diff --git a/DEPS b/DEPS index e846dca4..39019dd 100644 --- a/DEPS +++ b/DEPS
@@ -126,7 +126,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': '249a2573052167220fdb90828a5df43bfcaa3a07', + 'skia_revision': 'ca145bec7f3387bede9e2b5e33dd0196501534ec', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -142,7 +142,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '0a60818466f1efc7f142d6f267d113ecdc6591a5', + 'swiftshader_revision': '8f79d388784c4870b87c3e87753d5e054af07011', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -737,7 +737,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'd7810fd2d7b31fe57f8a155653d94976223d68d0', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'fd080e04f1e41186d0fe25463cf7371764d460d6', 'condition': 'checkout_linux', }, @@ -762,7 +762,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '9d686bcef57534e3474cbe93e29b65a965aef877', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '9e3080f52cbc7e5c2fb42f4410fd5923780ae01c', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -1275,7 +1275,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'a0f51b2e123f39c9ff12e621b0b47dd28dd64424', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '599d59237abf0dcb6b92774595316bfda84ab7f5', + Var('webrtc_git') + '/src.git' + '@' + '0d4869c2b9c2fdb536217209a4a88700fd121dd5', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1316,7 +1316,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f94d08d7c6f4c712ce9456425d2e1450927f82a4', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@274ad0c9456bbb4682b79566ec496c6b8a8f9e60', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java b/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java index dc410eaa..2c41a03 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java +++ b/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java
@@ -6,6 +6,7 @@ import org.chromium.android_webview.AwContents.VisualStateCallback; import org.chromium.base.task.PostTask; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContentsObserver; @@ -90,38 +91,38 @@ } @Override - public void didFinishNavigation(final String url, boolean isInMainFrame, boolean isErrorPage, - boolean hasCommitted, boolean isSameDocument, boolean isFragmentNavigation, - boolean isRendererInitiated, boolean isDownload, Integer pageTransition, int errorCode, - String errorDescription, int httpStatusCode) { - if (errorCode != 0 && !isDownload) { - didFailLoad(isInMainFrame, errorCode, errorDescription, url); + public void didFinishNavigation(NavigationHandle navigation) { + String url = navigation.getUrl(); + if (navigation.errorCode() != 0 && !navigation.isDownload()) { + didFailLoad(navigation.isInMainFrame(), navigation.errorCode(), + navigation.errorDescription(), url); } - if (!hasCommitted) return; + if (!navigation.hasCommitted()) return; mCommittedNavigation = true; - if (!isInMainFrame) return; + if (!navigation.isInMainFrame()) return; AwContentsClient client = mAwContentsClient.get(); if (client != null) { // OnPageStarted is not called for in-page navigations, which include fragment // navigations and navigation from history.push/replaceState. // Error page is handled by AwContentsClientBridge.onReceivedError. - if (!isSameDocument && !isErrorPage - && AwFeatureList.pageStartedOnCommitEnabled(isRendererInitiated)) { + if (!navigation.isSameDocument() && !navigation.isErrorPage() + && AwFeatureList.pageStartedOnCommitEnabled(navigation.isRendererInitiated())) { client.getCallbackHelper().postOnPageStarted(url); } - boolean isReload = pageTransition != null - && ((pageTransition & PageTransition.CORE_MASK) == PageTransition.RELOAD); + boolean isReload = navigation.pageTransition() != null + && ((navigation.pageTransition() & PageTransition.CORE_MASK) + == PageTransition.RELOAD); client.getCallbackHelper().postDoUpdateVisitedHistory(url, isReload); } // Only invoke the onPageCommitVisible callback when navigating to a different document, // but not when navigating to a different fragment within the same document. - if (!isSameDocument) { + if (!navigation.isSameDocument()) { PostTask.postTask(UiThreadTaskTraits.DEFAULT, () -> { AwContents awContents = mAwContents.get(); if (awContents != null) { @@ -138,7 +139,7 @@ }); } - if (client != null && isFragmentNavigation) { + if (client != null && navigation.isFragmentNavigation()) { // Note fragment navigations do not have a matching onPageStarted. client.getCallbackHelper().postOnPageFinished(url); }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwWebContentsObserverTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwWebContentsObserverTest.java index 46c4310..4df10b52 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwWebContentsObserverTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwWebContentsObserverTest.java
@@ -16,6 +16,7 @@ import org.chromium.android_webview.AwContentsStatics; import org.chromium.android_webview.AwWebContentsObserver; import org.chromium.base.test.util.Feature; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.test.util.TestCallbackHelperContainer; import org.chromium.ui.base.PageTransition; @@ -34,7 +35,6 @@ private static final String EXAMPLE_URL = "http://www.example.com/"; private static final String EXAMPLE_URL_WITH_FRAGMENT = "http://www.example.com/#anchor"; private static final String SYNC_URL = "http://example.org/"; - private static final String ERROR_DESCRIPTION = "description"; private String mUnreachableWebDataUrl; @Before @@ -96,21 +96,16 @@ String baseUrl = null; boolean isInMainFrame = true; boolean isErrorPage = false; - boolean hasCommitted = true; boolean isSameDocument = true; boolean fragmentNavigation = true; boolean isRendererInitiated = true; - boolean isDownload = false; int errorCode = 0; - String errorDescription = ""; int httpStatusCode = 200; callCount = onPageFinishedHelper.getCallCount(); - mWebContentsObserver.didFinishNavigation(EXAMPLE_URL, isInMainFrame, isErrorPage, - hasCommitted, !isSameDocument, !fragmentNavigation, !isRendererInitiated, - isDownload, PageTransition.TYPED, errorCode, errorDescription, httpStatusCode); - mWebContentsObserver.didFinishNavigation(EXAMPLE_URL_WITH_FRAGMENT, isInMainFrame, - isErrorPage, hasCommitted, isSameDocument, fragmentNavigation, isRendererInitiated, - isDownload, PageTransition.TYPED, errorCode, errorDescription, httpStatusCode); + simulateNavigation(EXAMPLE_URL, isInMainFrame, isErrorPage, !isSameDocument, + !fragmentNavigation, !isRendererInitiated, PageTransition.TYPED); + simulateNavigation(EXAMPLE_URL_WITH_FRAGMENT, isInMainFrame, isErrorPage, isSameDocument, + fragmentNavigation, isRendererInitiated, PageTransition.TYPED); onPageFinishedHelper.waitForCallback(callCount); Assert.assertEquals("onPageFinished should be called for main frame fragment navigations.", callCount + 1, onPageFinishedHelper.getCallCount()); @@ -118,9 +113,8 @@ EXAMPLE_URL_WITH_FRAGMENT, onPageFinishedHelper.getUrl()); callCount = onPageFinishedHelper.getCallCount(); - mWebContentsObserver.didFinishNavigation(EXAMPLE_URL, isInMainFrame, isErrorPage, - hasCommitted, !isSameDocument, !fragmentNavigation, !isRendererInitiated, - isDownload, PageTransition.TYPED, errorCode, errorDescription, httpStatusCode); + simulateNavigation(EXAMPLE_URL, isInMainFrame, isErrorPage, !isSameDocument, + !fragmentNavigation, !isRendererInitiated, PageTransition.TYPED); mWebContentsObserver.didFinishLoad(frameId, SYNC_URL, mainFrame); mWebContentsObserver.didStopLoading(SYNC_URL); onPageFinishedHelper.waitForCallback(callCount); @@ -141,21 +135,15 @@ String baseUrl = null; boolean isInMainFrame = true; boolean isErrorPage = false; - boolean hasCommitted = true; boolean isSameDocument = true; boolean fragmentNavigation = false; boolean isRendererInitiated = false; - boolean isDownload = false; - int errorCode = 0; - String errorDescription = ""; - int httpStatusCode = 200; TestAwContentsClient.DoUpdateVisitedHistoryHelper doUpdateVisitedHistoryHelper = mContentsClient.getDoUpdateVisitedHistoryHelper(); int callCount = doUpdateVisitedHistoryHelper.getCallCount(); - mWebContentsObserver.didFinishNavigation(nullUrl, isInMainFrame, !isErrorPage, hasCommitted, - !isSameDocument, fragmentNavigation, isRendererInitiated, isDownload, - PageTransition.TYPED, errorCode, errorDescription, httpStatusCode); + simulateNavigation(nullUrl, isInMainFrame, !isErrorPage, !isSameDocument, + fragmentNavigation, isRendererInitiated, PageTransition.TYPED); doUpdateVisitedHistoryHelper.waitForCallback(callCount); Assert.assertEquals("doUpdateVisitedHistory should be called for any url.", callCount + 1, doUpdateVisitedHistoryHelper.getCallCount()); @@ -164,9 +152,8 @@ Assert.assertEquals(false, doUpdateVisitedHistoryHelper.getIsReload()); callCount = doUpdateVisitedHistoryHelper.getCallCount(); - mWebContentsObserver.didFinishNavigation(EXAMPLE_URL, isInMainFrame, isErrorPage, - hasCommitted, !isSameDocument, fragmentNavigation, isRendererInitiated, isDownload, - PageTransition.TYPED, errorCode, errorDescription, httpStatusCode); + simulateNavigation(EXAMPLE_URL, isInMainFrame, isErrorPage, !isSameDocument, + fragmentNavigation, isRendererInitiated, PageTransition.TYPED); doUpdateVisitedHistoryHelper.waitForCallback(callCount); Assert.assertEquals("doUpdateVisitedHistory should be called for any url.", callCount + 1, doUpdateVisitedHistoryHelper.getCallCount()); @@ -175,12 +162,10 @@ Assert.assertEquals(false, doUpdateVisitedHistoryHelper.getIsReload()); callCount = doUpdateVisitedHistoryHelper.getCallCount(); - mWebContentsObserver.didFinishNavigation(nullUrl, isInMainFrame, isErrorPage, hasCommitted, - !isSameDocument, fragmentNavigation, isRendererInitiated, isDownload, - PageTransition.TYPED, errorCode, errorDescription, httpStatusCode); - mWebContentsObserver.didFinishNavigation(EXAMPLE_URL, !isInMainFrame, isErrorPage, - hasCommitted, !isSameDocument, fragmentNavigation, isRendererInitiated, isDownload, - PageTransition.TYPED, errorCode, errorDescription, httpStatusCode); + simulateNavigation(nullUrl, isInMainFrame, isErrorPage, !isSameDocument, fragmentNavigation, + isRendererInitiated, PageTransition.TYPED); + simulateNavigation(EXAMPLE_URL, !isInMainFrame, isErrorPage, !isSameDocument, + fragmentNavigation, isRendererInitiated, PageTransition.TYPED); doUpdateVisitedHistoryHelper.waitForCallback(callCount); Assert.assertEquals("doUpdateVisitedHistory should only be called for the main frame.", callCount + 1, doUpdateVisitedHistoryHelper.getCallCount()); @@ -189,9 +174,8 @@ Assert.assertEquals(false, doUpdateVisitedHistoryHelper.getIsReload()); callCount = doUpdateVisitedHistoryHelper.getCallCount(); - mWebContentsObserver.didFinishNavigation(EXAMPLE_URL, isInMainFrame, isErrorPage, - hasCommitted, isSameDocument, !fragmentNavigation, !isRendererInitiated, isDownload, - PageTransition.RELOAD, errorCode, errorDescription, httpStatusCode); + simulateNavigation(EXAMPLE_URL, isInMainFrame, isErrorPage, isSameDocument, + !fragmentNavigation, !isRendererInitiated, PageTransition.RELOAD); doUpdateVisitedHistoryHelper.waitForCallback(callCount); Assert.assertEquals("doUpdateVisitedHistory should be called for reloads.", callCount + 1, doUpdateVisitedHistoryHelper.getCallCount()); @@ -199,4 +183,16 @@ doUpdateVisitedHistoryHelper.getUrl()); Assert.assertEquals(true, doUpdateVisitedHistoryHelper.getIsReload()); } + + private void simulateNavigation(String url, boolean isInMainFrame, boolean isErrorPage, + boolean isSameDocument, boolean isFragmentNavigation, boolean isRendererInitiated, + int transition) { + NavigationHandle navigation = new NavigationHandle(0 /* navigationHandleProxy */, url, + isInMainFrame, isSameDocument, isRendererInitiated); + mWebContentsObserver.didStartNavigation(navigation); + + navigation.didFinish(url, isErrorPage, true /* hasCommitted */, isFragmentNavigation, + false /* isDownload */, transition, 0 /* errorCode*/, 200 /* httpStatusCode*/); + mWebContentsObserver.didFinishNavigation(navigation); + } }
diff --git a/apps/saved_files_service_unittest.cc b/apps/saved_files_service_unittest.cc index d0679e9..7f9f1de 100644 --- a/apps/saved_files_service_unittest.cc +++ b/apps/saved_files_service_unittest.cc
@@ -38,7 +38,7 @@ protected: void SetUp() override { testing::Test::SetUp(); - extension_ = env_.MakeExtension(*base::test::ParseJson( + extension_ = env_.MakeExtension(*base::test::ParseJsonDeprecated( "{" " \"app\": {" " \"background\": {" @@ -147,7 +147,7 @@ } TEST_F(SavedFilesServiceUnitTest, NoRetainEntriesPermissionTest) { - extension_ = env_.MakeExtension(*base::test::ParseJson( + extension_ = env_.MakeExtension(*base::test::ParseJsonDeprecated( "{\"app\": {\"background\": {\"scripts\": [\"background.js\"]}}," "\"permissions\": [\"fileSystem\"]}")); service_->RegisterFileEntry(extension_->id(), GenerateId(1), path_, true);
diff --git a/ash/assistant/assistant_ui_controller.cc b/ash/assistant/assistant_ui_controller.cc index f03d8478..a0def9d 100644 --- a/ash/assistant/assistant_ui_controller.cc +++ b/ash/assistant/assistant_ui_controller.cc
@@ -251,8 +251,12 @@ // navigation was initiated by a server response. Otherwise the navigation // was user initiated so we only hide the UI to retain session state. That way // the user can choose to resume their session if they are so inclined. + // However, we close the UI if it is in the |kLauncherEmbeddedUi| mode, where + // we only maintain |kVisible| and |kClosed| two states. if (from_server) CloseUi(AssistantExitPoint::kNewBrowserTabFromServer); + else if (model_.ui_mode() == AssistantUiMode::kLauncherEmbeddedUi) + CloseUi(AssistantExitPoint::kNewBrowserTabFromUser); else HideUi(AssistantExitPoint::kNewBrowserTabFromUser); }
diff --git a/base/BUILD.gn b/base/BUILD.gn index c54a54c..2134595f 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -1308,6 +1308,8 @@ "android/path_service_android.cc", "android/path_utils.cc", "android/path_utils.h", + "android/reached_addresses_bitset.cc", + "android/reached_addresses_bitset.h", "android/reached_code_profiler.cc", "android/reached_code_profiler.h", "android/record_histogram.cc", @@ -2287,6 +2289,7 @@ "android/library_loader/library_loader_hooks_unittest.cc", "android/library_loader/library_prefetcher_unittest.cc", "android/path_utils_unittest.cc", + "android/reached_addresses_bitset_unittest.cc", "android/scoped_java_ref_unittest.cc", "android/sys_utils_unittest.cc", "android/unguessable_token_android_unittest.cc",
diff --git a/base/android/library_loader/anchor_functions.cc b/base/android/library_loader/anchor_functions.cc index 0865d9d..9914c34 100644 --- a/base/android/library_loader/anchor_functions.cc +++ b/base/android/library_loader/anchor_functions.cc
@@ -56,8 +56,12 @@ const size_t kEndOfOrderedText = reinterpret_cast<size_t>(dummy_function_end_of_ordered_text); -bool IsOrderingSane() { +bool AreAnchorsSane() { size_t here = reinterpret_cast<size_t>(&IsOrderingSane); + return kStartOfText < here && here < kEndOfText; +} + +bool IsOrderingSane() { // The symbols linker_script_start_of_text and linker_script_end_of_text // should cover all of .text, and dummy_function_start_of_ordered_text and // dummy_function_end_of_ordered_text should cover the ordered part of it. @@ -68,8 +72,7 @@ // different, but linker-defined symbols have zero size and therefore the // start address could be the same as the address of // dummy_function_start_of_ordered_text. - return kStartOfText < here && here < kEndOfText && - kStartOfOrderedText < kEndOfOrderedText && + return AreAnchorsSane() && kStartOfOrderedText < kEndOfOrderedText && kStartOfText <= kStartOfOrderedText && kEndOfOrderedText < kEndOfText; }
diff --git a/base/android/library_loader/anchor_functions.h b/base/android/library_loader/anchor_functions.h index 9894583..fe95d5fb 100644 --- a/base/android/library_loader/anchor_functions.h +++ b/base/android/library_loader/anchor_functions.h
@@ -22,6 +22,9 @@ BASE_EXPORT extern const size_t kStartOfOrderedText; BASE_EXPORT extern const size_t kEndOfOrderedText; +// Returns true if anchors are sane. +BASE_EXPORT bool AreAnchorsSane(); + // Returns true if the ordering looks sane. BASE_EXPORT bool IsOrderingSane();
diff --git a/base/android/reached_addresses_bitset.cc b/base/android/reached_addresses_bitset.cc new file mode 100644 index 0000000..9be0b10 --- /dev/null +++ b/base/android/reached_addresses_bitset.cc
@@ -0,0 +1,99 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/android/reached_addresses_bitset.h" + +#include "base/android/library_loader/anchor_functions.h" +#include "base/android/library_loader/anchor_functions_buildflags.h" +#include "base/logging.h" +#include "base/no_destructor.h" + +namespace base { +namespace android { + +namespace { +constexpr size_t kBitsPerElement = sizeof(uint32_t) * 8; + +#if BUILDFLAG(SUPPORTS_CODE_ORDERING) +// Enough for 1 << 29 bytes of code, 512MB. +constexpr size_t kTextBitfieldSize = 1 << 20; +std::atomic<uint32_t> g_text_bitfield[kTextBitfieldSize]; +#endif +} // namespace + +// static +ReachedAddressesBitset* ReachedAddressesBitset::GetTextBitset() { +#if BUILDFLAG(SUPPORTS_CODE_ORDERING) + static base::NoDestructor<ReachedAddressesBitset> text_bitset( + kStartOfText, kEndOfText, g_text_bitfield, kTextBitfieldSize); + return text_bitset.get(); +#else + return nullptr; +#endif +} + +void ReachedAddressesBitset::RecordAddress(uintptr_t address) { + // |address| is outside of the range. + if (address < start_address_ || address >= end_address_) + return; + + uint32_t offset = address - start_address_; + uint32_t offset_index = offset / kBytesGranularity; + + // Atomically set the corresponding bit in the array. + std::atomic<uint32_t>* element = reached_ + (offset_index / kBitsPerElement); + + // First, a racy check. This saves a CAS if the bit is already set, and + // allows the cache line to remain shared across CPUs in this case. + uint32_t value = element->load(std::memory_order_relaxed); + uint32_t mask = 1 << (offset_index % kBitsPerElement); + if (value & mask) + return; + element->fetch_or(mask, std::memory_order_relaxed); +} + +std::vector<uint32_t> ReachedAddressesBitset::GetReachedOffsets() const { + std::vector<uint32_t> offsets; + const size_t elements = NumberOfReachableElements(); + + for (size_t i = 0; i < elements; ++i) { + uint32_t element = reached_[i].load(std::memory_order_relaxed); + // No reached addresses at this element. + if (element == 0) + continue; + + for (size_t j = 0; j < 32; ++j) { + if (!((element >> j) & 1)) + continue; + + uint32_t offset_index = i * 32 + j; + uint32_t offset = offset_index * kBytesGranularity; + offsets.push_back(offset); + } + } + + return offsets; +} + +ReachedAddressesBitset::ReachedAddressesBitset( + uintptr_t start_address, + uintptr_t end_address, + std::atomic<uint32_t>* storage_ptr, + size_t storage_size) + : start_address_(start_address), + end_address_(end_address), + reached_(storage_ptr) { + DCHECK_LE(start_address_, end_address_); + DCHECK_LE(NumberOfReachableElements(), storage_size * kBitsPerElement); +} + +size_t ReachedAddressesBitset::NumberOfReachableElements() const { + size_t reachable_bits = + (end_address_ + kBytesGranularity - 1) / kBytesGranularity - + start_address_ / kBytesGranularity; + return (reachable_bits + kBitsPerElement - 1) / kBitsPerElement; +} + +} // namespace android +} // namespace base
diff --git a/base/android/reached_addresses_bitset.h b/base/android/reached_addresses_bitset.h new file mode 100644 index 0000000..1f4b8927 --- /dev/null +++ b/base/android/reached_addresses_bitset.h
@@ -0,0 +1,75 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_ANDROID_REACHED_ADDRESSES_BITSET_H_ +#define BASE_ANDROID_REACHED_ADDRESSES_BITSET_H_ + +#include <atomic> +#include <vector> + +#include "base/base_export.h" + +namespace base { + +template <typename T> +class NoDestructor; + +namespace android { + +// ReachedAddressesBitset is a set that stores addresses for the +// ReachedCodeProfiler in compact form. Its main features are lock-free +// thread-safety and fast adding of elements. +// +// The addresses are kept with |kBytesGranularity| to save the storage space. +// +// Once insterted, elements cannot be erased from the set. +// +// All methods can be called from any thread. +class BASE_EXPORT ReachedAddressesBitset { + public: + // Returns an instance of ReachedAddressesBitset having enough storage space + // to keep all addresses from the .text section. + // Returns nullptr if SUPPORTS_CODE_ORDERING isn't defined. + // This instance is stored in the .bss section of the binary, meaning that it + // doesn't incur the binary size overhead and it doesn't increase the resident + // memory footprint when not used. + static ReachedAddressesBitset* GetTextBitset(); + + // Inserts |address| into the bitset iff |address| lies in the range between + // |start_address_| and |end_address_|. + void RecordAddress(uintptr_t address); + + // Returns a list of recorded addresses in the form of offsets from + // |start_address_|. + std::vector<uint32_t> GetReachedOffsets() const; + + private: + friend class ReachedAddressesBitsetTest; + friend class NoDestructor<ReachedAddressesBitset>; + + // Represents the number of bytes that are mapped into the same bit in the + // bitset. + static constexpr size_t kBytesGranularity = 4; + + // Constructs a ReachedAddressesBitset on top of an external storage of + // |storage_size| pointed by |storage_ptr|. This external storage must outlive + // the constructed bitset instance. The size of storage must be large enough + // to fit all addresses in the range between |start_address| and + // |end_address|. + ReachedAddressesBitset(uintptr_t start_address, + uintptr_t end_address, + std::atomic<uint32_t>* storage_ptr, + size_t storage_size); + + size_t NumberOfReachableElements() const; + + uintptr_t start_address_; + uintptr_t end_address_; + std::atomic<uint32_t>* reached_; +}; + +} // namespace android +} // namespace base + +#endif // BASE_ANDROID_REACHED_ADDRESSES_BITSET_H_
diff --git a/base/android/reached_addresses_bitset_unittest.cc b/base/android/reached_addresses_bitset_unittest.cc new file mode 100644 index 0000000..32fb4f2 --- /dev/null +++ b/base/android/reached_addresses_bitset_unittest.cc
@@ -0,0 +1,78 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/android/reached_addresses_bitset.h" + +#include <utility> + +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { +namespace android { + +using testing::ElementsAre; +using testing::ElementsAreArray; + +constexpr uintptr_t kStartAddress = 0x1000; +constexpr uintptr_t kEndAddress = 0x2000; +constexpr size_t kStorageSize = 512; + +class ReachedAddressesBitsetTest : public testing::Test { + public: + ReachedAddressesBitsetTest() + : bitset_(kStartAddress, kEndAddress, storage_, kStorageSize) { + memset(storage_, 0, kStorageSize * sizeof(uint32_t)); + EXPECT_TRUE(bitset()->GetReachedOffsets().empty()); + } + + ReachedAddressesBitset* bitset() { return &bitset_; } + + private: + std::atomic<uint32_t> storage_[kStorageSize]; + ReachedAddressesBitset bitset_; +}; + +TEST_F(ReachedAddressesBitsetTest, RecordStartAddress) { + bitset()->RecordAddress(kStartAddress); + EXPECT_THAT(bitset()->GetReachedOffsets(), ElementsAre(0)); +} + +TEST_F(ReachedAddressesBitsetTest, RecordLastAddress) { + bitset()->RecordAddress(kEndAddress - 4); + EXPECT_THAT(bitset()->GetReachedOffsets(), + ElementsAre(kEndAddress - 4 - kStartAddress)); +} + +TEST_F(ReachedAddressesBitsetTest, RecordAddressOutsideOfRange_Small) { + bitset()->RecordAddress(kStartAddress - 4); + EXPECT_THAT(bitset()->GetReachedOffsets(), ElementsAre()); +} + +TEST_F(ReachedAddressesBitsetTest, RecordAddressOutsideOfRange_Large) { + bitset()->RecordAddress(kEndAddress); + EXPECT_THAT(bitset()->GetReachedOffsets(), ElementsAre()); +} + +TEST_F(ReachedAddressesBitsetTest, RecordUnalignedAddresses) { + constexpr uint32_t aligned_offset = 0x100; + bitset()->RecordAddress(kStartAddress + aligned_offset + 1); + bitset()->RecordAddress(kStartAddress + aligned_offset + 2); + bitset()->RecordAddress(kStartAddress + aligned_offset + 3); + EXPECT_THAT(bitset()->GetReachedOffsets(), ElementsAre(aligned_offset)); +} + +TEST_F(ReachedAddressesBitsetTest, FillBitsetOneByOne) { + std::vector<uint32_t> expected_offsets; + for (uintptr_t address = kStartAddress; address < kEndAddress; address += 4) { + bitset()->RecordAddress(address); + expected_offsets.push_back(address - kStartAddress); + ASSERT_THAT(bitset()->GetReachedOffsets(), + ElementsAreArray(expected_offsets)) + << "Last added: " << address; + } +} + +} // namespace android +} // namespace base
diff --git a/base/android/reached_code_profiler.cc b/base/android/reached_code_profiler.cc index 07e6d5e..93100fa 100644 --- a/base/android/reached_code_profiler.cc +++ b/base/android/reached_code_profiler.cc
@@ -13,6 +13,7 @@ #include "base/android/library_loader/anchor_functions.h" #include "base/android/orderfile/orderfile_buildflags.h" +#include "base/android/reached_addresses_bitset.h" #include "base/base_switches.h" #include "base/bind.h" #include "base/command_line.h" @@ -57,10 +58,6 @@ constexpr const char kDumpToFileFlag[] = "reached-code-profiler-dump-to-file"; -// Enough for 1 << 29 bytes of code, 512MB. -constexpr size_t kBitfieldSize = 1 << 20; -constexpr size_t kBitsPerElement = 4 * 32; - constexpr uint64_t kIterationsBeforeSkipping = 50; constexpr uint64_t kIterationsBetweenUpdates = 100; constexpr int kProfilerSignal = SIGURG; @@ -69,45 +66,13 @@ base::TimeDelta::FromMilliseconds(10); constexpr base::TimeDelta kDumpInterval = base::TimeDelta::FromSeconds(30); -std::atomic<uint32_t> g_reached[kBitfieldSize]; -std::atomic<std::atomic<uint32_t>*> g_enabled_and_reached(g_reached); - -size_t NumberOfReachableElements() { - return (kEndOfText - kStartOfText) / kBitsPerElement + 1; -} - -void RecordAddress(uint32_t address) { - auto* reached = g_enabled_and_reached.load(std::memory_order_relaxed); - if (!reached) - return; - - // Stopped in libc, third-party, or Java code. - if (address < kStartOfText || address > kEndOfText) - return; - - size_t offset = address - kStartOfText; - static_assert(sizeof(int) == 4, - "Collection and processing code assumes that sizeof(int) == 4"); - size_t offset_index = offset / 4; - - // Atomically set the corresponding bit in the array. - std::atomic<uint32_t>* element = reached + (offset_index / 32); - // First, a racy check. This saves a CAS if the bit is already set, and - // allows the cache line to remain shared acoss CPUs in this case. - uint32_t value = element->load(std::memory_order_relaxed); - uint32_t mask = 1 << (offset_index % 32); - if (value & mask) - return; - element->fetch_or(mask, std::memory_order_relaxed); -} - void HandleSignal(int signal, siginfo_t* info, void* context) { if (signal != kProfilerSignal) return; ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); uint32_t address = ucontext->uc_mcontext.arm_pc; - RecordAddress(address); + ReachedAddressesBitset::GetTextBitset()->RecordAddress(address); } struct ScopedTimerCloseTraits { @@ -120,30 +85,9 @@ using ScopedTimer = base::ScopedGeneric<base::Optional<timer_t>, ScopedTimerCloseTraits>; -std::vector<uint8_t> SnapshotReachedCodeBitset() { - std::vector<uint8_t> buf; - size_t elements = NumberOfReachableElements(); - buf.resize(elements * sizeof(uint32_t)); - // Copy the reached array into a buffer with atomic loads with the explicit - // memory ordering flag. In practice this is likely not necessary because: - // a) integrity of the data across individual elements of |g_reached| is not - // maintained anyway - // b) write(2) will not take the data in smaller chunks than 4 bytes - // c) it would be bizarre for mojo initialization code to cause the compiler - // to spill stuff into the array.. - // Anyway .. come to the Safe Side, we have CPUs to spin. - for (size_t i = 0; i < elements; i++) { - uint32_t word = g_reached[i].load(std::memory_order_relaxed); - for (int j = 0; j < 4; j++) { - buf[4 * i + j] = static_cast<uint8_t>((word >> (j * 8)) & 0xFF); - } - } - return buf; -} - void DumpToFile(const base::FilePath& path, scoped_refptr<base::SingleThreadTaskRunner> task_runner) { - CHECK(task_runner->BelongsToCurrentThread()); + DCHECK(task_runner->BelongsToCurrentThread()); auto dir_path = path.DirName(); if (!base::DirectoryExists(dir_path) && !base::CreateDirectory(dir_path)) { @@ -151,9 +95,11 @@ return; } - std::vector<uint8_t> buf = SnapshotReachedCodeBitset(); - base::StringPiece contents(reinterpret_cast<const char*>(buf.data()), - buf.size()); + std::vector<uint32_t> reached_offsets = + ReachedAddressesBitset::GetTextBitset()->GetReachedOffsets(); + base::StringPiece contents( + reinterpret_cast<const char*>(reached_offsets.data()), + reached_offsets.size()); if (!base::ImportantFileWriter::WriteFileAtomically(path, contents, "ReachedDump")) { LOG(ERROR) << "Could not write reached dump into " << path;
diff --git a/base/json/json_reader.h b/base/json/json_reader.h index 738f72e..fb458cfe 100644 --- a/base/json/json_reader.h +++ b/base/json/json_reader.h
@@ -110,8 +110,7 @@ ~JSONReader(); // Reads and parses |json|, returning a Value. - // If |json| is not a properly formed JSON string, returns a Value of type - // NONE. + // If |json| is not a properly formed JSON string, returns base::nullopt. static Optional<Value> Read(StringPiece json, int options = JSON_PARSE_RFC, int max_depth = kStackMaxDepth);
diff --git a/base/json/json_reader_unittest.cc b/base/json/json_reader_unittest.cc index ac1796cf..5023f33 100644 --- a/base/json/json_reader_unittest.cc +++ b/base/json/json_reader_unittest.cc
@@ -6,7 +6,7 @@ #include <stddef.h> -#include <memory> +#include <utility> #include "base/base_paths.h" #include "base/files/file_util.h" @@ -53,31 +53,29 @@ std::string value; EXPECT_TRUE(root->GetAsString(&value)); EXPECT_EQ("sample string", value); - std::unique_ptr<ListValue> list = ListValue::From( - JSONReader::ReadDeprecated("[1, /* comment, 2 ] */ \n 3]")); - ASSERT_TRUE(list); - EXPECT_EQ(2u, list->GetSize()); - int int_val = 0; - EXPECT_TRUE(list->GetInteger(0, &int_val)); - EXPECT_EQ(1, int_val); - EXPECT_TRUE(list->GetInteger(1, &int_val)); - EXPECT_EQ(3, int_val); - list = ListValue::From(JSONReader::ReadDeprecated("[1, /*a*/2, 3]")); - ASSERT_TRUE(list); - EXPECT_EQ(3u, list->GetSize()); + root = JSONReader::Read("[1, /* comment, 2 ] */ \n 3]"); + ASSERT_TRUE(root); + ASSERT_TRUE(root->is_list()); + ASSERT_EQ(2u, root->GetList().size()); + ASSERT_TRUE(root->GetList()[0].is_int()); + EXPECT_EQ(1, root->GetList()[0].GetInt()); + ASSERT_TRUE(root->GetList()[1].is_int()); + EXPECT_EQ(3, root->GetList()[1].GetInt()); + root = JSONReader::Read("[1, /*a*/2, 3]"); + ASSERT_TRUE(root); + ASSERT_TRUE(root->is_list()); + EXPECT_EQ(3u, root->GetList().size()); root = JSONReader::Read("/* comment **/42"); ASSERT_TRUE(root); - EXPECT_TRUE(root->is_int()); - EXPECT_TRUE(root->GetAsInteger(&int_val)); - EXPECT_EQ(42, int_val); + ASSERT_TRUE(root->is_int()); + EXPECT_EQ(42, root->GetInt()); root = JSONReader::Read( "/* comment **/\n" "// */ 43\n" "44"); ASSERT_TRUE(root); EXPECT_TRUE(root->is_int()); - EXPECT_TRUE(root->GetAsInteger(&int_val)); - EXPECT_EQ(44, int_val); + EXPECT_EQ(44, root->GetInt()); } TEST(JSONReaderTest, Ints) { @@ -478,12 +476,12 @@ EXPECT_TRUE(root->GetAsString(&str_val)); EXPECT_EQ(L"\x7f51\x9875", UTF8ToWide(str_val)); - std::unique_ptr<DictionaryValue> dict_val = - DictionaryValue::From(JSONReader::ReadDeprecated( - "{\"path\": \"/tmp/\xc3\xa0\xc3\xa8\xc3\xb2.png\"}")); - ASSERT_TRUE(dict_val); - EXPECT_TRUE(dict_val->GetString("path", &str_val)); - EXPECT_EQ("/tmp/\xC3\xA0\xC3\xA8\xC3\xB2.png", str_val); + root = JSONReader::Read("{\"path\": \"/tmp/\xc3\xa0\xc3\xa8\xc3\xb2.png\"}"); + ASSERT_TRUE(root); + ASSERT_TRUE(root->is_dict()); + const std::string* maybe_string = root->FindStringKey("path"); + ASSERT_TRUE(maybe_string); + EXPECT_EQ("/tmp/\xC3\xA0\xC3\xA8\xC3\xB2.png", *maybe_string); } TEST(JSONReaderTest, InvalidUTF8Input) { @@ -572,15 +570,15 @@ // Tests that the root of a JSON object can be deleted safely while its // children outlive it. TEST(JSONReaderTest, StringOptimizations) { - std::unique_ptr<Value> dict_literal_0; - std::unique_ptr<Value> dict_literal_1; - std::unique_ptr<Value> dict_string_0; - std::unique_ptr<Value> dict_string_1; - std::unique_ptr<Value> list_value_0; - std::unique_ptr<Value> list_value_1; + Value dict_literal_0; + Value dict_literal_1; + Value dict_string_0; + Value dict_string_1; + Value list_value_0; + Value list_value_1; { - std::unique_ptr<Value> root = JSONReader::ReadDeprecated( + Optional<Value> root = JSONReader::Read( "{" " \"test\": {" " \"foo\": true," @@ -595,46 +593,52 @@ "}", JSON_PARSE_RFC); ASSERT_TRUE(root); + ASSERT_TRUE(root->is_dict()); - DictionaryValue* root_dict = nullptr; - ASSERT_TRUE(root->GetAsDictionary(&root_dict)); + Value* dict = root->FindKeyOfType("test", Value::Type::DICTIONARY); + ASSERT_TRUE(dict); + Value* list = root->FindKeyOfType("list", Value::Type::LIST); + ASSERT_TRUE(list); - DictionaryValue* dict = nullptr; - ListValue* list = nullptr; + Value* to_move = dict->FindKey("foo"); + ASSERT_TRUE(to_move); + dict_literal_0 = std::move(*to_move); + to_move = dict->FindKey("bar"); + ASSERT_TRUE(to_move); + dict_literal_1 = std::move(*to_move); + to_move = dict->FindKey("baz"); + ASSERT_TRUE(to_move); + dict_string_0 = std::move(*to_move); + to_move = dict->FindKey("moo"); + ASSERT_TRUE(to_move); + dict_string_1 = std::move(*to_move); + ASSERT_TRUE(dict->RemoveKey("foo")); + ASSERT_TRUE(dict->RemoveKey("bar")); + ASSERT_TRUE(dict->RemoveKey("baz")); + ASSERT_TRUE(dict->RemoveKey("moo")); - ASSERT_TRUE(root_dict->GetDictionary("test", &dict)); - ASSERT_TRUE(root_dict->GetList("list", &list)); - - ASSERT_TRUE(dict->Remove("foo", &dict_literal_0)); - ASSERT_TRUE(dict->Remove("bar", &dict_literal_1)); - ASSERT_TRUE(dict->Remove("baz", &dict_string_0)); - ASSERT_TRUE(dict->Remove("moo", &dict_string_1)); - - ASSERT_EQ(2u, list->GetSize()); - ASSERT_TRUE(list->Remove(0, &list_value_0)); - ASSERT_TRUE(list->Remove(0, &list_value_1)); + ASSERT_EQ(2u, list->GetList().size()); + list_value_0 = std::move(list->GetList()[0]); + list_value_1 = std::move(list->GetList()[1]); + list->GetList().clear(); } - bool b = false; - double d = 0; - std::string s; + ASSERT_TRUE(dict_literal_0.is_bool()); + EXPECT_TRUE(dict_literal_0.GetBool()); - EXPECT_TRUE(dict_literal_0->GetAsBoolean(&b)); - EXPECT_TRUE(b); + ASSERT_TRUE(dict_literal_1.is_double()); + EXPECT_EQ(3.14, dict_literal_1.GetDouble()); - EXPECT_TRUE(dict_literal_1->GetAsDouble(&d)); - EXPECT_EQ(3.14, d); + ASSERT_TRUE(dict_string_0.is_string()); + EXPECT_EQ("bat", dict_string_0.GetString()); - EXPECT_TRUE(dict_string_0->GetAsString(&s)); - EXPECT_EQ("bat", s); + ASSERT_TRUE(dict_string_1.is_string()); + EXPECT_EQ("cow", dict_string_1.GetString()); - EXPECT_TRUE(dict_string_1->GetAsString(&s)); - EXPECT_EQ("cow", s); - - EXPECT_TRUE(list_value_0->GetAsString(&s)); - EXPECT_EQ("a", s); - EXPECT_TRUE(list_value_1->GetAsString(&s)); - EXPECT_EQ("b", s); + ASSERT_TRUE(list_value_0.is_string()); + EXPECT_EQ("a", list_value_0.GetString()); + ASSERT_TRUE(list_value_1.is_string()); + EXPECT_EQ("b", list_value_1.GetString()); } // A smattering of invalid JSON designed to test specific portions of the
diff --git a/base/test/values_test_util.cc b/base/test/values_test_util.cc index 80e0a36..007e6f6 100644 --- a/base/test/values_test_util.cc +++ b/base/test/values_test_util.cc
@@ -4,7 +4,6 @@ #include "base/test/values_test_util.h" -#include <memory> #include <ostream> #include <utility> @@ -63,7 +62,7 @@ namespace test { IsJsonMatcher::IsJsonMatcher(base::StringPiece json) - : expected_value_(std::move(*test::ParseJson(json))) {} + : expected_value_(test::ParseJson(json)) {} IsJsonMatcher::IsJsonMatcher(const base::Value& value) : expected_value_(value.Clone()) {} @@ -102,16 +101,19 @@ *os << "is not the JSON value " << expected_value_; } -std::unique_ptr<Value> ParseJson(base::StringPiece json) { - std::string error_msg; - std::unique_ptr<Value> result = - base::JSONReader::ReadAndReturnErrorDeprecated( - json, base::JSON_ALLOW_TRAILING_COMMAS, nullptr, &error_msg); - if (!result) { - ADD_FAILURE() << "Failed to parse \"" << json << "\": " << error_msg; - result = std::make_unique<Value>(); +Value ParseJson(StringPiece json) { + JSONReader::ValueWithError result = + JSONReader::ReadAndReturnValueWithError(json, JSON_ALLOW_TRAILING_COMMAS); + if (!result.value) { + ADD_FAILURE() << "Failed to parse \"" << json + << "\": " << result.error_message; + return Value(); } - return result; + return std::move(result.value.value()); +} + +std::unique_ptr<Value> ParseJsonDeprecated(StringPiece json) { + return Value::ToUniquePtrValue(ParseJson(json)); } } // namespace test
diff --git a/base/test/values_test_util.h b/base/test/values_test_util.h index 73483bf..c7d5509 100644 --- a/base/test/values_test_util.h +++ b/base/test/values_test_util.h
@@ -77,10 +77,16 @@ return testing::MakePolymorphicMatcher(IsJsonMatcher(value)); } +// Parses |json| as JSON, allowing trailing commas, and returns the resulting +// value. If |json| fails to parse, causes an EXPECT failure and returns the +// Null Value. +Value ParseJson(StringPiece json); + +// DEPRECATED. // Parses |json| as JSON, allowing trailing commas, and returns the // resulting value. If the json fails to parse, causes an EXPECT // failure and returns the Null Value (but never a NULL pointer). -std::unique_ptr<Value> ParseJson(base::StringPiece json); +std::unique_ptr<Value> ParseJsonDeprecated(StringPiece json); } // namespace test } // namespace base
diff --git a/base/trace_event/trace_config.cc b/base/trace_event/trace_config.cc index 6c9dc03..e28456bd 100644 --- a/base/trace_event/trace_config.cc +++ b/base/trace_event/trace_config.cc
@@ -33,6 +33,7 @@ // String parameters that can be used to parse the trace config string. const char kRecordModeParam[] = "record_mode"; const char kTraceBufferSizeInEvents[] = "trace_buffer_size_in_events"; +const char kTraceBufferSizeInKb[] = "trace_buffer_size_in_kb"; const char kEnableSystraceParam[] = "enable_systrace"; const char kEnableArgumentFilterParam[] = "enable_argument_filter"; @@ -292,6 +293,7 @@ record_mode_ = rhs.record_mode_; trace_buffer_size_in_events_ = rhs.trace_buffer_size_in_events_; + trace_buffer_size_in_kb_ = rhs.trace_buffer_size_in_kb_; enable_systrace_ = rhs.enable_systrace_; enable_argument_filter_ = rhs.enable_argument_filter_; category_filter_ = rhs.category_filter_; @@ -334,6 +336,8 @@ } DCHECK_EQ(trace_buffer_size_in_events_, config.trace_buffer_size_in_events_) << "Cannot change trace buffer size"; + DCHECK_EQ(trace_buffer_size_in_kb_, config.trace_buffer_size_in_kb_) + << "Cannot change trace buffer size"; category_filter_.Merge(config.category_filter_); memory_dump_config_.Merge(config.memory_dump_config_); @@ -348,6 +352,7 @@ void TraceConfig::Clear() { record_mode_ = RECORD_UNTIL_FULL; trace_buffer_size_in_events_ = 0; + trace_buffer_size_in_kb_ = 0; enable_systrace_ = false; enable_argument_filter_ = false; category_filter_.Clear(); @@ -360,6 +365,7 @@ void TraceConfig::InitializeDefault() { record_mode_ = RECORD_UNTIL_FULL; trace_buffer_size_in_events_ = 0; + trace_buffer_size_in_kb_ = 0; enable_systrace_ = false; enable_argument_filter_ = false; } @@ -381,6 +387,8 @@ int buffer_size = 0; trace_buffer_size_in_events_ = dict.GetInteger(kTraceBufferSizeInEvents, &buffer_size) ? buffer_size : 0; + trace_buffer_size_in_kb_ = + dict.GetInteger(kTraceBufferSizeInKb, &buffer_size) ? buffer_size : 0; bool val; enable_systrace_ = dict.GetBoolean(kEnableSystraceParam, &val) ? val : false; @@ -423,6 +431,7 @@ record_mode_ = RECORD_UNTIL_FULL; trace_buffer_size_in_events_ = 0; + trace_buffer_size_in_kb_ = 0; enable_systrace_ = false; enable_argument_filter_ = false; if (!trace_options_string.empty()) { @@ -564,6 +573,8 @@ dict->SetBoolean(kEnableArgumentFilterParam, enable_argument_filter_); if (trace_buffer_size_in_events_ > 0) dict->SetInteger(kTraceBufferSizeInEvents, trace_buffer_size_in_events_); + if (trace_buffer_size_in_kb_ > 0) + dict->SetInteger(kTraceBufferSizeInKb, trace_buffer_size_in_kb_); category_filter_.ToDict(dict.get()); process_filter_config_.ToDict(dict.get());
diff --git a/base/trace_event/trace_config.h b/base/trace_event/trace_config.h index 09bdd60..30f647f 100644 --- a/base/trace_event/trace_config.h +++ b/base/trace_event/trace_config.h
@@ -116,7 +116,7 @@ class BASE_EXPORT EventFilterConfig { public: - EventFilterConfig(const std::string& predicate_name); + explicit EventFilterConfig(const std::string& predicate_name); EventFilterConfig(const EventFilterConfig& tc); ~EventFilterConfig(); @@ -229,6 +229,7 @@ size_t GetTraceBufferSizeInEvents() const { return trace_buffer_size_in_events_; } + size_t GetTraceBufferSizeInKb() const { return trace_buffer_size_in_kb_; } bool IsSystraceEnabled() const { return enable_systrace_; } bool IsArgumentFilterEnabled() const { return enable_argument_filter_; } @@ -236,6 +237,7 @@ void SetTraceBufferSizeInEvents(size_t size) { trace_buffer_size_in_events_ = size; } + void SetTraceBufferSizeInKb(size_t size) { trace_buffer_size_in_kb_ = size; } void EnableSystrace() { enable_systrace_ = true; } void EnableArgumentFilter() { enable_argument_filter_ = true; } void EnableHistogram(const std::string& histogram_name); @@ -317,6 +319,7 @@ TraceRecordMode record_mode_; size_t trace_buffer_size_in_events_ = 0; // 0 specifies default size + size_t trace_buffer_size_in_kb_ = 0; // 0 specifies default size bool enable_systrace_ : 1; bool enable_argument_filter_ : 1;
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index df4c101..f8c9a30 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -4e667b3998b2dcc3e611ed26003fbafc7abaeb30 \ No newline at end of file +81b54a7e2b2fff7f5dad246801c3c4b34486abdf \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 3c5cdb1..eec3a7a4 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -3da35f1d08e145c7e9589ab286562d97b23e940c \ No newline at end of file +f80285fb56fc829316c85929d34f5fbe9b15b4a9 \ No newline at end of file
diff --git a/cc/test/layer_tree_json_parser.cc b/cc/test/layer_tree_json_parser.cc index d23dfb4..8d600d5 100644 --- a/cc/test/layer_tree_json_parser.cc +++ b/cc/test/layer_tree_json_parser.cc
@@ -138,7 +138,7 @@ scoped_refptr<Layer> ParseTreeFromJson(std::string json, ContentLayerClient* content_client) { - std::unique_ptr<base::Value> val = base::test::ParseJson(json); + std::unique_ptr<base::Value> val = base::test::ParseJsonDeprecated(json); return ParseTreeFromValue(*val, content_client); }
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index a1c0c47..1f18015 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc
@@ -147,8 +147,8 @@ enum MainOrder : int { MAIN_START = 1, MAIN_LAYOUT, - MAIN_DID_BEGIN_FRAME, MAIN_COMMIT_COMPLETE, + MAIN_DID_BEGIN_FRAME, MAIN_END, };
diff --git a/cc/trees/proxy_main.cc b/cc/trees/proxy_main.cc index 7218721..e0683e5 100644 --- a/cc/trees/proxy_main.cc +++ b/cc/trees/proxy_main.cc
@@ -236,8 +236,6 @@ skip_commit |= defer_main_frame_update_ || defer_commits_; if (skip_commit) { - current_pipeline_stage_ = NO_PIPELINE_STAGE; - layer_tree_host_->DidBeginMainFrame(); TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit_InsideBeginMainFrame", TRACE_EVENT_SCOPE_THREAD); layer_tree_host_->RecordEndOfFrameMetrics(begin_main_frame_start_time); @@ -248,8 +246,10 @@ CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT, begin_main_frame_start_time, base::Passed(&empty_swap_promises))); + current_pipeline_stage_ = NO_PIPELINE_STAGE; // We intentionally don't report CommitComplete() here since it was aborted // prematurely and we're waiting to do another commit in the future. + layer_tree_host_->DidBeginMainFrame(); // When we stop deferring commits, we should resume any previously requested // pipeline stages. deferred_final_pipeline_stage_ = final_pipeline_stage_; @@ -284,8 +284,6 @@ current_pipeline_stage_ = COMMIT_PIPELINE_STAGE; if (final_pipeline_stage_ < COMMIT_PIPELINE_STAGE) { - current_pipeline_stage_ = NO_PIPELINE_STAGE; - layer_tree_host_->DidBeginMainFrame(); TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoUpdates", TRACE_EVENT_SCOPE_THREAD); layer_tree_host_->RecordEndOfFrameMetrics(begin_main_frame_start_time); std::vector<std::unique_ptr<SwapPromise>> swap_promises = @@ -300,7 +298,9 @@ // Although the commit is internally aborted, this is because it has been // detected to be a no-op. From the perspective of an embedder, this commit // went through, and input should no longer be throttled, etc. + current_pipeline_stage_ = NO_PIPELINE_STAGE; layer_tree_host_->CommitComplete(); + layer_tree_host_->DidBeginMainFrame(); return; } @@ -314,9 +314,6 @@ layer_tree_host_->QueueSwapPromise( std::make_unique<LatencyInfoSwapPromise>(new_latency_info)); - current_pipeline_stage_ = NO_PIPELINE_STAGE; - layer_tree_host_->DidBeginMainFrame(); - // Notify the impl thread that the main thread is ready to commit. This will // begin the commit process, which is blocking from the main thread's // point of view, but asynchronously performed on the impl thread, @@ -339,7 +336,9 @@ completion.Wait(); } + current_pipeline_stage_ = NO_PIPELINE_STAGE; layer_tree_host_->CommitComplete(); + layer_tree_host_->DidBeginMainFrame(); } void ProxyMain::DidPresentCompositorFrame(
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc index 056cfe70..874079dc 100644 --- a/cc/trees/single_thread_proxy.cc +++ b/cc/trees/single_thread_proxy.cc
@@ -231,8 +231,8 @@ << "Activation is expected to have synchronously occurred by now."; DebugScopedSetMainThread main(task_runner_provider_); - layer_tree_host_->DidBeginMainFrame(); layer_tree_host_->CommitComplete(); + layer_tree_host_->DidBeginMainFrame(); next_frame_is_newly_committed_frame_ = true; }
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedAppLifecycle.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedAppLifecycle.java index e6d5be9c..55de18d 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedAppLifecycle.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedAppLifecycle.java
@@ -15,6 +15,9 @@ import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.signin.SigninManager; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Aggregation point for application lifecycle events that the Feed cares about. Events that * originate in Java flow directly to FeedAppLifecycle, while native-originating events arrive @@ -22,12 +25,13 @@ */ public class FeedAppLifecycle implements SigninManager.SignInStateObserver, ApplicationStatus.ActivityStateListener { - @IntDef({AppLifecycleEvent.ENTER_FOREGROUND, AppLifecycleEvent.ENTER_BACKGROUND, - AppLifecycleEvent.CLEAR_ALL, AppLifecycleEvent.INITIALIZE, - AppLifecycleEvent.NUM_ENTRIES}) - // Intdef used to assign each event a number for metrics logging purposes. This maps directly to // the AppLifecycleEvent enum defined in tools/metrics/enums.xml + @IntDef({AppLifecycleEvent.ENTER_FOREGROUND, AppLifecycleEvent.ENTER_BACKGROUND, + AppLifecycleEvent.CLEAR_ALL, AppLifecycleEvent.INITIALIZE, AppLifecycleEvent.SIGN_IN, + AppLifecycleEvent.SIGN_OUT, AppLifecycleEvent.HISTORY_DELETED, + AppLifecycleEvent.CACHED_DATA_CLEARED}) + @Retention(RetentionPolicy.SOURCE) public @interface AppLifecycleEvent { int ENTER_FOREGROUND = 0; int ENTER_BACKGROUND = 1;
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/StreamLifecycleManager.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/StreamLifecycleManager.java index bda37b4..f2ad96e 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/StreamLifecycleManager.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/StreamLifecycleManager.java
@@ -29,21 +29,22 @@ */ class StreamLifecycleManager implements ApplicationStatus.ActivityStateListener { /** The different states that the Stream can be in its lifecycle. */ - @IntDef({NOT_SPECIFIED, CREATED, SHOWN, ACTIVE, INACTIVE, HIDDEN, DESTROYED}) + @IntDef({StreamState.NOT_SPECIFIED, StreamState.CREATED, StreamState.SHOWN, StreamState.ACTIVE, + StreamState.INACTIVE, StreamState.HIDDEN, StreamState.DESTROYED}) @Retention(RetentionPolicy.SOURCE) - private @interface StreamState {} + private @interface StreamState { + int NOT_SPECIFIED = -1; + int CREATED = 0; + int SHOWN = 1; + int ACTIVE = 2; + int INACTIVE = 3; + int HIDDEN = 4; + int DESTROYED = 5; + } /** Key for the Stream instance state that may be stored in a navigation entry. */ private static final String STREAM_SAVED_INSTANCE_STATE_KEY = "StreamSavedInstanceState"; - private static final int NOT_SPECIFIED = -1; - private static final int CREATED = 0; - private static final int SHOWN = 1; - private static final int ACTIVE = 2; - private static final int INACTIVE = 3; - private static final int HIDDEN = 4; - private static final int DESTROYED = 5; - /** The {@link Stream} that this class manages. */ private final Stream mStream; @@ -60,7 +61,7 @@ private final TabObserver mTabObserver; /** The current state the Stream is in its lifecycle. */ - private @StreamState int mStreamState = NOT_SPECIFIED; + private @StreamState int mStreamState = StreamState.NOT_SPECIFIED; /** * @param stream The {@link Stream} that this class manages. @@ -100,7 +101,7 @@ } }; - mStreamState = CREATED; + mStreamState = StreamState.CREATED; mStream.onCreate(restoreInstanceState()); show(); activate(); @@ -138,7 +139,8 @@ final int state = ApplicationStatus.getStateForActivity(mActivity); // We don't call Stream#onShow to prevent feed services from being warmed up if the user // has opted out from article suggestions during the previous session. - return (mStreamState == CREATED || mStreamState == HIDDEN) && !mTab.isHidden() + return (mStreamState == StreamState.CREATED || mStreamState == StreamState.HIDDEN) + && !mTab.isHidden() && (state == ActivityState.STARTED || state == ActivityState.RESUMED) && FeedProcessScopeFactory.areArticlesVisibleDuringSession(); } @@ -147,13 +149,14 @@ private void show() { if (!canShow()) return; - mStreamState = SHOWN; + mStreamState = StreamState.SHOWN; mStream.onShow(); } /** @return Whether the {@link Stream} can be activated. */ private boolean canActivate() { - return (mStreamState == SHOWN || mStreamState == INACTIVE) && mTab.isUserInteractable() + return (mStreamState == StreamState.SHOWN || mStreamState == StreamState.INACTIVE) + && mTab.isUserInteractable() && ApplicationStatus.getStateForActivity(mActivity) == ActivityState.RESUMED && FeedProcessScopeFactory.areArticlesVisibleDuringSession(); } @@ -164,25 +167,27 @@ show(); if (!canActivate()) return; - mStreamState = ACTIVE; + mStreamState = StreamState.ACTIVE; mStream.onActive(); } /** Calls {@link Stream#onInactive()}. */ private void deactivate() { - if (mStreamState != ACTIVE) return; + if (mStreamState != StreamState.ACTIVE) return; - mStreamState = INACTIVE; + mStreamState = StreamState.INACTIVE; mStream.onInactive(); } /** Calls {@link Stream#onHide()}. */ private void hide() { - if (mStreamState == HIDDEN || mStreamState == CREATED || mStreamState == DESTROYED) return; + if (mStreamState == StreamState.HIDDEN || mStreamState == StreamState.CREATED + || mStreamState == StreamState.DESTROYED) + return; // Make sure the Stream is inactive before setting it to hidden state. deactivate(); - mStreamState = HIDDEN; + mStreamState = StreamState.HIDDEN; // Save instance state as the Stream begins to hide. This matches the activity lifecycle // that instance state is saved as the activity begins to stop. saveInstanceState(); @@ -194,11 +199,11 @@ * anymore. */ void destroy() { - if (mStreamState == DESTROYED) return; + if (mStreamState == StreamState.DESTROYED) return; // Make sure the Stream is hidden before setting it to destroyed state. hide(); - mStreamState = DESTROYED; + mStreamState = StreamState.DESTROYED; mTab.removeObserver(mTabObserver); ApplicationStatus.unregisterActivityStateListener(this); mStream.onDestroy();
diff --git a/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_header.xml b/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_header.xml index 91f6bbb..bd934c70 100644 --- a/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_header.xml +++ b/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_header.xml
@@ -8,7 +8,8 @@ xmlns:tools="http://schemas.android.com/tools"> <LinearLayout android:layout_width="match_parent" - android:layout_height="56dp" + android:layout_height="wrap_content" + android:minHeight="56dp" android:gravity="center_vertical" android:orientation="horizontal" android:paddingStart="24dp"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ActivityTabTaskDescriptionHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ActivityTabTaskDescriptionHelper.java index 4624ea20..01d4bef 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ActivityTabTaskDescriptionHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ActivityTabTaskDescriptionHelper.java
@@ -22,6 +22,7 @@ import org.chromium.chrome.browser.tabmodel.TabSelectionType; import org.chromium.chrome.browser.util.UrlUtilities; import org.chromium.components.security_state.ConnectionSecurityLevel; +import org.chromium.content_public.browser.NavigationHandle; import java.util.List; @@ -90,11 +91,9 @@ } @Override - public void onDidFinishNavigation(Tab tab, String url, boolean isInMainFrame, - boolean isErrorPage, boolean hasCommitted, boolean isSameDocument, - boolean isFragmentNavigation, Integer pageTransition, int errorCode, - int httpStatusCode) { - if (hasCommitted && isInMainFrame && !isSameDocument) { + public void onDidFinishNavigation(Tab tab, NavigationHandle navigation) { + if (navigation.hasCommitted() && navigation.isInMainFrame() + && !navigation.isSameDocument()) { mLargestFavicon = null; updateTaskDescription(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index f79c87a3..af0e418 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -151,6 +151,7 @@ import org.chromium.components.feature_engagement.FeatureConstants; import org.chromium.components.feature_engagement.Tracker; import org.chromium.content_public.browser.LoadUrlParams; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContentsAccessibility; @@ -1545,14 +1546,11 @@ } @Override - public void onDidFinishNavigation(Tab tab, String url, boolean isInMainFrame, - boolean isErrorPage, boolean hasCommitted, boolean isSameDocument, - boolean isFragmentNavigation, Integer pageTransition, int errorCode, - int httpStatusCode) { - if (hasCommitted && isInMainFrame) { + public void onDidFinishNavigation(Tab tab, NavigationHandle navigation) { + if (navigation.hasCommitted() && navigation.isInMainFrame()) { DataReductionPromoInfoBar.maybeLaunchPromoInfoBar(ChromeTabbedActivity.this, - tab.getWebContents(), url, tab.isShowingErrorPage(), - isFragmentNavigation, httpStatusCode); + tab.getWebContents(), navigation.getUrl(), tab.isShowingErrorPage(), + navigation.isFragmentNavigation(), navigation.httpStatusCode()); } } };
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/PostMessageHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/PostMessageHandler.java index 3d50a330..9deadb5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/PostMessageHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/PostMessageHandler.java
@@ -16,6 +16,7 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.content_public.browser.MessagePort; import org.chromium.content_public.browser.MessagePort.MessageCallback; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContentsObserver; @@ -68,12 +69,9 @@ private boolean mNavigatedOnce; @Override - public void didFinishNavigation(String url, boolean isInMainFrame, boolean isErrorPage, - boolean hasCommitted, boolean isSameDocument, boolean isFragmentNavigation, - boolean isRendererInitiated, boolean isDownload, Integer pageTransition, - int errorCode, String errorDescription, int httpStatusCode) { - if (mNavigatedOnce && hasCommitted && isInMainFrame && !isSameDocument - && mChannel != null) { + public void didFinishNavigation(NavigationHandle navigation) { + if (mNavigatedOnce && navigation.hasCommitted() && navigation.isInMainFrame() + && !navigation.isSameDocument() && mChannel != null) { webContents.removeObserver(this); disconnectChannel(); return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifier.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifier.java index bfe36cb8..ef411bb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifier.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifier.java
@@ -23,6 +23,7 @@ import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabObserver; +import org.chromium.content_public.browser.NavigationHandle; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -81,16 +82,13 @@ /** A {@link TabObserver} that checks whether we are on a verified Origin on page navigation. */ private final TabObserver mVerifyOnPageLoadObserver = new EmptyTabObserver() { @Override - public void onDidFinishNavigation(Tab tab, String url, boolean isInMainFrame, - boolean isErrorPage, boolean hasCommitted, boolean isSameDocument, - boolean isFragmentNavigation, Integer pageTransition, int errorCode, - int httpStatusCode) { - if (!hasCommitted || !isInMainFrame) return; + public void onDidFinishNavigation(Tab tab, NavigationHandle navigation) { + if (!navigation.hasCommitted() || !navigation.isInMainFrame()) return; if (!ChromeFeatureList.isEnabled(ChromeFeatureList.TRUSTED_WEB_ACTIVITY)) { assert false : "Shouldn't observe navigation when TWAs are disabled"; return; } - verify(new Origin(url)); + verify(new Origin(navigation.getUrl())); } };
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java index d27ed854..cc4f08b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java
@@ -24,6 +24,7 @@ import org.chromium.components.navigation_interception.InterceptNavigationDelegate; import org.chromium.components.navigation_interception.NavigationParams; import org.chromium.content_public.browser.LoadUrlParams; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.RenderCoordinates; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContentsObserver; @@ -333,25 +334,21 @@ } @Override - public void didStartNavigation(String url, boolean isInMainFrame, - boolean isSameDocument, long navigationHandleProxy) { - if (isInMainFrame && !isSameDocument) { + public void didStartNavigation(NavigationHandle navigation) { + if (navigation.isInMainFrame() && !navigation.isSameDocument()) { + String url = navigation.getUrl(); mContentDelegate.onMainFrameLoadStarted( url, !TextUtils.equals(url, mLoadedUrl)); } } @Override - public void didFinishNavigation(String url, boolean isInMainFrame, - boolean isErrorPage, boolean hasCommitted, boolean isSameDocument, - boolean isFragmentNavigation, boolean isRendererInitiated, - boolean isDownload, Integer pageTransition, int errorCode, - String errorDescription, int httpStatusCode) { - if (hasCommitted && isInMainFrame) { + public void didFinishNavigation(NavigationHandle navigation) { + if (navigation.hasCommitted() && navigation.isInMainFrame()) { mIsProcessingPendingNavigation = false; - mContentDelegate.onMainFrameNavigation(url, - !TextUtils.equals(url, mLoadedUrl), - isHttpFailureCode(httpStatusCode)); + mContentDelegate.onMainFrameNavigation(navigation.getUrl(), + !TextUtils.equals(navigation.getUrl(), mLoadedUrl), + isHttpFailureCode(navigation.httpStatusCode())); } } };
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java index ecf159bc..a8224ac 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java
@@ -26,6 +26,7 @@ import org.chromium.chrome.browser.tab.TabObserver; import org.chromium.components.security_state.ConnectionSecurityLevel; import org.chromium.content_public.browser.LoadUrlParams; +import org.chromium.content_public.browser.NavigationHandle; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -186,13 +187,11 @@ } @Override - public void onDidFinishNavigation(Tab tab, String url, boolean isInMainFrame, - boolean isErrorPage, boolean hasCommitted, boolean isSameDocument, - boolean isFragmentNavigation, Integer pageTransition, int errorCode, - int httpStatusCode) { + public void onDidFinishNavigation(Tab tab, NavigationHandle navigation) { boolean firstNavigation = mFirstCommitTimestamp == 0; - boolean isFirstMainFrameCommit = firstNavigation && hasCommitted && !isErrorPage - && isInMainFrame && !isSameDocument && !isFragmentNavigation; + boolean isFirstMainFrameCommit = firstNavigation && navigation.hasCommitted() + && !navigation.isErrorPage() && navigation.isInMainFrame() + && !navigation.isSameDocument() && !navigation.isFragmentNavigation(); if (isFirstMainFrameCommit) mFirstCommitTimestamp = SystemClock.elapsedRealtime(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java index 5a6862f..3d71630 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java
@@ -44,7 +44,7 @@ import org.chromium.chrome.browser.tab.TabObserver; import org.chromium.chrome.browser.util.UrlUtilities; import org.chromium.content_public.browser.LoadUrlParams; -import org.chromium.content_public.browser.NavigationHandleProxy; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.WebContents; @@ -108,49 +108,43 @@ private final EmptyTabObserver mHeaderVisibilityObserver = new EmptyTabObserver() { @Override - public void onDidFinishNavigation(Tab tab, String url, boolean isInMainFrame, - boolean isErrorPage, boolean hasCommitted, - boolean isSameDocument, boolean isFragmentNavigation, - @Nullable Integer pageTransition, int errorCode, - int httpStatusCode) { - if (!isInMainFrame || !hasCommitted) return; - maybeCustomizeCctHeader(url); + public void onDidFinishNavigation(Tab tab, NavigationHandle navigation) { + if (!navigation.isInMainFrame() || !navigation.hasCommitted()) return; + maybeCustomizeCctHeader(navigation.getUrl()); } }; // Update the request's header on module managed URLs. private final EmptyTabObserver mCustomRequestHeaderModifier = new EmptyTabObserver() { @Override - public void onDidStartNavigation(Tab tab, String url, boolean isInMainFrame, - boolean isSameDocument, long navigationHandleProxy) { - if (!isInMainFrame || isSameDocument) return; - - updateCustomRequestHeader(url, navigationHandleProxy, false /* isRedirect */); + public void onDidStartNavigation(Tab tab, NavigationHandle navigation) { + updateCustomRequestHeader(navigation, /* isRedirect */ false); } @Override - public void onDidRedirectNavigation( - Tab tab, String url, boolean isInMainFrame, long navigationHandleProxy) { - if (!isInMainFrame) return; - - updateCustomRequestHeader(url, navigationHandleProxy, true /* isRedirect */); + public void onDidRedirectNavigation(Tab tab, NavigationHandle navigation) { + updateCustomRequestHeader(navigation, /* is_redirect */ true); } - private void updateCustomRequestHeader( - String url, long navigationHandleProxy, boolean isRedirect) { - if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_MODULE_CUSTOM_REQUEST_HEADER)) + private void updateCustomRequestHeader(NavigationHandle navigation, boolean isRedirect) { + // Update an header only when the navigation emit a network request.² + if (!navigation.isInMainFrame() || navigation.isSameDocument() + || navigation.isErrorPage() + || !ChromeFeatureList.isEnabled( + ChromeFeatureList.CCT_MODULE_CUSTOM_REQUEST_HEADER)) { return; + } + try (TraceEvent e = TraceEvent.scoped( "DynamicModuleCoordinator.updateCustomRequestHeader")) { - if (isModuleManagedUrl(url)) { + if (isModuleManagedUrl(navigation.getUrl())) { String headerValue = mIntentDataProvider.getExtraModuleManagedUrlsHeaderValue(); if (headerValue != null) { - NavigationHandleProxy.nativeSetRequestHeader(navigationHandleProxy, + navigation.setRequestHeader( DynamicModuleConstants.MANAGED_URL_HEADER, headerValue); } } else if (isRedirect) { - NavigationHandleProxy.nativeRemoveRequestHeader( - navigationHandleProxy, DynamicModuleConstants.MANAGED_URL_HEADER); + navigation.removeRequestHeader(DynamicModuleConstants.MANAGED_URL_HEADER); } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java index 5a4860c..91c40b1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java
@@ -36,6 +36,7 @@ import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.NavigationController; import org.chromium.content_public.browser.NavigationEntry; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContentsObserver; import org.chromium.ui.KeyboardVisibilityDelegate; @@ -313,9 +314,8 @@ private int mLastDistillerPageIndex; @Override - public void didStartNavigation(String url, boolean isInMainFrame, - boolean isSameDocument, long navigationHandleProxy) { - if (!isInMainFrame || isSameDocument) return; + public void didStartNavigation(NavigationHandle navigation) { + if (!navigation.isInMainFrame() || navigation.isSameDocument()) return; // Reader Mode should not pollute the navigation stack. To avoid this, watch for // navigations and prepare to remove any that are "chrome-distiller" urls. @@ -332,21 +332,20 @@ ReaderModeTabInfo tabInfo = mTabStatusMap.get(readerTabId); if (tabInfo == null) return; - tabInfo.setUrl(url); - if (DomDistillerUrlUtils.isDistilledPage(url)) { + tabInfo.setUrl(navigation.getUrl()); + if (DomDistillerUrlUtils.isDistilledPage(navigation.getUrl())) { tabInfo.setStatus(STARTED); - mReaderModePageUrl = url; + mReaderModePageUrl = navigation.getUrl(); } } @Override - public void didFinishNavigation(String url, boolean isInMainFrame, boolean isErrorPage, - boolean hasCommitted, boolean isSameDocument, boolean isFragmentNavigation, - boolean isRendererInitiated, boolean isDownload, Integer pageTransition, - int errorCode, String errorDescription, int httpStatusCode) { + public void didFinishNavigation(NavigationHandle navigation) { // TODO(cjhopman): This should possibly ignore navigations that replace the entry // (like those from history.replaceState()). - if (!hasCommitted || !isInMainFrame || isSameDocument) return; + if (!navigation.hasCommitted() || !navigation.isInMainFrame() + || navigation.isSameDocument()) + return; if (mShouldRemovePreviousNavigation) { mShouldRemovePreviousNavigation = false; @@ -361,7 +360,7 @@ if (tabInfo == null) return; tabInfo.setStatus(POSSIBLE); - if (!TextUtils.equals(url, + if (!TextUtils.equals(navigation.getUrl(), DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl( mReaderModePageUrl))) { tabInfo.setStatus(NOT_POSSIBLE);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainer.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainer.java index 629b170..af7db4d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainer.java
@@ -30,6 +30,7 @@ import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet; import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetObserver; import org.chromium.chrome.browser.widget.bottomsheet.EmptyBottomSheetObserver; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.WebContents; import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.display.DisplayAndroid; @@ -115,11 +116,8 @@ /** Resets the state of the InfoBarContainer when the user navigates. */ private final TabObserver mTabObserver = new EmptyTabObserver() { @Override - public void onDidFinishNavigation(Tab tab, String url, boolean isInMainFrame, - boolean isErrorPage, boolean hasCommitted, boolean isSameDocument, - boolean isFragmentNavigation, Integer pageTransition, int errorCode, - int httpStatusCode) { - if (hasCommitted && isInMainFrame) { + public void onDidFinishNavigation(Tab tab, NavigationHandle navigation) { + if (navigation.hasCommitted() && navigation.isInMainFrame()) { setHidden(false); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java index a79d0f6b3..e861be4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java
@@ -27,6 +27,7 @@ import org.chromium.components.url_formatter.UrlFormatter; import org.chromium.content_public.browser.MediaSession; import org.chromium.content_public.browser.MediaSessionObserver; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.WebContents; import org.chromium.media_session.mojom.MediaSessionAction; import org.chromium.services.media_session.MediaImage; @@ -297,13 +298,12 @@ } @Override - public void onDidFinishNavigation(Tab tab, String url, boolean isInMainFrame, - boolean isErrorPage, boolean hasCommitted, boolean isSameDocument, - boolean isFragmentNavigation, Integer pageTransition, int errorCode, - int httpStatusCode) { + public void onDidFinishNavigation(Tab tab, NavigationHandle navigation) { assert tab == mTab; - if (!hasCommitted || !isInMainFrame || isSameDocument) return; + if (!navigation.hasCommitted() || !navigation.isInMainFrame() + || navigation.isSameDocument()) + return; String origin = mTab.getUrl(); try {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/ActivityTabStartupMetricsTracker.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/ActivityTabStartupMetricsTracker.java index 4715fe74..4aec465ac 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/metrics/ActivityTabStartupMetricsTracker.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/ActivityTabStartupMetricsTracker.java
@@ -5,7 +5,6 @@ package org.chromium.chrome.browser.metrics; import android.os.SystemClock; -import android.support.annotation.Nullable; import org.chromium.base.library_loader.LibraryProcessType; import org.chromium.base.metrics.RecordHistogram; @@ -14,6 +13,7 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver; import org.chromium.chrome.browser.util.UrlUtilities; import org.chromium.content_public.browser.BrowserStartupController; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.WebContents; /** @@ -68,13 +68,12 @@ } @Override - public void onDidFinishNavigation(Tab tab, String url, boolean isInMainFrame, - boolean isErrorPage, boolean hasCommitted, boolean isSameDocument, - boolean isFragmentNavigation, @Nullable Integer pageTransition, - int errorCode, int httpStatusCode) { - boolean isTrackedPage = hasCommitted && isInMainFrame && !isErrorPage - && !isSameDocument && !isFragmentNavigation - && UrlUtilities.isHttpOrHttps(url); + public void onDidFinishNavigation(Tab tab, NavigationHandle navigation) { + boolean isTrackedPage = navigation.hasCommitted() + && navigation.isInMainFrame() && !navigation.isErrorPage() + && !navigation.isSameDocument() + && !navigation.isFragmentNavigation() + && UrlUtilities.isHttpOrHttps(navigation.getUrl()); registerFinishNavigation(isTrackedPage); } };
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarVoiceRecognitionHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarVoiceRecognitionHandler.java index 721a326..dd28aca3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarVoiceRecognitionHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarVoiceRecognitionHandler.java
@@ -12,7 +12,6 @@ import android.os.Bundle; import android.speech.RecognizerIntent; import android.support.annotation.IntDef; -import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import android.text.TextUtils; @@ -24,6 +23,7 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.toolbar.ToolbarDataProvider; import org.chromium.chrome.browser.util.FeatureUtilities; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.RenderFrameHost; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContentsObserver; @@ -193,11 +193,11 @@ } @Override - public void didFinishNavigation(String url, boolean isInMainFrame, boolean isErrorPage, - boolean hasCommitted, boolean isSameDocument, boolean isFragmentNavigation, - boolean isRendererInitiated, boolean isDownload, @Nullable Integer pageTransition, - int errorCode, String errorDescription, int httpStatusCode) { - if (hasCommitted && isInMainFrame && !isErrorPage) setReceivedUserGesture(url); + public void didFinishNavigation(NavigationHandle navigation) { + if (navigation.hasCommitted() && navigation.isInMainFrame() + && !navigation.isErrorPage()) { + setReceivedUserGesture(navigation.getUrl()); + } destroy(); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS b/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS index fa9c0a4..b961ce7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS
@@ -1,10 +1,13 @@ +include_rules = { + "+content/public/android/java/src/org/chromium/content_public", +} + specific_include_rules = { 'Tab\.java': [ "-chrome", "+chrome/android/java/src/org/chromium/chrome/browser/tab", "+components/embedder_support/android/java/src/org/chromium/components/embedder_support/view", "+components/navigation_interception/android/java/src/org/chromium/components/navigation_interception", - "+content/public/android/java/src/org/chromium/content_public", "+ui/android/java/src/org/chromium/ui/base", "+ui/android/java/src/org/chromium/ui/mojom", ],
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java index e4ff56c..9e5fcc9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java
@@ -11,6 +11,7 @@ import org.chromium.chrome.browser.tab.Tab.TabHidingType; import org.chromium.chrome.browser.tabmodel.TabSelectionType; import org.chromium.content_public.browser.LoadUrlParams; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.common.BrowserControlsState; @@ -98,18 +99,13 @@ Tab tab, boolean isMainFrame, int errorCode, String description, String failingUrl) {} @Override - public void onDidStartNavigation(Tab tab, String url, boolean isInMainFrame, - boolean isSameDocument, long navigationHandleProxy) {} + public void onDidStartNavigation(Tab tab, NavigationHandle navigationHandle) {} @Override - public void onDidRedirectNavigation( - Tab tab, String url, boolean isInMainFrame, long navigationHandleProxy) {} + public void onDidRedirectNavigation(Tab tab, NavigationHandle navigationHandle) {} @Override - public void onDidFinishNavigation(Tab tab, String url, boolean isInMainFrame, - boolean isErrorPage, boolean hasCommitted, boolean isSameDocument, - boolean isFragmentNavigation, Integer pageTransition, int errorCode, - int httpStatusCode) {} + public void onDidFinishNavigation(Tab tab, NavigationHandle navigationHandle) {} @Override public void didFirstVisuallyNonEmptyPaint(Tab tab) {}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserver.java index 49b8b87..0c9948fd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserver.java
@@ -5,7 +5,6 @@ package org.chromium.chrome.browser.tab; import android.graphics.Bitmap; -import android.support.annotation.Nullable; import android.view.ContextMenu; import org.chromium.chrome.browser.TabLoadStatus; @@ -13,6 +12,7 @@ import org.chromium.chrome.browser.tab.Tab.TabHidingType; import org.chromium.chrome.browser.tabmodel.TabSelectionType; import org.chromium.content_public.browser.LoadUrlParams; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.common.BrowserControlsState; @@ -222,52 +222,26 @@ /** * Called when a navigation is started in the WebContents. * @param tab The notifying {@link Tab}. - * @param url The validated URL for the loading page. - * @param isInMainFrame Whether the navigation is for the main frame. - * @param isSameDocument Whether the main frame navigation did not cause changes to the - * document (for example scrolling to a named anchor or PopState). - * @param navigationHandleProxy Pointer to a NavigationHandleProxy representing the navigation. - * Its lifetime is bound to this function. Do not store it. It can - * be used to modify headers. + * @param navigationHandle Pointer to a NavigationHandle representing the navigation. + * Its lifetime end at the end of onDidFinishNavigation(). */ - public void onDidStartNavigation(Tab tab, String url, boolean isInMainFrame, - boolean isSameDocument, long navigationHandleProxy); + public void onDidStartNavigation(Tab tab, NavigationHandle navigationHandle); /** * Called when a navigation is redirected in the WebContents. * @param tab The notifying {@link Tab}. - * @param url The validated URL for the loading page. - * @param isInMainFrame Whether the navigation is for the main frame. - * @param navigationHandleProxy Pointer to a NavigationHandleProxy representing the navigation. - * Its lifetime is bound to this function. Do not store it. It can - * be used to modify headers. + * @param navigationHandle Pointer to a NavigationHandle representing the navigation. + * Its lifetime end at the end of onDidFinishNavigation(). */ - public void onDidRedirectNavigation( - Tab tab, String url, boolean isInMainFrame, long navigationHandleProxy); + public void onDidRedirectNavigation(Tab tab, NavigationHandle navigationHandle); /** * Called when a navigation is finished i.e. committed, aborted or replaced by a new one. * @param tab The notifying {@link Tab}. - * @param url The validated URL for the loading page. - * @param isInMainFrame Whether the navigation is for the main frame. - * @param isErrorPage Whether the navigation shows an error page. - * @param hasCommitted Whether the navigation has committed. This returns true for either - * successful commits or error pages that replace the previous page - * (distinguished by |isErrorPage|), and false for errors that leave the - * user on the previous page. - * @param isSameDocument Whether the main frame navigation did not cause changes to the - * document (for example scrolling to a named anchor or PopState). - * @param isFragmentNavigation Whether the main frame navigation did not cause changes - * to the document (for example scrolling to a named anchor - * or PopState). - * @param pageTransition The page transition type associated with this navigation. - * @param errorCode The net error code if an error occurred prior to commit, otherwise net::OK. - * @param httpStatusCode The HTTP status code of the navigation. + * @param navigationHandle Pointer to a NavigationHandle representing the navigation. + * Its lifetime end at the end of this function. */ - public void onDidFinishNavigation(Tab tab, String url, boolean isInMainFrame, - boolean isErrorPage, boolean hasCommitted, boolean isSameDocument, - boolean isFragmentNavigation, @Nullable Integer pageTransition, int errorCode, - int httpStatusCode); + public void onDidFinishNavigation(Tab tab, NavigationHandle navigation); /** * Called when the page has painted something non-empty.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabStateBrowserControlsVisibilityDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabStateBrowserControlsVisibilityDelegate.java index c6684ebe..b44ca18 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabStateBrowserControlsVisibilityDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabStateBrowserControlsVisibilityDelegate.java
@@ -14,6 +14,7 @@ import org.chromium.chrome.browser.util.AccessibilityUtil; import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; import org.chromium.components.security_state.ConnectionSecurityLevel; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.SelectionPopupController; import org.chromium.content_public.browser.WebContents; @@ -86,11 +87,8 @@ } @Override - public void onDidFinishNavigation(Tab tab, String url, boolean isInMainFrame, - boolean isErrorPage, boolean hasCommitted, boolean isSameDocument, - boolean isFragmentNavigation, Integer pageTransition, int errorCode, - int httpStatusCode) { - if (!hasCommitted || !isInMainFrame) return; + public void onDidFinishNavigation(Tab tab, NavigationHandle navigation) { + if (!navigation.hasCommitted() || !navigation.isInMainFrame()) return; mHandler.removeMessages(MSG_ID_ENABLE_FULLSCREEN_AFTER_LOAD); mHandler.sendEmptyMessageDelayed( MSG_ID_ENABLE_FULLSCREEN_AFTER_LOAD, getLoadDelayMs());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabThemeColorHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabThemeColorHelper.java index 23f714be..e02f7f6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabThemeColorHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabThemeColorHelper.java
@@ -12,6 +12,7 @@ import org.chromium.base.VisibleForTesting; import org.chromium.chrome.browser.util.ColorUtils; import org.chromium.components.security_state.ConnectionSecurityLevel; +import org.chromium.content_public.browser.NavigationHandle; /** * Manages theme color used for {@link Tab}. Destroyed together with the tab. @@ -162,11 +163,8 @@ } @Override - public void onDidFinishNavigation(Tab tab, String url, boolean isInMainFrame, - boolean isErrorPage, boolean hasCommitted, boolean isSameDocument, - boolean isFragmentNavigation, @Nullable Integer pageTransition, int errorCode, - int httpStatusCode) { - if (errorCode != 0) updateIfNeeded(true); + public void onDidFinishNavigation(Tab tab, NavigationHandle navigation) { + if (navigation.errorCode() != 0) updateIfNeeded(true); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java index 46a3034..6c66988 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java
@@ -22,6 +22,7 @@ import org.chromium.chrome.browser.media.MediaCaptureNotificationService; import org.chromium.chrome.browser.policy.PolicyAuditor; import org.chromium.chrome.browser.policy.PolicyAuditor.AuditEvent; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContentsObserver; @@ -216,54 +217,46 @@ } @Override - public void didStartNavigation(String url, boolean isInMainFrame, boolean isSameDocument, - long navigationHandleProxy) { - if (isInMainFrame && !isSameDocument) { - mTab.didStartPageLoad(url); + public void didStartNavigation(NavigationHandle navigation) { + if (navigation.isInMainFrame() && !navigation.isSameDocument()) { + mTab.didStartPageLoad(navigation.getUrl()); } RewindableIterator<TabObserver> observers = mTab.getTabObservers(); while (observers.hasNext()) { - observers.next().onDidStartNavigation( - mTab, url, isInMainFrame, isSameDocument, navigationHandleProxy); + observers.next().onDidStartNavigation(mTab, navigation); } } @Override - public void didRedirectNavigation( - String url, boolean isInMainFrame, long navigationHandleProxy) { + public void didRedirectNavigation(NavigationHandle navigation) { RewindableIterator<TabObserver> observers = mTab.getTabObservers(); while (observers.hasNext()) { - observers.next().onDidRedirectNavigation( - mTab, url, isInMainFrame, navigationHandleProxy); + observers.next().onDidRedirectNavigation(mTab, navigation); } } @Override - public void didFinishNavigation(String url, boolean isInMainFrame, boolean isErrorPage, - boolean hasCommitted, boolean isSameDocument, boolean isFragmentNavigation, - boolean isRendererInitiated, boolean isDownload, Integer pageTransition, - int errorCode, String errorDescription, int httpStatusCode) { + public void didFinishNavigation(NavigationHandle navigation) { RewindableIterator<TabObserver> observers = mTab.getTabObservers(); while (observers.hasNext()) { - observers.next().onDidFinishNavigation(mTab, url, isInMainFrame, isErrorPage, - hasCommitted, isSameDocument, isFragmentNavigation, pageTransition, - errorCode, httpStatusCode); + observers.next().onDidFinishNavigation(mTab, navigation); } - if (errorCode != 0) { - if (isInMainFrame) mTab.didFailPageLoad(errorCode); + if (navigation.errorCode() != 0) { + if (navigation.isInMainFrame()) mTab.didFailPageLoad(navigation.errorCode()); - recordErrorInPolicyAuditor(url, errorDescription, errorCode); + recordErrorInPolicyAuditor( + navigation.getUrl(), navigation.errorDescription(), navigation.errorCode()); } - if (!hasCommitted) return; + if (!navigation.hasCommitted()) return; - if (isInMainFrame) { + if (navigation.isInMainFrame()) { mTab.setIsTabStateDirty(true); mTab.updateTitle(); - mTab.handleDidFinishNavigation(url, pageTransition); - mTab.setIsShowingErrorPage(isErrorPage); + mTab.handleDidFinishNavigation(navigation.getUrl(), navigation.pageTransition()); + mTab.setIsShowingErrorPage(navigation.isErrorPage()); observers.rewind(); while (observers.hasNext()) { @@ -272,11 +265,12 @@ } FullscreenManager fullscreenManager = mTab.getFullscreenManager(); - if (isInMainFrame && !isSameDocument && fullscreenManager != null) { + if (navigation.isInMainFrame() && !navigation.isSameDocument() + && fullscreenManager != null) { fullscreenManager.exitPersistentFullscreenMode(); } - if (isInMainFrame) { + if (navigation.isInMainFrame()) { // Stop swipe-to-refresh animation. SwipeRefreshHandler handler = SwipeRefreshHandler.get(mTab); if (handler != null) handler.didStopRefreshing();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index a1f189f..11d30c4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -109,6 +109,7 @@ import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.NavigationController; import org.chromium.content_public.browser.NavigationEntry; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.WebContents; import org.chromium.ui.AsyncViewProvider; @@ -566,9 +567,8 @@ } @Override - public void onDidStartNavigation(Tab tab, String url, boolean isInMainFrame, - boolean isSameDocument, long navigationHandleProxy) { - if (!isInMainFrame) return; + public void onDidStartNavigation(Tab tab, NavigationHandle navigation) { + if (!navigation.isInMainFrame()) return; // Update URL as soon as it becomes available when it's a new tab. // But we want to update only when it's a new tab. So we check whether the current // navigation entry is initial, meaning whether it has the same target URL as the @@ -579,14 +579,14 @@ mLocationBar.setUrlToPageUrl(); } - if (isSameDocument) return; + if (navigation.isSameDocument()) return; // This event is used as the primary trigger for the progress bar because it // is the earliest indication that a load has started for a particular frame. In // the case of the progress bar, it should only traverse the screen a single time // per page load. So if this event states the main frame has started loading the // progress bar is started. - if (NativePageFactory.isNativePageUrl(url, tab.isIncognito())) { + if (NativePageFactory.isNativePageUrl(navigation.getUrl(), tab.isIncognito())) { finishLoadProgress(false); return; } @@ -597,15 +597,13 @@ } @Override - public void onDidFinishNavigation(Tab tab, String url, boolean isInMainFrame, - boolean isErrorPage, boolean hasCommitted, boolean isSameDocument, - boolean isFragmentNavigation, Integer pageTransition, int errorCode, - int httpStatusCode) { - if (hasCommitted && isInMainFrame && !isSameDocument) { + public void onDidFinishNavigation(Tab tab, NavigationHandle navigation) { + if (navigation.hasCommitted() && navigation.isInMainFrame() + && !navigation.isSameDocument()) { mToolbar.onNavigatedToDifferentPage(); } - if (hasCommitted && tab.isPreview()) { + if (navigation.hasCommitted() && tab.isPreview()) { // Some previews are not fully decided until the page commits. If this // is a preview, update the security icon which will also update the verbose // status view to make sure the "Lite" badge is displayed. @@ -613,12 +611,13 @@ PreviewsUma.recordLitePageAtCommit( PreviewsAndroidBridge.getInstance().getPreviewsType( tab.getWebContents()), - isInMainFrame); + navigation.isInMainFrame()); } // If the load failed due to a different navigation, there is no need to reset the // location bar animations. - if (errorCode != 0 && isInMainFrame && !hasPendingNonNtpNavigation(tab)) { + if (navigation.errorCode() != 0 && navigation.isInMainFrame() + && !hasPendingNonNtpNavigation(tab)) { NewTabPage ntp = mLocationBarModel.getNewTabPageForCurrentTab(); if (ntp == null) return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkSplashNetworkErrorObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkSplashNetworkErrorObserver.java index 86e28e1..3e58a11 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkSplashNetworkErrorObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkSplashNetworkErrorObserver.java
@@ -11,6 +11,7 @@ import org.chromium.chrome.browser.metrics.WebApkUma; import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.net.NetError; import org.chromium.net.NetworkChangeNotifier; @@ -37,13 +38,10 @@ } @Override - public void onDidFinishNavigation(final Tab tab, final String url, boolean isInMainFrame, - boolean isErrorPage, boolean hasCommitted, boolean isSameDocument, - boolean isFragmentNavigation, Integer pageTransition, int errorCode, - int httpStatusCode) { - if (!isInMainFrame) return; + public void onDidFinishNavigation(final Tab tab, NavigationHandle navigation) { + if (!navigation.isInMainFrame()) return; - switch (errorCode) { + switch (navigation.errorCode()) { case ERROR_OK: mDelegate.hideWebApkNetworkErrorDialog(); break; @@ -51,10 +49,10 @@ onNetworkChanged(tab); break; default: - onNetworkError(tab, errorCode); + onNetworkError(tab, navigation.errorCode()); break; } - WebApkUma.recordNetworkErrorWhenLaunch(-errorCode); + WebApkUma.recordNetworkErrorWhenLaunch(-navigation.errorCode()); } private void onNetworkChanged(Tab tab) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java index 01c0bb6..bfdd9e4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -57,6 +57,7 @@ import org.chromium.chrome.browser.widget.TintedDrawable; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.NavigationController; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.ScreenOrientationProvider; import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.net.NetworkChangeNotifier; @@ -631,23 +632,20 @@ protected TabObserver createTabObserver() { return new EmptyTabObserver() { - @Override - public void onDidFinishNavigation(Tab tab, String url, boolean isInMainFrame, - boolean isErrorPage, boolean hasCommitted, boolean isSameDocument, - boolean isFragmentNavigation, Integer pageTransition, int errorCode, - int httpStatusCode) { - if (hasCommitted && isInMainFrame) { + public void onDidFinishNavigation(Tab tab, NavigationHandle navigation) { + if (navigation.hasCommitted() && navigation.isInMainFrame()) { // Notify the renderer to permanently hide the top controls since they do // not apply to fullscreen content views. tab.updateBrowserControlsState(tab.getBrowserControlsStateConstraints(), true); RecordHistogram.recordBooleanHistogram( - HISTOGRAM_NAVIGATION_STATUS, !isErrorPage); + HISTOGRAM_NAVIGATION_STATUS, !navigation.isErrorPage()); updateToolbarCloseButtonVisibility(); - if (!WebappScopePolicy.isUrlInScope(scopePolicy(), mWebappInfo, url)) { + if (!WebappScopePolicy.isUrlInScope( + scopePolicy(), mWebappInfo, navigation.getUrl())) { // Briefly show the toolbar for off-scope navigations. getFullscreenManager() .getBrowserVisibilityDelegate()
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java index 71b9f62..96ce5d2 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java
@@ -38,6 +38,7 @@ import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.content_public.browser.LoadUrlParams; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.TouchCommon; @@ -96,11 +97,8 @@ } @Override - public void onDidFinishNavigation(Tab tab, String url, boolean isInMainFrame, - boolean isErrorPage, boolean hasCommitted, boolean isSameDocument, - boolean isFragmentNavigation, Integer pageTransition, int errorCode, - int httpStatusCode) { - if (errorCode == 0) return; + public void onDidFinishNavigation(Tab tab, NavigationHandle navigation) { + if (navigation.errorCode() == 0) return; mFailCallback.notifyCalled(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarAppearanceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarAppearanceTest.java index c942710a..eefed199 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarAppearanceTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarAppearanceTest.java
@@ -25,6 +25,7 @@ import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.InfoBarTestAnimationListener; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.test.util.CriteriaHelper; import java.util.List; @@ -102,8 +103,7 @@ CallbackHelper callbackHelper = new CallbackHelper(); EmptyTabObserver navigationWaiter = new EmptyTabObserver() { @Override - public void onDidStartNavigation(Tab tab, String url, boolean isInMainFrame, - boolean isSameDocument, long navigationHandleProxy) { + public void onDidStartNavigation(Tab tab, NavigationHandle navigation) { callbackHelper.notifyCalled(); } };
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PictureInPictureControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PictureInPictureControllerTest.java index f1fec86..3a47793a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PictureInPictureControllerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PictureInPictureControllerTest.java
@@ -26,6 +26,7 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper; @@ -239,10 +240,7 @@ } @Override - public void onDidFinishNavigation(Tab tab, String url, boolean isInMainFrame, - boolean isErrorPage, boolean hasCommitted, boolean isSameDocument, - boolean isFragmentNavigation, Integer pageTransition, int errorCode, - int httpStatusCode) { + public void onDidFinishNavigation(Tab tab, NavigationHandle navigation) { mNavigationOccurred = true; } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/PermissionNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/PermissionNavigationTest.java index 76b87a4c..d00dbb80 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/PermissionNavigationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/PermissionNavigationTest.java
@@ -18,6 +18,7 @@ import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.test.util.CriteriaHelper; /** @@ -63,10 +64,7 @@ final CallbackHelper callbackHelper = new CallbackHelper(); EmptyTabObserver navigationWaiter = new EmptyTabObserver() { @Override - public void onDidFinishNavigation(Tab tab, String url, boolean isInMainFrame, - boolean isErrorPage, boolean hasCommitted, boolean isSameDocument, - boolean isFragmentNavigation, Integer pageTransition, int errorCode, - int httpStatusCode) { + public void onDidFinishNavigation(Tab tab, NavigationHandle navigation) { callbackHelper.notifyCalled(); } };
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifierTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifierTest.java index 86dab1b..969745f2 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifierTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifierTest.java
@@ -43,6 +43,7 @@ import org.chromium.chrome.test.util.browser.Features; import org.chromium.chrome.test.util.browser.Features.DisableFeatures; import org.chromium.chrome.test.util.browser.Features.EnableFeatures; +import org.chromium.content_public.browser.NavigationHandle; import java.util.Arrays; import java.util.HashSet; @@ -228,8 +229,18 @@ private void navigateToUrl(String url) { when(mTab.getUrl()).thenReturn(url); + NavigationHandle navigation = + new NavigationHandle(0 /* navigationHandleProxy */, url, true /* isMainFrame */, + false /* isSameDocument */, false /* isRendererInitiated */); for (TabObserver tabObserver : mTabObserverCaptor.getAllValues()) { - tabObserver.onDidFinishNavigation(mTab, url, true, false, true, true, false, 0, 0, 0); + tabObserver.onDidStartNavigation(mTab, navigation); + } + + navigation.didFinish(url, false /* isErrorPage */, true /* hasCommitted */, + false /* isFragmentNavigation */, false /* isDownload */, 0 /* pageTransition */, + 0 /* errorCode*/, 200 /* httpStatusCode*/); + for (TabObserver tabObserver : mTabObserverCaptor.getAllValues()) { + tabObserver.onDidFinishNavigation(mTab, navigation); } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationTestTabHolder.java b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationTestTabHolder.java index b6ac764..93ebf3e 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationTestTabHolder.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationTestTabHolder.java
@@ -16,6 +16,7 @@ import org.chromium.chrome.browser.favicon.LargeIconBridge; import org.chromium.chrome.browser.tab.Tab; import org.chromium.content_public.browser.MediaSession; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.WebContents; import org.chromium.services.media_session.MediaMetadata; @@ -97,9 +98,14 @@ public void simulateNavigation(String url, boolean isSameDocument) { mUrl = url; - mMediaSessionTabHelper.mTabObserver.onDidFinishNavigation(mTab, url, - true /* isInMainFrame */, false /* isErrorPage */, true /* hasCommitted */, - isSameDocument, false /* isFragmentNavigation */, 0 /* pageTransition */, + + NavigationHandle navigation = new NavigationHandle(0 /* navigationHandleProxy */, url, + true /* isInMainFrame */, isSameDocument, false /* isRendererInitiated */); + mMediaSessionTabHelper.mTabObserver.onDidStartNavigation(mTab, navigation); + + navigation.didFinish(url, false /* isErrorPage */, true /* hasCommitted */, + false /* isFragmentNavigation */, false /* isDownload */, 0 /* pageTransition */, 0 /* errorCode */, 200 /* httpStatusCode */); + mMediaSessionTabHelper.mTabObserver.onDidFinishNavigation(mTab, navigation); } }
diff --git a/chrome/app/BUILD.gn b/chrome/app/BUILD.gn index ec4bc38..09832433 100644 --- a/chrome/app/BUILD.gn +++ b/chrome/app/BUILD.gn
@@ -459,6 +459,7 @@ "//chromeos/services/media_perception/public/mojom", "//chromeos/services/multidevice_setup/public/cpp:manifest", "//chromeos/services/multidevice_setup/public/mojom", + "//media/capture/video/chromeos/mojo:cros_camera", "//ui/accessibility/mojom", ]
diff --git a/chrome/app/DEPS b/chrome/app/DEPS index fb87c9d..7ea4725 100644 --- a/chrome/app/DEPS +++ b/chrome/app/DEPS
@@ -62,6 +62,7 @@ "+components/translate/content/common", "+extensions/buildflags", "+extensions/common", + "+media/capture/video/chromeos/mojo", "+services/identity", "+services/image_annotation/public", "+services/resource_coordinator/public",
diff --git a/chrome/app/chrome_content_browser_overlay_manifest.cc b/chrome/app/chrome_content_browser_overlay_manifest.cc index 4eb0aa1..0679ebba 100644 --- a/chrome/app/chrome_content_browser_overlay_manifest.cc +++ b/chrome/app/chrome_content_browser_overlay_manifest.cc
@@ -59,6 +59,7 @@ #include "chromeos/services/media_perception/public/mojom/media_perception.mojom.h" #include "chromeos/services/multidevice_setup/public/cpp/manifest.h" #include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h" +#include "media/capture/video/chromeos/mojo/cros_image_capture.mojom.h" #include "services/ws/common/switches.h" #include "ui/accessibility/mojom/ax_host.mojom.h" // nogncheck #if BUILDFLAG(ENABLE_CROS_ASSISTANT) @@ -178,6 +179,7 @@ .RequireCapability("unzip", "unzip_file") .RequireCapability("util_win", "util_win") .RequireCapability("wifi_util_win", "wifi_credentials") + .RequireCapability("video_capture", "capture") .RequireCapability("xr_device_service", "xr_device_provider") .RequireCapability("xr_device_service", "xr_device_test_hook") #if defined(OS_CHROMEOS) @@ -206,6 +208,7 @@ #if defined(OS_CHROMEOS) chromeos::ime::mojom::InputEngineManager, chromeos::media_perception::mojom::MediaPerception, + cros::mojom::CrosImageCapture, #endif contextual_search::mojom::ContextualSearchJsApiService, dom_distiller::mojom::DistillabilityService,
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 4ac5ee1..b201111 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -3369,6 +3369,9 @@ <message name="IDS_CROSTINI_INSTALLER_INSTALLING" desc="Text shown in the Crostini installer dialog while Linux is installing."> Installing Linux... </message> + <message name="IDS_CROSTINI_INSTALLER_CANCELING" desc="Text shown in the Crostini installer dialog when the install is canceled."> + Canceling... + </message> <message name="IDS_CROSTINI_INSTALLER_ERROR_TITLE" desc="Title of the Crostini installer when an error occurs."> Error installing Linux... </message>
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 21d46d6..2c4b8b61 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -4215,6 +4215,14 @@ FEATURE_VALUE_TYPE(chromeos::features::kUserActivityPredictionMlService)}, #endif // defined(OS_CHROMEOS) +#if defined(OS_ANDROID) + {"manual-password-generation-android", + flag_descriptions::kManualPasswordGenerationAndroidName, + flag_descriptions::kManualPasswordGenerationAndroidDescription, kOsAndroid, + FEATURE_VALUE_TYPE( + password_manager::features::kManualPasswordGenerationAndroid)}, +#endif // defined(OS_ANDROID) + // NOTE: Adding a new flag requires adding a corresponding entry to enum // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag // Histograms" in tools/metrics/histograms/README.md (run the
diff --git a/chrome/browser/android/browsing_data/browsing_data_bridge.cc b/chrome/browser/android/browsing_data/browsing_data_bridge.cc index 16dc93ab..4091cdf 100644 --- a/chrome/browser/android/browsing_data/browsing_data_bridge.cc +++ b/chrome/browser/android/browsing_data/browsing_data_bridge.cc
@@ -28,10 +28,10 @@ #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/common/channel_info.h" #include "chrome/common/chrome_features.h" -#include "components/browser_sync/profile_sync_service.h" #include "components/browsing_data/core/history_notice_utils.h" #include "components/browsing_data/core/pref_names.h" #include "components/prefs/pref_service.h" +#include "components/sync/driver/sync_service.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browsing_data_filter_builder.h" #include "content/public/browser/browsing_data_remover.h"
diff --git a/chrome/browser/app_controller_mac_unittest.mm b/chrome/browser/app_controller_mac_unittest.mm index 565c194a..3327cc8 100644 --- a/chrome/browser/app_controller_mac_unittest.mm +++ b/chrome/browser/app_controller_mac_unittest.mm
@@ -13,16 +13,11 @@ #import "chrome/browser/app_controller_mac.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile_manager.h" -#include "chrome/browser/signin/signin_error_controller_factory.h" -#include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" -#include "components/browser_sync/profile_sync_service.h" -#include "components/browser_sync/profile_sync_service_mock.h" -#include "components/signin/core/browser/signin_error_controller.h" #include "content/public/test/test_browser_thread_bundle.h" #include "testing/platform_test.h"
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index f15d9d1..c116945 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -475,6 +475,7 @@ <include name="IDR_SITE_ENGAGEMENT_JS" file="resources\engagement\site_engagement.js" flattenhtml="true" type="BINDATA" compress="gzip" /> <include name="IDR_SITE_ENGAGEMENT_MOJO_JS" file="${root_gen_dir}\chrome\browser\engagement\site_engagement_details.mojom.js" use_base_dir="false" type="BINDATA" compress="gzip" /> <include name="IDR_URL_MOJO_JS" file="${root_gen_dir}\url\mojom\url.mojom.js" use_base_dir="false" type="BINDATA" compress="gzip" /> + <include name="IDR_URL_MOJO_LITE_JS" file="${root_gen_dir}\url\mojom\url.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" /> <include name="IDR_SYNC_CONFIRMATION_CSS" file="resources\signin\sync_confirmation\sync_confirmation.css" type="BINDATA" /> <include name="IDR_SYNC_CONFIRMATION_HTML" file="resources\signin\sync_confirmation\sync_confirmation.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> <include name="IDR_SYNC_CONFIRMATION_JS" file="resources\signin\sync_confirmation\sync_confirmation.js" type="BINDATA" /> @@ -491,8 +492,8 @@ <include name="IDR_USB_INTERNALS_CSS" file="resources\usb_internals\usb_internals.css" type="BINDATA" compress="gzip" /> <include name="IDR_USB_INTERNALS_HTML" file="resources\usb_internals\usb_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" /> <include name="IDR_USB_INTERNALS_JS" file="resources\usb_internals\usb_internals.js" type="BINDATA" compress="gzip" /> - <include name="IDR_USB_INTERNALS_MOJO_JS" file="${root_gen_dir}\chrome\browser\ui\webui\usb_internals\usb_internals.mojom.js" use_base_dir="false" type="BINDATA" compress="gzip" /> - <include name="IDR_USB_DEVICE_MANAGER_TEST_MOJO_JS" file="${root_gen_dir}\device\usb\public\mojom\device_manager_test.mojom.js" use_base_dir="false" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" /> + <include name="IDR_USB_INTERNALS_MOJO_JS" file="${root_gen_dir}\chrome\browser\ui\webui\usb_internals\usb_internals.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" /> + <include name="IDR_USB_DEVICE_MANAGER_TEST_MOJO_JS" file="${root_gen_dir}\device\usb\public\mojom\device_manager_test.mojom-lite.js" use_base_dir="false" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" /> <include name="IDR_WEBRTC_LOGS_HTML" file="resources\media\webrtc_logs.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> <include name="IDR_WEBRTC_LOGS_JS" file="resources\media\webrtc_logs.js" type="BINDATA" /> <include name="IDR_WEBSTORE_MANIFEST" file="resources\webstore_app\manifest.json" type="BINDATA" />
diff --git a/chrome/browser/browsing_data/counters/browsing_data_counter_factory.cc b/chrome/browser/browsing_data/counters/browsing_data_counter_factory.cc index 29c25a0..69fa7f2 100644 --- a/chrome/browser/browsing_data/counters/browsing_data_counter_factory.cc +++ b/chrome/browser/browsing_data/counters/browsing_data_counter_factory.cc
@@ -22,7 +22,6 @@ #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/web_data_service_factory.h" #include "chrome/browser/webauthn/chrome_authenticator_request_delegate.h" -#include "components/browser_sync/profile_sync_service.h" #include "components/browsing_data/core/counters/autofill_counter.h" #include "components/browsing_data/core/counters/browsing_data_counter.h" #include "components/browsing_data/core/counters/history_counter.h" @@ -30,6 +29,7 @@ #include "components/browsing_data/core/pref_names.h" #include "components/history/core/browser/web_history_service.h" #include "components/password_manager/core/browser/password_store.h" +#include "components/sync/driver/sync_service.h" #include "extensions/buildflags/buildflags.h" #if BUILDFLAG(ENABLE_EXTENSIONS)
diff --git a/chrome/browser/browsing_data/counters/browsing_data_counter_utils_unittest.cc b/chrome/browser/browsing_data/counters/browsing_data_counter_utils_unittest.cc index 9cbcf094..76970685 100644 --- a/chrome/browser/browsing_data/counters/browsing_data_counter_utils_unittest.cc +++ b/chrome/browser/browsing_data/counters/browsing_data_counter_utils_unittest.cc
@@ -15,8 +15,8 @@ #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" -#include "components/browser_sync/profile_sync_service.h" #include "components/password_manager/core/browser/test_password_store.h" +#include "components/sync/driver/sync_service.h" #include "content/public/test/test_browser_thread_bundle.h" #include "extensions/buildflags/buildflags.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/browsing_data/counters/site_data_counter.cc b/chrome/browser/browsing_data/counters/site_data_counter.cc index a1e4647..6d251567 100644 --- a/chrome/browser/browsing_data/counters/site_data_counter.cc +++ b/chrome/browser/browsing_data/counters/site_data_counter.cc
@@ -8,8 +8,8 @@ #include "chrome/browser/browsing_data/counters/browsing_data_counter_utils.h" #include "chrome/browser/browsing_data/counters/site_data_counting_helper.h" #include "chrome/browser/sync/profile_sync_service_factory.h" -#include "components/browser_sync/profile_sync_service.h" #include "components/browsing_data/core/pref_names.h" +#include "components/sync/driver/sync_service.h" #include "content/public/browser/browser_thread.h" using content::BrowserThread;
diff --git a/chrome/browser/chromeos/arc/file_system_watcher/arc_file_system_watcher_service.cc b/chrome/browser/chromeos/arc/file_system_watcher/arc_file_system_watcher_service.cc index d66c703..8e77dfe2 100644 --- a/chrome/browser/chromeos/arc/file_system_watcher/arc_file_system_watcher_service.cc +++ b/chrome/browser/chromeos/arc/file_system_watcher/arc_file_system_watcher_service.cc
@@ -24,6 +24,7 @@ #include "base/task/task_traits.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/time/time.h" +#include "chrome/browser/chromeos/file_manager/path_util.h" #include "chrome/browser/download/download_prefs.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_paths.h" @@ -46,6 +47,11 @@ constexpr base::FilePath::CharType kAndroidDownloadDir[] = FILE_PATH_LITERAL("/storage/emulated/0/Download"); +// The MyFiles path inside ARC container. This will be the path that is used in +// MediaScanner.scanFile request. +constexpr base::FilePath::CharType kAndroidMyFilesDir[] = + FILE_PATH_LITERAL("/storage/MyFiles"); + // The removable media path in ChromeOS. This is the actual directory to be // watched. constexpr base::FilePath::CharType kCrosRemovableMediaDir[] = @@ -400,6 +406,7 @@ StopWatchingFileSystem(); DCHECK(!downloads_watcher_); + DCHECK(!myfiles_watcher_); DCHECK(!removable_media_watcher_); arc_bridge_service_->file_system()->RemoveObserver(this); @@ -418,40 +425,52 @@ void ArcFileSystemWatcherService::StartWatchingFileSystem() { DCHECK_CURRENTLY_ON(BrowserThread::UI); StopWatchingFileSystem(); + Profile* profile = Profile::FromBrowserContext(context_); + DCHECK(!downloads_watcher_); - downloads_watcher_ = std::make_unique<FileSystemWatcher>( - context_, - base::Bind(&ArcFileSystemWatcherService::OnFileSystemChanged, - weak_ptr_factory_.GetWeakPtr()), - DownloadPrefs(Profile::FromBrowserContext(context_)) + downloads_watcher_ = CreateAndStartFileSystemWatcher( + DownloadPrefs(profile) .GetDefaultDownloadDirectoryForProfile() .StripTrailingSeparators(), base::FilePath(kAndroidDownloadDir)); - file_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&FileSystemWatcher::Start, - base::Unretained(downloads_watcher_.get()))); + + DCHECK(!myfiles_watcher_); + myfiles_watcher_ = CreateAndStartFileSystemWatcher( + file_manager::util::GetMyFilesFolderForProfile(profile), + base::FilePath(kAndroidMyFilesDir)); + DCHECK(!removable_media_watcher_); - removable_media_watcher_ = std::make_unique<FileSystemWatcher>( - context_, - base::Bind(&ArcFileSystemWatcherService::OnFileSystemChanged, - weak_ptr_factory_.GetWeakPtr()), + removable_media_watcher_ = CreateAndStartFileSystemWatcher( base::FilePath(kCrosRemovableMediaDir), base::FilePath(kAndroidRemovableMediaDir)); - file_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&FileSystemWatcher::Start, - base::Unretained(removable_media_watcher_.get()))); } void ArcFileSystemWatcherService::StopWatchingFileSystem() { DCHECK_CURRENTLY_ON(BrowserThread::UI); if (downloads_watcher_) file_task_runner_->DeleteSoon(FROM_HERE, downloads_watcher_.release()); + if (myfiles_watcher_) + file_task_runner_->DeleteSoon(FROM_HERE, myfiles_watcher_.release()); if (removable_media_watcher_) file_task_runner_->DeleteSoon(FROM_HERE, removable_media_watcher_.release()); } +std::unique_ptr<ArcFileSystemWatcherService::FileSystemWatcher> +ArcFileSystemWatcherService::CreateAndStartFileSystemWatcher( + const base::FilePath& cros_path, + const base::FilePath& android_path) { + auto watcher = std::make_unique<FileSystemWatcher>( + context_, + base::BindRepeating(&ArcFileSystemWatcherService::OnFileSystemChanged, + weak_ptr_factory_.GetWeakPtr()), + base::FilePath(cros_path), base::FilePath(android_path)); + file_task_runner_->PostTask(FROM_HERE, + base::BindOnce(&FileSystemWatcher::Start, + base::Unretained(watcher.get()))); + return watcher; +} + void ArcFileSystemWatcherService::OnFileSystemChanged( const std::vector<std::string>& paths) { DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/chrome/browser/chromeos/arc/file_system_watcher/arc_file_system_watcher_service.h b/chrome/browser/chromeos/arc/file_system_watcher/arc_file_system_watcher_service.h index d68f8919..1367ba78 100644 --- a/chrome/browser/chromeos/arc/file_system_watcher/arc_file_system_watcher_service.h +++ b/chrome/browser/chromeos/arc/file_system_watcher/arc_file_system_watcher_service.h
@@ -62,12 +62,16 @@ void StartWatchingFileSystem(); void StopWatchingFileSystem(); + std::unique_ptr<FileSystemWatcher> CreateAndStartFileSystemWatcher( + const base::FilePath& cros_path, + const base::FilePath& android_path); void OnFileSystemChanged(const std::vector<std::string>& paths); content::BrowserContext* const context_; ArcBridgeService* const arc_bridge_service_; // Owned by ArcServiceManager. std::unique_ptr<FileSystemWatcher> downloads_watcher_; + std::unique_ptr<FileSystemWatcher> myfiles_watcher_; std::unique_ptr<FileSystemWatcher> removable_media_watcher_; scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
diff --git a/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.cc b/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.cc index 5340715..6f1f6e0 100644 --- a/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.cc +++ b/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.cc
@@ -343,8 +343,7 @@ if (state_ != State::kDisabled) { DLOG(WARNING) << "Cannot start tracing, it is already enabled."; - if (callback) - std::move(callback).Run(false /*success*/); + std::move(callback).Run(false /*success*/); return; } state_ = State::kStarting; @@ -391,8 +390,7 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_EQ(State::kStarting, state_); state_ = success ? State::kEnabled : State::kDisabled; - if (callback) - std::move(callback).Run(success); + std::move(callback).Run(success); } void ArcTracingBridge::StopAndFlush(TraceDataCallback callback) { @@ -463,9 +461,10 @@ void ArcTracingBridge::ArcTracingAgent::StartTracing( const std::string& config, - base::TimeTicks coordinator_time) { + base::TimeTicks coordinator_time, + Agent::StartTracingCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - bridge_->StartTracing(config, SuccessCallback()); + bridge_->StartTracing(config, std::move(callback)); } void ArcTracingBridge::ArcTracingAgent::StopAndFlush(
diff --git a/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.h b/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.h index e77f8a4..dc321c2 100644 --- a/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.h +++ b/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.h
@@ -78,7 +78,8 @@ // tracing::mojom::Agent. void StartTracing(const std::string& config, - base::TimeTicks coordinator_time) override; + base::TimeTicks coordinator_time, + Agent::StartTracingCallback callback) override; void StopAndFlush(tracing::mojom::RecorderPtr recorder) override; void OnTraceData(const std::string& data);
diff --git a/chrome/browser/chromeos/file_manager/file_manager_jstest.cc b/chrome/browser/chromeos/file_manager/file_manager_jstest.cc index f780e696..61f576e 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_jstest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_jstest.cc
@@ -197,3 +197,7 @@ IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ListContainer) { RunGeneratedTest("/foreground/js/ui/list_container_unittest.html"); } + +IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FileTableList) { + RunGeneratedTest("/foreground/js/ui/file_table_list_unittest.html"); +}
diff --git a/chrome/browser/chromeos/login/signin/oauth2_login_verifier.cc b/chrome/browser/chromeos/login/signin/oauth2_login_verifier.cc index 7fc9ffa..bd19f8b 100644 --- a/chrome/browser/chromeos/login/signin/oauth2_login_verifier.cc +++ b/chrome/browser/chromeos/login/signin/oauth2_login_verifier.cc
@@ -22,7 +22,8 @@ : delegate_(delegate), identity_manager_(identity_manager), primary_account_id_(primary_account_id), - access_token_(oauthlogin_access_token) { + access_token_(oauthlogin_access_token), + weak_ptr_factory_(this) { DCHECK(delegate); identity_manager_->AddObserver(this); } @@ -47,13 +48,19 @@ void OAuth2LoginVerifier::VerifyProfileTokens() { DCHECK_CURRENTLY_ON(BrowserThread::UI); + + GaiaCookieManagerService::AddAccountToCookieCompletedCallback + completion_callback = + base::BindOnce(&OAuth2LoginVerifier::OnAddAccountToCookieCompleted, + weak_ptr_factory_.GetWeakPtr()); if (access_token_.empty()) { identity_manager_->GetAccountsCookieMutator()->AddAccountToCookie( - primary_account_id_, gaia::GaiaSource::kOAuth2LoginVerifier); + primary_account_id_, gaia::GaiaSource::kOAuth2LoginVerifier, + std::move(completion_callback)); } else { identity_manager_->GetAccountsCookieMutator()->AddAccountToCookieWithToken( primary_account_id_, access_token_, - gaia::GaiaSource::kOAuth2LoginVerifier); + gaia::GaiaSource::kOAuth2LoginVerifier, std::move(completion_callback)); } }
diff --git a/chrome/browser/chromeos/login/signin/oauth2_login_verifier.h b/chrome/browser/chromeos/login/signin/oauth2_login_verifier.h index e2f2d92a..6eb4ae1 100644 --- a/chrome/browser/chromeos/login/signin/oauth2_login_verifier.h +++ b/chrome/browser/chromeos/login/signin/oauth2_login_verifier.h
@@ -11,6 +11,7 @@ #include "base/compiler_specific.h" #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "chrome/browser/profiles/profile.h" #include "services/identity/public/cpp/identity_manager.h" @@ -53,18 +54,20 @@ private: // IdentityManager::Observer - void OnAddAccountToCookieCompleted( - const std::string& account_id, - const GoogleServiceAuthError& error) override; void OnAccountsInCookieUpdated( const identity::AccountsInCookieJarInfo& accounts_in_cookie_jar_info, const GoogleServiceAuthError& error) override; + void OnAddAccountToCookieCompleted(const std::string& account_id, + const GoogleServiceAuthError& error); + OAuth2LoginVerifier::Delegate* delegate_; identity::IdentityManager* identity_manager_; const std::string primary_account_id_; const std::string access_token_; + base::WeakPtrFactory<OAuth2LoginVerifier> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(OAuth2LoginVerifier); };
diff --git a/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl_unittest.cc b/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl_unittest.cc index 18fab36..2e8d9e8 100644 --- a/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl_unittest.cc +++ b/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl_unittest.cc
@@ -137,8 +137,6 @@ user_manager::ScopedUserManager user_manager_enabler_; chromeos::ScopedCrosSettingsTestHelper cros_settings_test_helper_; network::TestURLLoaderFactory test_url_loader_factory_; - scoped_refptr<network::WeakWrapperSharedURLLoaderFactory> - test_shared_loader_factory_; TestingProfileManager profile_manager_; }; @@ -184,8 +182,8 @@ return invalidation_service_set_count; } -const invalidation::InvalidationService* -FakeConsumer::GetInvalidationService() const { +const invalidation::InvalidationService* FakeConsumer::GetInvalidationService() + const { return invalidation_service_; } @@ -195,9 +193,6 @@ profile_invalidation_service_(nullptr), fake_user_manager_(new chromeos::FakeChromeUserManager), user_manager_enabler_(base::WrapUnique(fake_user_manager_)), - test_shared_loader_factory_( - base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( - &test_url_loader_factory_)), profile_manager_(TestingBrowserProcess::GetGlobal()) { cros_settings_test_helper_.InstallAttributes()->SetCloudManaged("example.com", "device_id"); @@ -209,7 +204,7 @@ ASSERT_TRUE(profile_manager_.SetUp()); chromeos::DeviceOAuth2TokenServiceFactory::Initialize( - test_shared_loader_factory_, + test_url_loader_factory_.GetSafeWeakWrapper(), TestingBrowserProcess::GetGlobal()->local_state()); invalidation::DeprecatedProfileInvalidationProviderFactory::GetInstance() @@ -223,7 +218,6 @@ consumer_.reset(); provider_->Shutdown(); provider_.reset(); - test_shared_loader_factory_->Detach(); invalidation::DeprecatedProfileInvalidationProviderFactory::GetInstance() ->RegisterTestingFactory(
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn index 9f157580..548dbe0 100644 --- a/chrome/browser/extensions/BUILD.gn +++ b/chrome/browser/extensions/BUILD.gn
@@ -421,6 +421,8 @@ "blacklist_state_fetcher.h", "bookmark_app_experimental_navigation_throttle.cc", "bookmark_app_experimental_navigation_throttle.h", + "bookmark_app_extension_util.cc", + "bookmark_app_extension_util.h", "bookmark_app_helper.cc", "bookmark_app_helper.h", "bookmark_app_navigation_throttle.cc", @@ -876,6 +878,7 @@ "//services/network/public/mojom", "//services/service_manager/public/cpp", "//services/service_manager/public/mojom", + "//services/video_capture/public/mojom:constants", "//skia", "//sql", "//storage/browser", @@ -982,10 +985,10 @@ "//components/constrained_window", "//components/drive", "//components/user_manager", + "//media/capture/video/chromeos/mojo:cros_camera", "//remoting/base", "//remoting/host", "//remoting/host/it2me:chrome_os_host", - "//services/video_capture/public/mojom:constants", "//third_party/protobuf:protobuf_lite", "//ui/chromeos", "//ui/chromeos/events",
diff --git a/chrome/browser/extensions/api/debugger/debugger_api.cc b/chrome/browser/extensions/api/debugger/debugger_api.cc index e6c793b..529a9277 100644 --- a/chrome/browser/extensions/api/debugger/debugger_api.cc +++ b/chrome/browser/extensions/api/debugger/debugger_api.cc
@@ -525,7 +525,7 @@ GetProfile(), agent_host_.get(), extension(), debuggee_); if (!host->Attach()) { - FormatErrorMessage(debugger_api_constants::kRestrictedError); + error_ = debugger_api_constants::kRestrictedError; return false; }
diff --git a/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc b/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc index 945c5a1..b60f7e4 100644 --- a/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc +++ b/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc
@@ -162,7 +162,7 @@ // Add a rule. api::events::Rule rule; api::events::Rule::Populate( - *base::test::ParseJson( + *base::test::ParseJsonDeprecated( "{\n" " \"id\": \"rule1\",\n" " \"priority\": 100,\n" @@ -178,8 +178,8 @@ &rule); std::vector<const api::events::Rule*> rules({&rule}); - const Extension* extension = env()->MakeExtension(*base::test::ParseJson( - "{\"page_action\": {}}")); + const Extension* extension = env()->MakeExtension( + *base::test::ParseJsonDeprecated("{\"page_action\": {}}")); registry->AddRulesImpl(extension->id(), rules); registry->DidFinishNavigation(tab.get(), &navigation_handle);
diff --git a/chrome/browser/extensions/api/declarative_content/content_action_unittest.cc b/chrome/browser/extensions/api/declarative_content/content_action_unittest.cc index b6d947e..42e49361 100644 --- a/chrome/browser/extensions/api/declarative_content/content_action_unittest.cc +++ b/chrome/browser/extensions/api/declarative_content/content_action_unittest.cc
@@ -33,7 +33,7 @@ namespace extensions { namespace { -using base::test::ParseJson; +using base::test::ParseJsonDeprecated; using testing::HasSubstr; std::unique_ptr<base::DictionaryValue> SimpleManifest() { @@ -75,13 +75,15 @@ // Test wrong data type passed. error.clear(); - result = ContentAction::Create(&profile, nullptr, *ParseJson("[]"), &error); + result = ContentAction::Create(&profile, nullptr, *ParseJsonDeprecated("[]"), + &error); EXPECT_THAT(error, HasSubstr("missing instanceType")); EXPECT_FALSE(result.get()); // Test missing instanceType element. error.clear(); - result = ContentAction::Create(&profile, nullptr, *ParseJson("{}"), &error); + result = ContentAction::Create(&profile, nullptr, *ParseJsonDeprecated("{}"), + &error); EXPECT_THAT(error, HasSubstr("missing instanceType")); EXPECT_FALSE(result.get()); @@ -89,9 +91,10 @@ error.clear(); result = ContentAction::Create( &profile, nullptr, - *ParseJson("{\n" - " \"instanceType\": \"declarativeContent.UnknownType\",\n" - "}"), + *ParseJsonDeprecated( + "{\n" + " \"instanceType\": \"declarativeContent.UnknownType\",\n" + "}"), &error); EXPECT_THAT(error, HasSubstr("invalid instanceType")); EXPECT_FALSE(result.get()); @@ -118,9 +121,10 @@ std::string error; std::unique_ptr<const ContentAction> result = ContentAction::Create( &profile, extension.get(), - *ParseJson("{\n" - " \"instanceType\": \"declarativeContent.ShowAction\",\n" - "}"), + *ParseJsonDeprecated( + "{\n" + " \"instanceType\": \"declarativeContent.ShowAction\",\n" + "}"), &error); EXPECT_THAT(error, testing::HasSubstr("without an action")); ASSERT_FALSE(result.get()); @@ -145,7 +149,8 @@ TestingProfile profile; std::unique_ptr<const ContentAction> result = ContentAction::Create( nullptr, extension.get(), - *ParseJson(R"({"instanceType": "declarativeContent.ShowAction"})"), + *ParseJsonDeprecated( + R"({"instanceType": "declarativeContent.ShowAction"})"), &error); EXPECT_TRUE(error.empty()) << error; ASSERT_TRUE(result.get()); @@ -219,8 +224,8 @@ .Set("imageData", DictionaryBuilder().Set("19", data64).Build()) .Build(); - const Extension* extension = env.MakeExtension( - *ParseJson("{\"page_action\": { \"default_title\": \"Extension\" } }")); + const Extension* extension = env.MakeExtension(*ParseJsonDeprecated( + "{\"page_action\": { \"default_title\": \"Extension\" } }")); base::HistogramTester histogram_tester; TestingProfile profile; std::string error; @@ -278,8 +283,8 @@ .Build(); // Expect an error and no instance to be created. - const Extension* extension = env.MakeExtension( - *ParseJson(R"({"page_action": {"default_title": "Extension"}})")); + const Extension* extension = env.MakeExtension(*ParseJsonDeprecated( + R"({"page_action": {"default_title": "Extension"}})")); base::HistogramTester histogram_tester; TestingProfile profile; std::string error; @@ -302,7 +307,7 @@ std::string error; std::unique_ptr<const ContentAction> result = ContentAction::Create( profile(), extension(), - *ParseJson( + *ParseJsonDeprecated( "{\n" " \"instanceType\": \"declarativeContent.RequestContentScript\",\n" " \"allFrames\": true,\n" @@ -318,7 +323,7 @@ std::string error; std::unique_ptr<const ContentAction> result = ContentAction::Create( profile(), extension(), - *ParseJson( + *ParseJsonDeprecated( "{\n" " \"instanceType\": \"declarativeContent.RequestContentScript\",\n" " \"css\": [\"style.css\"]\n" @@ -333,7 +338,7 @@ std::string error; std::unique_ptr<const ContentAction> result = ContentAction::Create( profile(), extension(), - *ParseJson( + *ParseJsonDeprecated( "{\n" " \"instanceType\": \"declarativeContent.RequestContentScript\",\n" " \"js\": [\"script.js\"]\n" @@ -348,7 +353,7 @@ std::string error; std::unique_ptr<const ContentAction> result = ContentAction::Create( profile(), extension(), - *ParseJson( + *ParseJsonDeprecated( "{\n" " \"instanceType\": \"declarativeContent.RequestContentScript\",\n" " \"css\": \"style.css\"\n" @@ -362,7 +367,7 @@ std::string error; std::unique_ptr<const ContentAction> result = ContentAction::Create( profile(), extension(), - *ParseJson( + *ParseJsonDeprecated( "{\n" " \"instanceType\": \"declarativeContent.RequestContentScript\",\n" " \"js\": \"script.js\"\n" @@ -376,7 +381,7 @@ std::string error; std::unique_ptr<const ContentAction> result = ContentAction::Create( profile(), extension(), - *ParseJson( + *ParseJsonDeprecated( "{\n" " \"instanceType\": \"declarativeContent.RequestContentScript\",\n" " \"js\": [\"script.js\"],\n" @@ -392,7 +397,7 @@ std::string error; std::unique_ptr<const ContentAction> result = ContentAction::Create( profile(), extension(), - *ParseJson( + *ParseJsonDeprecated( "{\n" " \"instanceType\": \"declarativeContent.RequestContentScript\",\n" " \"js\": [\"script.js\"],\n" @@ -408,7 +413,7 @@ std::string error; std::unique_ptr<const ContentAction> result = ContentAction::Create( profile(), extension(), - *ParseJson( + *ParseJsonDeprecated( "{\n" " \"instanceType\": \"declarativeContent.RequestContentScript\",\n" " \"js\": [\"script.js\"],\n" @@ -423,7 +428,7 @@ std::string error; std::unique_ptr<const ContentAction> result = ContentAction::Create( profile(), extension(), - *ParseJson( + *ParseJsonDeprecated( "{\n" " \"instanceType\": \"declarativeContent.RequestContentScript\",\n" " \"js\": [\"script.js\"],\n"
diff --git a/chrome/browser/extensions/api/declarative_content/content_condition_unittest.cc b/chrome/browser/extensions/api/declarative_content/content_condition_unittest.cc index 758dc9f..a53f33a 100644 --- a/chrome/browser/extensions/api/declarative_content/content_condition_unittest.cc +++ b/chrome/browser/extensions/api/declarative_content/content_condition_unittest.cc
@@ -81,7 +81,7 @@ std::string error; std::unique_ptr<ContentCondition> condition = CreateContentCondition( nullptr, std::map<std::string, ContentPredicateFactory*>(), - *base::test::ParseJson( + *base::test::ParseJsonDeprecated( "{\n" " \"invalid\": \"foobar\",\n" " \"instanceType\": \"declarativeContent.PageStateMatcher\",\n" @@ -99,7 +99,7 @@ std::string error; std::unique_ptr<ContentCondition> condition = CreateContentCondition( nullptr, predicate_factories, - *base::test::ParseJson( + *base::test::ParseJsonDeprecated( "{\n" " \"test_predicate\": \"\",\n" " \"instanceType\": \"declarativeContent.PageStateMatcher\",\n" @@ -117,7 +117,7 @@ std::string error; std::unique_ptr<ContentCondition> condition = CreateContentCondition( nullptr, predicate_factories, - *base::test::ParseJson( + *base::test::ParseJsonDeprecated( "{\n" " \"test_predicate1\": {},\n" " \"test_predicate2\": [],\n"
diff --git a/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker_unittest.cc b/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker_unittest.cc index ae8d03c9..0f5446c1 100644 --- a/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker_unittest.cc +++ b/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker_unittest.cc
@@ -108,9 +108,7 @@ std::unique_ptr<const ContentPredicate>* predicate) { std::string error; *predicate = tracker_.CreatePredicate( - nullptr, - *base::test::ParseJson(value), - &error); + nullptr, *base::test::ParseJsonDeprecated(value), &error); EXPECT_EQ("", error); ASSERT_TRUE(*predicate); } @@ -122,7 +120,7 @@ std::string error; std::unique_ptr<DeclarativeContentCssPredicate> predicate = DeclarativeContentCssPredicate::Create( - nullptr, *base::test::ParseJson("\"selector\""), &error); + nullptr, *base::test::ParseJsonDeprecated("\"selector\""), &error); EXPECT_THAT(error, HasSubstr("invalid type")); EXPECT_FALSE(predicate); } @@ -131,7 +129,8 @@ std::string error; std::unique_ptr<DeclarativeContentCssPredicate> predicate = DeclarativeContentCssPredicate::Create( - nullptr, *base::test::ParseJson("[\"input\", \"a\"]"), &error); + nullptr, *base::test::ParseJsonDeprecated("[\"input\", \"a\"]"), + &error); EXPECT_EQ("", error); ASSERT_TRUE(predicate);
diff --git a/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker_unittest.cc b/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker_unittest.cc index 3b74e76..8c8917c2 100644 --- a/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker_unittest.cc +++ b/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker_unittest.cc
@@ -55,7 +55,8 @@ std::unique_ptr<DeclarativeContentIsBookmarkedPredicate> predicate = DeclarativeContentIsBookmarkedPredicate::Create( evaluator, extension, - *base::test::ParseJson(is_bookmarked ? "true" : "false"), &error); + *base::test::ParseJsonDeprecated(is_bookmarked ? "true" : "false"), + &error); EXPECT_EQ("", error); EXPECT_TRUE(predicate); EXPECT_EQ(is_bookmarked, predicate->is_bookmarked()); @@ -168,7 +169,8 @@ std::string error; std::unique_ptr<DeclarativeContentIsBookmarkedPredicate> predicate = DeclarativeContentIsBookmarkedPredicate::Create( - nullptr, extension.get(), *base::test::ParseJson("true"), &error); + nullptr, extension.get(), *base::test::ParseJsonDeprecated("true"), + &error); EXPECT_THAT(error, HasSubstr("requires 'bookmarks' permission")); EXPECT_FALSE(predicate); } @@ -181,7 +183,8 @@ std::string error; std::unique_ptr<DeclarativeContentIsBookmarkedPredicate> predicate = DeclarativeContentIsBookmarkedPredicate::Create( - nullptr, extension.get(), *base::test::ParseJson("[]"), &error); + nullptr, extension.get(), *base::test::ParseJsonDeprecated("[]"), + &error); EXPECT_THAT(error, HasSubstr("invalid type")); EXPECT_FALSE(predicate); }
diff --git a/chrome/browser/extensions/api/declarative_content/declarative_content_page_url_condition_tracker_unittest.cc b/chrome/browser/extensions/api/declarative_content/declarative_content_page_url_condition_tracker_unittest.cc index cea7cf1..075716ea 100644 --- a/chrome/browser/extensions/api/declarative_content/declarative_content_page_url_condition_tracker_unittest.cc +++ b/chrome/browser/extensions/api/declarative_content/declarative_content_page_url_condition_tracker_unittest.cc
@@ -80,9 +80,7 @@ std::unique_ptr<const ContentPredicate>* predicate) { std::string error; *predicate = tracker_.CreatePredicate( - nullptr, - *base::test::ParseJson(value), - &error); + nullptr, *base::test::ParseJsonDeprecated(value), &error); EXPECT_EQ("", error); ASSERT_TRUE(*predicate); } @@ -95,8 +93,8 @@ std::string error; std::unique_ptr<DeclarativeContentPageUrlPredicate> predicate = DeclarativeContentPageUrlPredicate::Create( - nullptr, matcher.condition_factory(), *base::test::ParseJson("[]"), - &error); + nullptr, matcher.condition_factory(), + *base::test::ParseJsonDeprecated("[]"), &error); EXPECT_THAT(error, HasSubstr("invalid type")); EXPECT_FALSE(predicate); @@ -109,7 +107,8 @@ std::unique_ptr<DeclarativeContentPageUrlPredicate> predicate = DeclarativeContentPageUrlPredicate::Create( nullptr, matcher.condition_factory(), - *base::test::ParseJson("{\"hostSuffix\": \"example.com\"}"), &error); + *base::test::ParseJsonDeprecated("{\"hostSuffix\": \"example.com\"}"), + &error); EXPECT_EQ("", error); ASSERT_TRUE(predicate);
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc index 7cd7aba..b82f4ee 100644 --- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc +++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc
@@ -51,7 +51,8 @@ const char kUnknownActionType[] = "unknownType"; std::unique_ptr<WebRequestActionSet> CreateSetOfActions(const char* json) { - std::unique_ptr<base::Value> parsed_value(base::test::ParseJson(json)); + std::unique_ptr<base::Value> parsed_value( + base::test::ParseJsonDeprecated(json)); const base::ListValue* parsed_list; CHECK(parsed_value->GetAsList(&parsed_list));
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc index c8f2b9b7d..4bb494b 100644 --- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc +++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc
@@ -206,7 +206,7 @@ json_description += attributes; json_description += "}"; - return base::test::ParseJson(json_description); + return base::test::ParseJsonDeprecated(json_description); } // Create a rule with the ID |rule_id| and with conditions created from the
diff --git a/chrome/browser/extensions/api/device_permissions_manager_unittest.cc b/chrome/browser/extensions/api/device_permissions_manager_unittest.cc index e81b634..1beb223 100644 --- a/chrome/browser/extensions/api/device_permissions_manager_unittest.cc +++ b/chrome/browser/extensions/api/device_permissions_manager_unittest.cc
@@ -55,16 +55,15 @@ void SetUp() override { testing::Test::SetUp(); env_.reset(new extensions::TestExtensionEnvironment()); - extension_ = - env_->MakeExtension(*base::test::ParseJson( - "{" - " \"app\": {" - " \"background\": {" - " \"scripts\": [\"background.js\"]" - " }" - " }," - " \"permissions\": [ \"hid\", \"usb\" ]" - "}")); + extension_ = env_->MakeExtension(*base::test::ParseJsonDeprecated( + "{" + " \"app\": {" + " \"background\": {" + " \"scripts\": [\"background.js\"]" + " }" + " }," + " \"permissions\": [ \"hid\", \"usb\" ]" + "}")); HidDeviceManager::GetFactoryInstance()->SetTestingFactory( env_->profile(), base::BindRepeating(&CreateHidDeviceManager)); @@ -337,7 +336,7 @@ } TEST_F(DevicePermissionsManagerTest, LoadPrefs) { - std::unique_ptr<base::Value> prefs_value = base::test::ParseJson( + std::unique_ptr<base::Value> prefs_value = base::test::ParseJsonDeprecated( "[" " {" " \"manufacturer_string\": \"Test Manufacturer\","
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc index f35c291..fa32e0d 100644 --- a/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc +++ b/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc
@@ -17,9 +17,9 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/common/extensions/api/passwords_private.h" -#include "components/browser_sync/profile_sync_service.h" #include "components/password_manager/core/browser/manage_passwords_referrer.h" #include "components/password_manager/core/browser/password_manager_util.h" +#include "components/sync/driver/sync_service.h" #include "content/public/browser/web_contents.h" #include "extensions/browser/extension_function_registry.h"
diff --git a/chrome/browser/extensions/bookmark_app_extension_util.cc b/chrome/browser/extensions/bookmark_app_extension_util.cc new file mode 100644 index 0000000..84418902 --- /dev/null +++ b/chrome/browser/extensions/bookmark_app_extension_util.cc
@@ -0,0 +1,74 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/bookmark_app_extension_util.h" + +#include "build/build_config.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/extensions/application_launch.h" +#include "chrome/browser/web_applications/extensions/web_app_extension_shortcut.h" +#include "chrome/common/chrome_features.h" +#include "chrome/common/chrome_switches.h" +#include "extensions/common/extension.h" + +#if defined(OS_MACOSX) +#include "chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.h" +#include "chrome/common/chrome_switches.h" +#endif + +#if defined(OS_CHROMEOS) +// gn check complains on Linux Ozone. +#include "ash/public/cpp/shelf_model.h" // nogncheck +#include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" +#endif + +namespace extensions { + +void BookmarkAppCreateOsShortcuts(Profile* profile, + const Extension* extension) { +#if !defined(OS_CHROMEOS) + web_app::ShortcutLocations creation_locations; +#if defined(OS_LINUX) || defined(OS_WIN) + creation_locations.on_desktop = true; +#else + creation_locations.on_desktop = false; +#endif + creation_locations.applications_menu_location = + web_app::APP_MENU_LOCATION_SUBDIR_CHROMEAPPS; + creation_locations.in_quick_launch_bar = false; + + Profile* current_profile = profile->GetOriginalProfile(); + web_app::CreateShortcuts(web_app::SHORTCUT_CREATION_BY_USER, + creation_locations, current_profile, extension); +#else + // ChromeLauncherController does not exist in unit tests. + if (ChromeLauncherController::instance()) { + ChromeLauncherController::instance()->shelf_model()->PinAppWithID( + extension->id()); + } +#endif // !defined(OS_CHROMEOS) +} + +void BookmarkAppReparentTab(Profile* profile, + content::WebContents* contents, + const Extension* extension, + LaunchType launch_type) { +#if defined(OS_MACOSX) + // TODO(https://crbug.com/915571): Reparent the tab on Mac just like the + // other platforms. + if (!base::CommandLine::ForCurrentProcess()->HasSwitch( + ::switches::kDisableHostedAppShimCreation)) { + Profile* current_profile = profile->GetOriginalProfile(); + web_app::RevealAppShimInFinderForApp(current_profile, extension); + } +#else + // Reparent the tab into an app window immediately when opening as a window. + if (base::FeatureList::IsEnabled(::features::kDesktopPWAWindowing) && + launch_type == LAUNCH_TYPE_WINDOW && !profile->IsOffTheRecord()) { + ReparentWebContentsIntoAppBrowser(contents, extension); + } +#endif // !defined(OS_MACOSX) +} + +} // namespace extensions
diff --git a/chrome/browser/extensions/bookmark_app_extension_util.h b/chrome/browser/extensions/bookmark_app_extension_util.h new file mode 100644 index 0000000..3d1e5f4 --- /dev/null +++ b/chrome/browser/extensions/bookmark_app_extension_util.h
@@ -0,0 +1,29 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_EXTENSIONS_BOOKMARK_APP_EXTENSION_UTIL_H_ +#define CHROME_BROWSER_EXTENSIONS_BOOKMARK_APP_EXTENSION_UTIL_H_ + +#include "extensions/common/constants.h" + +class Profile; + +namespace content { +class WebContents; +} + +namespace extensions { + +class Extension; + +void BookmarkAppCreateOsShortcuts(Profile* profile, const Extension* extension); + +void BookmarkAppReparentTab(Profile* profile, + content::WebContents* contents, + const Extension* extension, + LaunchType launch_type); + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_BOOKMARK_APP_EXTENSION_UTIL_H_
diff --git a/chrome/browser/extensions/bookmark_app_helper.cc b/chrome/browser/extensions/bookmark_app_helper.cc index 03bccc3..853efea 100644 --- a/chrome/browser/extensions/bookmark_app_helper.cc +++ b/chrome/browser/extensions/bookmark_app_helper.cc
@@ -16,12 +16,10 @@ #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "build/build_config.h" -#include "chrome/browser/banners/app_banner_manager.h" -#include "chrome/browser/banners/app_banner_manager_desktop.h" -#include "chrome/browser/banners/app_banner_settings_helper.h" #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h" #include "chrome/browser/bitmap_fetcher/bitmap_fetcher_delegate.h" #include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/extensions/bookmark_app_extension_util.h" #include "chrome/browser/extensions/convert_web_app.h" #include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/extensions/extension_service.h" @@ -36,11 +34,9 @@ #include "chrome/browser/ui/browser_dialogs.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_window.h" -#include "chrome/browser/ui/extensions/application_launch.h" #include "chrome/browser/web_applications/components/web_app_icon_downloader.h" #include "chrome/browser/web_applications/components/web_app_install_utils.h" #include "chrome/browser/web_applications/extensions/bookmark_app_util.h" -#include "chrome/browser/web_applications/extensions/web_app_extension_shortcut.h" #include "chrome/browser/webshare/share_target_pref_helper.h" #include "chrome/common/chrome_features.h" #include "chrome/common/extensions/api/url_handlers/url_handlers_parser.h" @@ -63,17 +59,6 @@ #include "third_party/blink/public/common/manifest/manifest.h" #include "third_party/skia/include/core/SkBitmap.h" -#if defined(OS_MACOSX) -#include "chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.h" -#include "chrome/common/chrome_switches.h" -#endif - -#if defined(OS_CHROMEOS) -// gn check complains on Linux Ozone. -#include "ash/public/cpp/shelf_model.h" // nogncheck -#include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" -#endif - namespace extensions { namespace { @@ -483,62 +468,19 @@ return; } - // Record an app banner added to homescreen event to ensure banners are not - // shown for this app. - AppBannerSettingsHelper::RecordBannerEvent( - contents_, web_app_info_.app_url, web_app_info_.app_url.spec(), - AppBannerSettingsHelper::APP_BANNER_EVENT_DID_ADD_TO_HOMESCREEN, - base::Time::Now()); + web_app::RecordAppBanner(contents_, web_app_info_.app_url); -#if !defined(OS_CHROMEOS) - // Pin the app to the relevant launcher depending on the OS. - Profile* current_profile = profile_->GetOriginalProfile(); -#endif // !defined(OS_CHROMEOS) + if (create_shortcuts_) + BookmarkAppCreateOsShortcuts(profile_, extension); - // If there is no browser, it means that the app is being installed in the - // background. We skip some steps in this case. - const bool silent_install = - (chrome::FindBrowserWithWebContents(contents_) == nullptr); - - if (create_shortcuts_) { -#if !defined(OS_CHROMEOS) - web_app::ShortcutLocations creation_locations; -#if defined(OS_LINUX) || defined(OS_WIN) - creation_locations.on_desktop = true; -#else - creation_locations.on_desktop = false; -#endif - creation_locations.applications_menu_location = - web_app::APP_MENU_LOCATION_SUBDIR_CHROMEAPPS; - creation_locations.in_quick_launch_bar = false; - - web_app::CreateShortcuts(web_app::SHORTCUT_CREATION_BY_USER, - creation_locations, current_profile, extension); -#else - // ChromeLauncherController does not exist in unit tests. - if (ChromeLauncherController::instance()) { - ChromeLauncherController::instance()->shelf_model()->PinAppWithID( - extension->id()); - } -#endif // !defined(OS_CHROMEOS) - } - - if (!silent_install) { -#if defined(OS_MACOSX) - // TODO(https://crbug.com/915571): Reparent the tab on Mac just like the - // other platforms. - if (!base::CommandLine::ForCurrentProcess()->HasSwitch( - ::switches::kDisableHostedAppShimCreation)) { - web_app::RevealAppShimInFinderForApp(current_profile, extension); - } -#else - // Reparent the tab into an app window immediately when opening as a window. - if (base::FeatureList::IsEnabled(::features::kDesktopPWAWindowing) && - launch_type == LAUNCH_TYPE_WINDOW && !profile_->IsOffTheRecord()) { - ReparentWebContentsIntoAppBrowser(contents_, extension); - } -#endif // !defined(OS_MACOSX) - } + // If there is a browser, it means that the app is being installed in the + // foreground: window reparenting needed. + const bool reparent_tab = + (chrome::FindBrowserWithWebContents(contents_) != nullptr); + // TODO(loyso): Reparenting must be implemented in + // chrome/browser/ui/web_applications/ UI layer as a post-install step. + if (reparent_tab) + BookmarkAppReparentTab(profile_, contents_, extension, launch_type); callback_.Run(extension, web_app_info_); }
diff --git a/chrome/browser/extensions/chrome_extensions_interface_registration.cc b/chrome/browser/extensions/chrome_extensions_interface_registration.cc index f5742714..a1dd82b 100644 --- a/chrome/browser/extensions/chrome_extensions_interface_registration.cc +++ b/chrome/browser/extensions/chrome_extensions_interface_registration.cc
@@ -9,6 +9,7 @@ #include "base/logging.h" #include "chrome/browser/media/router/media_router_feature.h" // nogncheck #include "chrome/browser/media/router/mojo/media_router_desktop.h" // nogncheck +#include "chrome/common/extensions/extension_constants.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "extensions/common/extension.h" @@ -24,7 +25,9 @@ #include "content/public/common/service_manager_connection.h" #include "extensions/browser/api/extensions_api_client.h" #include "extensions/browser/api/media_perception_private/media_perception_api_delegate.h" +#include "media/capture/video/chromeos/mojo/cros_image_capture.mojom.h" #include "services/service_manager/public/cpp/connector.h" +#include "services/video_capture/public/mojom/constants.mojom.h" #endif namespace extensions { @@ -87,6 +90,11 @@ base::Unretained(delegate))); } } + if (extension->id().compare(extension_misc::kChromeCameraAppId) == 0) { + registry->AddInterface( + base::BindRepeating(&ForwardRequest<cros::mojom::CrosImageCapture>, + video_capture::mojom::kServiceName)); + } #endif }
diff --git a/chrome/browser/extensions/extension_protocols_unittest.cc b/chrome/browser/extensions/extension_protocols_unittest.cc index b860393..708c8f0b5 100644 --- a/chrome/browser/extensions/extension_protocols_unittest.cc +++ b/chrome/browser/extensions/extension_protocols_unittest.cc
@@ -768,7 +768,7 @@ })"; test_dir.WriteManifest(kManifest); std::unique_ptr<base::DictionaryValue> manifest = - base::DictionaryValue::From(base::test::ParseJson(kManifest)); + base::DictionaryValue::From(base::test::ParseJsonDeprecated(kManifest)); ASSERT_TRUE(manifest); test_dir.WriteFile(FILE_PATH_LITERAL("json_file.json"), "{}");
diff --git a/chrome/browser/extensions/extension_service_sync_unittest.cc b/chrome/browser/extensions/extension_service_sync_unittest.cc index 20b7147..3b27aa2b 100644 --- a/chrome/browser/extensions/extension_service_sync_unittest.cc +++ b/chrome/browser/extensions/extension_service_sync_unittest.cc
@@ -37,12 +37,14 @@ #include "chrome/common/extensions/extension_test_util.h" #include "chrome/common/extensions/sync_helper.h" #include "chrome/test/base/testing_profile.h" -#include "components/browser_sync/profile_sync_service.h" #include "components/crx_file/id_util.h" +#include "components/sync/driver/sync_service.h" +#include "components/sync/driver/sync_user_settings.h" #include "components/sync/model/fake_sync_change_processor.h" #include "components/sync/model/sync_change_processor_wrapper_for_test.h" #include "components/sync/model/sync_data.h" #include "components/sync/model/sync_error_factory_mock.h" +#include "components/sync/protocol/sync.pb.h" #include "components/variations/variations_associated_data.h" #include "extensions/browser/api_test_utils.h" #include "extensions/browser/app_sorting.h"
diff --git a/chrome/browser/extensions/permission_message_combinations_unittest.cc b/chrome/browser/extensions/permission_message_combinations_unittest.cc index 3d87493..5ebe1e2e 100644 --- a/chrome/browser/extensions/permission_message_combinations_unittest.cc +++ b/chrome/browser/extensions/permission_message_combinations_unittest.cc
@@ -44,7 +44,7 @@ std::replace(json_manifest_with_double_quotes.begin(), json_manifest_with_double_quotes.end(), '\'', '"'); app_ = env_.MakeExtension( - *base::test::ParseJson(json_manifest_with_double_quotes), + *base::test::ParseJsonDeprecated(json_manifest_with_double_quotes), kAllowlistedExtensionID); }
diff --git a/chrome/browser/extensions/updater/update_service_browsertest.cc b/chrome/browser/extensions/updater/update_service_browsertest.cc index 1b080db..a5755d4 100644 --- a/chrome/browser/extensions/updater/update_service_browsertest.cc +++ b/chrome/browser/extensions/updater/update_service_browsertest.cc
@@ -117,7 +117,8 @@ const std::string update_request = std::get<0>(update_interceptor_->GetRequests()[0]); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(update_request); + const auto root = base::JSONReader::Read(update_request); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(kExtensionId, app.FindKey("appid")->GetString()); EXPECT_EQ("0.10", app.FindKey("version")->GetString()); @@ -189,7 +190,8 @@ const std::string update_request = std::get<0>(update_interceptor_->GetRequests()[0]); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(update_request); + const auto root = base::JSONReader::Read(update_request); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(kExtensionId, app.FindKey("appid")->GetString()); EXPECT_EQ("0.10", app.FindKey("version")->GetString()); @@ -352,7 +354,8 @@ const std::string update_request = std::get<0>(update_interceptor_->GetRequests()[0]); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(update_request); + const auto root = base::JSONReader::Read(update_request); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(kExtensionId, app.FindKey("appid")->GetString()); EXPECT_EQ("0.10", app.FindKey("version")->GetString()); @@ -457,7 +460,8 @@ const std::string update_request = std::get<0>(update_interceptor_->GetRequests()[0]); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(update_request); + const auto root = base::JSONReader::Read(update_request); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(kExtensionId, app.FindKey("appid")->GetString()); EXPECT_EQ("0.0.0.0", app.FindKey("version")->GetString()); @@ -703,7 +707,8 @@ const std::string update_request = std::get<0>(update_interceptor_->GetRequests()[0]); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(update_request); + const auto root = base::JSONReader::Read(update_request); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(id_, app.FindKey("appid")->GetString()); EXPECT_EQ("0.0.0.0", app.FindKey("version")->GetString()); @@ -834,7 +839,8 @@ const std::string update_request = std::get<0>(update_interceptor_->GetRequests()[0]); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(update_request); + const auto root = base::JSONReader::Read(update_request); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(id_, app.FindKey("appid")->GetString()); EXPECT_EQ("0.0.0.0", app.FindKey("version")->GetString());
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index a3cbe93..9ce56ff 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -2286,6 +2286,11 @@ "expiry_milestone": 76 }, { + "name": "manual-password-generation-android", + "owners": [ "ioanap" ], + "expiry_milestone": 76 + }, + { "name": "mash", "owners": [ "mustash-team@google.com" ], "expiry_milestone": 79
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index ce91e0f..8550012 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -2449,14 +2449,20 @@ "Whether to use the Google Play Services Location Settings Dialog " "permission dialog."; -const char kModalPermissionDialogViewName[] = "Modal Permission Dialog"; -const char kModalPermissionDialogViewDescription[] = - "Enable this option to use ModalDialogManager for permission Dialogs."; +const char kManualPasswordGenerationAndroidName[] = + "Manual password generation"; +const char kManualPasswordGenerationAndroidDescription[] = + "Whether Chrome should offer users the option to manually request to " + "generate passwords on Android."; const char kMediaScreenCaptureName[] = "Experimental ScreenCapture."; const char kMediaScreenCaptureDescription[] = "Enable this option for experimental ScreenCapture feature on Android."; +const char kModalPermissionDialogViewName[] = "Modal Permission Dialog"; +const char kModalPermissionDialogViewDescription[] = + "Enable this option to use ModalDialogManager for permission Dialogs."; + const char kModalPermissionPromptsName[] = "Modal Permission Prompts"; const char kModalPermissionPromptsDescription[] = "Whether to use permission dialogs in place of permission infobars.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 87806e9..7f0f2aef 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1449,12 +1449,15 @@ extern const char kLsdPermissionPromptName[]; extern const char kLsdPermissionPromptDescription[]; -extern const char kModalPermissionDialogViewName[]; -extern const char kModalPermissionDialogViewDescription[]; +extern const char kManualPasswordGenerationAndroidName[]; +extern const char kManualPasswordGenerationAndroidDescription[]; extern const char kMediaScreenCaptureName[]; extern const char kMediaScreenCaptureDescription[]; +extern const char kModalPermissionDialogViewName[]; +extern const char kModalPermissionDialogViewDescription[]; + extern const char kModalPermissionPromptsName[]; extern const char kModalPermissionPromptsDescription[];
diff --git a/chrome/browser/media/router/providers/cast/cast_activity_manager_unittest.cc b/chrome/browser/media/router/providers/cast/cast_activity_manager_unittest.cc index 88a59958..d5ca539 100644 --- a/chrome/browser/media/router/providers/cast/cast_activity_manager_unittest.cc +++ b/chrome/browser/media/router/providers/cast/cast_activity_manager_unittest.cc
@@ -26,7 +26,7 @@ #include "testing/gtest/include/gtest/gtest.h" using base::test::IsJson; -using base::test::ParseJson; +using base::test::ParseJsonDeprecated; using testing::_; using testing::IsEmpty; using testing::Not; @@ -198,7 +198,7 @@ } cast_channel::LaunchSessionResponse GetSuccessLaunchResponse() { - auto receiver_status = ParseJson(kReceiverStatus); + auto receiver_status = ParseJsonDeprecated(kReceiverStatus); cast_channel::LaunchSessionResponse response; response.result = cast_channel::LaunchSessionResponse::Result::kOk; response.receiver_status = std::move(*receiver_status); @@ -404,7 +404,8 @@ } TEST_F(CastActivityManagerTest, AddRemoveNonLocalActivity) { - auto session = CastSession::From(sink_, *ParseJson(kReceiverStatus)); + auto session = + CastSession::From(sink_, *ParseJsonDeprecated(kReceiverStatus)); ASSERT_TRUE(session); MediaRoute route; @@ -422,7 +423,8 @@ LaunchSession(); LaunchSessionResponseSuccess(); - auto session = CastSession::From(sink_, *ParseJson(kReceiverStatus)); + auto session = + CastSession::From(sink_, *ParseJsonDeprecated(kReceiverStatus)); ASSERT_TRUE(session); MediaRoute route; @@ -438,7 +440,8 @@ TEST_F(CastActivityManagerTest, UpdateExistingSession) { // Create and add the session to be updated, and verify it was added. - auto session = CastSession::From(sink_, *ParseJson(kReceiverStatus)); + auto session = + CastSession::From(sink_, *ParseJsonDeprecated(kReceiverStatus)); ASSERT_TRUE(session); MediaRoute route; ExpectSingleRouteUpdate(&route); @@ -448,7 +451,8 @@ auto old_route_id = route.media_route_id(); // Description change should be reflect in route update. - auto updated_session = CastSession::From(sink_, *ParseJson(kReceiverStatus2)); + auto updated_session = + CastSession::From(sink_, *ParseJsonDeprecated(kReceiverStatus2)); ASSERT_TRUE(updated_session); ExpectSingleRouteUpdate(&route); @@ -462,7 +466,8 @@ TEST_F(CastActivityManagerTest, ReplaceExistingSession) { // Create and add the session to be replaced, and verify it was added. - auto session = CastSession::From(sink_, *ParseJson(kReceiverStatus)); + auto session = + CastSession::From(sink_, *ParseJsonDeprecated(kReceiverStatus)); ASSERT_TRUE(session); MediaRoute route; ExpectSingleRouteUpdate(&route); @@ -472,7 +477,8 @@ EXPECT_EQ(route.description(), session->GetRouteDescription()); // Different session. - auto new_session = CastSession::From(sink_, *ParseJson(kReceiverStatus3)); + auto new_session = + CastSession::From(sink_, *ParseJsonDeprecated(kReceiverStatus3)); ASSERT_TRUE(new_session); ExpectSingleRouteUpdate(&route); @@ -590,7 +596,8 @@ "timeoutMillis": 0, "type": "v2_message" })"))); - manager_->OnMediaStatusUpdated(sink_, *ParseJson(R"({"foo": "bar"})"), 345); + manager_->OnMediaStatusUpdated( + sink_, *ParseJsonDeprecated(R"({"foo": "bar"})"), 345); } TEST_F(CastActivityManagerTest, OnMediaStatusUpdatedWithPendingRequest) { @@ -619,7 +626,8 @@ "timeoutMillis": 0, "type": "v2_message" })"))); - manager_->OnMediaStatusUpdated(sink_, *ParseJson(R"({"foo": "bar"})"), 345); + manager_->OnMediaStatusUpdated( + sink_, *ParseJsonDeprecated(R"({"foo": "bar"})"), 345); } TEST_F(CastActivityManagerTest, SendVolumeCommandToReceiver) {
diff --git a/chrome/browser/media/router/providers/cast/cast_internal_message_util_unittest.cc b/chrome/browser/media/router/providers/cast/cast_internal_message_util_unittest.cc index 5b7c6c5..3f1dffa 100644 --- a/chrome/browser/media/router/providers/cast/cast_internal_message_util_unittest.cc +++ b/chrome/browser/media/router/providers/cast/cast_internal_message_util_unittest.cc
@@ -40,14 +40,14 @@ void ExpectNoCastSession(const MediaSinkInternal& sink, const std::string& receiver_status_str, const std::string& reason) { - auto session = CastSession::From(sink, *ParseJson(receiver_status_str)); + auto session = CastSession::From(sink, ParseJson(receiver_status_str)); EXPECT_FALSE(session) << "Shouldn't have created session because of " << reason; } void ExpectInvalidCastInternalMessage(const std::string& message_str, const std::string& invalid_reason) { - EXPECT_FALSE(CastInternalMessage::From(std::move(*ParseJson(message_str)))) + EXPECT_FALSE(CastInternalMessage::From(ParseJson(message_str))) << "message expected to be invlaid: " << invalid_reason; } @@ -73,7 +73,7 @@ } })"; - auto message = CastInternalMessage::From(std::move(*ParseJson(message_str))); + auto message = CastInternalMessage::From(ParseJson(message_str)); ASSERT_TRUE(message); EXPECT_EQ(CastInternalMessage::Type::kAppMessage, message->type); EXPECT_EQ("12345", message->client_id); @@ -101,7 +101,7 @@ } })"; - auto message = CastInternalMessage::From(std::move(*ParseJson(message_str))); + auto message = CastInternalMessage::From(ParseJson(message_str)); ASSERT_TRUE(message); EXPECT_EQ(CastInternalMessage::Type::kV2Message, message->type); EXPECT_EQ("12345", message->client_id); @@ -113,7 +113,7 @@ "sessionId": "sessionId", "foo": "bar" })"); - EXPECT_EQ(*v2_body, message->v2_message_body()); + EXPECT_EQ(v2_body, message->v2_message_body()); EXPECT_DCHECK_DEATH(message->app_message_namespace()); EXPECT_DCHECK_DEATH(message->app_message_body()); @@ -127,7 +127,7 @@ "message": {} })"; - auto message = CastInternalMessage::From(std::move(*ParseJson(message_str))); + auto message = CastInternalMessage::From(ParseJson(message_str)); ASSERT_TRUE(message); EXPECT_EQ(CastInternalMessage::Type::kClientConnect, message->type); EXPECT_EQ("12345", message->client_id); @@ -211,7 +211,7 @@ "transportId":"transportId" }] })"; - auto session = CastSession::From(sink, *ParseJson(receiver_status_str)); + auto session = CastSession::From(sink, ParseJson(receiver_status_str)); ASSERT_TRUE(session); EXPECT_EQ("sessionId", session->session_id()); EXPECT_EQ("ABCDEFGH", session->app_id());
diff --git a/chrome/browser/media/router/providers/cast/cast_session_tracker_unittest.cc b/chrome/browser/media/router/providers/cast/cast_session_tracker_unittest.cc index 9e4494a..96d5f16 100644 --- a/chrome/browser/media/router/providers/cast/cast_session_tracker_unittest.cc +++ b/chrome/browser/media/router/providers/cast/cast_session_tracker_unittest.cc
@@ -15,7 +15,7 @@ #include "testing/gtest/include/gtest/gtest.h" using base::test::IsJson; -using base::test::ParseJson; +using base::test::ParseJsonDeprecated; using testing::_; using testing::ByRef; using testing::Eq; @@ -99,7 +99,7 @@ sink_.cast_data().cast_channel_id, cast_channel::InternalMessage( cast_channel::CastMessageType::kReceiverStatus, - std::move(*ParseJson(kReceiverStatus)))); + std::move(*ParseJsonDeprecated(kReceiverStatus)))); session_ = session_tracker_.GetSessions().begin()->second.get(); ASSERT_TRUE(session_); @@ -145,7 +145,7 @@ sink_.cast_data().cast_channel_id, cast_channel::InternalMessage( cast_channel::CastMessageType::kReceiverStatus, - std::move(*ParseJson(kIdleReceiverStatus)))); + std::move(*ParseJsonDeprecated(kIdleReceiverStatus)))); } TEST_F(CastSessionTrackerTest, GetSessions) { @@ -192,7 +192,7 @@ session_tracker_.OnInternalMessage( sink_.cast_data().cast_channel_id, cast_channel::InternalMessage(cast_channel::CastMessageType::kMediaStatus, - std::move(*ParseJson(R"({ + std::move(*ParseJsonDeprecated(R"({ "status": [{ "playerState": "anything but IDLE", "supportedMediaRequests": 0, @@ -247,7 +247,7 @@ session_tracker_.OnInternalMessage( sink_.cast_data().cast_channel_id, cast_channel::InternalMessage(cast_channel::CastMessageType::kMediaStatus, - std::move(*ParseJson(R"({ + std::move(*ParseJsonDeprecated(R"({ "requestId": 12345, "status": [{ "playerState": "anything but IDLE", @@ -278,7 +278,7 @@ session_tracker_.OnInternalMessage( sink_.cast_data().cast_channel_id, cast_channel::InternalMessage(cast_channel::CastMessageType::kMediaStatus, - std::move(*ParseJson(R"({ + std::move(*ParseJsonDeprecated(R"({ "status": [{ "media": "theMedia", "mediaSessionId": 345, @@ -324,7 +324,7 @@ session_tracker_.OnInternalMessage( sink_.cast_data().cast_channel_id, cast_channel::InternalMessage(cast_channel::CastMessageType::kMediaStatus, - std::move(*ParseJson(R"({ + std::move(*ParseJsonDeprecated(R"({ "status": [{ "mediaSessionId": 345, "playerState": "anything but IDLE",
diff --git a/chrome/browser/net/reporting_browsertest.cc b/chrome/browser/net/reporting_browsertest.cc index 1575744..d672a4d 100644 --- a/chrome/browser/net/reporting_browsertest.cc +++ b/chrome/browser/net/reporting_browsertest.cc
@@ -116,7 +116,7 @@ } std::unique_ptr<base::Value> ParseReportUpload(const std::string& payload) { - auto parsed_payload = base::test::ParseJson(payload); + auto parsed_payload = base::test::ParseJsonDeprecated(payload); // Clear out any non-reproducible fields. for (auto& report : parsed_payload->GetList()) { report.RemoveKey("age"); @@ -151,7 +151,7 @@ // Verify the contents of the report that we received. EXPECT_TRUE(actual != nullptr); - auto expected = base::test::ParseJson(base::StringPrintf( + auto expected = base::test::ParseJsonDeprecated(base::StringPrintf( R"json( [ {
diff --git a/chrome/browser/password_manager/password_store_factory.cc b/chrome/browser/password_manager/password_store_factory.cc index 84f3b75f..cd1d05d4 100644 --- a/chrome/browser/password_manager/password_store_factory.cc +++ b/chrome/browser/password_manager/password_store_factory.cc
@@ -23,7 +23,6 @@ #include "chrome/browser/web_data_service_factory.h" #include "chrome/common/chrome_paths_internal.h" #include "chrome/common/chrome_switches.h" -#include "components/browser_sync/profile_sync_service.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/os_crypt/os_crypt_switches.h" #include "components/password_manager/core/browser/login_database.h" @@ -35,6 +34,7 @@ #include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" +#include "components/sync/driver/sync_service.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/network_service_instance.h" #include "content/public/browser/storage_partition.h" @@ -112,7 +112,7 @@ if (!password_store) return; syncer::SyncService* sync_service = - ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile); + ProfileSyncServiceFactory::GetForProfile(profile); password_manager::ToggleAffiliationBasedMatchingBasedOnPasswordSyncedState( password_store.get(), sync_service,
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 d723390..9e16482 100644 --- a/chrome/browser/password_manager/save_password_infobar_delegate_android.cc +++ b/chrome/browser/password_manager/save_password_infobar_delegate_android.cc
@@ -15,11 +15,11 @@ #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" #include "components/infobars/core/infobar_manager.h" #include "components/password_manager/core/browser/password_bubble_experiment.h" #include "components/password_manager/core/browser/password_form_metrics_recorder.h" +#include "components/sync/driver/sync_service.h" #include "content/public/browser/web_contents.h" #include "ui/base/l10n/l10n_util.h" #include "url/origin.h"
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 b7bf90a..95ef3c3 100644 --- a/chrome/browser/password_manager/update_password_infobar_delegate_android.cc +++ b/chrome/browser/password_manager/update_password_infobar_delegate_android.cc
@@ -14,11 +14,11 @@ #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" #include "components/password_manager/core/browser/password_bubble_experiment.h" #include "components/password_manager/core/browser/password_form_metrics_recorder.h" #include "components/strings/grit/components_strings.h" +#include "components/sync/driver/sync_service.h" #include "content/public/browser/web_contents.h" #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/previews/previews_browsertest.cc b/chrome/browser/previews/previews_browsertest.cc index f876c11..84c2546dc0 100644 --- a/chrome/browser/previews/previews_browsertest.cc +++ b/chrome/browser/previews/previews_browsertest.cc
@@ -522,7 +522,7 @@ }; std::unique_ptr<base::Value> ParseReportUpload(const std::string& payload) { - auto parsed_payload = base::test::ParseJson(payload); + auto parsed_payload = base::test::ParseJsonDeprecated(payload); // Clear out any non-reproducible fields. for (auto& report : parsed_payload->GetList()) { report.RemoveKey("age"); @@ -560,7 +560,7 @@ // Verify the contents of the report that we received. EXPECT_TRUE(actual != nullptr); - auto expected = base::test::ParseJson(base::StringPrintf( + auto expected = base::test::ParseJsonDeprecated(base::StringPrintf( R"text( [ {
diff --git a/chrome/browser/resources/chromeos/switch_access/menu_panel.html b/chrome/browser/resources/chromeos/switch_access/menu_panel.html index 987e907..7c17135 100644 --- a/chrome/browser/resources/chromeos/switch_access/menu_panel.html +++ b/chrome/browser/resources/chromeos/switch_access/menu_panel.html
@@ -7,7 +7,6 @@ <meta charset="utf-8"> <title>Switch Access Menu</title> <script type="text/javascript" src="closure/base.js"></script> - <script type="text/javascript" src="message_handler.js"></script> <script type="text/javascript" src="menu_panel.js"></script> <link rel="stylesheet" href="menu_panel.css"> </head>
diff --git a/chrome/browser/resources/chromeos/switch_access/menu_panel.js b/chrome/browser/resources/chromeos/switch_access/menu_panel.js index e23777e..cfca914 100644 --- a/chrome/browser/resources/chromeos/switch_access/menu_panel.js +++ b/chrome/browser/resources/chromeos/switch_access/menu_panel.js
@@ -45,10 +45,10 @@ * @private */ setupButton_(button) { - let id = button.id; - button.addEventListener('click', function() { - MessageHandler.sendMessage(MessageHandler.Destination.BACKGROUND, id); - }.bind(id)); + let action = button.id; + button.addEventListener('click', function(action) { + this.menuManager_.performAction(action); + }.bind(this, action)); } /**
diff --git a/chrome/browser/resources/pdf/BUILD.gn b/chrome/browser/resources/pdf/BUILD.gn index ac96b75..214f03a 100644 --- a/chrome/browser/resources/pdf/BUILD.gn +++ b/chrome/browser/resources/pdf/BUILD.gn
@@ -76,10 +76,15 @@ ] } +js_library("metrics") { + externs_list = [ "$externs_path/metrics_private.js" ] +} + js_type_check("pdf_resources") { deps = [ ":browser_api", ":gesture_detector", + ":metrics", ":open_pdf_params_parser", ":pdf_fitting_type", ":pdf_scripting_api",
diff --git a/chrome/browser/resources/pdf/elements/icons.html b/chrome/browser/resources/pdf/elements/icons.html index f71953e..a5976b1 100644 --- a/chrome/browser/resources/pdf/elements/icons.html +++ b/chrome/browser/resources/pdf/elements/icons.html
@@ -12,12 +12,14 @@ <g id="bookmark"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2-2-2z"></path></g> <g id="bookmark-border"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2-2-2zm0 15l-5-2.18L7 18V5h10v13z"></path></g> <g id="create"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"></path></g> - <g id="eraser"><path d="m15.543 4.9863c-0.32193 0.019835-0.65088 0.1626-0.91016 0.42188l-4.8867 4.8867 5.5332 5.5332h-2.1211l-4.4727-4.4727-0.65234 0.65234c-0.51854 0.51855-0.56773 1.319-0.10938 1.7773l4.166 4.166c0.45836 0.45836 1.2588 0.40917 1.7773-0.10938l6.5996-6.5996c0.51854-0.51855 0.56773-1.319 0.10938-1.7773l-4.166-4.166c-0.22918-0.22918-0.54525-0.33233-0.86719-0.3125zm-12.543 13.764v1.5h0.75 6 0.75v-1.5h-0.75-6-0.75z"></path></g> + <g id="eraser"><path d="M21.41,11.33 L13.04,20 L4.73,20 L2.58,17.86 C1.8,17.08 1.8,15.83 2.58,15.04 L13.62,3.58 C14.4,2.81 15.68,2.81 16.46,3.58 L21.41,8.51 C22.2,9.29 22.2,10.55 21.41,11.33 L21.41,11.33 Z"></path><polygon points="17.26 18 15.26 20 21.96 20 21.96 18"></polygon></g> <g id="fullscreen-exit"><path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"></path></g> - <g id="highlighter"><path d="M15.7498169,15.9885 L18.69405,19.7475 C18.75405,19.8165 18.79455,19.89975 18.8148,19.98825 C17.22405,20.30025 14.37105,20.25 12.0648,20.25 C9.72705,20.25 6.61248962,20.295 5.01423962,19.9755 C5.03523962,19.8915 5.07348962,19.8135 5.13123962,19.7475 L8.25498962,15.9885 L8.25498962,11.3135317 C8.25498962,11.2722817 8.26398962,11.2317817 8.28123962,11.1957817 L8.59698962,10.5297817 C8.59698962,10.5 15.4078169,10.49925 15.4078169,10.5 L15.7235669,11.1957817 C15.7400669,11.2317817 15.7498169,11.2722817 15.7498169,11.3135317 L15.7498169,15.9885"></path><path d="M13.846962,4.03912354 L14.04,4.09664481 C14.163,4.13093052 14.25,4.25693052 14.25,4.40178767 L14.25,5.43243216 L14.25,5.7872893 L14.25,8.82657296 C13.6995,8.91057296 12.79575,9 12,9 C11.20275,9 10.3005,8.91057296 9.75,8.82571582 L9.75,4.41586073 L9.75,3.85871787 L9.75,3.3152893 C9.75,3.11043216 9.91725,2.96043216 10.09125,3.0092893 L13.846962,4.03912354 Z" style="fill: var(--pen-tip-fill)"></g> - <g id="marker"><path d="M14.25,8.91853902 L14.25,6.53925711 C14.25,5.97869512 14.1161242,5.42520919 13.8582163,4.92039274 L12.7090497,2.67089612 C12.4225948,2.10981636 11.5774052,2.10964378 11.2909503,2.67072353 C10.911176,3.41422755 10.4575732,4.30184157 10.1413899,4.92108308 C9.88348208,5.42589953 9.75,5.97869512 9.75,6.53925711 L9.75,8.91940195 C10.4758827,8.97169576 11.2816971,9 11.9916328,9 C12.7058997,9 13.5195892,8.97152317 14.25,8.91853902" style="fill: var(--pen-tip-fill)"></path><path d="M15.7498169,15.9885 L15.7498169,11.3135317 C15.7498169,11.2722817 15.7400669,11.2317817 15.7235669,11.1957817 L15.4078169,10.5 C15.4078169,10.49925 8.59698962,10.5 8.59698962,10.5297817 L8.28123962,11.1957817 C8.26398962,11.2317817 8.25498962,11.2722817 8.25498962,11.3135317 L8.25498962,15.9885 L5.13123962,19.7475 C5.07348962,19.8135 5.03523962,19.8915 5.01423962,19.9755 C6.61248962,20.295 9.72705,20.25 12.0648,20.25 C14.37105,20.25 17.22405,20.30025 18.8148,19.98825 C18.79455,19.89975 18.75405,19.8165 18.69405,19.7475 L15.7498169,15.9885 Z"></path></g> + <g id="highlighter"><path d="M10.22,9.49 L4.31,15.49 C3.54,16.29 3.61,17.54 4.39,18.34 L0.77,22 L6.45,22 L7.19,21.25 C7.97,22.06 9.14,22.11 9.92,21.3 L15.88,15.25 L10.22,9.49 L10.22,9.49 Z"></path><path style="fill: var(--pen-tip-fill)" d="M22.68,5.49 L19.86,2.62 C19.08,1.82 17.79,1.78 17.02,2.58 L11.27,8.43 L16.93,14.18 L22.62,8.4 C23.39,7.59 23.45,6.29 22.68,5.49 L22.68,5.49 Z"></path><path style="fill: var(--pen-tip-border)" d="M18.4,3c0.3,0,0.5,0.1,0.7,0.3L22,6.2c0.4,0.4,0.4,1.1-0.1,1.5l-5,5.1l-4.3-4.3l5.1-5.2 C17.9,3.1,18.1,3,18.4,3 M18.4,2c-0.5,0-1,0.2-1.4,0.6l-5.8,5.9l5.7,5.8l5.7-5.8c0.8-0.8,0.8-2.1,0.1-2.9l-2.8-2.9 C19.5,2.2,18.9,2,18.4,2L18.4,2z"></path></g> + <g id="marker"><polygon points="3 17.25 3 21 6.74 21 14.28 13.47 10.53 9.72"></polygon><path style="fill: var(--pen-tip-fill)" d="M18.37,3.3 L20.71,5.63 C21.1,6.02 21.11,6.66 20.72,7.05 L15.35,12.41 L11.59,8.65 L14.12,6.12 L13.39,5.39 L7.73,11.05 L6.33,9.65 L12.7,3.29 C13.09,2.9 13.74,2.91 14.12,3.3 L15.54,4.71 L16.96,3.3 C17.34,2.91 17.98,2.91 18.37,3.3 L18.37,3.3 Z"></path><path style="fill: var(--pen-tip-border)" d="M17.7,4L20,6.3L15.4,11L13,8.6l1.8-1.8l0.7-0.7l-0.7-0.7l-0.2-0.2l0.2,0.2l0.7,0.7l0.7-0.7L17.7,4 M13.4,3 c-0.3,0-0.5,0.1-0.7,0.3L6.3,9.6l1.4,1.4l5.7-5.7l0.7,0.7l-2.5,2.5l3.8,3.8L20.7,7c0.4-0.4,0.4-1,0-1.4l-2.3-2.3 C18.2,3.1,17.9,3,17.7,3S17.2,3.1,17,3.3l-1.4,1.4l-1.4-1.4C13.9,3.1,13.7,3,13.4,3L13.4,3z"></path></g> + <g id="redo"><path d="M18.4 10.6C16.55 8.99 14.15 8 11.5 8c-4.65 0-8.58 3.03-9.96 7.22L3.9 16c1.05-3.19 4.05-5.5 7.6-5.5 1.95 0 3.73.72 5.12 1.88L13 16h9V7l-3.6 3.6z"></path></g> <g id="remove"><path d="M19 13H5v-2h14v2z"></path></g> <g id="rotate-right"><path d="M15.55 5.55L11 1v3.07C7.06 4.56 4 7.92 4 12s3.05 7.44 7 7.93v-2.02c-2.84-.48-5-2.94-5-5.91s2.16-5.43 5-5.91V10l4.55-4.45zM19.93 11c-.17-1.39-.72-2.73-1.62-3.89l-1.42 1.42c.54.75.88 1.6 1.02 2.47h2.02zM13 17.9v2.02c1.39-.17 2.74-.71 3.9-1.61l-1.44-1.44c-.75.54-1.59.89-2.46 1.03zm3.89-2.42l1.42 1.41c.9-1.16 1.45-2.5 1.62-3.89h-2.02c-.14.87-.48 1.72-1.02 2.48z"></path></g> + <g id="undo"><path d="M12.5 8c-2.65 0-5.05.99-6.9 2.6L2 7v9h9l-3.62-3.62c1.39-1.16 3.16-1.88 5.12-1.88 3.54 0 6.55 2.31 7.6 5.5l2.37-.78C21.08 11.03 17.15 8 12.5 8z"></path></g> </defs> </svg> </iron-iconset-svg>
diff --git a/chrome/browser/resources/pdf/elements/viewer-ink-host/BUILD.gn b/chrome/browser/resources/pdf/elements/viewer-ink-host/BUILD.gn index a2cb5af..32ca2b0 100644 --- a/chrome/browser/resources/pdf/elements/viewer-ink-host/BUILD.gn +++ b/chrome/browser/resources/pdf/elements/viewer-ink-host/BUILD.gn
@@ -12,6 +12,7 @@ js_library("viewer-ink-host") { deps = [ + "//chrome/browser/resources/pdf:metrics", "//chrome/browser/resources/pdf:viewport", "//chrome/browser/resources/pdf/ink:ink_api", ]
diff --git a/chrome/browser/resources/pdf/elements/viewer-ink-host/viewer-ink-host.js b/chrome/browser/resources/pdf/elements/viewer-ink-host/viewer-ink-host.js index d4e26340..d8002d4 100644 --- a/chrome/browser/resources/pdf/elements/viewer-ink-host/viewer-ink-host.js +++ b/chrome/browser/resources/pdf/elements/viewer-ink-host/viewer-ink-host.js
@@ -50,6 +50,9 @@ /** @type {Viewport} */ viewport: null, + /** @type {?AnnotationTool} */ + tool_: null, + /** * Whether we should suppress pointer events due to a gesture, * eg. pinch-zoom. @@ -168,6 +171,24 @@ this.activePointer_ = null; if (!this.pointerGesture_) { this.dispatchPointerEvent_(e); + // If the stroke was not cancelled, record metrics. + if (e.type == 'pointerup') { + if (e.pointerType == 'mouse') { + PDFMetrics.record(PDFMetrics.UserAction.ANNOTATE_STROKE_DEVICE_MOUSE); + } else if (e.pointerType == 'pen') { + PDFMetrics.record(PDFMetrics.UserAction.ANNOTATE_STROKE_DEVICE_PEN); + } else if (e.pointerType == 'touch') { + PDFMetrics.record(PDFMetrics.UserAction.ANNOTATE_STROKE_DEVICE_TOUCH); + } + if (this.tool_.tool == 'eraser') { + PDFMetrics.record(PDFMetrics.UserAction.ANNOTATE_STROKE_TOOL_ERASER); + } else if (this.tool_.tool == 'pen') { + PDFMetrics.record(PDFMetrics.UserAction.ANNOTATE_STROKE_TOOL_PEN); + } else if (this.tool_.tool == 'highlighter') { + PDFMetrics.record( + PDFMetrics.UserAction.ANNOTATE_STROKE_TOOL_HIGHLIGHTER); + } + } } this.pointerGesture_ = false; }, @@ -248,6 +269,16 @@ this.ink_.setCamera(camera); }, + /** Undo the last edit action. */ + undo() { + this.ink_.undo(); + }, + + /** Redo the last undone edit action. */ + redo() { + this.ink_.redo(); + }, + /** * @return {!Promise<{fileName: string, dataToSave: ArrayBuffer}>} * The serialized PDF document including any annotations that were made.
diff --git a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html index 1d0b87a..d8e6c6f 100644 --- a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html +++ b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html
@@ -103,7 +103,8 @@ #eraser:not([selected]), #pen:not([selected]), #highlighter:not([selected]) { - filter: contrast(30%); + --pen-tip-fill: currentcolor !important; + --pen-tip-border: currentcolor !important; } #pen, @@ -116,6 +117,13 @@ border-radius: 4px; } + #annotation-separator { + background: rgb(151, 152, 152); + height: 30px; + margin-inline-end: 12px; + width: 1px; + } + :host([annotation-mode]) #annotate { background-color: rgb(25, 27, 29); border-radius: 4px; @@ -208,14 +216,6 @@ </div> <div id="annotations-bar" class="invisible"> - <paper-icon-button id="eraser" - selected$="[[equal_('eraser', annotationTool.tool)]]" - on-click="annotationToolClicked_" - icon="pdf:eraser" - aria-label$="{{strings.annotationEraser}}" - title$="{{strings.annotationEraser}}"> - </paper-icon-button> - <viewer-toolbar-dropdown id="pen" selected$="[[equal_('pen', annotationTool.tool)]]" open-after-select @@ -253,6 +253,30 @@ on-selected-color-changed="annotationToolOptionChanged_"> </viewer-pen-options> </viewer-toolbar-dropdown> + + <paper-icon-button id="eraser" + selected$="[[equal_('eraser', annotationTool.tool)]]" + on-click="annotationToolClicked_" + icon="pdf:eraser" + aria-label$="{{strings.annotationEraser}}" + title$="{{strings.annotationEraser}}"> + </paper-icon-button> + + <div id="annotation-separator"></div> + + <paper-icon-button id="undo" + icon="pdf:undo" + on-click="undo" + aria-label$="{{strings.annotationUndo}}" + title$="{{strings.annotationUndo}}"> + </paper-icon-button> + + <paper-icon-button id="redo" + icon="pdf:redo" + on-click="redo" + aria-label$="{{strings.annotationRedo}}" + title$="{{strings.annotationRedo}}"> + </paper-icon-button> </div> </template> <script src="viewer-pdf-toolbar.js"></script>
diff --git a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.js b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.js index 5c61b3b8..3f3524ff 100644 --- a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.js +++ b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.js
@@ -163,6 +163,14 @@ this.fire('print'); }, + undo: function() { + this.fire('undo'); + }, + + redo: function() { + this.fire('redo'); + }, + toggleAnnotation: function() { this.annotationMode = !this.annotationMode; if (this.annotationMode) { @@ -193,6 +201,10 @@ selectedColor: null, }; element.attributeStyleMap.set('--pen-tip-fill', options.selectedColor); + element.attributeStyleMap.set( + '--pen-tip-border', + options.selectedColor == '#000000' ? 'currentcolor' : + options.selectedColor); this.annotationTool = { tool: tool, size: options.selectedSize,
diff --git a/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html b/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html index 9401afc..1568f0c 100644 --- a/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html +++ b/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html
@@ -55,7 +55,7 @@ } #arrow { - margin-inline-start: -12px; + margin-inline-start: -8px; padding-inline-end: 4px; }
diff --git a/chrome/browser/resources/pdf/ink/ink_api.js b/chrome/browser/resources/pdf/ink/ink_api.js index bec99a7..c530d57 100644 --- a/chrome/browser/resources/pdf/ink/ink_api.js +++ b/chrome/browser/resources/pdf/ink/ink_api.js
@@ -90,6 +90,14 @@ const event = new PointerEvent(type, init); document.querySelector('#ink-engine').dispatchEvent(event); } + + undo() { + this.embed_.undo(); + } + + redo() { + this.embed_.redo(); + } } /** @return {Promise<InkAPI>} */
diff --git a/chrome/browser/resources/pdf/metrics.js b/chrome/browser/resources/pdf/metrics.js index d965d30..d55c0d1 100644 --- a/chrome/browser/resources/pdf/metrics.js +++ b/chrome/browser/resources/pdf/metrics.js
@@ -57,7 +57,7 @@ } } -/** @private {Object} */ +/** @private {?chrome.metricsPrivate.MetricType} */ PDFMetrics.actionsMetric_ = null; /** @private {Set} */ @@ -80,24 +80,75 @@ * denominator to determine percentages of documents in which an action was * taken as well as average number of each action per document. */ - DOCUMENT_OPENED: 0, // Baseline to use as denominator for all formulas. - ROTATE_FIRST: 1, + DOCUMENT_OPENED: 0, + /** Recorded when the document is rotated clockwise or counter-clockwise. */ + ROTATE_FIRST: 1, ROTATE: 2, + FIT_TO_WIDTH_FIRST: 3, FIT_TO_WIDTH: 4, + FIT_TO_PAGE_FIRST: 5, FIT_TO_PAGE: 6, - OPEN_BOOKMARKS_PANEL_FIRST: 7, + /** Recorded when the bookmarks panel is opened. */ + OPEN_BOOKMARKS_PANEL_FIRST: 7, OPEN_BOOKMARKS_PANEL: 8, - FOLLOW_BOOKMARK_FIRST: 9, + /** Recorded when a bookmark is followed. */ + FOLLOW_BOOKMARK_FIRST: 9, FOLLOW_BOOKMARK: 10, - PAGE_SELECTOR_NAVIGATE_FIRST: 11, + /** Recorded when the page selection is used to navigate to another page. */ + PAGE_SELECTOR_NAVIGATE_FIRST: 11, PAGE_SELECTOR_NAVIGATE: 12, - NUMBER_OF_ACTIONS: 13 + + /** Recorded when the user triggers a save of the document. */ + SAVE_FIRST: 13, + SAVE: 14, + + /** + * Recorded when the user triggers a save of the document and the document + * has been modified by annotations. + */ + SAVE_WITH_ANNOTATION_FIRST: 15, + SAVE_WITH_ANNOTATION: 16, + + PRINT_FIRST: 17, + PRINT: 18, + + ENTER_ANNOTATION_MODE_FIRST: 19, + ENTER_ANNOTATION_MODE: 20, + + EXIT_ANNOTATION_MODE_FIRST: 21, + EXIT_ANNOTATION_MODE: 22, + + /** Recorded when a pen stroke is made. */ + ANNOTATE_STROKE_TOOL_PEN_FIRST: 23, + ANNOTATE_STROKE_TOOL_PEN: 24, + + /** Recorded when an eraser stroke is made. */ + ANNOTATE_STROKE_TOOL_ERASER_FIRST: 25, + ANNOTATE_STROKE_TOOL_ERASER: 26, + + /** Recorded when a highlighter stroke is made. */ + ANNOTATE_STROKE_TOOL_HIGHLIGHTER_FIRST: 27, + ANNOTATE_STROKE_TOOL_HIGHLIGHTER: 28, + + /** Recorded when a stroke is made using touch. */ + ANNOTATE_STROKE_DEVICE_TOUCH_FIRST: 29, + ANNOTATE_STROKE_DEVICE_TOUCH: 30, + + /** Recorded when a stroke is made using mouse. */ + ANNOTATE_STROKE_DEVICE_MOUSE_FIRST: 31, + ANNOTATE_STROKE_DEVICE_MOUSE: 32, + + /** Recorded when a stroke is made using pen. */ + ANNOTATE_STROKE_DEVICE_PEN_FIRST: 33, + ANNOTATE_STROKE_DEVICE_PEN: 34, + + NUMBER_OF_ACTIONS: 35, }; // Map from UserAction to the 'FIRST' action. These metrics are recorded @@ -128,4 +179,48 @@ PDFMetrics.UserAction.PAGE_SELECTOR_NAVIGATE, PDFMetrics.UserAction.PAGE_SELECTOR_NAVIGATE_FIRST, ], + [ + PDFMetrics.UserAction.SAVE, + PDFMetrics.UserAction.SAVE_FIRST, + ], + [ + PDFMetrics.UserAction.SAVE_WITH_ANNOTATION, + PDFMetrics.UserAction.SAVE_WITH_ANNOTATION_FIRST, + ], + [ + PDFMetrics.UserAction.PRINT, + PDFMetrics.UserAction.PRINT_FIRST, + ], + [ + PDFMetrics.UserAction.ENTER_ANNOTATION_MODE, + PDFMetrics.UserAction.ENTER_ANNOTATION_MODE_FIRST, + ], + [ + PDFMetrics.UserAction.EXIT_ANNOTATION_MODE, + PDFMetrics.UserAction.EXIT_ANNOTATION_MODE_FIRST, + ], + [ + PDFMetrics.UserAction.ANNOTATE_STROKE_TOOL_PEN, + PDFMetrics.UserAction.ANNOTATE_STROKE_TOOL_PEN_FIRST, + ], + [ + PDFMetrics.UserAction.ANNOTATE_STROKE_TOOL_ERASER, + PDFMetrics.UserAction.ANNOTATE_STROKE_TOOL_ERASER_FIRST, + ], + [ + PDFMetrics.UserAction.ANNOTATE_STROKE_TOOL_HIGHLIGHTER, + PDFMetrics.UserAction.ANNOTATE_STROKE_TOOL_HIGHLIGHTER_FIRST, + ], + [ + PDFMetrics.UserAction.ANNOTATE_STROKE_DEVICE_TOUCH, + PDFMetrics.UserAction.ANNOTATE_STROKE_DEVICE_TOUCH_FIRST, + ], + [ + PDFMetrics.UserAction.ANNOTATE_STROKE_DEVICE_MOUSE, + PDFMetrics.UserAction.ANNOTATE_STROKE_DEVICE_MOUSE_FIRST, + ], + [ + PDFMetrics.UserAction.ANNOTATE_STROKE_DEVICE_PEN, + PDFMetrics.UserAction.ANNOTATE_STROKE_DEVICE_PEN_FIRST, + ], ]);
diff --git a/chrome/browser/resources/pdf/pdf_viewer.js b/chrome/browser/resources/pdf/pdf_viewer.js index 0a4a071b..0208d63 100644 --- a/chrome/browser/resources/pdf/pdf_viewer.js +++ b/chrome/browser/resources/pdf/pdf_viewer.js
@@ -250,6 +250,10 @@ this.toolbar_.addEventListener('save', () => this.save()); this.toolbar_.addEventListener('print', () => this.print()); this.toolbar_.addEventListener( + 'undo', () => this.currentController_.undo()); + this.toolbar_.addEventListener( + 'redo', () => this.currentController_.redo()); + this.toolbar_.addEventListener( 'rotate-right', () => this.currentController_.rotateClockwise()); this.toolbar_.addEventListener( 'annotation-mode-changed', e => this.annotationModeChanged_(e)); @@ -499,9 +503,10 @@ annotationModeChanged_: async function(e) { const annotationMode = e.detail.value; if (annotationMode) { + // Enter annotation mode. + PDFMetrics.record(PDFMetrics.UserAction.ENTER_ANNOTATION_MODE); this.hasEnteredAnnotationMode_ = true; assert(this.currentController_ == this.pluginController_); - // Enter annotation mode. // TODO(dstockwell): set plugin read-only, begin transition this.updateProgress(0); // TODO(dstockwell): handle save failure @@ -515,6 +520,7 @@ this.updateProgress(100); } else { // Exit annotation mode. + PDFMetrics.record(PDFMetrics.UserAction.EXIT_ANNOTATION_MODE); assert(this.currentController_ == this.inkController_); // TODO(dstockwell): set ink read-only, begin transition this.updateProgress(0); @@ -1147,6 +1153,10 @@ * Saves the current PDF document to disk. */ save: async function() { + PDFMetrics.record(PDFMetrics.UserAction.SAVE); + if (this.hasEnteredAnnotationMode_) { + PDFMetrics.record(PDFMetrics.UserAction.SAVE_WITH_ANNOTATION); + } // If we have entered annotation mode we must require the local // contents to ensure annotations are saved. Otherwise we would // save the cached or remote copy without annotatios. @@ -1185,6 +1195,7 @@ }, print: async function() { + PDFMetrics.record(PDFMetrics.UserAction.PRINT); await this.exitAnnotationMode_(); this.currentController_.print(); } @@ -1227,6 +1238,16 @@ print() {} /** + * Undo an edit action. + */ + undo() {} + + /** + * Redo an edit action. + */ + redo() {} + + /** * Requests that the current document be saved. * @param {boolean} requireResult whether a response is required, otherwise * the controller may save the document to disk internally. @@ -1294,6 +1315,16 @@ } /** @override */ + undo() { + this.inkHost_.undo(); + } + + /** @override */ + redo() { + this.inkHost_.redo(); + } + + /** @override */ load(filename, data) { if (!this.inkHost_) { this.inkHost_ = document.createElement('viewer-ink-host');
diff --git a/chrome/browser/resources/print_preview/new/scaling_settings.html b/chrome/browser/resources/print_preview/new/scaling_settings.html index 58c12da..ca6a9ea 100644 --- a/chrome/browser/resources/print_preview/new/scaling_settings.html +++ b/chrome/browser/resources/print_preview/new/scaling_settings.html
@@ -15,8 +15,7 @@ <span slot="title" id="scaling-label">$i18n{scalingLabel}</span> <div slot="controls"> <select class="md-select" aria-labelledby="scaling-label" - disabled$="[[dropdownDisabled_(disabled, inputValid_)]]" - value="{{selectedValue::change}}"> + disabled$="[[dropdownDisabled_]]" value="{{selectedValue::change}}"> <option value="[[scalingValueEnum_.DEFAULT]]"> $i18n{optionDefaultScaling} </option> @@ -34,7 +33,7 @@ on-transitionend="onCollapseChanged_"> <print-preview-number-settings-section max-value="200" min-value="10" default-value="100" - disabled$="[[inputDisabled_(disabled, inputValid_, customSelected_)]]" + disabled$="[[inputDisabled_(dropdownDisabled_, customSelected_)]]" current-value="{{currentValue_}}" input-valid="{{inputValid_}}" hint-message="$i18n{scalingInstruction}"> </print-preview-number-settings-section>
diff --git a/chrome/browser/resources/print_preview/new/scaling_settings.js b/chrome/browser/resources/print_preview/new/scaling_settings.js index 4d2e396..ea05eef 100644 --- a/chrome/browser/resources/print_preview/new/scaling_settings.js +++ b/chrome/browser/resources/print_preview/new/scaling_settings.js
@@ -25,7 +25,10 @@ behaviors: [SettingsBehavior, print_preview_new.SelectBehavior], properties: { - disabled: Boolean, + disabled: { + type: Boolean, + observer: 'onDisabledChanged_', + }, /** @private {string} */ currentValue_: { @@ -42,6 +45,12 @@ /** @private {boolean} */ inputValid_: Boolean, + /** @private {boolean} */ + dropdownDisabled_: { + type: Boolean, + value: false, + }, + /** * Mirroring the enum so that it can be used from HTML bindings. * @private @@ -130,21 +139,16 @@ * @private */ onInputChanged_: function() { - if (this.currentValue_ !== '') { - this.setSettingValid('scaling', this.inputValid_); - } + this.setSettingValid('scaling', this.inputValid_); if (this.currentValue_ !== '' && this.inputValid_) { this.setSetting('scaling', this.currentValue_); } }, - /** - * @return {boolean} Whether the dropdown should be disabled. - * @private - */ - dropdownDisabled_: function() { - return this.disabled && this.inputValid_; + /** @private */ + onDisabledChanged_: function() { + this.dropdownDisabled_ = this.disabled && this.inputValid_; }, /** @@ -152,7 +156,7 @@ * @private */ inputDisabled_: function() { - return !this.customSelected_ || (this.disabled && this.inputValid_); + return !this.customSelected_ || this.dropdownDisabled_; }, /**
diff --git a/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js b/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js index e584065c..cb850b8 100644 --- a/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js +++ b/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js
@@ -210,6 +210,8 @@ this.unpairedDeviceList_, this.deviceList_.filter(d => !(d.paired || d.connecting))); + this.$.pairedDevices.fire('iron-resize'); + this.$.unpairedDevices.fire('iron-resize'); this.updateScrollableContents(); this.restoreScroll(this.$.unpairedDevices); this.restoreScroll(this.$.pairedDevices);
diff --git a/chrome/browser/resources/usb_internals/usb_internals.html b/chrome/browser/resources/usb_internals/usb_internals.html index 1c84c37..cc025f8d 100644 --- a/chrome/browser/resources/usb_internals/usb_internals.html +++ b/chrome/browser/resources/usb_internals/usb_internals.html
@@ -14,10 +14,13 @@ <script src="chrome://resources/js/cr/ui.js"></script> <script src="chrome://resources/js/cr/ui/focus_outline_manager.js"></script> <script src="chrome://resources/js/cr/ui/tabs.js"></script> - <script src="chrome://resources/js/mojo_bindings.js"></script> + <script src="chrome://resources/js/mojo_bindings_lite.js"></script> <script src="chrome://resources/js/util.js"></script> - <script src="device/usb/public/mojom/device_manager_test.mojom.js"></script> - <script src="chrome/browser/ui/webui/usb_internals/usb_internals.mojom.js"> + <script src="url/mojom/url.mojom-lite.js"></script> + <script src="device/usb/public/mojom/device_manager_test.mojom-lite.js"> + </script> + <script + src="chrome/browser/ui/webui/usb_internals/usb_internals.mojom-lite.js"> </script> </head>
diff --git a/chrome/browser/resources/usb_internals/usb_internals.js b/chrome/browser/resources/usb_internals/usb_internals.js index 67e63a8..0315f13 100644 --- a/chrome/browser/resources/usb_internals/usb_internals.js +++ b/chrome/browser/resources/usb_internals/usb_internals.js
@@ -12,13 +12,9 @@ // browser process. this.usbManagerTest = null; - const pageHandler = new mojom.UsbInternalsPageHandlerPtr; - Mojo.bindInterface( - mojom.UsbInternalsPageHandler.name, - mojo.makeRequest(pageHandler).handle); - - this.usbManagerTest = new device.mojom.UsbDeviceManagerTestPtr; - pageHandler.bindTestInterface(mojo.makeRequest(this.usbManagerTest)); + const pageHandler = mojom.UsbInternalsPageHandler.getProxy(); + this.usbManagerTest = new device.mojom.UsbDeviceManagerTestProxy; + pageHandler.bindTestInterface(this.usbManagerTest.createRequest()); cr.ui.decorate('tabbox', cr.ui.TabBox); $('add-test-device-form').addEventListener('submit', (event) => {
diff --git a/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc b/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc index f3ec5f8..e977bbd 100644 --- a/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc
@@ -56,6 +56,17 @@ const bool should_enable_uss = index == 0 ? std::get<0>(GetParam()) : std::get<1>(GetParam()); + // In order to avoid test flakiness, for any client other than the first, we + // need to make sure the feature toggle has been fully read by PasswordStore + // before overriding it again. The way to achieve that, for the current + // implementation of PasswordStore, is to make a round trip to the backend + // sequence, which guarantees that initialization has completed. + if (index != 0) { + // We ignore the returned value since all we want is to wait for the + // round trip to be completed. + GetPasswordCount(index - 1); + } + // The value of the feature kSyncUSSPasswords only matters during the // setup of each client, when the profile is created, ProfileSyncService // instantiated as well as the datatype controllers. By overriding the
diff --git a/chrome/browser/sync/user_event_service_factory.cc b/chrome/browser/sync/user_event_service_factory.cc index b2a3182..b0cf20a 100644 --- a/chrome/browser/sync/user_event_service_factory.cc +++ b/chrome/browser/sync/user_event_service_factory.cc
@@ -14,10 +14,10 @@ #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/sync/session_sync_service_factory.h" #include "chrome/common/channel_info.h" -#include "components/browser_sync/profile_sync_service.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/sync/base/model_type.h" #include "components/sync/base/report_unrecoverable_error.h" +#include "components/sync/driver/sync_service.h" #include "components/sync/model/model_type_store_service.h" #include "components/sync/model_impl/client_tag_based_model_type_processor.h" #include "components/sync/user_events/no_op_user_event_service.h"
diff --git a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc index 948fa68..a8a34e5 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
@@ -57,10 +57,11 @@ #include "components/arc/arc_util.h" #include "components/arc/metrics/arc_metrics_constants.h" #include "components/arc/test/fake_app_instance.h" -#include "components/browser_sync/profile_sync_service.h" +#include "components/sync/driver/sync_service.h" #include "components/sync/model/fake_sync_change_processor.h" #include "components/sync/model/sync_data.h" #include "components/sync/model/sync_error_factory_mock.h" +#include "components/sync/protocol/sync.pb.h" #include "components/sync_preferences/testing_pref_service_syncable.h" #include "content/public/browser/browser_thread.h" #include "content/public/test/test_utils.h"
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc index 911977c..943a0a3 100644 --- a/chrome/browser/ui/autofill/chrome_autofill_client.cc +++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc
@@ -47,7 +47,6 @@ #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/browser_sync/profile_sync_service.h" #include "components/password_manager/content/browser/content_password_manager_driver.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/password_manager/core/browser/password_requirements_service.h" @@ -56,6 +55,7 @@ #include "components/signin/core/browser/signin_buildflags.h" #include "components/signin/core/browser/signin_header_helper.h" #include "components/signin/core/browser/signin_metrics.h" +#include "components/sync/driver/sync_service.h" #include "components/translate/core/browser/translate_manager.h" #include "components/ukm/content/source_url_recorder.h" #include "components/user_prefs/user_prefs.h" @@ -125,7 +125,7 @@ syncer::SyncService* ChromeAutofillClient::GetSyncService() { Profile* profile = Profile::FromBrowserContext(web_contents()->GetBrowserContext()); - return ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile); + return ProfileSyncServiceFactory::GetForProfile(profile); } identity::IdentityManager* ChromeAutofillClient::GetIdentityManager() {
diff --git a/chrome/browser/ui/passwords/settings/password_manager_presenter.cc b/chrome/browser/ui/passwords/settings/password_manager_presenter.cc index 70a232d..1625e5d 100644 --- a/chrome/browser/ui/passwords/settings/password_manager_presenter.cc +++ b/chrome/browser/ui/passwords/settings/password_manager_presenter.cc
@@ -30,13 +30,13 @@ #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" #include "components/autofill/core/common/password_form.h" -#include "components/browser_sync/profile_sync_service.h" #include "components/password_manager/core/browser/password_list_sorter.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/password_manager/core/browser/password_sync_util.h" #include "components/password_manager/core/browser/password_ui_utils.h" #include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/prefs/pref_service.h" +#include "components/sync/driver/sync_service.h" #include "components/undo/undo_operation.h" #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/ui/views/crostini/crostini_installer_view.cc b/chrome/browser/ui/views/crostini/crostini_installer_view.cc index 83dc9ed..6615368 100644 --- a/chrome/browser/ui/views/crostini/crostini_installer_view.cc +++ b/chrome/browser/ui/views/crostini/crostini_installer_view.cc
@@ -133,6 +133,14 @@ return l10n_util::GetStringUTF16(IDS_APP_CANCEL); } +bool CrostiniInstallerView::IsDialogButtonEnabled( + ui::DialogButton button) const { + if (button == ui::DIALOG_BUTTON_CANCEL && + (state_ == State::CLEANUP || state_ == State::CLEANUP_FINISHED)) { + return false; + } + return true; +} bool CrostiniInstallerView::ShouldShowCloseButton() const { return false; @@ -157,14 +165,10 @@ profile_->GetPrefs()->Set(crostini::prefs::kCrostiniContainers, base::Value(base::Value::Type::LIST)); - progress_bar_->SetVisible(true); - // |learn_more_link_| should only be present in State::PROMPT. delete learn_more_link_; learn_more_link_ = nullptr; - StepProgress(); - // HandleError needs the |progress_bar_|, so we delay our Offline check until // it exists. if (content::GetNetworkConnectionTracker()->IsOffline()) { @@ -250,7 +254,6 @@ } VLOG(1) << "cros-termina install success"; UpdateState(State::START_CONCIERGE); - StepProgress(); } void CrostiniInstallerView::OnConciergeStarted(CrostiniResult result) { @@ -265,7 +268,6 @@ } VLOG(1) << "Concierge service started"; UpdateState(State::CREATE_DISK_IMAGE); - StepProgress(); } void CrostiniInstallerView::OnDiskImageCreated( @@ -290,7 +292,6 @@ } VLOG(1) << "Created crostini disk image"; UpdateState(State::START_TERMINA_VM); - StepProgress(); } void CrostiniInstallerView::OnVmStarted(CrostiniResult result) { @@ -305,7 +306,6 @@ } VLOG(1) << "Started Termina VM successfully"; UpdateState(State::CREATE_CONTAINER); - StepProgress(); } void CrostiniInstallerView::OnContainerDownloading(int32_t download_percent) { @@ -319,7 +319,6 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_EQ(state_, State::CREATE_CONTAINER); UpdateState(State::START_CONTAINER); - StepProgress(); } void CrostiniInstallerView::OnContainerStarted(CrostiniResult result) { @@ -336,7 +335,6 @@ } VLOG(1) << "Started container successfully"; UpdateState(State::SETUP_CONTAINER); - StepProgress(); } void CrostiniInstallerView::OnContainerSetup(CrostiniResult result) { @@ -353,7 +351,6 @@ } VLOG(1) << "Set up container successfully"; UpdateState(State::FETCH_SSH_KEYS); - StepProgress(); } void CrostiniInstallerView::OnSshKeysFetched(CrostiniResult result) { @@ -370,7 +367,6 @@ } VLOG(1) << "Fetched ssh keys successfully"; UpdateState(State::MOUNT_CONTAINER); - StepProgress(); } // static @@ -490,8 +486,6 @@ UpdateState(State::ERROR); message_label_->SetVisible(true); message_label_->SetText(error_message); - SetBigMessageLabel(); - progress_bar_->SetVisible(false); // Remove the buttons so they get recreated with correct color and // highlighting. Without this it is possible for both buttons to be styled as @@ -512,7 +506,6 @@ SetupResult::kErrorMountingContainer); return; } - StepProgress(); ShowLoginShell(); } @@ -526,7 +519,6 @@ crostini::kCrostiniDefaultVmName, crostini::kCrostiniDefaultContainerName, std::vector<std::string>()); - StepProgress(); RecordSetupResultHistogram(SetupResult::kSuccess); crostini_manager->UpdateLaunchMetricsForEnterpriseReporting(); RecordTimeFromDeviceSetupToInstallMetric(); @@ -628,6 +620,8 @@ state_progress_timer_->AbandonAndStop(); } } + + StepProgress(); } void CrostiniInstallerView::SetMessageLabel() { @@ -662,6 +656,9 @@ case State::MOUNT_CONTAINER: message_id = IDS_CROSTINI_INSTALLER_MOUNT_CONTAINER_MESSAGE; break; + case State::CLEANUP: + message_id = IDS_CROSTINI_INSTALLER_CANCELING; + break; default: break; }
diff --git a/chrome/browser/ui/views/crostini/crostini_installer_view.h b/chrome/browser/ui/views/crostini/crostini_installer_view.h index 9be1784..9a1c3b4 100644 --- a/chrome/browser/ui/views/crostini/crostini_installer_view.h +++ b/chrome/browser/ui/views/crostini/crostini_installer_view.h
@@ -72,6 +72,7 @@ // views::DialogDelegateView: int GetDialogButtons() const override; base::string16 GetDialogButtonLabel(ui::DialogButton button) const override; + bool IsDialogButtonEnabled(ui::DialogButton button) const override; bool ShouldShowCloseButton() const override; bool ShouldShowWindowTitle() const override; bool Accept() override;
diff --git a/chrome/browser/ui/views/location_bar/custom_tab_bar_view.cc b/chrome/browser/ui/views/location_bar/custom_tab_bar_view.cc index a5acd2a1f..e2483158 100644 --- a/chrome/browser/ui/views/location_bar/custom_tab_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/custom_tab_bar_view.cc
@@ -107,17 +107,15 @@ // page. class CustomTabBarTitleOriginView : public views::View { public: - explicit CustomTabBarTitleOriginView(SkColor foreground_color, - SkColor background_color) { - title_label_ = new views::Label( - base::string16(), views::style::TextContext::CONTEXT_DIALOG_TITLE); - location_label_ = new views::Label(base::string16()); + explicit CustomTabBarTitleOriginView(SkColor background_color) { + title_label_ = new views::Label(base::string16(), CONTEXT_BODY_TEXT_LARGE, + views::style::TextStyle::STYLE_PRIMARY); + location_label_ = new views::Label( + base::string16(), CONTEXT_BODY_TEXT_SMALL, STYLE_SECONDARY); - title_label_->SetEnabledColor(foreground_color); title_label_->SetBackgroundColor(background_color); title_label_->SetElideBehavior(gfx::ElideBehavior::ELIDE_TAIL); - location_label_->SetEnabledColor(foreground_color); location_label_->SetBackgroundColor(background_color); location_label_->SetElideBehavior(gfx::ElideBehavior::ELIDE_TAIL); @@ -171,19 +169,20 @@ title_bar_color_ = optional_theme_color.value_or(GetDefaultFrameColor()); SetBackground(views::CreateSolidBackground(kCustomTabBarViewBackgroundColor)); - constexpr SkColor kForegroundColor = gfx::kGoogleGrey900; + const SkColor foreground_color = + color_utils::GetColorWithMaxContrast(kCustomTabBarViewBackgroundColor); const gfx::FontList& font_list = views::style::GetFont( CONTEXT_OMNIBOX_PRIMARY, views::style::STYLE_PRIMARY); - close_button_ = CreateCloseButton(this, kForegroundColor); + close_button_ = CreateCloseButton(this, foreground_color); AddChildView(close_button_); location_icon_view_ = new LocationIconView(font_list, this); AddChildView(location_icon_view_); - title_origin_view_ = new CustomTabBarTitleOriginView( - kForegroundColor, kCustomTabBarViewBackgroundColor); + title_origin_view_ = + new CustomTabBarTitleOriginView(kCustomTabBarViewBackgroundColor); AddChildView(title_origin_view_); auto layout = std::make_unique<views::FlexLayout>();
diff --git a/chrome/browser/ui/webui/media_router/media_router_webui_message_handler.cc b/chrome/browser/ui/webui/media_router/media_router_webui_message_handler.cc index 871c69f..029f640 100644 --- a/chrome/browser/ui/webui/media_router/media_router_webui_message_handler.cc +++ b/chrome/browser/ui/webui/media_router/media_router_webui_message_handler.cc
@@ -25,9 +25,9 @@ #include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" -#include "components/browser_sync/profile_sync_service.h" #include "components/prefs/pref_service.h" #include "components/signin/core/browser/account_info.h" +#include "components/sync/driver/sync_service.h" #include "content/public/browser/web_ui.h" #include "extensions/common/constants.h" #include "services/identity/public/cpp/identity_manager.h"
diff --git a/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc b/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc index 5e5186e..08df873 100644 --- a/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc +++ b/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc
@@ -599,10 +599,12 @@ base::MakeRefCounted<MockUsbDevice>(0, 1, "Google", "USB Printer", ""); usb_service().AddDevice(device1); - const Extension* extension_1 = env_.MakeExtension( - *base::test::ParseJson(kExtension1), "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); - const Extension* extension_2 = env_.MakeExtension( - *base::test::ParseJson(kExtension2), "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); + const Extension* extension_1 = + env_.MakeExtension(*base::test::ParseJsonDeprecated(kExtension1), + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + const Extension* extension_2 = + env_.MakeExtension(*base::test::ParseJsonDeprecated(kExtension2), + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); extensions::DevicePermissionsManager* permissions_manager = extensions::DevicePermissionsManager::Get(env_.profile());
diff --git a/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc b/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc index 33867b01..8b61315 100644 --- a/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc +++ b/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc
@@ -19,12 +19,12 @@ source->AddResourcePath("usb_internals.css", IDR_USB_INTERNALS_CSS); source->AddResourcePath("usb_internals.js", IDR_USB_INTERNALS_JS); source->AddResourcePath( - "device/usb/public/mojom/device_manager_test.mojom.js", + "device/usb/public/mojom/device_manager_test.mojom-lite.js", IDR_USB_DEVICE_MANAGER_TEST_MOJO_JS); source->AddResourcePath( - "chrome/browser/ui/webui/usb_internals/usb_internals.mojom.js", + "chrome/browser/ui/webui/usb_internals/usb_internals.mojom-lite.js", IDR_USB_INTERNALS_MOJO_JS); - source->AddResourcePath("url/mojom/url.mojom.js", IDR_URL_MOJO_JS); + source->AddResourcePath("url/mojom/url.mojom-lite.js", IDR_URL_MOJO_LITE_JS); source->SetDefaultResource(IDR_USB_INTERNALS_HTML); source->UseGzip();
diff --git a/chrome/browser/web_applications/components/web_app_install_utils.cc b/chrome/browser/web_applications/components/web_app_install_utils.cc index d6295571..39230d6 100644 --- a/chrome/browser/web_applications/components/web_app_install_utils.cc +++ b/chrome/browser/web_applications/components/web_app_install_utils.cc
@@ -7,6 +7,10 @@ #include <utility> #include "base/stl_util.h" +#include "base/time/time.h" +#include "chrome/browser/banners/app_banner_manager.h" +#include "chrome/browser/banners/app_banner_manager_desktop.h" +#include "chrome/browser/banners/app_banner_settings_helper.h" #include "chrome/browser/installable/installable_data.h" #include "chrome/browser/web_applications/components/web_app_icon_generator.h" #include "chrome/common/web_application_info.h" @@ -163,4 +167,11 @@ ReplaceWebAppIcons(size_to_icons, web_app_info); } +void RecordAppBanner(content::WebContents* contents, const GURL& app_url) { + AppBannerSettingsHelper::RecordBannerEvent( + contents, app_url, app_url.spec(), + AppBannerSettingsHelper::APP_BANNER_EVENT_DID_ADD_TO_HOMESCREEN, + base::Time::Now()); +} + } // namespace web_app
diff --git a/chrome/browser/web_applications/components/web_app_install_utils.h b/chrome/browser/web_applications/components/web_app_install_utils.h index edda0a86..488134c 100644 --- a/chrome/browser/web_applications/components/web_app_install_utils.h +++ b/chrome/browser/web_applications/components/web_app_install_utils.h
@@ -19,6 +19,10 @@ struct Manifest; } +namespace content { +class WebContents; +} + namespace web_app { struct BitmapAndSource; @@ -65,6 +69,10 @@ std::vector<BitmapAndSource> downloaded_icons, WebApplicationInfo* web_app_info); +// Record an app banner added to homescreen event to ensure banners are not +// shown for this app. +void RecordAppBanner(content::WebContents* contents, const GURL& app_url); + } // namespace web_app #endif // CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_WEB_APP_INSTALL_UTILS_H_
diff --git a/chrome/common/extensions/manifest_tests/extension_manifests_action_key_unittest.cc b/chrome/common/extensions/manifest_tests/extension_manifests_action_key_unittest.cc index 6e92c97..cc45977 100644 --- a/chrome/common/extensions/manifest_tests/extension_manifests_action_key_unittest.cc +++ b/chrome/common/extensions/manifest_tests/extension_manifests_action_key_unittest.cc
@@ -16,11 +16,12 @@ protected: ManifestData CreateManifest(const std::string& action_json) { std::unique_ptr<base::DictionaryValue> manifest = - base::DictionaryValue::From(base::test::ParseJson(R"json({ + base::DictionaryValue::From( + base::test::ParseJsonDeprecated(R"json({ "name": "test", "version": "1", "manifest_version": 2, )json" + - action_json + "}")); + action_json + "}")); EXPECT_TRUE(manifest); return ManifestData(std::move(manifest), "test"); }
diff --git a/chrome/common/extensions/permissions/permissions_data_unittest.cc b/chrome/common/extensions/permissions/permissions_data_unittest.cc index 37cabda..6a1c3b3 100644 --- a/chrome/common/extensions/permissions/permissions_data_unittest.cc +++ b/chrome/common/extensions/permissions/permissions_data_unittest.cc
@@ -129,10 +129,7 @@ extension->permissions_data()->IsRestrictedUrl(invalid_url, &error)) << name; if (!allow_on_other_schemes) { - EXPECT_EQ(ErrorUtils::FormatErrorMessage( - manifest_errors::kCannotAccessPage, - invalid_url.spec()), - error) << name; + EXPECT_EQ(manifest_errors::kCannotAccessPage, error) << name; } else { EXPECT_TRUE(error.empty()); }
diff --git a/chrome/installer/gcapi/BUILD.gn b/chrome/installer/gcapi/BUILD.gn index 297c55a..a6a5018 100644 --- a/chrome/installer/gcapi/BUILD.gn +++ b/chrome/installer/gcapi/BUILD.gn
@@ -54,7 +54,6 @@ "//base", "//chrome/installer/launcher_support", "//chrome/installer/util:with_no_strings", - "//components/variations", "//google_update", ] } @@ -75,7 +74,6 @@ "//chrome/install_static:install_static_util", "//chrome/install_static/test:test_support", "//chrome/installer/util:with_no_strings", - "//components/variations", "//testing/gtest", ]
diff --git a/chrome/installer/gcapi/gcapi_omaha_experiment.cc b/chrome/installer/gcapi/gcapi_omaha_experiment.cc index 286d22f..68c50c34 100644 --- a/chrome/installer/gcapi/gcapi_omaha_experiment.cc +++ b/chrome/installer/gcapi/gcapi_omaha_experiment.cc
@@ -4,18 +4,27 @@ #include "chrome/installer/gcapi/gcapi_omaha_experiment.h" +#include "base/logging.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" -#include "base/time/time.h" #include "chrome/installer/gcapi/gcapi.h" #include "chrome/installer/gcapi/google_update_util.h" #include "chrome/installer/util/google_update_constants.h" -#include "components/variations/variations_experiment_util.h" namespace { +constexpr const base::char16* kDays[] = { + STRING16_LITERAL("Sun"), STRING16_LITERAL("Mon"), STRING16_LITERAL("Tue"), + STRING16_LITERAL("Wed"), STRING16_LITERAL("Thu"), STRING16_LITERAL("Fri"), + STRING16_LITERAL("Sat")}; + +constexpr const base::char16* kMonths[] = { + STRING16_LITERAL("Jan"), STRING16_LITERAL("Feb"), STRING16_LITERAL("Mar"), + STRING16_LITERAL("Apr"), STRING16_LITERAL("May"), STRING16_LITERAL("Jun"), + STRING16_LITERAL("Jul"), STRING16_LITERAL("Aug"), STRING16_LITERAL("Sep"), + STRING16_LITERAL("Oct"), STRING16_LITERAL("Nov"), STRING16_LITERAL("Dec")}; + // Returns the number of weeks since 2/3/2003. int GetCurrentRlzWeek(const base::Time& current_time) { const base::Time::Exploded february_third_2003_exploded = @@ -43,8 +52,7 @@ // Split the original labels by the label separator. std::vector<base::string16> entries = base::SplitString( - original_labels, - base::string16(1, variations::kExperimentLabelSeparator), + original_labels, base::string16(1, kExperimentLabelSeparator), base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); // Keep all labels, but the one we want to add/replace. @@ -56,7 +64,7 @@ !base::StartsWith(entry, label_and_separator, base::CompareCase::SENSITIVE)) { new_labels += entry; - new_labels += variations::kExperimentLabelSeparator; + new_labels += kExperimentLabelSeparator; } } @@ -86,17 +94,16 @@ base::string16 gcapi_experiment_label; base::SStringPrintf(&gcapi_experiment_label, - L"%ls=%ls_%d|%ls", - label.c_str(), - brand_code, - GetCurrentRlzWeek(instance_time), - variations::BuildExperimentDateString( - instance_time).c_str()); + STRING16_LITERAL("%ls=%ls_%d|%ls"), label.c_str(), + brand_code, GetCurrentRlzWeek(instance_time), + BuildExperimentDateString(instance_time).c_str()); return gcapi_experiment_label; } } // namespace gcapi_internals +const base::char16 kExperimentLabelSeparator = ';'; + bool SetReactivationExperimentLabels(const wchar_t* brand_code, int shell_mode) { return SetExperimentLabel(brand_code, gcapi_internals::kReactivationLabel, @@ -107,3 +114,25 @@ return SetExperimentLabel(brand_code, gcapi_internals::kRelaunchLabel, shell_mode); } + +base::string16 BuildExperimentDateString(base::Time current_time) { + // The Google Update experiment_labels timestamp format is: + // "DAY, DD0 MON YYYY HH0:MI0:SE0 TZ" + // DAY = 3 character day of week, + // DD0 = 2 digit day of month, + // MON = 3 character month of year, + // YYYY = 4 digit year, + // HH0 = 2 digit hour, + // MI0 = 2 digit minute, + // SE0 = 2 digit second, + // TZ = 3 character timezone + base::Time::Exploded then = {}; + current_time.UTCExplode(&then); + then.year += 1; + DCHECK(then.HasValidValues()); + + return base::StringPrintf( + STRING16_LITERAL("%s, %02d %s %d %02d:%02d:%02d GMT"), + kDays[then.day_of_week], then.day_of_month, kMonths[then.month - 1], + then.year, then.hour, then.minute, then.second); +}
diff --git a/chrome/installer/gcapi/gcapi_omaha_experiment.h b/chrome/installer/gcapi/gcapi_omaha_experiment.h index 8e5d79f0..5e423ccc 100644 --- a/chrome/installer/gcapi/gcapi_omaha_experiment.h +++ b/chrome/installer/gcapi/gcapi_omaha_experiment.h
@@ -6,6 +6,7 @@ #define CHROME_INSTALLER_GCAPI_GCAPI_OMAHA_EXPERIMENT_H_ #include "base/strings/string16.h" +#include "base/time/time.h" namespace gcapi_internals { @@ -19,6 +20,9 @@ } // namespace gcapi_internals +// The separator used to separate items in experiment labels. +extern const base::char16 kExperimentLabelSeparator; + // Writes a reactivation brand code experiment label in the Chrome product and // binaries registry keys for |brand_code|. This experiment label will have a // expiration date of now plus one year. If |shell_mode| is set to @@ -35,4 +39,8 @@ // at the same time (they are mutually exclusive). bool SetRelaunchExperimentLabels(const wchar_t* brand_code, int shell_mode); +// Constructs a date string in the format understood by Google Update for the +// |current_time| plus one year. +base::string16 BuildExperimentDateString(base::Time current_time); + #endif // CHROME_INSTALLER_GCAPI_GCAPI_OMAHA_EXPERIMENT_H_
diff --git a/chrome/installer/gcapi/gcapi_omaha_experiment_test.cc b/chrome/installer/gcapi/gcapi_omaha_experiment_test.cc index 038c7fe4..00ce5297 100644 --- a/chrome/installer/gcapi/gcapi_omaha_experiment_test.cc +++ b/chrome/installer/gcapi/gcapi_omaha_experiment_test.cc
@@ -6,17 +6,13 @@ #include <stdint.h> -#include "base/strings/utf_string_conversions.h" #include "base/test/test_reg_util_win.h" #include "chrome/install_static/test/scoped_install_details.h" #include "chrome/installer/gcapi/gcapi.h" #include "chrome/installer/util/google_update_constants.h" #include "chrome/installer/util/google_update_settings.h" -#include "components/variations/variations_experiment_util.h" #include "testing/gtest/include/gtest/gtest.h" -using base::ASCIIToUTF16; - namespace { const wchar_t kBrand[] = L"ABCD"; @@ -83,7 +79,7 @@ ASSERT_TRUE(SetReactivationExperimentLabels(kBrand, shell_mode())); base::string16 expected_labels(kSomeExperiments); - expected_labels += variations::kExperimentLabelSeparator; + expected_labels += kExperimentLabelSeparator; expected_labels.append(reactivation_label_); VerifyExperimentLabels(expected_labels); } @@ -91,18 +87,18 @@ TEST_P(GCAPIOmahaExperimentTest, SetReactivationLabelWithExistingIdenticalExperiment) { base::string16 previous_labels(kSomeExperiments); - previous_labels += variations::kExperimentLabelSeparator; + previous_labels += kExperimentLabelSeparator; previous_labels.append(reactivation_label_); - previous_labels += variations::kExperimentLabelSeparator; + previous_labels += kExperimentLabelSeparator; previous_labels.append(kSomeOtherExperiments); GoogleUpdateSettings::SetExperimentLabels(previous_labels); ASSERT_TRUE(SetReactivationExperimentLabels(kBrand, shell_mode())); base::string16 expected_labels(kSomeExperiments); - expected_labels += variations::kExperimentLabelSeparator; + expected_labels += kExperimentLabelSeparator; expected_labels.append(kSomeOtherExperiments); - expected_labels += variations::kExperimentLabelSeparator; + expected_labels += kExperimentLabelSeparator; expected_labels.append(reactivation_label_); VerifyExperimentLabels(expected_labels); } @@ -110,14 +106,14 @@ TEST_P(GCAPIOmahaExperimentTest, SetReactivationLabelWithExistingIdenticalAtBeginning) { base::string16 previous_labels(reactivation_label_); - previous_labels += variations::kExperimentLabelSeparator; + previous_labels += kExperimentLabelSeparator; previous_labels.append(kSomeExperiments); GoogleUpdateSettings::SetExperimentLabels(previous_labels); ASSERT_TRUE(SetReactivationExperimentLabels(kBrand, shell_mode())); base::string16 expected_labels(kSomeExperiments); - expected_labels += variations::kExperimentLabelSeparator; + expected_labels += kExperimentLabelSeparator; expected_labels.append(reactivation_label_); VerifyExperimentLabels(expected_labels); } @@ -125,30 +121,30 @@ TEST_P(GCAPIOmahaExperimentTest, SetReactivationLabelWithFakeMatchInAnExperiment) { base::string16 previous_labels(kSomeExperiments); - previous_labels += variations::kExperimentLabelSeparator; + previous_labels += kExperimentLabelSeparator; previous_labels.append(L"blah_"); // Shouldn't match deletion criteria. previous_labels.append(reactivation_label_); - previous_labels += variations::kExperimentLabelSeparator; + previous_labels += kExperimentLabelSeparator; previous_labels.append(kSomeOtherExperiments); - previous_labels += variations::kExperimentLabelSeparator; + previous_labels += kExperimentLabelSeparator; // Should match the deletion criteria. previous_labels.append(reactivation_label_); - previous_labels += variations::kExperimentLabelSeparator; + previous_labels += kExperimentLabelSeparator; previous_labels.append(kSomeMoreExperiments); GoogleUpdateSettings::SetExperimentLabels(previous_labels); ASSERT_TRUE(SetReactivationExperimentLabels(kBrand, shell_mode())); base::string16 expected_labels(kSomeExperiments); - expected_labels += variations::kExperimentLabelSeparator; + expected_labels += kExperimentLabelSeparator; expected_labels.append(L"blah_"); expected_labels.append(reactivation_label_); - expected_labels += variations::kExperimentLabelSeparator; + expected_labels += kExperimentLabelSeparator; expected_labels.append(kSomeOtherExperiments); - expected_labels += variations::kExperimentLabelSeparator; + expected_labels += kExperimentLabelSeparator; expected_labels.append(kSomeMoreExperiments); - expected_labels += variations::kExperimentLabelSeparator; + expected_labels += kExperimentLabelSeparator; expected_labels.append(reactivation_label_); VerifyExperimentLabels(expected_labels); } @@ -156,23 +152,23 @@ TEST_P(GCAPIOmahaExperimentTest, SetReactivationLabelWithFakeMatchInAnExperimentAndNoRealMatch) { base::string16 previous_labels(kSomeExperiments); - previous_labels += variations::kExperimentLabelSeparator; + previous_labels += kExperimentLabelSeparator; previous_labels.append(L"blah_"); // Shouldn't match deletion criteria. previous_labels.append(reactivation_label_); - previous_labels += variations::kExperimentLabelSeparator; + previous_labels += kExperimentLabelSeparator; previous_labels.append(kSomeOtherExperiments); GoogleUpdateSettings::SetExperimentLabels(previous_labels); ASSERT_TRUE(SetReactivationExperimentLabels(kBrand, shell_mode())); base::string16 expected_labels(kSomeExperiments); - expected_labels += variations::kExperimentLabelSeparator; + expected_labels += kExperimentLabelSeparator; expected_labels.append(L"blah_"); expected_labels.append(reactivation_label_); - expected_labels += variations::kExperimentLabelSeparator; + expected_labels += kExperimentLabelSeparator; expected_labels.append(kSomeOtherExperiments); - expected_labels += variations::kExperimentLabelSeparator; + expected_labels += kExperimentLabelSeparator; expected_labels.append(reactivation_label_); VerifyExperimentLabels(expected_labels); } @@ -180,7 +176,7 @@ TEST_P(GCAPIOmahaExperimentTest, SetReactivationLabelWithExistingEntryWithLabelAsPrefix) { base::string16 previous_labels(kSomeExperiments); - previous_labels += variations::kExperimentLabelSeparator; + previous_labels += kExperimentLabelSeparator; // Append prefix matching the label, but not followed by '='. previous_labels.append(gcapi_internals::kReactivationLabel); // Shouldn't match deletion criteria. @@ -190,14 +186,113 @@ ASSERT_TRUE(SetReactivationExperimentLabels(kBrand, shell_mode())); base::string16 expected_labels(kSomeExperiments); - expected_labels += variations::kExperimentLabelSeparator; + expected_labels += kExperimentLabelSeparator; expected_labels.append(gcapi_internals::kReactivationLabel); expected_labels.append(kSomeOtherExperiments); - expected_labels += variations::kExperimentLabelSeparator; + expected_labels += kExperimentLabelSeparator; expected_labels.append(reactivation_label_); VerifyExperimentLabels(expected_labels); } +TEST_P(GCAPIOmahaExperimentTest, BuildExperimentDateString) { + // Sat, 1 Jan 2000 00:00:00 UTC + base::Time::Exploded kTestTimeExploded = {2000, 1, 6, 1, 0, 0, 0, 0}; + base::Time kTestTime; + EXPECT_TRUE(base::Time::FromUTCExploded(kTestTimeExploded, &kTestTime)); + EXPECT_EQ(STRING16_LITERAL("Sat, 01 Jan 2001 00:00:00 GMT"), + BuildExperimentDateString(kTestTime)); + EXPECT_EQ(STRING16_LITERAL("Sat, 01 Jan 2001 00:00:00 GMT"), + BuildExperimentDateString(kTestTime + + base::TimeDelta::FromMilliseconds(1))); + EXPECT_EQ( + STRING16_LITERAL("Sat, 01 Jan 2001 00:00:01 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromSeconds(1))); + EXPECT_EQ( + STRING16_LITERAL("Sat, 01 Jan 2001 00:00:59 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromSeconds(59))); + EXPECT_EQ( + STRING16_LITERAL("Sat, 01 Jan 2001 00:01:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromSeconds(60))); + EXPECT_EQ( + STRING16_LITERAL("Sat, 01 Jan 2001 00:01:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromMinutes(1))); + EXPECT_EQ( + STRING16_LITERAL("Sat, 01 Jan 2001 00:59:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromMinutes(59))); + EXPECT_EQ( + STRING16_LITERAL("Sat, 01 Jan 2001 01:00:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromMinutes(60))); + EXPECT_EQ( + STRING16_LITERAL("Sat, 01 Jan 2001 01:00:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromHours(1))); + EXPECT_EQ( + STRING16_LITERAL("Sat, 01 Jan 2001 23:00:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromHours(23))); + EXPECT_EQ( + STRING16_LITERAL("Sun, 02 Jan 2001 00:00:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromHours(24))); + EXPECT_EQ( + STRING16_LITERAL("Sun, 02 Jan 2001 00:00:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromDays(1))); + EXPECT_EQ( + STRING16_LITERAL("Mon, 03 Jan 2001 00:00:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromDays(2))); + EXPECT_EQ( + STRING16_LITERAL("Tue, 04 Jan 2001 00:00:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromDays(3))); + EXPECT_EQ( + STRING16_LITERAL("Wed, 05 Jan 2001 00:00:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromDays(4))); + EXPECT_EQ( + STRING16_LITERAL("Thu, 06 Jan 2001 00:00:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromDays(5))); + EXPECT_EQ( + STRING16_LITERAL("Fri, 07 Jan 2001 00:00:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromDays(6))); + EXPECT_EQ( + STRING16_LITERAL("Sat, 08 Jan 2001 00:00:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromDays(7))); + EXPECT_EQ( + STRING16_LITERAL("Mon, 31 Jan 2001 00:00:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromDays(30))); + EXPECT_EQ( + STRING16_LITERAL("Tue, 01 Feb 2001 00:00:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromDays(31))); + EXPECT_EQ( + STRING16_LITERAL("Wed, 01 Mar 2001 00:00:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromDays(60))); + EXPECT_EQ( + STRING16_LITERAL("Sat, 01 Apr 2001 00:00:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromDays(91))); + EXPECT_EQ( + STRING16_LITERAL("Mon, 01 May 2001 00:00:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromDays(121))); + EXPECT_EQ( + STRING16_LITERAL("Thu, 01 Jun 2001 00:00:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromDays(152))); + EXPECT_EQ( + STRING16_LITERAL("Sat, 01 Jul 2001 00:00:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromDays(182))); + EXPECT_EQ( + STRING16_LITERAL("Tue, 01 Aug 2001 00:00:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromDays(213))); + EXPECT_EQ( + STRING16_LITERAL("Fri, 01 Sep 2001 00:00:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromDays(244))); + EXPECT_EQ( + STRING16_LITERAL("Sun, 01 Oct 2001 00:00:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromDays(274))); + EXPECT_EQ( + STRING16_LITERAL("Wed, 01 Nov 2001 00:00:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromDays(305))); + EXPECT_EQ( + STRING16_LITERAL("Fri, 01 Dec 2001 00:00:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromDays(335))); + EXPECT_EQ( + STRING16_LITERAL("Mon, 01 Jan 2002 00:00:00 GMT"), + BuildExperimentDateString(kTestTime + base::TimeDelta::FromDays(366))); +} + INSTANTIATE_TEST_SUITE_P(, GCAPIOmahaExperimentTest, ::testing::Bool()); } // namespace
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 65faf7c..5cea213 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -382,6 +382,9 @@ "//media/test/data/four-colors-rot-180.mp4", "//media/test/data/four-colors-rot-270.mp4", "//media/test/data/four-colors-vp9.webm", + + # For power + "//media/test/data/bear-1280x720.mp4", ] # For pixel_test and maps_pixel_test. Because this links to a CIPD
diff --git a/chrome/test/data/autofill/captured_sites/cipd.yaml b/chrome/test/data/autofill/captured_sites/cipd.yaml index 839a8b88..505c396 100644 --- a/chrome/test/data/autofill/captured_sites/cipd.yaml +++ b/chrome/test/data/autofill/captured_sites/cipd.yaml
@@ -13,7 +13,7 @@ # Captured Sites Test Framework Eng doc: # https://docs.google.com/document/d/12ZLoGmBK9kc5C5ComHkJWWJUXOda5K0uFr-hfSt6ZUg description: captured sites test archives and recipes. -install_mode: "copy" +install_mode: copy data: - file: amazon - file: amazon.test
diff --git a/chrome/test/data/extensions/api_test/permissions/file_access_no/background.js b/chrome/test/data/extensions/api_test/permissions/file_access_no/background.js index bfc3c0e..bc54ecb 100644 --- a/chrome/test/data/extensions/api_test/permissions/file_access_no/background.js +++ b/chrome/test/data/extensions/api_test/permissions/file_access_no/background.js
@@ -5,7 +5,7 @@ var callbackFail = chrome.test.callbackFail; var callbackPass = chrome.test.callbackPass; var expectedError = - "Invalid value for origin pattern file:///Invalid scheme.: *"; + "Invalid value for origin pattern file:///*: Invalid scheme."; function test() { chrome.permissions.request({"origins": ["file:///*"]},
diff --git a/chrome/test/data/webui/cr_elements/cr_action_menu_test.js b/chrome/test/data/webui/cr_elements/cr_action_menu_test.js index 76800e7a..e5b5a6d 100644 --- a/chrome/test/data/webui/cr_elements/cr_action_menu_test.js +++ b/chrome/test/data/webui/cr_elements/cr_action_menu_test.js
@@ -166,6 +166,13 @@ assertEquals(items[2], getDeepActiveElement()); }); + test('close on click away', function() { + menu.showAt(dots); + assertTrue(dialog.open); + menu.click(); + assertFalse(dialog.open); + }); + test('close on resize', function() { menu.showAt(dots); assertTrue(dialog.open);
diff --git a/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js b/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js index 92a5fd7..c364aa6 100644 --- a/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js +++ b/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js
@@ -1256,3 +1256,31 @@ this.runMochaTest( destination_settings_test.TestNames.TwoAccountsRecentDestinations); }); + +PrintPreviewScalingSettingsTest = class extends NewPrintPreviewTest { + /** @override */ + get browsePreload() { + return 'chrome://print/new/scaling_settings.html'; + } + + /** @override */ + get extraLibraries() { + return super.extraLibraries.concat([ + '../settings/test_util.js', + 'print_preview_test_utils.js', + 'scaling_settings_test.js', + ]); + } + + /** @override */ + get suiteName() { + return scaling_settings_test.suiteName; + } +}; + +TEST_F( + 'PrintPreviewScalingSettingsTest', 'InputNotDisabledOnValidityChange', + function() { + this.runMochaTest( + scaling_settings_test.TestNames.InputNotDisabledOnValidityChange); + });
diff --git a/chrome/test/data/webui/print_preview/scaling_settings_test.js b/chrome/test/data/webui/print_preview/scaling_settings_test.js new file mode 100644 index 0000000..7a7299b --- /dev/null +++ b/chrome/test/data/webui/print_preview/scaling_settings_test.js
@@ -0,0 +1,148 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +cr.define('scaling_settings_test', function() { + /** @enum {string} */ + const TestNames = { + InputNotDisabledOnValidityChange: 'input not disabled on validity change', + }; + + const suiteName = 'ScalingSettingsTest'; + suite(suiteName, function() { + /** @type {?PrintPreviewScalingSettingsElement} */ + let scalingSection = null; + + /** @override */ + setup(function() { + PolymerTest.clearBody(); + scalingSection = document.createElement('print-preview-scaling-settings'); + scalingSection.settings = { + scaling: { + value: '100', + unavailableValue: '100', + valid: true, + available: true, + key: 'scaleFactor', + }, + customScaling: { + value: false, + unavailableValue: false, + valid: true, + available: true, + key: 'customScaling', + }, + fitToPage: { + value: false, + unavailableValue: false, + valid: true, + available: false, + key: 'isFitToPageEnabled', + }, + }; + scalingSection.disabled = false; + document.body.appendChild(scalingSection); + }); + + /** + * Sets up the scaling section to use the custom input with the input string + * given by |inputString|. + * @param {string} inputString + * @param {number} pageCount + * @return {!Promise} Promise that resolves when the input-change event + * has fired. + */ + function setupInput(inputString) { + const numberSection = + scalingSection.$$('print-preview-number-settings-section'); + const input = numberSection.getInput(); + const scalingSelect = scalingSection.$$('select'); + const isCustomSelected = scalingSelect.value === + scalingSection.scalingValueEnum_.CUSTOM.toString(); + const readyForInput = isCustomSelected ? + Promise.resolve() : + test_util.eventToPromise('process-select-change', scalingSection); + + // Select custom + if (!isCustomSelected) { + scalingSelect.value = + scalingSection.scalingValueEnum_.CUSTOM.toString(); + scalingSelect.dispatchEvent(new CustomEvent('change')); + } + return readyForInput.then(() => { + // Set input string + input.value = inputString; + input.dispatchEvent( + new CustomEvent('input', {composed: true, bubbles: true})); + + // Validate results + return test_util.eventToPromise('input-change', numberSection); + }); + } + + /** + * @param {string} expectedScaling The expected scaling value. + * @param {boolean} invalid Whether the scaling setting should be invalid. + */ + function validateState(expectedScaling, invalid) { + assertEquals(expectedScaling, scalingSection.getSettingValue('scaling')); + assertEquals(!invalid, scalingSection.getSetting('scaling').valid); + assertEquals( + invalid, + scalingSection.$$('print-preview-number-settings-section') + .getInput() + .invalid); + } + + // Verifies that the input is never disabled when the validity of the + // setting changes. + test(assert(TestNames.InputNotDisabledOnValidityChange), function() { + // In the real UI, the print preview app listens for this event from this + // section and others and sets disabled to true if any change from true to + // false is detected. Imitate this here. Since we are only interacting + // with the scaling input, at no point should the input be disabled, as it + // will lose focus. + scalingSection.addEventListener('setting-valid-changed', function(e) { + const numberSection = + scalingSection.$$('print-preview-number-settings-section'); + assertFalse(numberSection.getInput().disabled); + }); + + // Set a valid input + return setupInput('90') + .then(function() { + validateState('90', false); + // Set invalid input + return setupInput('9'); + }) + .then(function() { + validateState('90', true); + // Restore valid input + return setupInput('90'); + }) + .then(function() { + validateState('90', false); + // Invalid input again + return setupInput('9'); + }) + .then(function() { + validateState('90', true); + // Clear input + return setupInput(''); + }) + .then(function() { + validateState('90', false); + // Set valid input + return setupInput('50'); + }) + .then(function() { + validateState('50', false); + }); + }); + }); + + return { + suiteName: suiteName, + TestNames: TestNames, + }; +});
diff --git a/chrome/test/data/webui/settings/bluetooth_page_tests.js b/chrome/test/data/webui/settings/bluetooth_page_tests.js index da9a6bc7..544b347b 100644 --- a/chrome/test/data/webui/settings/bluetooth_page_tests.js +++ b/chrome/test/data/webui/settings/bluetooth_page_tests.js
@@ -18,6 +18,25 @@ }; } +/** + * @param {number} numPairedDevices Number of paired devices to generate. + * @param {number} numUnpairedDevices Number of unparied devices to generate. + * @return {!Array<!chrome.bluetooth.Device>} An array of fake bluetooth + * devices. + */ +function generateFakeDevices(numPairedDevices, numUnpairedDevices) { + let devices = []; + for (let i = 0; i < numPairedDevices + numUnpairedDevices; ++i) { + devices.push({ + address: '00:00:00:00:01:' + i.toString().padStart(2, '0'), + name: 'FakeDevice' + i, + paired: i < numPairedDevices, + connected: false, + }); + } + return devices; +} + suite('Bluetooth', function() { let bluetoothPage = null; @@ -161,14 +180,17 @@ assertFalse(bluetoothPage.bluetoothToggleState_); }); - // listUpdateFrequencyMs is set to 0 for tests, but we still need to wait - // for the callback of setTimeout(0) to be processed in the message queue. - // Add another setTimeout(0) to the end of message queue and wait for it to - // complete ensures the previous callback has been executed. - function waitForListUpdateTimeout() { - return new Promise(function(resolve) { + async function waitForListUpdateTimeout() { + // listUpdateFrequencyMs is set to 0 for tests, but we still need to wait + // for the callback of setTimeout(0) to be processed in the message queue. + await new Promise(function(resolve) { setTimeout(resolve, 0); }); + + // Adding two flushTasks ensures that all events are fully handled after + // being fired. + await PolymerTest.flushTasks(); + await PolymerTest.flushTasks(); } test('pair device', async function() { @@ -178,8 +200,9 @@ ]); await waitForListUpdateTimeout(); - Polymer.dom.flush(); + // TODO(jlklein): Stop referencing private state in these tests. Only use + // public observable state. assertEquals(4, subpage.deviceList_.length); assertEquals(2, subpage.pairedDeviceList_.length); assertEquals(2, subpage.unpairedDeviceList_.length); @@ -189,7 +212,6 @@ resolve => bluetoothPrivateApi.connect(address, resolve)); await waitForListUpdateTimeout(); - Polymer.dom.flush(); assertEquals(3, subpage.pairedDeviceList_.length); assertEquals(1, subpage.unpairedDeviceList_.length); @@ -202,7 +224,6 @@ ]); await waitForListUpdateTimeout(); - Polymer.dom.flush(); const dialog = subpage.$.deviceDialog; assertTrue(!!dialog); assertFalse(dialog.$.dialog.open); @@ -251,7 +272,6 @@ bluetoothApi.simulateDevicesAddedForTest( [fakeUnpairedDevice1, fakeUnpairedDevice2]); await waitForListUpdateTimeout(); - Polymer.dom.flush(); assertEquals(2, deviceList().length); assertEquals(2, unpairedDeviceList().length); @@ -264,7 +284,6 @@ assertEquals( unpairedDeviceList()[1].address, fakeUnpairedDevice2.address); - unpairedDeviceIronList.notifyResize(); Polymer.dom.flush(); const devices = unpairedDeviceIronList.querySelectorAll( @@ -294,7 +313,6 @@ bluetoothApi.simulateDevicesAddedForTest([fakeUnpairedDevice1]); await waitForListUpdateTimeout(); - Polymer.dom.flush(); assertEquals(2, deviceList().length); assertEquals(2, unpairedDeviceList().length); @@ -312,7 +330,6 @@ [fakeUnpairedDevice1.address, fakeUnpairedDevice2.address]); await waitForListUpdateTimeout(); - Polymer.dom.flush(); assertEquals(0, deviceList().length); assertEquals(0, unpairedDeviceList().length); @@ -327,7 +344,6 @@ [fakeUnpairedDevice1, fakeUnpairedDevice2, fakeUnpairedDevice3]); await waitForListUpdateTimeout(); - Polymer.dom.flush(); assertEquals(3, deviceList().length); assertEquals(3, unpairedDeviceList().length); @@ -341,7 +357,6 @@ bluetoothApi.simulateDeviceUpdatedForTest(updatedDevice); await waitForListUpdateTimeout(); - Polymer.dom.flush(); assertEquals(3, deviceList().length); assertEquals(3, unpairedDeviceList().length); @@ -360,7 +375,6 @@ bluetoothApi.simulateDevicesAddedForTest( [fakePairedDevice1, fakePairedDevice2]); await waitForListUpdateTimeout(); - Polymer.dom.flush(); assertEquals(2, deviceList().length); assertEquals(0, unpairedDeviceList().length); @@ -368,7 +382,6 @@ assertFalse(subpage.$.noUnpairedDevices.hidden); assertTrue(subpage.$.noPairedDevices.hidden); - pairedDeviceIronList.notifyResize(); Polymer.dom.flush(); const devices = @@ -383,7 +396,6 @@ bluetoothApi.simulateDevicesRemovedForTest([fakePairedDevice1.address]); await waitForListUpdateTimeout(); - Polymer.dom.flush(); assertEquals(1, deviceList().length); assertEquals(0, unpairedDeviceList().length); @@ -398,7 +410,6 @@ bluetoothApi.simulateDevicesAddedForTest([fakePairedDevice1]); await waitForListUpdateTimeout(); - Polymer.dom.flush(); assertEquals(2, deviceList().length); assertEquals(0, unpairedDeviceList().length); @@ -414,7 +425,6 @@ [fakePairedDevice1.address, fakePairedDevice2.address]); await waitForListUpdateTimeout(); - Polymer.dom.flush(); assertEquals(0, deviceList().length); assertEquals(0, unpairedDeviceList().length); @@ -429,7 +439,6 @@ [fakePairedDevice1, fakePairedDevice2, fakePairedDevice3]); await waitForListUpdateTimeout(); - Polymer.dom.flush(); assertEquals(3, deviceList().length); assertEquals(0, unpairedDeviceList().length); @@ -443,7 +452,6 @@ bluetoothApi.simulateDeviceUpdatedForTest(updatedDevice); await waitForListUpdateTimeout(); - Polymer.dom.flush(); assertEquals(3, deviceList().length); assertEquals(0, unpairedDeviceList().length); @@ -462,7 +470,6 @@ bluetoothApi.simulateDevicesAddedForTest([fakeUnpairedDevice1]); await waitForListUpdateTimeout(); - Polymer.dom.flush(); assertEquals(1, deviceList().length); assertEquals(1, unpairedDeviceList().length); @@ -477,7 +484,6 @@ bluetoothApi.simulateDeviceUpdatedForTest(nowPairedDevice); await waitForListUpdateTimeout(); - Polymer.dom.flush(); assertEquals(1, deviceList().length); assertEquals(0, unpairedDeviceList().length); @@ -495,7 +501,6 @@ bluetoothApi.simulateDevicesAddedForTest([fakePairedDevice1]); await waitForListUpdateTimeout(); - Polymer.dom.flush(); assertEquals(1, deviceList().length); assertEquals(0, unpairedDeviceList().length); @@ -510,7 +515,6 @@ bluetoothApi.simulateDeviceUpdatedForTest(nowUnpairedDevice); await waitForListUpdateTimeout(); - Polymer.dom.flush(); assertEquals(1, deviceList().length); assertEquals(1, unpairedDeviceList().length); @@ -530,7 +534,6 @@ ]); await waitForListUpdateTimeout(); - Polymer.dom.flush(); assertEquals(4, deviceList().length); assertEquals(2, unpairedDeviceList().length); @@ -538,8 +541,6 @@ assertTrue(subpage.$.noUnpairedDevices.hidden); assertTrue(subpage.$.noPairedDevices.hidden); - pairedDeviceIronList.notifyResize(); - unpairedDeviceIronList.notifyResize(); Polymer.dom.flush(); const unpairedDevices = unpairedDeviceIronList.querySelectorAll( @@ -556,6 +557,26 @@ assertTrue(pairedDevices[1].device.paired); assertFalse(pairedDevices[1].device.connected); }); + + test('Unpaired and paired devices: many devices added', async function() { + bluetoothApi.simulateDevicesAddedForTest(generateFakeDevices(5, 15)); + + await waitForListUpdateTimeout(); + + assertEquals(20, deviceList().length); + assertEquals(15, unpairedDeviceList().length); + assertEquals(5, pairedDeviceList().length); + assertTrue(subpage.$.noUnpairedDevices.hidden); + assertTrue(subpage.$.noPairedDevices.hidden); + + const unpairedDevices = unpairedDeviceIronList.querySelectorAll( + 'bluetooth-device-list-item'); + assertEquals(15, unpairedDevices.length); + + const pairedDevices = + pairedDeviceIronList.querySelectorAll('bluetooth-device-list-item'); + assertEquals(5, pairedDevices.length); + }); }); }); });
diff --git a/chrome/test/remoting/it2me_browsertest.cc b/chrome/test/remoting/it2me_browsertest.cc index 6a9123a..5efd795 100644 --- a/chrome/test/remoting/it2me_browsertest.cc +++ b/chrome/test/remoting/it2me_browsertest.cc
@@ -6,6 +6,7 @@ #include "base/strings/string_number_conversions.h" #include "chrome/test/remoting/remote_desktop_browsertest.h" +#include "chrome/test/remoting/remote_test_helper.h" namespace remoting {
diff --git a/chrome/test/remoting/remote_desktop_browsertest.cc b/chrome/test/remoting/remote_desktop_browsertest.cc index a1f563c1..2cf56e3 100644 --- a/chrome/test/remoting/remote_desktop_browsertest.cc +++ b/chrome/test/remoting/remote_desktop_browsertest.cc
@@ -18,8 +18,10 @@ #include "chrome/browser/ui/extensions/application_launch.h" #include "chrome/browser/ui/webui/signin/login_ui_test_utils.h" #include "chrome/common/chrome_switches.h" +#include "chrome/test/base/ui_test_utils.h" #include "chrome/test/remoting/key_code_conv.h" #include "chrome/test/remoting/page_load_notification_observer.h" +#include "chrome/test/remoting/remote_test_helper.h" #include "chrome/test/remoting/waiter.h" #include "content/public/browser/native_web_keyboard_event.h" #include "content/public/browser/render_view_host.h" @@ -30,11 +32,33 @@ #include "extensions/common/extension.h" #include "extensions/common/extension_set.h" #include "extensions/common/switches.h" +#include "net/dns/mock_host_resolver.h" #include "ui/base/window_open_disposition.h" #include "ui/events/keycodes/dom/keycode_converter.h" +using extensions::Extension; + namespace remoting { +namespace { + +// Command line arguments specific to the chromoting browser tests. +const char kOverrideUserDataDir[] = "override-user-data-dir"; +const char kNoCleanup[] = "no-cleanup"; +const char kNoInstall[] = "no-install"; +const char kWebAppCrx[] = "webapp-crx"; +const char kWebAppUnpacked[] = "webapp-unpacked"; +const char kUserName[] = "username"; +const char kUserPassword[] = "password"; +const char kAccountsFile[] = "accounts-file"; +const char kAccountType[] = "account-type"; +const char kMe2MePin[] = "me2me-pin"; +const char kRemoteHostName[] = "remote-host-name"; +const char kExtensionName[] = "extension-name"; +const char kHttpServer[] = "http-server"; + +} // namespace + RemoteDesktopBrowserTest::RemoteDesktopBrowserTest() : remote_test_helper_(nullptr), extension_(nullptr) { } @@ -712,6 +736,28 @@ observer.Wait(); } +bool RemoteDesktopBrowserTest::ExecuteScriptAndExtractBool( + const std::string& script) { + return RemoteTestHelper::ExecuteScriptAndExtractBool(active_web_contents(), + script); +} + +// Helper to execute a JavaScript code snippet in the active WebContents +// and extract the int result. +int RemoteDesktopBrowserTest::ExecuteScriptAndExtractInt( + const std::string& script) { + return RemoteTestHelper::ExecuteScriptAndExtractInt(active_web_contents(), + script); +} + +// Helper to execute a JavaScript code snippet in the active WebContents +// and extract the string result. +std::string RemoteDesktopBrowserTest::ExecuteScriptAndExtractString( + const std::string& script) { + return RemoteTestHelper::ExecuteScriptAndExtractString(active_web_contents(), + script); +} + // static bool RemoteDesktopBrowserTest::LoadScript( content::WebContents* web_contents, @@ -746,9 +792,9 @@ content::ExecuteScriptAndExtractString(web_contents, script, &result)); // Read in the JSON - base::JSONReader reader; - std::unique_ptr<base::Value> value = - reader.ReadDeprecated(result, base::JSON_ALLOW_TRAILING_COMMAS); + base::Optional<base::Value> value = + base::JSONReader::Read(result, base::JSON_ALLOW_TRAILING_COMMAS); + ASSERT_TRUE(value); // Convert to dictionary base::DictionaryValue* dict_value = NULL; @@ -836,10 +882,9 @@ } bool RemoteDesktopBrowserTest::IsHostOnline(const std::string& host_id) { - ExecuteScript("remoting.hostList.refreshAndDisplay()"); - // Verify the host is online. + // Verify the host is online. std::string element_id = "host_" + host_id; std::string host_div_class = ExecuteScriptAndExtractString( "document.getElementById('" + element_id + "').parentNode.className"); @@ -890,11 +935,12 @@ ASSERT_TRUE(base::ReadFileToString(absolute_path, &accounts_info)); // Get the root dictionary from the input json file contents. - std::unique_ptr<base::Value> root = base::JSONReader::ReadDeprecated( - accounts_info, base::JSON_ALLOW_TRAILING_COMMAS); + base::Optional<base::Value> root = + base::JSONReader::Read(accounts_info, base::JSON_ALLOW_TRAILING_COMMAS); const base::DictionaryValue* root_dict = NULL; - ASSERT_TRUE(root.get() && root->GetAsDictionary(&root_dict)); + ASSERT_TRUE(root); + ASSERT_TRUE(root->GetAsDictionary(&root_dict)); // Now get the dictionary for the specified account type. const base::DictionaryValue* account_dict = NULL;
diff --git a/chrome/test/remoting/remote_desktop_browsertest.h b/chrome/test/remoting/remote_desktop_browsertest.h index 7d58c23a..903b2b1 100644 --- a/chrome/test/remoting/remote_desktop_browsertest.h +++ b/chrome/test/remoting/remote_desktop_browsertest.h
@@ -5,40 +5,22 @@ #ifndef CHROME_TEST_REMOTING_REMOTE_DESKTOP_BROWSERTEST_H_ #define CHROME_TEST_REMOTING_REMOTE_DESKTOP_BROWSERTEST_H_ -#include "base/debug/stack_trace.h" +#include <memory> +#include <string> +#include <vector> + #include "chrome/browser/apps/platform_apps/app_browsertest_util.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/test/base/ui_test_utils.h" -#include "chrome/test/remoting/remote_test_helper.h" -#include "content/public/browser/notification_service.h" -#include "content/public/test/browser_test_utils.h" -#include "net/dns/mock_host_resolver.h" +#include "third_party/blink/public/platform/web_mouse_event.h" #include "ui/events/keycodes/dom/dom_code.h" #include "ui/events/keycodes/dom/dom_key.h" - -namespace { -// Command line arguments specific to the chromoting browser tests. -const char kOverrideUserDataDir[] = "override-user-data-dir"; -const char kNoCleanup[] = "no-cleanup"; -const char kNoInstall[] = "no-install"; -const char kWebAppCrx[] = "webapp-crx"; -const char kWebAppUnpacked[] = "webapp-unpacked"; -const char kUserName[] = "username"; -const char kUserPassword[] = "password"; -const char kAccountsFile[] = "accounts-file"; -const char kAccountType[] = "account-type"; -const char kMe2MePin[] = "me2me-pin"; -const char kRemoteHostName[] = "remote-host-name"; -const char kExtensionName[] = "extension-name"; -const char kHttpServer[] = "http-server"; - -} // namespace - -using extensions::Extension; +#include "ui/events/keycodes/keyboard_codes.h" namespace remoting { +class RemoteTestHelper; + class RemoteDesktopBrowserTest : public extensions::PlatformAppBrowserTest { public: RemoteDesktopBrowserTest(); @@ -82,7 +64,7 @@ // to set up appropriate mocks. // |window_open_disposition| controls where the app will be launched. For v2 // app, the value of |window_open_disposition| will always be NEW_WINDOW. - // Returns the content::Webconetns of the launched app. The lifetime of the + // Returns the content::WebContents of the launched app. The lifetime of the // returned value is managed by LaunchChromotingApp(). content::WebContents* LaunchChromotingApp(bool defer_start); content::WebContents* LaunchChromotingApp( @@ -256,24 +238,15 @@ // Helper to execute a JavaScript code snippet in the active WebContents // and extract the boolean result. - bool ExecuteScriptAndExtractBool(const std::string& script) { - return RemoteTestHelper::ExecuteScriptAndExtractBool( - active_web_contents(), script); - } + bool ExecuteScriptAndExtractBool(const std::string& script); // Helper to execute a JavaScript code snippet in the active WebContents // and extract the int result. - int ExecuteScriptAndExtractInt(const std::string& script) { - return RemoteTestHelper::ExecuteScriptAndExtractInt( - active_web_contents(), script); - } + int ExecuteScriptAndExtractInt(const std::string& script); // Helper to execute a JavaScript code snippet in the active WebContents // and extract the string result. - std::string ExecuteScriptAndExtractString(const std::string& script) { - return RemoteTestHelper::ExecuteScriptAndExtractString( - active_web_contents(), script); - } + std::string ExecuteScriptAndExtractString(const std::string& script); // Helper to load a JavaScript file from |path| and inject it to // current web_content. The variable |path| is relative to the directory of @@ -390,7 +363,7 @@ bool no_cleanup_; bool no_install_; - const Extension* extension_; + const extensions::Extension* extension_; base::FilePath webapp_crx_; base::FilePath webapp_unpacked_; std::string username_;
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc index 472fd8c..9c45f39 100644 --- a/components/autofill/core/browser/personal_data_manager.cc +++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -625,16 +625,19 @@ AutofillProfile* profile = GetProfileByGUID(data_model.guid()); if (profile) { - if (profile->record_type() == AutofillProfile::LOCAL_PROFILE) { - profile->RecordAndLogUse(); - UpdateProfileInDB(*profile, /*enforced=*/true); - } else if (profile->record_type() == AutofillProfile::SERVER_PROFILE) { - profile->RecordAndLogUse(); - // TODO(crbug.com/864519): Update this once addresses support account - // storage, and also use the server database. - database_helper_->GetLocalDatabase()->UpdateServerAddressMetadata( - *profile); - Refresh(); + profile->RecordAndLogUse(); + + switch (profile->record_type()) { + case AutofillProfile::LOCAL_PROFILE: + UpdateProfileInDB(*profile, /*enforced=*/true); + break; + case AutofillProfile::SERVER_PROFILE: + DCHECK(database_helper_->GetServerDatabase()) + << "Recording use of server address without server storage."; + database_helper_->GetServerDatabase()->UpdateServerAddressMetadata( + *profile); + Refresh(); + break; } } } @@ -2355,12 +2358,9 @@ if (!wallet_address->has_converted()) { // Try to merge the server address into a similar local profile, or create // a new local profile if no similar profile is found. - // TODO(crbug.com/864519): Use GetAccountInfoForPaymentsServer instead of - // going to IdentityManager directly. This will be necessary to properly - // support Wallet addresses with Butter. std::string address_guid = MergeServerAddressesIntoProfiles( *wallet_address, local_profiles, app_locale_, - identity_manager_->GetPrimaryAccountInfo().email); + GetAccountInfoForPaymentsServer().email); // Update the map to transfer the billing address relationship from the // server address to the converted/merged local profile.
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc index 4ff7eb6..7258415 100644 --- a/components/autofill/core/browser/personal_data_manager_unittest.cc +++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -66,6 +66,9 @@ namespace autofill { namespace { +const char kPrimaryAccountEmail[] = "syncuser@example.com"; +const char kSyncTransportAccountEmail[] = "transport@example.com"; + enum UserMode { USER_MODE_NORMAL, USER_MODE_INCOGNITO }; const base::Time kArbitraryTime = base::Time::FromDoubleT(25); @@ -202,7 +205,8 @@ personal_data->AddObserver(&personal_data_observer_); AccountInfo account_info; - account_info.email = "sync@account"; + account_info.email = use_sync_transport_mode ? kSyncTransportAccountEmail + : kPrimaryAccountEmail; sync_service_.SetAuthenticatedAccountInfo(account_info); sync_service_.SetIsAuthenticatedAccountPrimary(!use_sync_transport_mode); personal_data->OnSyncServiceInitialized(&sync_service_); @@ -222,7 +226,7 @@ } void EnableWalletCardImport() { - identity_test_env_.MakePrimaryAccountAvailable("syncuser@example.com"); + identity_test_env_.MakePrimaryAccountAvailable(kPrimaryAccountEmail); base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kEnableOfferStoreUnmaskedWalletCards); } @@ -274,7 +278,7 @@ AccountInfo SetActiveSecondaryAccount() { AccountInfo account_info; - account_info.email = "signed_in_account@email.com"; + account_info.email = kSyncTransportAccountEmail; account_info.account_id = "account_id"; sync_service_.SetAuthenticatedAccountInfo(account_info); sync_service_.SetIsAuthenticatedAccountPrimary(false); @@ -337,12 +341,6 @@ return PersonalDataManagerTestBase::TurnOnSyncFeature(personal_data_.get()); } - void EnableWalletCardImport() { - identity_test_env_.MakePrimaryAccountAvailable("syncuser@example.com"); - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableOfferStoreUnmaskedWalletCards); - } - void EnableAutofillProfileCleanup() { personal_data_->is_autofill_profile_cleanup_pending_ = true; } @@ -5427,7 +5425,7 @@ // Make sure that the added address has the email address of the currently // signed-in user. - EXPECT_EQ(base::UTF8ToUTF16("syncuser@example.com"), + EXPECT_EQ(base::UTF8ToUTF16(kPrimaryAccountEmail), profiles[0]->GetRawInfo(EMAIL_ADDRESS)); } @@ -7317,18 +7315,15 @@ } TEST_F(PersonalDataManagerTest, GetAccountInfoForPaymentsServer) { - const std::string kIdentityManagerAccountEmail = "identity_account@email.com"; - const std::string kSyncServiceAccountEmail = "active_sync_account@email.com"; - // Make the IdentityManager return a non-empty AccountInfo when // GetPrimaryAccountInfo() is called. - identity_test_env_.SetPrimaryAccount(kIdentityManagerAccountEmail); + identity_test_env_.SetPrimaryAccount(kPrimaryAccountEmail); ResetPersonalDataManager(USER_MODE_NORMAL); // Make the sync service return a non-empty AccountInfo when // GetAuthenticatedAccountInfo() is called. AccountInfo active_info; - active_info.email = kSyncServiceAccountEmail; + active_info.email = kSyncTransportAccountEmail; sync_service_.SetAuthenticatedAccountInfo(active_info); // The IdentityManager's AccountInfo should be returned by default. @@ -7339,7 +7334,7 @@ /*disabled_features=*/{features::kAutofillEnableAccountWalletStorage, features::kAutofillGetPaymentsIdentityFromSync}); - EXPECT_EQ(kIdentityManagerAccountEmail, + EXPECT_EQ(kPrimaryAccountEmail, personal_data_->GetAccountInfoForPaymentsServer().email); } @@ -7351,7 +7346,7 @@ /*enabled_features=*/{features::kAutofillEnableAccountWalletStorage}, /*disabled_features=*/{features::kAutofillGetPaymentsIdentityFromSync}); - EXPECT_EQ(kSyncServiceAccountEmail, + EXPECT_EQ(kSyncTransportAccountEmail, personal_data_->GetAccountInfoForPaymentsServer().email); } @@ -7363,7 +7358,7 @@ /*enabled_features=*/{features::kAutofillGetPaymentsIdentityFromSync}, /*disabled_features=*/{features::kAutofillEnableAccountWalletStorage}); - EXPECT_EQ(kSyncServiceAccountEmail, + EXPECT_EQ(kSyncTransportAccountEmail, personal_data_->GetAccountInfoForPaymentsServer().email); } } @@ -7396,7 +7391,7 @@ // Set everything up so that the proposition should be shown. // Set an an active secondary account. AccountInfo active_info; - active_info.email = "signed_in_account@email.com"; + active_info.email = kPrimaryAccountEmail; active_info.account_id = "account_id"; sync_service_.SetAuthenticatedAccountInfo(active_info); sync_service_.SetIsAuthenticatedAccountPrimary(false); @@ -7521,7 +7516,7 @@ // Set everything up so that the proposition should be shown on Desktop. // Set an an active secondary account. AccountInfo active_info; - active_info.email = "signed_in_account@email.com"; + active_info.email = kPrimaryAccountEmail; active_info.account_id = "account_id"; sync_service_.SetAuthenticatedAccountInfo(active_info); sync_service_.SetIsAuthenticatedAccountPrimary(false); @@ -7654,7 +7649,7 @@ // Simulate that the user has enabled the sync feature. AccountInfo primary_account_info; - primary_account_info.email = "active_sync_account@email.com"; + primary_account_info.email = kPrimaryAccountEmail; sync_service_.SetAuthenticatedAccountInfo(primary_account_info); sync_service_.SetIsAuthenticatedAccountPrimary(true); // MakePrimaryAccountAvailable is not supported on CrOS. @@ -7688,8 +7683,9 @@ // Make a non-primary account available with both a refresh token and cookie // to be in Sync Transport for Wallet mode. AccountInfo active_info; - active_info.email = "test@gmail.com"; + active_info.email = kSyncTransportAccountEmail; active_info.account_id = "account_id"; + // TODO(treib): This seems wrong, we want a NON-primary account here. identity_test_env_.SetPrimaryAccount(active_info.email); sync_service_.SetAuthenticatedAccountInfo(active_info); sync_service_.SetIsAuthenticatedAccountPrimary(false);
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc index b4d1154..6fe3627 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc +++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
@@ -254,8 +254,7 @@ return false; } -AutofillWalletSyncBridge::StopSyncResponse -AutofillWalletSyncBridge::ApplyStopSyncChanges( +void AutofillWalletSyncBridge::ApplyStopSyncChanges( std::unique_ptr<syncer::MetadataChangeList> delete_metadata_change_list) { // If a metadata change list gets passed in, that means sync is actually // disabled, so we want to delete the payments data. @@ -282,7 +281,6 @@ initial_sync_done_ = false; } - return StopSyncResponse::kModelStillReadyToSync; } void AutofillWalletSyncBridge::GetAllDataForTesting(DataCallback callback) {
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h index 17ea21c9..3f91a3c 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h +++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h
@@ -66,9 +66,8 @@ std::string GetClientTag(const syncer::EntityData& entity_data) override; std::string GetStorageKey(const syncer::EntityData& entity_data) override; bool SupportsIncrementalUpdates() const override; - StopSyncResponse ApplyStopSyncChanges( - std::unique_ptr<syncer::MetadataChangeList> delete_metadata_change_list) - override; + void ApplyStopSyncChanges(std::unique_ptr<syncer::MetadataChangeList> + delete_metadata_change_list) override; // Sends all Wallet Data to the |callback| and keeps all the strings in their // original format (whereas GetAllDataForDebugging() has to make them UTF-8).
diff --git a/components/cast_channel/cast_message_handler_unittest.cc b/components/cast_channel/cast_message_handler_unittest.cc index 89f67e7..cab1fdbe 100644 --- a/components/cast_channel/cast_message_handler_unittest.cc +++ b/components/cast_channel/cast_message_handler_unittest.cc
@@ -21,7 +21,7 @@ #include "testing/gtest/include/gtest/gtest.h" using base::test::IsJson; -using base::test::ParseJson; +using base::test::ParseJsonDeprecated; using testing::_; using testing::AnyNumber; using testing::InSequence; @@ -140,7 +140,7 @@ Result::kOk, handler_.SendSetVolumeRequest( channel_id_, - *ParseJson( + *ParseJsonDeprecated( R"({"sessionId": "theSessionId", "type": "SET_VOLUME"})"), "theSourceId", set_volume_callback_.Get())); } @@ -376,8 +376,9 @@ "requestId": 1, "type": "PLAY", })"; - auto expected = CreateMediaRequest(*ParseJson(expected_body), 1, - "theSourceId", "theDestinationId"); + auto expected = + CreateMediaRequest(*ParseJsonDeprecated(expected_body), 1, + "theSourceId", "theDestinationId"); EXPECT_EQ(expected.namespace_(), message.namespace_()); EXPECT_EQ(expected.source_id(), message.source_id()); EXPECT_EQ(expected.destination_id(), message.destination_id()); @@ -392,8 +393,9 @@ std::string message_str = R"({ "type": "PLAY", })"; - base::Optional<int> request_id = handler_.SendMediaRequest( - channel_id_, *ParseJson(message_str), "theSourceId", "theDestinationId"); + base::Optional<int> request_id = + handler_.SendMediaRequest(channel_id_, *ParseJsonDeprecated(message_str), + "theSourceId", "theDestinationId"); EXPECT_EQ(1, request_id); } @@ -409,8 +411,8 @@ "requestId": 1, "type": "SET_VOLUME", })"; - auto expected = CreateSetVolumeRequest(*ParseJson(expected_body), 1, - "theSourceId"); + auto expected = CreateSetVolumeRequest( + *ParseJsonDeprecated(expected_body), 1, "theSourceId"); EXPECT_EQ(expected.namespace_(), message.namespace_()); EXPECT_EQ(expected.source_id(), message.source_id()); EXPECT_EQ(expected.destination_id(), message.destination_id()); @@ -427,7 +429,7 @@ "type": "SET_VOLUME", })"; EXPECT_EQ(Result::kOk, handler_.SendSetVolumeRequest( - channel_id_, *ParseJson(message_str), + channel_id_, *ParseJsonDeprecated(message_str), "theSourceId", base::DoNothing::Once<Result>())); } @@ -472,7 +474,7 @@ // Handle pending launch session request. handler_.HandleCastInternalMessage(channel_id_, "theSourceId", - "theDestinationId", ParseJson(R"( + "theDestinationId", ParseJsonDeprecated(R"( { "requestId": 1, "type": "RECEIVER_STATUS", @@ -481,29 +483,29 @@ // Handle both pending get app availability requests. handler_.HandleCastInternalMessage(channel_id_, "theSourceId", - "theDestinationId", ParseJson(R"( + "theDestinationId", ParseJsonDeprecated(R"( { "requestId": 2, "availability": {"theAppId": "APP_AVAILABLE"}, })")); // Handle pending set volume request (1 of 2). - handler_.HandleCastInternalMessage(channel_id_, "theSourceId", - "theDestinationId", - ParseJson(R"({"requestId": 3})")); + handler_.HandleCastInternalMessage( + channel_id_, "theSourceId", "theDestinationId", + ParseJsonDeprecated(R"({"requestId": 3})")); // Skip request_id == 4, since it was used by the second get app availability // request. // Handle pending set volume request (2 of 2). - handler_.HandleCastInternalMessage(channel_id_, "theSourceId", - "theDestinationId", - ParseJson(R"({"requestId": 5})")); + handler_.HandleCastInternalMessage( + channel_id_, "theSourceId", "theDestinationId", + ParseJsonDeprecated(R"({"requestId": 5})")); // Handle pending stop session request. - handler_.HandleCastInternalMessage(channel_id_, "theSourceId", - "theDestinationId", - ParseJson(R"({"requestId": 6})")); + handler_.HandleCastInternalMessage( + channel_id_, "theSourceId", "theDestinationId", + ParseJsonDeprecated(R"({"requestId": 6})")); } // Check that set volume requests time out correctly. @@ -515,9 +517,9 @@ "type": "SET_VOLUME", })"; base::MockCallback<ResultCallback> callback; - EXPECT_EQ(Result::kOk, - handler_.SendSetVolumeRequest(channel_id_, *ParseJson(message_str), - "theSourceId", callback.Get())); + EXPECT_EQ(Result::kOk, handler_.SendSetVolumeRequest( + channel_id_, *ParseJsonDeprecated(message_str), + "theSourceId", callback.Get())); EXPECT_CALL(callback, Run(Result::kFailed)); thread_bundle_.FastForwardBy(kRequestTimeout); }
diff --git a/components/cast_channel/cast_message_util_unittest.cc b/components/cast_channel/cast_message_util_unittest.cc index 7bc1027..24e96aea 100644 --- a/components/cast_channel/cast_message_util_unittest.cc +++ b/components/cast_channel/cast_message_util_unittest.cc
@@ -10,7 +10,7 @@ #include "testing/gtest/include/gtest/gtest.h" using base::test::IsJson; -using base::test::ParseJson; +using base::test::ParseJsonDeprecated; namespace cast_channel { @@ -39,7 +39,7 @@ )"; LaunchSessionResponse response = - GetLaunchSessionResponse(*ParseJson(payload)); + GetLaunchSessionResponse(*ParseJsonDeprecated(payload)); EXPECT_EQ(LaunchSessionResponse::Result::kOk, response.result); EXPECT_TRUE(response.receiver_status); } @@ -53,7 +53,7 @@ )"; LaunchSessionResponse response = - GetLaunchSessionResponse(*ParseJson(payload)); + GetLaunchSessionResponse(*ParseJsonDeprecated(payload)); EXPECT_EQ(LaunchSessionResponse::Result::kError, response.result); EXPECT_FALSE(response.receiver_status); } @@ -69,7 +69,7 @@ )"; LaunchSessionResponse response = - GetLaunchSessionResponse(*ParseJson(payload)); + GetLaunchSessionResponse(*ParseJsonDeprecated(payload)); EXPECT_EQ(LaunchSessionResponse::Result::kUnknown, response.result); EXPECT_FALSE(response.receiver_status); } @@ -110,8 +110,8 @@ "requestId": 123, })"; - CastMessage message = CreateMediaRequest(*ParseJson(body), 123, "theSourceId", - "theDestinationId"); + CastMessage message = CreateMediaRequest(*ParseJsonDeprecated(body), 123, + "theSourceId", "theDestinationId"); ASSERT_TRUE(IsCastMessageValid(message)); EXPECT_EQ(kMediaNamespace, message.namespace_()); EXPECT_EQ("theSourceId", message.source_id()); @@ -130,7 +130,7 @@ })"; CastMessage message = - CreateSetVolumeRequest(*ParseJson(body), 123, "theSourceId"); + CreateSetVolumeRequest(*ParseJsonDeprecated(body), 123, "theSourceId"); ASSERT_TRUE(IsCastMessageValid(message)); EXPECT_EQ(kReceiverNamespace, message.namespace_()); EXPECT_EQ("theSourceId", message.source_id());
diff --git a/components/consent_auditor/consent_sync_bridge_impl.cc b/components/consent_auditor/consent_sync_bridge_impl.cc index ea3c403..4338d25f 100644 --- a/components/consent_auditor/consent_sync_bridge_impl.cc +++ b/components/consent_auditor/consent_sync_bridge_impl.cc
@@ -135,8 +135,7 @@ return GetStorageKeyFromSpecifics(entity_data.specifics.user_consent()); } -ModelTypeSyncBridge::StopSyncResponse -ConsentSyncBridgeImpl::ApplyStopSyncChanges( +void ConsentSyncBridgeImpl::ApplyStopSyncChanges( std::unique_ptr<MetadataChangeList> delete_metadata_change_list) { // Sync can only be stopped after initialization. DCHECK(deferred_consents_while_initializing_.empty()); @@ -155,8 +154,6 @@ base::BindOnce(&ConsentSyncBridgeImpl::OnCommit, weak_ptr_factory_.GetWeakPtr())); } - - return StopSyncResponse::kModelStillReadyToSync; } void ConsentSyncBridgeImpl::ReadAllDataAndResubmit() {
diff --git a/components/consent_auditor/consent_sync_bridge_impl.h b/components/consent_auditor/consent_sync_bridge_impl.h index 47132d7..be0ace2 100644 --- a/components/consent_auditor/consent_sync_bridge_impl.h +++ b/components/consent_auditor/consent_sync_bridge_impl.h
@@ -42,9 +42,8 @@ void GetAllDataForDebugging(DataCallback callback) override; std::string GetClientTag(const syncer::EntityData& entity_data) override; std::string GetStorageKey(const syncer::EntityData& entity_data) override; - StopSyncResponse ApplyStopSyncChanges( - std::unique_ptr<syncer::MetadataChangeList> delete_metadata_change_list) - override; + void ApplyStopSyncChanges(std::unique_ptr<syncer::MetadataChangeList> + delete_metadata_change_list) override; // ConsentSyncBridge implementation. void RecordConsent(
diff --git a/components/consent_auditor/consent_sync_bridge_impl_unittest.cc b/components/consent_auditor/consent_sync_bridge_impl_unittest.cc index 750de5c..1e258365 100644 --- a/components/consent_auditor/consent_sync_bridge_impl_unittest.cc +++ b/components/consent_auditor/consent_sync_bridge_impl_unittest.cc
@@ -197,9 +197,7 @@ std::make_unique<UserConsentSpecifics>(user_consent_specifics)); ASSERT_THAT(GetAllData(), SizeIs(1)); - EXPECT_THAT( - bridge()->ApplyStopSyncChanges(WriteBatch::CreateMetadataChangeList()), - Eq(ModelTypeSyncBridge::StopSyncResponse::kModelStillReadyToSync)); + bridge()->ApplyStopSyncChanges(WriteBatch::CreateMetadataChangeList()); // The bridge may asynchronously query the store to choose what to delete. base::RunLoop().RunUntilIdle(); @@ -314,9 +312,7 @@ // User disables sync, hovewer, the consent hasn't been submitted yet. It is // preserved to be submitted when sync is re-enabled. - EXPECT_THAT( - bridge()->ApplyStopSyncChanges(WriteBatch::CreateMetadataChangeList()), - Eq(ModelTypeSyncBridge::StopSyncResponse::kModelStillReadyToSync)); + bridge()->ApplyStopSyncChanges(WriteBatch::CreateMetadataChangeList()); // The bridge may asynchronously query the store to choose what to delete. base::RunLoop().RunUntilIdle(); @@ -385,9 +381,7 @@ std::make_unique<UserConsentSpecifics>(user_consent_specifics)); ASSERT_THAT(GetAllData(), SizeIs(1)); - EXPECT_THAT( - bridge()->ApplyStopSyncChanges(WriteBatch::CreateMetadataChangeList()), - Eq(ModelTypeSyncBridge::StopSyncResponse::kModelStillReadyToSync)); + bridge()->ApplyStopSyncChanges(WriteBatch::CreateMetadataChangeList()); // The bridge may asynchronously query the store to choose what to delete. base::RunLoop().RunUntilIdle(); @@ -404,9 +398,7 @@ EntityChangeList()); base::RunLoop().RunUntilIdle(); - EXPECT_THAT( - bridge()->ApplyStopSyncChanges(WriteBatch::CreateMetadataChangeList()), - Eq(ModelTypeSyncBridge::StopSyncResponse::kModelStillReadyToSync)); + bridge()->ApplyStopSyncChanges(WriteBatch::CreateMetadataChangeList()); base::RunLoop().RunUntilIdle(); // This time their consent should be resubmitted, because it is for the same
diff --git a/components/cronet/url_request_context_config_unittest.cc b/components/cronet/url_request_context_config_unittest.cc index 132fd13..cb62f84 100644 --- a/components/cronet/url_request_context_config_unittest.cc +++ b/components/cronet/url_request_context_config_unittest.cc
@@ -32,10 +32,6 @@ namespace { -base::Value ParseJson(base::StringPiece json) { - return std::move(*base::test::ParseJson(json)); -} - std::string WrapJsonHeader(base::StringPiece value) { std::string result; result.reserve(value.size() + 2); @@ -48,8 +44,8 @@ // Returns whether two JSON-encoded headers contain the same content, ignoring // irrelevant encoding issues like whitespace and map element ordering. bool JsonHeaderEquals(base::StringPiece expected, base::StringPiece actual) { - return ParseJson(WrapJsonHeader(expected)) == - ParseJson(WrapJsonHeader(actual)); + return base::test::ParseJson(WrapJsonHeader(expected)) == + base::test::ParseJson(WrapJsonHeader(actual)); } } // namespace @@ -71,7 +67,7 @@ options.SetPath({"AsyncDNS", "enable"}, base::Value(true)); options.SetPath({"NetworkErrorLogging", "enable"}, base::Value(true)); options.SetPath({"NetworkErrorLogging", "preloaded_report_to_headers"}, - ParseJson(R"json( + base::test::ParseJson(R"json( [ { "origin": "https://test-origin/", @@ -119,7 +115,7 @@ ] )json")); options.SetPath({"NetworkErrorLogging", "preloaded_nel_headers"}, - ParseJson(R"json( + base::test::ParseJson(R"json( [ { "origin": "https://test-origin/",
diff --git a/components/exo/surface.cc b/components/exo/surface.cc index 1817c3e3..ec94dbf 100644 --- a/components/exo/surface.cc +++ b/components/exo/surface.cc
@@ -942,13 +942,15 @@ viz::TextureDrawQuad* texture_quad = render_pass->CreateAndAppendDrawQuad<viz::TextureDrawQuad>(); float vertex_opacity[4] = {1.0, 1.0, 1.0, 1.0}; - + SkColor background_color = SK_ColorTRANSPARENT; + if (current_resource_has_alpha_ && are_contents_opaque) + background_color = SK_ColorBLACK; // Avoid writing alpha < 1 texture_quad->SetNew( - quad_state, quad_rect, quad_rect, !are_contents_opaque, - current_resource_.id, true /* premultiplied_alpha */, - uv_crop.origin(), uv_crop.bottom_right(), - SK_ColorTRANSPARENT /* background_color */, vertex_opacity, - false /* y_flipped */, false /* nearest_neighbor */, + quad_state, quad_rect, quad_rect, + /* needs_blending=*/!are_contents_opaque, current_resource_.id, + /* premultiplied_alpha=*/true, uv_crop.origin(), + uv_crop.bottom_right(), background_color, vertex_opacity, + /* y_flipped=*/false, /* nearest_neighbor=*/false, state_.only_visible_on_secure_output, ui::ProtectedVideoType::kClear); if (current_resource_.is_overlay_candidate) texture_quad->set_resource_size_in_pixels(current_resource_.size);
diff --git a/components/exo/surface_unittest.cc b/components/exo/surface_unittest.cc index 3670188..7e1cecc 100644 --- a/components/exo/surface_unittest.cc +++ b/components/exo/surface_unittest.cc
@@ -221,9 +221,11 @@ GetFrameFromSurface(shell_surface.get()); ASSERT_EQ(1u, frame.render_pass_list.size()); ASSERT_EQ(1u, frame.render_pass_list.back()->quad_list.size()); - EXPECT_FALSE(frame.render_pass_list.back() - ->quad_list.back() - ->ShouldDrawWithBlending()); + auto* texture_draw_quad = viz::TextureDrawQuad::MaterialCast( + frame.render_pass_list.back()->quad_list.back()); + + EXPECT_FALSE(texture_draw_quad->ShouldDrawWithBlending()); + EXPECT_EQ(SK_ColorBLACK, texture_draw_quad->background_color); EXPECT_EQ(ToPixel(gfx::Rect(0, 0, 1, 1)), frame.render_pass_list.back()->damage_rect); } @@ -238,9 +240,10 @@ GetFrameFromSurface(shell_surface.get()); ASSERT_EQ(1u, frame.render_pass_list.size()); ASSERT_EQ(1u, frame.render_pass_list.back()->quad_list.size()); - EXPECT_TRUE(frame.render_pass_list.back() - ->quad_list.back() - ->ShouldDrawWithBlending()); + auto* texture_draw_quad = viz::TextureDrawQuad::MaterialCast( + frame.render_pass_list.back()->quad_list.back()); + EXPECT_TRUE(texture_draw_quad->ShouldDrawWithBlending()); + EXPECT_EQ(SK_ColorTRANSPARENT, texture_draw_quad->background_color); EXPECT_EQ(ToPixel(gfx::Rect(0, 0, 1, 1)), frame.render_pass_list.back()->damage_rect); }
diff --git a/components/keyed_service/content/browser_context_dependency_manager.cc b/components/keyed_service/content/browser_context_dependency_manager.cc index e9cf9d39..3179ba48 100644 --- a/components/keyed_service/content/browser_context_dependency_manager.cc +++ b/components/keyed_service/content/browser_context_dependency_manager.cc
@@ -85,7 +85,7 @@ #ifndef NDEBUG void BrowserContextDependencyManager::DumpContextDependencies( - base::SupportsUserData* context) const { + void* context) const { // Whenever we try to build a destruction ordering, we should also dump a // dependency graph to "/path/to/context/context-dependencies.dot". if (base::CommandLine::ForCurrentProcess()->HasSwitch(
diff --git a/components/keyed_service/content/browser_context_dependency_manager.h b/components/keyed_service/content/browser_context_dependency_manager.h index 8320e2b..bf434adec 100644 --- a/components/keyed_service/content/browser_context_dependency_manager.h +++ b/components/keyed_service/content/browser_context_dependency_manager.h
@@ -96,7 +96,7 @@ #ifndef NDEBUG // DependencyManager: - void DumpContextDependencies(base::SupportsUserData* context) const final; + void DumpContextDependencies(void* context) const final; #endif // NDEBUG // A list of callbacks to call just before executing
diff --git a/components/keyed_service/content/browser_context_keyed_base_factory.cc b/components/keyed_service/content/browser_context_keyed_base_factory.cc index 79d1ed0..8076ee3d 100644 --- a/components/keyed_service/content/browser_context_keyed_base_factory.cc +++ b/components/keyed_service/content/browser_context_keyed_base_factory.cc
@@ -42,8 +42,7 @@ KeyedServiceBaseFactory::ContextDestroyed(context); } -base::SupportsUserData* BrowserContextKeyedBaseFactory::GetContextToUse( - base::SupportsUserData* context) const { +void* BrowserContextKeyedBaseFactory::GetContextToUse(void* context) const { AssertContextWasntDestroyed(context); return GetBrowserContextToUse(static_cast<content::BrowserContext*>(context)); } @@ -52,13 +51,11 @@ return ServiceIsCreatedWithBrowserContext(); } -void BrowserContextKeyedBaseFactory::ContextShutdown( - base::SupportsUserData* context) { +void BrowserContextKeyedBaseFactory::ContextShutdown(void* context) { BrowserContextShutdown(static_cast<content::BrowserContext*>(context)); } -void BrowserContextKeyedBaseFactory::ContextDestroyed( - base::SupportsUserData* context) { +void BrowserContextKeyedBaseFactory::ContextDestroyed(void* context) { BrowserContextDestroyed(static_cast<content::BrowserContext*>(context)); } @@ -67,17 +64,14 @@ RegisterProfilePrefs(registry); } -void BrowserContextKeyedBaseFactory::SetEmptyTestingFactory( - base::SupportsUserData* context) { +void BrowserContextKeyedBaseFactory::SetEmptyTestingFactory(void* context) { SetEmptyTestingFactory(static_cast<content::BrowserContext*>(context)); } -bool BrowserContextKeyedBaseFactory::HasTestingFactory( - base::SupportsUserData* context) { +bool BrowserContextKeyedBaseFactory::HasTestingFactory(void* context) { return HasTestingFactory(static_cast<content::BrowserContext*>(context)); } -void BrowserContextKeyedBaseFactory::CreateServiceNow( - base::SupportsUserData* context) { +void BrowserContextKeyedBaseFactory::CreateServiceNow(void* context) { CreateServiceNow(static_cast<content::BrowserContext*>(context)); }
diff --git a/components/keyed_service/content/browser_context_keyed_base_factory.h b/components/keyed_service/content/browser_context_keyed_base_factory.h index 940fad4..69556d8 100644 --- a/components/keyed_service/content/browser_context_keyed_base_factory.h +++ b/components/keyed_service/content/browser_context_keyed_base_factory.h
@@ -94,15 +94,14 @@ virtual void CreateServiceNow(content::BrowserContext* context) = 0; // KeyedServiceBaseFactory: - base::SupportsUserData* GetContextToUse( - base::SupportsUserData* context) const final; + void* GetContextToUse(void* context) const final; bool ServiceIsCreatedWithContext() const final; - void ContextShutdown(base::SupportsUserData* context) final; - void ContextDestroyed(base::SupportsUserData* context) final; + void ContextShutdown(void* context) final; + void ContextDestroyed(void* context) final; void RegisterPrefs(user_prefs::PrefRegistrySyncable* registry) final; - void SetEmptyTestingFactory(base::SupportsUserData* context) final; - bool HasTestingFactory(base::SupportsUserData* context) final; - void CreateServiceNow(base::SupportsUserData* context) final; + void SetEmptyTestingFactory(void* context) final; + bool HasTestingFactory(void* context) final; + void CreateServiceNow(void* context) final; }; #endif // COMPONENTS_KEYED_SERVICE_CONTENT_BROWSER_CONTEXT_KEYED_BASE_FACTORY_H_
diff --git a/components/keyed_service/content/browser_context_keyed_service_factory.cc b/components/keyed_service/content/browser_context_keyed_service_factory.cc index 21e9611..67cbd36 100644 --- a/components/keyed_service/content/browser_context_keyed_service_factory.cc +++ b/components/keyed_service/content/browser_context_keyed_service_factory.cc
@@ -4,6 +4,8 @@ #include "components/keyed_service/content/browser_context_keyed_service_factory.h" +#include <utility> + #include "base/bind.h" #include "base/logging.h" #include "base/memory/ptr_util.h" @@ -18,8 +20,7 @@ KeyedServiceFactory::TestingFactory wrapped_factory; if (testing_factory) { wrapped_factory = base::BindRepeating( - [](const TestingFactory& testing_factory, - base::SupportsUserData* context) { + [](const TestingFactory& testing_factory, void* context) { return testing_factory.Run( static_cast<content::BrowserContext*>(context)); }, @@ -33,13 +34,13 @@ TestingFactory testing_factory) { DCHECK(testing_factory); return KeyedServiceFactory::SetTestingFactoryAndUse( - context, base::BindRepeating( - [](const TestingFactory& testing_factory, - base::SupportsUserData* context) { - return testing_factory.Run( - static_cast<content::BrowserContext*>(context)); - }, - std::move(testing_factory))); + context, nullptr /* side_parameter */, + base::BindRepeating( + [](const TestingFactory& testing_factory, void* context) { + return testing_factory.Run( + static_cast<content::BrowserContext*>(context)); + }, + std::move(testing_factory))); } BrowserContextKeyedServiceFactory::BrowserContextKeyedServiceFactory( @@ -54,7 +55,8 @@ KeyedService* BrowserContextKeyedServiceFactory::GetServiceForBrowserContext( content::BrowserContext* context, bool create) { - return KeyedServiceFactory::GetServiceForContext(context, create); + return KeyedServiceFactory::GetServiceForContext( + context, nullptr /* side_parameter */, create); } content::BrowserContext* @@ -91,20 +93,19 @@ std::unique_ptr<KeyedService> BrowserContextKeyedServiceFactory::BuildServiceInstanceFor( - base::SupportsUserData* context) const { + void* context, + void* side_parameter) const { // TODO(isherman): The wrapped BuildServiceInstanceFor() should return a // scoped_ptr as well. return base::WrapUnique( BuildServiceInstanceFor(static_cast<content::BrowserContext*>(context))); } -bool BrowserContextKeyedServiceFactory::IsOffTheRecord( - base::SupportsUserData* context) const { +bool BrowserContextKeyedServiceFactory::IsOffTheRecord(void* context) const { return static_cast<content::BrowserContext*>(context)->IsOffTheRecord(); } -base::SupportsUserData* BrowserContextKeyedServiceFactory::GetContextToUse( - base::SupportsUserData* context) const { +void* BrowserContextKeyedServiceFactory::GetContextToUse(void* context) const { AssertContextWasntDestroyed(context); return GetBrowserContextToUse(static_cast<content::BrowserContext*>(context)); } @@ -113,13 +114,11 @@ return ServiceIsCreatedWithBrowserContext(); } -void BrowserContextKeyedServiceFactory::ContextShutdown( - base::SupportsUserData* context) { +void BrowserContextKeyedServiceFactory::ContextShutdown(void* context) { BrowserContextShutdown(static_cast<content::BrowserContext*>(context)); } -void BrowserContextKeyedServiceFactory::ContextDestroyed( - base::SupportsUserData* context) { +void BrowserContextKeyedServiceFactory::ContextDestroyed(void* context) { BrowserContextDestroyed(static_cast<content::BrowserContext*>(context)); } @@ -127,3 +126,8 @@ user_prefs::PrefRegistrySyncable* registry) { RegisterProfilePrefs(registry); } + +void BrowserContextKeyedServiceFactory::CreateServiceNow(void* context) { + KeyedServiceFactory::GetServiceForContext(context, + nullptr /* side_parameter */, true); +}
diff --git a/components/keyed_service/content/browser_context_keyed_service_factory.h b/components/keyed_service/content/browser_context_keyed_service_factory.h index ab605769..e6ec079b 100644 --- a/components/keyed_service/content/browser_context_keyed_service_factory.h +++ b/components/keyed_service/content/browser_context_keyed_service_factory.h
@@ -122,16 +122,17 @@ // KeyedServiceFactory: std::unique_ptr<KeyedService> BuildServiceInstanceFor( - base::SupportsUserData* context) const final; - bool IsOffTheRecord(base::SupportsUserData* context) const final; + void* context, + void* side_parameter) const final; + bool IsOffTheRecord(void* context) const final; // KeyedServiceBaseFactory: - base::SupportsUserData* GetContextToUse( - base::SupportsUserData* context) const final; + void* GetContextToUse(void* context) const final; bool ServiceIsCreatedWithContext() const final; - void ContextShutdown(base::SupportsUserData* context) final; - void ContextDestroyed(base::SupportsUserData* context) final; + void ContextShutdown(void* context) final; + void ContextDestroyed(void* context) final; void RegisterPrefs(user_prefs::PrefRegistrySyncable* registry) final; + void CreateServiceNow(void* context) final; DISALLOW_COPY_AND_ASSIGN(BrowserContextKeyedServiceFactory); };
diff --git a/components/keyed_service/content/refcounted_browser_context_keyed_service_factory.cc b/components/keyed_service/content/refcounted_browser_context_keyed_service_factory.cc index cab1652..e6095171 100644 --- a/components/keyed_service/content/refcounted_browser_context_keyed_service_factory.cc +++ b/components/keyed_service/content/refcounted_browser_context_keyed_service_factory.cc
@@ -16,8 +16,7 @@ RefcountedKeyedServiceFactory::TestingFactory wrapped_factory; if (testing_factory) { wrapped_factory = base::BindRepeating( - [](const TestingFactory& testing_factory, - base::SupportsUserData* context) { + [](const TestingFactory& testing_factory, void* context) { return testing_factory.Run( static_cast<content::BrowserContext*>(context)); }, @@ -33,13 +32,13 @@ TestingFactory testing_factory) { DCHECK(testing_factory); return RefcountedKeyedServiceFactory::SetTestingFactoryAndUse( - context, base::BindRepeating( - [](const TestingFactory& testing_factory, - base::SupportsUserData* context) { - return testing_factory.Run( - static_cast<content::BrowserContext*>(context)); - }, - std::move(testing_factory))); + context, nullptr /* side_parameter */, + base::BindRepeating( + [](const TestingFactory& testing_factory, void* context) { + return testing_factory.Run( + static_cast<content::BrowserContext*>(context)); + }, + std::move(testing_factory))); } RefcountedBrowserContextKeyedServiceFactory:: @@ -57,7 +56,8 @@ RefcountedBrowserContextKeyedServiceFactory::GetServiceForBrowserContext( content::BrowserContext* context, bool create) { - return RefcountedKeyedServiceFactory::GetServiceForContext(context, create); + return RefcountedKeyedServiceFactory::GetServiceForContext( + context, nullptr /* side_parameter */, create); } content::BrowserContext* @@ -95,19 +95,19 @@ scoped_refptr<RefcountedKeyedService> RefcountedBrowserContextKeyedServiceFactory::BuildServiceInstanceFor( - base::SupportsUserData* context) const { + void* context, + void* side_parameter) const { return BuildServiceInstanceFor( static_cast<content::BrowserContext*>(context)); } bool RefcountedBrowserContextKeyedServiceFactory::IsOffTheRecord( - base::SupportsUserData* context) const { + void* context) const { return static_cast<content::BrowserContext*>(context)->IsOffTheRecord(); } -base::SupportsUserData* -RefcountedBrowserContextKeyedServiceFactory::GetContextToUse( - base::SupportsUserData* context) const { +void* RefcountedBrowserContextKeyedServiceFactory::GetContextToUse( + void* context) const { AssertContextWasntDestroyed(context); return GetBrowserContextToUse(static_cast<content::BrowserContext*>(context)); } @@ -118,12 +118,12 @@ } void RefcountedBrowserContextKeyedServiceFactory::ContextShutdown( - base::SupportsUserData* context) { + void* context) { BrowserContextShutdown(static_cast<content::BrowserContext*>(context)); } void RefcountedBrowserContextKeyedServiceFactory::ContextDestroyed( - base::SupportsUserData* context) { + void* context) { BrowserContextDestroyed(static_cast<content::BrowserContext*>(context)); }
diff --git a/components/keyed_service/content/refcounted_browser_context_keyed_service_factory.h b/components/keyed_service/content/refcounted_browser_context_keyed_service_factory.h index 3d2deb80..0e9090cc 100644 --- a/components/keyed_service/content/refcounted_browser_context_keyed_service_factory.h +++ b/components/keyed_service/content/refcounted_browser_context_keyed_service_factory.h
@@ -127,15 +127,15 @@ // RefcountedKeyedServiceFactory: scoped_refptr<RefcountedKeyedService> BuildServiceInstanceFor( - base::SupportsUserData* context) const final; - bool IsOffTheRecord(base::SupportsUserData* context) const final; + void* context, + void* side_parameter) const final; + bool IsOffTheRecord(void* context) const final; // KeyedServiceBaseFactory: - base::SupportsUserData* GetContextToUse( - base::SupportsUserData* context) const final; + void* GetContextToUse(void* context) const final; bool ServiceIsCreatedWithContext() const final; - void ContextShutdown(base::SupportsUserData* context) final; - void ContextDestroyed(base::SupportsUserData* context) final; + void ContextShutdown(void* context) final; + void ContextDestroyed(void* context) final; void RegisterPrefs(user_prefs::PrefRegistrySyncable* registry) final; DISALLOW_COPY_AND_ASSIGN(RefcountedBrowserContextKeyedServiceFactory);
diff --git a/components/keyed_service/core/dependency_manager.cc b/components/keyed_service/core/dependency_manager.cc index a55ca5c..9395b86 100644 --- a/components/keyed_service/core/dependency_manager.cc +++ b/components/keyed_service/core/dependency_manager.cc
@@ -35,7 +35,7 @@ } void DependencyManager::RegisterPrefsForServices( - base::SupportsUserData* context, + void* context, user_prefs::PrefRegistrySyncable* pref_registry) { std::vector<DependencyNode*> construction_order; if (!dependency_graph_.GetConstructionOrder(&construction_order)) { @@ -49,7 +49,7 @@ } } -void DependencyManager::CreateContextServices(base::SupportsUserData* context, +void DependencyManager::CreateContextServices(void* context, bool is_testing_context) { MarkContextLive(context); @@ -74,8 +74,7 @@ } } -void DependencyManager::DestroyContextServices( - base::SupportsUserData* context) { +void DependencyManager::DestroyContextServices(void* context) { std::vector<DependencyNode*> destruction_order; if (!dependency_graph_.GetDestructionOrder(&destruction_order)) { NOTREACHED(); @@ -101,8 +100,7 @@ } } -void DependencyManager::AssertContextWasntDestroyed( - base::SupportsUserData* context) const { +void DependencyManager::AssertContextWasntDestroyed(void* context) const { if (dead_context_pointers_.find(context) != dead_context_pointers_.end()) { #if DCHECK_IS_ON() NOTREACHED() << "Attempted to access a context that was ShutDown(). " @@ -116,7 +114,7 @@ } } -void DependencyManager::MarkContextLive(base::SupportsUserData* context) { +void DependencyManager::MarkContextLive(void* context) { dead_context_pointers_.erase(context); }
diff --git a/components/keyed_service/core/dependency_manager.h b/components/keyed_service/core/dependency_manager.h index 32c1f64..0f881a9 100644 --- a/components/keyed_service/core/dependency_manager.h +++ b/components/keyed_service/core/dependency_manager.h
@@ -15,7 +15,6 @@ namespace base { class FilePath; -class SupportsUserData; } namespace user_prefs { @@ -42,7 +41,7 @@ // Registers preferences for all services via |registry| associated with // |context| (the association is managed by the embedder). The |context| // is used as a key to prevent multiple registration during tests. - void RegisterPrefsForServices(base::SupportsUserData* context, + void RegisterPrefsForServices(void* context, user_prefs::PrefRegistrySyncable* registry); // Called upon creation of |context| to create services that want to be @@ -55,24 +54,23 @@ // // If |is_testing_context| then the service will not be started unless the // method KeyedServiceBaseFactory::ServiceIsNULLWhileTesting() return false. - void CreateContextServices(base::SupportsUserData* context, - bool is_testing_context); + void CreateContextServices(void* context, bool is_testing_context); // Called upon destruction of |context| to destroy all services associated // with it. - void DestroyContextServices(base::SupportsUserData* context); + void DestroyContextServices(void* context); // Runtime assertion called as a part of GetServiceForContext() to check if // |context| is considered stale. This will NOTREACHED() or // base::debug::DumpWithoutCrashing() depending on the DCHECK_IS_ON() value. - void AssertContextWasntDestroyed(base::SupportsUserData* context) const; + void AssertContextWasntDestroyed(void* context) const; // Marks |context| as live (i.e., not stale). This method can be called as a // safeguard against |AssertContextWasntDestroyed()| checks going off due to // |context| aliasing an instance from a prior construction (i.e., 0xWhatever // might be created, be destroyed, and then a new object might be created at // 0xWhatever). - void MarkContextLive(base::SupportsUserData* context); + void MarkContextLive(void* context); #ifndef NDEBUG // Dumps service dependency graph as a Graphviz dot file |dot_file| with a @@ -86,8 +84,7 @@ #ifndef NDEBUG // Hook for subclass to dump the dependency graph of service for |context|. - virtual void DumpContextDependencies( - base::SupportsUserData* context) const = 0; + virtual void DumpContextDependencies(void* context) const = 0; #endif // NDEBUG DependencyGraph dependency_graph_; @@ -96,7 +93,7 @@ // These pointers are most likely invalid, but we keep track of their // locations in memory so we can nicely assert if we're asked to do anything // with them. - std::set<base::SupportsUserData*> dead_context_pointers_; + std::set<void*> dead_context_pointers_; }; #endif // COMPONENTS_KEYED_SERVICE_CORE_DEPENDENCY_MANAGER_H_
diff --git a/components/keyed_service/core/keyed_service_base_factory.cc b/components/keyed_service/core/keyed_service_base_factory.cc index b9cf09c..fe02e58 100644 --- a/components/keyed_service/core/keyed_service_base_factory.cc +++ b/components/keyed_service/core/keyed_service_base_factory.cc
@@ -25,15 +25,14 @@ dependency_manager_->AddEdge(rhs, this); } -void KeyedServiceBaseFactory::AssertContextWasntDestroyed( - base::SupportsUserData* context) const { +void KeyedServiceBaseFactory::AssertContextWasntDestroyed(void* context) const { // TODO(crbug.com/701326): We should DCHECK(CalledOnValidThread()) here, but // currently some code doesn't do service getting on the main thread. // This needs to be fixed and DCHECK should be restored here. dependency_manager_->AssertContextWasntDestroyed(context); } -void KeyedServiceBaseFactory::MarkContextLive(base::SupportsUserData* context) { +void KeyedServiceBaseFactory::MarkContextLive(void* context) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); dependency_manager_->MarkContextLive(context); } @@ -46,8 +45,7 @@ return false; } -void KeyedServiceBaseFactory::ContextDestroyed( - base::SupportsUserData* context) { +void KeyedServiceBaseFactory::ContextDestroyed(void* context) { // While object destruction can be customized in ways where the object is // only dereferenced, this still must run on the UI thread. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/components/keyed_service/core/keyed_service_base_factory.h b/components/keyed_service/core/keyed_service_base_factory.h index 612395e2b..f603dcc 100644 --- a/components/keyed_service/core/keyed_service_base_factory.h +++ b/components/keyed_service/core/keyed_service_base_factory.h
@@ -13,17 +13,13 @@ class DependencyManager; -namespace base { -class SupportsUserData; -} - namespace user_prefs { class PrefRegistrySyncable; } -// Base class for factories that take a base::SupportsUserData and return some -// service. Not for direct usage, instead use descendent classes that deal with -// more specific context objects. +// Base class for factories that take an opaque pointer and return some service. +// Not for direct usage, instead use descendent classes that deal with more +// specific context objects. // // This object describes general dependency management between factories while // direct subclasses react to lifecycle events and implement memory management. @@ -42,18 +38,17 @@ // Runtime assertion to check if |context| is considered stale. Should be used // by subclasses when accessing |context|. - void AssertContextWasntDestroyed(base::SupportsUserData* context) const; + void AssertContextWasntDestroyed(void* context) const; // Marks |context| as live (i.e., not stale). This method can be called as a // safeguard against |AssertContextWasntDestroyed()| checks going off due to // |context| aliasing an instance from a prior construction (i.e., 0xWhatever // might be created, be destroyed, and then a new object might be created at // 0xWhatever). - void MarkContextLive(base::SupportsUserData* context); + void MarkContextLive(void* context); // Finds which context (if any) to use. - virtual base::SupportsUserData* GetContextToUse( - base::SupportsUserData* context) const = 0; + virtual void* GetContextToUse(void* context) const = 0; // By default, instance of a service are created lazily when GetForContext() // is called by the subclass. Some services need to be created as soon as the @@ -76,8 +71,8 @@ // service with GetForContext() will NOTREACHED() and code should delete/ // deref/do other final memory management during this phase. The base class // method *must* be called as the last thing. - virtual void ContextShutdown(base::SupportsUserData* context) = 0; - virtual void ContextDestroyed(base::SupportsUserData* context); + virtual void ContextShutdown(void* context) = 0; + virtual void ContextDestroyed(void* context); SEQUENCE_CHECKER(sequence_checker_); @@ -94,13 +89,13 @@ // Used by DependencyManager to disable creation of the service when the // method ServiceIsNULLWhileTesting() returns true. - virtual void SetEmptyTestingFactory(base::SupportsUserData* context) = 0; + virtual void SetEmptyTestingFactory(void* context) = 0; // Returns true if a testing factory function has been set for |context|. - virtual bool HasTestingFactory(base::SupportsUserData* context) = 0; + virtual bool HasTestingFactory(void* context) = 0; // Create the service associated with |context|. - virtual void CreateServiceNow(base::SupportsUserData* context) = 0; + virtual void CreateServiceNow(void* context) = 0; // A static string passed in to the constructor. Should be unique across all // services.
diff --git a/components/keyed_service/core/keyed_service_factory.cc b/components/keyed_service/core/keyed_service_factory.cc index f3629a59..f490446 100644 --- a/components/keyed_service/core/keyed_service_factory.cc +++ b/components/keyed_service/core/keyed_service_factory.cc
@@ -21,7 +21,7 @@ DCHECK(mapping_.empty()); } -void KeyedServiceFactory::SetTestingFactory(base::SupportsUserData* context, +void KeyedServiceFactory::SetTestingFactory(void* context, TestingFactory testing_factory) { // Ensure that |context| is not marked as stale (e.g., due to it aliasing an // instance that was destroyed in an earlier test) in order to avoid accesses @@ -39,16 +39,17 @@ } KeyedService* KeyedServiceFactory::SetTestingFactoryAndUse( - base::SupportsUserData* context, + void* context, + void* side_parameter, TestingFactory testing_factory) { DCHECK(testing_factory); SetTestingFactory(context, std::move(testing_factory)); - return GetServiceForContext(context, true); + return GetServiceForContext(context, side_parameter, true); } -KeyedService* KeyedServiceFactory::GetServiceForContext( - base::SupportsUserData* context, - bool create) { +KeyedService* KeyedServiceFactory::GetServiceForContext(void* context, + void* side_parameter, + bool create) { TRACE_EVENT1("browser,startup", "KeyedServiceFactory::GetServiceForContext", "service_name", name()); context = GetContextToUse(context); @@ -75,33 +76,33 @@ service = factory_iterator->second.Run(context); } } else { - service = BuildServiceInstanceFor(context); + service = BuildServiceInstanceFor(context, side_parameter); } return Associate(context, std::move(service)); } KeyedService* KeyedServiceFactory::Associate( - base::SupportsUserData* context, + void* context, std::unique_ptr<KeyedService> service) { DCHECK(!base::ContainsKey(mapping_, context)); auto iterator = mapping_.emplace(context, std::move(service)).first; return iterator->second.get(); } -void KeyedServiceFactory::Disassociate(base::SupportsUserData* context) { +void KeyedServiceFactory::Disassociate(void* context) { auto iterator = mapping_.find(context); if (iterator != mapping_.end()) mapping_.erase(iterator); } -void KeyedServiceFactory::ContextShutdown(base::SupportsUserData* context) { +void KeyedServiceFactory::ContextShutdown(void* context) { auto iterator = mapping_.find(context); if (iterator != mapping_.end() && iterator->second) iterator->second->Shutdown(); } -void KeyedServiceFactory::ContextDestroyed(base::SupportsUserData* context) { +void KeyedServiceFactory::ContextDestroyed(void* context) { Disassociate(context); // For unit tests, we also remove the factory function both so we don't @@ -113,15 +114,10 @@ KeyedServiceBaseFactory::ContextDestroyed(context); } -void KeyedServiceFactory::SetEmptyTestingFactory( - base::SupportsUserData* context) { +void KeyedServiceFactory::SetEmptyTestingFactory(void* context) { SetTestingFactory(context, TestingFactory()); } -bool KeyedServiceFactory::HasTestingFactory(base::SupportsUserData* context) { +bool KeyedServiceFactory::HasTestingFactory(void* context) { return base::ContainsKey(testing_factories_, context); } - -void KeyedServiceFactory::CreateServiceNow(base::SupportsUserData* context) { - GetServiceForContext(context, true); -}
diff --git a/components/keyed_service/core/keyed_service_factory.h b/components/keyed_service/core/keyed_service_factory.h index cc82b15..b6d8e300 100644 --- a/components/keyed_service/core/keyed_service_factory.h +++ b/components/keyed_service/core/keyed_service_factory.h
@@ -17,9 +17,9 @@ class DependencyManager; class KeyedService; -// Base class for Factories that take a base::SupportsUserData object and return -// some service on a one-to-one mapping. Each concrete factory that derives from -// this class *must* be a Singleton (only unit tests don't do that). +// Base class for Factories that take an opaque pointer and return some service +// on a one-to-one mapping. Each concrete factory that derives from this class +// *must* be a Singleton (only unit tests don't do that). // // We do this because services depend on each other and we need to control // shutdown/destruction order. In each derived classes' constructors, the @@ -33,61 +33,64 @@ // A callback that supplies the instance of a KeyedService for a given // |context|. This is used primarily for testing, where we want to feed // a specific test double into the KeyedServiceFactory system. - using TestingFactory = base::RepeatingCallback<std::unique_ptr<KeyedService>( - base::SupportsUserData* context)>; + using TestingFactory = + base::RepeatingCallback<std::unique_ptr<KeyedService>(void* context)>; // Associates |testing_factory| with |context| so that |testing_factory| is // used to create the KeyedService when requested. |testing_factory| can be // empty to signal that KeyedService should be null. Multiple calls to // SetTestingFactory() are allowed; previous services will be shut down. - void SetTestingFactory(base::SupportsUserData* context, - TestingFactory testing_factory); + void SetTestingFactory(void* context, TestingFactory testing_factory); // Associates |testing_factory| with |context| and immediately returns the // created KeyedService. Since the factory will be used immediately, it may // not be empty. - KeyedService* SetTestingFactoryAndUse(base::SupportsUserData* context, + KeyedService* SetTestingFactoryAndUse(void* context, + void* side_parameter, TestingFactory testing_factory); // Common implementation that maps |context| to some service object. Deals // with incognito contexts per subclass instructions with GetContextToUse() // method on the base. If |create| is true, the service will be created - // using BuildServiceInstanceFor() if it doesn't already exist. - KeyedService* GetServiceForContext(base::SupportsUserData* context, + // using BuildServiceInstanceFor() if it doesn't already exist. Subclasses + // could pass |side_parameters| object if needed to create a service object. + KeyedService* GetServiceForContext(void* context, + void* side_parameter, bool create); // Maps |context| to |service| with debug checks to prevent duplication and // returns a raw pointer to |service|. - KeyedService* Associate(base::SupportsUserData* context, - std::unique_ptr<KeyedService> service); + KeyedService* Associate(void* context, std::unique_ptr<KeyedService> service); // Removes the mapping from |context| to a service. - void Disassociate(base::SupportsUserData* context); + void Disassociate(void* context); - // Returns a new KeyedService that will be associated with |context|. + // Returns a new KeyedService that will be associated with |context|. The + // |side_parameter| could be nullptr or some object required to create a + // service instance. virtual std::unique_ptr<KeyedService> BuildServiceInstanceFor( - base::SupportsUserData* context) const = 0; + void* context, + void* side_parameter) const = 0; // Returns whether the |context| is off-the-record or not. - virtual bool IsOffTheRecord(base::SupportsUserData* context) const = 0; + virtual bool IsOffTheRecord(void* context) const = 0; // KeyedServiceBaseFactory: - void ContextShutdown(base::SupportsUserData* context) override; - void ContextDestroyed(base::SupportsUserData* context) override; + void ContextShutdown(void* context) override; + void ContextDestroyed(void* context) override; - void SetEmptyTestingFactory(base::SupportsUserData* context) override; - bool HasTestingFactory(base::SupportsUserData* context) override; - void CreateServiceNow(base::SupportsUserData* context) override; + void SetEmptyTestingFactory(void* context) override; + bool HasTestingFactory(void* context) override; private: friend class DependencyManager; friend class DependencyManagerUnittests; // The mapping between a context and its service. - std::map<base::SupportsUserData*, std::unique_ptr<KeyedService>> mapping_; + std::map<void*, std::unique_ptr<KeyedService>> mapping_; // The mapping between a context and its overridden TestingFactory. - std::map<base::SupportsUserData*, TestingFactory> testing_factories_; + std::map<void*, TestingFactory> testing_factories_; DISALLOW_COPY_AND_ASSIGN(KeyedServiceFactory); };
diff --git a/components/keyed_service/core/refcounted_keyed_service_factory.cc b/components/keyed_service/core/refcounted_keyed_service_factory.cc index 2e7355d3..a40650f 100644 --- a/components/keyed_service/core/refcounted_keyed_service_factory.cc +++ b/components/keyed_service/core/refcounted_keyed_service_factory.cc
@@ -20,7 +20,7 @@ } void RefcountedKeyedServiceFactory::SetTestingFactory( - base::SupportsUserData* context, + void* context, TestingFactory testing_factory) { // Ensure that |context| is not marked as stale (e.g., due to it aliasing an // instance that was destroyed in an earlier test) in order to avoid accesses @@ -39,17 +39,18 @@ scoped_refptr<RefcountedKeyedService> RefcountedKeyedServiceFactory::SetTestingFactoryAndUse( - base::SupportsUserData* context, + void* context, + void* side_parameter, TestingFactory testing_factory) { DCHECK(testing_factory); SetTestingFactory(context, std::move(testing_factory)); - return GetServiceForContext(context, true); + return GetServiceForContext(context, side_parameter, true); } scoped_refptr<RefcountedKeyedService> -RefcountedKeyedServiceFactory::GetServiceForContext( - base::SupportsUserData* context, - bool create) { +RefcountedKeyedServiceFactory::GetServiceForContext(void* context, + void* side_parameter, + bool create) { context = GetContextToUse(context); if (!context) return nullptr; @@ -74,22 +75,21 @@ service = factory_iterator->second.Run(context); } } else { - service = BuildServiceInstanceFor(context); + service = BuildServiceInstanceFor(context, side_parameter); } return Associate(context, std::move(service)); } scoped_refptr<RefcountedKeyedService> RefcountedKeyedServiceFactory::Associate( - base::SupportsUserData* context, + void* context, scoped_refptr<RefcountedKeyedService> service) { DCHECK(!base::ContainsKey(mapping_, context)); auto iterator = mapping_.emplace(context, std::move(service)).first; return iterator->second; } -void RefcountedKeyedServiceFactory::Disassociate( - base::SupportsUserData* context) { +void RefcountedKeyedServiceFactory::Disassociate(void* context) { // We "merely" drop our reference to the service. Hopefully this will cause // the service to be destroyed. If not, oh well. auto iterator = mapping_.find(context); @@ -97,15 +97,13 @@ mapping_.erase(iterator); } -void RefcountedKeyedServiceFactory::ContextShutdown( - base::SupportsUserData* context) { +void RefcountedKeyedServiceFactory::ContextShutdown(void* context) { auto iterator = mapping_.find(context); if (iterator != mapping_.end() && iterator->second.get()) iterator->second->ShutdownOnUIThread(); } -void RefcountedKeyedServiceFactory::ContextDestroyed( - base::SupportsUserData* context) { +void RefcountedKeyedServiceFactory::ContextDestroyed(void* context) { Disassociate(context); // For unit tests, we also remove the factory function both so we don't @@ -117,17 +115,14 @@ KeyedServiceBaseFactory::ContextDestroyed(context); } -void RefcountedKeyedServiceFactory::SetEmptyTestingFactory( - base::SupportsUserData* context) { +void RefcountedKeyedServiceFactory::SetEmptyTestingFactory(void* context) { SetTestingFactory(context, TestingFactory()); } -bool RefcountedKeyedServiceFactory::HasTestingFactory( - base::SupportsUserData* context) { +bool RefcountedKeyedServiceFactory::HasTestingFactory(void* context) { return base::ContainsKey(testing_factories_, context); } -void RefcountedKeyedServiceFactory::CreateServiceNow( - base::SupportsUserData* context) { - GetServiceForContext(context, true); +void RefcountedKeyedServiceFactory::CreateServiceNow(void* context) { + GetServiceForContext(context, nullptr /* side_parameter */, true); }
diff --git a/components/keyed_service/core/refcounted_keyed_service_factory.h b/components/keyed_service/core/refcounted_keyed_service_factory.h index 7641934..07839e5 100644 --- a/components/keyed_service/core/refcounted_keyed_service_factory.h +++ b/components/keyed_service/core/refcounted_keyed_service_factory.h
@@ -34,62 +34,63 @@ // a specific test double into the KeyedServiceFactory system. using TestingFactory = base::RepeatingCallback<scoped_refptr<RefcountedKeyedService>( - base::SupportsUserData* context)>; + void* context)>; // Associates |testing_factory| with |context| so that |testing_factory| is // used to create the KeyedService when requested. |testing_factory| can be // empty to signal that KeyedService should be null. Multiple calls to // SetTestingFactory() are allowed; previous services will be shut down. - void SetTestingFactory(base::SupportsUserData* context, - TestingFactory testing_factory); + void SetTestingFactory(void* context, TestingFactory testing_factory); // Associates |testing_factory| with |context| and immediately returns the // created KeyedService. Since the factory will be used immediately, it may // not be empty. scoped_refptr<RefcountedKeyedService> SetTestingFactoryAndUse( - base::SupportsUserData* context, + void* context, + void* side_parameter, TestingFactory testing_factory); // Common implementation that maps |context| to some service object. Deals // with incognito contexts per subclass instructions with GetContextToUse() // method on the base. If |create| is true, the service will be created - // using BuildServiceInstanceFor() if it doesn't already exist. - scoped_refptr<RefcountedKeyedService> GetServiceForContext( - base::SupportsUserData* context, - bool create); + // using BuildServiceInstanceFor() if it doesn't already exist. Subclasses + // could pass |side_parameters| object if needed to create a service object. + scoped_refptr<RefcountedKeyedService> + GetServiceForContext(void* context, void* side_parameter, bool create); // Maps |context| to |service| with debug checks to prevent duplication and // returns |service|. scoped_refptr<RefcountedKeyedService> Associate( - base::SupportsUserData* context, + void* context, scoped_refptr<RefcountedKeyedService> service); // Removes the mapping from |context| to a service. - void Disassociate(base::SupportsUserData* context); + void Disassociate(void* context); // Returns a new RefcountedKeyedService that will be associated with - // |context|. + // |context|. The |side_parameter| could be nullptr or some object required + // to create a service instance. virtual scoped_refptr<RefcountedKeyedService> BuildServiceInstanceFor( - base::SupportsUserData* context) const = 0; + void* context, + void* side_parameter) const = 0; // Returns whether the |context| is off-the-record or not. - virtual bool IsOffTheRecord(base::SupportsUserData* context) const = 0; + virtual bool IsOffTheRecord(void* context) const = 0; // KeyedServiceBaseFactory: - void ContextShutdown(base::SupportsUserData* context) override; - void ContextDestroyed(base::SupportsUserData* context) override; + void ContextShutdown(void* context) override; + void ContextDestroyed(void* context) override; - void SetEmptyTestingFactory(base::SupportsUserData* context) override; - bool HasTestingFactory(base::SupportsUserData* context) override; - void CreateServiceNow(base::SupportsUserData* context) override; + void SetEmptyTestingFactory(void* context) override; + bool HasTestingFactory(void* context) override; + void CreateServiceNow(void* context) override; private: // The mapping between a context and its refcounted service. - std::map<base::SupportsUserData*, scoped_refptr<RefcountedKeyedService>> - mapping_; + std::map<void*, scoped_refptr<RefcountedKeyedService>> mapping_; // The mapping between a context and its overridden TestingFactory. - std::map<base::SupportsUserData*, TestingFactory> testing_factories_; + std::map<void*, TestingFactory> testing_factories_; DISALLOW_COPY_AND_ASSIGN(RefcountedKeyedServiceFactory); };
diff --git a/components/keyed_service/ios/browser_state_dependency_manager.cc b/components/keyed_service/ios/browser_state_dependency_manager.cc index 7dcc8d9..d9c8577 100644 --- a/components/keyed_service/ios/browser_state_dependency_manager.cc +++ b/components/keyed_service/ios/browser_state_dependency_manager.cc
@@ -60,6 +60,5 @@ #ifndef NDEBUG void BrowserStateDependencyManager::DumpContextDependencies( - base::SupportsUserData* context) const { -} + void* context) const {} #endif // NDEBUG
diff --git a/components/keyed_service/ios/browser_state_dependency_manager.h b/components/keyed_service/ios/browser_state_dependency_manager.h index 927f9a4..96c6743 100644 --- a/components/keyed_service/ios/browser_state_dependency_manager.h +++ b/components/keyed_service/ios/browser_state_dependency_manager.h
@@ -80,7 +80,7 @@ #ifndef NDEBUG // DependencyManager: - void DumpContextDependencies(base::SupportsUserData* context) const final; + void DumpContextDependencies(void* context) const final; #endif // NDEBUG DISALLOW_COPY_AND_ASSIGN(BrowserStateDependencyManager);
diff --git a/components/keyed_service/ios/browser_state_keyed_service_factory.cc b/components/keyed_service/ios/browser_state_keyed_service_factory.cc index da2937af..7f5b11ba 100644 --- a/components/keyed_service/ios/browser_state_keyed_service_factory.cc +++ b/components/keyed_service/ios/browser_state_keyed_service_factory.cc
@@ -16,8 +16,7 @@ KeyedServiceFactory::TestingFactory wrapped_factory; if (testing_factory) { wrapped_factory = base::BindRepeating( - [](const TestingFactory& testing_factory, - base::SupportsUserData* context) { + [](const TestingFactory& testing_factory, void* context) { return testing_factory.Run(static_cast<web::BrowserState*>(context)); }, std::move(testing_factory)); @@ -30,13 +29,13 @@ TestingFactory testing_factory) { DCHECK(testing_factory); return KeyedServiceFactory::SetTestingFactoryAndUse( - context, base::BindRepeating( - [](const TestingFactory& testing_factory, - base::SupportsUserData* context) { - return testing_factory.Run( - static_cast<web::BrowserState*>(context)); - }, - std::move(testing_factory))); + context, nullptr /* side_parameter */, + base::BindRepeating( + [](const TestingFactory& testing_factory, void* context) { + return testing_factory.Run( + static_cast<web::BrowserState*>(context)); + }, + std::move(testing_factory))); } BrowserStateKeyedServiceFactory::BrowserStateKeyedServiceFactory( @@ -51,7 +50,8 @@ KeyedService* BrowserStateKeyedServiceFactory::GetServiceForBrowserState( web::BrowserState* context, bool create) { - return KeyedServiceFactory::GetServiceForContext(context, create); + return KeyedServiceFactory::GetServiceForContext( + context, nullptr /* side_parameter */, create); } web::BrowserState* BrowserStateKeyedServiceFactory::GetBrowserStateToUse( @@ -86,17 +86,16 @@ std::unique_ptr<KeyedService> BrowserStateKeyedServiceFactory::BuildServiceInstanceFor( - base::SupportsUserData* context) const { + void* context, + void* side_parameter) const { return BuildServiceInstanceFor(static_cast<web::BrowserState*>(context)); } -bool BrowserStateKeyedServiceFactory::IsOffTheRecord( - base::SupportsUserData* context) const { +bool BrowserStateKeyedServiceFactory::IsOffTheRecord(void* context) const { return static_cast<web::BrowserState*>(context)->IsOffTheRecord(); } -base::SupportsUserData* BrowserStateKeyedServiceFactory::GetContextToUse( - base::SupportsUserData* context) const { +void* BrowserStateKeyedServiceFactory::GetContextToUse(void* context) const { AssertContextWasntDestroyed(context); return GetBrowserStateToUse(static_cast<web::BrowserState*>(context)); } @@ -105,13 +104,11 @@ return ServiceIsCreatedWithBrowserState(); } -void BrowserStateKeyedServiceFactory::ContextShutdown( - base::SupportsUserData* context) { +void BrowserStateKeyedServiceFactory::ContextShutdown(void* context) { BrowserStateShutdown(static_cast<web::BrowserState*>(context)); } -void BrowserStateKeyedServiceFactory::ContextDestroyed( - base::SupportsUserData* context) { +void BrowserStateKeyedServiceFactory::ContextDestroyed(void* context) { BrowserStateDestroyed(static_cast<web::BrowserState*>(context)); } @@ -119,3 +116,8 @@ user_prefs::PrefRegistrySyncable* registry) { RegisterBrowserStatePrefs(registry); } + +void BrowserStateKeyedServiceFactory::CreateServiceNow(void* context) { + KeyedServiceFactory::GetServiceForContext(context, + nullptr /* side_parameter */, true); +}
diff --git a/components/keyed_service/ios/browser_state_keyed_service_factory.h b/components/keyed_service/ios/browser_state_keyed_service_factory.h index d891c113..95711d32 100644 --- a/components/keyed_service/ios/browser_state_keyed_service_factory.h +++ b/components/keyed_service/ios/browser_state_keyed_service_factory.h
@@ -117,16 +117,17 @@ // KeyedServiceFactory: std::unique_ptr<KeyedService> BuildServiceInstanceFor( - base::SupportsUserData* context) const final; - bool IsOffTheRecord(base::SupportsUserData* context) const final; + void* context, + void* side_parameter) const final; + bool IsOffTheRecord(void* context) const final; // KeyedServiceBaseFactory: - base::SupportsUserData* GetContextToUse( - base::SupportsUserData* context) const final; + void* GetContextToUse(void* context) const final; bool ServiceIsCreatedWithContext() const final; - void ContextShutdown(base::SupportsUserData* context) final; - void ContextDestroyed(base::SupportsUserData* context) final; + void ContextShutdown(void* context) final; + void ContextDestroyed(void* context) final; void RegisterPrefs(user_prefs::PrefRegistrySyncable* registry) final; + void CreateServiceNow(void* context) final; DISALLOW_COPY_AND_ASSIGN(BrowserStateKeyedServiceFactory); };
diff --git a/components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.cc b/components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.cc index b179954..1f838a54 100644 --- a/components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.cc +++ b/components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.cc
@@ -16,8 +16,7 @@ RefcountedKeyedServiceFactory::TestingFactory wrapped_factory; if (testing_factory) { wrapped_factory = base::BindRepeating( - [](const TestingFactory& testing_factory, - base::SupportsUserData* context) { + [](const TestingFactory& testing_factory, void* context) { return testing_factory.Run(static_cast<web::BrowserState*>(context)); }, std::move(testing_factory)); @@ -32,13 +31,13 @@ TestingFactory testing_factory) { DCHECK(testing_factory); return RefcountedKeyedServiceFactory::SetTestingFactoryAndUse( - context, base::BindRepeating( - [](const TestingFactory& testing_factory, - base::SupportsUserData* context) { - return testing_factory.Run( - static_cast<web::BrowserState*>(context)); - }, - std::move(testing_factory))); + context, nullptr /* side_parameter*/, + base::BindRepeating( + [](const TestingFactory& testing_factory, void* context) { + return testing_factory.Run( + static_cast<web::BrowserState*>(context)); + }, + std::move(testing_factory))); } RefcountedBrowserStateKeyedServiceFactory:: @@ -56,7 +55,8 @@ RefcountedBrowserStateKeyedServiceFactory::GetServiceForBrowserState( web::BrowserState* context, bool create) { - return RefcountedKeyedServiceFactory::GetServiceForContext(context, create); + return RefcountedKeyedServiceFactory::GetServiceForContext( + context, nullptr /* side_parameter*/, create); } web::BrowserState* @@ -94,18 +94,18 @@ scoped_refptr<RefcountedKeyedService> RefcountedBrowserStateKeyedServiceFactory::BuildServiceInstanceFor( - base::SupportsUserData* context) const { + void* context, + void* side_parameter) const { return BuildServiceInstanceFor(static_cast<web::BrowserState*>(context)); } bool RefcountedBrowserStateKeyedServiceFactory::IsOffTheRecord( - base::SupportsUserData* context) const { + void* context) const { return static_cast<web::BrowserState*>(context)->IsOffTheRecord(); } -base::SupportsUserData* -RefcountedBrowserStateKeyedServiceFactory::GetContextToUse( - base::SupportsUserData* context) const { +void* RefcountedBrowserStateKeyedServiceFactory::GetContextToUse( + void* context) const { AssertContextWasntDestroyed(context); return GetBrowserStateToUse(static_cast<web::BrowserState*>(context)); } @@ -115,13 +115,12 @@ return ServiceIsCreatedWithBrowserState(); } -void RefcountedBrowserStateKeyedServiceFactory::ContextShutdown( - base::SupportsUserData* context) { +void RefcountedBrowserStateKeyedServiceFactory::ContextShutdown(void* context) { BrowserStateShutdown(static_cast<web::BrowserState*>(context)); } void RefcountedBrowserStateKeyedServiceFactory::ContextDestroyed( - base::SupportsUserData* context) { + void* context) { BrowserStateDestroyed(static_cast<web::BrowserState*>(context)); }
diff --git a/components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.h b/components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.h index 56afdfe..a0da0c05 100644 --- a/components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.h +++ b/components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.h
@@ -122,15 +122,15 @@ // RefcountedKeyedServiceFactory: scoped_refptr<RefcountedKeyedService> BuildServiceInstanceFor( - base::SupportsUserData* context) const final; - bool IsOffTheRecord(base::SupportsUserData* context) const final; + void* context, + void* side_parameter) const final; + bool IsOffTheRecord(void* context) const final; // KeyedServiceBaseFactory: - base::SupportsUserData* GetContextToUse( - base::SupportsUserData* context) const final; + void* GetContextToUse(void* context) const final; bool ServiceIsCreatedWithContext() const final; - void ContextShutdown(base::SupportsUserData* context) final; - void ContextDestroyed(base::SupportsUserData* context) final; + void ContextShutdown(void* context) final; + void ContextDestroyed(void* context) final; void RegisterPrefs(user_prefs::PrefRegistrySyncable* registry) final; DISALLOW_COPY_AND_ASSIGN(RefcountedBrowserStateKeyedServiceFactory);
diff --git a/components/password_manager/core/browser/sync/password_sync_bridge.cc b/components/password_manager/core/browser/sync/password_sync_bridge.cc index 09cf825b..6122d6e 100644 --- a/components/password_manager/core/browser/sync/password_sync_bridge.cc +++ b/components/password_manager/core/browser/sync/password_sync_bridge.cc
@@ -447,12 +447,11 @@ return false; } -syncer::ModelTypeSyncBridge::StopSyncResponse -PasswordSyncBridge::ApplyStopSyncChanges( +void PasswordSyncBridge::ApplyStopSyncChanges( std::unique_ptr<syncer::MetadataChangeList> delete_metadata_change_list) { // TODO(crbug.com/902349): Implement disable-sync case by a more robust // implementation, via a dedicated method in PasswordStoreSync. - return ModelTypeSyncBridge::ApplyStopSyncChanges( + ModelTypeSyncBridge::ApplyStopSyncChanges( std::move(delete_metadata_change_list)); }
diff --git a/components/password_manager/core/browser/sync/password_sync_bridge.h b/components/password_manager/core/browser/sync/password_sync_bridge.h index 7772f2ed..7838ddbc 100644 --- a/components/password_manager/core/browser/sync/password_sync_bridge.h +++ b/components/password_manager/core/browser/sync/password_sync_bridge.h
@@ -54,9 +54,8 @@ std::string GetClientTag(const syncer::EntityData& entity_data) override; std::string GetStorageKey(const syncer::EntityData& entity_data) override; bool SupportsGetStorageKey() const override; - ModelTypeSyncBridge::StopSyncResponse ApplyStopSyncChanges( - std::unique_ptr<syncer::MetadataChangeList> delete_metadata_change_list) - override; + void ApplyStopSyncChanges(std::unique_ptr<syncer::MetadataChangeList> + delete_metadata_change_list) override; private: // Password store responsible for persistence.
diff --git a/components/password_manager/core/common/password_manager_features.cc b/components/password_manager/core/common/password_manager_features.cc index 14f1336..12842831 100644 --- a/components/password_manager/core/common/password_manager_features.cc +++ b/components/password_manager/core/common/password_manager_features.cc
@@ -6,6 +6,8 @@ namespace password_manager { +// NOTE: It is strongly recommended to use UpperCamelCase style for feature +// names, e.g. "MyGreatFeature". namespace features { // Enable affiliation based matching, so that credentials stored for an Android @@ -85,6 +87,11 @@ const base::Feature kOnlyNewParser = {"only-new-password-form-parsing", base::FEATURE_DISABLED_BY_DEFAULT}; +// Controls whether to offer manual password generation in the accessory sheet +// on Android. +const base::Feature kManualPasswordGenerationAndroid{ + "ManualPasswordGenerationAndroid", base::FEATURE_DISABLED_BY_DEFAULT}; + // Performs a one-off migration (with retries) from a native backend into // logindb. Passwords are served from the new location. const base::Feature kMigrateLinuxToLoginDB = {
diff --git a/components/password_manager/core/common/password_manager_features.h b/components/password_manager/core/common/password_manager_features.h index 55e8109..2196b89d 100644 --- a/components/password_manager/core/common/password_manager_features.h +++ b/components/password_manager/core/common/password_manager_features.h
@@ -25,6 +25,7 @@ extern const base::Feature kFillOnAccountSelect; extern const base::Feature kFillOnAccountSelectHttp; extern const base::Feature kGooglePasswordManager; +extern const base::Feature kManualPasswordGenerationAndroid; extern const base::Feature kMigrateLinuxToLoginDB; extern const base::Feature kNewPasswordFormParsing; extern const base::Feature kNewPasswordFormParsingForSaving;
diff --git a/components/signin/core/browser/account_reconcilor.cc b/components/signin/core/browser/account_reconcilor.cc index 4d7d458..b3cc6478 100644 --- a/components/signin/core/browser/account_reconcilor.cc +++ b/components/signin/core/browser/account_reconcilor.cc
@@ -389,8 +389,10 @@ return; } VLOG(1) << "AccountReconcilor::PerformMergeAction: " << account_id; - cookie_manager_service_->AddAccountToCookie(account_id, - delegate_->GetGaiaApiSource()); + cookie_manager_service_->AddAccountToCookie( + account_id, delegate_->GetGaiaApiSource(), + base::BindOnce(&AccountReconcilor::OnAddAccountToCookieCompleted, + weak_factory_.GetWeakPtr())); } void AccountReconcilor::PerformSetCookiesAction(
diff --git a/components/signin/core/browser/account_reconcilor.h b/components/signin/core/browser/account_reconcilor.h index 2d46144f..bb1ac48 100644 --- a/components/signin/core/browser/account_reconcilor.h +++ b/components/signin/core/browser/account_reconcilor.h
@@ -281,9 +281,6 @@ void OnErrorStateOfRefreshTokenUpdatedForAccount( const CoreAccountInfo& account_info, const GoogleServiceAuthError& error) override; - void OnAddAccountToCookieCompleted( - const std::string& account_id, - const GoogleServiceAuthError& error) override; void OnAccountsInCookieUpdated( const identity::AccountsInCookieJarInfo& accounts_in_cookie_jar_info, const GoogleServiceAuthError& error) override; @@ -294,6 +291,8 @@ const std::vector<std::string>& chrome_accounts, std::vector<gaia::ListedAccount>&& gaia_accounts); + void OnAddAccountToCookieCompleted(const std::string& account_id, + const GoogleServiceAuthError& error); void OnSetAccountsInCookieCompleted(const GoogleServiceAuthError& error); // Lock related methods.
diff --git a/components/signin/core/browser/account_reconcilor_unittest.cc b/components/signin/core/browser/account_reconcilor_unittest.cc index a29985d..82648e6 100644 --- a/components/signin/core/browser/account_reconcilor_unittest.cc +++ b/components/signin/core/browser/account_reconcilor_unittest.cc
@@ -276,10 +276,9 @@ std::string SeedAccountInfo(const std::string& gaia_id, const std::string& username); - void SimulateAddAccountToCookieCompleted( - identity::IdentityManager::Observer* observer, - const std::string& account_id, - const GoogleServiceAuthError& error); + void SimulateAddAccountToCookieCompleted(AccountReconcilor* reconcilor, + const std::string& account_id, + const GoogleServiceAuthError& error); void SimulateCookieContentSettingsChanged( content_settings::Observer* observer, @@ -450,10 +449,10 @@ } void AccountReconcilorTest::SimulateAddAccountToCookieCompleted( - identity::IdentityManager::Observer* observer, + AccountReconcilor* reconcilor, const std::string& account_id, const GoogleServiceAuthError& error) { - observer->OnAddAccountToCookieCompleted(account_id, error); + reconcilor->OnAddAccountToCookieCompleted(account_id, error); } void AccountReconcilorTest::SimulateSetAccountsInCookieCompleted(
diff --git a/components/signin/core/browser/gaia_cookie_manager_service.cc b/components/signin/core/browser/gaia_cookie_manager_service.cc index 6166afaf..94ab355c 100644 --- a/components/signin/core/browser/gaia_cookie_manager_service.cc +++ b/components/signin/core/browser/gaia_cookie_manager_service.cc
@@ -164,6 +164,16 @@ source_(source), set_accounts_in_cookie_completed_callback_(std::move(callback)) {} +GaiaCookieManagerService::GaiaCookieRequest::GaiaCookieRequest( + GaiaCookieRequestType request_type, + const std::vector<std::string>& account_ids, + gaia::GaiaSource source, + AddAccountToCookieCompletedCallback callback) + : request_type_(request_type), + account_ids_(account_ids), + source_(source), + add_account_to_cookie_completed_callback_(std::move(callback)) {} + GaiaCookieManagerService::GaiaCookieRequest::~GaiaCookieRequest() {} GaiaCookieManagerService::GaiaCookieRequest::GaiaCookieRequest( @@ -186,13 +196,23 @@ std::move(set_accounts_in_cookie_completed_callback_).Run(error); } +void GaiaCookieManagerService::GaiaCookieRequest:: + RunAddAccountToCookieCompletedCallback( + const std::string& account_id, + const GoogleServiceAuthError& error) { + if (add_account_to_cookie_completed_callback_) + std::move(add_account_to_cookie_completed_callback_).Run(account_id, error); +} + // static GaiaCookieManagerService::GaiaCookieRequest GaiaCookieManagerService::GaiaCookieRequest::CreateAddAccountRequest( const std::string& account_id, - gaia::GaiaSource source) { + gaia::GaiaSource source, + AddAccountToCookieCompletedCallback callback) { return GaiaCookieManagerService::GaiaCookieRequest( - GaiaCookieRequestType::ADD_ACCOUNT, {account_id}, source); + GaiaCookieRequestType::ADD_ACCOUNT, {account_id}, source, + std::move(callback)); } // static @@ -541,16 +561,19 @@ void GaiaCookieManagerService::AddAccountToCookieInternal( const std::string& account_id, - gaia::GaiaSource source) { + gaia::GaiaSource source, + AddAccountToCookieCompletedCallback completion_callback) { DCHECK(!account_id.empty()); + requests_.push_back(GaiaCookieRequest::CreateAddAccountRequest( + account_id, source, std::move(completion_callback))); + if (!signin_client_->AreSigninCookiesAllowed()) { - SignalComplete(account_id, GoogleServiceAuthError( - GoogleServiceAuthError::REQUEST_CANCELED)); + SignalAddToCookieComplete( + requests_.begin(), + GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED)); return; } - requests_.push_back( - GaiaCookieRequest::CreateAddAccountRequest(account_id, source)); if (requests_.size() == 1) { signin_client_->DelayNetworkCall( base::BindOnce(&GaiaCookieManagerService::StartFetchingUbertoken, @@ -558,22 +581,27 @@ } } -void GaiaCookieManagerService::AddAccountToCookie(const std::string& account_id, - gaia::GaiaSource source) { +void GaiaCookieManagerService::AddAccountToCookie( + const std::string& account_id, + gaia::GaiaSource source, + AddAccountToCookieCompletedCallback completion_callback) { VLOG(1) << "GaiaCookieManagerService::AddAccountToCookie: " << account_id; access_token_ = std::string(); - AddAccountToCookieInternal(account_id, source); + AddAccountToCookieInternal(account_id, source, + std::move(completion_callback)); } void GaiaCookieManagerService::AddAccountToCookieWithToken( const std::string& account_id, const std::string& access_token, - gaia::GaiaSource source) { + gaia::GaiaSource source, + AddAccountToCookieCompletedCallback completion_callback) { VLOG(1) << "GaiaCookieManagerService::AddAccountToCookieWithToken: " << account_id; DCHECK(!access_token.empty()); access_token_ = access_token; - AddAccountToCookieInternal(account_id, source); + AddAccountToCookieInternal(account_id, source, + std::move(completion_callback)); } bool GaiaCookieManagerService::ListAccounts( @@ -634,7 +662,7 @@ // We have a pending log in request for an account followed by // a signout. GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED); - SignalComplete(it->GetAccountID(), error); + SignalAddToCookieComplete(it, error); } // Keep all requests except for ADD_ACCOUNTS. @@ -735,14 +763,20 @@ InitCookieListener(); } -void GaiaCookieManagerService::SignalComplete( - const std::string& account_id, +void GaiaCookieManagerService::SignalAddToCookieComplete( + const base::circular_deque<GaiaCookieRequest>::iterator& request, const GoogleServiceAuthError& error) { - // Its possible for the observer to delete |this| object. Don't access - // access any members after this calling the observer. This method should - // be the last call in any other method. - for (auto& observer : observer_list_) - observer.OnAddAccountToCookieCompleted(account_id, error); + // SignalAddToCookieComplete is called in two circumstances: + // + // - normal flow: this happens when SignalAddToCookieComplete is called at + // the end of processing a ADD_ACCOUNT request. + // + // - during a LogOut operation: When logging out, any queue request to + // ADD_ACCOUNT is canceled (which implies that it is possible to run the + // completion callback of a request that it not front of the queue). + + request->RunAddAccountToCookieCompletedCallback(request->GetAccountID(), + error); } void GaiaCookieManagerService::SignalSetAccountsComplete( @@ -760,8 +794,8 @@ const std::string account_id = requests_.front().GetAccountID(); VLOG(1) << "Failed to retrieve ubertoken" << " account=" << account_id << " error=" << error.ToString(); + SignalAddToCookieComplete(requests_.begin(), error); HandleNextRequest(); - SignalComplete(account_id, error); return; } @@ -837,8 +871,9 @@ GaiaCookieRequestType::ADD_ACCOUNT); MarkListAccountsStale(); + SignalAddToCookieComplete(requests_.begin(), + GoogleServiceAuthError::AuthErrorNone()); HandleNextRequest(); - SignalComplete(account_id, GoogleServiceAuthError::AuthErrorNone()); fetcher_backoff_.InformOfRequest(true); uber_token_ = std::string(); @@ -869,8 +904,8 @@ UMA_HISTOGRAM_ENUMERATION("OAuth2Login.MergeSessionFailure", error.state(), GoogleServiceAuthError::NUM_STATES); + SignalAddToCookieComplete(requests_.begin(), error); HandleNextRequest(); - SignalComplete(account_id, error); } void GaiaCookieManagerService::OnOAuthMultiloginFinished(
diff --git a/components/signin/core/browser/gaia_cookie_manager_service.h b/components/signin/core/browser/gaia_cookie_manager_service.h index 26038ed..ee2a8c5 100644 --- a/components/signin/core/browser/gaia_cookie_manager_service.h +++ b/components/signin/core/browser/gaia_cookie_manager_service.h
@@ -83,6 +83,9 @@ typedef base::OnceCallback<void(const GoogleServiceAuthError& error)> SetAccountsInCookieCompletedCallback; + typedef base::OnceCallback<void(const std::string& account_id, + const GoogleServiceAuthError& error)> + AddAccountToCookieCompletedCallback; // Contains the information and parameters for any request. class GaiaCookieRequest { @@ -101,10 +104,14 @@ void RunSetAccountsInCookieCompletedCallback( const GoogleServiceAuthError& error); + void RunAddAccountToCookieCompletedCallback( + const std::string& account_id, + const GoogleServiceAuthError& error); static GaiaCookieRequest CreateAddAccountRequest( const std::string& account_id, - gaia::GaiaSource source); + gaia::GaiaSource source, + AddAccountToCookieCompletedCallback callback); static GaiaCookieRequest CreateLogOutRequest(gaia::GaiaSource source); static GaiaCookieRequest CreateListAccountsRequest(); static GaiaCookieRequest CreateSetAccountsRequest( @@ -120,6 +127,10 @@ const std::vector<std::string>& account_ids, gaia::GaiaSource source, SetAccountsInCookieCompletedCallback callback); + GaiaCookieRequest(GaiaCookieRequestType request_type, + const std::vector<std::string>& account_ids, + gaia::GaiaSource source, + AddAccountToCookieCompletedCallback callback); GaiaCookieRequestType request_type_; std::vector<std::string> account_ids_; @@ -127,19 +138,14 @@ SetAccountsInCookieCompletedCallback set_accounts_in_cookie_completed_callback_; + AddAccountToCookieCompletedCallback + add_account_to_cookie_completed_callback_; DISALLOW_COPY_AND_ASSIGN(GaiaCookieRequest); }; class Observer { public: - // Called whenever a merge session is completed. The account that was - // merged is given by |account_id|. If |error| is equal to - // GoogleServiceAuthError::AuthErrorNone() then the merge succeeded. - virtual void OnAddAccountToCookieCompleted( - const std::string& account_id, - const GoogleServiceAuthError& error) {} - // Called whenever the GaiaCookieManagerService's list of GAIA accounts is // updated. The GCMS monitors the APISID cookie and triggers a /ListAccounts // call on change. The GCMS will also call ListAccounts upon the first call @@ -241,11 +247,15 @@ void InitCookieListener(); void Shutdown() override; - void AddAccountToCookie(const std::string& account_id, - gaia::GaiaSource source); - void AddAccountToCookieWithToken(const std::string& account_id, - const std::string& access_token, - gaia::GaiaSource source); + void AddAccountToCookie( + const std::string& account_id, + gaia::GaiaSource source, + AddAccountToCookieCompletedCallback completion_callback); + void AddAccountToCookieWithToken( + const std::string& account_id, + const std::string& access_token, + gaia::GaiaSource source, + AddAccountToCookieCompletedCallback completion_callback); // Takes list of account_ids and sets the cookie for these accounts regardless // of the current cookie state. Removes the accounts that are not in @@ -327,8 +337,9 @@ scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory(); // Calls the AddAccountToCookie completion callback. - void SignalComplete(const std::string& account_id, - const GoogleServiceAuthError& error); + void SignalAddToCookieComplete( + const base::circular_deque<GaiaCookieRequest>::iterator& request, + const GoogleServiceAuthError& error); // Marks the list account being staled, and for iOS only, it triggers to fetch // the list of accounts (on iOS there is no OnCookieChange() notification). @@ -369,8 +380,10 @@ virtual void OnSetAccountsFinished(const GoogleServiceAuthError& error); // Helper method for AddAccountToCookie* methods. - void AddAccountToCookieInternal(const std::string& account_id, - gaia::GaiaSource source); + void AddAccountToCookieInternal( + const std::string& account_id, + gaia::GaiaSource source, + AddAccountToCookieCompletedCallback completion_callback); // Helper function to trigger fetching retry in case of failure for only // failed account id. Virtual for testing purposes.
diff --git a/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc b/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc index 93a15c2..04b96f42 100644 --- a/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc +++ b/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc
@@ -17,6 +17,7 @@ #include "base/single_thread_task_runner.h" #include "base/strings/stringprintf.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/mock_callback.h" #include "base/test/scoped_task_environment.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" @@ -34,6 +35,9 @@ namespace { +using MockAddAccountToCookieCompletedCallback = base::MockCallback< + GaiaCookieManagerService::AddAccountToCookieCompletedCallback>; + class MockObserver : public GaiaCookieManagerService::Observer { public: explicit MockObserver(GaiaCookieManagerService* helper) : helper_(helper) { @@ -42,8 +46,6 @@ ~MockObserver() override { helper_->RemoveObserver(this); } - MOCK_METHOD2(OnAddAccountToCookieCompleted, - void(const std::string&, const GoogleServiceAuthError&)); MOCK_METHOD3(OnGaiaAccountsInCookieUpdated, void(const std::vector<gaia::ListedAccount>&, const std::vector<gaia::ListedAccount>&, @@ -254,10 +256,13 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc1@gmail.com", no_error())); - helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); + MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed; + EXPECT_CALL(add_account_to_cookie_completed, + Run("acc1@gmail.com", no_error())); + + helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed.Get()); SimulateMergeSessionSuccess(&helper, "token"); } @@ -267,10 +272,12 @@ base::HistogramTester histograms; EXPECT_CALL(helper, StartFetchingUbertoken()); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc1@gmail.com", error())); - helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); + MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed; + EXPECT_CALL(add_account_to_cookie_completed, Run("acc1@gmail.com", error())); + + helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed.Get()); SimulateMergeSessionFailure(&helper, error()); // Persistent error incurs no further retries. DCHECK(!helper.is_running()); @@ -283,10 +290,12 @@ MockObserver observer(&helper); signin_client()->set_are_signin_cookies_allowed(false); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc1@gmail.com", canceled())); + MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed; + EXPECT_CALL(add_account_to_cookie_completed, + Run("acc1@gmail.com", canceled())); - helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); + helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed.Get()); } TEST_F(GaiaCookieManagerServiceTest, MergeSessionRetried) { @@ -299,10 +308,13 @@ EXPECT_CALL(helper, StartFetchingUbertoken()); EXPECT_CALL(helper, StartFetchingMergeSession()); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc1@gmail.com", no_error())); - helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); + MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed; + EXPECT_CALL(add_account_to_cookie_completed, + Run("acc1@gmail.com", no_error())); + + helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed.Get()); SimulateMergeSessionFailure(&helper, canceled()); DCHECK(helper.is_running()); Advance(test_task_runner, helper.GetBackoffEntry()->GetTimeUntilRelease()); @@ -321,10 +333,13 @@ EXPECT_CALL(helper, StartFetchingUbertoken()); EXPECT_CALL(helper, StartFetchingMergeSession()).Times(2); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc1@gmail.com", no_error())); - helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); + MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed; + EXPECT_CALL(add_account_to_cookie_completed, + Run("acc1@gmail.com", no_error())); + + helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed.Get()); SimulateMergeSessionFailure(&helper, canceled()); DCHECK(helper.is_running()); Advance(test_task_runner, helper.GetBackoffEntry()->GetTimeUntilRelease()); @@ -342,10 +357,12 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc1@gmail.com", error())); - helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); + MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed; + EXPECT_CALL(add_account_to_cookie_completed, Run("acc1@gmail.com", error())); + + helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed.Get()); SimulateUbertokenFailure(&helper, error()); } @@ -897,13 +914,18 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()).Times(2); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc1@gmail.com", no_error())); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc2@gmail.com", no_error())); - helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); - helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome); + MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed1, + add_account_to_cookie_completed2; + EXPECT_CALL(add_account_to_cookie_completed1, + Run("acc1@gmail.com", no_error())); + EXPECT_CALL(add_account_to_cookie_completed2, + Run("acc2@gmail.com", no_error())); + + helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed1.Get()); + helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed2.Get()); SimulateMergeSessionSuccess(&helper, "token1"); SimulateMergeSessionSuccess(&helper, "token2"); } @@ -913,13 +935,17 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()).Times(2); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc1@gmail.com", error())); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc2@gmail.com", no_error())); - helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); - helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome); + MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed1, + add_account_to_cookie_completed2; + EXPECT_CALL(add_account_to_cookie_completed1, Run("acc1@gmail.com", error())); + EXPECT_CALL(add_account_to_cookie_completed2, + Run("acc2@gmail.com", no_error())); + + helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed1.Get()); + helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed2.Get()); SimulateMergeSessionFailure(&helper, error()); SimulateMergeSessionSuccess(&helper, "token2"); } @@ -929,13 +955,17 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()).Times(2); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc1@gmail.com", error())); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc2@gmail.com", no_error())); - helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); - helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome); + MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed1, + add_account_to_cookie_completed2; + EXPECT_CALL(add_account_to_cookie_completed1, Run("acc1@gmail.com", error())); + EXPECT_CALL(add_account_to_cookie_completed2, + Run("acc2@gmail.com", no_error())); + + helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed1.Get()); + helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed2.Get()); SimulateUbertokenFailure(&helper, error()); SimulateMergeSessionSuccess(&helper, "token2"); } @@ -945,19 +975,25 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()).Times(4); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted(_, no_error())).Times(4); - helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); - helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome); + MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed; + EXPECT_CALL(add_account_to_cookie_completed, Run(_, no_error())).Times(4); + + helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed.Get()); + helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed.Get()); SimulateMergeSessionSuccess(&helper, "token1"); - helper.AddAccountToCookie("acc3@gmail.com", gaia::GaiaSource::kChrome); + helper.AddAccountToCookie("acc3@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed.Get()); SimulateMergeSessionSuccess(&helper, "token2"); SimulateMergeSessionSuccess(&helper, "token3"); - helper.AddAccountToCookie("acc4@gmail.com", gaia::GaiaSource::kChrome); + helper.AddAccountToCookie("acc4@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed.Get()); SimulateMergeSessionSuccess(&helper, "token4"); } @@ -967,11 +1003,14 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc2@gmail.com", no_error())); EXPECT_CALL(helper, StartFetchingLogOut()); - helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome); + MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed; + EXPECT_CALL(add_account_to_cookie_completed, + Run("acc2@gmail.com", no_error())); + + helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed.Get()); SimulateMergeSessionSuccess(&helper, "token1"); helper.LogOutAllAccounts(gaia::GaiaSource::kChrome); @@ -984,11 +1023,14 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc2@gmail.com", no_error())); EXPECT_CALL(helper, StartFetchingLogOut()); - helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome); + MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed; + EXPECT_CALL(add_account_to_cookie_completed, + Run("acc2@gmail.com", no_error())); + + helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed.Get()); SimulateMergeSessionSuccess(&helper, "token1"); helper.LogOutAllAccounts(gaia::GaiaSource::kChrome); @@ -1002,11 +1044,14 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc2@gmail.com", no_error())); EXPECT_CALL(helper, StartFetchingLogOut()); - helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome); + MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed; + EXPECT_CALL(add_account_to_cookie_completed, + Run("acc2@gmail.com", no_error())); + + helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed.Get()); helper.LogOutAllAccounts(gaia::GaiaSource::kChrome); SimulateMergeSessionSuccess(&helper, "token1"); @@ -1018,15 +1063,20 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc1@gmail.com", no_error())); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc2@gmail.com", canceled())); EXPECT_CALL(helper, StartFetchingLogOut()); - helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); + MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed1, + add_account_to_cookie_completed2; + EXPECT_CALL(add_account_to_cookie_completed1, + Run("acc1@gmail.com", no_error())); + EXPECT_CALL(add_account_to_cookie_completed2, + Run("acc2@gmail.com", canceled())); + + helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed1.Get()); // The Log Out should prevent this AddAccount from being fetched. - helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome); + helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed2.Get()); helper.LogOutAllAccounts(gaia::GaiaSource::kChrome); SimulateMergeSessionSuccess(&helper, "token1"); @@ -1038,11 +1088,14 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc2@gmail.com", no_error())); EXPECT_CALL(helper, StartFetchingLogOut()); - helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome); + MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed; + EXPECT_CALL(add_account_to_cookie_completed, + Run("acc2@gmail.com", no_error())); + + helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed.Get()); SimulateMergeSessionSuccess(&helper, "token1"); helper.LogOutAllAccounts(gaia::GaiaSource::kChrome); @@ -1056,16 +1109,22 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()).Times(2); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc2@gmail.com", no_error())); EXPECT_CALL(helper, StartFetchingLogOut()); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc3@gmail.com", no_error())); - helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome); + + MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed2, + add_account_to_cookie_completed3; + EXPECT_CALL(add_account_to_cookie_completed2, + Run("acc2@gmail.com", no_error())); + EXPECT_CALL(add_account_to_cookie_completed3, + Run("acc3@gmail.com", no_error())); + + helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed2.Get()); SimulateMergeSessionSuccess(&helper, "token1"); helper.LogOutAllAccounts(gaia::GaiaSource::kChrome); - helper.AddAccountToCookie("acc3@gmail.com", gaia::GaiaSource::kChrome); + helper.AddAccountToCookie("acc3@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed3.Get()); SimulateLogOutSuccess(&helper); // After LogOut the MergeSession should be fetched. @@ -1077,19 +1136,24 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()).Times(2); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc2@gmail.com", no_error())); EXPECT_CALL(helper, StartFetchingLogOut()); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc3@gmail.com", no_error())); - helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome); + MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed2, + add_account_to_cookie_completed3; + EXPECT_CALL(add_account_to_cookie_completed2, + Run("acc2@gmail.com", no_error())); + EXPECT_CALL(add_account_to_cookie_completed3, + Run("acc3@gmail.com", no_error())); + + helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed2.Get()); SimulateMergeSessionSuccess(&helper, "token1"); helper.LogOutAllAccounts(gaia::GaiaSource::kChrome); // Second LogOut will never be fetched. helper.LogOutAllAccounts(gaia::GaiaSource::kChrome); - helper.AddAccountToCookie("acc3@gmail.com", gaia::GaiaSource::kChrome); + helper.AddAccountToCookie("acc3@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed3.Get()); SimulateLogOutSuccess(&helper); // After LogOut the MergeSession should be fetched. @@ -1101,24 +1165,29 @@ MockObserver observer(&helper); // From the first Signin. - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc1@gmail.com", no_error())); + MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed1; + EXPECT_CALL(add_account_to_cookie_completed1, + Run("acc1@gmail.com", no_error())); // From the sign out and then re-sign in. EXPECT_CALL(helper, StartFetchingLogOut()); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc3@gmail.com", no_error())); + + MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed3; + EXPECT_CALL(add_account_to_cookie_completed3, + Run("acc3@gmail.com", no_error())); // Total sign in 2 times, not enforcing ordered sequences. EXPECT_CALL(helper, StartFetchingUbertoken()).Times(2); - helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); + helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed1.Get()); helper.LogOutAllAccounts(gaia::GaiaSource::kChrome); SimulateMergeSessionSuccess(&helper, "token1"); SimulateLogOutSuccess(&helper); - helper.AddAccountToCookie("acc3@gmail.com", gaia::GaiaSource::kChrome); + helper.AddAccountToCookie("acc3@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed3.Get()); SimulateMergeSessionSuccess(&helper, "token3"); } @@ -1127,14 +1196,18 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc2@gmail.com", canceled())); - EXPECT_CALL(observer, - OnAddAccountToCookieCompleted("acc1@gmail.com", no_error())); + MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed1, + add_account_to_cookie_completed2; + EXPECT_CALL(add_account_to_cookie_completed1, + Run("acc1@gmail.com", no_error())); + EXPECT_CALL(add_account_to_cookie_completed2, + Run("acc2@gmail.com", canceled())); EXPECT_CALL(helper, StartFetchingLogOut()); - helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); - helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome); + helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed1.Get()); + helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome, + add_account_to_cookie_completed2.Get()); helper.LogOutAllAccounts(gaia::GaiaSource::kChrome); SimulateMergeSessionSuccess(&helper, "token1"); @@ -1374,7 +1447,9 @@ InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); EXPECT_CALL(helper, StartFetchingUbertoken()); - helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); + helper.AddAccountToCookie( + "acc1@gmail.com", gaia::GaiaSource::kChrome, + GaiaCookieManagerService::AddAccountToCookieCompletedCallback()); ASSERT_FALSE(IsLoadPending()); SimulateUbertokenSuccess(&helper, "token"); @@ -1396,7 +1471,9 @@ helper.external_cc_result_fetcher_for_testing()->Start(); EXPECT_CALL(helper, StartFetchingUbertoken()); - helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome); + helper.AddAccountToCookie( + "acc2@gmail.com", gaia::GaiaSource::kChrome, + GaiaCookieManagerService::AddAccountToCookieCompletedCallback()); // There is already a ExternalCCResultFetch underway. This will trigger // StartFetchingMergeSession. EXPECT_CALL(helper, StartFetchingMergeSession());
diff --git a/components/signin/core/browser/signin_manager.cc b/components/signin/core/browser/signin_manager.cc index 4250086..dbe01004 100644 --- a/components/signin/core/browser/signin_manager.cc +++ b/components/signin/core/browser/signin_manager.cc
@@ -239,8 +239,9 @@ if (!IsAuthenticated()) return; - cookie_manager_service_->AddAccountToCookie(GetAuthenticatedAccountId(), - gaia::GaiaSource::kSigninManager); + cookie_manager_service_->AddAccountToCookie( + GetAuthenticatedAccountId(), gaia::GaiaSource::kSigninManager, + GaiaCookieManagerService::AddAccountToCookieCompletedCallback()); } void SigninManager::OnExternalSigninCompleted(const std::string& username) {
diff --git a/components/sync/device_info/device_info_sync_bridge.cc b/components/sync/device_info/device_info_sync_bridge.cc index f28e009..ce147ff 100644 --- a/components/sync/device_info/device_info_sync_bridge.cc +++ b/components/sync/device_info/device_info_sync_bridge.cc
@@ -234,8 +234,7 @@ return entity_data.specifics.device_info().cache_guid(); } -ModelTypeSyncBridge::StopSyncResponse -DeviceInfoSyncBridge::ApplyStopSyncChanges( +void DeviceInfoSyncBridge::ApplyStopSyncChanges( std::unique_ptr<MetadataChangeList> delete_metadata_change_list) { // TODO(skym, crbug.com/659263): Would it be reasonable to pulse_timer_.Stop() // or subscription_.reset() here? @@ -249,7 +248,6 @@ NotifyObservers(); } } - return StopSyncResponse::kModelStillReadyToSync; } bool DeviceInfoSyncBridge::IsSyncing() const {
diff --git a/components/sync/device_info/device_info_sync_bridge.h b/components/sync/device_info/device_info_sync_bridge.h index 7134399..293b0f2 100644 --- a/components/sync/device_info/device_info_sync_bridge.h +++ b/components/sync/device_info/device_info_sync_bridge.h
@@ -52,7 +52,7 @@ void GetAllDataForDebugging(DataCallback callback) override; std::string GetClientTag(const EntityData& entity_data) override; std::string GetStorageKey(const EntityData& entity_data) override; - StopSyncResponse ApplyStopSyncChanges( + void ApplyStopSyncChanges( std::unique_ptr<MetadataChangeList> delete_metadata_change_list) override; // DeviceInfoTracker implementation.
diff --git a/components/sync/model/fake_model_type_sync_bridge.cc b/components/sync/model/fake_model_type_sync_bridge.cc index 86fe0ae..860a127 100644 --- a/components/sync/model/fake_model_type_sync_bridge.cc +++ b/components/sync/model/fake_model_type_sync_bridge.cc
@@ -361,12 +361,10 @@ return std::move(*conflict_resolution_); } -ModelTypeSyncBridge::StopSyncResponse -FakeModelTypeSyncBridge::ApplyStopSyncChanges( +void FakeModelTypeSyncBridge::ApplyStopSyncChanges( std::unique_ptr<MetadataChangeList> delete_metadata_change_list) { ModelTypeSyncBridge::ApplyStopSyncChanges( std::move(delete_metadata_change_list)); - return stop_sync_response_; } void FakeModelTypeSyncBridge::SetConflictResolution( @@ -375,10 +373,6 @@ std::make_unique<ConflictResolution>(std::move(resolution)); } -void FakeModelTypeSyncBridge::SetStopSyncResponse(StopSyncResponse response) { - stop_sync_response_ = response; -} - void FakeModelTypeSyncBridge::ErrorOnNextCall() { EXPECT_FALSE(error_next_); error_next_ = true;
diff --git a/components/sync/model/fake_model_type_sync_bridge.h b/components/sync/model/fake_model_type_sync_bridge.h index 10a8aac..82e37fa 100644 --- a/components/sync/model/fake_model_type_sync_bridge.h +++ b/components/sync/model/fake_model_type_sync_bridge.h
@@ -126,16 +126,13 @@ ConflictResolution ResolveConflict( const EntityData& local_data, const EntityData& remote_data) const override; - StopSyncResponse ApplyStopSyncChanges( + void ApplyStopSyncChanges( std::unique_ptr<MetadataChangeList> delete_metadata_change_list) override; // Stores a resolution for the next call to ResolveConflict. Note that if this // is a USE_NEW resolution, the data will only exist for one resolve call. void SetConflictResolution(ConflictResolution resolution); - // Stores the value returned by future calls to ApplyStopSyncChanges(). - void SetStopSyncResponse(StopSyncResponse response); - // Sets an error that the next fallible call to the bridge will generate. void ErrorOnNextCall(); @@ -163,9 +160,6 @@ // The conflict resolution to use for calls to ResolveConflict. std::unique_ptr<ConflictResolution> conflict_resolution_; - StopSyncResponse stop_sync_response_ = - StopSyncResponse::kModelStillReadyToSync; - // The storage keys which bridge will ignore. std::unordered_set<std::string> keys_to_ignore_;
diff --git a/components/sync/model/model_type_sync_bridge.cc b/components/sync/model/model_type_sync_bridge.cc index 6ad1900..f1e94ab 100644 --- a/components/sync/model/model_type_sync_bridge.cc +++ b/components/sync/model/model_type_sync_bridge.cc
@@ -46,14 +46,13 @@ return ConflictResolution::UseRemote(); } -ModelTypeSyncBridge::StopSyncResponse ModelTypeSyncBridge::ApplyStopSyncChanges( +void ModelTypeSyncBridge::ApplyStopSyncChanges( std::unique_ptr<MetadataChangeList> delete_metadata_change_list) { if (delete_metadata_change_list) { // Nothing to do if this fails, so just ignore the error it might return. ApplySyncChanges(std::move(delete_metadata_change_list), EntityChangeList()); } - return StopSyncResponse::kModelStillReadyToSync; } size_t ModelTypeSyncBridge::EstimateSyncOverheadMemoryUsage() const {
diff --git a/components/sync/model/model_type_sync_bridge.h b/components/sync/model/model_type_sync_bridge.h index f650aac9..2247c85 100644 --- a/components/sync/model/model_type_sync_bridge.h +++ b/components/sync/model/model_type_sync_bridge.h
@@ -36,13 +36,6 @@ using DataCallback = base::OnceCallback<void(std::unique_ptr<DataBatch>)>; using StorageKeyList = std::vector<std::string>; - // TODO(crbug.com/863870): Remove this enum now the sessions has migrated - // away. - enum class StopSyncResponse { - kModelStillReadyToSync, - kModelNoLongerReadyToSync - }; - ModelTypeSyncBridge( std::unique_ptr<ModelTypeChangeProcessor> change_processor); @@ -166,7 +159,7 @@ // was disabled), and |*delete_metadata_change_list| contains a change list to // remove all metadata that the processor knows about (the bridge may decide // to implement deletion by other means). - virtual StopSyncResponse ApplyStopSyncChanges( + virtual void ApplyStopSyncChanges( std::unique_ptr<MetadataChangeList> delete_metadata_change_list); // Returns an estimate of memory usage attributed to sync (that is, excludes
diff --git a/components/sync/model_impl/client_tag_based_model_type_processor.cc b/components/sync/model_impl/client_tag_based_model_type_processor.cc index 4e6d16c..2489a35 100644 --- a/components/sync/model_impl/client_tag_based_model_type_processor.cc +++ b/components/sync/model_impl/client_tag_based_model_type_processor.cc
@@ -193,27 +193,13 @@ // and the one received from sync and stored it |activation_request_|. This // indicates that the stored metadata are invalid (e.g. has been // manipulated) and don't belong to the current syncing client. - const ModelTypeSyncBridge::StopSyncResponse response = - ClearMetadataAndResetState(); + ClearMetadataAndResetState(); - switch (response) { - case ModelTypeSyncBridge::StopSyncResponse::kModelStillReadyToSync: - // The model is still ready to sync (with the same |bridge_|) - replay - // the initialization. - model_ready_to_sync_ = true; - // Notify the bridge sync is starting to simulate an enable event. - bridge_->OnSyncStarting(activation_request_); - break; - case ModelTypeSyncBridge::StopSyncResponse::kModelNoLongerReadyToSync: - // Model not ready to sync, so wait until the bridge calls - // ModelReadyToSync(). - DCHECK(!model_ready_to_sync_); - // Notify the bridge sync is starting to simulate an enable event. - bridge_->OnSyncStarting(activation_request_); - // Return early to avoid replying to OnSyncStarting() immediately. This - // will be handled in ModelReadyToSync(). - return; - } + // The model is still ready to sync (with the same |bridge_|) - replay + // the initialization. + model_ready_to_sync_ = true; + // Notify the bridge sync is starting to simulate an enable event. + bridge_->OnSyncStarting(activation_request_); } // Cache GUID verification earlier above guarantees the user is the same. @@ -252,38 +238,21 @@ switch (metadata_fate) { case KEEP_METADATA: { - switch (bridge_->ApplyStopSyncChanges( - /*delete_metadata_change_list=*/nullptr)) { - case ModelTypeSyncBridge::StopSyncResponse::kModelStillReadyToSync: - // The model is still ready to sync (with the same |bridge_|) and same - // sync metadata. - ResetState(KEEP_METADATA); - DCHECK(model_ready_to_sync_); - break; - case ModelTypeSyncBridge::StopSyncResponse::kModelNoLongerReadyToSync: - // Model not ready to sync, so wait until the bridge calls - // ModelReadyToSync(), and meanwhile throw away all metadata. - ResetState(CLEAR_METADATA); - DCHECK(!model_ready_to_sync_); - break; - } + bridge_->ApplyStopSyncChanges( + /*delete_metadata_change_list=*/nullptr); + // The model is still ready to sync (with the same |bridge_|) and same + // sync metadata. + ResetState(KEEP_METADATA); + DCHECK(model_ready_to_sync_); break; } case CLEAR_METADATA: { - switch (ClearMetadataAndResetState()) { - case ModelTypeSyncBridge::StopSyncResponse::kModelStillReadyToSync: - // The model is still ready to sync (with the same |bridge_|) - replay - // the initialization. - ModelReadyToSync(std::make_unique<MetadataBatch>()); - DCHECK(model_ready_to_sync_); - break; - case ModelTypeSyncBridge::StopSyncResponse::kModelNoLongerReadyToSync: - // Model not ready to sync, so wait until the bridge calls - // ModelReadyToSync(). - DCHECK(!model_ready_to_sync_); - break; - } + ClearMetadataAndResetState(); + // The model is still ready to sync (with the same |bridge_|) - replay + // the initialization. + ModelReadyToSync(std::make_unique<MetadataBatch>()); + DCHECK(model_ready_to_sync_); break; } } @@ -291,8 +260,7 @@ DCHECK(!IsConnected()); } -ModelTypeSyncBridge::StopSyncResponse -ClientTagBasedModelTypeProcessor::ClearMetadataAndResetState() { +void ClientTagBasedModelTypeProcessor::ClearMetadataAndResetState() { std::unique_ptr<MetadataChangeList> change_list; // Clear metadata if MergeSyncData() was called before. @@ -309,13 +277,10 @@ DCHECK(entities_.empty()); } - const ModelTypeSyncBridge::StopSyncResponse response = - bridge_->ApplyStopSyncChanges(std::move(change_list)); + bridge_->ApplyStopSyncChanges(std::move(change_list)); // Reset all the internal state of the processor. ResetState(CLEAR_METADATA); - - return response; } bool ClientTagBasedModelTypeProcessor::IsTrackingMetadata() {
diff --git a/components/sync/model_impl/client_tag_based_model_type_processor.h b/components/sync/model_impl/client_tag_based_model_type_processor.h index 5ee7c4a..d9a7888 100644 --- a/components/sync/model_impl/client_tag_based_model_type_processor.h +++ b/components/sync/model_impl/client_tag_based_model_type_processor.h
@@ -116,7 +116,7 @@ // Clears all metadata and directs the bridge to clear the persisted metadata // as well. In addition, it resets the state of the processor and clears all // tracking maps such as |entities_| and |storage_key_to_tag_hash_|. - ModelTypeSyncBridge::StopSyncResponse ClearMetadataAndResetState(); + void ClearMetadataAndResetState(); // Returns true if the model is ready or encountered an error. bool IsModelReadyOrError() const;
diff --git a/components/sync/model_impl/client_tag_based_model_type_processor_unittest.cc b/components/sync/model_impl/client_tag_based_model_type_processor_unittest.cc index 5b90834..c47c1ec6 100644 --- a/components/sync/model_impl/client_tag_based_model_type_processor_unittest.cc +++ b/components/sync/model_impl/client_tag_based_model_type_processor_unittest.cc
@@ -2200,43 +2200,6 @@ } TEST_F(ClientTagBasedModelTypeProcessorTest, - ShouldNotConnectImmediatelyAfterGuidMismatchIfNotReadyToSync) { - // Commit item. - InitializeToReadyState(); - WriteItemAndAck(kKey1, kValue1); - // Reset the processor to simulate a restart. - ResetState(/*keep_db=*/true); - - // Force future stops cause the model to become unready. - bridge()->SetStopSyncResponse( - ModelTypeSyncBridge::StopSyncResponse::kModelNoLongerReadyToSync); - - // A new processor loads the metadata after changing the cache GUID. - bridge()->SetInitialSyncDone(true); - - std::unique_ptr<MetadataBatch> metadata_batch = db()->CreateMetadataBatch(); - sync_pb::ModelTypeState model_type_state(metadata_batch->GetModelTypeState()); - model_type_state.set_cache_guid("WRONG_CACHE_GUID"); - metadata_batch->SetModelTypeState(model_type_state); - - type_processor()->ModelReadyToSync(std::move(metadata_batch)); - ASSERT_TRUE(type_processor()->IsModelReadyToSyncForTest()); - - OnSyncStarting(); - - // Model should not be ready to sync. - ASSERT_FALSE(type_processor()->IsModelReadyToSyncForTest()); - // OnSyncStarting() should NOT have completed. - EXPECT_EQ(nullptr, worker()); - // Upon a mismatch, metadata should have been cleared. - EXPECT_EQ(0U, db()->metadata_count()); - - // Calling ModelReadyToSync() should complete OnSyncStarting(). - type_processor()->ModelReadyToSync(std::make_unique<MetadataBatch>()); - EXPECT_NE(nullptr, worker()); -} - -TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldClearOrphanMetadataInGetLocalChangesWhenDataIsMissing) { InitializeToReadyState(); bridge()->WriteItem(kKey1, kValue1);
diff --git a/components/sync/model_impl/syncable_service_based_bridge.cc b/components/sync/model_impl/syncable_service_based_bridge.cc index 8225fe3..6fb89ab1 100644 --- a/components/sync/model_impl/syncable_service_based_bridge.cc +++ b/components/sync/model_impl/syncable_service_based_bridge.cc
@@ -423,8 +423,7 @@ return ConflictResolution::UseLocal(); } -ModelTypeSyncBridge::StopSyncResponse -SyncableServiceBasedBridge::ApplyStopSyncChanges( +void SyncableServiceBasedBridge::ApplyStopSyncChanges( std::unique_ptr<MetadataChangeList> delete_metadata_change_list) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(store_); @@ -438,8 +437,6 @@ syncable_service_->StopSyncing(type_); syncable_service_started_ = false; } - - return StopSyncResponse::kModelStillReadyToSync; } size_t SyncableServiceBasedBridge::EstimateSyncOverheadMemoryUsage() const {
diff --git a/components/sync/model_impl/syncable_service_based_bridge.h b/components/sync/model_impl/syncable_service_based_bridge.h index 04dda28..1576aab8 100644 --- a/components/sync/model_impl/syncable_service_based_bridge.h +++ b/components/sync/model_impl/syncable_service_based_bridge.h
@@ -64,7 +64,7 @@ ConflictResolution ResolveConflict( const EntityData& local_data, const EntityData& remote_data) const override; - StopSyncResponse ApplyStopSyncChanges( + void ApplyStopSyncChanges( std::unique_ptr<MetadataChangeList> delete_metadata_change_list) override; size_t EstimateSyncOverheadMemoryUsage() const override;
diff --git a/components/sync/user_events/user_event_sync_bridge.cc b/components/sync/user_events/user_event_sync_bridge.cc index ae12693..5f8be12 100644 --- a/components/sync/user_events/user_event_sync_bridge.cc +++ b/components/sync/user_events/user_event_sync_bridge.cc
@@ -145,14 +145,12 @@ return GetStorageKeyFromSpecifics(entity_data.specifics.user_event()); } -ModelTypeSyncBridge::StopSyncResponse UserEventSyncBridge::ApplyStopSyncChanges( +void UserEventSyncBridge::ApplyStopSyncChanges( std::unique_ptr<MetadataChangeList> delete_metadata_change_list) { if (delete_metadata_change_list) { store_->DeleteAllDataAndMetadata(base::BindOnce( &UserEventSyncBridge::OnCommit, weak_ptr_factory_.GetWeakPtr())); } - - return StopSyncResponse::kModelStillReadyToSync; } void UserEventSyncBridge::RecordUserEvent(
diff --git a/components/sync/user_events/user_event_sync_bridge.h b/components/sync/user_events/user_event_sync_bridge.h index 2979732a..a3300dc 100644 --- a/components/sync/user_events/user_event_sync_bridge.h +++ b/components/sync/user_events/user_event_sync_bridge.h
@@ -42,7 +42,7 @@ void GetAllDataForDebugging(DataCallback callback) override; std::string GetClientTag(const EntityData& entity_data) override; std::string GetStorageKey(const EntityData& entity_data) override; - StopSyncResponse ApplyStopSyncChanges( + void ApplyStopSyncChanges( std::unique_ptr<MetadataChangeList> delete_metadata_change_list) override; void RecordUserEvent(std::unique_ptr<sync_pb::UserEventSpecifics> specifics);
diff --git a/components/sync/user_events/user_event_sync_bridge_unittest.cc b/components/sync/user_events/user_event_sync_bridge_unittest.cc index a15f370..41f8967 100644 --- a/components/sync/user_events/user_event_sync_bridge_unittest.cc +++ b/components/sync/user_events/user_event_sync_bridge_unittest.cc
@@ -216,9 +216,7 @@ bridge()->RecordUserEvent(std::make_unique<UserEventSpecifics>(specifics)); ASSERT_THAT(GetAllData(), SizeIs(1)); - EXPECT_THAT( - bridge()->ApplyStopSyncChanges(WriteBatch::CreateMetadataChangeList()), - Eq(ModelTypeSyncBridge::StopSyncResponse::kModelStillReadyToSync)); + bridge()->ApplyStopSyncChanges(WriteBatch::CreateMetadataChangeList()); // The bridge may asynchronously query the store to choose what to delete. base::RunLoop().RunUntilIdle();
diff --git a/components/sync_sessions/session_sync_bridge.cc b/components/sync_sessions/session_sync_bridge.cc index c05c5647..4f5fead 100644 --- a/components/sync_sessions/session_sync_bridge.cc +++ b/components/sync_sessions/session_sync_bridge.cc
@@ -292,7 +292,7 @@ return SessionStore::GetStorageKey(entity_data.specifics.session()); } -ModelTypeSyncBridge::StopSyncResponse SessionSyncBridge::ApplyStopSyncChanges( +void SessionSyncBridge::ApplyStopSyncChanges( std::unique_ptr<MetadataChangeList> delete_metadata_change_list) { DCHECK(store_); local_session_event_router_->Stop(); @@ -300,7 +300,6 @@ store_->DeleteAllDataAndMetadata(); } syncing_.reset(); - return StopSyncResponse::kModelStillReadyToSync; } std::unique_ptr<LocalSessionEventHandlerImpl::WriteBatch>
diff --git a/components/sync_sessions/session_sync_bridge.h b/components/sync_sessions/session_sync_bridge.h index 7f9e142..aa14ae3 100644 --- a/components/sync_sessions/session_sync_bridge.h +++ b/components/sync_sessions/session_sync_bridge.h
@@ -64,9 +64,8 @@ void GetAllDataForDebugging(DataCallback callback) override; std::string GetClientTag(const syncer::EntityData& entity_data) override; std::string GetStorageKey(const syncer::EntityData& entity_data) override; - StopSyncResponse ApplyStopSyncChanges( - std::unique_ptr<syncer::MetadataChangeList> delete_metadata_change_list) - override; + void ApplyStopSyncChanges(std::unique_ptr<syncer::MetadataChangeList> + delete_metadata_change_list) override; // LocalSessionEventHandlerImpl::Delegate implementation. std::unique_ptr<LocalSessionEventHandlerImpl::WriteBatch>
diff --git a/components/tracing/common/trace_startup_config.cc b/components/tracing/common/trace_startup_config.cc index 4376acb3..6c6392c 100644 --- a/components/tracing/common/trace_startup_config.cc +++ b/components/tracing/common/trace_startup_config.cc
@@ -31,6 +31,9 @@ const size_t kTraceConfigFileSizeLimit = 64 * 1024; const int kDefaultStartupDuration = 5; +// 95th percentile size of current startup traces size uploaded. +const size_t kMaxStartupTraceSizeInKb = 300; + // Trace config file path: // - Android: /data/local/chrome-trace-config.json // - Others: specified by --trace-config-file flag. @@ -70,6 +73,7 @@ {base::GetCurrentProcId()}); // First 10k events at start are sufficient to debug startup traces. trace_config.SetTraceBufferSizeInEvents(10000); + trace_config.SetTraceBufferSizeInKb(kMaxStartupTraceSizeInKb); trace_config.SetProcessFilterConfig(process_config); // Enable argument filter since we could be background tracing. trace_config.EnableArgumentFilter();
diff --git a/components/update_client/ping_manager_unittest.cc b/components/update_client/ping_manager_unittest.cc index 8520616..b48a905e 100644 --- a/components/update_client/ping_manager_unittest.cc +++ b/components/update_client/ping_manager_unittest.cc
@@ -139,7 +139,8 @@ EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); const auto msg = interceptor->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(msg); + const auto root = base::JSONReader::Read(msg); + ASSERT_TRUE(root); const auto* request = root->FindKey("request"); ASSERT_TRUE(request); EXPECT_TRUE(request->FindKey("@os")); @@ -219,7 +220,8 @@ EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); const auto msg = interceptor->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(msg); + const auto root = base::JSONReader::Read(msg); + ASSERT_TRUE(root); const auto* request = root->FindKey("request"); const auto& app = request->FindKey("app")->GetList()[0]; EXPECT_EQ("abc", app.FindKey("appid")->GetString()); @@ -266,7 +268,8 @@ EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); const auto msg = interceptor->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(msg); + const auto root = base::JSONReader::Read(msg); + ASSERT_TRUE(root); const auto* request = root->FindKey("request"); const auto& app = request->FindKey("app")->GetList()[0]; EXPECT_EQ("abc", app.FindKey("appid")->GetString()); @@ -316,7 +319,8 @@ EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); const auto msg = interceptor->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(msg); + const auto root = base::JSONReader::Read(msg); + ASSERT_TRUE(root); const auto* request = root->FindKey("request"); const auto& app = request->FindKey("app")->GetList()[0]; EXPECT_EQ("abc", app.FindKey("appid")->GetString()); @@ -350,7 +354,8 @@ EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); const auto msg = interceptor->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(msg); + const auto root = base::JSONReader::Read(msg); + ASSERT_TRUE(root); const auto* request = root->FindKey("request"); const auto& app = request->FindKey("app")->GetList()[0]; EXPECT_EQ("abc", app.FindKey("appid")->GetString()); @@ -414,7 +419,8 @@ EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); const auto msg = interceptor->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(msg); + const auto root = base::JSONReader::Read(msg); + ASSERT_TRUE(root); const auto* request = root->FindKey("request"); const auto& app = request->FindKey("app")->GetList()[0]; EXPECT_EQ("abc", app.FindKey("appid")->GetString());
diff --git a/components/update_client/protocol_parser_json.cc b/components/update_client/protocol_parser_json.cc index d7d0037..09dd08f6 100644 --- a/components/update_client/protocol_parser_json.cc +++ b/components/update_client/protocol_parser_json.cc
@@ -282,7 +282,7 @@ ParseError("Missing secure JSON prefix."); return false; } - const auto doc = base::JSONReader().ReadDeprecated( + const auto doc = base::JSONReader::Read( {response_json.begin() + std::char_traits<char>::length(kJSONPrefix), response_json.end()}); if (!doc) {
diff --git a/components/update_client/update_checker_unittest.cc b/components/update_client/update_checker_unittest.cc index 4ab14f6..c74a51f 100644 --- a/components/update_client/update_checker_unittest.cc +++ b/components/update_client/update_checker_unittest.cc
@@ -284,7 +284,8 @@ // Sanity check the request. const auto& request = post_interceptor_->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(request); + const auto root = base::JSONReader::Read(request); + ASSERT_TRUE(root); const auto* request = root->FindKey("request"); ASSERT_TRUE(request); EXPECT_TRUE(request->FindKey("@os")); @@ -431,7 +432,8 @@ const auto request = post_interceptor_->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(request); + const auto root = base::JSONReader::Read(request); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(kUpdateItemId, app.FindKey("appid")->GetString()); EXPECT_EQ("0.9", app.FindKey("version")->GetString()); @@ -488,7 +490,8 @@ const auto request = post_interceptor_->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(request); + const auto root = base::JSONReader::Read(request); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(kUpdateItemId, app.FindKey("appid")->GetString()); EXPECT_EQ("0.9", app.FindKey("version")->GetString()); @@ -570,7 +573,8 @@ // The request must contain dlpref="cacheable". const auto request = post_interceptor_->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(request); + const auto root = base::JSONReader().Read(request); + ASSERT_TRUE(root); EXPECT_EQ("cacheable", root->FindKey("request")->FindKey("dlpref")->GetString()); } else { @@ -608,7 +612,8 @@ // Sanity check the request. const auto& request = post_interceptor_->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(request); + const auto root = base::JSONReader::Read(request); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(kUpdateItemId, app.FindKey("appid")->GetString()); EXPECT_EQ("0.9", app.FindKey("version")->GetString()); @@ -711,11 +716,13 @@ if (use_JSON_) { const auto root1 = - base::JSONReader().ReadDeprecated(post_interceptor_->GetRequestBody(0)); + base::JSONReader::Read(post_interceptor_->GetRequestBody(0)); + ASSERT_TRUE(root1); const auto& app1 = root1->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(5, app1.FindPath({"ping", "r"})->GetInt()); const auto root2 = - base::JSONReader().ReadDeprecated(post_interceptor_->GetRequestBody(1)); + base::JSONReader::Read(post_interceptor_->GetRequestBody(1)); + ASSERT_TRUE(root2); const auto& app2 = root2->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(3383, app2.FindPath({"ping", "rd"})->GetInt()); EXPECT_TRUE(app2.FindPath({"ping", "ping_freshness"})->is_string()); @@ -783,23 +790,26 @@ if (use_JSON_) { { - const auto root = base::JSONReader().ReadDeprecated( - post_interceptor_->GetRequestBody(0)); + const auto root = + base::JSONReader::Read(post_interceptor_->GetRequestBody(0)); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(10, app.FindPath({"ping", "a"})->GetInt()); EXPECT_EQ(-2, app.FindPath({"ping", "r"})->GetInt()); } { - const auto root = base::JSONReader().ReadDeprecated( - post_interceptor_->GetRequestBody(1)); + const auto root = + base::JSONReader::Read(post_interceptor_->GetRequestBody(1)); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(3383, app.FindPath({"ping", "ad"})->GetInt()); EXPECT_EQ(3383, app.FindPath({"ping", "rd"})->GetInt()); EXPECT_TRUE(app.FindPath({"ping", "ping_freshness"})->is_string()); } { - const auto root = base::JSONReader().ReadDeprecated( - post_interceptor_->GetRequestBody(2)); + const auto root = + base::JSONReader::Read(post_interceptor_->GetRequestBody(2)); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(3383, app.FindPath({"ping", "rd"})->GetInt()); EXPECT_TRUE(app.FindPath({"ping", "ping_freshness"})->is_string()); @@ -839,7 +849,8 @@ RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(request); + const auto root = base::JSONReader::Read(request); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ("ondemand", app.FindKey("installsource")->GetString()); @@ -867,7 +878,8 @@ RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(request); + const auto root = base::JSONReader::Read(request); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ("sideload", app.FindKey("installsource")->GetString()); @@ -895,7 +907,8 @@ RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(request); + const auto root = base::JSONReader::Read(request); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_FALSE(app.FindKey("installsource")); } else { @@ -919,7 +932,8 @@ RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(request); + const auto root = base::JSONReader::Read(request); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ("webstore", app.FindKey("installsource")->GetString()); EXPECT_EQ("external", app.FindKey("installedby")->GetString()); @@ -953,7 +967,8 @@ RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(request); + const auto root = base::JSONReader::Read(request); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(true, app.FindKey("enabled")->GetBool()); EXPECT_FALSE(app.FindKey("disabled")); @@ -979,7 +994,8 @@ RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(request); + const auto root = base::JSONReader::Read(request); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(true, app.FindKey("enabled")->GetBool()); EXPECT_FALSE(app.FindKey("disabled")); @@ -1005,7 +1021,8 @@ RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(request); + const auto root = base::JSONReader::Read(request); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(false, app.FindKey("enabled")->GetBool()); const auto& disabled = app.FindKey("disabled")->GetList(); @@ -1032,7 +1049,8 @@ RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(request); + const auto root = base::JSONReader::Read(request); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(false, app.FindKey("enabled")->GetBool()); const auto& disabled = app.FindKey("disabled")->GetList(); @@ -1060,7 +1078,8 @@ RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(request); + const auto root = base::JSONReader::Read(request); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(false, app.FindKey("enabled")->GetBool()); const auto& disabled = app.FindKey("disabled")->GetList(); @@ -1092,7 +1111,8 @@ RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(request); + const auto root = base::JSONReader::Read(request); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(false, app.FindKey("enabled")->GetBool()); const auto& disabled = app.FindKey("disabled")->GetList(); @@ -1143,7 +1163,8 @@ RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(request); + const auto root = base::JSONReader::Read(request); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(kUpdateItemId, app.FindKey("appid")->GetString()); EXPECT_EQ("0.9", app.FindKey("version")->GetString()); @@ -1176,7 +1197,8 @@ RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(request); + const auto root = base::JSONReader::Read(request); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(kUpdateItemId, app.FindKey("appid")->GetString()); EXPECT_EQ("0.9", app.FindKey("version")->GetString()); @@ -1209,7 +1231,8 @@ RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(request); + const auto root = base::JSONReader::Read(request); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(kUpdateItemId, app.FindKey("appid")->GetString()); EXPECT_EQ("0.9", app.FindKey("version")->GetString()); @@ -1242,7 +1265,8 @@ RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(request); + const auto root = base::JSONReader::Read(request); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(kUpdateItemId, app.FindKey("appid")->GetString()); EXPECT_EQ("0.9", app.FindKey("version")->GetString()); @@ -1317,7 +1341,8 @@ const auto& request = post_interceptor_->GetRequestBody(0); if (use_JSON_) { - const auto root = base::JSONReader().ReadDeprecated(request); + const auto root = base::JSONReader::Read(request); + ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(kUpdateItemId, app.FindKey("appid")->GetString()); EXPECT_EQ("0.9", app.FindKey("version")->GetString());
diff --git a/components/variations/BUILD.gn b/components/variations/BUILD.gn index c764b7d..5caa15ce 100644 --- a/components/variations/BUILD.gn +++ b/components/variations/BUILD.gn
@@ -21,8 +21,6 @@ "client_filterable_state.h", "entropy_provider.cc", "entropy_provider.h", - "experiment_labels.cc", - "experiment_labels.h", "hashing.cc", "hashing.h", "metrics.cc", @@ -49,8 +47,6 @@ "variations_associated_data.h", "variations_crash_keys.cc", "variations_crash_keys.h", - "variations_experiment_util.cc", - "variations_experiment_util.h", "variations_http_header_provider.cc", "variations_http_header_provider.h", "variations_id_collection.cc", @@ -103,12 +99,16 @@ } android_library("load_seed_result_enum_java") { - deps = [ "//base:base_java" ] + deps = [ + "//base:base_java", + ] srcjar_deps = [ ":load_seed_result_enum_srcjar" ] } java_cpp_enum("load_seed_result_enum_srcjar") { - sources = [ "metrics.h" ] + sources = [ + "metrics.h", + ] } } @@ -135,7 +135,6 @@ "active_field_trials_unittest.cc", "child_process_field_trial_syncer_unittest.cc", "entropy_provider_unittest.cc", - "experiment_labels_unittest.cc", "hashing_unittest.cc", "net/variations_command_line_unittest.cc", "net/variations_http_headers_unittest.cc",
diff --git a/components/variations/experiment_labels.cc b/components/variations/experiment_labels.cc deleted file mode 100644 index 1b0d85a..0000000 --- a/components/variations/experiment_labels.cc +++ /dev/null
@@ -1,49 +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 "components/variations/experiment_labels.h" - -#include <vector> - -#include "base/logging.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_split.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "components/variations/variations_associated_data.h" -#include "components/variations/variations_experiment_util.h" - -namespace variations { -namespace { - -const char kVariationPrefix[] = "CrVar"; - -} // namespace - -base::string16 ExtractNonVariationLabels(const base::string16& labels) { - // First, split everything by the label separator. - std::vector<base::StringPiece16> entries = base::SplitStringPiece( - labels, base::StringPiece16(&kExperimentLabelSeparator, 1), - base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); - - // For each label, keep the ones that do not look like a Variations label. - base::string16 non_variation_labels; - for (const base::StringPiece16& entry : entries) { - if (entry.empty() || - base::StartsWith(entry, - base::ASCIIToUTF16(kVariationPrefix), - base::CompareCase::INSENSITIVE_ASCII)) { - continue; - } - - // Dump the whole thing, including the timestamp. - if (!non_variation_labels.empty()) - non_variation_labels += kExperimentLabelSeparator; - entry.AppendToString(&non_variation_labels); - } - - return non_variation_labels; -} - -} // namespace variations
diff --git a/components/variations/experiment_labels.h b/components/variations/experiment_labels.h deleted file mode 100644 index cd10825..0000000 --- a/components/variations/experiment_labels.h +++ /dev/null
@@ -1,20 +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 COMPONENTS_VARIATIONS_EXPERIMENT_LABELS_H_ -#define COMPONENTS_VARIATIONS_EXPERIMENT_LABELS_H_ - -#include "base/metrics/field_trial.h" -#include "base/strings/string16.h" - -namespace variations { - -// Takes the value of experiment_labels from the registry and returns a valid -// experiment_labels string value containing only the labels that are not -// associated with Chrome Variations. -base::string16 ExtractNonVariationLabels(const base::string16& labels); - -} // namespace variations - -#endif // COMPONENTS_VARIATIONS_EXPERIMENT_LABELS_H_
diff --git a/components/variations/experiment_labels_unittest.cc b/components/variations/experiment_labels_unittest.cc deleted file mode 100644 index 797f57a..0000000 --- a/components/variations/experiment_labels_unittest.cc +++ /dev/null
@@ -1,87 +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 "components/variations/experiment_labels.h" - -#include <stddef.h> - -#include <set> -#include <string> -#include <vector> - -#include "base/macros.h" -#include "base/metrics/field_trial.h" -#include "base/stl_util.h" -#include "base/strings/string_split.h" -#include "base/strings/utf_string_conversions.h" -#include "components/variations/variations_associated_data.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace variations { - -TEST(ExperimentLabelsTest, ExtractNonVariationLabels) { - struct { - const char* input_label; - const char* expected_output; - } test_cases[] = { - // Empty - {"", ""}, - // One - {"gcapi_brand=123|Tue, 21 Jan 2014 15:30:21 GMT", - "gcapi_brand=123|Tue, 21 Jan 2014 15:30:21 GMT"}, - // Three - {"CrVar1=123|Tue, 21 Jan 2014 15:30:21 GMT;" - "experiment1=456|Tue, 21 Jan 2014 15:30:21 GMT;" - "experiment2=789|Tue, 21 Jan 2014 15:30:21 GMT;" - "CrVar1=123|Tue, 21 Jan 2014 15:30:21 GMT", - "experiment1=456|Tue, 21 Jan 2014 15:30:21 GMT;" - "experiment2=789|Tue, 21 Jan 2014 15:30:21 GMT"}, - // One and one Variation - {"gcapi_brand=123|Tue, 21 Jan 2014 15:30:21 GMT;" - "CrVar1=3310002|Tue, 21 Jan 2014 15:30:21 GMT", - "gcapi_brand=123|Tue, 21 Jan 2014 15:30:21 GMT"}, - // One and one Variation, flipped - {"CrVar1=3310002|Tue, 21 Jan 2014 15:30:21 GMT;" - "gcapi_brand=123|Tue, 21 Jan 2014 15:30:21 GMT", - "gcapi_brand=123|Tue, 21 Jan 2014 15:30:21 GMT"}, - // Sandwiched - {"CrVar1=3310002|Tue, 21 Jan 2014 15:30:21 GMT;" - "gcapi_brand=123|Tue, 21 Jan 2014 15:30:21 GMT;" - "CrVar2=3310003|Tue, 21 Jan 2014 15:30:21 GMT;" - "CrVar3=3310004|Tue, 21 Jan 2014 15:30:21 GMT", - "gcapi_brand=123|Tue, 21 Jan 2014 15:30:21 GMT"}, - // Only Variations - {"CrVar1=3310002|Tue, 21 Jan 2014 15:30:21 GMT;" - "CrVar2=3310003|Tue, 21 Jan 2014 15:30:21 GMT;" - "CrVar3=3310004|Tue, 21 Jan 2014 15:30:21 GMT", - ""}, - // Empty values - {"gcapi_brand=123|Tue, 21 Jan 2014 15:30:21 GMT;" - "CrVar1=3310002|Tue, 21 Jan 2014 15:30:21 GMT", - "gcapi_brand=123|Tue, 21 Jan 2014 15:30:21 GMT"}, - // Trailing semicolon - {"gcapi_brand=123|Tue, 21 Jan 2014 15:30:21 GMT;" - "CrVar1=3310002|Tue, 21 Jan 2014 15:30:21 GMT;", // Note the semi here. - "gcapi_brand=123|Tue, 21 Jan 2014 15:30:21 GMT"}, - // Semis - {";;;;", ""}, - // Three non-Variation labels - // Testing that the order is preserved. - {"experiment1=456|Tue, 21 Jan 2014 15:30:21 GMT;" - "experiment2=789|Tue, 21 Jan 2014 15:30:21 GMT;" - "experiment3=123|Tue, 21 Jan 2014 15:30:21 GMT", - "experiment1=456|Tue, 21 Jan 2014 15:30:21 GMT;" - "experiment2=789|Tue, 21 Jan 2014 15:30:21 GMT;" - "experiment3=123|Tue, 21 Jan 2014 15:30:21 GMT"}, - }; - - for (size_t i = 0; i < base::size(test_cases); ++i) { - std::string non_variation_labels = base::UTF16ToUTF8( - ExtractNonVariationLabels( - base::ASCIIToUTF16(test_cases[i].input_label))); - EXPECT_EQ(test_cases[i].expected_output, non_variation_labels); - } -} - -} // namespace variations
diff --git a/components/variations/variations_experiment_util.cc b/components/variations/variations_experiment_util.cc deleted file mode 100644 index 9cf78bba..0000000 --- a/components/variations/variations_experiment_util.cc +++ /dev/null
@@ -1,54 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/variations/variations_experiment_util.h" - -#include <vector> - -#include "base/logging.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" -#include "base/time/time.h" - -namespace variations { - -const base::char16 kExperimentLabelSeparator = ';'; - -namespace { - -const char* const kDays[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; - -const char* const kMonths[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - -} // namespace - -base::string16 BuildExperimentDateString(const base::Time& current_time) { - // The Google Update experiment_labels timestamp format is: - // "DAY, DD0 MON YYYY HH0:MI0:SE0 TZ" - // DAY = 3 character day of week, - // DD0 = 2 digit day of month, - // MON = 3 character month of year, - // YYYY = 4 digit year, - // HH0 = 2 digit hour, - // MI0 = 2 digit minute, - // SE0 = 2 digit second, - // TZ = 3 character timezone - base::Time::Exploded then = {}; - current_time.UTCExplode(&then); - then.year += 1; - DCHECK(then.HasValidValues()); - - return base::UTF8ToUTF16( - base::StringPrintf("%s, %02d %s %d %02d:%02d:%02d GMT", - kDays[then.day_of_week], - then.day_of_month, - kMonths[then.month - 1], - then.year, - then.hour, - then.minute, - then.second)); -} - -} // namespace variations
diff --git a/components/variations/variations_experiment_util.h b/components/variations/variations_experiment_util.h deleted file mode 100644 index c9c23f40..0000000 --- a/components/variations/variations_experiment_util.h +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_VARIATIONS_VARIATIONS_EXPERIMENT_UTIL_H_ -#define COMPONENTS_VARIATIONS_VARIATIONS_EXPERIMENT_UTIL_H_ - -#include "base/strings/string16.h" - -namespace base { -class Time; -} - -namespace variations { - -// The separator used to separate items in experiment labels. -extern const base::char16 kExperimentLabelSeparator; - -// Constructs a date string in the format understood by Google Update for the -// |current_time| plus one year. -base::string16 BuildExperimentDateString(const base::Time& current_time); - -} // namespace variations - -#endif // COMPONENTS_VARIATIONS_VARIATIONS_EXPERIMENT_UTIL_H_
diff --git a/components/viz/service/display/overlay_candidate.cc b/components/viz/service/display/overlay_candidate.cc index 2ec72ea..f1a25012 100644 --- a/components/viz/service/display/overlay_candidate.cc +++ b/components/viz/service/display/overlay_candidate.cc
@@ -274,7 +274,9 @@ DisplayResourceProvider* resource_provider, const TextureDrawQuad* quad, OverlayCandidate* candidate) { - if (quad->background_color != SK_ColorTRANSPARENT) + if (quad->background_color != SK_ColorTRANSPARENT && + (quad->background_color != SK_ColorBLACK || + quad->ShouldDrawWithBlending())) return false; if (!FromDrawQuadResource(resource_provider, quad, quad->resource_id(), quad->y_flipped, candidate)) {
diff --git a/components/viz/service/display/overlay_unittest.cc b/components/viz/service/display/overlay_unittest.cc index 645fee87..e7a9569 100644 --- a/components/viz/service/display/overlay_unittest.cc +++ b/components/viz/service/display/overlay_unittest.cc
@@ -1025,6 +1025,25 @@ TextureDrawQuad* quad = CreateFullscreenCandidateQuad( resource_provider_.get(), child_resource_provider_.get(), child_provider_.get(), pass->shared_quad_state_list.back(), pass.get()); + quad->background_color = SK_ColorRED; + + OverlayCandidateList candidate_list; + OverlayProcessor::FilterOperationsMap render_pass_filters; + OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters; + RenderPassList pass_list; + pass_list.push_back(std::move(pass)); + overlay_processor_->ProcessForOverlays( + resource_provider_.get(), &pass_list, GetIdentityColorMatrix(), + render_pass_filters, render_pass_backdrop_filters, &candidate_list, + nullptr, nullptr, &damage_rect_, &content_bounds_); + EXPECT_EQ(0U, candidate_list.size()); +} + +TEST_F(SingleOverlayOnTopTest, AcceptBlackBackgroundColor) { + std::unique_ptr<RenderPass> pass = CreateRenderPass(); + TextureDrawQuad* quad = CreateFullscreenCandidateQuad( + resource_provider_.get(), child_resource_provider_.get(), + child_provider_.get(), pass->shared_quad_state_list.back(), pass.get()); quad->background_color = SK_ColorBLACK; OverlayCandidateList candidate_list; @@ -1036,6 +1055,26 @@ resource_provider_.get(), &pass_list, GetIdentityColorMatrix(), render_pass_filters, render_pass_backdrop_filters, &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_); + EXPECT_EQ(1U, candidate_list.size()); +} + +TEST_F(SingleOverlayOnTopTest, RejectBlackBackgroundColorWithBlending) { + std::unique_ptr<RenderPass> pass = CreateRenderPass(); + TextureDrawQuad* quad = CreateFullscreenCandidateQuad( + resource_provider_.get(), child_resource_provider_.get(), + child_provider_.get(), pass->shared_quad_state_list.back(), pass.get()); + quad->background_color = SK_ColorBLACK; + quad->needs_blending = true; + + OverlayCandidateList candidate_list; + OverlayProcessor::FilterOperationsMap render_pass_filters; + OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters; + RenderPassList pass_list; + pass_list.push_back(std::move(pass)); + overlay_processor_->ProcessForOverlays( + resource_provider_.get(), &pass_list, GetIdentityColorMatrix(), + render_pass_filters, render_pass_backdrop_filters, &candidate_list, + nullptr, nullptr, &damage_rect_, &content_bounds_); EXPECT_EQ(0U, candidate_list.size()); }
diff --git a/content/browser/android/navigation_handle_proxy.cc b/content/browser/android/navigation_handle_proxy.cc index ec48e73e6..286cddb0 100644 --- a/content/browser/android/navigation_handle_proxy.cc +++ b/content/browser/android/navigation_handle_proxy.cc
@@ -4,29 +4,98 @@ #include "content/browser/android/navigation_handle_proxy.h" +#include "base/android/jni_android.h" +#include "base/android/jni_string.h" +#include "base/android/scoped_java_ref.h" #include "content/public/browser/navigation_handle.h" -#include "jni/NavigationHandleProxy_jni.h" +#include "jni/NavigationHandle_jni.h" + +using base::android::AttachCurrentThread; +using base::android::ConvertUTF8ToJavaString; +using base::android::JavaParamRef; +using base::android::ScopedJavaLocalRef; namespace content { +NavigationHandleProxy::NavigationHandleProxy( + NavigationHandle* cpp_navigation_handle) + : cpp_navigation_handle_(cpp_navigation_handle) { + JNIEnv* env = AttachCurrentThread(); + java_navigation_handle_ = Java_NavigationHandle_Constructor( + env, reinterpret_cast<jlong>(this), + ConvertUTF8ToJavaString(env, cpp_navigation_handle_->GetURL().spec()), + cpp_navigation_handle_->IsInMainFrame(), + cpp_navigation_handle_->IsSameDocument(), + cpp_navigation_handle_->IsRendererInitiated()); +} + +void NavigationHandleProxy::DidRedirect() { + JNIEnv* env = AttachCurrentThread(); + Java_NavigationHandle_didRedirect( + env, java_navigation_handle_, + ConvertUTF8ToJavaString(env, cpp_navigation_handle_->GetURL().spec())); +} + +void NavigationHandleProxy::DidFinish() { + JNIEnv* env = AttachCurrentThread(); + // Matches logic in + // components/navigation_interception/navigation_params_android.cc + ScopedJavaLocalRef<jstring> jstring_url(ConvertUTF8ToJavaString( + env, cpp_navigation_handle_->GetBaseURLForDataURL().is_empty() + ? cpp_navigation_handle_->GetURL().spec() + : cpp_navigation_handle_->GetBaseURLForDataURL() + .possibly_invalid_spec())); + + bool is_fragment_navigation = cpp_navigation_handle_->IsSameDocument(); + + if (cpp_navigation_handle_->HasCommitted()) { + // See http://crbug.com/251330 for why it's determined this way. + url::Replacements<char> replacements; + replacements.ClearRef(); + bool urls_same_ignoring_fragment = + cpp_navigation_handle_->GetURL().ReplaceComponents(replacements) == + cpp_navigation_handle_->GetPreviousURL().ReplaceComponents( + replacements); + is_fragment_navigation &= urls_same_ignoring_fragment; + } + + Java_NavigationHandle_didFinish( + env, java_navigation_handle_, jstring_url, + cpp_navigation_handle_->IsErrorPage(), + cpp_navigation_handle_->HasCommitted(), is_fragment_navigation, + cpp_navigation_handle_->IsDownload(), + cpp_navigation_handle_->HasCommitted() + ? cpp_navigation_handle_->GetPageTransition() + : -1, + cpp_navigation_handle_->GetNetErrorCode(), + // TODO(shaktisahu): Change default status to -1 after fixing + // crbug/690041. + cpp_navigation_handle_->GetResponseHeaders() + ? cpp_navigation_handle_->GetResponseHeaders()->response_code() + : 200); +} + +NavigationHandleProxy::~NavigationHandleProxy() { + JNIEnv* env = AttachCurrentThread(); + Java_NavigationHandle_release(env, java_navigation_handle_); +} + // Called from Java. void NavigationHandleProxy::SetRequestHeader( JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj, - const base::android::JavaParamRef<jstring>& name, - const base::android::JavaParamRef<jstring>& value) { - navigation_handle_->SetRequestHeader( - base::android::ConvertJavaStringToUTF8(name), - base::android::ConvertJavaStringToUTF8(value)); + const JavaParamRef<jobject>& obj, + const JavaParamRef<jstring>& name, + const JavaParamRef<jstring>& value) { + cpp_navigation_handle_->SetRequestHeader(ConvertJavaStringToUTF8(name), + ConvertJavaStringToUTF8(value)); } // Called from Java. void NavigationHandleProxy::RemoveRequestHeader( JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj, - const base::android::JavaParamRef<jstring>& name) { - navigation_handle_->RemoveRequestHeader( - base::android::ConvertJavaStringToUTF8(name)); + const JavaParamRef<jobject>& obj, + const JavaParamRef<jstring>& name) { + cpp_navigation_handle_->RemoveRequestHeader(ConvertJavaStringToUTF8(name)); } } // namespace content
diff --git a/content/browser/android/navigation_handle_proxy.h b/content/browser/android/navigation_handle_proxy.h index ec2e4a0..af3797c 100644 --- a/content/browser/android/navigation_handle_proxy.h +++ b/content/browser/android/navigation_handle_proxy.h
@@ -16,11 +16,25 @@ class NavigationHandle; -// JNI bridge for using a content::NavigationHandle from Java. -class NavigationHandleProxy { +// JNI Bridge in between: +// - [C++] NavigationHandle +// - [Java] NavigationHandle +class NavigationHandleProxy final { public: - explicit NavigationHandleProxy(content::NavigationHandle* navigation_handle) - : navigation_handle_(navigation_handle) {} + explicit NavigationHandleProxy(NavigationHandle* cpp_navigation_handle); + ~NavigationHandleProxy(); + + NavigationHandle* cpp_navigation_handle() const { + return cpp_navigation_handle_; + } + base::android::ScopedJavaGlobalRef<jobject> java_navigation_handle() const { + return java_navigation_handle_; + } + + // |DidRedirect| and |DidFinish| updates the NavigationHandle on the java side + // with the state from the C++ side. + void DidRedirect(); + void DidFinish(); // Called from Java. void SetRequestHeader(JNIEnv* env, @@ -33,10 +47,9 @@ const base::android::JavaParamRef<jobject>& obj, const base::android::JavaParamRef<jstring>& name); - jlong JavaThis() const { return reinterpret_cast<jlong>(this); } - private: - content::NavigationHandle* navigation_handle_; + base::android::ScopedJavaGlobalRef<jobject> java_navigation_handle_; + NavigationHandle* cpp_navigation_handle_ = nullptr; }; } // namespace content
diff --git a/content/browser/android/web_contents_observer_proxy.cc b/content/browser/android/web_contents_observer_proxy.cc index 1bca9e7..b965c98 100644 --- a/content/browser/android/web_contents_observer_proxy.cc +++ b/content/browser/android/web_contents_observer_proxy.cc
@@ -10,9 +10,11 @@ #include "base/android/jni_string.h" #include "base/android/scoped_java_ref.h" #include "base/optional.h" +#include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" #include "base/trace_event/trace_event.h" #include "content/browser/android/navigation_handle_proxy.h" +#include "content/browser/frame_host/navigation_handle_impl.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/navigation_details.h" @@ -127,68 +129,29 @@ void WebContentsObserverProxy::DidStartNavigation( NavigationHandle* navigation_handle) { - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jstring> jstring_url( - ConvertUTF8ToJavaString(env, navigation_handle->GetURL().spec())); - NavigationHandleProxy navigation_handle_proxy(navigation_handle); Java_WebContentsObserverProxy_didStartNavigation( - env, java_observer_, jstring_url, navigation_handle->IsInMainFrame(), - navigation_handle->IsSameDocument(), navigation_handle_proxy.JavaThis()); + AttachCurrentThread(), java_observer_, + static_cast<NavigationHandleImpl*>(navigation_handle) + ->java_navigation_handle()); } void WebContentsObserverProxy::DidRedirectNavigation( NavigationHandle* navigation_handle) { - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jstring> jstring_url( - ConvertUTF8ToJavaString(env, navigation_handle->GetURL().spec())); - NavigationHandleProxy navigation_handle_proxy(navigation_handle); Java_WebContentsObserverProxy_didRedirectNavigation( - env, java_observer_, jstring_url, navigation_handle->IsInMainFrame(), - navigation_handle_proxy.JavaThis()); + AttachCurrentThread(), java_observer_, + static_cast<NavigationHandleImpl*>(navigation_handle) + ->java_navigation_handle()); } void WebContentsObserverProxy::DidFinishNavigation( NavigationHandle* navigation_handle) { - JNIEnv* env = AttachCurrentThread(); - // Matches logic in - // components/navigation_interception/navigation_params_android.cc - ScopedJavaLocalRef<jstring> jstring_url(ConvertUTF8ToJavaString( - env, - navigation_handle->GetBaseURLForDataURL().is_empty() - ? navigation_handle->GetURL().spec() - : navigation_handle->GetBaseURLForDataURL().possibly_invalid_spec())); - - bool is_fragment_navigation = navigation_handle->IsSameDocument(); - - if (navigation_handle->HasCommitted()) { - // See http://crbug.com/251330 for why it's determined this way. - url::Replacements<char> replacements; - replacements.ClearRef(); - bool urls_same_ignoring_fragment = - navigation_handle->GetURL().ReplaceComponents(replacements) == - navigation_handle->GetPreviousURL().ReplaceComponents(replacements); - is_fragment_navigation &= urls_same_ignoring_fragment; - } - - // TODO(shaktisahu): Provide appropriate error description (crbug/690784). - ScopedJavaLocalRef<jstring> jerror_description = - ConvertUTF8ToJavaString(env, ""); - // Remove after fixing https://crbug/905461. TRACE_EVENT0("browser", "Java_WebContentsObserverProxy_didFinishNavigation"); + Java_WebContentsObserverProxy_didFinishNavigation( - env, java_observer_, jstring_url, navigation_handle->IsInMainFrame(), - navigation_handle->IsErrorPage(), navigation_handle->HasCommitted(), - navigation_handle->IsSameDocument(), is_fragment_navigation, - navigation_handle->IsRendererInitiated(), navigation_handle->IsDownload(), - navigation_handle->HasCommitted() ? navigation_handle->GetPageTransition() - : -1, - navigation_handle->GetNetErrorCode(), jerror_description, - // TODO(shaktisahu): Change default status to -1 after fixing - // crbug/690041. - navigation_handle->GetResponseHeaders() - ? navigation_handle->GetResponseHeaders()->response_code() - : 200); + AttachCurrentThread(), java_observer_, + static_cast<NavigationHandleImpl*>(navigation_handle) + ->java_navigation_handle()); } void WebContentsObserverProxy::DidFinishLoad(RenderFrameHost* render_frame_host,
diff --git a/content/browser/android/web_contents_observer_proxy.h b/content/browser/android/web_contents_observer_proxy.h index e558c5c4..16eb7752 100644 --- a/content/browser/android/web_contents_observer_proxy.h +++ b/content/browser/android/web_contents_observer_proxy.h
@@ -6,6 +6,7 @@ #define CONTENT_BROWSER_ANDROID_WEB_CONTENTS_OBSERVER_PROXY_H_ #include <jni.h> +#include <memory> #include "base/android/jni_weak_ref.h" #include "base/macros.h"
diff --git a/content/browser/frame_host/navigation_handle_impl.cc b/content/browser/frame_host/navigation_handle_impl.cc index 48b56d9..38238ad 100644 --- a/content/browser/frame_host/navigation_handle_impl.cc +++ b/content/browser/frame_host/navigation_handle_impl.cc
@@ -218,6 +218,10 @@ } } +#if defined(OS_ANDROID) + navigation_handle_proxy_ = std::make_unique<NavigationHandleProxy>(this); +#endif + GetDelegate()->DidStartNavigation(this); if (IsInMainFrame()) { @@ -245,6 +249,10 @@ } } +#if defined(OS_ANDROID) + navigation_handle_proxy_->DidFinish(); +#endif + GetDelegate()->DidFinishNavigation(this); if (IsInMainFrame()) { @@ -459,6 +467,13 @@ throttle_runner_.AddThrottle(std::move(navigation_throttle)); } +#if defined(OS_ANDROID) +base::android::ScopedJavaGlobalRef<jobject> +NavigationHandleImpl::java_navigation_handle() { + return navigation_handle_proxy_->java_navigation_handle(); +} +#endif + bool NavigationHandleImpl::IsDeferredForTesting() { return throttle_runner_.GetDeferringThrottle() != nullptr; } @@ -939,6 +954,10 @@ if (result.action() == NavigationThrottle::PROCEED) { state_ = WILL_REDIRECT_REQUEST; +#if defined(OS_ANDROID) + navigation_handle_proxy_->DidRedirect(); +#endif + // Notify the delegate that a redirect was encountered and will be followed. if (GetDelegate()) GetDelegate()->DidRedirectNavigation(this);
diff --git a/content/browser/frame_host/navigation_handle_impl.h b/content/browser/frame_host/navigation_handle_impl.h index 02a4c83..cb51e06 100644 --- a/content/browser/frame_host/navigation_handle_impl.h +++ b/content/browser/frame_host/navigation_handle_impl.h
@@ -20,6 +20,7 @@ #include "base/optional.h" #include "base/time/time.h" #include "base/timer/timer.h" +#include "build/build_config.h" #include "content/browser/frame_host/frame_tree_node.h" #include "content/browser/frame_host/navigation_request.h" #include "content/browser/frame_host/navigation_throttle_runner.h" @@ -34,6 +35,11 @@ #include "third_party/blink/public/platform/web_mixed_content_context_type.h" #include "url/gurl.h" +#if defined(OS_ANDROID) +#include "base/android/scoped_java_ref.h" +#include "content/browser/android/navigation_handle_proxy.h" +#endif + struct FrameHostMsg_DidCommitProvisionalLoad_Params; namespace content { @@ -155,6 +161,12 @@ void RegisterSubresourceOverride( mojom::TransferrableURLLoaderPtr transferrable_loader) override; +#if defined(OS_ANDROID) + // Returns a reference to this NavigationHandle Java counterpart. It is used + // by Java WebContentsObservers. + base::android::ScopedJavaGlobalRef<jobject> java_navigation_handle(); +#endif + // Used in tests. State state_for_testing() const { return state_; } @@ -554,6 +566,12 @@ // responsible for notifying them about the various navigation events. NavigationThrottleRunner throttle_runner_; +#if defined(OS_ANDROID) + // For each C++ NavigationHandle, there is a Java counterpart. It is the JNI + // bridge in between the two. + std::unique_ptr<NavigationHandleProxy> navigation_handle_proxy_; +#endif + base::WeakPtrFactory<NavigationHandleImpl> weak_factory_; DISALLOW_COPY_AND_ASSIGN(NavigationHandleImpl);
diff --git a/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.cc b/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.cc index 3006f21..9e167cdd 100644 --- a/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.cc +++ b/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.cc
@@ -331,7 +331,8 @@ hang_event_for_testing->Wait(); } - DCHECK(extracted_names.size()); + if (!extracted_names.size()) + continue; family_result.push_back( DWriteFontLookupTableBuilder::FontFileWithUniqueNames(
diff --git a/content/browser/service_worker/service_worker_database.cc b/content/browser/service_worker/service_worker_database.cc index c4a75cf5..adaed7d 100644 --- a/content/browser/service_worker/service_worker_database.cc +++ b/content/browser/service_worker/service_worker_database.cc
@@ -1245,8 +1245,12 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::ClearPurgeableResourceIds( const std::set<int64_t>& ids) { + Status status = LazyOpen(false); + if (IsNewOrNonexistentDatabase(status)) + return STATUS_OK; + leveldb::WriteBatch batch; - Status status = DeleteResourceIdsInBatch( + status = DeleteResourceIdsInBatch( service_worker_internals::kPurgeableResIdKeyPrefix, ids, &batch); if (status != STATUS_OK) return status; @@ -1256,8 +1260,12 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::PurgeUncommittedResourceIds( const std::set<int64_t>& ids) { + Status status = LazyOpen(false); + if (IsNewOrNonexistentDatabase(status)) + return STATUS_OK; + leveldb::WriteBatch batch; - Status status = DeleteResourceIdsInBatch( + status = DeleteResourceIdsInBatch( service_worker_internals::kUncommittedResIdKeyPrefix, ids, &batch); if (status != STATUS_OK) return status;
diff --git a/content/browser/service_worker/service_worker_file_upload_browsertest.cc b/content/browser/service_worker/service_worker_file_upload_browsertest.cc index 2fd4645e..43119d99b 100644 --- a/content/browser/service_worker/service_worker_file_upload_browsertest.cc +++ b/content/browser/service_worker/service_worker_file_upload_browsertest.cc
@@ -184,7 +184,8 @@ std::string result; RunTest(BuildTargetUrl("/service_worker/upload", target_query), TargetOrigin::kSameOrigin, out_filename, &result); - *out_result = base::DictionaryValue::From(base::test::ParseJson(result)); + *out_result = + base::DictionaryValue::From(base::test::ParseJsonDeprecated(result)); ASSERT_TRUE(*out_result); } @@ -250,7 +251,8 @@ base::ReplaceFirstSubstringAfterOffset(&expectation, 0, "@SIZE@", base::NumberToString(kFileSize)); - return base::DictionaryValue::From(base::test::ParseJson(expectation)); + return base::DictionaryValue::From( + base::test::ParseJsonDeprecated(expectation)); } private:
diff --git a/content/browser/tracing/background_tracing_manager_impl.cc b/content/browser/tracing/background_tracing_manager_impl.cc index f094ae0..65ea05d 100644 --- a/content/browser/tracing/background_tracing_manager_impl.cc +++ b/content/browser/tracing/background_tracing_manager_impl.cc
@@ -505,10 +505,16 @@ config.EnableArgumentFilter(); #if defined(OS_ANDROID) // Set low trace buffer size on Android in order to upload small trace files. - if (config_->tracing_mode() == BackgroundTracingConfigImpl::PREEMPTIVE) + if (config_->tracing_mode() == BackgroundTracingConfigImpl::PREEMPTIVE) { config.SetTraceBufferSizeInEvents(20000); + config.SetTraceBufferSizeInKb(500); + } #endif + is_tracing_ = TracingControllerImpl::GetInstance()->StartTracing( + config, base::BindOnce(&BackgroundTracingManagerImpl::OnStartTracingDone, + base::Unretained(this), preset)); + // Activate the categories immediately. StartTracing eventually does this // itself, but asynchronously via PostTask, and in the meantime events will be // dropped. This ensures that we start recording events for those categories @@ -520,10 +526,6 @@ base::trace_event::TraceLog::GetInstance()->SetEnabled(config, modes); } - is_tracing_ = TracingControllerImpl::GetInstance()->StartTracing( - config, base::BindOnce(&BackgroundTracingManagerImpl::OnStartTracingDone, - base::Unretained(this), preset)); - RecordBackgroundTracingMetric(RECORDING_ENABLED); }
diff --git a/content/browser/tracing/cast_tracing_agent.cc b/content/browser/tracing/cast_tracing_agent.cc index fa4ae658..770f64c 100644 --- a/content/browser/tracing/cast_tracing_agent.cc +++ b/content/browser/tracing/cast_tracing_agent.cc
@@ -279,13 +279,14 @@ // tracing::mojom::Agent. Called by Mojo internals on the UI thread. void CastTracingAgent::StartTracing(const std::string& config, - base::TimeTicks coordinator_time) { + base::TimeTicks coordinator_time, + Agent::StartTracingCallback callback) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(!session_); session_ = std::make_unique<CastSystemTracingSession>(worker_task_runner_); session_->StartTracing( config, base::BindOnce(&CastTracingAgent::StartTracingCallbackProxy, - base::Unretained(this))); + base::Unretained(this), std::move(callback))); } void CastTracingAgent::StopAndFlush(tracing::mojom::RecorderPtr recorder) { @@ -305,10 +306,12 @@ } void CastTracingAgent::StartTracingCallbackProxy( + Agent::StartTracingCallback callback, bool success) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); if (!success) session_.reset(); + std::move(callback).Run(success); } void CastTracingAgent::HandleTraceData(chromecast::SystemTracer::Status status,
diff --git a/content/browser/tracing/cast_tracing_agent.h b/content/browser/tracing/cast_tracing_agent.h index 8d59d1c..7b90f2a 100644 --- a/content/browser/tracing/cast_tracing_agent.h +++ b/content/browser/tracing/cast_tracing_agent.h
@@ -33,10 +33,12 @@ // tracing::mojom::Agent. Called by Mojo internals on the UI thread. void StartTracing(const std::string& config, - base::TimeTicks coordinator_time) override; + base::TimeTicks coordinator_time, + Agent::StartTracingCallback callback) override; void StopAndFlush(tracing::mojom::RecorderPtr recorder) override; - void StartTracingCallbackProxy(bool success); + void StartTracingCallbackProxy(Agent::StartTracingCallback callback, + bool success); void HandleTraceData(chromecast::SystemTracer::Status status, std::string trace_data);
diff --git a/content/browser/tracing/cros_tracing_agent.cc b/content/browser/tracing/cros_tracing_agent.cc index 427f6d0..a28b7c56 100644 --- a/content/browser/tracing/cros_tracing_agent.cc +++ b/content/browser/tracing/cros_tracing_agent.cc
@@ -227,12 +227,13 @@ // tracing::mojom::Agent. Called by Mojo internals on the UI thread. void CrOSTracingAgent::StartTracing(const std::string& config, - base::TimeTicks coordinator_time) { + base::TimeTicks coordinator_time, + Agent::StartTracingCallback callback) { DCHECK(!session_); session_ = std::make_unique<CrOSSystemTracingSession>(); session_->StartTracing( config, base::BindOnce(&CrOSTracingAgent::StartTracingCallbackProxy, - base::Unretained(this))); + base::Unretained(this), std::move(callback))); } void CrOSTracingAgent::StopAndFlush(tracing::mojom::RecorderPtr recorder) { @@ -245,9 +246,11 @@ } void CrOSTracingAgent::StartTracingCallbackProxy( + Agent::StartTracingCallback callback, bool success) { if (!success) session_.reset(); + std::move(callback).Run(success); } void CrOSTracingAgent::RecorderProxy(
diff --git a/content/browser/tracing/cros_tracing_agent.h b/content/browser/tracing/cros_tracing_agent.h index 91ae13c..289db7c 100644 --- a/content/browser/tracing/cros_tracing_agent.h +++ b/content/browser/tracing/cros_tracing_agent.h
@@ -32,10 +32,12 @@ // tracing::mojom::Agent. Called by Mojo internals on the UI thread. void StartTracing(const std::string& config, - base::TimeTicks coordinator_time) override; + base::TimeTicks coordinator_time, + Agent::StartTracingCallback callback) override; void StopAndFlush(tracing::mojom::RecorderPtr recorder) override; - void StartTracingCallbackProxy(bool success); + void StartTracingCallbackProxy(Agent::StartTracingCallback callback, + bool success); void RecorderProxy(const scoped_refptr<base::RefCountedString>& events); std::unique_ptr<CrOSSystemTracingSession> session_;
diff --git a/content/browser/tracing/tracing_controller_impl.cc b/content/browser/tracing/tracing_controller_impl.cc index 558c2c5..4812441 100644 --- a/content/browser/tracing/tracing_controller_impl.cc +++ b/content/browser/tracing/tracing_controller_impl.cc
@@ -143,22 +143,16 @@ } TracingControllerImpl::TracingControllerImpl() - : delegate_(GetContentClient()->browser()->GetTracingDelegate()), - weak_ptr_factory_(this) { + : delegate_(GetContentClient()->browser()->GetTracingDelegate()) { DCHECK(!g_tracing_controller); DCHECK_CURRENTLY_ON(BrowserThread::UI); // Deliberately leaked, like this class. base::FileTracing::SetProvider(new FileTracingProviderImpl); AddAgents(); - base::trace_event::TraceLog::GetInstance()->AddAsyncEnabledStateObserver( - weak_ptr_factory_.GetWeakPtr()); g_tracing_controller = this; } -TracingControllerImpl::~TracingControllerImpl() { - base::trace_event::TraceLog::GetInstance()->RemoveAsyncEnabledStateObserver( - this); -} +TracingControllerImpl::~TracingControllerImpl() = default; void TracingControllerImpl::AddAgents() { tracing::TracedProcessImpl::GetInstance()->SetTaskRunner( @@ -364,32 +358,20 @@ trace_config_ = std::make_unique<base::trace_event::TraceConfig>(trace_config); - start_tracing_done_ = std::move(callback); ConnectToServiceIfNeeded(); - coordinator_->StartTracing(trace_config.ToString()); - - if (start_tracing_done_ && - (base::trace_event::TraceLog::GetInstance()->IsEnabled() || - !trace_config.process_filter_config().IsEnabled( - base::Process::Current().Pid()))) { - // If we're already tracing, or if the current process is excluded from the - // process filter, we'll never receive a callback from the TraceLog, so then - // we just run the callback right away. - std::move(start_tracing_done_).Run(); - } - + coordinator_->StartTracing( + trace_config.ToString(), + base::BindOnce( + [](StartTracingDoneCallback callback, bool success) { + if (!callback.is_null()) + std::move(callback).Run(); + }, + std::move(callback))); // TODO(chiniforooshan): The actual success value should be sent by the // callback asynchronously. return true; } -void TracingControllerImpl::OnTraceLogEnabled() { - if (start_tracing_done_) - std::move(start_tracing_done_).Run(); -} - -void TracingControllerImpl::OnTraceLogDisabled() {} - bool TracingControllerImpl::StopTracing( const scoped_refptr<TraceDataEndpoint>& trace_data_endpoint) { return StopTracing(std::move(trace_data_endpoint), "");
diff --git a/content/browser/tracing/tracing_controller_impl.h b/content/browser/tracing/tracing_controller_impl.h index 5a6f9e6..dbb0b86e 100644 --- a/content/browser/tracing/tracing_controller_impl.h +++ b/content/browser/tracing/tracing_controller_impl.h
@@ -12,8 +12,6 @@ #include "base/callback_forward.h" #include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "base/trace_event/trace_log.h" #include "content/common/content_export.h" #include "content/public/browser/tracing_controller.h" #include "mojo/public/cpp/system/data_pipe_drainer.h" @@ -38,10 +36,8 @@ class TracingDelegate; class TracingUI; -class TracingControllerImpl - : public TracingController, - public mojo::DataPipeDrainer::Client, - public base::trace_event::TraceLog::AsyncEnabledStateObserver { +class TracingControllerImpl : public TracingController, + public mojo::DataPipeDrainer::Client { public: // Create an endpoint for dumping the trace data to a callback. CONTENT_EXPORT static scoped_refptr<TraceDataEndpoint> CreateCallbackEndpoint( @@ -87,10 +83,6 @@ void OnDataAvailable(const void* data, size_t num_bytes) override; void OnDataComplete() override; - // base::trace_event::TraceLog::AsyncEnabledStateObserver - void OnTraceLogEnabled() override; - void OnTraceLogDisabled() override; - void OnMetadataAvailable(base::Value metadata); void CompleteFlush(); @@ -99,7 +91,6 @@ std::vector<std::unique_ptr<tracing::BaseAgent>> agents_; std::unique_ptr<TracingDelegate> delegate_; std::unique_ptr<base::trace_event::TraceConfig> trace_config_; - StartTracingDoneCallback start_tracing_done_; std::unique_ptr<mojo::DataPipeDrainer> drainer_; scoped_refptr<TraceDataEndpoint> trace_data_endpoint_; std::unique_ptr<base::DictionaryValue> filtered_metadata_; @@ -107,8 +98,6 @@ bool is_data_complete_ = false; bool is_metadata_available_ = false; - // NOTE: Weak pointers must be invalidated before all other member variables. - base::WeakPtrFactory<TracingControllerImpl> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(TracingControllerImpl); };
diff --git a/content/browser/webauth/authenticator_impl.cc b/content/browser/webauth/authenticator_impl.cc index eb0d191..bfa9ddeb9 100644 --- a/content/browser/webauth/authenticator_impl.cc +++ b/content/browser/webauth/authenticator_impl.cc
@@ -659,6 +659,14 @@ std::move(options->challenge)); } + // U2F requests proxied from the cryptotoken extension are limited to USB + // devices. + const auto transports = + OriginIsCryptoTokenExtension(caller_origin_) + ? base::flat_set<device::FidoTransportProtocol>( + {device::FidoTransportProtocol::kUsbHumanInterfaceDevice}) + : transports_; + auto authenticator_selection_criteria = options->authenticator_selection ? mojo::ConvertTo<device::AuthenticatorSelectionCriteria>( @@ -667,6 +675,7 @@ auto ctap_request = CreateCtapMakeCredentialRequest( client_data_json_, options, browser_context()->IsOffTheRecord()); + // On dual protocol CTAP2/U2F devices, force credential creation over U2F. ctap_request.set_is_u2f_only(OriginIsCryptoTokenExtension(caller_origin_)); // Compute the effective attestation conveyance preference and set @@ -683,7 +692,7 @@ attestation != ::device::AttestationConveyancePreference::NONE; request_ = std::make_unique<device::MakeCredentialRequestHandler>( - connector_, transports_, std::move(ctap_request), + connector_, transports, std::move(ctap_request), std::move(authenticator_selection_criteria), base::BindOnce(&AuthenticatorImpl::OnRegisterResponse, weak_factory_.GetWeakPtr())); @@ -730,7 +739,6 @@ // TODO(kpaulhamus): Fetch and add the Channel ID/Token Binding ID public key // used to communicate with the origin. if (OriginIsCryptoTokenExtension(caller_origin_)) { - // Cryptotoken requests should be proxied without UI. request_delegate_->DisableUI(); // As Cryptotoken validates the origin, accept the relying party id as the @@ -780,6 +788,14 @@ } } + // U2F requests proxied from the cryptotoken extension are limited to USB + // devices. + const auto transports = + OriginIsCryptoTokenExtension(caller_origin_) + ? base::flat_set<device::FidoTransportProtocol>( + {device::FidoTransportProtocol::kUsbHumanInterfaceDevice}) + : transports_; + DCHECK(get_assertion_response_callback_.is_null()); get_assertion_response_callback_ = std::move(callback); @@ -797,7 +813,7 @@ CreatePlatformAuthenticatorIfAvailableAndCheckIfCredentialExists( ctap_request); request_ = std::make_unique<device::GetAssertionRequestHandler>( - connector_, transports_, std::move(ctap_request), + connector_, transports, std::move(ctap_request), base::BindOnce(&AuthenticatorImpl::OnSignResponse, weak_factory_.GetWeakPtr()));
diff --git a/content/browser/webauth/authenticator_impl.h b/content/browser/webauth/authenticator_impl.h index 6fe474b..538ea05 100644 --- a/content/browser/webauth/authenticator_impl.h +++ b/content/browser/webauth/authenticator_impl.h
@@ -86,6 +86,10 @@ const { return transports_; } + void set_transports_for_testing( + base::flat_set<device::FidoTransportProtocol> transports) { + transports_ = transports; + } protected: virtual void UpdateRequestDelegate(); @@ -183,7 +187,7 @@ RenderFrameHost* const render_frame_host_; service_manager::Connector* connector_ = nullptr; - const base::flat_set<device::FidoTransportProtocol> transports_; + base::flat_set<device::FidoTransportProtocol> transports_; std::unique_ptr<device::FidoRequestHandlerBase> request_; MakeCredentialCallback make_credential_response_callback_;
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc index a6feba0..8924c79 100644 --- a/content/browser/webauth/authenticator_impl_unittest.cc +++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -418,12 +418,20 @@ scoped_feature_list_->InitAndDisableFeature(feature); } + void SetUpMockBluetooth() { + mock_adapter_ = base::MakeRefCounted< + ::testing::NiceMock<device::MockBluetoothAdapter>>(); + device::BluetoothAdapterFactory::SetAdapterForTesting(mock_adapter_); + } + protected: std::unique_ptr<AuthenticatorImpl> authenticator_impl_; service_manager::mojom::ConnectorRequest request_; std::unique_ptr<service_manager::Connector> connector_; std::unique_ptr<device::FakeHidManager> fake_hid_manager_; base::Optional<base::test::ScopedFeatureList> scoped_feature_list_; + scoped_refptr<::testing::NiceMock<device::MockBluetoothAdapter>> + mock_adapter_; }; // Verify behavior for various combinations of origins and RP IDs. @@ -814,6 +822,59 @@ } } +// Test that Cryptotoken requests should only be dispatched to USB +// authenticators. +TEST_F(AuthenticatorImplTest, CryptotokenUsbOnly) { + TestServiceManagerContext smc; + SimulateNavigation(GURL(kTestOrigin1)); + auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>( + base::Time::Now(), base::TimeTicks::Now()); + url::AddStandardScheme("chrome-extension", url::SCHEME_WITH_HOST); + auto authenticator = ConstructAuthenticatorWithTimer(task_runner); + authenticator_impl_->set_transports_for_testing( + device::GetAllTransportProtocols()); + SetUpMockBluetooth(); + + for (const bool is_cryptotoken_request : {false, true}) { + // caBLE and platform discoveries cannot be instantiated through + // ScopedVirtualFidoDevice, so we don't test them here. + for (const device::FidoTransportProtocol transport : + {device::FidoTransportProtocol::kUsbHumanInterfaceDevice, + device::FidoTransportProtocol::kBluetoothLowEnergy, + device::FidoTransportProtocol::kNearFieldCommunication}) { + SCOPED_TRACE(::testing::Message() + << "is_cryptotoken_request=" << is_cryptotoken_request + << ", transport=" << device::ToString(transport)); + + OverrideLastCommittedOrigin( + main_rfh(), + url::Origin::Create(GURL(is_cryptotoken_request ? kCryptotokenOrigin + : kTestOrigin1))); + + device::test::ScopedVirtualFidoDevice device; + device.SetSupportedProtocol(device::ProtocolVersion::kU2f); + device.SetTransport(transport); + device.mutable_state()->transport = transport; + + PublicKeyCredentialCreationOptionsPtr options = + GetTestPublicKeyCredentialCreationOptions(); + TestMakeCredentialCallback callback_receiver; + authenticator->MakeCredential(std::move(options), + callback_receiver.callback()); + base::RunLoop().RunUntilIdle(); + task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1)); + callback_receiver.WaitForCallback(); + EXPECT_EQ( + !is_cryptotoken_request || + transport == + device::FidoTransportProtocol::kUsbHumanInterfaceDevice + ? AuthenticatorStatus::SUCCESS + : AuthenticatorStatus::NOT_ALLOWED_ERROR, + callback_receiver.status()); + } + } +} + // Requests originating from cryptotoken should only target U2F devices. TEST_F(AuthenticatorImplTest, AttestationPermitted) { TestServiceManagerContext smc; @@ -1043,15 +1104,6 @@ } TEST_F(AuthenticatorImplTest, GetAssertionWithEmptyAllowCredentials) { - auto mock_adapter = - base::MakeRefCounted<::testing::NiceMock<device::MockBluetoothAdapter>>(); - EXPECT_CALL(*mock_adapter, IsPresent()) - .WillRepeatedly(::testing::Return(true)); - device::BluetoothAdapterFactory::SetAdapterForTesting(mock_adapter); - auto bluetooth_adapter_factory_overrides = - device::BluetoothAdapterFactory::Get().InitGlobalValuesForTesting(); - bluetooth_adapter_factory_overrides->SetLESupported(true); - SimulateNavigation(GURL(kTestOrigin1)); PublicKeyCredentialRequestOptionsPtr options = GetTestPublicKeyCredentialRequestOptions(); @@ -1544,78 +1596,114 @@ const std::vector<TestCase> kTests = { { AttestationConveyancePreference::NONE, - IndividualAttestation::NOT_REQUESTED, AttestationConsent::DENIED, - AuthenticatorStatus::SUCCESS, AttestationType::NONE, "", + IndividualAttestation::NOT_REQUESTED, + AttestationConsent::DENIED, + AuthenticatorStatus::SUCCESS, + AttestationType::NONE, + "", }, { AttestationConveyancePreference::NONE, - IndividualAttestation::REQUESTED, AttestationConsent::DENIED, - AuthenticatorStatus::SUCCESS, AttestationType::NONE, "", + IndividualAttestation::REQUESTED, + AttestationConsent::DENIED, + AuthenticatorStatus::SUCCESS, + AttestationType::NONE, + "", }, { AttestationConveyancePreference::INDIRECT, - IndividualAttestation::NOT_REQUESTED, AttestationConsent::DENIED, - AuthenticatorStatus::NOT_ALLOWED_ERROR, AttestationType::ANY, "", + IndividualAttestation::NOT_REQUESTED, + AttestationConsent::DENIED, + AuthenticatorStatus::NOT_ALLOWED_ERROR, + AttestationType::ANY, + "", }, { AttestationConveyancePreference::INDIRECT, - IndividualAttestation::REQUESTED, AttestationConsent::DENIED, - AuthenticatorStatus::NOT_ALLOWED_ERROR, AttestationType::ANY, "", + IndividualAttestation::REQUESTED, + AttestationConsent::DENIED, + AuthenticatorStatus::NOT_ALLOWED_ERROR, + AttestationType::ANY, + "", }, { AttestationConveyancePreference::INDIRECT, - IndividualAttestation::NOT_REQUESTED, AttestationConsent::GRANTED, - AuthenticatorStatus::SUCCESS, AttestationType::U2F, + IndividualAttestation::NOT_REQUESTED, + AttestationConsent::GRANTED, + AuthenticatorStatus::SUCCESS, + AttestationType::U2F, kStandardCommonName, }, { AttestationConveyancePreference::INDIRECT, - IndividualAttestation::REQUESTED, AttestationConsent::GRANTED, - AuthenticatorStatus::SUCCESS, AttestationType::U2F, + IndividualAttestation::REQUESTED, + AttestationConsent::GRANTED, + AuthenticatorStatus::SUCCESS, + AttestationType::U2F, kStandardCommonName, }, { AttestationConveyancePreference::DIRECT, - IndividualAttestation::NOT_REQUESTED, AttestationConsent::DENIED, - AuthenticatorStatus::NOT_ALLOWED_ERROR, AttestationType::ANY, "", + IndividualAttestation::NOT_REQUESTED, + AttestationConsent::DENIED, + AuthenticatorStatus::NOT_ALLOWED_ERROR, + AttestationType::ANY, + "", }, { AttestationConveyancePreference::DIRECT, - IndividualAttestation::REQUESTED, AttestationConsent::DENIED, - AuthenticatorStatus::NOT_ALLOWED_ERROR, AttestationType::ANY, "", + IndividualAttestation::REQUESTED, + AttestationConsent::DENIED, + AuthenticatorStatus::NOT_ALLOWED_ERROR, + AttestationType::ANY, + "", }, { AttestationConveyancePreference::DIRECT, - IndividualAttestation::NOT_REQUESTED, AttestationConsent::GRANTED, - AuthenticatorStatus::SUCCESS, AttestationType::U2F, + IndividualAttestation::NOT_REQUESTED, + AttestationConsent::GRANTED, + AuthenticatorStatus::SUCCESS, + AttestationType::U2F, kStandardCommonName, }, { AttestationConveyancePreference::DIRECT, - IndividualAttestation::REQUESTED, AttestationConsent::GRANTED, - AuthenticatorStatus::SUCCESS, AttestationType::U2F, + IndividualAttestation::REQUESTED, + AttestationConsent::GRANTED, + AuthenticatorStatus::SUCCESS, + AttestationType::U2F, kStandardCommonName, }, { AttestationConveyancePreference::ENTERPRISE, - IndividualAttestation::NOT_REQUESTED, AttestationConsent::DENIED, - AuthenticatorStatus::NOT_ALLOWED_ERROR, AttestationType::ANY, "", + IndividualAttestation::NOT_REQUESTED, + AttestationConsent::DENIED, + AuthenticatorStatus::NOT_ALLOWED_ERROR, + AttestationType::ANY, + "", }, { AttestationConveyancePreference::ENTERPRISE, - IndividualAttestation::REQUESTED, AttestationConsent::DENIED, - AuthenticatorStatus::NOT_ALLOWED_ERROR, AttestationType::ANY, "", + IndividualAttestation::REQUESTED, + AttestationConsent::DENIED, + AuthenticatorStatus::NOT_ALLOWED_ERROR, + AttestationType::ANY, + "", }, { AttestationConveyancePreference::ENTERPRISE, - IndividualAttestation::NOT_REQUESTED, AttestationConsent::GRANTED, - AuthenticatorStatus::SUCCESS, AttestationType::U2F, + IndividualAttestation::NOT_REQUESTED, + AttestationConsent::GRANTED, + AuthenticatorStatus::SUCCESS, + AttestationType::U2F, kStandardCommonName, }, { AttestationConveyancePreference::ENTERPRISE, - IndividualAttestation::REQUESTED, AttestationConsent::GRANTED, - AuthenticatorStatus::SUCCESS, AttestationType::U2F, + IndividualAttestation::REQUESTED, + AttestationConsent::GRANTED, + AuthenticatorStatus::SUCCESS, + AttestationType::U2F, kIndividualCommonName, }, }; @@ -1638,32 +1726,42 @@ const std::vector<TestCase> kTests = { { AttestationConveyancePreference::ENTERPRISE, - IndividualAttestation::NOT_REQUESTED, AttestationConsent::DENIED, - AuthenticatorStatus::NOT_ALLOWED_ERROR, AttestationType::ANY, "", + IndividualAttestation::NOT_REQUESTED, + AttestationConsent::DENIED, + AuthenticatorStatus::NOT_ALLOWED_ERROR, + AttestationType::ANY, + "", }, { AttestationConveyancePreference::DIRECT, - IndividualAttestation::NOT_REQUESTED, AttestationConsent::GRANTED, + IndividualAttestation::NOT_REQUESTED, + AttestationConsent::GRANTED, AuthenticatorStatus::SUCCESS, // If individual attestation was not requested then the attestation // certificate will be removed, even if consent is given, because the // consent isn't to be tracked. - AttestationType::NONE, "", + AttestationType::NONE, + "", }, { AttestationConveyancePreference::ENTERPRISE, - IndividualAttestation::NOT_REQUESTED, AttestationConsent::GRANTED, + IndividualAttestation::NOT_REQUESTED, + AttestationConsent::GRANTED, AuthenticatorStatus::SUCCESS, // If individual attestation was not requested then the attestation // certificate will be removed, even if consent is given, because the // consent isn't to be tracked. - AttestationType::NONE, "", + AttestationType::NONE, + "", }, { AttestationConveyancePreference::ENTERPRISE, - IndividualAttestation::REQUESTED, AttestationConsent::GRANTED, - AuthenticatorStatus::SUCCESS, AttestationType::U2F, kCommonName, + IndividualAttestation::REQUESTED, + AttestationConsent::GRANTED, + AuthenticatorStatus::SUCCESS, + AttestationType::U2F, + kCommonName, }, }; @@ -1694,24 +1792,31 @@ // attestation is requested, the self-attestation will be removed but, // because the transport is kInternal, the AAGUID will be preserved. AttestationConveyancePreference::NONE, - IndividualAttestation::NOT_REQUESTED, AttestationConsent::DENIED, + IndividualAttestation::NOT_REQUESTED, + AttestationConsent::DENIED, AuthenticatorStatus::SUCCESS, - AttestationType::NONE_WITH_NONZERO_AAGUID, "", + AttestationType::NONE_WITH_NONZERO_AAGUID, + "", }, { // If attestation is requested, but denied, we'll still fail the // request. AttestationConveyancePreference::DIRECT, - IndividualAttestation::NOT_REQUESTED, AttestationConsent::DENIED, - AuthenticatorStatus::NOT_ALLOWED_ERROR, AttestationType::ANY, "", + IndividualAttestation::NOT_REQUESTED, + AttestationConsent::DENIED, + AuthenticatorStatus::NOT_ALLOWED_ERROR, + AttestationType::ANY, + "", }, { // If attestation is requested and granted, the self attestation // will be returned. AttestationConveyancePreference::DIRECT, - IndividualAttestation::NOT_REQUESTED, AttestationConsent::GRANTED, + IndividualAttestation::NOT_REQUESTED, + AttestationConsent::GRANTED, AuthenticatorStatus::SUCCESS, - AttestationType::SELF_WITH_NONZERO_AAGUID, "", + AttestationType::SELF_WITH_NONZERO_AAGUID, + "", }, }; @@ -1728,22 +1833,31 @@ // If no attestation is requested, we'll return the self attestation // rather than erasing it. AttestationConveyancePreference::NONE, - IndividualAttestation::NOT_REQUESTED, AttestationConsent::DENIED, - AuthenticatorStatus::SUCCESS, AttestationType::SELF, "", + IndividualAttestation::NOT_REQUESTED, + AttestationConsent::DENIED, + AuthenticatorStatus::SUCCESS, + AttestationType::SELF, + "", }, { // If attestation is requested, but denied, we'll still fail the // request. AttestationConveyancePreference::DIRECT, - IndividualAttestation::NOT_REQUESTED, AttestationConsent::DENIED, - AuthenticatorStatus::NOT_ALLOWED_ERROR, AttestationType::ANY, "", + IndividualAttestation::NOT_REQUESTED, + AttestationConsent::DENIED, + AuthenticatorStatus::NOT_ALLOWED_ERROR, + AttestationType::ANY, + "", }, { // If attestation is requested and granted, the self attestation will // be returned. AttestationConveyancePreference::DIRECT, - IndividualAttestation::NOT_REQUESTED, AttestationConsent::GRANTED, - AuthenticatorStatus::SUCCESS, AttestationType::SELF, "", + IndividualAttestation::NOT_REQUESTED, + AttestationConsent::GRANTED, + AuthenticatorStatus::SUCCESS, + AttestationType::SELF, + "", }, }; @@ -1763,8 +1877,11 @@ // self-attestation should still be replaced with a "none" // attestation. AttestationConveyancePreference::NONE, - IndividualAttestation::NOT_REQUESTED, AttestationConsent::DENIED, - AuthenticatorStatus::SUCCESS, AttestationType::NONE, "", + IndividualAttestation::NOT_REQUESTED, + AttestationConsent::DENIED, + AuthenticatorStatus::SUCCESS, + AttestationType::NONE, + "", }, }; @@ -2101,11 +2218,10 @@ TEST_F(AuthenticatorImplRequestDelegateTest, TestRequestDelegateObservesFidoRequestHandler) { EnableFeature(features::kWebAuthBle); - auto mock_adapter = - base::MakeRefCounted<::testing::NiceMock<device::MockBluetoothAdapter>>(); - EXPECT_CALL(*mock_adapter, IsPresent()) + SetUpMockBluetooth(); + + EXPECT_CALL(*mock_adapter_, IsPresent()) .WillRepeatedly(::testing::Return(true)); - device::BluetoothAdapterFactory::SetAdapterForTesting(mock_adapter); auto bluetooth_adapter_factory_overrides = device::BluetoothAdapterFactory::Get().InitGlobalValuesForTesting(); bluetooth_adapter_factory_overrides->SetLESupported(true);
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn index 628baf4..cc3cda7 100644 --- a/content/public/android/BUILD.gn +++ b/content/public/android/BUILD.gn
@@ -262,7 +262,7 @@ "java/src/org/chromium/content_public/browser/MotionEventSynthesizer.java", "java/src/org/chromium/content_public/browser/NavigationController.java", "java/src/org/chromium/content_public/browser/NavigationEntry.java", - "java/src/org/chromium/content_public/browser/NavigationHandleProxy.java", + "java/src/org/chromium/content_public/browser/NavigationHandle.java", "java/src/org/chromium/content_public/browser/NavigationHistory.java", "java/src/org/chromium/content_public/browser/RenderCoordinates.java", "java/src/org/chromium/content_public/browser/RenderFrameHost.java", @@ -421,7 +421,7 @@ "java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java", "java/src/org/chromium/content/common/ServiceManagerConnectionImpl.java", "java/src/org/chromium/content_public/browser/LoadUrlParams.java", - "java/src/org/chromium/content_public/browser/NavigationHandleProxy.java", + "java/src/org/chromium/content_public/browser/NavigationHandle.java", "java/src/org/chromium/content_public/common/ResourceRequestBody.java", "java/src/org/chromium/content_public/common/UseZoomForDSFPolicy.java", ] @@ -553,6 +553,7 @@ java_files = [ "junit/src/org/chromium/content/browser/BindingManagerTest.java", "junit/src/org/chromium/content/browser/ChildProcessRankingTest.java", + "junit/src/org/chromium/content/browser/UiThreadTaskTraitsImplTest.java", "junit/src/org/chromium/content/browser/accessibility/BrowserAccessibilityStateTest.java", "junit/src/org/chromium/content/browser/SpareChildConnectionTest.java", "junit/src/org/chromium/content/browser/androidoverlay/DialogOverlayCoreTest.java",
diff --git a/content/public/android/java/src/org/chromium/content/browser/UiThreadTaskTraitsImpl.java b/content/public/android/java/src/org/chromium/content/browser/UiThreadTaskTraitsImpl.java index 835dc95d8..c3146ff 100644 --- a/content/public/android/java/src/org/chromium/content/browser/UiThreadTaskTraitsImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/UiThreadTaskTraitsImpl.java
@@ -6,6 +6,7 @@ import org.chromium.base.task.TaskPriority; import org.chromium.base.task.TaskTraits; +import org.chromium.base.task.TaskTraitsExtensionDescriptor; import org.chromium.content_public.browser.BrowserTaskExecutor; import org.chromium.content_public.browser.BrowserTaskType; @@ -13,20 +14,49 @@ * Provides the implementation needed in UiThreadTaskTraits. */ public class UiThreadTaskTraitsImpl { - private UiThreadTaskTraitsImpl() {} + private static class Descriptor + implements TaskTraitsExtensionDescriptor<UiThreadTaskTraitsImpl> { + // Corresponds to content::BrowserTaskTraitsExtension. + private static final byte EXTENSION_ID = 1; - // Corresponds to content::BrowserTaskTraitsExtension. - public static final byte EXTENSION_ID = 1; + // Keep in sync with content::BrowserTaskTraitsExtension::Serialize. + private static final byte TASK_TYPE = 1; + private static final byte NESTING_INDEX = 2; - // Keep in sync with content::BrowserTaskTraitsExtension::Serialize. - private static final byte TASK_TYPE = 1; - private static final byte NESTING_INDEX = 2; + @Override + public int getId() { + return EXTENSION_ID; + } - private static final byte[] sDefaultExtensionData = getDefaultExtensionData(); + @Override + public UiThreadTaskTraitsImpl fromSerializedData(byte[] data) { + int taskType = data[TASK_TYPE]; + return new UiThreadTaskTraitsImpl().setTaskType(taskType); + } - public static final TaskTraits DEFAULT = new TaskTraits(EXTENSION_ID, sDefaultExtensionData); - public static final TaskTraits BOOTSTRAP = new TaskTraits( - EXTENSION_ID, getExtensionDataForBrowserTaskType(BrowserTaskType.BOOTSTRAP)); + @Override + public byte[] toSerializedData(UiThreadTaskTraitsImpl extension) { + byte extensionData[] = new byte[TaskTraits.EXTENSION_STORAGE_SIZE]; + + // Note we don't specify the UI thread directly here because it's ID 0 and the array is + // initialized to zero. + + // Similarly we don't specify BrowserTaskType.Default its ID is also 0. + + // TODO(crbug.com/876272) Remove this if possible. + extensionData[NESTING_INDEX] = 1; // Allow the task to run in a nested RunLoop. + extensionData[TASK_TYPE] = (byte) extension.mTaskType; + return extensionData; + } + } + + public static final TaskTraitsExtensionDescriptor<UiThreadTaskTraitsImpl> DESCRIPTOR = + new Descriptor(); + + public static final TaskTraits DEFAULT = + TaskTraits.USER_VISIBLE.withExtension(DESCRIPTOR, new UiThreadTaskTraitsImpl()); + public static final TaskTraits BOOTSTRAP = TaskTraits.USER_VISIBLE.withExtension( + DESCRIPTOR, new UiThreadTaskTraitsImpl().setTaskType(BrowserTaskType.BOOTSTRAP)); public static final TaskTraits BEST_EFFORT = DEFAULT.taskPriority(TaskPriority.BEST_EFFORT); public static final TaskTraits USER_VISIBLE = DEFAULT.taskPriority(TaskPriority.USER_VISIBLE); public static final TaskTraits USER_BLOCKING = DEFAULT.taskPriority(TaskPriority.USER_BLOCKING); @@ -35,22 +65,19 @@ BrowserTaskExecutor.register(); } - private static byte[] getDefaultExtensionData() { - byte extensionData[] = new byte[TaskTraits.EXTENSION_STORAGE_SIZE]; + private @BrowserTaskType int mTaskType; - // Note we don't specify the UI thread directly here because it's ID 0 and the array is - // initialized to zero. - - // Similarly we don't specify BrowserTaskType.Default its ID is also 0. - - // TODO(crbug.com/876272) Remove this if possible. - extensionData[NESTING_INDEX] = 1; // Allow the task to run in a nested RunLoop. - return extensionData; + private UiThreadTaskTraitsImpl() { + mTaskType = BrowserTaskType.DEFAULT; } - private static byte[] getExtensionDataForBrowserTaskType(int browserTaskType) { - byte extensionData[] = getDefaultExtensionData(); - extensionData[TASK_TYPE] = (byte) browserTaskType; - return extensionData; + @BrowserTaskType + public int getTaskType() { + return mTaskType; + } + + private UiThreadTaskTraitsImpl setTaskType(@BrowserTaskType int taskType) { + mTaskType = taskType; + return this; } }
diff --git a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java index 79909bd4..a39651f1 100644 --- a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java +++ b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java
@@ -9,6 +9,7 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.WebContentsObserver; /** @@ -77,34 +78,23 @@ @Override @CalledByNative - public void didStartNavigation( - String url, boolean isInMainFrame, boolean isSameDocument, long navigationHandleProxy) { - for (mObserversIterator.rewind(); mObserversIterator.hasNext();) { - mObserversIterator.next().didStartNavigation( - url, isInMainFrame, isSameDocument, navigationHandleProxy); - } + public void didStartNavigation(NavigationHandle navigation) { + for (mObserversIterator.rewind(); mObserversIterator.hasNext();) + mObserversIterator.next().didStartNavigation(navigation); } @Override @CalledByNative - public void didRedirectNavigation( - String url, boolean isInMainFrame, long navigationHandleProxy) { - for (mObserversIterator.rewind(); mObserversIterator.hasNext();) { - mObserversIterator.next().didRedirectNavigation( - url, isInMainFrame, navigationHandleProxy); - } + public void didRedirectNavigation(NavigationHandle navigation) { + for (mObserversIterator.rewind(); mObserversIterator.hasNext();) + mObserversIterator.next().didRedirectNavigation(navigation); } + @Override @CalledByNative - private void didFinishNavigation(String url, boolean isInMainFrame, boolean isErrorPage, - boolean hasCommitted, boolean isSameDocument, boolean isFragmentNavigation, - boolean isRendererInitiated, boolean isDownload, int transition, int errorCode, - String errorDescription, int httpStatusCode) { - Integer pageTransition = transition == -1 ? null : transition; + public void didFinishNavigation(NavigationHandle navigation) { for (mObserversIterator.rewind(); mObserversIterator.hasNext();) { - mObserversIterator.next().didFinishNavigation(url, isInMainFrame, isErrorPage, - hasCommitted, isSameDocument, isFragmentNavigation, isRendererInitiated, - isDownload, pageTransition, errorCode, errorDescription, httpStatusCode); + mObserversIterator.next().didFinishNavigation(navigation); } }
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/BrowserTaskExecutor.java b/content/public/android/java/src/org/chromium/content_public/browser/BrowserTaskExecutor.java index 2857aa3e..e457409 100644 --- a/content/public/android/java/src/org/chromium/content_public/browser/BrowserTaskExecutor.java +++ b/content/public/android/java/src/org/chromium/content_public/browser/BrowserTaskExecutor.java
@@ -61,10 +61,10 @@ public static void register() { // In some tests we will get called multiple times. if (sRegistered) return; + sRegistered = true; PostTask.registerTaskExecutor( - UiThreadTaskTraitsImpl.EXTENSION_ID, new BrowserTaskExecutor()); - sRegistered = true; + UiThreadTaskTraitsImpl.DESCRIPTOR.getId(), new BrowserTaskExecutor()); } private final WeakHashMap<TaskTraits, SingleThreadTaskRunner> mTaskRunners =
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/NavigationHandle.java b/content/public/android/java/src/org/chromium/content_public/browser/NavigationHandle.java new file mode 100644 index 0000000..6769ebc --- /dev/null +++ b/content/public/android/java/src/org/chromium/content_public/browser/NavigationHandle.java
@@ -0,0 +1,204 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.content_public.browser; + +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; + +/** + * JNI bridge with content::NavigationHandle + */ +@JNINamespace("content") +public class NavigationHandle { + private long mNativeNavigationHandleProxy; + private final boolean mIsInMainFrame; + private final boolean mIsRendererInitiated; + private final boolean mIsSameDocument; + private Integer mPageTransition; + private String mUrl; + private boolean mHasCommitted; + private boolean mIsDownload; + private boolean mIsErrorPage; + private boolean mIsFragmentNavigation; + private int mErrorCode; + private int mHttpStatusCode; + + @CalledByNative + public NavigationHandle(long nativeNavigationHandleProxy, String url, boolean isInMainFrame, + boolean isSameDocument, boolean isRendererInitiated) { + mNativeNavigationHandleProxy = nativeNavigationHandleProxy; + mUrl = url; + mIsInMainFrame = isInMainFrame; + mIsSameDocument = isSameDocument; + mIsRendererInitiated = isRendererInitiated; + } + + /** + * The navigation received a redirect. Called once per redirect. + * @param url The new URL. + */ + @CalledByNative + private void didRedirect(String url) { + mUrl = url; + } + + /** + * The navigation finished. Called once per navigation. + */ + @CalledByNative + public void didFinish(String url, boolean isErrorPage, boolean hasCommitted, + boolean isFragmentNavigation, boolean isDownload, int transition, int errorCode, + int httpStatuscode) { + mUrl = url; + mIsErrorPage = isErrorPage; + mHasCommitted = hasCommitted; + mIsFragmentNavigation = isFragmentNavigation; + mIsDownload = isDownload; + mPageTransition = transition == -1 ? null : transition; + mErrorCode = errorCode; + mHttpStatusCode = httpStatuscode; + } + + /** + * Release the C++ pointer. + */ + @CalledByNative + private void release() { + mNativeNavigationHandleProxy = 0; + } + + public long nativePtr() { + return mNativeNavigationHandleProxy; + } + + /** + * The URL the frame is navigating to. This may change during the navigation when encountering + * a server redirect. + */ + public String getUrl() { + return mUrl; + } + + /** + * Whether the navigation is taking place in the main frame or in a subframe. + */ + public boolean isInMainFrame() { + return mIsInMainFrame; + } + + /** + * Whether the navigation was initiated by the renderer process. Examples of renderer-initiated + * navigations include: + * - <a> link click + * - changing window.location.href + * - redirect via the <meta http-equiv="refresh"> tag + * - using window.history.pushState + * + * This method returns false for browser-initiated navigations, including: + * - any navigation initiated from the omnibox + * - navigations via suggestions in browser UI + * - navigations via browser UI: Ctrl-R, refresh/forward/back/home buttons + * - using window.history.forward() or window.history.back() + * - any other "explicit" URL navigations, e.g. bookmarks + */ + public boolean isRendererInitiated() { + return mIsRendererInitiated; + } + + /** + * Whether the navigation happened without changing document. + * Examples of same document navigations are: + * - reference fragment navigations + * - pushState/replaceState + * - same page history navigation + */ + public boolean isSameDocument() { + return mIsSameDocument; + } + + public String errorDescription() { + // TODO(shaktisahu): Provide appropriate error description (crbug/690784). + return ""; + } + + public int errorCode() { + return mErrorCode; + } + + /** + * Whether the navigation has committed. Navigations that end up being downloads or return + * 204/205 response codes do not commit (i.e. the WebContents stays at the existing URL). This + * returns true for either successful commits or error pages that replace the previous page + * (distinguished by |IsErrorPage|), and false for errors that leave the user on the previous + * page. + */ + public boolean hasCommitted() { + return mHasCommitted; + } + + /** + * Return the HTTP status code. This can be used after the response is received in + * didFinishNavigation() + */ + public int httpStatusCode() { + return mHttpStatusCode; + } + + /** + * Returns the page transition type. + */ + public Integer pageTransition() { + return mPageTransition; + } + + /** + * Returns true on same-document navigation with fragment change. + */ + public boolean isFragmentNavigation() { + return mIsFragmentNavigation; + } + + /** + * Whether the navigation resulted in an error page. + * Note that if an error page reloads, this will return true even though GetNetErrorCode will be + * net::OK. + */ + public boolean isErrorPage() { + return mIsErrorPage; + } + + /** + * Returns true if this navigation resulted in a download. Returns false if this navigation did + * not result in a download, or if download status is not yet known for this navigation. + * Download status is determined for a navigation when processing final (post redirect) HTTP + * response headers. + */ + public boolean isDownload() { + return mIsDownload; + } + + /** + * Set request's header. If the header is already present, its value is overwritten. When + * modified during a navigation start, the headers will be applied to the initial network + * request. When modified during a redirect, the headers will be applied to the redirected + * request. + */ + public void setRequestHeader(String headerName, String headerValue) { + nativeSetRequestHeader(mNativeNavigationHandleProxy, headerName, headerValue); + } + + /** + * Remove a request's header. If the header is not present, it has no effect. Must be called + * during a redirect. + */ + public void removeRequestHeader(String headerName) { + nativeRemoveRequestHeader(mNativeNavigationHandleProxy, headerName); + } + + private static native void nativeSetRequestHeader( + long nativeNavigationHandleProxy, String headerName, String headerValue); + private static native void nativeRemoveRequestHeader( + long nativeNavigationHandleProxy, String headerName); +}
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/NavigationHandleProxy.java b/content/public/android/java/src/org/chromium/content_public/browser/NavigationHandleProxy.java deleted file mode 100644 index 3b9be3c3..0000000 --- a/content/public/android/java/src/org/chromium/content_public/browser/NavigationHandleProxy.java +++ /dev/null
@@ -1,18 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.content_public.browser; - -import org.chromium.base.annotations.JNINamespace; - -/** - * JNI bridge with content::NavigationHandleProxy. - */ -@JNINamespace("content") -public class NavigationHandleProxy { - public static native void nativeSetRequestHeader( - long nativeNavigationHandleProxy, String headerName, String headerValue); - public static native void nativeRemoveRequestHeader( - long nativeNavigationHandleProxy, String headerName); -}
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/WebContentsObserver.java b/content/public/android/java/src/org/chromium/content_public/browser/WebContentsObserver.java index 649a54d..21e6d1e 100644 --- a/content/public/android/java/src/org/chromium/content_public/browser/WebContentsObserver.java +++ b/content/public/android/java/src/org/chromium/content_public/browser/WebContentsObserver.java
@@ -5,7 +5,6 @@ package org.chromium.content_public.browser; import android.support.annotation.IntDef; -import android.support.annotation.Nullable; import org.chromium.blink.mojom.ViewportFit; @@ -38,54 +37,31 @@ /** * Called when the browser process starts a navigation. - * @param url The validated URL for the loading page. - * @param isInMainFrame Whether the navigation is for the main frame. - * @param isSameDocument Whether the main frame navigation did not cause changes to the - * document (for example scrolling to a named anchor or PopState). - * @param navigationHandleProxy Pointer to a NavigationHandleProxy representing the navigation. - * Its lifetime is bound to this function. Do not store it. It can - * be used to modify headers. + * @param navigationHandle + * NavigationHandle are provided to several WebContentsObserver methods to allow + * observers to track specific navigations. Observers should clear any references to a + * NavigationHandle at didFinishNavigation(); */ - public void didStartNavigation(String url, boolean isInMainFrame, boolean isSameDocument, - long navigationHandleProxy) {} + public void didStartNavigation(NavigationHandle navigationHandle) {} /** * Called when the browser process redirect a navigation. - * @param url The validated URL for the loading page. - * @param isInMainFrame Whether the navigation is for the main frame. - * @param navigationHandleProxy Pointer to a NavigationHandleProxy representing the navigation. - * Its lifetime is bound to this function. Do not store it. It can - * be used to modify headers. + * @param navigationHandle + * NavigationHandle are provided to several WebContentsObserver methods to allow + * observers to track specific navigations. Observers should clear any references to a + * NavigationHandle at didFinishNavigation(); */ - public void didRedirectNavigation( - String url, boolean isInMainFrame, long navigationHandleProxy) {} + public void didRedirectNavigation(NavigationHandle navigationHandle) {} /** * Called when the current navigation is finished. This happens when a navigation is committed, * aborted or replaced by a new one. - * @param url The validated URL for the loading page. - * @param isInMainFrame Whether the navigation is for the main frame. - * @param isErrorPage Whether the navigation shows an error page. - * @param hasCommitted Whether the navigation has committed. This returns true for either - * successful commits or error pages that replace the previous page - * (distinguished by |isErrorPage|), and false for errors that leave the - * user on the previous page. When false, |isSameDocument|, - * |isFragmentNavigation|, |pageTransition| and |httpStatusCode| will have - * default values. - * @param isSameDocument Whether the main frame navigation did not cause changes to the - * document (for example scrolling to a named anchor or PopState). - * @param isFragmentNavigation Whether the navigation was to a different fragment. - * @param isRendererInitiated Whether initiated by renderer. Eg clicking on a link. - * @param isDownload See NavigationHandle::IsDownload. - * @param pageTransition The page transition type associated with this navigation. - * @param errorCode The net error code if an error occurred prior to commit, otherwise net::OK. - * @param errorDescription The description for the net error code. - * @param httpStatusCode The HTTP status code of the navigation. + * @param navigationHandle + * NavigationHandle are provided to several WebContentsObserver methods to allow + * observers to track specific navigations. Observers should clear any references to a + * NavigationHandle at the end of this function. */ - public void didFinishNavigation(String url, boolean isInMainFrame, boolean isErrorPage, - boolean hasCommitted, boolean isSameDocument, boolean isFragmentNavigation, - boolean isRendererInitiated, boolean isDownload, @Nullable Integer pageTransition, - int errorCode, String errorDescription, int httpStatusCode) {} + public void didFinishNavigation(NavigationHandle navigationHandle) {} /** * Called when the a page starts loading.
diff --git a/content/public/android/junit/src/org/chromium/content/browser/UiThreadTaskTraitsImplTest.java b/content/public/android/junit/src/org/chromium/content/browser/UiThreadTaskTraitsImplTest.java new file mode 100644 index 0000000..1709097 --- /dev/null +++ b/content/public/android/junit/src/org/chromium/content/browser/UiThreadTaskTraitsImplTest.java
@@ -0,0 +1,43 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.content.browser; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import android.support.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; + +import org.chromium.base.task.TaskTraits; +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.content_public.browser.BrowserTaskType; + +/** + * Tests for {@link UiThreadTaskTraitsImpl} + */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public class UiThreadTaskTraitsImplTest { + @Test + @SmallTest + public void testContainsExtension() { + TaskTraits traits = UiThreadTaskTraitsImpl.BOOTSTRAP; + UiThreadTaskTraitsImpl impl = traits.getExtension(UiThreadTaskTraitsImpl.DESCRIPTOR); + + assertNotNull(impl); + } + + @Test + @SmallTest + public void testCanDeserializeProperties() { + TaskTraits traits = UiThreadTaskTraitsImpl.BOOTSTRAP; + UiThreadTaskTraitsImpl impl = traits.getExtension(UiThreadTaskTraitsImpl.DESCRIPTOR); + + assertEquals(BrowserTaskType.BOOTSTRAP, impl.getTaskType()); + } +}
diff --git a/content/public/browser/tracing_controller.h b/content/public/browser/tracing_controller.h index 51151438..c2e3e98d 100644 --- a/content/public/browser/tracing_controller.h +++ b/content/public/browser/tracing_controller.h
@@ -75,9 +75,8 @@ // Tracing begins immediately locally, and asynchronously on child processes // as soon as they receive the StartTracing request. // - // Once tracing is enabled in the current process and trace events can be - // emitted (unless excluded from the config), StartTracingDoneCallback will - // be called back. + // Once all child processes have acked to the StartTracing request, + // StartTracingDoneCallback will be called back. // // |category_filter| is a filter to control what category groups should be // traced. A filter can have an optional '-' prefix to exclude category groups
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index 4f716c14..47714c8 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -658,6 +658,8 @@ "//services/device/public/cpp/generic_sensor", "//services/device/public/mojom", "//services/device/public/mojom:constants", + "//services/image_annotation/public/cpp:cpp", + "//services/image_annotation/public/mojom:mojom", "//services/metrics/public/cpp:metrics_cpp", "//services/network:network_service", "//services/service_manager/public/cpp",
diff --git a/content/renderer/accessibility/ax_image_annotator.cc b/content/renderer/accessibility/ax_image_annotator.cc index 8de3080..e8805b0 100644 --- a/content/renderer/accessibility/ax_image_annotator.cc +++ b/content/renderer/accessibility/ax_image_annotator.cc
@@ -4,19 +4,30 @@ #include "content/renderer/accessibility/ax_image_annotator.h" +#include "base/base64.h" #include "base/stl_util.h" +#include "content/renderer/render_frame_impl.h" +#include "crypto/sha2.h" #include "third_party/blink/public/web/web_ax_object.h" #include "third_party/blink/public/web/web_document.h" +#include "third_party/blink/public/web/web_element.h" +#include "third_party/blink/public/web/web_node.h" +#include "ui/gfx/geometry/size.h" +#include "url/gurl.h" namespace content { AXImageAnnotator::AXImageAnnotator( RenderAccessibilityImpl* const render_accessibility) - : render_accessibility_(render_accessibility) { + : render_accessibility_(render_accessibility), weak_factory_(this) { DCHECK(render_accessibility_); + render_accessibility_->render_frame()->GetRemoteInterfaces()->GetInterface( + mojo::MakeRequest(&annotator_ptr_)); } -AXImageAnnotator::~AXImageAnnotator() { +AXImageAnnotator::~AXImageAnnotator() {} + +void AXImageAnnotator::Destroy() { MarkAllImagesDirty(); } @@ -25,24 +36,57 @@ DCHECK(!image.IsDetached()); const auto lookup = image_annotations_.find(image.AxID()); if (lookup != image_annotations_.end()) - return lookup->second; - return {}; + return lookup->second.annotation(); + return std::string(); +} + +bool AXImageAnnotator::HasAnnotationInCache(blink::WebAXObject& image) const { + DCHECK(!image.IsDetached()); + if (!HasImageInCache(image)) + return false; + return image_annotations_.at(image.AxID()).HasAnnotation(); +} + +bool AXImageAnnotator::HasImageInCache(const blink::WebAXObject& image) const { + DCHECK(!image.IsDetached()); + return base::ContainsKey(image_annotations_, image.AxID()); } void AXImageAnnotator::OnImageAdded(blink::WebAXObject& image) { DCHECK(!image.IsDetached()); DCHECK(!base::ContainsKey(image_annotations_, image.AxID())); + std::string document_url = + render_accessibility_->GetMainDocument().Url().GetString().Utf8(); + std::string image_src = image.Url().GetString().Utf8(); + std::string image_id = GenerateImageSourceId(document_url, image_src); + if (image_id.empty()) + return; + + image_annotations_.emplace(image.AxID(), image); + ImageInfo& image_info = image_annotations_.at(image.AxID()); // Fetch image annotation. - image_annotations_.emplace(image.AxID(), std::string()); - render_accessibility_->MarkWebAXObjectDirty(image, false /* subtree */); + annotator_ptr_->AnnotateImage( + image_id, image_info.GetImageProcessor(), + base::BindOnce(&AXImageAnnotator::OnImageAnnotated, + weak_factory_.GetWeakPtr(), image)); } void AXImageAnnotator::OnImageUpdated(blink::WebAXObject& image) { DCHECK(!image.IsDetached()); DCHECK(base::ContainsKey(image_annotations_, image.AxID())); + std::string document_url = + render_accessibility_->GetMainDocument().Url().GetString().Utf8(); + std::string image_src = image.Url().GetString().Utf8(); + std::string image_id = GenerateImageSourceId(document_url, image_src); + if (image_id.empty()) + return; + + ImageInfo& image_info = image_annotations_.at(image.AxID()); // Update annotation. - image_annotations_[image.AxID()] = std::string(); - render_accessibility_->MarkWebAXObjectDirty(image, false /* subtree */); + annotator_ptr_->AnnotateImage( + image_id, image_info.GetImageProcessor(), + base::BindOnce(&AXImageAnnotator::OnImageAnnotated, + weak_factory_.GetWeakPtr(), image)); } void AXImageAnnotator::OnImageRemoved(blink::WebAXObject& image) { @@ -53,7 +97,6 @@ return; } image_annotations_.erase(lookup); - render_accessibility_->MarkWebAXObjectDirty(image, false /* subtree */); } void AXImageAnnotator::MarkAllImagesDirty() { @@ -66,4 +109,78 @@ image_annotations_.clear(); } +AXImageAnnotator::ImageInfo::ImageInfo(const blink::WebAXObject& image) + : image_processor_( + base::BindRepeating(&AXImageAnnotator::GetImageData, image)), + annotation_(base::nullopt) {} + +AXImageAnnotator::ImageInfo::~ImageInfo() = default; + +image_annotation::mojom::ImageProcessorPtr +AXImageAnnotator::ImageInfo::GetImageProcessor() { + return image_processor_.GetPtr(); +} + +bool AXImageAnnotator::ImageInfo::HasAnnotation() const { + return annotation_.has_value(); +} + +// static +std::string AXImageAnnotator::GenerateImageSourceId( + const std::string& document_url, + const std::string& image_src) { + if (document_url.empty() || image_src.empty()) + return std::string(); + + // The |image_src| might be a URL that is relative to the document's URL. + const GURL image_url = GURL(document_url).Resolve(image_src); + if (!image_url.is_valid()) + return std::string(); + + // If |image_url| appears to be publicly reachable, return the URL as the + // image source ID. + if (image_url.SchemeIsHTTPOrHTTPS()) + return image_url.spec(); + + // If |image_url| is not publicly reachable, return a hash of |image_url|. + // Scheme could be "data", "javascript", "ftp", "file", etc. + const std::string& content = image_url.GetContent(); + if (content.empty()) + return std::string(); + std::string source_id; + base::Base64Encode(crypto::SHA256HashString(content), &source_id); + return source_id; +} + +// static +SkBitmap AXImageAnnotator::GetImageData(const blink::WebAXObject& image) { + if (image.IsDetached()) + return SkBitmap(); + blink::WebNode node = image.GetNode(); + if (node.IsNull() || !node.IsElementNode()) + return SkBitmap(); + blink::WebElement element = node.To<blink::WebElement>(); + return element.ImageContents(); +} + +void AXImageAnnotator::OnImageAnnotated( + const blink::WebAXObject& image, + image_annotation::mojom::AnnotateImageResultPtr result) { + if (image.IsDetached()) + return; + if (!base::ContainsKey(image_annotations_, image.AxID())) + return; + // TODO(nektar): Set the image annotation status on this image to Error. + if (result->is_error_code()) + return; + if (!result->is_ocr_text()) { + DLOG(WARNING) << "Unrecognized image annotation result."; + return; + } + // TODO(nektar): Add message to explain that the annotation is a best guess, + // e.g. "appears to be". + image_annotations_.at(image.AxID()).set_annotation(result->get_ocr_text()); + render_accessibility_->MarkWebAXObjectDirty(image, false /* subtree */); +} + } // namespace content
diff --git a/content/renderer/accessibility/ax_image_annotator.h b/content/renderer/accessibility/ax_image_annotator.h index c3c6c09..5b640e6c 100644 --- a/content/renderer/accessibility/ax_image_annotator.h +++ b/content/renderer/accessibility/ax_image_annotator.h
@@ -8,9 +8,15 @@ #include <string> #include <unordered_map> +#include "base/bind.h" #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "base/observer_list_types.h" +#include "base/optional.h" #include "content/renderer/accessibility/render_accessibility_impl.h" +#include "services/image_annotation/public/cpp/image_processor.h" +#include "services/image_annotation/public/mojom/image_annotation.mojom.h" +#include "third_party/skia/include/core/SkBitmap.h" namespace blink { @@ -29,23 +35,67 @@ AXImageAnnotator(RenderAccessibilityImpl* const render_accessibility); ~AXImageAnnotator() override; + void Destroy(); + std::string GetImageAnnotation(blink::WebAXObject& image) const; + bool HasAnnotationInCache(blink::WebAXObject& image) const; + bool HasImageInCache(const blink::WebAXObject& image) const; void OnImageAdded(blink::WebAXObject& image); void OnImageUpdated(blink::WebAXObject& image); void OnImageRemoved(blink::WebAXObject& image); private: + // Keeps track of the image data and the automatic annotation for each image. + class ImageInfo final { + public: + ImageInfo(const blink::WebAXObject& image); + virtual ~ImageInfo(); + + image_annotation::mojom::ImageProcessorPtr GetImageProcessor(); + bool HasAnnotation() const; + + std::string annotation() const { + DCHECK(annotation_.has_value()); + return annotation_.value_or(""); + } + + void set_annotation(std::string annotation) { annotation_ = annotation; } + + private: + image_annotation::ImageProcessor image_processor_; + base::Optional<std::string> annotation_; + }; + + // Given the URL of the main document and the src attribute of an image, + // generates a unique identifier for the image that could be provided to the + // image annotation service. + static std::string GenerateImageSourceId(const std::string& document_url, + const std::string& image_src); + + // Retrieves the image data from the renderer. + static SkBitmap GetImageData(const blink::WebAXObject& image); + // Removes the automatic image annotations from all images. void MarkAllImagesDirty(); + // Gets called when an image gets annotated by the image annotation service. + void OnImageAnnotated(const blink::WebAXObject& image, + image_annotation::mojom::AnnotateImageResultPtr result); + // Weak, owns us. RenderAccessibilityImpl* const render_accessibility_; - // Keeps track of all the automatic annotations for each image. + // A pointer to the automatic image annotation service. + image_annotation::mojom::AnnotatorPtr annotator_ptr_; + + // Keeps track of the image data and the automatic annotations for each image. // // The key is retrieved using WebAXObject::AxID(). - std::unordered_map<int, std::string> image_annotations_; + std::unordered_map<int, ImageInfo> image_annotations_; + + // This member needs to be last because it should destructed first. + base::WeakPtrFactory<AXImageAnnotator> weak_factory_; DISALLOW_COPY_AND_ASSIGN(AXImageAnnotator); };
diff --git a/content/renderer/accessibility/blink_ax_tree_source.cc b/content/renderer/accessibility/blink_ax_tree_source.cc index c1f5e20..372534c 100644 --- a/content/renderer/accessibility/blink_ax_tree_source.cc +++ b/content/renderer/accessibility/blink_ax_tree_source.cc
@@ -883,8 +883,12 @@ if (accessibility_mode_.has_mode(ui::AXMode::kLabelImages) && dst->role == ax::mojom::Role::kImage) { DCHECK(image_annotator_); - dst->AddStringAttribute(ax::mojom::StringAttribute::kImageAnnotation, - image_annotator_->GetImageAnnotation(src)); + if (image_annotator_->HasAnnotationInCache(src)) { + dst->AddStringAttribute(ax::mojom::StringAttribute::kImageAnnotation, + image_annotator_->GetImageAnnotation(src)); + } else if (!image_annotator_->HasImageInCache(src)) { + image_annotator_->OnImageAdded(src); + } } // The majority of the rest of this code computes attributes needed for
diff --git a/content/renderer/accessibility/blink_ax_tree_source.h b/content/renderer/accessibility/blink_ax_tree_source.h index 78b2220..7f9c6788 100644 --- a/content/renderer/accessibility/blink_ax_tree_source.h +++ b/content/renderer/accessibility/blink_ax_tree_source.h
@@ -75,7 +75,7 @@ // The following methods add or remove an image annotator which is used to // provide automatic labels for images. - void AddImageAnnotator(const AXImageAnnotator* const annotator) { + void AddImageAnnotator(AXImageAnnotator* const annotator) { image_annotator_ = annotator; } void RemoveImageAnnotator() { image_annotator_ = nullptr; } @@ -144,7 +144,7 @@ gfx::Size max_image_data_size_; - const AXImageAnnotator* image_annotator_ = nullptr; + AXImageAnnotator* image_annotator_ = nullptr; // These are updated when calling |Freeze|. bool frozen_ = false;
diff --git a/content/renderer/accessibility/render_accessibility_impl.cc b/content/renderer/accessibility/render_accessibility_impl.cc index f3b4ee9b..716d7637 100644 --- a/content/renderer/accessibility/render_accessibility_impl.cc +++ b/content/renderer/accessibility/render_accessibility_impl.cc
@@ -131,14 +131,7 @@ const WebDocument& document = GetMainDocument(); if (!document.IsNull()) { ax_context_ = std::make_unique<blink::WebAXContext>(document); - - if (mode.has_mode(ui::AXMode::kLabelImages)) { - ax_image_annotator_ = std::make_unique<AXImageAnnotator>(this); - tree_source_.AddImageAnnotator(ax_image_annotator_.get()); - } else { - tree_source_.RemoveImageAnnotator(); - ax_image_annotator_.release(); - } + StartOrStopLabelingImages(ui::AXMode(), mode); // It's possible that the webview has already loaded a webpage without // accessibility being enabled. Initialize the browser's cached @@ -156,8 +149,9 @@ } void RenderAccessibilityImpl::AccessibilityModeChanged() { + ui::AXMode old_mode = tree_source_.accessibility_mode(); ui::AXMode new_mode = render_frame_->accessibility_mode(); - if (tree_source_.accessibility_mode() == new_mode) + if (old_mode == new_mode) return; tree_source_.SetAccessibilityMode(new_mode); @@ -184,13 +178,7 @@ serializer_.Reset(); const WebDocument& document = GetMainDocument(); if (!document.IsNull()) { - if (new_mode.has_mode(ui::AXMode::kLabelImages)) { - ax_image_annotator_ = std::make_unique<AXImageAnnotator>(this); - tree_source_.AddImageAnnotator(ax_image_annotator_.get()); - } else { - tree_source_.RemoveImageAnnotator(); - ax_image_annotator_.release(); - } + StartOrStopLabelingImages(old_mode, new_mode); // If there are any events in flight, |HandleAXEvent| will refuse to process // our new event. @@ -842,6 +830,20 @@ update->has_tree_data = true; } +void RenderAccessibilityImpl::StartOrStopLabelingImages(ui::AXMode old_mode, + ui::AXMode new_mode) { + if (!old_mode.has_mode(ui::AXMode::kLabelImages) && + new_mode.has_mode(ui::AXMode::kLabelImages)) { + ax_image_annotator_ = std::make_unique<AXImageAnnotator>(this); + tree_source_.AddImageAnnotator(ax_image_annotator_.get()); + } else if (old_mode.has_mode(ui::AXMode::kLabelImages) && + !new_mode.has_mode(ui::AXMode::kLabelImages)) { + tree_source_.RemoveImageAnnotator(); + ax_image_annotator_->Destroy(); + ax_image_annotator_.release(); + } +} + void RenderAccessibilityImpl::Scroll(const WebAXObject& target, ax::mojom::Action scroll_action) { WebAXObject offset_container;
diff --git a/content/renderer/accessibility/render_accessibility_impl.h b/content/renderer/accessibility/render_accessibility_impl.h index 4f5a3151..49dd68b 100644 --- a/content/renderer/accessibility/render_accessibility_impl.h +++ b/content/renderer/accessibility/render_accessibility_impl.h
@@ -67,9 +67,11 @@ AXContentTreeUpdate* response, ui::AXMode ax_mode); - RenderAccessibilityImpl(RenderFrameImpl* render_frame, ui::AXMode mode); + RenderAccessibilityImpl(RenderFrameImpl* const render_frame, ui::AXMode mode); ~RenderAccessibilityImpl() override; + RenderFrameImpl* render_frame() { return render_frame_; } + // RenderAccessibility implementation. int GenerateAXID() override; void SetPluginTreeSource(PluginAXTreeSource* source) override; @@ -134,6 +136,12 @@ void OnLoadInlineTextBoxes(const blink::WebAXObject& obj); void OnGetImageData(const blink::WebAXObject& obj, const gfx::Size& max_size); void AddPluginTreeToUpdate(AXContentTreeUpdate* update); + + // Automatically labels images for accessibility if the accessibility mode for + // this feature is turned on, otherwise stops automatic labeling and removes + // any automatic annotations that might have been added before. + void StartOrStopLabelingImages(ui::AXMode old_mode, ui::AXMode new_mode); + void Scroll(const blink::WebAXObject& target, ax::mojom::Action scroll_action); void ScrollPlugin(int id_to_make_visible); @@ -142,7 +150,7 @@ void RecordImageMetrics(AXContentTreeUpdate* update); // The RenderFrameImpl that owns us. - RenderFrameImpl* render_frame_; + RenderFrameImpl* const render_frame_; // This keeps accessibility enabled as long as it lives. std::unique_ptr<blink::WebAXContext> ax_context_;
diff --git a/content/renderer/compositor/layer_tree_view.cc b/content/renderer/compositor/layer_tree_view.cc index 811c170..13288f8 100644 --- a/content/renderer/compositor/layer_tree_view.cc +++ b/content/renderer/compositor/layer_tree_view.cc
@@ -571,9 +571,7 @@ delegate_->WillBeginCompositorFrame(); } -void LayerTreeView::DidBeginMainFrame() { - delegate_->DidBeginMainFrame(); -} +void LayerTreeView::DidBeginMainFrame() {} void LayerTreeView::DidUpdateLayers() { // Dump property trees and layers if run with:
diff --git a/content/renderer/compositor/layer_tree_view_delegate.h b/content/renderer/compositor/layer_tree_view_delegate.h index c219245..a5d2d82 100644 --- a/content/renderer/compositor/layer_tree_view_delegate.h +++ b/content/renderer/compositor/layer_tree_view_delegate.h
@@ -56,10 +56,6 @@ // Notifies that the compositor has issued a BeginMainFrame. virtual void BeginMainFrame(base::TimeTicks frame_time) = 0; - // Notifies that the layer tree host has completed a call to - // RequestMainFrameUpdate in response to a BeginMainFrame. - virtual void DidBeginMainFrame() = 0; - // Requests a LayerTreeFrameSink to submit CompositorFrames to. virtual void RequestNewLayerTreeFrameSink( LayerTreeFrameSinkCallback callback) = 0;
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index c870350..84dbb79 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -1102,12 +1102,6 @@ GetWebWidget()->BeginFrame(frame_time, record_main_frame_metrics); } -void RenderWidget::DidBeginMainFrame() { - if (!GetWebWidget()) - return; - GetWebWidget()->DidBeginFrame(); -} - void RenderWidget::RequestNewLayerTreeFrameSink( LayerTreeFrameSinkCallback callback) { // For widgets that are never visible, we don't start the compositor, so we
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index bd4a3b94..6205ae9 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h
@@ -333,7 +333,6 @@ void SendScrollEndEventFromImplSide( cc::ElementId scroll_latched_element_id) override; void BeginMainFrame(base::TimeTicks frame_time) override; - void DidBeginMainFrame() override; void RequestNewLayerTreeFrameSink( LayerTreeFrameSinkCallback callback) override; void DidCommitAndDrawCompositorFrame() override;
diff --git a/content/renderer/v8_value_converter_impl_unittest.cc b/content/renderer/v8_value_converter_impl_unittest.cc index e60f671..2d3d67c 100644 --- a/content/renderer/v8_value_converter_impl_unittest.cc +++ b/content/renderer/v8_value_converter_impl_unittest.cc
@@ -249,7 +249,7 @@ }; TEST_F(V8ValueConverterImplTest, BasicRoundTrip) { - std::unique_ptr<base::Value> original_root = base::test::ParseJson( + std::unique_ptr<base::Value> original_root = base::test::ParseJsonDeprecated( "{ \n" " \"null\": null, \n" " \"true\": true, \n" @@ -389,7 +389,7 @@ TEST_F(V8ValueConverterImplTest, KeysWithDots) { std::unique_ptr<base::Value> original = - base::test::ParseJson("{ \"foo.bar\": \"baz\" }"); + base::test::ParseJsonDeprecated("{ \"foo.bar\": \"baz\" }"); v8::HandleScope handle_scope(isolate_); v8::Local<v8::Context> context = @@ -480,7 +480,7 @@ // because the setters/getters are defined on the array instance, not // on the Array's prototype. converted.reset(static_cast<base::ListValue*>( - base::test::ParseJson("[ \"foo\", \"bar\" ]").release())); + base::test::ParseJsonDeprecated("[ \"foo\", \"bar\" ]").release())); v8::Local<v8::Array> copy = converter.ToV8Value(converted.get(), context).As<v8::Array>(); ASSERT_FALSE(copy.IsEmpty()); @@ -547,7 +547,7 @@ TEST_F(V8ValueConverterImplTest, ObjectPrototypeSetter) { std::unique_ptr<base::Value> original = - base::test::ParseJson("{ \"foo\": \"good value\" }"); + base::test::ParseJsonDeprecated("{ \"foo\": \"good value\" }"); v8::HandleScope handle_scope(isolate_); v8::Local<v8::Context> context = @@ -615,7 +615,7 @@ TEST_F(V8ValueConverterImplTest, ArrayPrototypeSetter) { std::unique_ptr<base::Value> original = - base::test::ParseJson("[100, 200, 300]"); + base::test::ParseJsonDeprecated("[100, 200, 300]"); v8::HandleScope handle_scope(isolate_); v8::Local<v8::Context> context = @@ -776,7 +776,7 @@ V8ValueConverterImpl converter; std::unique_ptr<base::Value> actual(converter.FromV8Value(object, context)); - std::unique_ptr<base::Value> expected = base::test::ParseJson( + std::unique_ptr<base::Value> expected = base::test::ParseJsonDeprecated( "{ \n" " \"1\": \"foo\", \n" " \"2\": \"bar\", \n" @@ -848,16 +848,18 @@ std::unique_ptr<base::Value> actual_object( converter.FromV8Value(object, context)); - EXPECT_EQ(*base::test::ParseJson("{ \"bar\": null }"), *actual_object); + EXPECT_EQ(*base::test::ParseJsonDeprecated("{ \"bar\": null }"), + *actual_object); // Everything is null because JSON stringification preserves array length. std::unique_ptr<base::Value> actual_array( converter.FromV8Value(array, context)); - EXPECT_EQ(*base::test::ParseJson("[ null, null, null ]"), *actual_array); + EXPECT_EQ(*base::test::ParseJsonDeprecated("[ null, null, null ]"), + *actual_array); std::unique_ptr<base::Value> actual_sparse_array( converter.FromV8Value(sparse_array, context)); - EXPECT_EQ(*base::test::ParseJson("[ null, null, null ]"), + EXPECT_EQ(*base::test::ParseJsonDeprecated("[ null, null, null ]"), *actual_sparse_array); } @@ -885,7 +887,7 @@ // The expected base::Value result. std::unique_ptr<base::Value> expected = - base::test::ParseJson("[{},{},[],[]]"); + base::test::ParseJsonDeprecated("[{},{},[],[]]"); ASSERT_TRUE(expected.get()); // The actual result. @@ -1212,7 +1214,7 @@ converter.FromV8Value(object, context)); ASSERT_TRUE(object_value); std::unique_ptr<base::Value> reference_object_value( - base::test::ParseJson("{}")); + base::test::ParseJsonDeprecated("{}")); EXPECT_EQ(*reference_object_value, *object_value); v8::Local<v8::Array> array(v8::Array::New(isolate_)); @@ -1220,7 +1222,7 @@ converter.FromV8Value(array, context)); ASSERT_TRUE(array_value); std::unique_ptr<base::Value> reference_array_value( - base::test::ParseJson("[]")); + base::test::ParseJsonDeprecated("[]")); EXPECT_EQ(*reference_array_value, *array_value); const char kExampleData[] = {1, 2, 3, 4, 5}; @@ -1249,7 +1251,7 @@ converter.FromV8Value(number, context)); ASSERT_TRUE(number_value); std::unique_ptr<base::Value> reference_number_value( - base::test::ParseJson("0")); + base::test::ParseJsonDeprecated("0")); EXPECT_EQ(*reference_number_value, *number_value); v8::Local<v8::Primitive> undefined(v8::Undefined(isolate_));
diff --git a/content/test/data/gpu/power_video_bear_1280x720_mp4.html b/content/test/data/gpu/power_video_bear_1280x720_mp4.html new file mode 100644 index 0000000..fdaeb22 --- /dev/null +++ b/content/test/data/gpu/power_video_bear_1280x720_mp4.html
@@ -0,0 +1,16 @@ +<!DOCTYPE HTML> + +<html> +<head> +<title>MP4 Video Power Test</title> +<script src="power_video_test.js"></script> +</head> +<body onload="main()"> +<button id="fullscreen" onclick="goFullscreen()">Fullscreen</button> +<div id="container"> +<video id="video" width="1280" height="720" > +<source src="/media/test/data/bear-1280x720.mp4" type="video/mp4"> +</video> +</div> +</body> +</html>
diff --git a/content/test/data/gpu/power_video_test.js b/content/test/data/gpu/power_video_test.js new file mode 100644 index 0000000..283f551 --- /dev/null +++ b/content/test/data/gpu/power_video_test.js
@@ -0,0 +1,71 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var video = null; +var box = null; + +function main() { + video = document.getElementById("video"); + // This is necessary for us to insert a colored box on top of the video + // and position it to the corner correctly so video becomes underlay. + video.parentNode.style.position = "relative"; + video.loop = true; + video.muted = true; + video.addEventListener('timeupdate', waitForVideoToPlay); + video.play(); +} + +function waitForVideoToPlay() { + if (video.currentTime > 0) { + video.removeEventListener('timeupdate', waitForVideoToPlay); + domAutomationController.send("SUCCESS"); + } +} + +function goFullscreen() { + if (video.requestFullscreen) { + video.requestFullscreen(); + } else if (video.webkitRequestFullscreen) { + video.webkitRequestFullscreen(); + } +} + +function goUnderlay() { + if (!box) { + // Draw a solid color box in the top left corner of the video, so the + // video becomes an underlay. + box = document.createElement("div"); + //redbox.style.border = "thick solid rgb(0,0,255)"; + box.style.backgroundColor = "red"; + box.style.width = "100px"; + box.style.height = "50px"; + box.style.position = "absolute"; + box.style.zIndex = "1000"; + var vid_rect = video.getBoundingClientRect(); + var parent_rect = video.parentNode.getBoundingClientRect(); + var top = vid_rect.top - parent_rect.top + 10; + var left = vid_rect.left - parent_rect.left + 10; + box.style.top = top.toString() + "px"; + box.style.left = left.toString() + "px"; + box.style.visibility = "visible"; + video.parentNode.appendChild(box); + } + // Change box color between red/blue every second. This is to emulate UI + // or ads change (once per second) on top of a video. + setTimeout(setBoxColorToBlue, 1000); +} + +function setBoxColorToBlue() { + if (!box) + return; + box.style.backgroundColor = "blue"; + setTimeout(setBoxColorToRed, 1000); +} + +function setBoxColorToRed() { + if (!box) + return; + box.style.backgroundColor = "red"; + setTimeout(setBoxColorToBlue, 1000); +}
diff --git a/content/test/gpu/gpu_tests/gpu_integration_test.py b/content/test/gpu/gpu_tests/gpu_integration_test.py index 7c908f6..4f88735 100644 --- a/content/test/gpu/gpu_tests/gpu_integration_test.py +++ b/content/test/gpu/gpu_tests/gpu_integration_test.py
@@ -136,8 +136,8 @@ cls.tab = cls.browser.tabs[0] return except Exception: - logging.warning('Browser start failed (attempt %d of %d)', - x, _START_BROWSER_RETRIES) + logging.exception('Browser start failed (attempt %d of %d). Backtrace:', + x, _START_BROWSER_RETRIES) # If we are on the last try and there is an exception take a screenshot # to try and capture more about the browser failure and raise if x == _START_BROWSER_RETRIES:
diff --git a/content/test/gpu/gpu_tests/power_measurement_integration_test.py b/content/test/gpu/gpu_tests/power_measurement_integration_test.py index 4a9b484b..1f7a82a 100644 --- a/content/test/gpu/gpu_tests/power_measurement_integration_test.py +++ b/content/test/gpu/gpu_tests/power_measurement_integration_test.py
@@ -25,6 +25,7 @@ from gpu_tests import gpu_integration_test from gpu_tests import ipg_utils +from gpu_tests import path_util from gpu_tests.gpu_test_expectations import GpuTestExpectations import logging @@ -42,6 +43,40 @@ # Measures power in resolution of [x] milli-seconds. _POWER_MEASUREMENT_RESOLUTION = 100 +_GPU_RELATIVE_PATH = "content/test/data/gpu/" + +_DATA_PATHS = [os.path.join( + path_util.GetChromiumSrcDir(), _GPU_RELATIVE_PATH), + os.path.join( + path_util.GetChromiumSrcDir(), 'media', 'test', 'data')] + +_BASIC_TEST_HARNESS_SCRIPT = r""" + var domAutomationController = {}; + + domAutomationController._proceed = false; + + domAutomationController._readyForActions = false; + domAutomationController._succeeded = false; + domAutomationController._finished = false; + + domAutomationController.send = function(msg) { + domAutomationController._proceed = true; + let lmsg = msg.toLowerCase(); + if (lmsg == "ready") { + domAutomationController._readyForActions = true; + } else { + domAutomationController._finished = true; + if (lmsg == "success") { + domAutomationController._succeeded = true; + } else { + domAutomationController._succeeded = false; + } + } + } + + window.domAutomationController = domAutomationController; +""" + _FULLSCREEN_SCRIPT = r""" function locateElement(tag) { // return the element with largest width. @@ -196,14 +231,26 @@ yield ('Basic', '-', {'test_func': 'Basic', 'bypass_ipg': options.bypass_ipg}) + yield ('Video_720_MP4', + _GPU_RELATIVE_PATH + 'power_video_bear_1280x720_mp4.html', + {'test_func': 'Video', + 'bypass_ipg': options.bypass_ipg, + 'underlay': False, + 'fullscreen': False}) + yield ('Video_720_MP4_Underlay', + _GPU_RELATIVE_PATH + 'power_video_bear_1280x720_mp4.html', + {'test_func': 'Video', + 'bypass_ipg': options.bypass_ipg, + 'underlay': True, + 'fullscreen': False}) @classmethod def SetUpProcess(cls): super(cls, PowerMeasurementIntegrationTest).SetUpProcess() - cls.CustomizeBrowserArgs([ - '--autoplay-policy=no-user-gesture-required' - ]) + path_util.SetupTelemetryPaths() + cls.CustomizeBrowserArgs(cls._AddDefaultArgs([])) cls.StartBrowser() + cls.SetStaticServerDirs(_DATA_PATHS) def RunActualGpuTest(self, test_path, *args): test_params = args[0] @@ -215,11 +262,13 @@ def _CreateExpectations(cls): return PowerMeasurementExpectations() - ######################################### - # Actual test functions + @staticmethod + def _AddDefaultArgs(browser_args): + # All tests receive the following options. + return ['--autoplay-policy=no-user-gesture-required'] + browser_args - def _RunTest_Basic(self, test_path, params): - bypass_ipg = params['bypass_ipg'] + @staticmethod + def _MeasurePowerWithIPG(bypass_ipg): total_time = _POWER_MEASUREMENT_DURATION + _POWER_MEASUREMENT_DELAY if bypass_ipg: logging.info("Bypassing Intel Power Gadget") @@ -232,6 +281,41 @@ # chromeperf.appspot.com. logging.info("Results: %s", str(results)) + ######################################### + # Actual test functions + + def _RunTest_Basic(self, test_path, params): + bypass_ipg = params['bypass_ipg'] + PowerMeasurementIntegrationTest._MeasurePowerWithIPG(bypass_ipg) + + + def _RunTest_Video(self, test_path, params): + fullscreen = params['fullscreen'] + underlay = params['underlay'] + bypass_ipg = params['bypass_ipg'] + + disabled_features = [ + 'D3D11VideoDecoder', + 'DirectCompositionUseNV12DecodeSwapChain', + 'DirectCompositionUnderlays'] + self.RestartBrowserWithArgs( + PowerMeasurementIntegrationTest._AddDefaultArgs([ + '--disable-features=' + ','.join(disabled_features)])) + + url = self.UrlOfStaticFilePath(test_path) + self.tab.Navigate( + url, script_to_evaluate_on_commit=_BASIC_TEST_HARNESS_SCRIPT) + self.tab.action_runner.WaitForJavaScriptCondition( + 'domAutomationController._finished', timeout=30) + if fullscreen: + # TODO(zmo): Figure out why the following doesn't work + self.tab.action_runner.ClickElement(element_function=( + 'document.getElementById("fullscreen")')) + if underlay: + self.tab.action_runner.ExecuteJavaScript('goUnderlay();') + + PowerMeasurementIntegrationTest._MeasurePowerWithIPG(bypass_ipg) + def _RunTest_URL(self, test_path, params): repeat = params['repeat']
diff --git a/content/test/stub_layer_tree_view_delegate.h b/content/test/stub_layer_tree_view_delegate.h index eddef3c..a75b0ebe 100644 --- a/content/test/stub_layer_tree_view_delegate.h +++ b/content/test/stub_layer_tree_view_delegate.h
@@ -26,7 +26,6 @@ void SendScrollEndEventFromImplSide( cc::ElementId scroll_latched_element_id) override {} void BeginMainFrame(base::TimeTicks frame_time) override {} - void DidBeginMainFrame() override {} void RecordStartOfFrameMetrics() override {} void RecordEndOfFrameMetrics(base::TimeTicks) override {} void RequestNewLayerTreeFrameSink(
diff --git a/device/fido/scoped_virtual_fido_device.cc b/device/fido/scoped_virtual_fido_device.cc index 4d5f999..9aa0c74 100644 --- a/device/fido/scoped_virtual_fido_device.cc +++ b/device/fido/scoped_virtual_fido_device.cc
@@ -24,9 +24,10 @@ public base::SupportsWeakPtr<VirtualFidoDeviceDiscovery> { public: explicit VirtualFidoDeviceDiscovery( + FidoTransportProtocol transport, scoped_refptr<VirtualFidoDevice::State> state, ProtocolVersion supported_protocol) - : FidoDeviceDiscovery(FidoTransportProtocol::kUsbHumanInterfaceDevice), + : FidoDeviceDiscovery(transport), state_(std::move(state)), supported_protocol_(supported_protocol) {} ~VirtualFidoDeviceDiscovery() override = default; @@ -61,6 +62,10 @@ supported_protocol_ = supported_protocol; } +void ScopedVirtualFidoDevice::SetTransport(FidoTransportProtocol transport) { + transport_ = transport; +} + VirtualFidoDevice::State* ScopedVirtualFidoDevice::mutable_state() { return state_.get(); } @@ -68,10 +73,10 @@ std::unique_ptr<FidoDiscoveryBase> ScopedVirtualFidoDevice::CreateFidoDiscovery( FidoTransportProtocol transport, ::service_manager::Connector* connector) { - if (transport != FidoTransportProtocol::kUsbHumanInterfaceDevice) { + if (transport != transport_) { return nullptr; } - return std::make_unique<VirtualFidoDeviceDiscovery>(state_, + return std::make_unique<VirtualFidoDeviceDiscovery>(transport_, state_, supported_protocol_); }
diff --git a/device/fido/scoped_virtual_fido_device.h b/device/fido/scoped_virtual_fido_device.h index bbe4a5d..24765bec 100644 --- a/device/fido/scoped_virtual_fido_device.h +++ b/device/fido/scoped_virtual_fido_device.h
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "device/fido/fido_constants.h" #include "device/fido/fido_discovery_factory.h" +#include "device/fido/fido_transport_protocol.h" #include "device/fido/virtual_fido_device.h" namespace device { @@ -24,6 +25,14 @@ ScopedVirtualFidoDevice(); ~ScopedVirtualFidoDevice() override; + // Sets the FidoTransportProtocol of the FidoDiscovery to be instantiated by + // this ScopedVirtualFidoDevice. The default is + // FidoTransportProtocol::kUsbHumanInterfaceDevice. + // + // The FidoTransportProtocol of the device instantiated by the FidoDiscovery + // must be set separately in mutable_state(). + void SetTransport(FidoTransportProtocol transport); + void SetSupportedProtocol(ProtocolVersion supported_protocol); VirtualFidoDevice::State* mutable_state(); @@ -34,6 +43,8 @@ private: ProtocolVersion supported_protocol_ = ProtocolVersion::kU2f; + FidoTransportProtocol transport_ = + FidoTransportProtocol::kUsbHumanInterfaceDevice; scoped_refptr<VirtualFidoDevice::State> state_; DISALLOW_COPY_AND_ASSIGN(ScopedVirtualFidoDevice); };
diff --git a/docs/how_to_add_your_feature_flag.md b/docs/how_to_add_your_feature_flag.md index f9d5eea..e59fa5a 100644 --- a/docs/how_to_add_your_feature_flag.md +++ b/docs/how_to_add_your_feature_flag.md
@@ -1,6 +1,8 @@ # Adding a new feature flag in chrome://flags -This document describes how to add your new feature behind a flag. +This document describes how to add your new feature behind a flag. See also +[Configuration](configuration.md), which gives more explanation about flags and +other options for configuring Chrome. ## Step 1: Adding a new `base::Feature` This step would be different between where you want to use the flag.
diff --git a/extensions/browser/api/declarative/declarative_rule_unittest.cc b/extensions/browser/api/declarative/declarative_rule_unittest.cc index 04315c53d..87f7195 100644 --- a/extensions/browser/api/declarative/declarative_rule_unittest.cc +++ b/extensions/browser/api/declarative/declarative_rule_unittest.cc
@@ -12,7 +12,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using base::test::ParseJson; +using base::test::ParseJsonDeprecated; using url_matcher::URLMatcher; using url_matcher::URLMatcherConditionFactory; using url_matcher::URLMatcherConditionSet; @@ -64,8 +64,8 @@ TEST(DeclarativeConditionTest, ErrorConditionSet) { URLMatcher matcher; RecordingConditionSet::Values conditions; - conditions.push_back(ParseJson("{\"key\": 1}")); - conditions.push_back(ParseJson("{\"bad_key\": 2}")); + conditions.push_back(ParseJsonDeprecated("{\"key\": 1}")); + conditions.push_back(ParseJsonDeprecated("{\"bad_key\": 2}")); std::string error; std::unique_ptr<RecordingConditionSet> result = RecordingConditionSet::Create( @@ -77,8 +77,8 @@ TEST(DeclarativeConditionTest, CreateConditionSet) { URLMatcher matcher; RecordingConditionSet::Values conditions; - conditions.push_back(ParseJson("{\"key\": 1}")); - conditions.push_back(ParseJson("[\"val1\", 2]")); + conditions.push_back(ParseJsonDeprecated("{\"key\": 1}")); + conditions.push_back(ParseJsonDeprecated("[\"val1\", 2]")); // Test insertion std::string error; @@ -89,8 +89,8 @@ EXPECT_EQ(2u, result->conditions().size()); EXPECT_EQ(matcher.condition_factory(), result->conditions()[0]->factory); - EXPECT_TRUE(ParseJson("{\"key\": 1}")->Equals( - result->conditions()[0]->value.get())); + EXPECT_TRUE(ParseJsonDeprecated("{\"key\": 1}") + ->Equals(result->conditions()[0]->value.get())); } struct FulfillableCondition { @@ -151,10 +151,10 @@ TEST(DeclarativeConditionTest, FulfillConditionSet) { typedef DeclarativeConditionSet<FulfillableCondition> FulfillableConditionSet; FulfillableConditionSet::Values conditions; - conditions.push_back(ParseJson("{\"url_id\": 1, \"max\": 3}")); - conditions.push_back(ParseJson("{\"url_id\": 2, \"max\": 5}")); - conditions.push_back(ParseJson("{\"url_id\": 3, \"max\": 1}")); - conditions.push_back(ParseJson("{\"max\": -5}")); // No url. + conditions.push_back(ParseJsonDeprecated("{\"url_id\": 1, \"max\": 3}")); + conditions.push_back(ParseJsonDeprecated("{\"url_id\": 2, \"max\": 5}")); + conditions.push_back(ParseJsonDeprecated("{\"url_id\": 3, \"max\": 1}")); + conditions.push_back(ParseJsonDeprecated("{\"max\": -5}")); // No url. // Test insertion std::string error; @@ -254,8 +254,8 @@ TEST(DeclarativeActionTest, ErrorActionSet) { SummingActionSet::Values actions; - actions.push_back(ParseJson("{\"value\": 1}")); - actions.push_back(ParseJson("{\"error\": \"the error\"}")); + actions.push_back(ParseJsonDeprecated("{\"value\": 1}")); + actions.push_back(ParseJsonDeprecated("{\"error\": \"the error\"}")); std::string error; bool bad = false; @@ -266,8 +266,8 @@ EXPECT_FALSE(result); actions.clear(); - actions.push_back(ParseJson("{\"value\": 1}")); - actions.push_back(ParseJson("{\"bad\": 3}")); + actions.push_back(ParseJsonDeprecated("{\"value\": 1}")); + actions.push_back(ParseJsonDeprecated("{\"bad\": 3}")); result = SummingActionSet::Create(NULL, NULL, actions, &error, &bad); EXPECT_EQ("", error); EXPECT_TRUE(bad); @@ -277,9 +277,9 @@ TEST(DeclarativeActionTest, ApplyActionSet) { SummingActionSet::Values actions; actions.push_back( - ParseJson("{\"value\": 1," - " \"priority\": 5}")); - actions.push_back(ParseJson("{\"value\": 2}")); + ParseJsonDeprecated("{\"value\": 1," + " \"priority\": 5}")); + actions.push_back(ParseJsonDeprecated("{\"value\": 2}")); // Test insertion std::string error; @@ -300,21 +300,21 @@ TEST(DeclarativeRuleTest, Create) { typedef DeclarativeRule<FulfillableCondition, SummingAction> Rule; Rule::JsonRule json_rule; - ASSERT_TRUE( - Rule::JsonRule::Populate(*ParseJson("{ \n" - " \"id\": \"rule1\", \n" - " \"conditions\": [ \n" - " {\"url_id\": 1, \"max\": 3}, \n" - " {\"url_id\": 2, \"max\": 5}, \n" - " ], \n" - " \"actions\": [ \n" - " { \n" - " \"value\": 2 \n" - " } \n" - " ], \n" - " \"priority\": 200 \n" - "}"), - &json_rule)); + ASSERT_TRUE(Rule::JsonRule::Populate( + *ParseJsonDeprecated("{ \n" + " \"id\": \"rule1\", \n" + " \"conditions\": [ \n" + " {\"url_id\": 1, \"max\": 3}, \n" + " {\"url_id\": 2, \"max\": 5}, \n" + " ], \n" + " \"actions\": [ \n" + " { \n" + " \"value\": 2 \n" + " } \n" + " ], \n" + " \"priority\": 200 \n" + "}"), + &json_rule)); const char kExtensionId[] = "ext1"; scoped_refptr<const Extension> extension = ExtensionBuilder() @@ -376,39 +376,40 @@ .SetID(kExtensionId) .Build(); - ASSERT_TRUE( - Rule::JsonRule::Populate(*ParseJson("{ \n" - " \"id\": \"rule1\", \n" - " \"conditions\": [ \n" - " {\"url_id\": 1, \"max\": 3}, \n" - " {\"url_id\": 2, \"max\": 5}, \n" - " ], \n" - " \"actions\": [ \n" - " { \n" - " \"value\": 2 \n" - " } \n" - " ], \n" - " \"priority\": 200 \n" - "}"), - &json_rule)); + ASSERT_TRUE(Rule::JsonRule::Populate( + *ParseJsonDeprecated("{ \n" + " \"id\": \"rule1\", \n" + " \"conditions\": [ \n" + " {\"url_id\": 1, \"max\": 3}, \n" + " {\"url_id\": 2, \"max\": 5}, \n" + " ], \n" + " \"actions\": [ \n" + " { \n" + " \"value\": 2 \n" + " } \n" + " ], \n" + " \"priority\": 200 \n" + "}"), + &json_rule)); std::unique_ptr<Rule> rule(Rule::Create( matcher.condition_factory(), NULL, extension.get(), base::Time(), json_rule, base::Bind(AtLeastOneCondition), &error)); EXPECT_TRUE(rule); EXPECT_EQ("", error); - ASSERT_TRUE(Rule::JsonRule::Populate(*ParseJson("{ \n" - " \"id\": \"rule1\", \n" - " \"conditions\": [ \n" - " ], \n" - " \"actions\": [ \n" - " { \n" - " \"value\": 2 \n" - " } \n" - " ], \n" - " \"priority\": 200 \n" - "}"), - &json_rule)); + ASSERT_TRUE( + Rule::JsonRule::Populate(*ParseJsonDeprecated("{ \n" + " \"id\": \"rule1\", \n" + " \"conditions\": [ \n" + " ], \n" + " \"actions\": [ \n" + " { \n" + " \"value\": 2 \n" + " } \n" + " ], \n" + " \"priority\": 200 \n" + "}"), + &json_rule)); rule = Rule::Create(matcher.condition_factory(), NULL, extension.get(), base::Time(), json_rule, base::Bind(AtLeastOneCondition), &error);
diff --git a/extensions/browser/api/declarative_webrequest/webrequest_condition_unittest.cc b/extensions/browser/api/declarative_webrequest/webrequest_condition_unittest.cc index 193f15d..0a66a1d 100644 --- a/extensions/browser/api/declarative_webrequest/webrequest_condition_unittest.cc +++ b/extensions/browser/api/declarative_webrequest/webrequest_condition_unittest.cc
@@ -37,12 +37,11 @@ // Test wrong condition name passed. error.clear(); result = WebRequestCondition::Create( - NULL, - matcher.condition_factory(), - *base::test::ParseJson( - "{ \"invalid\": \"foobar\", \n" - " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", \n" - "}"), + NULL, matcher.condition_factory(), + *base::test::ParseJsonDeprecated( + "{ \"invalid\": \"foobar\", \n" + " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", \n" + "}"), &error); EXPECT_FALSE(error.empty()); EXPECT_FALSE(result.get()); @@ -50,13 +49,12 @@ // Test wrong datatype in host_suffix. error.clear(); result = WebRequestCondition::Create( - NULL, - matcher.condition_factory(), - *base::test::ParseJson( - "{ \n" - " \"url\": [], \n" - " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", \n" - "}"), + NULL, matcher.condition_factory(), + *base::test::ParseJsonDeprecated( + "{ \n" + " \"url\": [], \n" + " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", \n" + "}"), &error); EXPECT_FALSE(error.empty()); EXPECT_FALSE(result.get()); @@ -64,14 +62,13 @@ // Test success (can we support multiple criteria?) error.clear(); result = WebRequestCondition::Create( - NULL, - matcher.condition_factory(), - *base::test::ParseJson( - "{ \n" - " \"resourceType\": [\"main_frame\"], \n" - " \"url\": { \"hostSuffix\": \"example.com\" }, \n" - " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", \n" - "}"), + NULL, matcher.condition_factory(), + *base::test::ParseJsonDeprecated( + "{ \n" + " \"resourceType\": [\"main_frame\"], \n" + " \"url\": { \"hostSuffix\": \"example.com\" }, \n" + " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", \n" + "}"), &error); EXPECT_EQ("", error); ASSERT_TRUE(result.get()); @@ -133,13 +130,12 @@ std::unique_ptr<WebRequestCondition> result; result = WebRequestCondition::Create( - NULL, - matcher.condition_factory(), - *base::test::ParseJson( - "{ \n" - " \"firstPartyForCookiesUrl\": { \"hostPrefix\": \"fpfc\"}, \n" - " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", \n" - "}"), + NULL, matcher.condition_factory(), + *base::test::ParseJsonDeprecated( + "{ \n" + " \"firstPartyForCookiesUrl\": { \"hostPrefix\": \"fpfc\"}, \n" + " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", \n" + "}"), &error); EXPECT_EQ("", error); ASSERT_TRUE(result.get()); @@ -191,7 +187,7 @@ std::unique_ptr<WebRequestCondition> condition_empty = WebRequestCondition::Create( NULL, matcher.condition_factory(), - *base::test::ParseJson( + *base::test::ParseJsonDeprecated( "{ \n" " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", \n" "}"), @@ -204,7 +200,7 @@ std::unique_ptr<WebRequestCondition> condition_no_url_true = WebRequestCondition::Create( NULL, matcher.condition_factory(), - *base::test::ParseJson( + *base::test::ParseJsonDeprecated( "{ \n" " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", " "\n" @@ -221,7 +217,7 @@ std::unique_ptr<WebRequestCondition> condition_no_url_false = WebRequestCondition::Create( NULL, matcher.condition_factory(), - *base::test::ParseJson( + *base::test::ParseJsonDeprecated( "{ \n" " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", " "\n" @@ -260,7 +256,7 @@ URLMatcher matcher; WebRequestConditionSet::Values conditions; - conditions.push_back(base::test::ParseJson( + conditions.push_back(base::test::ParseJsonDeprecated( "{ \n" " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", \n" " \"url\": { \n" @@ -268,7 +264,7 @@ " \"schemes\": [\"http\"], \n" " }, \n" "}")); - conditions.push_back(base::test::ParseJson( + conditions.push_back(base::test::ParseJsonDeprecated( "{ \n" " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", \n" " \"url\": { \n" @@ -334,7 +330,7 @@ URLMatcher matcher; WebRequestConditionSet::Values conditions; - conditions.push_back(base::test::ParseJson( + conditions.push_back(base::test::ParseJsonDeprecated( "{ \n" " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", \n" " \"url\": { \n" @@ -403,16 +399,15 @@ // Test error on incompatible application stages for involved attributes. error.clear(); result = WebRequestCondition::Create( - NULL, - matcher.condition_factory(), - *base::test::ParseJson( - "{ \n" - " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", \n" - // Pass a JS array with one empty object to each of the header - // filters. - " \"requestHeaders\": [{}], \n" - " \"responseHeaders\": [{}], \n" - "}"), + NULL, matcher.condition_factory(), + *base::test::ParseJsonDeprecated( + "{ \n" + " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", \n" + // Pass a JS array with one empty object to each of the header + // filters. + " \"requestHeaders\": [{}], \n" + " \"responseHeaders\": [{}], \n" + "}"), &error); EXPECT_FALSE(error.empty()); EXPECT_FALSE(result.get());
diff --git a/extensions/common/BUILD.gn b/extensions/common/BUILD.gn index 593b8f9c..4ae214d 100644 --- a/extensions/common/BUILD.gn +++ b/extensions/common/BUILD.gn
@@ -398,6 +398,7 @@ "api/sockets/sockets_manifest_permission_unittest.cc", "component_extension_url_pattern_unittest.cc", "csp_validator_unittest.cc", + "error_utils_unittest.cc", "event_filter_unittest.cc", "extension_builder_unittest.cc", "extension_icon_set_unittest.cc",
diff --git a/extensions/common/error_utils.cc b/extensions/common/error_utils.cc index 5fd6d653..211c629 100644 --- a/extensions/common/error_utils.cc +++ b/extensions/common/error_utils.cc
@@ -4,36 +4,64 @@ #include "extensions/common/error_utils.h" +#include <initializer_list> + +#include "base/logging.h" +#include "base/strings/string_tokenizer.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" namespace extensions { +namespace { + +std::string FormatErrorMessageInternal( + base::StringPiece format, + std::initializer_list<base::StringPiece> args) { + std::string format_str = format.as_string(); + base::StringTokenizer tokenizer(format_str, "*"); + tokenizer.set_options(base::StringTokenizer::RETURN_DELIMS); + + std::vector<base::StringPiece> result_pieces; + auto* args_it = args.begin(); + while (tokenizer.GetNext()) { + if (!tokenizer.token_is_delim()) { + result_pieces.push_back(tokenizer.token_piece()); + continue; + } + + CHECK_NE(args_it, args.end()) + << "More placeholders (*) than substitutions."; + + // Substitute the argument. + result_pieces.push_back(*args_it); + args_it++; + } + + // Not all substitutions were consumed. + CHECK_EQ(args_it, args.end()) << "Fewer placeholders (*) than substitutions."; + + return base::JoinString(result_pieces, "" /* separator */); +} + +} // namespace + std::string ErrorUtils::FormatErrorMessage(base::StringPiece format, base::StringPiece s1) { - std::string ret_val = format.as_string(); - base::ReplaceFirstSubstringAfterOffset(&ret_val, 0, "*", s1); - return ret_val; + return FormatErrorMessageInternal(format, {s1}); } std::string ErrorUtils::FormatErrorMessage(base::StringPiece format, base::StringPiece s1, base::StringPiece s2) { - std::string ret_val = format.as_string(); - base::ReplaceFirstSubstringAfterOffset(&ret_val, 0, "*", s1); - base::ReplaceFirstSubstringAfterOffset(&ret_val, 0, "*", s2); - return ret_val; + return FormatErrorMessageInternal(format, {s1, s2}); } std::string ErrorUtils::FormatErrorMessage(base::StringPiece format, base::StringPiece s1, base::StringPiece s2, base::StringPiece s3) { - std::string ret_val = format.as_string(); - base::ReplaceFirstSubstringAfterOffset(&ret_val, 0, "*", s1); - base::ReplaceFirstSubstringAfterOffset(&ret_val, 0, "*", s2); - base::ReplaceFirstSubstringAfterOffset(&ret_val, 0, "*", s3); - return ret_val; + return FormatErrorMessageInternal(format, {s1, s2, s3}); } std::string ErrorUtils::FormatErrorMessage(base::StringPiece format, @@ -41,30 +69,25 @@ base::StringPiece s2, base::StringPiece s3, base::StringPiece s4) { - std::string ret_val = format.as_string(); - base::ReplaceFirstSubstringAfterOffset(&ret_val, 0, "*", s1); - base::ReplaceFirstSubstringAfterOffset(&ret_val, 0, "*", s2); - base::ReplaceFirstSubstringAfterOffset(&ret_val, 0, "*", s3); - base::ReplaceFirstSubstringAfterOffset(&ret_val, 0, "*", s4); - return ret_val; + return FormatErrorMessageInternal(format, {s1, s2, s3, s4}); } base::string16 ErrorUtils::FormatErrorMessageUTF16(base::StringPiece format, base::StringPiece s1) { - return base::UTF8ToUTF16(FormatErrorMessage(format, s1)); + return base::UTF8ToUTF16(FormatErrorMessageInternal(format, {s1})); } base::string16 ErrorUtils::FormatErrorMessageUTF16(base::StringPiece format, base::StringPiece s1, base::StringPiece s2) { - return base::UTF8ToUTF16(FormatErrorMessage(format, s1, s2)); + return base::UTF8ToUTF16(FormatErrorMessageInternal(format, {s1, s2})); } base::string16 ErrorUtils::FormatErrorMessageUTF16(base::StringPiece format, base::StringPiece s1, base::StringPiece s2, base::StringPiece s3) { - return base::UTF8ToUTF16(FormatErrorMessage(format, s1, s2, s3)); + return base::UTF8ToUTF16(FormatErrorMessageInternal(format, {s1, s2, s3})); } base::string16 ErrorUtils::FormatErrorMessageUTF16(base::StringPiece format, @@ -72,7 +95,8 @@ base::StringPiece s2, base::StringPiece s3, base::StringPiece s4) { - return base::UTF8ToUTF16(FormatErrorMessage(format, s1, s2, s3, s4)); + return base::UTF8ToUTF16( + FormatErrorMessageInternal(format, {s1, s2, s3, s4})); } } // namespace extensions
diff --git a/extensions/common/error_utils_unittest.cc b/extensions/common/error_utils_unittest.cc new file mode 100644 index 0000000..6cf8b22 --- /dev/null +++ b/extensions/common/error_utils_unittest.cc
@@ -0,0 +1,67 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "extensions/common/error_utils.h" + +#include "base/logging.h" +#include "base/strings/utf_string_conversions.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace extensions { +namespace { + +// Tests ErrorUtils::FormatErrorMessage which takes two placeholders. +TEST(ErrorUtils, FormatErrorMessage_Success) { + struct { + base::StringPiece format; + base::StringPiece s1; + base::StringPiece s2; + const char* expected; + } cases[] = { + {"Hello * Bye *", "arg1", "arg2", "Hello arg1 Bye arg2"}, + // Ensure substitutions respect the size of the StringPiece. + {"Hello * Bye *", base::StringPiece("12345", 2), "3", "Hello 12 Bye 3"}, + // Regression test for crbug.com/928415. + {"Hello * Bye *", "*arg1", "*arg2", "Hello *arg1 Bye *arg2"}, + }; + + for (const auto& test_case : cases) { + SCOPED_TRACE(test_case.format); + + EXPECT_EQ(test_case.expected, + ErrorUtils::FormatErrorMessage(test_case.format, test_case.s1, + test_case.s2)); + EXPECT_EQ(base::UTF8ToUTF16(test_case.expected), + ErrorUtils::FormatErrorMessageUTF16(test_case.format, + test_case.s1, test_case.s2)); + } +} + +#if defined(GTEST_HAS_DEATH_TEST) +// Tests that we raise an error if the number of placeholders and substitution +// arguments are not equal. +TEST(ErrorUtils, FormatErrorMessage_Death) { + struct { + base::StringPiece format; + base::StringPiece s1; + base::StringPiece s2; + const char* death_message_regex; + } cases[] = {{"Hello * Bye * *", "arg1", "arg2", "More placeholders"}, + {"Hello * Bye", "arg1", "arg2", "Fewer placeholders"}}; + + for (const auto& test_case : cases) { + SCOPED_TRACE(test_case.format); + + EXPECT_DEATH(ErrorUtils::FormatErrorMessage(test_case.format, test_case.s1, + test_case.s2), + test_case.death_message_regex); + EXPECT_DEATH(ErrorUtils::FormatErrorMessageUTF16( + test_case.format, test_case.s1, test_case.s2), + test_case.death_message_regex); + } +} +#endif // defined(GTEST_HAS_DEATH_TEST) + +} // namespace +} // namespace extensions
diff --git a/extensions/common/manifest_handlers/action_handlers_handler_unittest.cc b/extensions/common/manifest_handlers/action_handlers_handler_unittest.cc index 5196732..2832c7a5 100644 --- a/extensions/common/manifest_handlers/action_handlers_handler_unittest.cc +++ b/extensions/common/manifest_handlers/action_handlers_handler_unittest.cc
@@ -22,8 +22,7 @@ class ActionHandlersManifestTest : public ManifestTest { protected: ManifestData CreateManifest(const std::string& action_handlers) { - std::unique_ptr<base::Value> manifest = - base::test::ParseJson(R"json({ + base::Value manifest = base::test::ParseJson(R"json({ "name": "test", "version": "1", "app": { @@ -33,9 +32,9 @@ }, "manifest_version": 2, "action_handlers": )json" + - action_handlers + "}"); - EXPECT_TRUE(manifest); - return ManifestData(std::move(manifest), "test"); + action_handlers + "}"); + return ManifestData(base::Value::ToUniquePtrValue(std::move(manifest)), + "test"); } // Returns all action handlers associated with |extension|.
diff --git a/extensions/common/manifest_handlers/file_handler_info.cc b/extensions/common/manifest_handlers/file_handler_info.cc index 848d17b..da5c5a1 100644 --- a/extensions/common/manifest_handlers/file_handler_info.cc +++ b/extensions/common/manifest_handlers/file_handler_info.cc
@@ -98,8 +98,7 @@ if (include_directories->is_bool()) { handler.include_directories = include_directories->GetBool(); } else { - *error = ErrorUtils::FormatErrorMessageUTF16( - errors::kInvalidFileHandlerIncludeDirectories, handler_id); + *error = base::UTF8ToUTF16(errors::kInvalidFileHandlerIncludeDirectories); return false; } }
diff --git a/extensions/common/manifest_handlers/icons_handler_unittest.cc b/extensions/common/manifest_handlers/icons_handler_unittest.cc index 494bb99..8ea883a 100644 --- a/extensions/common/manifest_handlers/icons_handler_unittest.cc +++ b/extensions/common/manifest_handlers/icons_handler_unittest.cc
@@ -15,7 +15,7 @@ protected: std::unique_ptr<base::Value> CreateManifest(const std::string& extra_icons) { - std::unique_ptr<base::Value> manifest = base::test::ParseJson( + std::unique_ptr<base::Value> manifest = base::test::ParseJsonDeprecated( "{ \n" " \"name\": \"test\", \n" " \"version\": \"0.1\", \n"
diff --git a/extensions/common/manifest_handlers/oauth2_manifest_unittest.cc b/extensions/common/manifest_handlers/oauth2_manifest_unittest.cc index 1034171..81f9d42 100644 --- a/extensions/common/manifest_handlers/oauth2_manifest_unittest.cc +++ b/extensions/common/manifest_handlers/oauth2_manifest_unittest.cc
@@ -49,7 +49,7 @@ std::unique_ptr<base::Value> CreateManifest(AutoApproveValue auto_approve, bool extension_id_whitelisted, ClientIdValue client_id) { - std::unique_ptr<base::Value> manifest = base::test::ParseJson( + std::unique_ptr<base::Value> manifest = base::test::ParseJsonDeprecated( "{ \n" " \"name\": \"test\", \n" " \"version\": \"0.1\", \n"
diff --git a/extensions/common/manifest_handlers/permissions_parser.cc b/extensions/common/manifest_handlers/permissions_parser.cc index 1d9a0aea..0c1d632 100644 --- a/extensions/common/manifest_handlers/permissions_parser.cc +++ b/extensions/common/manifest_handlers/permissions_parser.cc
@@ -94,8 +94,7 @@ const base::Value* permissions = nullptr; if (!extension->manifest()->GetList(key, &permissions)) { - *error = ErrorUtils::FormatErrorMessageUTF16(errors::kInvalidPermissions, - std::string()); + *error = base::UTF8ToUTF16(errors::kInvalidPermissions); return false; }
diff --git a/gpu/command_buffer/client/image_decode_accelerator_interface.h b/gpu/command_buffer/client/image_decode_accelerator_interface.h index 5e1aa72..d56c6b6c 100644 --- a/gpu/command_buffer/client/image_decode_accelerator_interface.h +++ b/gpu/command_buffer/client/image_decode_accelerator_interface.h
@@ -24,6 +24,9 @@ public: virtual ~ImageDecodeAcceleratorInterface() {} + virtual bool IsImageSupported( + base::span<const uint8_t> encoded_data) const = 0; + virtual SyncToken ScheduleImageDecode( base::span<const uint8_t> encoded_data, const gfx::Size& output_size,
diff --git a/gpu/command_buffer/client/raster_implementation.cc b/gpu/command_buffer/client/raster_implementation.cc index b7c4039..bae4d80 100644 --- a/gpu/command_buffer/client/raster_implementation.cc +++ b/gpu/command_buffer/client/raster_implementation.cc
@@ -1146,6 +1146,11 @@ FlushPaintCachePurgedEntries(); } +bool RasterImplementation::CanDecodeWithHardwareAcceleration( + base::span<const uint8_t> encoded_data) { + return image_decode_accelerator_->IsImageSupported(encoded_data); +} + SyncToken RasterImplementation::ScheduleImageDecode( base::span<const uint8_t> encoded_data, const gfx::Size& output_size,
diff --git a/gpu/command_buffer/client/raster_implementation.h b/gpu/command_buffer/client/raster_implementation.h index c4e01fd..22a403a 100644 --- a/gpu/command_buffer/client/raster_implementation.h +++ b/gpu/command_buffer/client/raster_implementation.h
@@ -134,6 +134,8 @@ const gfx::Vector2dF& post_translate, GLfloat post_scale, bool requires_clear) override; + bool CanDecodeWithHardwareAcceleration( + base::span<const uint8_t> encoded_data) override; SyncToken ScheduleImageDecode(base::span<const uint8_t> encoded_data, const gfx::Size& output_size, uint32_t transfer_cache_entry_id,
diff --git a/gpu/command_buffer/client/raster_implementation_gles.cc b/gpu/command_buffer/client/raster_implementation_gles.cc index 4fd888e1..293d0bb 100644 --- a/gpu/command_buffer/client/raster_implementation_gles.cc +++ b/gpu/command_buffer/client/raster_implementation_gles.cc
@@ -153,6 +153,12 @@ NOTREACHED(); } +bool RasterImplementationGLES::CanDecodeWithHardwareAcceleration( + base::span<const uint8_t> encoded_data) { + NOTREACHED(); + return false; +} + SyncToken RasterImplementationGLES::ScheduleImageDecode( base::span<const uint8_t> encoded_data, const gfx::Size& output_size,
diff --git a/gpu/command_buffer/client/raster_implementation_gles.h b/gpu/command_buffer/client/raster_implementation_gles.h index 2de8b7f..9d8e39f 100644 --- a/gpu/command_buffer/client/raster_implementation_gles.h +++ b/gpu/command_buffer/client/raster_implementation_gles.h
@@ -78,6 +78,8 @@ void EndRasterCHROMIUM() override; // Image decode acceleration. + bool CanDecodeWithHardwareAcceleration( + base::span<const uint8_t> encoded_data) override; SyncToken ScheduleImageDecode(base::span<const uint8_t> encoded_data, const gfx::Size& output_size, uint32_t transfer_cache_entry_id,
diff --git a/gpu/command_buffer/client/raster_interface.h b/gpu/command_buffer/client/raster_interface.h index 7373ad4..e88f36dc 100644 --- a/gpu/command_buffer/client/raster_interface.h +++ b/gpu/command_buffer/client/raster_interface.h
@@ -66,6 +66,12 @@ GLfloat post_scale, bool requires_clear) = 0; + // Determines if an encoded image can be decoded using hardware decode + // acceleration. If this method returns true, then the client can be confident + // that a call to ScheduleImageDecode() will succeed. + virtual bool CanDecodeWithHardwareAcceleration( + base::span<const uint8_t> encoded_data) = 0; + // Schedules a hardware-accelerated image decode and a sync token that's // released when the image decode is complete. If the decode could not be // scheduled, an empty sync token is returned.
diff --git a/gpu/dawn_end2end_tests_main.cc b/gpu/dawn_end2end_tests_main.cc index 1188ccb..d6a85ab 100644 --- a/gpu/dawn_end2end_tests_main.cc +++ b/gpu/dawn_end2end_tests_main.cc
@@ -19,10 +19,15 @@ } // namespace +// Definition located in third_party/dawn/src/tests/DawnTest.h +// Forward declared here to avoid pulling in the Dawn headers. +void InitDawnEnd2EndTestEnvironment(int argc, char** argv); + int main(int argc, char** argv) { base::CommandLine::Init(argc, argv); testing::InitGoogleMock(&argc, argv); base::TestSuite test_suite(argc, argv); + InitDawnEnd2EndTestEnvironment(argc, argv); int rt = base::LaunchUnitTestsWithOptions( argc, argv, 1, // Run tests serially.
diff --git a/gpu/ipc/client/BUILD.gn b/gpu/ipc/client/BUILD.gn index acab7a514..5a9ee4b7 100644 --- a/gpu/ipc/client/BUILD.gn +++ b/gpu/ipc/client/BUILD.gn
@@ -37,6 +37,7 @@ "//gpu/command_buffer/common:common_sources", "//gpu/config:config_sources", "//gpu/ipc/common:ipc_common_sources", + "//media/filters:jpeg_parser", "//mojo/public/cpp/system", "//ui/gfx:color_space", "//ui/gfx/geometry",
diff --git a/gpu/ipc/client/DEPS b/gpu/ipc/client/DEPS index 1caa6b1..3333b39 100644 --- a/gpu/ipc/client/DEPS +++ b/gpu/ipc/client/DEPS
@@ -10,6 +10,9 @@ "gpu_in_process_context_tests.cc": [ "+components/viz/test/test_gpu_memory_buffer_manager.h", ], + "image_decode_accelerator_proxy.cc": [ + "+media/filters/jpeg_parser.h", + ], "raster_in_process_context_tests.cc": [ "+cc/paint/color_space_transfer_cache_entry.h", "+components/viz/common/resources/resource_format.h",
diff --git a/gpu/ipc/client/image_decode_accelerator_proxy.cc b/gpu/ipc/client/image_decode_accelerator_proxy.cc index 4691684..d992ee9 100644 --- a/gpu/ipc/client/image_decode_accelerator_proxy.cc +++ b/gpu/ipc/client/image_decode_accelerator_proxy.cc
@@ -4,24 +4,160 @@ #include "gpu/ipc/client/image_decode_accelerator_proxy.h" +#include <string.h> + +#include <algorithm> #include <utility> #include <vector> +#include "base/logging.h" +#include "base/numerics/safe_conversions.h" #include "gpu/command_buffer/common/constants.h" +#include "gpu/config/gpu_info.h" #include "gpu/ipc/client/gpu_channel_host.h" #include "gpu/ipc/common/command_buffer_id.h" #include "gpu/ipc/common/gpu_messages.h" +#include "media/filters/jpeg_parser.h" #include "ui/gfx/color_space.h" #include "ui/gfx/geometry/size.h" namespace gpu { +namespace { + +bool IsJpegImage(base::span<const uint8_t> encoded_data) { + if (encoded_data.size() < 3u) + return false; + return memcmp("\xFF\xD8\xFF", encoded_data.data(), 3u) == 0; +} + +ImageDecodeAcceleratorType GetImageType( + base::span<const uint8_t> encoded_data) { + static_assert(static_cast<int>(ImageDecodeAcceleratorType::kMaxValue) == 1, + "GetImageType() must be adapted to support all image types in " + "ImageDecodeAcceleratorType"); + + // Currently, only JPEG images are supported. + if (IsJpegImage(encoded_data)) + return ImageDecodeAcceleratorType::kJpeg; + + return ImageDecodeAcceleratorType::kUnknown; +} + +bool GetJpegSubsampling(const media::JpegParseResult& parse_result, + ImageDecodeAcceleratorSubsampling* subsampling) { + static_assert( + static_cast<int>(ImageDecodeAcceleratorSubsampling::kMaxValue) == 1, + "GetJpegSubsampling() must be adapted to support all " + "subsampling factors in ImageDecodeAcceleratorSubsampling"); + + // Currently, only 3 components are supported (this excludes, for example, + // grayscale and CMYK JPEGs). + if (parse_result.frame_header.num_components != 3u) + return false; + + const uint8_t comp0_h = + parse_result.frame_header.components[0].horizontal_sampling_factor; + const uint8_t comp0_v = + parse_result.frame_header.components[0].vertical_sampling_factor; + const uint8_t comp1_h = + parse_result.frame_header.components[1].horizontal_sampling_factor; + const uint8_t comp1_v = + parse_result.frame_header.components[1].vertical_sampling_factor; + const uint8_t comp2_h = + parse_result.frame_header.components[2].horizontal_sampling_factor; + const uint8_t comp2_v = + parse_result.frame_header.components[2].vertical_sampling_factor; + + if (comp0_h == 2u && (comp1_h == 1u && comp1_v == 1u) && + (comp2_h == 1u && comp2_v == 1u)) { + if (comp0_v == 2u) { + *subsampling = ImageDecodeAcceleratorSubsampling::k420; + return true; + } else if (comp0_v == 1u) { + *subsampling = ImageDecodeAcceleratorSubsampling::k422; + return true; + } + } + + return false; +} + +bool IsSupportedJpegImage( + base::span<const uint8_t> encoded_data, + const ImageDecodeAcceleratorSupportedProfile& supported_profile) { + DCHECK(IsJpegImage(encoded_data)); + DCHECK_EQ(ImageDecodeAcceleratorType::kJpeg, supported_profile.image_type); + + // First, parse the JPEG file. This fails for progressive JPEGs (which we + // don't support anyway). + media::JpegParseResult parse_result; + if (!media::ParseJpegPicture(encoded_data.data(), encoded_data.size(), + &parse_result)) { + return false; + } + + // Now, check the chroma subsampling format. + ImageDecodeAcceleratorSubsampling subsampling; + if (!GetJpegSubsampling(parse_result, &subsampling)) + return false; + if (std::find(supported_profile.subsamplings.cbegin(), + supported_profile.subsamplings.cend(), + subsampling) == supported_profile.subsamplings.cend()) { + return false; + } + + // Now, check the dimensions. + const int encoded_width = + base::strict_cast<int>(parse_result.frame_header.coded_width); + const int encoded_height = + base::strict_cast<int>(parse_result.frame_header.coded_height); + if (encoded_width < supported_profile.min_encoded_dimensions.width() || + encoded_height < supported_profile.min_encoded_dimensions.height() || + encoded_width > supported_profile.max_encoded_dimensions.width() || + encoded_height > supported_profile.max_encoded_dimensions.height()) { + return false; + } + + return true; +} + +} // namespace + ImageDecodeAcceleratorProxy::ImageDecodeAcceleratorProxy(GpuChannelHost* host, int32_t route_id) : host_(host), route_id_(route_id) {} ImageDecodeAcceleratorProxy::~ImageDecodeAcceleratorProxy() {} +bool ImageDecodeAcceleratorProxy::IsImageSupported( + base::span<const uint8_t> encoded_data) const { + DCHECK(host_); + + const ImageDecodeAcceleratorType image_type = GetImageType(encoded_data); + if (image_type == ImageDecodeAcceleratorType::kUnknown) + return false; + + // Find the image decode accelerator supported profile according to the type + // of the image. + const std::vector<ImageDecodeAcceleratorSupportedProfile>& profiles = + host_->gpu_info().image_decode_accelerator_supported_profiles; + auto profile_it = std::find_if( + profiles.cbegin(), profiles.cend(), + [image_type](const ImageDecodeAcceleratorSupportedProfile& profile) { + return profile.image_type == image_type; + }); + if (profile_it == profiles.cend()) + return false; + + // Validate the image according to that profile. + if (image_type == ImageDecodeAcceleratorType::kJpeg) + return IsSupportedJpegImage(encoded_data, *profile_it); + + NOTREACHED(); + return false; +} + SyncToken ImageDecodeAcceleratorProxy::ScheduleImageDecode( base::span<const uint8_t> encoded_data, const gfx::Size& output_size, @@ -35,6 +171,7 @@ DCHECK(host_); DCHECK_EQ(host_->channel_id(), ChannelIdFromCommandBufferId(raster_decoder_command_buffer_id)); + DCHECK(IsImageSupported(encoded_data)); GpuChannelMsg_ScheduleImageDecode_Params params; params.encoded_data =
diff --git a/gpu/ipc/client/image_decode_accelerator_proxy.h b/gpu/ipc/client/image_decode_accelerator_proxy.h index 5ad7bec..b40a3fe 100644 --- a/gpu/ipc/client/image_decode_accelerator_proxy.h +++ b/gpu/ipc/client/image_decode_accelerator_proxy.h
@@ -50,6 +50,12 @@ ImageDecodeAcceleratorProxy(GpuChannelHost* host, int32_t route_id); ~ImageDecodeAcceleratorProxy() override; + // Determines if an encoded image is supported by the hardware accelerator. + // The ScheduleImageDecode() method should only be called for images for which + // IsImageSupported() returns true. Otherwise, the client faces a GPU channel + // teardown if the decode fails. + bool IsImageSupported(base::span<const uint8_t> encoded_data) const override; + // Schedules a hardware-accelerated image decode on the GPU process. The image // in |encoded_data| is decoded and scaled to |output_size|. Upon completion // and after the sync token corresponding to
diff --git a/ios/chrome/browser/ui/settings/google_services/google_services_settings_view_controller.mm b/ios/chrome/browser/ui/settings/google_services/google_services_settings_view_controller.mm index ff4f843..c62ba9d 100644 --- a/ios/chrome/browser/ui/settings/google_services/google_services_settings_view_controller.mm +++ b/ios/chrome/browser/ui/settings/google_services/google_services_settings_view_controller.mm
@@ -122,6 +122,7 @@ [super tableView:tableView didSelectRowAtIndexPath:indexPath]; TableViewItem* item = [self.tableViewModel itemAtIndexPath:indexPath]; [self.serviceDelegate didSelectItem:item]; + [tableView deselectRowAtIndexPath:indexPath animated:YES]; } @end
diff --git a/ios/chrome/browser/ui/settings/password/passwords_settings_egtest.mm b/ios/chrome/browser/ui/settings/password/passwords_settings_egtest.mm index a3169a4..ba0c0bd 100644 --- a/ios/chrome/browser/ui/settings/password/passwords_settings_egtest.mm +++ b/ios/chrome/browser/ui/settings/password/passwords_settings_egtest.mm
@@ -1581,8 +1581,8 @@ UIAccessibilityTraitNotEnabled))]; } -// Test that user can type text in search field and that it filters out the -// passwords and blacklisted items. +// Test that when user types text in search field, passwords and blacklisted +// items are filtered out and "save passwords" switch is removed. - (void)testSearchPasswords { SaveExamplePasswordForms(); SaveExampleBlacklistedForms(); @@ -1598,12 +1598,14 @@ [GetInteractionForPasswordEntry(@"exclude2.com") assertWithMatcher:grey_notNil()]; - [[EarlGrey - selectElementWithMatcher:grey_accessibilityID(kPasswordsTableViewId)] - performAction:grey_scrollToContentEdge(kGREYContentEdgeTop)]; [[EarlGrey selectElementWithMatcher:SearchTextField()] performAction:grey_typeText(@"2")]; + // Check that the "Save Passwords" switch is hidden. + [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell( + @"savePasswordsItem_switch", YES)] + assertWithMatcher:grey_nil()]; + [GetInteractionForPasswordEntry(@"example11.com, user1") assertWithMatcher:grey_nil()]; [GetInteractionForPasswordEntry(@"example12.com, user2")
diff --git a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm index 2356a19e..8c53971 100644 --- a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm
@@ -159,6 +159,8 @@ // The observable boolean that binds to the password manager setting state. // Saved passwords are only on if the password manager is enabled. PrefBackedBoolean* passwordManagerEnabled_; + // The header for save passwords switch section. + TableViewLinkHeaderFooterItem* manageAccountLinkItem_; // The item related to the switch for the password manager setting. SettingsSwitchItem* savePasswordsItem_; // The item related to the button for exporting passwords. @@ -207,6 +209,9 @@ // The scrim view that covers the table view when search bar is focused with // empty search term. Tapping on the scrim view will dismiss the search bar. @property(nonatomic, strong) UIControl* scrimView; +// Example headers for calculating headers' heights. +@property(nonatomic, strong) + NSMutableDictionary<Class, UITableViewHeaderFooterView*>* exampleHeaders; @end @@ -228,6 +233,7 @@ _passwordExporter = [[PasswordExporter alloc] initWithReauthenticationModule:reauthenticationModule_ delegate:self]; + self.exampleHeaders = [[NSMutableDictionary alloc] init]; self.title = l10n_util::GetNSString(IDS_IOS_PASSWORDS); self.shouldHideDoneButton = YES; self.searchTerm = @""; @@ -341,9 +347,8 @@ savePasswordsItem_ = [self savePasswordsItem]; [model addItem:savePasswordsItem_ toSectionWithIdentifier:SectionIdentifierSavePasswordsSwitch]; - TableViewLinkHeaderFooterItem* manageAccountLinkItem = - [self manageAccountLinkItem]; - [model setHeader:manageAccountLinkItem + manageAccountLinkItem_ = [self manageAccountLinkItem]; + [model setHeader:manageAccountLinkItem_ forSectionWithIdentifier:SectionIdentifierSavePasswordsSwitch]; // Saved passwords. @@ -500,15 +505,79 @@ [self reloadData]; } +#pragma mark - UITableViewDelegate + +// Uses a group of example headers to calculate the heights. Returning +// UITableViewAutomaticDimension here will cause UITableView to cache the +// heights and reuse them when sections are inserted or removed, which will +// break the UI. For example: +// 1. UITableView is inited with 4 headers; +// 2. "tableView:heightForHeaderInSection" is called and +// UITableViewAutomaticDimension is returned; +// 3. UITableView calculates headers' heights and get [10, 20, 10, 20]; +// 4. UITableView caches these heights; +// 5. The first header is removed from UITableView; +// 6. "tableView:heightForHeaderInSection" is called and +// UITableViewAutomaticDimension is returned; +// 7. UITableView decides to use cached results as [10, 20, 10], while +// expected heights are [20, 10, 20]. +- (CGFloat)tableView:(UITableView*)tableView + heightForHeaderInSection:(NSInteger)section { + if ([self.tableViewModel headerForSection:section]) { + TableViewHeaderFooterItem* item = + [self.tableViewModel headerForSection:section]; + Class headerClass = item.cellClass; + if (!self.exampleHeaders[headerClass]) { + UITableViewHeaderFooterView* view = + [[headerClass alloc] initWithReuseIdentifier:@""]; + [item configureHeaderFooterView:view withStyler:self.styler]; + [self.exampleHeaders setObject:view forKey:headerClass]; + } + UITableViewHeaderFooterView* view = self.exampleHeaders[headerClass]; + CGSize size = + [view systemLayoutSizeFittingSize:self.tableView.safeAreaLayoutGuide + .layoutFrame.size + withHorizontalFittingPriority:UILayoutPriorityRequired + verticalFittingPriority:1]; + return size.height; + } + return [super tableView:tableView heightForHeaderInSection:section]; +} + #pragma mark - UISearchControllerDelegate - (void)willPresentSearchController:(UISearchController*)searchController { [self showScrim]; + // Remove save passwords switch section. + [self + performBatchTableViewUpdates:^{ + [self clearSectionWithIdentifier:SectionIdentifierSavePasswordsSwitch + withRowAnimation:UITableViewRowAnimationTop]; + } + completion:nil]; } - (void)willDismissSearchController:(UISearchController*)searchController { [self hideScrim]; [self searchForTerm:@""]; + // Recover save passwords switch section. + TableViewModel* model = self.tableViewModel; + [self.tableView + performBatchUpdates:^{ + [model insertSectionWithIdentifier:SectionIdentifierSavePasswordsSwitch + atIndex:0]; + [model setHeader:manageAccountLinkItem_ + forSectionWithIdentifier:SectionIdentifierSavePasswordsSwitch]; + [self.tableView insertSections:[NSIndexSet indexSetWithIndex:0] + withRowAnimation:UITableViewRowAnimationTop]; + [model addItem:savePasswordsItem_ + toSectionWithIdentifier:SectionIdentifierSavePasswordsSwitch]; + [self.tableView + insertRowsAtIndexPaths:@[ [NSIndexPath indexPathForRow:0 + inSection:0] ] + withRowAnimation:UITableViewRowAnimationTop]; + } + completion:nil]; } #pragma mark - UISearchBarDelegate @@ -708,13 +777,13 @@ // Removes the given section if it exists and if isEmpty is true. - (void)clearSectionWithIdentifier:(NSInteger)sectionIdentifier - ifEmpty:(bool)isEmpty { + withRowAnimation:(UITableViewRowAnimation)animation { TableViewModel* model = self.tableViewModel; - if (isEmpty && [model hasSectionForSectionIdentifier:sectionIdentifier]) { + if ([model hasSectionForSectionIdentifier:sectionIdentifier]) { NSInteger section = [model sectionForSectionIdentifier:sectionIdentifier]; [model removeSectionWithIdentifier:sectionIdentifier]; [[self tableView] deleteSections:[NSIndexSet indexSetWithIndex:section] - withRowAnimation:UITableViewRowAnimationAutomatic]; + withRowAnimation:animation]; } } @@ -795,11 +864,15 @@ // Delete in reverse order of section indexes (bottom up of section // displayed), so that indexes in model matches those in the view. if // we don't we'll cause a crash. - [strongSelf - clearSectionWithIdentifier:SectionIdentifierBlacklist - ifEmpty:strongSelf->blacklistedForms_.empty()]; - [strongSelf clearSectionWithIdentifier:SectionIdentifierSavedPasswords - ifEmpty:strongSelf->savedForms_.empty()]; + if (strongSelf->blacklistedForms_.empty()) { + [self clearSectionWithIdentifier:SectionIdentifierBlacklist + withRowAnimation:UITableViewRowAnimationAutomatic]; + } + if (strongSelf->savedForms_.empty()) { + [strongSelf + clearSectionWithIdentifier:SectionIdentifierSavedPasswords + withRowAnimation:UITableViewRowAnimationAutomatic]; + } } completion:^(BOOL finished) { PasswordsTableViewController* strongSelf = weakSelf;
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_text_header_footer_item.mm b/ios/chrome/browser/ui/table_view/cells/table_view_text_header_footer_item.mm index 6ea5ce0..007e5d7 100644 --- a/ios/chrome/browser/ui/table_view/cells/table_view_text_header_footer_item.mm +++ b/ios/chrome/browser/ui/table_view/cells/table_view_text_header_footer_item.mm
@@ -91,12 +91,12 @@ // beyond the margins. heightConstraint.priority = UILayoutPriorityDefaultHigh + 1; NSLayoutConstraint* topAnchorConstraint = [containerView.topAnchor - constraintGreaterThanOrEqualToAnchor:self.contentView.topAnchor - constant:kTableViewVerticalSpacing]; + constraintEqualToAnchor:self.contentView.topAnchor + constant:kTableViewVerticalSpacing]; topAnchorConstraint.priority = UILayoutPriorityDefaultHigh; NSLayoutConstraint* bottomAnchorConstraint = [containerView.bottomAnchor - constraintLessThanOrEqualToAnchor:self.contentView.bottomAnchor - constant:-kTableViewVerticalSpacing]; + constraintEqualToAnchor:self.contentView.bottomAnchor + constant:-kTableViewVerticalSpacing]; bottomAnchorConstraint.priority = UILayoutPriorityDefaultHigh; NSLayoutConstraint* leadingAnchorConstraint = [containerView.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor
diff --git a/ios/web/public/test/web_test_with_web_state.mm b/ios/web/public/test/web_test_with_web_state.mm index 78ea327..bf5b24c 100644 --- a/ios/web/public/test/web_test_with_web_state.mm +++ b/ios/web/public/test/web_test_with_web_state.mm
@@ -128,32 +128,6 @@ } void WebTestWithWebState::LoadHtml(NSString* html, const GURL& url) { - // Sets MIME type to "text/html" once navigation is committed. - class MimeTypeUpdater : public WebStateObserver { - public: - MimeTypeUpdater() = default; - - // WebStateObserver overrides: - void DidFinishNavigation(WebState* web_state, - NavigationContext* context) override { - // loadHTML:forURL: does not notify web view delegate about received - // response, so web controller does not get a chance to properly update - // MIME type and it should be set manually after navigation is committed - // but before WebState signal load completion and clients will start - // checking if MIME type is in fact HTML. - static_cast<WebStateImpl*>(web_state)->SetContentsMimeType("text/html"); - } - void WebStateDestroyed(WebState* web_state) override { NOTREACHED(); } - - private: - DISALLOW_COPY_AND_ASSIGN(MimeTypeUpdater); - }; - - MimeTypeUpdater mime_type_updater; - ScopedObserver<WebState, WebStateObserver> scoped_observer( - &mime_type_updater); - scoped_observer.Add(web_state()); - // Initiate asynchronous HTML load. CRWWebController* web_controller = GetWebController(web_state()); ASSERT_EQ(PAGE_LOADED, web_controller.loadPhase);
diff --git a/ios/web/web_state/navigation_context_impl.h b/ios/web/web_state/navigation_context_impl.h index b5c760b..ca98a33 100644 --- a/ios/web/web_state/navigation_context_impl.h +++ b/ios/web/web_state/navigation_context_impl.h
@@ -88,6 +88,10 @@ bool IsPlaceholderNavigation() const; void SetPlaceholderNavigation(bool flag); + // MIMEType of the navigation. + void SetMimeType(NSString* mime_type); + NSString* GetMimeType() const; + private: NavigationContextImpl(WebState* web_state, const GURL& url, @@ -104,7 +108,7 @@ bool has_committed_ = false; bool is_download_ = false; bool is_post_ = false; - NSError* error_; + NSError* error_ = nil; scoped_refptr<net::HttpResponseHeaders> response_headers_; bool is_renderer_initiated_ = false; int navigation_item_unique_id_ = -1; @@ -113,6 +117,7 @@ bool is_loading_html_string_ = false; bool is_native_content_presented_ = false; bool is_placeholder_navigation_ = false; + NSString* mime_type_ = nil; DISALLOW_COPY_AND_ASSIGN(NavigationContextImpl); };
diff --git a/ios/web/web_state/navigation_context_impl.mm b/ios/web/web_state/navigation_context_impl.mm index fbc28ef..9981c6726 100644 --- a/ios/web/web_state/navigation_context_impl.mm +++ b/ios/web/web_state/navigation_context_impl.mm
@@ -179,6 +179,14 @@ is_placeholder_navigation_ = flag; } +void NavigationContextImpl::SetMimeType(NSString* mime_type) { + mime_type_ = mime_type; +} + +NSString* NavigationContextImpl::GetMimeType() const { + return mime_type_; +} + NavigationContextImpl::NavigationContextImpl(WebState* web_state, const GURL& url, bool has_user_gesture,
diff --git a/ios/web/web_state/navigation_context_impl_unittest.mm b/ios/web/web_state/navigation_context_impl_unittest.mm index ad4be8f..6f177658 100644 --- a/ios/web/web_state/navigation_context_impl_unittest.mm +++ b/ios/web/web_state/navigation_context_impl_unittest.mm
@@ -7,6 +7,7 @@ #import "ios/web/public/test/fakes/test_web_state.h" #include "net/http/http_response_headers.h" #include "testing/gtest/include/gtest/gtest.h" +#import "testing/gtest_mac.h" #include "testing/platform_test.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -93,6 +94,7 @@ ASSERT_FALSE(context->IsRendererInitiated()); ASSERT_NE(response_headers_.get(), context->GetResponseHeaders()); EXPECT_EQ(WKNavigationTypeOther, context->GetWKNavigationType()); + EXPECT_FALSE(context->GetMimeType()); // SetUrl GURL new_url("https://new.test"); @@ -107,6 +109,7 @@ EXPECT_NE(response_headers_.get(), context->GetResponseHeaders()); EXPECT_EQ(WKNavigationTypeOther, context->GetWKNavigationType()); EXPECT_EQ(WKNavigationTypeOther, context->GetWKNavigationType()); + EXPECT_FALSE(context->GetMimeType()); // SetSameDocument context->SetIsSameDocument(true); @@ -120,6 +123,7 @@ EXPECT_NE(response_headers_.get(), context->GetResponseHeaders()); EXPECT_EQ(WKNavigationTypeOther, context->GetWKNavigationType()); EXPECT_EQ(WKNavigationTypeOther, context->GetWKNavigationType()); + EXPECT_FALSE(context->GetMimeType()); // SetHasCommitted context->SetHasCommitted(true); @@ -133,6 +137,7 @@ EXPECT_NE(response_headers_.get(), context->GetResponseHeaders()); EXPECT_EQ(WKNavigationTypeOther, context->GetWKNavigationType()); EXPECT_EQ(WKNavigationTypeOther, context->GetWKNavigationType()); + EXPECT_FALSE(context->GetMimeType()); // SetIsDownload context->SetIsDownload(true); @@ -146,6 +151,7 @@ EXPECT_NE(response_headers_.get(), context->GetResponseHeaders()); EXPECT_EQ(WKNavigationTypeOther, context->GetWKNavigationType()); EXPECT_EQ(WKNavigationTypeOther, context->GetWKNavigationType()); + EXPECT_FALSE(context->GetMimeType()); // SetPost context->SetIsPost(true); @@ -158,6 +164,7 @@ EXPECT_FALSE(context->IsRendererInitiated()); EXPECT_NE(response_headers_.get(), context->GetResponseHeaders()); EXPECT_EQ(WKNavigationTypeOther, context->GetWKNavigationType()); + EXPECT_FALSE(context->GetMimeType()); // SetErrorPage NSError* error = [[NSError alloc] initWithDomain:@"" code:0 userInfo:nil]; @@ -171,6 +178,7 @@ EXPECT_FALSE(context->IsRendererInitiated()); EXPECT_NE(response_headers_.get(), context->GetResponseHeaders()); EXPECT_EQ(WKNavigationTypeOther, context->GetWKNavigationType()); + EXPECT_FALSE(context->GetMimeType()); // SetResponseHeaders context->SetResponseHeaders(response_headers_); @@ -183,6 +191,7 @@ EXPECT_FALSE(context->IsRendererInitiated()); EXPECT_EQ(response_headers_.get(), context->GetResponseHeaders()); EXPECT_EQ(WKNavigationTypeOther, context->GetWKNavigationType()); + EXPECT_FALSE(context->GetMimeType()); // SetWKNavigationType context->SetWKNavigationType(WKNavigationTypeBackForward); @@ -195,6 +204,19 @@ EXPECT_FALSE(context->IsRendererInitiated()); EXPECT_EQ(response_headers_.get(), context->GetResponseHeaders()); EXPECT_EQ(WKNavigationTypeBackForward, context->GetWKNavigationType()); + EXPECT_FALSE(context->GetMimeType()); + + context->SetMimeType(@"test/mime"); + EXPECT_EQ(new_url, context->GetUrl()); + EXPECT_TRUE(context->IsSameDocument()); + EXPECT_TRUE(context->HasCommitted()); + EXPECT_TRUE(context->IsDownload()); + ASSERT_TRUE(context->IsPost()); + EXPECT_EQ(error, context->GetError()); + EXPECT_FALSE(context->IsRendererInitiated()); + EXPECT_EQ(response_headers_.get(), context->GetResponseHeaders()); + EXPECT_EQ(WKNavigationTypeBackForward, context->GetWKNavigationType()); + EXPECT_NSEQ(@"test/mime", context->GetMimeType()); } } // namespace web
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index 7d0d593..2d5c77f 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -1550,6 +1550,7 @@ // Note: it is possible that the URL in item already match |url|. But item can // also contain a placeholder URL intended to be replaced. item->SetURL(URL); + navigationContext->SetMimeType(MIMEType); if (item->GetUserAgentType() == web::UserAgentType::NONE && web::wk_navigation_util::URLNeedsUserAgentType(URL)) { item->SetUserAgentType(web::UserAgentType::MOBILE); @@ -1712,10 +1713,6 @@ if ([_pendingNavigationInfo referrer]) { _currentReferrerString = [[_pendingNavigationInfo referrer] copy]; } - if ([_pendingNavigationInfo MIMEType]) { - self.webStateImpl->SetContentsMimeType( - base::SysNSStringToUTF8([_pendingNavigationInfo MIMEType])); - } [self updateCurrentBackForwardListItemHolder]; _pendingNavigationInfo = nil; @@ -4263,6 +4260,7 @@ placeholderNavigation:NO]; } context->SetLoadingHtmlString(true); + context->SetMimeType(@"text/html"); [_navigationStates setContext:std::move(context) forNavigation:navigation]; } @@ -4729,6 +4727,12 @@ _webStateImpl->OnHttpResponseHeadersReceived(headers.get(), responseURL); } + if (WKResponse.forMainFrame) { + web::NavigationContextImpl* context = + [self contextForPendingMainFrameNavigationWithURL:responseURL]; + context->SetMimeType(WKResponse.response.MIMEType); + } + // The page will not be changed until this navigation is committed, so the // retrieved state will be pending until |didCommitNavigation| callback. [self updatePendingNavigationInfoFromNavigationResponse:WKResponse]; @@ -5031,27 +5035,12 @@ context->SetHasCommitted(true); } context->SetResponseHeaders(_webStateImpl->GetHttpResponseHeaders()); + self.webStateImpl->SetContentsMimeType( + base::SysNSStringToUTF8(context->GetMimeType())); } [self commitPendingNavigationInfo]; - // TODO(crbug.com/925304): Pending item (which is stores - // currentBackForwardListItemHolder) should be owned by NavigationContext. - // Pending item should never be null. - if (self.currentNavItem) { - if ([self currentBackForwardListItemHolder] - -> navigation_type() == WKNavigationTypeBackForward) { - // A fast back/forward won't call decidePolicyForNavigationResponse, so - // the MIME type needs to be updated explicitly. - NSString* storedMIMEType = - [self currentBackForwardListItemHolder] -> mime_type(); - if (storedMIMEType) { - self.webStateImpl->SetContentsMimeType( - base::SysNSStringToUTF8(storedMIMEType)); - } - } - } - [self removeAllWebFrames]; // This point should closely approximate the document object change, so reset @@ -5207,6 +5196,10 @@ context->SetIsPost((holder && [holder->http_method() isEqual:@"POST"]) || item->HasPostData()); + if (holder) { + context->SetMimeType(holder->mime_type()); + } + [_navigationStates setContext:std::move(context) forNavigation:navigation]; [_navigationStates setState:web::WKNavigationState::REQUESTED forNavigation:navigation]; @@ -6053,6 +6046,7 @@ // |didCommitNavigation:| may not be called for fast navigation, so update // the navigation type now as it is already known. navigationContext->SetWKNavigationType(WKNavigationTypeBackForward); + navigationContext->SetMimeType(holder->mime_type()); holder->set_navigation_type(WKNavigationTypeBackForward); navigation = [_webView goToBackForwardListItem:holder->back_forward_list_item()];
diff --git a/ios/web/web_state/web_state_observer_inttest.mm b/ios/web/web_state/web_state_observer_inttest.mm index 6d6265d..2f25fb1 100644 --- a/ios/web/web_state/web_state_observer_inttest.mm +++ b/ios/web/web_state/web_state_observer_inttest.mm
@@ -277,7 +277,8 @@ EXPECT_FALSE((*context)->GetError()); EXPECT_FALSE((*context)->IsRendererInitiated()); EXPECT_FALSE((*context)->GetResponseHeaders()); - EXPECT_FALSE(web_state->ContentIsHTML()); + EXPECT_TRUE(web_state->ContentIsHTML()); + EXPECT_EQ(mime_type, web_state->GetContentsMimeType()); EXPECT_FALSE(web_state->IsLoading()); NavigationManager* navigation_manager = web_state->GetNavigationManager(); NavigationItem* item = navigation_manager->GetLastCommittedItem();
diff --git a/media/capture/BUILD.gn b/media/capture/BUILD.gn index 2ff140b..c60fa8a 100644 --- a/media/capture/BUILD.gn +++ b/media/capture/BUILD.gn
@@ -256,10 +256,14 @@ "video/chromeos/camera_hal_dispatcher_impl.h", "video/chromeos/camera_metadata_utils.cc", "video/chromeos/camera_metadata_utils.h", + "video/chromeos/cros_image_capture_impl.cc", + "video/chromeos/cros_image_capture_impl.h", "video/chromeos/display_rotation_observer.cc", "video/chromeos/display_rotation_observer.h", "video/chromeos/pixel_format_utils.cc", "video/chromeos/pixel_format_utils.h", + "video/chromeos/reprocess_manager.cc", + "video/chromeos/reprocess_manager.h", "video/chromeos/request_builder.cc", "video/chromeos/request_builder.h", "video/chromeos/request_manager.cc",
diff --git a/media/capture/video/chromeos/camera_device_delegate.cc b/media/capture/video/chromeos/camera_device_delegate.cc index ceac453b..d0c61e8 100644 --- a/media/capture/video/chromeos/camera_device_delegate.cc +++ b/media/capture/video/chromeos/camera_device_delegate.cc
@@ -22,6 +22,7 @@ #include "media/capture/video/chromeos/camera_device_context.h" #include "media/capture/video/chromeos/camera_hal_delegate.h" #include "media/capture/video/chromeos/camera_metadata_utils.h" +#include "media/capture/video/chromeos/reprocess_manager.h" #include "media/capture/video/chromeos/request_manager.h" namespace media { @@ -148,11 +149,13 @@ CameraDeviceDelegate::CameraDeviceDelegate( VideoCaptureDeviceDescriptor device_descriptor, scoped_refptr<CameraHalDelegate> camera_hal_delegate, - scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner) + scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner, + ReprocessManager* reprocess_manager) : device_descriptor_(device_descriptor), camera_id_(std::stoi(device_descriptor.device_id)), camera_hal_delegate_(std::move(camera_hal_delegate)), ipc_task_runner_(std::move(ipc_task_runner)), + reprocess_manager_(reprocess_manager), weak_ptr_factory_(this) {} CameraDeviceDelegate::~CameraDeviceDelegate() = default;
diff --git a/media/capture/video/chromeos/camera_device_delegate.h b/media/capture/video/chromeos/camera_device_delegate.h index a94abbc..05fe7f59 100644 --- a/media/capture/video/chromeos/camera_device_delegate.h +++ b/media/capture/video/chromeos/camera_device_delegate.h
@@ -20,6 +20,7 @@ class Camera3AController; class CameraDeviceContext; class CameraHalDelegate; +class ReprocessManager; class RequestManager; enum class StreamType : uint64_t { @@ -66,7 +67,8 @@ CameraDeviceDelegate( VideoCaptureDeviceDescriptor device_descriptor, scoped_refptr<CameraHalDelegate> camera_hal_delegate, - scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner); + scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner, + ReprocessManager* reprocess_manager); ~CameraDeviceDelegate(); @@ -182,6 +184,8 @@ VideoCaptureDevice::SetPhotoOptionsCallback set_photo_option_callback_; + ReprocessManager* reprocess_manager_; // weak + base::WeakPtrFactory<CameraDeviceDelegate> weak_ptr_factory_; DISALLOW_IMPLICIT_CONSTRUCTORS(CameraDeviceDelegate);
diff --git a/media/capture/video/chromeos/camera_device_delegate_unittest.cc b/media/capture/video/chromeos/camera_device_delegate_unittest.cc index 41e6c60..427de1a 100644 --- a/media/capture/video/chromeos/camera_device_delegate_unittest.cc +++ b/media/capture/video/chromeos/camera_device_delegate_unittest.cc
@@ -19,6 +19,7 @@ #include "media/capture/video/chromeos/camera_hal_delegate.h" #include "media/capture/video/chromeos/mock_camera_module.h" #include "media/capture/video/chromeos/mock_video_capture_client.h" +#include "media/capture/video/chromeos/reprocess_manager.h" #include "media/capture/video/chromeos/video_capture_device_factory_chromeos.h" #include "media/capture/video/mock_gpu_memory_buffer_manager.h" #include "testing/gmock/include/gmock/gmock.h" @@ -120,11 +121,13 @@ hal_delegate_thread_.Start(); camera_hal_delegate_ = new CameraHalDelegate(hal_delegate_thread_.task_runner()); + reprocess_manager_ = std::make_unique<ReprocessManager>(); camera_hal_delegate_->SetCameraModule( mock_camera_module_.GetInterfacePtrInfo()); } void TearDown() override { + reprocess_manager_.reset(); camera_hal_delegate_->Reset(); hal_delegate_thread_.Stop(); } @@ -134,8 +137,8 @@ ASSERT_FALSE(camera_device_delegate_); device_delegate_thread_.Start(); camera_device_delegate_ = std::make_unique<CameraDeviceDelegate>( - descriptor, camera_hal_delegate_, - device_delegate_thread_.task_runner()); + descriptor, camera_hal_delegate_, device_delegate_thread_.task_runner(), + reprocess_manager_.get()); num_streams_ = 0; } @@ -433,6 +436,8 @@ mojo::Binding<cros::mojom::Camera3DeviceOps> mock_camera_device_binding_; cros::mojom::Camera3CallbackOpsPtr callback_ops_; + std::unique_ptr<ReprocessManager> reprocess_manager_; + base::Thread device_delegate_thread_; std::unique_ptr<CameraDeviceContext> device_context_;
diff --git a/media/capture/video/chromeos/camera_hal_delegate.cc b/media/capture/video/chromeos/camera_hal_delegate.cc index 0568264..68bdbfed 100644 --- a/media/capture/video/chromeos/camera_hal_delegate.cc +++ b/media/capture/video/chromeos/camera_hal_delegate.cc
@@ -20,6 +20,7 @@ #include "media/capture/video/chromeos/camera_buffer_factory.h" #include "media/capture/video/chromeos/camera_hal_dispatcher_impl.h" #include "media/capture/video/chromeos/camera_metadata_utils.h" +#include "media/capture/video/chromeos/reprocess_manager.h" #include "media/capture/video/chromeos/video_capture_device_chromeos_halv3.h" namespace media { @@ -124,7 +125,8 @@ std::unique_ptr<VideoCaptureDevice> CameraHalDelegate::CreateDevice( scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_screen_observer, - const VideoCaptureDeviceDescriptor& device_descriptor) { + const VideoCaptureDeviceDescriptor& device_descriptor, + ReprocessManager* reprocess_manager) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); std::unique_ptr<VideoCaptureDevice> capture_device; if (!UpdateBuiltInCameraInfo()) { @@ -136,7 +138,8 @@ return capture_device; } capture_device.reset(new VideoCaptureDeviceChromeOSHalv3( - std::move(task_runner_for_screen_observer), device_descriptor, this)); + std::move(task_runner_for_screen_observer), device_descriptor, this, + reprocess_manager)); return capture_device; }
diff --git a/media/capture/video/chromeos/camera_hal_delegate.h b/media/capture/video/chromeos/camera_hal_delegate.h index 6d60146..bad13be 100644 --- a/media/capture/video/chromeos/camera_hal_delegate.h +++ b/media/capture/video/chromeos/camera_hal_delegate.h
@@ -24,6 +24,7 @@ namespace media { class CameraBufferFactory; +class ReprocessManager; // CameraHalDelegate is the component which does Mojo IPCs to the camera HAL // process on Chrome OS to access the module-level camera functionalities such @@ -56,7 +57,8 @@ std::unique_ptr<VideoCaptureDevice> CreateDevice( scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_screen_observer, - const VideoCaptureDeviceDescriptor& device_descriptor); + const VideoCaptureDeviceDescriptor& device_descriptor, + ReprocessManager* reprocess_manager); void GetSupportedFormats( const VideoCaptureDeviceDescriptor& device_descriptor, VideoCaptureFormats* supported_formats);
diff --git a/media/capture/video/chromeos/cros_image_capture_impl.cc b/media/capture/video/chromeos/cros_image_capture_impl.cc new file mode 100644 index 0000000..6574fef2 --- /dev/null +++ b/media/capture/video/chromeos/cros_image_capture_impl.cc
@@ -0,0 +1,45 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/capture/video/chromeos/cros_image_capture_impl.h" + +#include <utility> +#include <vector> + +#include "base/task/post_task.h" + +namespace media { + +CrosImageCaptureImpl::CrosImageCaptureImpl(ReprocessManager* reprocess_manager) + : reprocess_manager_(reprocess_manager) {} + +CrosImageCaptureImpl::~CrosImageCaptureImpl() = default; + +void CrosImageCaptureImpl::BindRequest( + cros::mojom::CrosImageCaptureRequest request) { + bindings_.AddBinding(this, std::move(request)); +} + +void CrosImageCaptureImpl::GetSupportedEffects( + GetSupportedEffectsCallback callback) { + reprocess_manager_->GetSupportedEffects( + base::BindOnce(&CrosImageCaptureImpl::OnGetSupportedEffects, + base::Unretained(this), std::move(callback))); +} + +void CrosImageCaptureImpl::SetReprocessOption( + cros::mojom::Effect effect, + SetReprocessOptionCallback callback) { + reprocess_manager_->SetReprocessOption(effect, std::move(callback)); +} + +void CrosImageCaptureImpl::OnGetSupportedEffects( + GetSupportedEffectsCallback callback, + base::flat_set<cros::mojom::Effect> supported_effects) { + std::vector<cros::mojom::Effect> effects(supported_effects.begin(), + supported_effects.end()); + std::move(callback).Run(std::move(effects)); +} + +} // namespace media
diff --git a/media/capture/video/chromeos/cros_image_capture_impl.h b/media/capture/video/chromeos/cros_image_capture_impl.h new file mode 100644 index 0000000..cc9d80c --- /dev/null +++ b/media/capture/video/chromeos/cros_image_capture_impl.h
@@ -0,0 +1,42 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_CAPTURE_VIDEO_CHROMEOS_CROS_IMAGE_CAPTURE_IMPL_H_ +#define MEDIA_CAPTURE_VIDEO_CHROMEOS_CROS_IMAGE_CAPTURE_IMPL_H_ + +#include "base/containers/flat_set.h" +#include "media/capture/video/chromeos/mojo/cros_image_capture.mojom.h" +#include "media/capture/video/chromeos/reprocess_manager.h" +#include "mojo/public/cpp/bindings/binding_set.h" + +namespace media { + +class CrosImageCaptureImpl : public cros::mojom::CrosImageCapture { + public: + explicit CrosImageCaptureImpl(ReprocessManager* reprocess_manager); + ~CrosImageCaptureImpl() override; + + void BindRequest(cros::mojom::CrosImageCaptureRequest request); + + // cros::mojom::CrosImageCapture implementations. + + void GetSupportedEffects(GetSupportedEffectsCallback callback) override; + void SetReprocessOption(cros::mojom::Effect effect, + SetReprocessOptionCallback callback) override; + + private: + void OnGetSupportedEffects( + GetSupportedEffectsCallback callback, + base::flat_set<cros::mojom::Effect> supported_effects); + + ReprocessManager* reprocess_manager_; // weak + + mojo::BindingSet<cros::mojom::CrosImageCapture> bindings_; + + DISALLOW_COPY_AND_ASSIGN(CrosImageCaptureImpl); +}; + +} // namespace media + +#endif // MEDIA_CAPTURE_VIDEO_CHROMEOS_CROS_IMAGE_CAPTURE_IMPL_H_
diff --git a/media/capture/video/chromeos/mojo/BUILD.gn b/media/capture/video/chromeos/mojo/BUILD.gn index a0372ce..ccd75a9 100644 --- a/media/capture/video/chromeos/mojo/BUILD.gn +++ b/media/capture/video/chromeos/mojo/BUILD.gn
@@ -11,9 +11,11 @@ "camera_metadata.mojom", "camera_metadata_tags.mojom", "cros_camera_service.mojom", + "cros_image_capture.mojom", ] deps = [ + "//media/capture/mojom:image_capture", "//media/mojo/interfaces", ] }
diff --git a/media/capture/video/chromeos/mojo/cros_image_capture.mojom b/media/capture/video/chromeos/mojo/cros_image_capture.mojom new file mode 100644 index 0000000..88b32ef --- /dev/null +++ b/media/capture/video/chromeos/mojo/cros_image_capture.mojom
@@ -0,0 +1,28 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module cros.mojom; + +import "media/capture/mojom/image_capture.mojom"; + +// Effect that recognized by Chrome OS. +enum Effect { + PORTRAIT_MODE = 0, + NO_EFFECT +}; + +// Interface for Chrome OS specific Image Capture API which supports reprocess +// mechanism. +interface CrosImageCapture { + // Gets supported effects for current active device. + GetSupportedEffects() => (array<Effect> supported_effects); + + // Sets reprocess option to bind with the coming take photo request. When this + // method is called, the reprocess option will be queued. All reprocess + // options in the queue will be consumed when TakePhoto() method in Image + // Capture API is triggered and all the queued reprocess options will be bound + // to that take photo request. + SetReprocessOption(Effect effect) + => (int32 status, media.mojom.Blob blob); +}; \ No newline at end of file
diff --git a/media/capture/video/chromeos/reprocess_manager.cc b/media/capture/video/chromeos/reprocess_manager.cc new file mode 100644 index 0000000..8872c7c3 --- /dev/null +++ b/media/capture/video/chromeos/reprocess_manager.cc
@@ -0,0 +1,173 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <utility> + +#include "media/capture/video/chromeos/camera_metadata_utils.h" +#include "media/capture/video/chromeos/reprocess_manager.h" + +namespace media { + +namespace { + +void OnStillCaptureDone(media::mojom::ImageCapture::TakePhotoCallback callback, + int status, + mojom::BlobPtr blob) { + std::move(callback).Run(std::move(blob)); +} + +} // namespace + +ReprocessTask::ReprocessTask() = default; + +ReprocessTask::ReprocessTask(ReprocessTask&& other) + : effect(other.effect), + callback(std::move(other.callback)), + extra_metadata(std::move(other.extra_metadata)) {} + +ReprocessTask::~ReprocessTask() = default; + +// static +int ReprocessManager::GetReprocessReturnCode( + cros::mojom::Effect effect, + cros::mojom::CameraMetadataPtr* metadata) { + if (effect == cros::mojom::Effect::PORTRAIT_MODE) { + auto* portrait_mode_segmentation_result = GetMetadataEntry( + *metadata, static_cast<cros::mojom::CameraMetadataTag>( + kPortraitModeSegmentationResultVendorKey)); + CHECK(portrait_mode_segmentation_result); + return static_cast<int>((*portrait_mode_segmentation_result)->data[0]); + } + return kReprocessSuccess; +} + +ReprocessManager::ReprocessManager() + : sequenced_task_runner_(base::CreateSequencedTaskRunnerWithTraits( + {base::TaskPriority::USER_VISIBLE})), + impl(new ReprocessManager::ReprocessManagerImpl) {} + +ReprocessManager::~ReprocessManager() { + sequenced_task_runner_->DeleteSoon(FROM_HERE, std::move(impl)); +}; + +void ReprocessManager::SetReprocessOption( + cros::mojom::Effect effect, + cros::mojom::CrosImageCapture::SetReprocessOptionCallback + reprocess_result_callback) { + sequenced_task_runner_->PostTask( + FROM_HERE, + base::BindOnce( + &ReprocessManager::ReprocessManagerImpl::SetReprocessOption, + base::Unretained(impl.get()), effect, + std::move(reprocess_result_callback))); +} + +void ReprocessManager::ConsumeReprocessOptions( + media::mojom::ImageCapture::TakePhotoCallback take_photo_callback, + base::OnceCallback<void(ReprocessTaskQueue)> consumption_callback) { + sequenced_task_runner_->PostTask( + FROM_HERE, + base::BindOnce( + &ReprocessManager::ReprocessManagerImpl::ConsumeReprocessOptions, + base::Unretained(impl.get()), std::move(take_photo_callback), + std::move(consumption_callback))); +} + +void ReprocessManager::FlushReprocessOptions() { + sequenced_task_runner_->PostTask( + FROM_HERE, + base::BindOnce( + &ReprocessManager::ReprocessManagerImpl::FlushReprocessOptions, + base::Unretained(impl.get()))); +} + +void ReprocessManager::GetSupportedEffects( + GetSupportedEffectsCallback callback) { + sequenced_task_runner_->PostTask( + FROM_HERE, + base::BindOnce( + &ReprocessManager::ReprocessManagerImpl::GetSupportedEffects, + base::Unretained(impl.get()), std::move(callback))); +} + +void ReprocessManager::UpdateSupportedEffects( + const cros::mojom::CameraMetadataPtr& metadata) { + sequenced_task_runner_->PostTask( + FROM_HERE, + base::BindOnce( + &ReprocessManager::ReprocessManagerImpl::UpdateSupportedEffects, + base::Unretained(impl.get()), base::ConstRef(metadata))); +} + +ReprocessManager::ReprocessManagerImpl::ReprocessManagerImpl() {} + +ReprocessManager::ReprocessManagerImpl::~ReprocessManagerImpl() = default; + +void ReprocessManager::ReprocessManagerImpl::SetReprocessOption( + cros::mojom::Effect effect, + cros::mojom::CrosImageCapture::SetReprocessOptionCallback + reprocess_result_callback) { + ReprocessTask task; + task.effect = effect; + task.callback = std::move(reprocess_result_callback); + + if (effect == cros::mojom::Effect::PORTRAIT_MODE) { + std::vector<uint8_t> portrait_mode_value(sizeof(int32_t)); + *reinterpret_cast<int32_t*>(portrait_mode_value.data()) = 1; + cros::mojom::CameraMetadataEntryPtr e = + cros::mojom::CameraMetadataEntry::New(); + e->tag = + static_cast<cros::mojom::CameraMetadataTag>(kPortraitModeVendorKey); + e->type = cros::mojom::EntryType::TYPE_INT32; + e->count = 1; + e->data = std::move(portrait_mode_value); + task.extra_metadata.push_back(std::move(e)); + } + + reprocess_task_queue_.push(std::move(task)); +} + +void ReprocessManager::ReprocessManagerImpl::ConsumeReprocessOptions( + media::mojom::ImageCapture::TakePhotoCallback take_photo_callback, + base::OnceCallback<void(ReprocessTaskQueue)> consumption_callback) { + ReprocessTaskQueue result_task_queue; + + ReprocessTask still_capture_task; + still_capture_task.effect = cros::mojom::Effect::NO_EFFECT; + still_capture_task.callback = + base::BindOnce(&OnStillCaptureDone, std::move(take_photo_callback)); + result_task_queue.push(std::move(still_capture_task)); + + auto& task_queue = reprocess_task_queue_; + while (!task_queue.empty()) { + result_task_queue.push(std::move(task_queue.front())); + task_queue.pop(); + } + std::move(consumption_callback).Run(std::move(result_task_queue)); +} + +void ReprocessManager::ReprocessManagerImpl::FlushReprocessOptions() { + auto empty_queue = ReprocessTaskQueue(); + reprocess_task_queue_.swap(empty_queue); +} + +void ReprocessManager::ReprocessManagerImpl::GetSupportedEffects( + GetSupportedEffectsCallback callback) { + std::move(callback).Run( + base::flat_set<cros::mojom::Effect>(supported_effects_)); +} + +void ReprocessManager::ReprocessManagerImpl::UpdateSupportedEffects( + const cros::mojom::CameraMetadataPtr& metadata) { + const cros::mojom::CameraMetadataEntryPtr* portrait_mode = + media::GetMetadataEntry( + metadata, + static_cast<cros::mojom::CameraMetadataTag>(kPortraitModeVendorKey)); + supported_effects_.clear(); + if (portrait_mode) { + supported_effects_.insert(cros::mojom::Effect::PORTRAIT_MODE); + } +} + +} // namespace media
diff --git a/media/capture/video/chromeos/reprocess_manager.h b/media/capture/video/chromeos/reprocess_manager.h new file mode 100644 index 0000000..715081925 --- /dev/null +++ b/media/capture/video/chromeos/reprocess_manager.h
@@ -0,0 +1,114 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_CAPTURE_VIDEO_CHROMEOS_REPROCESS_MANAGER_H_ +#define MEDIA_CAPTURE_VIDEO_CHROMEOS_REPROCESS_MANAGER_H_ + +#include <queue> +#include <set> +#include <vector> + +#include "base/containers/flat_set.h" +#include "base/sequenced_task_runner.h" +#include "base/task/post_task.h" +#include "media/capture/capture_export.h" +#include "media/capture/mojom/image_capture.mojom.h" +#include "media/capture/video/chromeos/mojo/camera3.mojom.h" +#include "media/capture/video/chromeos/mojo/cros_image_capture.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" + +namespace media { + +struct ReprocessTask { + public: + ReprocessTask(); + ReprocessTask(ReprocessTask&& other); + ~ReprocessTask(); + cros::mojom::Effect effect; + cros::mojom::CrosImageCapture::SetReprocessOptionCallback callback; + std::vector<cros::mojom::CameraMetadataEntryPtr> extra_metadata; +}; + +using ReprocessTaskQueue = base::queue<ReprocessTask>; + +constexpr uint32_t kPortraitModeVendorKey = 0x80000000; +constexpr uint32_t kPortraitModeSegmentationResultVendorKey = 0x80000001; +constexpr int32_t kReprocessSuccess = 0; + +// ReprocessManager is used to communicate between the reprocess requester and +// the consumer. When reprocess is requested, the reprocess information will be +// wrapped as a ReprocessTask and stored in the queue. When consumption, all +// ReprocessTask in the queue will be dumped and a default NO_EFFECT task will +// be added on the top of the result queue. Note that all calls will be +// sequentialize to a single sequence. +class CAPTURE_EXPORT ReprocessManager { + public: + using GetSupportedEffectsCallback = + base::OnceCallback<void(base::flat_set<cros::mojom::Effect>)>; + + class ReprocessManagerImpl { + public: + ReprocessManagerImpl(); + ~ReprocessManagerImpl(); + + void SetReprocessOption( + cros::mojom::Effect effect, + cros::mojom::CrosImageCapture::SetReprocessOptionCallback + reprocess_result_callback); + + void ConsumeReprocessOptions( + media::mojom::ImageCapture::TakePhotoCallback take_photo_callback, + base::OnceCallback<void(ReprocessTaskQueue)> consumption_callback); + + void FlushReprocessOptions(); + + void GetSupportedEffects(GetSupportedEffectsCallback callback); + + void UpdateSupportedEffects(const cros::mojom::CameraMetadataPtr& metadata); + + private: + base::queue<ReprocessTask> reprocess_task_queue_; + base::flat_set<cros::mojom::Effect> supported_effects_; + + DISALLOW_COPY_AND_ASSIGN(ReprocessManagerImpl); + }; + + static int GetReprocessReturnCode(cros::mojom::Effect effect, + cros::mojom::CameraMetadataPtr* metadata); + ReprocessManager(); + ~ReprocessManager(); + + // Sets the reprocess option for given effect. Each reprocess + // option has a corressponding callback. + void SetReprocessOption( + cros::mojom::Effect effect, + cros::mojom::CrosImageCapture::SetReprocessOptionCallback + reprocess_result_callback); + + // Consumes all ReprocessTasks in the queue. A default NO_EFFECT task will be + // added on the top of the result queue. + void ConsumeReprocessOptions( + media::mojom::ImageCapture::TakePhotoCallback take_photo_callback, + base::OnceCallback<void(ReprocessTaskQueue)> consumption_callback); + + // Clears all remaining ReprocessTasks in the queue. + void FlushReprocessOptions(); + + // Gets supported effects for current active device. + void GetSupportedEffects(GetSupportedEffectsCallback callback); + + // Updates supported effects for given active device. This method should be + // triggered whenever the camera characteristics is updated. + void UpdateSupportedEffects(const cros::mojom::CameraMetadataPtr& metadata); + + private: + scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_; + std::unique_ptr<ReprocessManagerImpl> impl; + + DISALLOW_COPY_AND_ASSIGN(ReprocessManager); +}; + +} // namespace media + +#endif // MEDIA_CAPTURE_VIDEO_CHROMEOS_REPROCESS_MANAGER_H_
diff --git a/media/capture/video/chromeos/video_capture_device_chromeos_halv3.cc b/media/capture/video/chromeos/video_capture_device_chromeos_halv3.cc index 8ca3677..9b67f893 100644 --- a/media/capture/video/chromeos/video_capture_device_chromeos_halv3.cc +++ b/media/capture/video/chromeos/video_capture_device_chromeos_halv3.cc
@@ -19,6 +19,7 @@ #include "media/capture/video/chromeos/camera_device_context.h" #include "media/capture/video/chromeos/camera_device_delegate.h" #include "media/capture/video/chromeos/camera_hal_delegate.h" +#include "media/capture/video/chromeos/reprocess_manager.h" #include "ui/display/display.h" #include "ui/display/display_observer.h" #include "ui/display/screen.h" @@ -28,7 +29,8 @@ VideoCaptureDeviceChromeOSHalv3::VideoCaptureDeviceChromeOSHalv3( scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_screen_observer, const VideoCaptureDeviceDescriptor& device_descriptor, - scoped_refptr<CameraHalDelegate> camera_hal_delegate) + scoped_refptr<CameraHalDelegate> camera_hal_delegate, + ReprocessManager* reprocess_manager) : device_descriptor_(device_descriptor), camera_hal_delegate_(std::move(camera_hal_delegate)), capture_task_runner_(base::ThreadTaskRunnerHandle::Get()), @@ -44,6 +46,7 @@ rotates_with_device_(lens_facing_ != VideoFacingMode::MEDIA_VIDEO_FACING_NONE), rotation_(0), + reprocess_manager_(reprocess_manager), weak_ptr_factory_(this) { chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver( this); @@ -76,7 +79,7 @@ device_context_ = std::make_unique<CameraDeviceContext>(std::move(client)); camera_device_delegate_ = std::make_unique<CameraDeviceDelegate>( device_descriptor_, camera_hal_delegate_, - camera_device_ipc_thread_.task_runner()); + camera_device_ipc_thread_.task_runner(), reprocess_manager_); OpenDevice(); }
diff --git a/media/capture/video/chromeos/video_capture_device_chromeos_halv3.h b/media/capture/video/chromeos/video_capture_device_chromeos_halv3.h index b08e093..492755d8 100644 --- a/media/capture/video/chromeos/video_capture_device_chromeos_halv3.h +++ b/media/capture/video/chromeos/video_capture_device_chromeos_halv3.h
@@ -28,6 +28,7 @@ class CameraHalDelegate; class CameraDeviceContext; class CameraDeviceDelegate; +class ReprocessManager; // Implementation of VideoCaptureDevice for ChromeOS with CrOS camera HALv3. class CAPTURE_EXPORT VideoCaptureDeviceChromeOSHalv3 final @@ -39,7 +40,8 @@ scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_screen_observer, const VideoCaptureDeviceDescriptor& device_descriptor, - scoped_refptr<CameraHalDelegate> camera_hal_delegate); + scoped_refptr<CameraHalDelegate> camera_hal_delegate, + ReprocessManager* reprocess_manager); ~VideoCaptureDeviceChromeOSHalv3() final; @@ -99,6 +101,8 @@ const bool rotates_with_device_; int rotation_; + ReprocessManager* reprocess_manager_; // weak + base::WeakPtrFactory<VideoCaptureDeviceChromeOSHalv3> weak_ptr_factory_; DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureDeviceChromeOSHalv3);
diff --git a/media/capture/video/chromeos/video_capture_device_factory_chromeos.cc b/media/capture/video/chromeos/video_capture_device_factory_chromeos.cc index 6fb9ccac..6d3ad46 100644 --- a/media/capture/video/chromeos/video_capture_device_factory_chromeos.cc +++ b/media/capture/video/chromeos/video_capture_device_factory_chromeos.cc
@@ -4,8 +4,12 @@ #include "media/capture/video/chromeos/video_capture_device_factory_chromeos.h" +#include <utility> + #include "base/memory/ptr_util.h" #include "media/capture/video/chromeos/camera_hal_dispatcher_impl.h" +#include "media/capture/video/chromeos/cros_image_capture_impl.h" +#include "media/capture/video/chromeos/reprocess_manager.h" namespace media { @@ -19,6 +23,8 @@ scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_screen_observer) : task_runner_for_screen_observer_(task_runner_for_screen_observer), camera_hal_ipc_thread_("CameraHalIpcThread"), + reprocess_manager_(new ReprocessManager), + cros_image_capture_(new CrosImageCaptureImpl(reprocess_manager_.get())), initialized_(Init()) {} VideoCaptureDeviceFactoryChromeOS::~VideoCaptureDeviceFactoryChromeOS() { @@ -34,7 +40,8 @@ return std::unique_ptr<VideoCaptureDevice>(); } return camera_hal_delegate_->CreateDevice(task_runner_for_screen_observer_, - device_descriptor); + device_descriptor, + reprocess_manager_.get()); } void VideoCaptureDeviceFactoryChromeOS::GetSupportedFormats( @@ -83,4 +90,9 @@ return true; } +void VideoCaptureDeviceFactoryChromeOS::BindCrosImageCaptureRequest( + cros::mojom::CrosImageCaptureRequest request) { + cros_image_capture_->BindRequest(std::move(request)); +} + } // namespace media
diff --git a/media/capture/video/chromeos/video_capture_device_factory_chromeos.h b/media/capture/video/chromeos/video_capture_device_factory_chromeos.h index bc452c3..56c74b52 100644 --- a/media/capture/video/chromeos/video_capture_device_factory_chromeos.h +++ b/media/capture/video/chromeos/video_capture_device_factory_chromeos.h
@@ -10,10 +10,14 @@ #include "base/macros.h" #include "base/single_thread_task_runner.h" #include "media/capture/video/chromeos/camera_hal_delegate.h" +#include "media/capture/video/chromeos/mojo/cros_image_capture.mojom.h" #include "media/capture/video/video_capture_device_factory.h" namespace media { +class CrosImageCaptureImpl; +class ReprocessManager; + class CAPTURE_EXPORT VideoCaptureDeviceFactoryChromeOS final : public VideoCaptureDeviceFactory { public: @@ -35,6 +39,9 @@ static gpu::GpuMemoryBufferManager* GetBufferManager(); static void SetGpuBufferManager(gpu::GpuMemoryBufferManager* buffer_manager); + void BindCrosImageCaptureRequest( + cros::mojom::CrosImageCaptureRequest request); + private: // Initializes the factory. The factory is functional only after this call // succeeds. @@ -53,6 +60,10 @@ // |camera_hal_ipc_thread_|. scoped_refptr<CameraHalDelegate> camera_hal_delegate_; + std::unique_ptr<ReprocessManager> reprocess_manager_; + + std::unique_ptr<CrosImageCaptureImpl> cros_image_capture_; + bool initialized_; DISALLOW_COPY_AND_ASSIGN(VideoCaptureDeviceFactoryChromeOS);
diff --git a/media/capture/video/video_capture_system.h b/media/capture/video/video_capture_system.h index 016b8e2..c4cdaaf 100644 --- a/media/capture/video/video_capture_system.h +++ b/media/capture/video/video_capture_system.h
@@ -8,6 +8,10 @@ #include "media/capture/video/video_capture_device_factory.h" #include "media/capture/video/video_capture_device_info.h" +#if defined(OS_CHROMEOS) +#include "media/capture/video/chromeos/mojo/cros_image_capture.mojom.h" +#endif // defined(OS_CHROMEOS) + namespace media { // GetDeviceInfosAsync() should be called at least once before calling @@ -29,6 +33,12 @@ // wrong. virtual std::unique_ptr<VideoCaptureDevice> CreateDevice( const std::string& device_id) = 0; + +#if defined(OS_CHROMEOS) + // Pass the mojo request to bind with DeviceFactory for Chrome OS. + virtual void BindCrosImageCaptureRequest( + cros::mojom::CrosImageCaptureRequest request) = 0; +#endif // defined(OS_CHROMEOS) }; } // namespace media
diff --git a/media/capture/video/video_capture_system_impl.cc b/media/capture/video/video_capture_system_impl.cc index ef82af1..966c3ee 100644 --- a/media/capture/video/video_capture_system_impl.cc +++ b/media/capture/video/video_capture_system_impl.cc
@@ -4,11 +4,18 @@ #include "media/capture/video/video_capture_system_impl.h" +#include <utility> + #include "base/bind.h" #include "base/bind_helpers.h" #include "build/build_config.h" #include "media/base/bind_to_current_loop.h" +#if defined(OS_CHROMEOS) +#include "media/capture/video/chromeos/public/cros_features.h" +#include "media/capture/video/chromeos/video_capture_device_factory_chromeos.h" +#endif // defined(OS_CHROMEOS) + namespace { // Compares two VideoCaptureFormat by checking smallest frame_size area, then @@ -156,4 +163,16 @@ ProcessDeviceInfoRequest(); } +#if defined(OS_CHROMEOS) +void VideoCaptureSystemImpl::BindCrosImageCaptureRequest( + cros::mojom::CrosImageCaptureRequest request) { + CHECK(factory_); + + if (media::ShouldUseCrosCameraService()) { + static_cast<VideoCaptureDeviceFactoryChromeOS*>(factory_.get()) + ->BindCrosImageCaptureRequest(std::move(request)); + } +} +#endif // defined(OS_CHROMEOS) + } // namespace media
diff --git a/media/capture/video/video_capture_system_impl.h b/media/capture/video/video_capture_system_impl.h index 581979a..0cbd5c8 100644 --- a/media/capture/video/video_capture_system_impl.h +++ b/media/capture/video/video_capture_system_impl.h
@@ -7,6 +7,10 @@ #include "media/capture/video/video_capture_system.h" +#if defined(OS_CHROMEOS) +#include "media/capture/video/chromeos/mojo/cros_image_capture.mojom.h" +#endif // defined(OS_CHROMEOS) + namespace media { // Layer on top of VideoCaptureDeviceFactory that translates device descriptors @@ -22,6 +26,11 @@ std::unique_ptr<VideoCaptureDevice> CreateDevice( const std::string& device_id) override; +#if defined(OS_CHROMEOS) + void BindCrosImageCaptureRequest( + cros::mojom::CrosImageCaptureRequest request) override; +#endif // defined(OS_CHROMEOS) + private: using DeviceEnumQueue = std::list<DeviceInfoCallback>;
diff --git a/media/filters/BUILD.gn b/media/filters/BUILD.gn index f551991..81c1e4fc 100644 --- a/media/filters/BUILD.gn +++ b/media/filters/BUILD.gn
@@ -47,8 +47,6 @@ "frame_processor.h", "gpu_video_decoder.cc", "gpu_video_decoder.h", - "jpeg_parser.cc", - "jpeg_parser.h", "memory_data_source.cc", "memory_data_source.h", "offloading_video_decoder.cc", @@ -96,6 +94,10 @@ "//media:subcomponent_config", ] + public_deps = [ + ":jpeg_parser", + ] + deps = [ "//cc/base", # For MathUtil. "//gpu/command_buffer/common", @@ -229,6 +231,34 @@ } } +# This component allows other targets to use the JPEG parser as a standalone, +# general-purpose utility without having to pull all of //media as a dependency +# (which could potentially result in cycles). +component("jpeg_parser") { + output_name = "media_filters_jpeg_parser" + sources = [ + "jpeg_parser.cc", + "jpeg_parser.h", + ] + defines = [ "IS_JPEG_PARSER_IMPL" ] + deps = [ + "//base", + ] +} + +source_set("jpeg_parser_unit_tests") { + testonly = true + sources = [ + "jpeg_parser_unittest.cc", + ] + deps = [ + ":jpeg_parser", + "//base", + "//media:test_support", + "//testing/gtest", + ] +} + source_set("perftests") { testonly = true sources = [] @@ -288,7 +318,6 @@ "frame_buffer_pool_unittest.cc", "frame_processor_unittest.cc", "ivf_parser_unittest.cc", - "jpeg_parser_unittest.cc", "memory_data_source_unittest.cc", "offloading_video_decoder_unittest.cc", "pipeline_controller_unittest.cc", @@ -304,6 +333,7 @@ ] deps = [ + ":jpeg_parser_unit_tests", "//base/test:test_support", "//media:test_support", "//testing/gmock",
diff --git a/media/filters/jpeg_parser.h b/media/filters/jpeg_parser.h index c616123..39df6b1 100644 --- a/media/filters/jpeg_parser.h +++ b/media/filters/jpeg_parser.h
@@ -7,7 +7,8 @@ #include <stddef.h> #include <stdint.h> -#include "media/base/media_export.h" + +#include "base/component_export.h" namespace media { @@ -80,12 +81,12 @@ }; // K.3.3.1 "Specification of typical tables for DC difference coding" -MEDIA_EXPORT extern const JpegHuffmanTable - kDefaultDcTable[kJpegMaxHuffmanTableNumBaseline]; +COMPONENT_EXPORT(JPEG_PARSER) +extern const JpegHuffmanTable kDefaultDcTable[kJpegMaxHuffmanTableNumBaseline]; // K.3.3.2 "Specification of typical tables for AC coefficient coding" -MEDIA_EXPORT extern const JpegHuffmanTable - kDefaultAcTable[kJpegMaxHuffmanTableNumBaseline]; +COMPONENT_EXPORT(JPEG_PARSER) +extern const JpegHuffmanTable kDefaultAcTable[kJpegMaxHuffmanTableNumBaseline]; // Parsing result of JPEG DQT marker. struct JpegQuantizationTable { @@ -93,11 +94,12 @@ uint8_t value[kDctSize]; // baseline only supports 8 bits quantization table }; -MEDIA_EXPORT extern const uint8_t kZigZag8x8[64]; +COMPONENT_EXPORT(JPEG_PARSER) extern const uint8_t kZigZag8x8[64]; // Table K.1 Luminance quantization table // Table K.2 Chrominance quantization table -MEDIA_EXPORT extern const JpegQuantizationTable kDefaultQuantTable[2]; +COMPONENT_EXPORT(JPEG_PARSER) +extern const JpegQuantizationTable kDefaultQuantTable[2]; // Parsing result of a JPEG component. struct JpegComponent { @@ -144,16 +146,18 @@ // Parses JPEG picture in |buffer| with |length|. Returns true iff header is // valid and JPEG baseline sequential process is present. If parsed // successfully, |result| is the parsed result. -MEDIA_EXPORT bool ParseJpegPicture(const uint8_t* buffer, - size_t length, - JpegParseResult* result); +COMPONENT_EXPORT(JPEG_PARSER) +bool ParseJpegPicture(const uint8_t* buffer, + size_t length, + JpegParseResult* result); // Parses the first image of JPEG stream in |buffer| with |length|. Returns // true iff header is valid and JPEG baseline sequential process is present. // If parsed successfully, |result| is the parsed result. -MEDIA_EXPORT bool ParseJpegStream(const uint8_t* buffer, - size_t length, - JpegParseResult* result); +COMPONENT_EXPORT(JPEG_PARSER) +bool ParseJpegStream(const uint8_t* buffer, + size_t length, + JpegParseResult* result); } // namespace media
diff --git a/net/BUILD.gn b/net/BUILD.gn index ecf7245..db0ddad1 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -1481,6 +1481,7 @@ "third_party/quic/platform/api/quic_clock.h", "third_party/quic/platform/api/quic_containers.h", "third_party/quic/platform/api/quic_endian.h", + "third_party/quic/platform/api/quic_error_code_wrappers.h", "third_party/quic/platform/api/quic_estimate_memory_usage.h", "third_party/quic/platform/api/quic_export.h", "third_party/quic/platform/api/quic_exported_stats.h", @@ -1497,6 +1498,7 @@ "third_party/quic/platform/api/quic_ip_address.h", "third_party/quic/platform/api/quic_ip_address_family.h", "third_party/quic/platform/api/quic_logging.h", + "third_party/quic/platform/api/quic_macros.h", "third_party/quic/platform/api/quic_map_util.h", "third_party/quic/platform/api/quic_mem_slice.h", "third_party/quic/platform/api/quic_mem_slice_span.h", @@ -1526,6 +1528,7 @@ "third_party/quic/platform/impl/quic_client_stats_impl.h", "third_party/quic/platform/impl/quic_containers_impl.h", "third_party/quic/platform/impl/quic_endian_impl.h", + "third_party/quic/platform/impl/quic_error_code_wrappers_impl.h", "third_party/quic/platform/impl/quic_estimate_memory_usage_impl.h", "third_party/quic/platform/impl/quic_export_impl.h", "third_party/quic/platform/impl/quic_fallthrough_impl.h", @@ -1540,6 +1543,7 @@ "third_party/quic/platform/impl/quic_ip_address_impl.cc", "third_party/quic/platform/impl/quic_ip_address_impl.h", "third_party/quic/platform/impl/quic_logging_impl.h", + "third_party/quic/platform/impl/quic_macros_impl.h", "third_party/quic/platform/impl/quic_map_util_impl.h", "third_party/quic/platform/impl/quic_mem_slice_impl.cc", "third_party/quic/platform/impl/quic_mem_slice_impl.h",
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index c5af703..9295d8cdf 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc
@@ -688,6 +688,7 @@ CertVerifier* /* cert_verifier */) : ParentPool(0, 0, + base::TimeDelta(), NULL, host_resolver, NULL, @@ -14262,8 +14263,9 @@ // each round of multi-round authentication. HttpNetworkSessionPeer session_peer(session.get()); TransportClientSocketPool* transport_pool = new TransportClientSocketPool( - 50, // Max sockets for pool - 1, // Max sockets per group + 50, // Max sockets for pool + 1, // Max sockets per group + base::TimeDelta::FromSeconds(10), // unused_idle_socket_timeout session_deps_.socket_factory.get(), session_deps_.host_resolver.get(), nullptr /* proxy_delegate */, session_deps_.cert_verifier.get(), session_deps_.channel_id_service.get(),
diff --git a/net/http/http_proxy_client_socket_pool_unittest.cc b/net/http/http_proxy_client_socket_pool_unittest.cc index 0ade6427..457b4a9 100644 --- a/net/http/http_proxy_client_socket_pool_unittest.cc +++ b/net/http/http_proxy_client_socket_pool_unittest.cc
@@ -49,6 +49,8 @@ const int kMaxSockets = 32; const int kMaxSocketsPerGroup = 6; +constexpr base::TimeDelta kUnusedIdleSocketTimeout = + base::TimeDelta::FromSeconds(10); const char * const kAuthHeaders[] = { "proxy-authorization", "Basic Zm9vOmJhcg==" }; @@ -73,6 +75,7 @@ : pool_(std::make_unique<TransportClientSocketPool>( kMaxSockets, kMaxSocketsPerGroup, + kUnusedIdleSocketTimeout, &socket_factory_, session_deps_.host_resolver.get(), nullptr /* proxy_delegate */, @@ -95,8 +98,8 @@ void InitPoolWithProxyDelegate(ProxyDelegate* proxy_delegate) { pool_ = std::make_unique<TransportClientSocketPool>( - kMaxSockets, kMaxSocketsPerGroup, &socket_factory_, - session_deps_.host_resolver.get(), proxy_delegate, + kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, + &socket_factory_, session_deps_.host_resolver.get(), proxy_delegate, session_deps_.cert_verifier.get(), session_deps_.channel_id_service.get(), session_deps_.transport_security_state.get(),
diff --git a/net/http/http_proxy_connect_job_unittest.cc b/net/http/http_proxy_connect_job_unittest.cc index ca9b002..e55fa43a 100644 --- a/net/http/http_proxy_connect_job_unittest.cc +++ b/net/http/http_proxy_connect_job_unittest.cc
@@ -56,6 +56,7 @@ : transport_socket_pool_( 32 /* max_sockets */, 6 /* max_sockets_pre_group */, + base::TimeDelta::FromSeconds(10) /* unused_idle_socket_timeout */, &socket_factory_, session_deps_.host_resolver.get(), nullptr /* proxy_delegate */, @@ -70,22 +71,24 @@ nullptr /* socket_performance_watcher_factory */, nullptr /* network_quality_estimator */, nullptr /* net_log */), - ssl_socket_pool_(32 /* max_sockets */, - 6 /* max_sockets_pre_group */, - &socket_factory_, - session_deps_.host_resolver.get(), - nullptr /* proxy_delegate */, - session_deps_.cert_verifier.get(), - session_deps_.channel_id_service.get(), - session_deps_.transport_security_state.get(), - session_deps_.cert_transparency_verifier.get(), - session_deps_.ct_policy_enforcer.get(), - nullptr /* ssl_client_session_cache */, - nullptr /* ssl_client_session_cache_privacy_mode */, - session_deps_.ssl_config_service.get(), - nullptr /* socket_performance_watcher_factory */, - nullptr /* network_quality_estimator */, - nullptr /* net_log */), + ssl_socket_pool_( + 32 /* max_sockets */, + 6 /* max_sockets_pre_group */, + base::TimeDelta::FromSeconds(10) /* unused_idle_socket_timeout */, + &socket_factory_, + session_deps_.host_resolver.get(), + nullptr /* proxy_delegate */, + session_deps_.cert_verifier.get(), + session_deps_.channel_id_service.get(), + session_deps_.transport_security_state.get(), + session_deps_.cert_transparency_verifier.get(), + session_deps_.ct_policy_enforcer.get(), + nullptr /* ssl_client_session_cache */, + nullptr /* ssl_client_session_cache_privacy_mode */, + session_deps_.ssl_config_service.get(), + nullptr /* socket_performance_watcher_factory */, + nullptr /* network_quality_estimator */, + nullptr /* net_log */), field_trial_list_(nullptr) { session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_); }
diff --git a/net/http/http_stream_factory_unittest.cc b/net/http/http_stream_factory_unittest.cc index 388333e..216f10b 100644 --- a/net/http/http_stream_factory_unittest.cc +++ b/net/http/http_stream_factory_unittest.cc
@@ -470,6 +470,7 @@ CTPolicyEnforcer*) : ParentPool(0, 0, + base::TimeDelta(), nullptr /* socket_factory */, host_resolver, nullptr /* proxy_delegate */,
diff --git a/net/network_error_logging/network_error_logging_service_unittest.cc b/net/network_error_logging/network_error_logging_service_unittest.cc index 0d57ed8..d660b6d 100644 --- a/net/network_error_logging/network_error_logging_service_unittest.cc +++ b/net/network_error_logging/network_error_logging_service_unittest.cc
@@ -838,7 +838,8 @@ kServerIP_, kHeaderWrongTypes); base::Value actual = service()->StatusAsValue(); - std::unique_ptr<base::Value> expected = base::test::ParseJson(R"json( + std::unique_ptr<base::Value> expected = + base::test::ParseJsonDeprecated(R"json( { "originPolicies": [ {
diff --git a/net/nqe/network_quality_estimator.cc b/net/nqe/network_quality_estimator.cc index 6ff54cb..fa5338af 100644 --- a/net/nqe/network_quality_estimator.cc +++ b/net/nqe/network_quality_estimator.cc
@@ -1063,17 +1063,8 @@ nqe::internal::InvalidRTT() && *http_rtt >= params_->ConnectionThreshold(type).http_rtt(); - const bool estimated_throughput_is_lower_than_threshold = - *downstream_throughput_kbps != nqe::internal::INVALID_RTT_THROUGHPUT && - params_->ConnectionThreshold(type).downstream_throughput_kbps() != - nqe::internal::INVALID_RTT_THROUGHPUT && - *downstream_throughput_kbps <= - params_->ConnectionThreshold(type).downstream_throughput_kbps(); - - if (estimated_http_rtt_is_higher_than_threshold || - estimated_throughput_is_lower_than_threshold) { + if (estimated_http_rtt_is_higher_than_threshold) return type; - } } // Return the fastest connection type. return static_cast<EffectiveConnectionType>(EFFECTIVE_CONNECTION_TYPE_LAST -
diff --git a/net/nqe/network_quality_estimator_params.cc b/net/nqe/network_quality_estimator_params.cc index c7fdb0a6..ca44e02 100644 --- a/net/nqe/network_quality_estimator_params.cc +++ b/net/nqe/network_quality_estimator_params.cc
@@ -381,14 +381,11 @@ .http_rtt() .InMilliseconds()))); - connection_thresholds[i].set_transport_rtt( - default_effective_connection_type_thresholds[i].transport_rtt()); - - connection_thresholds[i].set_downstream_throughput_kbps( - GetValueForVariationParam( - params, connection_type_name + ".ThresholdMedianKbps", - default_effective_connection_type_thresholds[i] - .downstream_throughput_kbps())); + DCHECK_EQ(nqe::internal::InvalidRTT(), + default_effective_connection_type_thresholds[i].transport_rtt()); + DCHECK_EQ(nqe::internal::INVALID_RTT_THROUGHPUT, + default_effective_connection_type_thresholds[i] + .downstream_throughput_kbps()); DCHECK(i == 0 || connection_thresholds[i].IsFaster(connection_thresholds[i - 1])); }
diff --git a/net/nqe/network_quality_estimator_unittest.cc b/net/nqe/network_quality_estimator_unittest.cc index 634485b..e7d1f05 100644 --- a/net/nqe/network_quality_estimator_unittest.cc +++ b/net/nqe/network_quality_estimator_unittest.cc
@@ -1173,11 +1173,6 @@ variation_params["2G.ThresholdMedianHttpRTTMsec"] = "1000"; variation_params["3G.ThresholdMedianHttpRTTMsec"] = "500"; - variation_params["Offline.ThresholdMedianKbps"] = "10"; - variation_params["Slow2G.ThresholdMedianKbps"] = "100"; - variation_params["2G.ThresholdMedianKbps"] = "300"; - variation_params["3G.ThresholdMedianKbps"] = "500"; - TestNetworkQualityEstimator estimator(variation_params); // Simulate the connection type as Wi-Fi so that GetEffectiveConnectionType @@ -1190,20 +1185,6 @@ int32_t downlink_throughput_kbps; EffectiveConnectionType expected_ect; } tests[] = { - // Set RTT to a very low value to observe the effect of throughput. - // Throughput is the bottleneck. - {1, 5, EFFECTIVE_CONNECTION_TYPE_OFFLINE}, - {1, 10, EFFECTIVE_CONNECTION_TYPE_OFFLINE}, - {1, 50, EFFECTIVE_CONNECTION_TYPE_SLOW_2G}, - {1, 100, EFFECTIVE_CONNECTION_TYPE_SLOW_2G}, - {1, 150, EFFECTIVE_CONNECTION_TYPE_2G}, - {1, 300, EFFECTIVE_CONNECTION_TYPE_2G}, - {1, 400, EFFECTIVE_CONNECTION_TYPE_3G}, - {1, 500, EFFECTIVE_CONNECTION_TYPE_3G}, - {1, 700, EFFECTIVE_CONNECTION_TYPE_4G}, - {1, 1000, EFFECTIVE_CONNECTION_TYPE_4G}, - {1, 1500, EFFECTIVE_CONNECTION_TYPE_4G}, - {1, 2500, EFFECTIVE_CONNECTION_TYPE_4G}, // Set both RTT and throughput. RTT is the bottleneck. {3000, 25000, EFFECTIVE_CONNECTION_TYPE_SLOW_2G}, {700, 25000, EFFECTIVE_CONNECTION_TYPE_3G},
diff --git a/net/reporting/reporting_cache_unittest.cc b/net/reporting/reporting_cache_unittest.cc index a6d1f6a3..b76fb24 100644 --- a/net/reporting/reporting_cache_unittest.cc +++ b/net/reporting/reporting_cache_unittest.cc
@@ -286,7 +286,8 @@ cache()->RemoveReports({report2}, ReportingReport::Outcome::UNKNOWN); base::Value actual = cache()->GetReportsAsValue(); - std::unique_ptr<base::Value> expected = base::test::ParseJson(R"json( + std::unique_ptr<base::Value> expected = + base::test::ParseJsonDeprecated(R"json( [ { "url": "https://origin1/path", @@ -429,7 +430,8 @@ cache()->IncrementEndpointDeliveries(kOrigin2_, kEndpoint2_, 1, false); base::Value actual = cache()->GetClientsAsValue(); - std::unique_ptr<base::Value> expected = base::test::ParseJson(R"json( + std::unique_ptr<base::Value> expected = + base::test::ParseJsonDeprecated(R"json( [ { "origin": "https://origin1",
diff --git a/net/socket/client_socket_pool.cc b/net/socket/client_socket_pool.cc index 4c9f13d..f68929d 100644 --- a/net/socket/client_socket_pool.cc +++ b/net/socket/client_socket_pool.cc
@@ -8,12 +8,6 @@ namespace { -// The maximum duration, in seconds, to keep unused idle persistent sockets -// alive. -// TODO(ziadh): Change this timeout after getting histogram data on how long it -// should be. -int64_t g_unused_idle_socket_timeout_s = 10; - // The maximum duration, in seconds, to keep used idle persistent sockets alive. int64_t g_used_idle_socket_timeout_s = 300; // 5 minutes @@ -22,17 +16,6 @@ namespace net { // static -base::TimeDelta ClientSocketPool::unused_idle_socket_timeout() { - return base::TimeDelta::FromSeconds(g_unused_idle_socket_timeout_s); -} - -// static -void ClientSocketPool::set_unused_idle_socket_timeout(base::TimeDelta timeout) { - DCHECK_GT(timeout.InSeconds(), 0); - g_unused_idle_socket_timeout_s = timeout.InSeconds(); -} - -// static base::TimeDelta ClientSocketPool::used_idle_socket_timeout() { return base::TimeDelta::FromSeconds(g_used_idle_socket_timeout_s); }
diff --git a/net/socket/client_socket_pool.h b/net/socket/client_socket_pool.h index 069f1711..7894baf 100644 --- a/net/socket/client_socket_pool.h +++ b/net/socket/client_socket_pool.h
@@ -188,9 +188,6 @@ // Returns the maximum amount of time to wait before retrying a connect. static const int kMaxConnectRetryIntervalMs = 250; - static base::TimeDelta unused_idle_socket_timeout(); - static void set_unused_idle_socket_timeout(base::TimeDelta timeout); - static base::TimeDelta used_idle_socket_timeout(); static void set_used_idle_socket_timeout(base::TimeDelta timeout);
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc index 157503a..164b7f8 100644 --- a/net/socket/client_socket_pool_base_unittest.cc +++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -63,6 +63,8 @@ const int kDefaultMaxSockets = 4; const int kDefaultMaxSocketsPerGroup = 2; +constexpr base::TimeDelta kUnusedIdleSocketTimeout = + base::TimeDelta::FromSeconds(10); // Make sure |handle| sets load times correctly when it has been assigned a // reused socket. @@ -739,11 +741,9 @@ } void CreatePool(int max_sockets, int max_sockets_per_group) { - CreatePoolWithIdleTimeouts( - max_sockets, - max_sockets_per_group, - ClientSocketPool::unused_idle_socket_timeout(), - ClientSocketPool::used_idle_socket_timeout()); + CreatePoolWithIdleTimeouts(max_sockets, max_sockets_per_group, + kUnusedIdleSocketTimeout, + ClientSocketPool::used_idle_socket_timeout()); } void CreatePoolWithIdleTimeouts(
diff --git a/net/socket/client_socket_pool_manager.cc b/net/socket/client_socket_pool_manager.cc index bf468c1..c16de189 100644 --- a/net/socket/client_socket_pool_manager.cc +++ b/net/socket/client_socket_pool_manager.cc
@@ -62,6 +62,8 @@ kDefaultMaxSocketsPerProxyServer // WEBSOCKET_SOCKET_POOL }; +base::TimeDelta g_unused_idle_socket_timeout = base::TimeDelta::FromSeconds(10); + static_assert(base::size(g_max_sockets_per_proxy_server) == HttpNetworkSession::NUM_SOCKET_POOL_TYPES, "max sockets per proxy server length mismatch"); @@ -356,6 +358,19 @@ g_max_sockets_per_proxy_server[pool_type] = socket_count; } +// static +base::TimeDelta ClientSocketPoolManager::unused_idle_socket_timeout( + HttpNetworkSession::SocketPoolType pool_type) { + return g_unused_idle_socket_timeout; +} + +// static +void ClientSocketPoolManager::set_unused_idle_socket_timeout( + HttpNetworkSession::SocketPoolType pool_type, + base::TimeDelta timeout) { + g_unused_idle_socket_timeout = timeout; +} + int InitSocketHandleForHttpRequest( ClientSocketPoolManager::SocketGroupType group_type, const HostPortPair& endpoint,
diff --git a/net/socket/client_socket_pool_manager.h b/net/socket/client_socket_pool_manager.h index a1f86f77..91d6b58 100644 --- a/net/socket/client_socket_pool_manager.h +++ b/net/socket/client_socket_pool_manager.h
@@ -75,6 +75,12 @@ HttpNetworkSession::SocketPoolType pool_type, int socket_count); + static base::TimeDelta unused_idle_socket_timeout( + HttpNetworkSession::SocketPoolType pool_type); + static void set_unused_idle_socket_timeout( + HttpNetworkSession::SocketPoolType pool_type, + base::TimeDelta timeout); + virtual void FlushSocketPoolsWithError(int error) = 0; virtual void CloseIdleSockets() = 0; // Returns the socket pool for direct HTTP and SSL connections.
diff --git a/net/socket/client_socket_pool_manager_impl.cc b/net/socket/client_socket_pool_manager_impl.cc index 288dfd8..dcd7affb 100644 --- a/net/socket/client_socket_pool_manager_impl.cc +++ b/net/socket/client_socket_pool_manager_impl.cc
@@ -76,6 +76,7 @@ ? std::make_unique<WebSocketTransportClientSocketPool>( max_sockets_per_pool(pool_type), max_sockets_per_group(pool_type), + unused_idle_socket_timeout(pool_type), socket_factory_, host_resolver, proxy_delegate, @@ -178,7 +179,6 @@ http_proxy, CreateTransportSocketPool( http_proxy, true /* use_socket_performance_watcher_factory */))); - return ret.first->second.get(); } @@ -196,12 +196,13 @@ int sockets_per_proxy_server = max_sockets_per_proxy_server(pool_type_); int sockets_per_group = std::min(sockets_per_proxy_server, max_sockets_per_group(pool_type_)); - std::pair<TransportSocketPoolMap::iterator, bool> ret = ssl_socket_pools_for_proxies_.insert(std::make_pair( proxy_server, std::make_unique<TransportClientSocketPool>( - sockets_per_proxy_server, sockets_per_group, socket_factory_, + + sockets_per_proxy_server, sockets_per_group, + unused_idle_socket_timeout(pool_type_), socket_factory_, host_resolver_, proxy_delegate_, cert_verifier_, channel_id_service_, transport_security_state_, cert_transparency_verifier_, ct_policy_enforcer_, @@ -259,8 +260,9 @@ std::min(sockets_per_proxy_server, max_sockets_per_group(pool_type_)); } return std::make_unique<TransportClientSocketPool>( - sockets_per_proxy_server, sockets_per_group, socket_factory_, - host_resolver_, proxy_delegate_, cert_verifier_, channel_id_service_, + sockets_per_proxy_server, sockets_per_group, + unused_idle_socket_timeout(pool_type_), socket_factory_, host_resolver_, + proxy_delegate_, cert_verifier_, channel_id_service_, transport_security_state_, cert_transparency_verifier_, ct_policy_enforcer_, ssl_client_session_cache_, ssl_client_session_cache_privacy_mode_, ssl_config_service_,
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc index 8379d114..e3c21f1 100644 --- a/net/socket/socket_test_util.cc +++ b/net/socket/socket_test_util.cc
@@ -2148,6 +2148,7 @@ : TransportClientSocketPool( max_sockets, max_sockets_per_group, + base::TimeDelta::FromSeconds(10) /* unused_idle_socket_timeout */, socket_factory, nullptr /* host_resolver */, nullptr /* proxy_delegate */,
diff --git a/net/socket/ssl_client_socket_pool_unittest.cc b/net/socket/ssl_client_socket_pool_unittest.cc index 31508ed..99cf66c 100644 --- a/net/socket/ssl_client_socket_pool_unittest.cc +++ b/net/socket/ssl_client_socket_pool_unittest.cc
@@ -55,6 +55,8 @@ const int kMaxSockets = 32; const int kMaxSocketsPerGroup = 6; +constexpr base::TimeDelta kUnusedIdleSocketTimeout = + base::TimeDelta::FromSeconds(10); const char kGroupName[] = "a"; class SSLClientSocketPoolTest : public TestWithScopedTaskEnvironment { @@ -92,6 +94,7 @@ http_proxy_socket_pool_( kMaxSockets, kMaxSocketsPerGroup, + kUnusedIdleSocketTimeout, &socket_factory_, &host_resolver_, nullptr /* proxy_delegate */, @@ -111,10 +114,10 @@ void CreatePool(bool http_proxy_pool) { pool_.reset(new TransportClientSocketPool( - kMaxSockets, kMaxSocketsPerGroup, &socket_factory_, &host_resolver_, - NULL /* proxy_delegate */, cert_verifier_.get(), - NULL /* channel_id_service */, transport_security_state_.get(), - &ct_verifier_, &ct_policy_enforcer_, + kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, + &socket_factory_, &host_resolver_, NULL /* proxy_delegate */, + cert_verifier_.get(), NULL /* channel_id_service */, + transport_security_state_.get(), &ct_verifier_, &ct_policy_enforcer_, nullptr /* ssl_client_session_cache */, nullptr /* ssl_client_session_cache_privacy_mode */, nullptr /* ssl_config_service */,
diff --git a/net/socket/ssl_connect_job_unittest.cc b/net/socket/ssl_connect_job_unittest.cc index 3ac937a..fb8740d 100644 --- a/net/socket/ssl_connect_job_unittest.cc +++ b/net/socket/ssl_connect_job_unittest.cc
@@ -51,6 +51,8 @@ const int kMaxSockets = 32; const int kMaxSocketsPerGroup = 6; +constexpr base::TimeDelta kUnusedIdleSocketTimeout = + base::TimeDelta::FromSeconds(10); const char kGroupName[] = "a"; // Just check that all connect times are set to base::TimeTicks::Now(), for @@ -125,6 +127,7 @@ http_proxy_socket_pool_( kMaxSockets, kMaxSocketsPerGroup, + kUnusedIdleSocketTimeout, &socket_factory_, &host_resolver_, nullptr /* proxy_delegate */,
diff --git a/net/socket/transport_client_socket_pool.cc b/net/socket/transport_client_socket_pool.cc index ef760d3..9ac3e121 100644 --- a/net/socket/transport_client_socket_pool.cc +++ b/net/socket/transport_client_socket_pool.cc
@@ -165,6 +165,7 @@ TransportClientSocketPool::TransportClientSocketPool( int max_sockets, int max_sockets_per_group, + base::TimeDelta unused_idle_socket_timeout, ClientSocketFactory* client_socket_factory, HostResolver* host_resolver, ProxyDelegate* proxy_delegate, @@ -183,7 +184,7 @@ : base_(this, max_sockets, max_sockets_per_group, - ClientSocketPool::unused_idle_socket_timeout(), + unused_idle_socket_timeout, ClientSocketPool::used_idle_socket_timeout(), new TransportConnectJobFactory( client_socket_factory,
diff --git a/net/socket/transport_client_socket_pool.h b/net/socket/transport_client_socket_pool.h index 29031d7..a70a0f2 100644 --- a/net/socket/transport_client_socket_pool.h +++ b/net/socket/transport_client_socket_pool.h
@@ -105,6 +105,7 @@ TransportClientSocketPool( int max_sockets, int max_sockets_per_group, + base::TimeDelta unused_idle_socket_timeout, ClientSocketFactory* client_socket_factory, HostResolver* host_resolver, ProxyDelegate* proxy_delegate,
diff --git a/net/socket/transport_client_socket_pool_unittest.cc b/net/socket/transport_client_socket_pool_unittest.cc index 806013d4..cc2cda85 100644 --- a/net/socket/transport_client_socket_pool_unittest.cc +++ b/net/socket/transport_client_socket_pool_unittest.cc
@@ -53,6 +53,8 @@ const int kMaxSockets = 32; const int kMaxSocketsPerGroup = 6; +constexpr base::TimeDelta kUnusedIdleSocketTimeout = + base::TimeDelta::FromSeconds(10); const RequestPriority kDefaultPriority = LOW; class SOCKS5MockData { @@ -96,6 +98,7 @@ client_socket_factory_(&net_log_), pool_(kMaxSockets, kMaxSocketsPerGroup, + kUnusedIdleSocketTimeout, &client_socket_factory_, host_resolver_.get(), nullptr /* proxy_delegate */, @@ -113,6 +116,7 @@ pool_for_real_sockets_( kMaxSockets, kMaxSocketsPerGroup, + kUnusedIdleSocketTimeout, ClientSocketFactory::GetDefaultFactory(), host_resolver_.get(), nullptr /* proxy_delegate */, @@ -447,9 +451,10 @@ TEST_F(TransportClientSocketPoolTest, RequestIgnoringLimitsIsNotReprioritized) { TransportClientSocketPool pool( - kMaxSockets, 1, &client_socket_factory_, host_resolver_.get(), - nullptr /* proxy_delegate */, nullptr /* cert_verifier */, - nullptr /* channel_id_server */, nullptr /* transport_security_state */, + kMaxSockets, 1, kUnusedIdleSocketTimeout, &client_socket_factory_, + host_resolver_.get(), nullptr /* proxy_delegate */, + nullptr /* cert_verifier */, nullptr /* channel_id_server */, + nullptr /* transport_security_state */, nullptr /* cert_transparency_verifier */, nullptr /* ct_policy_enforcer */, nullptr /* ssl_client_session_cache */, nullptr /* ssl_client_session_cache_privacy_mode */, @@ -1160,9 +1165,10 @@ for (IoMode socket_io_mode : {SYNCHRONOUS, ASYNC}) { MockTaggingClientSocketFactory socket_factory; TransportClientSocketPool pool( - kMaxSockets, kMaxSocketsPerGroup, &socket_factory, host_resolver_.get(), - nullptr /* proxy_delegate */, nullptr /* cert_verifier */, - nullptr /* channel_id_server */, nullptr /* transport_security_state */, + kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, + &socket_factory, host_resolver_.get(), nullptr /* proxy_delegate */, + nullptr /* cert_verifier */, nullptr /* channel_id_server */, + nullptr /* transport_security_state */, nullptr /* cert_transparency_verifier */, nullptr /* ct_policy_enforcer */, nullptr /* ssl_client_session_cache */, @@ -1211,7 +1217,7 @@ ASSERT_TRUE(test_server.Start()); TransportClientSocketPool pool( - kMaxSockets, kMaxSocketsPerGroup, + kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, ClientSocketFactory::GetDefaultFactory(), host_resolver_.get(), nullptr /* proxy_delegate */, nullptr /* cert_verifier */, nullptr /* channel_id_server */, nullptr /* transport_security_state */, @@ -1337,9 +1343,10 @@ host_resolver_->set_synchronous_mode(true); MockTaggingClientSocketFactory socket_factory; TransportClientSocketPool pool( - kMaxSockets, kMaxSocketsPerGroup, &socket_factory, host_resolver_.get(), - nullptr /* proxy_delegate */, nullptr /* cert_verifier */, - nullptr /* channel_id_server */, nullptr /* transport_security_state */, + kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, + &socket_factory, host_resolver_.get(), nullptr /* proxy_delegate */, + nullptr /* cert_verifier */, nullptr /* channel_id_server */, + nullptr /* transport_security_state */, nullptr /* cert_transparency_verifier */, nullptr /* ct_policy_enforcer */, nullptr /* ssl_client_session_cache */, nullptr /* ssl_client_session_cache_privacy_mode */,
diff --git a/net/socket/websocket_transport_client_socket_pool.cc b/net/socket/websocket_transport_client_socket_pool.cc index 113c2d1f..737e976 100644 --- a/net/socket/websocket_transport_client_socket_pool.cc +++ b/net/socket/websocket_transport_client_socket_pool.cc
@@ -29,6 +29,7 @@ WebSocketTransportClientSocketPool::WebSocketTransportClientSocketPool( int max_sockets, int max_sockets_per_group, + base::TimeDelta unused_idle_socket_timeout, ClientSocketFactory* client_socket_factory, HostResolver* host_resolver, ProxyDelegate* proxy_delegate, @@ -46,6 +47,7 @@ : TransportClientSocketPool( max_sockets, max_sockets_per_group, + unused_idle_socket_timeout, client_socket_factory, host_resolver, proxy_delegate,
diff --git a/net/socket/websocket_transport_client_socket_pool.h b/net/socket/websocket_transport_client_socket_pool.h index 56d9c50..0d33467 100644 --- a/net/socket/websocket_transport_client_socket_pool.h +++ b/net/socket/websocket_transport_client_socket_pool.h
@@ -45,6 +45,7 @@ WebSocketTransportClientSocketPool( int max_sockets, int max_sockets_per_group, + base::TimeDelta unused_idle_socket_timeout, ClientSocketFactory* client_socket_factory, HostResolver* host_resolver, ProxyDelegate* proxy_delegate,
diff --git a/net/socket/websocket_transport_client_socket_pool_unittest.cc b/net/socket/websocket_transport_client_socket_pool_unittest.cc index 8a2624d..6d6525a6 100644 --- a/net/socket/websocket_transport_client_socket_pool_unittest.cc +++ b/net/socket/websocket_transport_client_socket_pool_unittest.cc
@@ -44,6 +44,8 @@ const int kMaxSockets = 32; const int kMaxSocketsPerGroup = 6; +constexpr base::TimeDelta kUnusedIdleSocketTimeout = + base::TimeDelta::FromSeconds(10); const RequestPriority kDefaultPriority = LOW; // RunLoop doesn't support this natively but it is easy to emulate. @@ -69,6 +71,7 @@ client_socket_factory_(&net_log_), pool_(kMaxSockets, kMaxSocketsPerGroup, + kUnusedIdleSocketTimeout, &client_socket_factory_, host_resolver_.get(), nullptr /* proxy_delegate */, @@ -539,10 +542,10 @@ TEST_F(WebSocketTransportClientSocketPoolTest, IPv6FallbackSocketIPv4FinishesFirst) { WebSocketTransportClientSocketPool pool( - kMaxSockets, kMaxSocketsPerGroup, &client_socket_factory_, - host_resolver_.get(), nullptr /* proxy_delegate */, - nullptr /* cert_verifier */, nullptr /* channel_id_server */, - nullptr /* transport_security_state */, + kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, + &client_socket_factory_, host_resolver_.get(), + nullptr /* proxy_delegate */, nullptr /* cert_verifier */, + nullptr /* channel_id_server */, nullptr /* transport_security_state */, nullptr /* cert_transparency_verifier */, nullptr /* ct_policy_enforcer */, nullptr /* ssl_client_session_cache */, nullptr /* ssl_client_session_cache_privacy_mode */, @@ -585,10 +588,10 @@ TEST_F(WebSocketTransportClientSocketPoolTest, IPv6FallbackSocketIPv6FinishesFirst) { WebSocketTransportClientSocketPool pool( - kMaxSockets, kMaxSocketsPerGroup, &client_socket_factory_, - host_resolver_.get(), nullptr /* proxy_delegate */, - nullptr /* cert_verifier */, nullptr /* channel_id_server */, - nullptr /* transport_security_state */, + kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, + &client_socket_factory_, host_resolver_.get(), + nullptr /* proxy_delegate */, nullptr /* cert_verifier */, + nullptr /* channel_id_server */, nullptr /* transport_security_state */, nullptr /* cert_transparency_verifier */, nullptr /* ct_policy_enforcer */, nullptr /* ssl_client_session_cache */, nullptr /* ssl_client_session_cache_privacy_mode */, @@ -630,10 +633,10 @@ TEST_F(WebSocketTransportClientSocketPoolTest, IPv6NoIPv4AddressesToFallbackTo) { WebSocketTransportClientSocketPool pool( - kMaxSockets, kMaxSocketsPerGroup, &client_socket_factory_, - host_resolver_.get(), nullptr /* proxy_delegate */, - nullptr /* cert_verifier */, nullptr /* channel_id_server */, - nullptr /* transport_security_state */, + kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, + &client_socket_factory_, host_resolver_.get(), + nullptr /* proxy_delegate */, nullptr /* cert_verifier */, + nullptr /* channel_id_server */, nullptr /* transport_security_state */, nullptr /* cert_transparency_verifier */, nullptr /* ct_policy_enforcer */, nullptr /* ssl_client_session_cache */, nullptr /* ssl_client_session_cache_privacy_mode */, @@ -667,10 +670,10 @@ TEST_F(WebSocketTransportClientSocketPoolTest, IPv4HasNoFallback) { WebSocketTransportClientSocketPool pool( - kMaxSockets, kMaxSocketsPerGroup, &client_socket_factory_, - host_resolver_.get(), nullptr /* proxy_delegate */, - nullptr /* cert_verifier */, nullptr /* channel_id_server */, - nullptr /* transport_security_state */, + kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, + &client_socket_factory_, host_resolver_.get(), + nullptr /* proxy_delegate */, nullptr /* cert_verifier */, + nullptr /* channel_id_server */, nullptr /* transport_security_state */, nullptr /* cert_transparency_verifier */, nullptr /* ct_policy_enforcer */, nullptr /* ssl_client_session_cache */, nullptr /* ssl_client_session_cache_privacy_mode */, @@ -705,10 +708,10 @@ // proceeed immediately. TEST_F(WebSocketTransportClientSocketPoolTest, IPv6InstantFail) { WebSocketTransportClientSocketPool pool( - kMaxSockets, kMaxSocketsPerGroup, &client_socket_factory_, - host_resolver_.get(), nullptr /* proxy_delegate */, - nullptr /* cert_verifier */, nullptr /* channel_id_server */, - nullptr /* transport_security_state */, + kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, + &client_socket_factory_, host_resolver_.get(), + nullptr /* proxy_delegate */, nullptr /* cert_verifier */, + nullptr /* channel_id_server */, nullptr /* transport_security_state */, nullptr /* cert_transparency_verifier */, nullptr /* ct_policy_enforcer */, nullptr /* ssl_client_session_cache */, nullptr /* ssl_client_session_cache_privacy_mode */, @@ -747,10 +750,10 @@ // connections proceed immediately. TEST_F(WebSocketTransportClientSocketPoolTest, IPv6RapidFail) { WebSocketTransportClientSocketPool pool( - kMaxSockets, kMaxSocketsPerGroup, &client_socket_factory_, - host_resolver_.get(), nullptr /* proxy_delegate */, - nullptr /* cert_verifier */, nullptr /* channel_id_server */, - nullptr /* transport_security_state */, + kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, + &client_socket_factory_, host_resolver_.get(), + nullptr /* proxy_delegate */, nullptr /* cert_verifier */, + nullptr /* channel_id_server */, nullptr /* transport_security_state */, nullptr /* cert_transparency_verifier */, nullptr /* ct_policy_enforcer */, nullptr /* ssl_client_session_cache */, nullptr /* ssl_client_session_cache_privacy_mode */, @@ -797,10 +800,10 @@ // type do not race). TEST_F(WebSocketTransportClientSocketPoolTest, FirstSuccessWins) { WebSocketTransportClientSocketPool pool( - kMaxSockets, kMaxSocketsPerGroup, &client_socket_factory_, - host_resolver_.get(), nullptr /* proxy_delegate */, - nullptr /* cert_verifier */, nullptr /* channel_id_server */, - nullptr /* transport_security_state */, + kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, + &client_socket_factory_, host_resolver_.get(), + nullptr /* proxy_delegate */, nullptr /* cert_verifier */, + nullptr /* channel_id_server */, nullptr /* transport_security_state */, nullptr /* cert_transparency_verifier */, nullptr /* ct_policy_enforcer */, nullptr /* ssl_client_session_cache */, nullptr /* ssl_client_session_cache_privacy_mode */, @@ -841,10 +844,10 @@ // We should not report failure until all connections have failed. TEST_F(WebSocketTransportClientSocketPoolTest, LastFailureWins) { WebSocketTransportClientSocketPool pool( - kMaxSockets, kMaxSocketsPerGroup, &client_socket_factory_, - host_resolver_.get(), nullptr /* proxy_delegate */, - nullptr /* cert_verifier */, nullptr /* channel_id_server */, - nullptr /* transport_security_state */, + kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, + &client_socket_factory_, host_resolver_.get(), + nullptr /* proxy_delegate */, nullptr /* cert_verifier */, + nullptr /* channel_id_server */, nullptr /* transport_security_state */, nullptr /* cert_transparency_verifier */, nullptr /* ct_policy_enforcer */, nullptr /* ssl_client_session_cache */, nullptr /* ssl_client_session_cache_privacy_mode */, @@ -889,10 +892,10 @@ // want to run it. TEST_F(WebSocketTransportClientSocketPoolTest, DISABLED_OverallTimeoutApplies) { WebSocketTransportClientSocketPool pool( - kMaxSockets, kMaxSocketsPerGroup, &client_socket_factory_, - host_resolver_.get(), nullptr /* proxy_delegate */, - nullptr /* cert_verifier */, nullptr /* channel_id_server */, - nullptr /* transport_security_state */, + kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, + &client_socket_factory_, host_resolver_.get(), + nullptr /* proxy_delegate */, nullptr /* cert_verifier */, + nullptr /* channel_id_server */, nullptr /* transport_security_state */, nullptr /* cert_transparency_verifier */, nullptr /* ct_policy_enforcer */, nullptr /* ssl_client_session_cache */, nullptr /* ssl_client_session_cache_privacy_mode */,
diff --git a/net/third_party/quic/core/quic_config.cc b/net/third_party/quic/core/quic_config.cc index 23fe58e..510e0c9 100644 --- a/net/third_party/quic/core/quic_config.cc +++ b/net/third_party/quic/core/quic_config.cc
@@ -14,6 +14,7 @@ #include "net/third_party/quic/platform/api/quic_flag_utils.h" #include "net/third_party/quic/platform/api/quic_flags.h" #include "net/third_party/quic/platform/api/quic_logging.h" +#include "net/third_party/quic/platform/api/quic_macros.h" #include "net/third_party/quic/platform/api/quic_ptr_util.h" #include "net/third_party/quic/platform/api/quic_string.h" #include "net/third_party/quic/platform/api/quic_string_piece.h" @@ -492,7 +493,7 @@ } // TODO(ianswett) Use this for silent close on mobile, or delete. -void QuicConfig::SetSilentClose(bool silent_close) { +QUIC_UNUSED void QuicConfig::SetSilentClose(bool silent_close) { silent_close_.set(silent_close ? 1 : 0, silent_close ? 1 : 0); }
diff --git a/net/third_party/quic/core/quic_connection.cc b/net/third_party/quic/core/quic_connection.cc index 258d168..3889542f 100644 --- a/net/third_party/quic/core/quic_connection.cc +++ b/net/third_party/quic/core/quic_connection.cc
@@ -17,7 +17,6 @@ #include "base/format_macros.h" #include "base/macros.h" #include "base/metrics/histogram_macros.h" -#include "net/base/net_errors.h" #include "net/third_party/quic/core/crypto/crypto_protocol.h" #include "net/third_party/quic/core/crypto/quic_decrypter.h" #include "net/third_party/quic/core/crypto/quic_encrypter.h" @@ -30,6 +29,7 @@ #include "net/third_party/quic/core/quic_utils.h" #include "net/third_party/quic/platform/api/quic_bug_tracker.h" #include "net/third_party/quic/platform/api/quic_client_stats.h" +#include "net/third_party/quic/platform/api/quic_error_code_wrappers.h" #include "net/third_party/quic/platform/api/quic_exported_stats.h" #include "net/third_party/quic/platform/api/quic_flag_utils.h" #include "net/third_party/quic/platform/api/quic_flags.h" @@ -63,10 +63,6 @@ // One eighth RTT delay when doing ack decimation. const float kShortAckDecimationDelay = 0.125; -// Error code used in WriteResult to indicate that the packet writer rejected -// the message as being too big. -const int kMessageTooBigErrorCode = net::ERR_MSG_TOO_BIG; - // The minimum release time into future in ms. const int kMinReleaseTimeIntoFutureMs = 1; @@ -2386,8 +2382,7 @@ bool QuicConnection::IsMsgTooBig(const WriteResult& result) { return (result.status == WRITE_STATUS_MSG_TOO_BIG) || - (IsWriteError(result.status) && - result.error_code == kMessageTooBigErrorCode); + (IsWriteError(result.status) && result.error_code == QUIC_EMSGSIZE); } bool QuicConnection::ShouldDiscardPacket(const SerializedPacket& packet) { @@ -2422,7 +2417,7 @@ "Write failed with error: ", error_code, " (", strerror(error_code), ")"); QUIC_LOG_FIRST_N(ERROR, 2) << ENDPOINT << error_details; switch (error_code) { - case kMessageTooBigErrorCode: + case QUIC_EMSGSIZE: CloseConnection( QUIC_PACKET_WRITE_ERROR, error_details, ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET_WITH_NO_ACK);
diff --git a/net/third_party/quic/platform/api/quic_error_code_wrappers.h b/net/third_party/quic/platform/api/quic_error_code_wrappers.h new file mode 100644 index 0000000..2c03a15 --- /dev/null +++ b/net/third_party/quic/platform/api/quic_error_code_wrappers.h
@@ -0,0 +1,14 @@ +// Copyright (c) 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_THIRD_PARTY_QUIC_PLATFORM_API_QUIC_ERROR_CODE_WRAPPERS_H_ +#define NET_THIRD_PARTY_QUIC_PLATFORM_API_QUIC_ERROR_CODE_WRAPPERS_H_ + +#include "net/third_party/quic/platform/impl/quic_error_code_wrappers_impl.h" + +// TODO(vasilvv): ensure WRITE_STATUS_MSG_TOO_BIG works everywhere and remove +// this. +#define QUIC_EMSGSIZE QUIC_EMSGSIZE_IMPL + +#endif // NET_THIRD_PARTY_QUIC_PLATFORM_API_QUIC_ERROR_CODE_WRAPPERS_H_
diff --git a/net/third_party/quic/platform/api/quic_macros.h b/net/third_party/quic/platform/api/quic_macros.h new file mode 100644 index 0000000..d786df5 --- /dev/null +++ b/net/third_party/quic/platform/api/quic_macros.h
@@ -0,0 +1,13 @@ +// Copyright (c) 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_THIRD_PARTY_QUIC_PLATFORM_API_QUIC_MACROS_H_ +#define NET_THIRD_PARTY_QUIC_PLATFORM_API_QUIC_MACROS_H_ + +#include "net/third_party/quic/platform/impl/quic_macros_impl.h" + +#define QUIC_WARN_UNUSED_RESULT QUIC_MUST_USE_RESULT_IMPL +#define QUIC_UNUSED QUIC_UNUSED_IMPL + +#endif // NET_THIRD_PARTY_QUIC_PLATFORM_API_QUIC_MACROS_H_
diff --git a/net/third_party/quic/platform/impl/quic_error_code_wrappers_impl.h b/net/third_party/quic/platform/impl/quic_error_code_wrappers_impl.h new file mode 100644 index 0000000..387f6b9 --- /dev/null +++ b/net/third_party/quic/platform/impl/quic_error_code_wrappers_impl.h
@@ -0,0 +1,12 @@ +// Copyright (c) 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_ERROR_CODE_WRAPPERS_IMPL_H_ +#define NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_ERROR_CODE_WRAPPERS_IMPL_H_ + +#include "net/base/net_errors.h" + +#define QUIC_EMSGSIZE_IMPL net::ERR_MSG_TOO_BIG + +#endif // NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_ERROR_CODE_WRAPPERS_IMPL_H_
diff --git a/net/third_party/quic/platform/impl/quic_macros_impl.h b/net/third_party/quic/platform/impl/quic_macros_impl.h new file mode 100644 index 0000000..8d4d48a --- /dev/null +++ b/net/third_party/quic/platform/impl/quic_macros_impl.h
@@ -0,0 +1,13 @@ +// Copyright (c) 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_MACROS_IMPL_H_ +#define NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_MACROS_IMPL_H_ + +#include "base/compiler_specific.h" + +#define QUIC_MUST_USE_RESULT_IMPL WARN_UNUSED_RESULT +#define QUIC_UNUSED_IMPL ALLOW_UNUSED_TYPE + +#endif // NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_MACROS_IMPL_H_
diff --git a/net/third_party/quic/test_tools/packet_dropping_test_writer.h b/net/third_party/quic/test_tools/packet_dropping_test_writer.h index 0954858..5f7e6a19 100644 --- a/net/third_party/quic/test_tools/packet_dropping_test_writer.h +++ b/net/third_party/quic/test_tools/packet_dropping_test_writer.h
@@ -16,6 +16,7 @@ #include "net/third_party/quic/core/quic_alarm.h" #include "net/third_party/quic/core/quic_packet_writer_wrapper.h" #include "net/third_party/quic/platform/api/quic_clock.h" +#include "net/third_party/quic/platform/api/quic_macros.h" #include "net/third_party/quic/test_tools/quic_test_client.h" #include "net/third_party/quic/test_tools/quic_test_utils.h" @@ -121,7 +122,7 @@ } // Useful for reproducing very flaky issues. - void set_seed(uint64_t seed) { simple_random_.set_seed(seed); } + QUIC_UNUSED void set_seed(uint64_t seed) { simple_random_.set_seed(seed); } private: // Writes out the next packet to the contained writer and returns the time
diff --git a/net/third_party/quic/tools/quic_client_base.h b/net/third_party/quic/tools/quic_client_base.h index 17c86208..7b89b7c 100644 --- a/net/third_party/quic/tools/quic_client_base.h +++ b/net/third_party/quic/tools/quic_client_base.h
@@ -10,12 +10,12 @@ #include <string> -#include "base/macros.h" #include "net/third_party/quic/core/crypto/crypto_handshake.h" #include "net/third_party/quic/core/http/quic_client_push_promise_index.h" #include "net/third_party/quic/core/http/quic_spdy_client_session.h" #include "net/third_party/quic/core/http/quic_spdy_client_stream.h" #include "net/third_party/quic/core/quic_config.h" +#include "net/third_party/quic/platform/api/quic_macros.h" #include "net/third_party/quic/platform/api/quic_socket_address.h" #include "net/third_party/quic/platform/api/quic_string_piece.h" @@ -102,7 +102,7 @@ // Wait for events until the handshake is confirmed. // Returns true if the crypto handshake succeeds, false otherwise. - bool WaitForCryptoHandshakeConfirmed() WARN_UNUSED_RESULT; + bool WaitForCryptoHandshakeConfirmed() QUIC_WARN_UNUSED_RESULT; // Wait up to 50ms, and handle any events which occur. // Returns true if there are any outstanding requests.
diff --git a/services/BUILD.gn b/services/BUILD.gn index 6733c55..334b054b 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn
@@ -84,6 +84,7 @@ if (!is_ios) { test("services_perftests") { deps = [ + "//services/device:perftests", "//services/test:run_all_unittests", "//services/viz/public/cpp/compositing:perftests", ]
diff --git a/services/device/BUILD.gn b/services/device/BUILD.gn index 1e28c33..9bb21b45 100644 --- a/services/device/BUILD.gn +++ b/services/device/BUILD.gn
@@ -66,6 +66,24 @@ is_linux_without_udev = is_linux && !use_udev +source_set("perftests") { + testonly = true + + sources = [ + "geolocation/position_cache_impl_perftest.cc", + ] + + deps = [ + ":test_support", + "//base", + "//base/test:test_support", + "//services/device/geolocation", + "//services/device/geolocation:test_support", + "//testing/gtest", + "//testing/perf", + ] +} + source_set("tests") { testonly = true @@ -92,6 +110,7 @@ "geolocation/geolocation_service_unittest.cc", "geolocation/location_arbitrator_unittest.cc", "geolocation/network_location_provider_unittest.cc", + "geolocation/position_cache_impl_unittest.cc", "geolocation/public_ip_address_geolocator_unittest.cc", "geolocation/public_ip_address_location_notifier_unittest.cc", "geolocation/wifi_data_provider_chromeos_unittest.cc",
diff --git a/services/device/geolocation/BUILD.gn b/services/device/geolocation/BUILD.gn index 1f52214..ea8b7c7 100644 --- a/services/device/geolocation/BUILD.gn +++ b/services/device/geolocation/BUILD.gn
@@ -37,6 +37,9 @@ "network_location_provider.h", "network_location_request.cc", "network_location_request.h", + "position_cache.h", + "position_cache_impl.cc", + "position_cache_impl.h", "public_ip_address_geolocation_provider.cc", "public_ip_address_geolocation_provider.h", "public_ip_address_geolocator.cc", @@ -156,6 +159,10 @@ sources = [ "fake_location_provider.cc", "fake_location_provider.h", + "fake_position_cache.cc", + "fake_position_cache.h", + "position_cache_test_util.cc", + "position_cache_test_util.h", ] public_deps = [ ":geolocation",
diff --git a/services/device/geolocation/fake_position_cache.cc b/services/device/geolocation/fake_position_cache.cc new file mode 100644 index 0000000..7447bd0 --- /dev/null +++ b/services/device/geolocation/fake_position_cache.cc
@@ -0,0 +1,57 @@ +// 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 "services/device/geolocation/fake_position_cache.h" + +#include <algorithm> + +#include "services/device/geolocation/wifi_data.h" +#include "services/device/public/cpp/geolocation/geoposition.h" + +namespace device { +namespace { + +template <typename Set> +bool SetsEqual(const Set& lhs, const Set& rhs) { + // Since sets order elements via an operator, std::equal doesn't work. It + // would require elements to be equal-comparable. Check if symmetric + // difference is empty instead. + std::vector<typename Set::value_type> symmetric_difference; + std::set_symmetric_difference(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), + std::back_inserter(symmetric_difference), + typename Set::value_compare()); + return symmetric_difference.empty(); +} + +} // namespace + +FakePositionCache::FakePositionCache() = default; +FakePositionCache::~FakePositionCache() = default; + +void FakePositionCache::CachePosition(const WifiData& wifi_data, + const mojom::Geoposition& position) { + data.push_back(std::make_pair(wifi_data, position)); +} + +const mojom::Geoposition* FakePositionCache::FindPosition( + const WifiData& wifi_data) const { + auto it = std::find_if( + data.begin(), data.end(), [&wifi_data](const auto& candidate_pair) { + return SetsEqual(wifi_data.access_point_data, + candidate_pair.first.access_point_data); + }); + return it == data.end() ? nullptr : &(it->second); +} + +const mojom::Geoposition& FakePositionCache::GetLastUsedNetworkPosition() + const { + return last_used_position; +} + +void FakePositionCache::SetLastUsedNetworkPosition( + const mojom::Geoposition& position) { + last_used_position = position; +} + +} // namespace device
diff --git a/services/device/geolocation/fake_position_cache.h b/services/device/geolocation/fake_position_cache.h new file mode 100644 index 0000000..ec7c951e --- /dev/null +++ b/services/device/geolocation/fake_position_cache.h
@@ -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. + +#ifndef SERVICES_DEVICE_GEOLOCATION_FAKE_POSITION_CACHE_H_ +#define SERVICES_DEVICE_GEOLOCATION_FAKE_POSITION_CACHE_H_ + +#include <utility> +#include <vector> + +#include "base/macros.h" +#include "services/device/geolocation/position_cache.h" +#include "services/device/public/mojom/geoposition.mojom.h" + +namespace device { + +class FakePositionCache : public PositionCache { + public: + FakePositionCache(); + ~FakePositionCache() override; + + void CachePosition(const WifiData& wifi_data, + const mojom::Geoposition& position) override; + const mojom::Geoposition* FindPosition( + const WifiData& wifi_data) const override; + const mojom::Geoposition& GetLastUsedNetworkPosition() const override; + void SetLastUsedNetworkPosition(const mojom::Geoposition& position) override; + + private: + std::vector<std::pair<WifiData, mojom::Geoposition>> data; + mojom::Geoposition last_used_position; + DISALLOW_COPY_AND_ASSIGN(FakePositionCache); +}; + +} // namespace device + +#endif // SERVICES_DEVICE_GEOLOCATION_FAKE_POSITION_CACHE_H_
diff --git a/services/device/geolocation/geolocation_provider_impl.cc b/services/device/geolocation/geolocation_provider_impl.cc index 49b700a4..058933ca 100644 --- a/services/device/geolocation/geolocation_provider_impl.cc +++ b/services/device/geolocation/geolocation_provider_impl.cc
@@ -16,7 +16,10 @@ #include "base/memory/singleton.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/default_tick_clock.h" +#include "net/base/network_change_notifier.h" #include "services/device/geolocation/location_arbitrator.h" +#include "services/device/geolocation/position_cache_impl.h" #include "services/device/public/cpp/geolocation/geoposition.h" #include "services/network/public/cpp/shared_url_loader_factory.h" @@ -234,9 +237,13 @@ std::move(g_url_loader_factory_info.Get())); } + DCHECK(net::NetworkChangeNotifier::HasNetworkChangeNotifier()) + << "PositionCacheImpl needs a global NetworkChangeNotifier"; arbitrator_ = std::make_unique<LocationArbitrator>( g_custom_location_provider_callback.Get(), std::move(url_loader_factory), - g_api_key.Get()); + g_api_key.Get(), + std::make_unique<PositionCacheImpl>( + base::DefaultTickClock::GetInstance())); arbitrator_->SetUpdateCallback(callback); }
diff --git a/services/device/geolocation/geolocation_provider_impl.h b/services/device/geolocation/geolocation_provider_impl.h index 79cf0af..6e75055 100644 --- a/services/device/geolocation/geolocation_provider_impl.h +++ b/services/device/geolocation/geolocation_provider_impl.h
@@ -7,6 +7,7 @@ #include <list> #include <memory> +#include <string> #include <vector> #include "base/callback_forward.h"
diff --git a/services/device/geolocation/geolocation_service_unittest.cc b/services/device/geolocation/geolocation_service_unittest.cc index 3b514cb..3d69c7a6 100644 --- a/services/device/geolocation/geolocation_service_unittest.cc +++ b/services/device/geolocation/geolocation_service_unittest.cc
@@ -11,6 +11,7 @@ #include "chromeos/network/geolocation_handler.h" #endif #include "mojo/public/cpp/bindings/interface_ptr.h" +#include "net/base/network_change_notifier.h" #include "services/device/device_service_test_base.h" #include "services/device/geolocation/geolocation_provider_impl.h" #include "services/device/geolocation/network_location_request.h" @@ -42,7 +43,7 @@ chromeos::DBusThreadManager::Initialize(); chromeos::NetworkHandler::Initialize(); #endif - + network_change_notifier_.reset(net::NetworkChangeNotifier::CreateMock()); // We need to initialize the above *before* the base fixture instantiates // the device service. DeviceServiceTestBase::SetUp(); @@ -75,6 +76,7 @@ connector()->BindInterface(mojom::kServiceName, &geolocation_config_); } + std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_; mojom::GeolocationControlPtr geolocation_control_; mojom::GeolocationContextPtr geolocation_context_; mojom::GeolocationPtr geolocation_;
diff --git a/services/device/geolocation/location_arbitrator.cc b/services/device/geolocation/location_arbitrator.cc index 21ea659..24391a0 100644 --- a/services/device/geolocation/location_arbitrator.cc +++ b/services/device/geolocation/location_arbitrator.cc
@@ -27,12 +27,14 @@ LocationArbitrator::LocationArbitrator( const CustomLocationProviderCallback& custom_location_provider_getter, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - const std::string& api_key) + const std::string& api_key, + std::unique_ptr<PositionCache> position_cache) : custom_location_provider_getter_(custom_location_provider_getter), url_loader_factory_(url_loader_factory), api_key_(api_key), position_provider_(nullptr), is_permission_granted_(false), + position_cache_(std::move(position_cache)), is_running_(false) {} LocationArbitrator::~LocationArbitrator() { @@ -50,15 +52,6 @@ provider->OnPermissionGranted(); } -void LocationArbitrator::SetLastNetworkPosition( - const mojom::Geoposition& position) { - last_network_position_ = position; -} - -const mojom::Geoposition& LocationArbitrator::GetLastNetworkPosition() { - return last_network_position_; -} - void LocationArbitrator::StartProvider(bool enable_high_accuracy) { is_running_ = true; enable_high_accuracy_ = enable_high_accuracy; @@ -157,7 +150,7 @@ return nullptr; #else return std::make_unique<NetworkLocationProvider>( - std::move(url_loader_factory), api_key, this); + std::move(url_loader_factory), api_key, position_cache_.get()); #endif }
diff --git a/services/device/geolocation/location_arbitrator.h b/services/device/geolocation/location_arbitrator.h index 5d89450..eae4ee0 100644 --- a/services/device/geolocation/location_arbitrator.h +++ b/services/device/geolocation/location_arbitrator.h
@@ -7,6 +7,7 @@ #include <stdint.h> #include <memory> +#include <string> #include <vector> #include "base/callback_forward.h" @@ -16,6 +17,7 @@ #include "base/time/time.h" #include "services/device/geolocation/geolocation_provider_impl.h" #include "services/device/geolocation/network_location_provider.h" +#include "services/device/geolocation/position_cache.h" #include "services/device/public/cpp/geolocation/location_provider.h" #include "services/device/public/mojom/geoposition.mojom.h" #include "url/gurl.h" @@ -29,8 +31,7 @@ // This class is responsible for handling updates from multiple underlying // providers and resolving them to a single 'best' location fix at any given // moment. -class LocationArbitrator : public LocationProvider, - public NetworkLocationProvider::LastPositionCache { +class LocationArbitrator : public LocationProvider { public: // The TimeDelta newer a location provider has to be that it's worth // switching to this location provider on the basis of it being fresher @@ -42,7 +43,8 @@ LocationArbitrator( const CustomLocationProviderCallback& custom_location_provider_getter, const scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - const std::string& api_key); + const std::string& api_key, + std::unique_ptr<PositionCache> position_cache); ~LocationArbitrator() override; static GURL DefaultNetworkProviderURL(); @@ -56,10 +58,6 @@ const mojom::Geoposition& GetPosition() override; void OnPermissionGranted() override; - // NetworkLocationProvider::LastPositionCache implementation. - void SetLastNetworkPosition(const mojom::Geoposition& position) override; - const mojom::Geoposition& GetLastNetworkPosition() override; - protected: // These functions are useful for injection of dependencies in derived // testing classes. @@ -109,10 +107,7 @@ // The current best estimate of our position. mojom::Geoposition position_; - // The most recent position estimate returned by the network location - // provider. This must be preserved by LocationArbitrator so it is not lost - // when the provider is destroyed in StopProvider. - mojom::Geoposition last_network_position_; + std::unique_ptr<PositionCache> position_cache_; // Tracks whether providers should be running. bool is_running_;
diff --git a/services/device/geolocation/location_arbitrator_unittest.cc b/services/device/geolocation/location_arbitrator_unittest.cc index 08c61f5..2cbf5089 100644 --- a/services/device/geolocation/location_arbitrator_unittest.cc +++ b/services/device/geolocation/location_arbitrator_unittest.cc
@@ -11,6 +11,7 @@ #include "base/memory/ptr_util.h" #include "base/test/scoped_task_environment.h" #include "services/device/geolocation/fake_location_provider.h" +#include "services/device/geolocation/fake_position_cache.h" #include "services/device/public/cpp/geolocation/geoposition.h" #include "services/device/public/cpp/geolocation/location_provider.h" #include "services/device/public/mojom/geoposition.mojom.h" @@ -87,7 +88,8 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) : LocationArbitrator(provider_getter, std::move(url_loader_factory), - std::string() /* api_key */), + std::string() /* api_key */, + std::make_unique<FakePositionCache>()), cell_(nullptr), gps_(nullptr) { SetUpdateCallback(callback);
diff --git a/services/device/geolocation/network_location_provider.cc b/services/device/geolocation/network_location_provider.cc index c2f1ccd..99412f31 100644 --- a/services/device/geolocation/network_location_provider.cc +++ b/services/device/geolocation/network_location_provider.cc
@@ -13,6 +13,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "net/traffic_annotation/network_traffic_annotation.h" +#include "services/device/geolocation/position_cache.h" #include "services/device/public/cpp/geolocation/geoposition.h" #include "services/network/public/cpp/shared_url_loader_factory.h" @@ -28,88 +29,17 @@ const int kLastPositionMaxAgeSeconds = 10 * 60; // 10 minutes } // namespace -// static -const size_t NetworkLocationProvider::PositionCache::kMaximumSize = 10; - -NetworkLocationProvider::PositionCache::PositionCache() = default; - -NetworkLocationProvider::PositionCache::~PositionCache() = default; - -bool NetworkLocationProvider::PositionCache::CachePosition( - const WifiData& wifi_data, - const mojom::Geoposition& position) { - // Check that we can generate a valid key for the wifi data. - base::string16 key; - if (!MakeKey(wifi_data, &key)) { - return false; - } - // If the cache is full, remove the oldest entry. - if (cache_.size() == kMaximumSize) { - DCHECK(cache_age_list_.size() == kMaximumSize); - CacheAgeList::iterator oldest_entry = cache_age_list_.begin(); - DCHECK(oldest_entry != cache_age_list_.end()); - cache_.erase(*oldest_entry); - cache_age_list_.erase(oldest_entry); - } - DCHECK_LT(cache_.size(), kMaximumSize); - // Insert the position into the cache. - std::pair<CacheMap::iterator, bool> result = - cache_.insert(std::make_pair(key, position)); - if (!result.second) { - NOTREACHED(); // We never try to add the same key twice. - CHECK_EQ(cache_.size(), cache_age_list_.size()); - return false; - } - cache_age_list_.push_back(result.first); - DCHECK_EQ(cache_.size(), cache_age_list_.size()); - return true; -} - -// Searches for a cached position response for the current WiFi data. Returns -// the cached position if available, nullptr otherwise. -const mojom::Geoposition* NetworkLocationProvider::PositionCache::FindPosition( - const WifiData& wifi_data) { - base::string16 key; - if (!MakeKey(wifi_data, &key)) { - return nullptr; - } - CacheMap::const_iterator iter = cache_.find(key); - return iter == cache_.end() ? nullptr : &iter->second; -} - -// Makes the key for the map of cached positions, using the available data. -// Returns true if a good key was generated, false otherwise. -// -// static -bool NetworkLocationProvider::PositionCache::MakeKey(const WifiData& wifi_data, - base::string16* key) { - // Currently we use only WiFi data and base the key only on the MAC addresses. - DCHECK(key); - key->clear(); - const size_t kCharsPerMacAddress = 6 * 3 + 1; // e.g. "11:22:33:44:55:66|" - key->reserve(wifi_data.access_point_data.size() * kCharsPerMacAddress); - const base::string16 separator(base::ASCIIToUTF16("|")); - for (const auto& access_point_data : wifi_data.access_point_data) { - *key += separator; - *key += access_point_data.mac_address; - *key += separator; - } - // If the key is the empty string, return false, as we don't want to cache a - // position for such data. - return !key->empty(); -} - // NetworkLocationProvider NetworkLocationProvider::NetworkLocationProvider( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const std::string& api_key, - LastPositionCache* last_position_cache) + PositionCache* position_cache) : wifi_data_provider_manager_(nullptr), wifi_data_update_callback_( base::Bind(&NetworkLocationProvider::OnWifiDataUpdate, base::Unretained(this))), is_wifi_data_complete_(false), - last_position_delegate_(last_position_cache), + position_cache_(position_cache), is_permission_granted_(false), is_new_data_available_(false), request_(new NetworkLocationRequest( @@ -117,9 +47,8 @@ api_key, base::Bind(&NetworkLocationProvider::OnLocationResponse, base::Unretained(this)))), - position_cache_(new PositionCache), weak_factory_(this) { - DCHECK(last_position_delegate_); + DCHECK(position_cache_); } NetworkLocationProvider::~NetworkLocationProvider() { @@ -174,14 +103,13 @@ const WifiData& wifi_data) { DCHECK(thread_checker_.CalledOnValidThread()); // Record the position and update our cache. - last_position_delegate_->SetLastNetworkPosition(position); + position_cache_->SetLastUsedNetworkPosition(position); if (ValidateGeoposition(position)) position_cache_->CachePosition(wifi_data, position); // Let listeners know that we now have a position available. if (!location_provider_update_callback_.is_null()) { - location_provider_update_callback_.Run( - this, last_position_delegate_->GetLastNetworkPosition()); + location_provider_update_callback_.Run(this, position); } } @@ -214,7 +142,7 @@ } const mojom::Geoposition& NetworkLocationProvider::GetPosition() { - return last_position_delegate_->GetLastNetworkPosition(); + return position_cache_->GetLastUsedNetworkPosition(); } void NetworkLocationProvider::RequestPosition() { @@ -230,7 +158,7 @@ // there is no pending network request), report the last network position // estimate as if it were a fresh estimate. const mojom::Geoposition& last_position = - last_position_delegate_->GetLastNetworkPosition(); + position_cache_->GetLastUsedNetworkPosition(); if (!is_new_data_available_ && !request_->is_request_pending() && ValidateGeoposition(last_position)) { base::Time now = base::Time::Now(); @@ -261,7 +189,7 @@ is_new_data_available_ = false; // Record the position. - last_position_delegate_->SetLastNetworkPosition(position); + position_cache_->SetLastUsedNetworkPosition(position); // Let listeners know that we now have a position available. if (!location_provider_update_callback_.is_null())
diff --git a/services/device/geolocation/network_location_provider.h b/services/device/geolocation/network_location_provider.h index 75878bb..5229664 100644 --- a/services/device/geolocation/network_location_provider.h +++ b/services/device/geolocation/network_location_provider.h
@@ -10,6 +10,7 @@ #include <list> #include <map> #include <memory> +#include <string> #include "base/macros.h" #include "base/memory/ref_counted.h" @@ -23,60 +24,13 @@ #include "services/device/public/mojom/geoposition.mojom.h" namespace device { - +class PositionCache; class NetworkLocationProvider : public LocationProvider { public: - // To ensure the last-used position estimate can be preserved when the network - // location provider is torn down, a delegate manages the state of the cached - // position estimate outside of this provider. - class LastPositionCache { - public: - virtual ~LastPositionCache() = default; - virtual void SetLastNetworkPosition( - const mojom::Geoposition& new_position) = 0; - virtual const mojom::Geoposition& GetLastNetworkPosition() = 0; - }; - - // Cache of recently resolved locations, keyed by the set of unique WiFi APs - // used in the network query. Public for tests. - class PositionCache { - public: - // The maximum size of the cache of positions. - static const size_t kMaximumSize; - - PositionCache(); - ~PositionCache(); - - // Caches the current position response for the current set of cell ID and - // WiFi data. In the case of the cache exceeding kMaximumSize this will - // evict old entries in FIFO orderer of being added. - // Returns true on success, false otherwise. - bool CachePosition(const WifiData& wifi_data, - const mojom::Geoposition& position); - - // Searches for a cached position response for the current set of data. - // Returns NULL if the position is not in the cache, or the cached - // position if available. Ownership remains with the cache. - const mojom::Geoposition* FindPosition(const WifiData& wifi_data); - - private: - // Makes the key for the map of cached positions, using a set of - // data. Returns true if a good key was generated, false otherwise. - static bool MakeKey(const WifiData& wifi_data, base::string16* key); - - // The cache of positions. This is stored as a map keyed on a string that - // represents a set of data, and a list to provide - // least-recently-added eviction. - typedef std::map<base::string16, mojom::Geoposition> CacheMap; - CacheMap cache_; - typedef std::list<CacheMap::iterator> CacheAgeList; - CacheAgeList cache_age_list_; // Oldest first. - }; - NetworkLocationProvider( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const std::string& api_key, - LastPositionCache* last_position_cache); + PositionCache* position_cache); ~NetworkLocationProvider() override; // LocationProvider implementation @@ -113,9 +67,7 @@ // The timestamp for the latest wifi data update. base::Time wifi_timestamp_; - // A delegate to manage the current best network position estimate. Must not - // be nullptr. - LastPositionCache* const last_position_delegate_; + PositionCache* const position_cache_; LocationProvider::LocationProviderUpdateCallback location_provider_update_callback_; @@ -128,9 +80,6 @@ // The network location request object. const std::unique_ptr<NetworkLocationRequest> request_; - // The cache of positions. - const std::unique_ptr<PositionCache> position_cache_; - base::ThreadChecker thread_checker_; base::WeakPtrFactory<NetworkLocationProvider> weak_factory_;
diff --git a/services/device/geolocation/network_location_provider_unittest.cc b/services/device/geolocation/network_location_provider_unittest.cc index 24dae46b..abf6e87 100644 --- a/services/device/geolocation/network_location_provider_unittest.cc +++ b/services/device/geolocation/network_location_provider_unittest.cc
@@ -8,6 +8,7 @@ #include <memory> #include <string> +#include <utility> #include <vector> #include "base/bind.h" @@ -22,6 +23,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "net/base/net_errors.h" +#include "services/device/geolocation/fake_position_cache.h" #include "services/device/geolocation/location_arbitrator.h" #include "services/device/geolocation/wifi_data_provider.h" #include "services/device/public/cpp/geolocation/geoposition.h" @@ -107,21 +109,6 @@ DISALLOW_COPY_AND_ASSIGN(MockWifiDataProvider); }; -// An implementation of LastPositionCache. -class TestLastPositionCache - : public NetworkLocationProvider::LastPositionCache { - public: - void SetLastNetworkPosition(const mojom::Geoposition& position) override { - last_network_position_ = position; - } - const mojom::Geoposition& GetLastNetworkPosition() override { - return last_network_position_; - } - - private: - mojom::Geoposition last_network_position_; -}; - MockWifiDataProvider* MockWifiDataProvider::instance_ = nullptr; // Main test fixture @@ -131,11 +118,12 @@ WifiDataProviderManager::ResetFactoryForTesting(); } - LocationProvider* CreateProvider(bool set_permission_granted, - const std::string& api_key = std::string()) { - LocationProvider* provider = new NetworkLocationProvider( + std::unique_ptr<LocationProvider> CreateProvider( + bool set_permission_granted, + const std::string& api_key = std::string()) { + auto provider = std::make_unique<NetworkLocationProvider>( test_url_loader_factory_.GetSafeWeakWrapper(), api_key, - last_position_cache_.get()); + &position_cache_); if (set_permission_granted) provider->OnPermissionGranted(); return provider; @@ -143,8 +131,7 @@ protected: GeolocationNetworkProviderTest() - : wifi_data_provider_(MockWifiDataProvider::CreateInstance()), - last_position_cache_(std::make_unique<TestLastPositionCache>()) { + : wifi_data_provider_(MockWifiDataProvider::CreateInstance()) { // TODO(joth): Really these should be in SetUp, not here, but they take no // effect on Mac OS Release builds if done there. I kid not. Figure out why. WifiDataProviderManager::SetFactoryForTesting( @@ -287,8 +274,7 @@ const base::MessageLoop main_message_loop_; network::TestURLLoaderFactory test_url_loader_factory_; const scoped_refptr<MockWifiDataProvider> wifi_data_provider_; - std::unique_ptr<NetworkLocationProvider::LastPositionCache> - last_position_cache_; + FakePositionCache position_cache_; }; // Tests that fixture members were SetUp correctly. @@ -524,32 +510,6 @@ CheckRequestIsValid(kScanCount, 0); } -// Tests that the provider's position cache correctly caches each item, and -// begins evicting the oldest entries in order once it reaches its maximum size. -TEST_F(GeolocationNetworkProviderTest, NetworkPositionCache) { - NetworkLocationProvider::PositionCache cache; - - const int kCacheSize = NetworkLocationProvider::PositionCache::kMaximumSize; - for (int i = 1; i < kCacheSize * 2 + 1; ++i) { - mojom::Geoposition pos = CreateReferencePosition(i); - bool ret = cache.CachePosition(CreateReferenceWifiScanData(i), pos); - EXPECT_TRUE(ret) << i; - const mojom::Geoposition* item = - cache.FindPosition(CreateReferenceWifiScanData(i)); - ASSERT_TRUE(item) << i; - EXPECT_EQ(pos.latitude, item->latitude) << i; - EXPECT_EQ(pos.longitude, item->longitude) << i; - if (i <= kCacheSize) { - // Nothing should have spilled yet; check oldest item is still there. - EXPECT_TRUE(cache.FindPosition(CreateReferenceWifiScanData(1))); - } else { - const int evicted = i - kCacheSize; - EXPECT_FALSE(cache.FindPosition(CreateReferenceWifiScanData(evicted))); - EXPECT_TRUE(cache.FindPosition(CreateReferenceWifiScanData(evicted + 1))); - } - } -} - // Tests that the provider's last position cache delegate is correctly used to // cache the most recent network position estimate, and that this estimate is // not lost when the provider is torn down and recreated. @@ -562,7 +522,7 @@ EXPECT_FALSE(ValidateGeoposition(position)); // Check that the cached value is also invalid. - position = last_position_cache_->GetLastNetworkPosition(); + position = position_cache_.GetLastUsedNetworkPosition(); EXPECT_FALSE(ValidateGeoposition(position)); // Now wifi data arrives -- SetData will notify listeners. @@ -601,7 +561,7 @@ provider = nullptr; // The cache preserves the last estimate while the provider is inactive. - position = last_position_cache_->GetLastNetworkPosition(); + position = position_cache_.GetLastUsedNetworkPosition(); EXPECT_EQ(51.0, position.latitude); EXPECT_EQ(-0.1, position.longitude); EXPECT_EQ(1200.4, position.accuracy); @@ -609,7 +569,7 @@ EXPECT_TRUE(ValidateGeoposition(position)); // Restart the provider. - provider.reset(CreateProvider(true)); + provider = CreateProvider(true); provider->StartProvider(false); // Check that the most recent position estimate is retained. @@ -632,7 +592,7 @@ // timestamp set to the current time. mojom::Geoposition last_position = CreateReferencePosition(0); EXPECT_TRUE(ValidateGeoposition(last_position)); - last_position_cache_->SetLastNetworkPosition(last_position); + position_cache_.SetLastUsedNetworkPosition(last_position); // Simulate no initial wifi data. wifi_data_provider_->set_got_data(false); @@ -676,7 +636,7 @@ last_position.timestamp = base::Time::Now() - base::TimeDelta::FromMinutes(20); EXPECT_TRUE(ValidateGeoposition(last_position)); - last_position_cache_->SetLastNetworkPosition(last_position); + position_cache_.SetLastUsedNetworkPosition(last_position); // Simulate no initial wifi data. wifi_data_provider_->set_got_data(false); @@ -712,7 +672,7 @@ // of the cached position is set to the current time. mojom::Geoposition last_position = CreateReferencePosition(0); EXPECT_TRUE(ValidateGeoposition(last_position)); - last_position_cache_->SetLastNetworkPosition(last_position); + position_cache_.SetLastUsedNetworkPosition(last_position); // Simulate a completed wifi scan. const int kFirstScanAps = 6;
diff --git a/services/device/geolocation/position_cache.h b/services/device/geolocation/position_cache.h new file mode 100644 index 0000000..eae8d57 --- /dev/null +++ b/services/device/geolocation/position_cache.h
@@ -0,0 +1,45 @@ +// 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 SERVICES_DEVICE_GEOLOCATION_POSITION_CACHE_H_ +#define SERVICES_DEVICE_GEOLOCATION_POSITION_CACHE_H_ + +namespace device { +namespace mojom { +class Geoposition; +} // namespace mojom + +struct WifiData; + +// Cache of recently resolved locations, keyed by the set of unique WiFi APs +// used in the network query. +class PositionCache { + public: + virtual ~PositionCache() = default; + + // Caches the current position response for the current set of cell ID and + // WiFi data. In the case of the cache exceeding an implementation-defined + // maximum size this will evict old entries in FIFO orderer of being added. + virtual void CachePosition(const WifiData& wifi_data, + const mojom::Geoposition& position) = 0; + + // Searches for a cached position response for the current set of data. + // Returns nullptr if the position is not in the cache, or the cached + // position if available. Ownership remains with the cache. Do not store + // the pointer, treat it as an iterator into the cache's internals. + virtual const mojom::Geoposition* FindPosition( + const WifiData& wifi_data) const = 0; + + // Returns most recently used position, or an invalid Geoposition if + // SetLastUsedNetworkPosition wasn't called yet. + virtual const mojom::Geoposition& GetLastUsedNetworkPosition() const = 0; + + // Stores the most recently used position. + virtual void SetLastUsedNetworkPosition( + const mojom::Geoposition& position) = 0; +}; + +} // namespace device + +#endif // SERVICES_DEVICE_GEOLOCATION_POSITION_CACHE_H_
diff --git a/services/device/geolocation/position_cache_impl.cc b/services/device/geolocation/position_cache_impl.cc new file mode 100644 index 0000000..11cf0798 --- /dev/null +++ b/services/device/geolocation/position_cache_impl.cc
@@ -0,0 +1,108 @@ +// 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 "services/device/geolocation/position_cache_impl.h" + +#include <algorithm> + +#include "base/strings/utf_string_conversions.h" +#include "services/device/geolocation/wifi_data.h" +#include "services/device/public/mojom/geoposition.mojom.h" + +namespace device { + +// static +const size_t PositionCacheImpl::kMaximumSize = 10; +// static +const base::TimeDelta PositionCacheImpl::kMaximumLifetime = + base::TimeDelta::FromDays(1); + +PositionCacheImpl::CacheEntry::CacheEntry( + const Hash& hash, + const mojom::Geoposition& position, + std::unique_ptr<base::OneShotTimer> eviction_timer) + : hash_(hash), + position_(position), + eviction_timer_(std::move(eviction_timer)) {} +PositionCacheImpl::CacheEntry::~CacheEntry() = default; +PositionCacheImpl::CacheEntry::CacheEntry(CacheEntry&&) = default; +PositionCacheImpl::CacheEntry& PositionCacheImpl::CacheEntry::operator=( + CacheEntry&&) = default; + +// static +PositionCacheImpl::Hash PositionCacheImpl::MakeKey(const WifiData& wifi_data) { + // Currently we use only WiFi data and base the key only on the MAC addresses. + base::string16 key; + const size_t kCharsPerMacAddress = 6 * 3 + 1; // e.g. "11:22:33:44:55:66|" + key.reserve(wifi_data.access_point_data.size() * kCharsPerMacAddress); + const base::string16 separator(base::ASCIIToUTF16("|")); + for (const auto& access_point_data : wifi_data.access_point_data) { + key += separator; + key += access_point_data.mac_address; + key += separator; + } + return key; +} + +PositionCacheImpl::PositionCacheImpl(const base::TickClock* clock) + : clock_(clock) { + net::NetworkChangeNotifier::AddNetworkChangeObserver(this); +} + +PositionCacheImpl::~PositionCacheImpl() { + net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); +} + +void PositionCacheImpl::CachePosition(const WifiData& wifi_data, + const mojom::Geoposition& position) { + const Hash key = MakeKey(wifi_data); + + // If the cache is full, remove the oldest entry. + if (data_.size() == kMaximumSize) + data_.erase(data_.begin()); + + DCHECK_LT(data_.size(), kMaximumSize); + + auto eviction_timer = std::make_unique<base::OneShotTimer>(clock_); + // Ensure that the entry we're adding will be evicted after kMaximumLifetime. + // base::Unretained safe because the timer is indirectly owned by |this|. + eviction_timer->Start(FROM_HERE, kMaximumLifetime, + base::BindOnce(&PositionCacheImpl::EvictEntry, + base::Unretained(this), key)); + + data_.emplace_back(key, position, std::move(eviction_timer)); +} + +const mojom::Geoposition* PositionCacheImpl::FindPosition( + const WifiData& wifi_data) const { + const Hash key = MakeKey(wifi_data); + auto it = std::find(data_.begin(), data_.end(), key); + return it == data_.end() ? nullptr : (it->position()); +} + +const mojom::Geoposition& PositionCacheImpl::GetLastUsedNetworkPosition() + const { + return last_used_position_; +} + +void PositionCacheImpl::SetLastUsedNetworkPosition( + const mojom::Geoposition& position) { + last_used_position_ = position; +} + +void PositionCacheImpl::OnNetworkChanged( + net::NetworkChangeNotifier::ConnectionType) { + // OnNetworkChanged is called " when a change occurs to the host + // computer's hardware or software that affects the route network packets + // take to any network server.". This means that whatever position we had + // stored for a wired connection (empty WifiData) could have become stale. + EvictEntry(MakeKey(WifiData())); + last_used_position_ = {}; +} + +void PositionCacheImpl::EvictEntry(const Hash& hash) { + data_.erase(std::remove(data_.begin(), data_.end(), hash), data_.end()); +} + +} // namespace device
diff --git a/services/device/geolocation/position_cache_impl.h b/services/device/geolocation/position_cache_impl.h new file mode 100644 index 0000000..1ee5a1fe --- /dev/null +++ b/services/device/geolocation/position_cache_impl.h
@@ -0,0 +1,89 @@ +// 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 SERVICES_DEVICE_GEOLOCATION_POSITION_CACHE_IMPL_H_ +#define SERVICES_DEVICE_GEOLOCATION_POSITION_CACHE_IMPL_H_ + +#include <memory> +#include <utility> +#include <vector> + +#include "base/macros.h" +#include "base/strings/string16.h" +#include "base/time/time.h" +#include "base/timer/timer.h" +#include "net/base/network_change_notifier.h" +#include "services/device/geolocation/position_cache.h" +#include "services/device/public/mojom/geoposition.mojom.h" + +namespace base { +class TickClock; +} // namespace base + +namespace device { + +class PositionCacheImpl + : public PositionCache, + public net::NetworkChangeNotifier::NetworkChangeObserver { + public: + // The maximum size of the cache of positions. + static const size_t kMaximumSize; + // The maximum time an entry can reside in cache before forced eviction. + // This is to ensure the user's location cannot be tracked arbitrarily far + // back in history. + static const base::TimeDelta kMaximumLifetime; + + // |clock| is used to measure time left until kMaximumLifetime. + explicit PositionCacheImpl(const base::TickClock* clock); + ~PositionCacheImpl() override; + + void CachePosition(const WifiData& wifi_data, + const mojom::Geoposition& position) override; + + const mojom::Geoposition* FindPosition( + const WifiData& wifi_data) const override; + + const mojom::Geoposition& GetLastUsedNetworkPosition() const override; + void SetLastUsedNetworkPosition(const mojom::Geoposition& position) override; + + // net::NetworkChangeNotifier::NetworkChangeObserver + void OnNetworkChanged( + net::NetworkChangeNotifier::ConnectionType type) override; + + private: + // In order to avoid O(N) comparisons while searching for the right WifiData, + // we hash the contents of those objects and use the hashes as cache keys. + using Hash = base::string16; + + class CacheEntry { + public: + CacheEntry(const Hash& hash, + const mojom::Geoposition& position, + std::unique_ptr<base::OneShotTimer> eviction_timer); + ~CacheEntry(); + CacheEntry(CacheEntry&&); + CacheEntry& operator=(CacheEntry&&); + + inline bool operator==(const Hash& hash) const { return hash_ == hash; } + const mojom::Geoposition* position() const { return &position_; } + + private: + Hash hash_; + mojom::Geoposition position_; + std::unique_ptr<base::OneShotTimer> eviction_timer_; + DISALLOW_COPY_AND_ASSIGN(CacheEntry); + }; + + static Hash MakeKey(const WifiData& wifi_data); + void EvictEntry(const Hash& hash); + + const base::TickClock* clock_; + std::vector<CacheEntry> data_; + mojom::Geoposition last_used_position_; + DISALLOW_COPY_AND_ASSIGN(PositionCacheImpl); +}; + +} // namespace device + +#endif // SERVICES_DEVICE_GEOLOCATION_POSITION_CACHE_IMPL_H_
diff --git a/services/device/geolocation/position_cache_impl_perftest.cc b/services/device/geolocation/position_cache_impl_perftest.cc new file mode 100644 index 0000000..f0f74826 --- /dev/null +++ b/services/device/geolocation/position_cache_impl_perftest.cc
@@ -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. + +#include "services/device/geolocation/position_cache_impl.h" + +#include <memory> +#include <utility> + +#include "base/strings/string_number_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_task_environment.h" +#include "base/time/time.h" +#include "services/device/geolocation/position_cache_test_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/perf/perf_test.h" + +namespace device { + +class PositionCacheImplPerfTest : public ::testing::Test { + public: + PositionCacheImplPerfTest() + : task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME), + cache_(task_environment_.GetMockTickClock()) {} + + void SetUp() override { + data_.reserve(kBatchSize); + for (size_t i = 0; i < kBatchSize; ++i) + data_.push_back(std::make_pair(testing::CreateDefaultUniqueWifiData(), + testing::CreateGeoposition(i % 90))); + } + + protected: + static constexpr size_t kBatchSize = 5000; + std::vector<std::pair<WifiData, mojom::Geoposition>> data_; + base::test::ScopedTaskEnvironment task_environment_; + PositionCacheImpl cache_; +}; + +TEST_F(PositionCacheImplPerfTest, Adding) { + base::Time start = base::Time::Now(); + for (const auto& pair : data_) + cache_.CachePosition(pair.first, pair.second); + base::Time end = base::Time::Now(); + perf_test::PrintResult("adding_to_cache", "", "", + base::TimeDelta(end - start).InMillisecondsF(), + "ms per batch", true); +} + +TEST_F(PositionCacheImplPerfTest, Finding) { + for (const auto& pair : data_) + cache_.CachePosition(pair.first, pair.second); + base::Time start = base::Time::Now(); + for (const auto& pair : data_) + cache_.FindPosition(pair.first); + base::Time end = base::Time::Now(); + perf_test::PrintResult("finding_in_cache", "", "", + base::TimeDelta(end - start).InMillisecondsF(), + "ms per batch", true); +} +} // namespace device
diff --git a/services/device/geolocation/position_cache_impl_unittest.cc b/services/device/geolocation/position_cache_impl_unittest.cc new file mode 100644 index 0000000..1d7a605 --- /dev/null +++ b/services/device/geolocation/position_cache_impl_unittest.cc
@@ -0,0 +1,201 @@ +// 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 "services/device/geolocation/position_cache_impl.h" + +#include <memory> +#include <utility> + +#include "base/strings/string_number_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_task_environment.h" +#include "net/base/network_change_notifier.h" +#include "services/device/geolocation/position_cache_test_util.h" +#include "services/device/public/cpp/geolocation/geoposition.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace device { + +class PositionCacheImplTest : public ::testing::Test { + public: + PositionCacheImplTest() + : task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME), + network_change_notifier_(net::NetworkChangeNotifier::CreateMock()), + cache_(task_environment_.GetMockTickClock()) {} + + protected: + base::test::ScopedTaskEnvironment task_environment_; + std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_; + PositionCacheImpl cache_; +}; + +TEST_F(PositionCacheImplTest, EmptyCacheReturnsNoLocations) { + WifiData empty_wifi_data; + EXPECT_EQ(nullptr, cache_.FindPosition(empty_wifi_data)); +} + +TEST_F(PositionCacheImplTest, CanAddEmptyWifiData) { + WifiData empty_wifi_data; + mojom::Geoposition geoposition = testing::CreateGeoposition(1); + cache_.CachePosition(empty_wifi_data, geoposition); + + const mojom::Geoposition* found_position = + cache_.FindPosition(empty_wifi_data); + ASSERT_NE(nullptr, found_position); + EXPECT_TRUE(geoposition.Equals(*found_position)); +} + +TEST_F(PositionCacheImplTest, FirstAddedWifiDataReturned) { + WifiData wifi_data = testing::CreateDefaultUniqueWifiData(); + mojom::Geoposition geoposition = testing::CreateGeoposition(1); + cache_.CachePosition(wifi_data, geoposition); + + const mojom::Geoposition* found_position = cache_.FindPosition(wifi_data); + ASSERT_NE(nullptr, found_position); + EXPECT_TRUE(geoposition.Equals(*found_position)); +} + +TEST_F(PositionCacheImplTest, LastAddedWifiDataReturned) { + cache_.CachePosition(testing::CreateDefaultUniqueWifiData(), + testing::CreateGeoposition(1)); + cache_.CachePosition(testing::CreateDefaultUniqueWifiData(), + testing::CreateGeoposition(2)); + + WifiData final_wifi_data = testing::CreateDefaultUniqueWifiData(); + mojom::Geoposition final_geoposition = testing::CreateGeoposition(5); + cache_.CachePosition(final_wifi_data, final_geoposition); + + const mojom::Geoposition* found_position = + cache_.FindPosition(final_wifi_data); + ASSERT_NE(nullptr, found_position); + EXPECT_TRUE(final_geoposition.Equals(*found_position)); +} + +TEST_F(PositionCacheImplTest, MaxPositionsFound) { + std::vector<std::pair<WifiData, mojom::Geoposition>> test_data; + for (size_t i = 0; i < PositionCacheImpl::kMaximumSize; ++i) { + test_data.push_back(std::make_pair(testing::CreateDefaultUniqueWifiData(), + testing::CreateGeoposition(i))); + } + + // Populate the cache + for (const auto& test_data_pair : test_data) { + cache_.CachePosition(test_data_pair.first, test_data_pair.second); + } + // Make sure all elements are cached. + for (const auto& test_data_pair : test_data) { + const mojom::Geoposition* found_position = + cache_.FindPosition(test_data_pair.first); + ASSERT_NE(nullptr, found_position); + EXPECT_TRUE(test_data_pair.second.Equals(*found_position)); + } +} + +TEST_F(PositionCacheImplTest, Eviction) { + WifiData initial_wifi_data = testing::CreateDefaultUniqueWifiData(); + mojom::Geoposition initial_geoposition = testing::CreateGeoposition(1); + cache_.CachePosition(initial_wifi_data, initial_geoposition); + + // Add as many entries as the cache's size limit, which should evict + // |initial_wifi_data|. + for (size_t i = 0; i < PositionCacheImpl::kMaximumSize; ++i) { + cache_.CachePosition(testing::CreateDefaultUniqueWifiData(), + testing::CreateGeoposition(i)); + } + + // |initial_wifi_data| can no longer be found in cache_. + ASSERT_EQ(nullptr, cache_.FindPosition(initial_wifi_data)); +} + +TEST_F(PositionCacheImplTest, LastUsedPositionRemembered) { + // Initially, invalid. + EXPECT_FALSE(ValidateGeoposition(cache_.GetLastUsedNetworkPosition())); + // Remembered after setting. + mojom::Geoposition position = testing::CreateGeoposition(4); + cache_.SetLastUsedNetworkPosition(position); + EXPECT_TRUE(position.Equals(cache_.GetLastUsedNetworkPosition())); +} + +TEST_F(PositionCacheImplTest, EntryEvictedAfterMaxLifetimeReached) { + WifiData initial_wifi_data = testing::CreateDefaultUniqueWifiData(); + mojom::Geoposition initial_geoposition = testing::CreateGeoposition(1); + cache_.CachePosition(initial_wifi_data, initial_geoposition); + + // Initially, the position is there. + const mojom::Geoposition* found_position = + cache_.FindPosition(initial_wifi_data); + ASSERT_NE(nullptr, found_position); + EXPECT_TRUE(initial_geoposition.Equals(*found_position)); + + task_environment_.FastForwardBy(PositionCacheImpl::kMaximumLifetime); + + // Position was evicted. + EXPECT_EQ(nullptr, cache_.FindPosition(initial_wifi_data)); +} + +TEST_F(PositionCacheImplTest, OnlyOldEntriesEvicted) { + WifiData older_wifi_data = testing::CreateDefaultUniqueWifiData(); + mojom::Geoposition older_geoposition = testing::CreateGeoposition(1); + cache_.CachePosition(older_wifi_data, older_geoposition); + + // Some time passes, but less than kMaximumLifetime + task_environment_.FastForwardBy(PositionCacheImpl::kMaximumLifetime * 0.5); + + // Old position is still there. + const mojom::Geoposition* found_position = + cache_.FindPosition(older_wifi_data); + ASSERT_NE(nullptr, found_position); + EXPECT_TRUE(older_geoposition.Equals(*found_position)); + + // New position is added. + WifiData newer_wifi_data = testing::CreateDefaultUniqueWifiData(); + mojom::Geoposition newer_geoposition = testing::CreateGeoposition(2); + cache_.CachePosition(newer_wifi_data, newer_geoposition); + + // Enough time passes to evict the older entry, but not enough to evict the + // newer one. + task_environment_.FastForwardBy(PositionCacheImpl::kMaximumLifetime * 0.75); + + EXPECT_EQ(nullptr, cache_.FindPosition(older_wifi_data)); + + const mojom::Geoposition* found_newer_position = + cache_.FindPosition(newer_wifi_data); + ASSERT_NE(nullptr, found_newer_position); + EXPECT_TRUE(newer_geoposition.Equals(*found_newer_position)); +} + +TEST_F(PositionCacheImplTest, NetworkChangeClearsEmptyWifiDataPosition) { + // Cache a position for non-empty WifiData. + WifiData initial_wifi_data = testing::CreateDefaultUniqueWifiData(); + mojom::Geoposition initial_geoposition = testing::CreateGeoposition(1); + cache_.CachePosition(initial_wifi_data, initial_geoposition); + + // Cache a position for empty WifiData (wired network). + WifiData empty_wifi_data; + mojom::Geoposition empty_data_geoposition = testing::CreateGeoposition(2); + cache_.CachePosition(empty_wifi_data, empty_data_geoposition); + + cache_.SetLastUsedNetworkPosition(initial_geoposition); + + // When network changes... + net::NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests( + net::NetworkChangeNotifier::CONNECTION_UNKNOWN); + task_environment_.RunUntilIdle(); + + // ... last network position is cleared + EXPECT_FALSE(ValidateGeoposition(cache_.GetLastUsedNetworkPosition())); + + // And the position for empty WifiData is cleared, since we're probably on + // a different wired network now. + EXPECT_EQ(nullptr, cache_.FindPosition(empty_wifi_data)); + + // But the position for non-empty WifiData remains, since our access point + // scans remain valid even if we moved to a different access point. + const mojom::Geoposition* found_position = + cache_.FindPosition(initial_wifi_data); + ASSERT_NE(nullptr, found_position); + EXPECT_TRUE(initial_geoposition.Equals(*found_position)); +} +} // namespace device
diff --git a/services/device/geolocation/position_cache_test_util.cc b/services/device/geolocation/position_cache_test_util.cc new file mode 100644 index 0000000..d980e789 --- /dev/null +++ b/services/device/geolocation/position_cache_test_util.cc
@@ -0,0 +1,40 @@ +// 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 "services/device/geolocation/position_cache_test_util.h" + +#include <cmath> + +#include "base/guid.h" +#include "base/logging.h" +#include "base/strings/utf_string_conversions.h" + +namespace device { +namespace testing { + +WifiData CreateUniqueWifiData(int number_of_access_points) { + WifiData wifi_data; + for (int i = 0; i < number_of_access_points; ++i) { + AccessPointData single_access_point; + single_access_point.channel = 2; + single_access_point.mac_address = base::ASCIIToUTF16(base::GenerateGUID()); + single_access_point.radio_signal_strength = 4; + single_access_point.signal_to_noise = 5; + single_access_point.ssid = base::ASCIIToUTF16(base::GenerateGUID()); + wifi_data.access_point_data.insert(single_access_point); + } + return wifi_data; +} + +mojom::Geoposition CreateGeoposition(int offset) { + DCHECK_LT(std::abs(offset), 90) << "latitudes larger than 90 degrees are not " + "possible on spherical planets"; + mojom::Geoposition position; + position.latitude = offset; + position.longitude = offset; + return position; +} + +} // namespace testing +} // namespace device
diff --git a/services/device/geolocation/position_cache_test_util.h b/services/device/geolocation/position_cache_test_util.h new file mode 100644 index 0000000..44337d1b --- /dev/null +++ b/services/device/geolocation/position_cache_test_util.h
@@ -0,0 +1,25 @@ +// 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 SERVICES_DEVICE_GEOLOCATION_POSITION_CACHE_TEST_UTIL_H_ +#define SERVICES_DEVICE_GEOLOCATION_POSITION_CACHE_TEST_UTIL_H_ + +#include "services/device/geolocation/wifi_data.h" +#include "services/device/public/mojom/geoposition.mojom.h" + +namespace device { +namespace testing { + +WifiData CreateUniqueWifiData(int number_of_access_points); + +inline WifiData CreateDefaultUniqueWifiData() { + return CreateUniqueWifiData(10); +} + +mojom::Geoposition CreateGeoposition(int offset); + +} // namespace testing +} // namespace device + +#endif // SERVICES_DEVICE_GEOLOCATION_POSITION_CACHE_TEST_UTIL_H_
diff --git a/services/identity/public/cpp/accounts_cookie_mutator.h b/services/identity/public/cpp/accounts_cookie_mutator.h index 1c60863..6bfdd6b 100644 --- a/services/identity/public/cpp/accounts_cookie_mutator.h +++ b/services/identity/public/cpp/accounts_cookie_mutator.h
@@ -21,17 +21,25 @@ AccountsCookieMutator() = default; virtual ~AccountsCookieMutator() = default; + typedef base::OnceCallback<void(const std::string& account_id, + const GoogleServiceAuthError& error)> + AddAccountToCookieCompletedCallback; + // Adds an account identified by |account_id| to the cookie responsible for // tracking the list of logged-in Google sessions across the web. - virtual void AddAccountToCookie(const std::string& account_id, - gaia::GaiaSource source) = 0; + virtual void AddAccountToCookie( + const std::string& account_id, + gaia::GaiaSource source, + AddAccountToCookieCompletedCallback completion_callback) = 0; // Adds an account identified by |account_id| and with |access_token| to the // cookie responsible for tracking the list of logged-in Google sessions // across the web. - virtual void AddAccountToCookieWithToken(const std::string& account_id, - const std::string& access_token, - gaia::GaiaSource source) = 0; + virtual void AddAccountToCookieWithToken( + const std::string& account_id, + const std::string& access_token, + gaia::GaiaSource source, + AddAccountToCookieCompletedCallback completion_callback) = 0; // Updates the state of the Gaia cookie to contain |account_ids|, including // removal of any accounts that are currently present in the cookie but not
diff --git a/services/identity/public/cpp/accounts_cookie_mutator_impl.cc b/services/identity/public/cpp/accounts_cookie_mutator_impl.cc index 1f6dc5f..874a5a97 100644 --- a/services/identity/public/cpp/accounts_cookie_mutator_impl.cc +++ b/services/identity/public/cpp/accounts_cookie_mutator_impl.cc
@@ -20,16 +20,19 @@ void AccountsCookieMutatorImpl::AddAccountToCookie( const std::string& account_id, - gaia::GaiaSource source) { - gaia_cookie_manager_service_->AddAccountToCookie(account_id, source); + gaia::GaiaSource source, + AddAccountToCookieCompletedCallback completion_callback) { + gaia_cookie_manager_service_->AddAccountToCookie( + account_id, source, std::move(completion_callback)); } void AccountsCookieMutatorImpl::AddAccountToCookieWithToken( const std::string& account_id, const std::string& access_token, - gaia::GaiaSource source) { + gaia::GaiaSource source, + AddAccountToCookieCompletedCallback completion_callback) { gaia_cookie_manager_service_->AddAccountToCookieWithToken( - account_id, access_token, source); + account_id, access_token, source, std::move(completion_callback)); } void AccountsCookieMutatorImpl::SetAccountsInCookie(
diff --git a/services/identity/public/cpp/accounts_cookie_mutator_impl.h b/services/identity/public/cpp/accounts_cookie_mutator_impl.h index aa7edc7..72b56be1 100644 --- a/services/identity/public/cpp/accounts_cookie_mutator_impl.h +++ b/services/identity/public/cpp/accounts_cookie_mutator_impl.h
@@ -27,12 +27,16 @@ GaiaCookieManagerService* gaia_cookie_manager_service); ~AccountsCookieMutatorImpl() override; - void AddAccountToCookie(const std::string& account_id, - gaia::GaiaSource source) override; + void AddAccountToCookie( + const std::string& account_id, + gaia::GaiaSource source, + AddAccountToCookieCompletedCallback completion_callback) override; - void AddAccountToCookieWithToken(const std::string& account_id, - const std::string& access_token, - gaia::GaiaSource source) override; + void AddAccountToCookieWithToken( + const std::string& account_id, + const std::string& access_token, + gaia::GaiaSource source, + AddAccountToCookieCompletedCallback completion_callback) override; void SetAccountsInCookie( const std::vector<std::string>& account_ids,
diff --git a/services/identity/public/cpp/accounts_cookie_mutator_unittest.cc b/services/identity/public/cpp/accounts_cookie_mutator_unittest.cc index c7938a11..24c739a6 100644 --- a/services/identity/public/cpp/accounts_cookie_mutator_unittest.cc +++ b/services/identity/public/cpp/accounts_cookie_mutator_unittest.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/run_loop.h" +#include "base/test/bind_test_util.h" #include "base/test/gtest_util.h" #include "base/test/scoped_task_environment.h" #include "components/signin/core/browser/list_accounts_test_utils.h" @@ -142,18 +143,23 @@ // results in an error due to such account not being available. TEST_F(AccountsCookieMutatorTest, AddAccountToCookie_NonExistingAccount) { base::RunLoop run_loop; - identity_manager_observer()->SetOnAddAccountToCookieCompletedCallback( - run_loop.QuitClosure()); + std::string account_id_from_add_account_to_cookie_completed_callback; + GoogleServiceAuthError error_from_add_account_to_cookie_completed_callback; + auto completion_callback = base::BindLambdaForTesting( + [&](const std::string& account_id, const GoogleServiceAuthError& error) { + account_id_from_add_account_to_cookie_completed_callback = account_id; + error_from_add_account_to_cookie_completed_callback = error; + run_loop.Quit(); + }); + accounts_cookie_mutator()->AddAccountToCookie(kTestUnavailableAccountId, - gaia::GaiaSource::kChrome); + gaia::GaiaSource::kChrome, + std::move(completion_callback)); run_loop.Run(); - EXPECT_EQ(identity_manager_observer() - ->AccountFromAddAccountToCookieCompletedCallback(), + EXPECT_EQ(account_id_from_add_account_to_cookie_completed_callback, kTestUnavailableAccountId); - EXPECT_EQ(identity_manager_observer() - ->ErrorFromAddAccountToCookieCompletedCallback() - .state(), + EXPECT_EQ(error_from_add_account_to_cookie_completed_callback.state(), GoogleServiceAuthError::USER_NOT_SIGNED_UP); } @@ -165,21 +171,26 @@ std::string account_id = AddAcountWithRefreshToken(kTestAccountEmail); base::RunLoop run_loop; - identity_manager_observer()->SetOnAddAccountToCookieCompletedCallback( - run_loop.QuitClosure()); - accounts_cookie_mutator()->AddAccountToCookie(account_id, - gaia::GaiaSource::kChrome); + std::string account_id_from_add_account_to_cookie_completed_callback; + GoogleServiceAuthError error_from_add_account_to_cookie_completed_callback; + auto completion_callback = base::BindLambdaForTesting( + [&](const std::string& account_id, const GoogleServiceAuthError& error) { + account_id_from_add_account_to_cookie_completed_callback = account_id; + error_from_add_account_to_cookie_completed_callback = error; + run_loop.Quit(); + }); + + accounts_cookie_mutator()->AddAccountToCookie( + account_id, gaia::GaiaSource::kChrome, std::move(completion_callback)); + identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken( account_id, kTestAccessToken, base::Time::Now() + base::TimeDelta::FromHours(1)); run_loop.Run(); - EXPECT_EQ(identity_manager_observer() - ->AccountFromAddAccountToCookieCompletedCallback(), + EXPECT_EQ(account_id_from_add_account_to_cookie_completed_callback, account_id); - EXPECT_EQ(identity_manager_observer() - ->ErrorFromAddAccountToCookieCompletedCallback() - .state(), + EXPECT_EQ(error_from_add_account_to_cookie_completed_callback.state(), GoogleServiceAuthError::NONE); } @@ -191,18 +202,23 @@ AccountsCookiesMutatorAction::kAddAccountToCookie); base::RunLoop run_loop; - identity_manager_observer()->SetOnAddAccountToCookieCompletedCallback( - run_loop.QuitClosure()); + std::string account_id_from_add_account_to_cookie_completed_callback; + GoogleServiceAuthError error_from_add_account_to_cookie_completed_callback; + auto completion_callback = base::BindLambdaForTesting( + [&](const std::string& account_id, const GoogleServiceAuthError& error) { + account_id_from_add_account_to_cookie_completed_callback = account_id; + error_from_add_account_to_cookie_completed_callback = error; + run_loop.Quit(); + }); + accounts_cookie_mutator()->AddAccountToCookieWithToken( - kTestUnavailableAccountId, kTestAccessToken, gaia::GaiaSource::kChrome); + kTestUnavailableAccountId, kTestAccessToken, gaia::GaiaSource::kChrome, + std::move(completion_callback)); run_loop.Run(); - EXPECT_EQ(identity_manager_observer() - ->AccountFromAddAccountToCookieCompletedCallback(), + EXPECT_EQ(account_id_from_add_account_to_cookie_completed_callback, kTestUnavailableAccountId); - EXPECT_EQ(identity_manager_observer() - ->ErrorFromAddAccountToCookieCompletedCallback() - .state(), + EXPECT_EQ(error_from_add_account_to_cookie_completed_callback.state(), GoogleServiceAuthError::NONE); } @@ -215,19 +231,24 @@ std::string account_id = AddAcountWithRefreshToken(kTestAccountEmail); base::RunLoop run_loop; - identity_manager_observer()->SetOnAddAccountToCookieCompletedCallback( - run_loop.QuitClosure()); + std::string account_id_from_add_account_to_cookie_completed_callback; + GoogleServiceAuthError error_from_add_account_to_cookie_completed_callback; + auto completion_callback = base::BindLambdaForTesting( + [&](const std::string& account_id, const GoogleServiceAuthError& error) { + account_id_from_add_account_to_cookie_completed_callback = account_id; + error_from_add_account_to_cookie_completed_callback = error; + run_loop.Quit(); + }); + accounts_cookie_mutator()->AddAccountToCookieWithToken( - account_id, kTestAccessToken, gaia::GaiaSource::kChrome); + account_id, kTestAccessToken, gaia::GaiaSource::kChrome, + std::move(completion_callback)); run_loop.Run(); - EXPECT_EQ(identity_manager_observer() - ->AccountFromAddAccountToCookieCompletedCallback(), + EXPECT_EQ(account_id_from_add_account_to_cookie_completed_callback, account_id); - EXPECT_EQ(identity_manager_observer() - ->ErrorFromAddAccountToCookieCompletedCallback() - .state(), + EXPECT_EQ(error_from_add_account_to_cookie_completed_callback.state(), GoogleServiceAuthError::NONE); }
diff --git a/services/identity/public/cpp/identity_manager.cc b/services/identity/public/cpp/identity_manager.cc index 4bf6e5ad..d960705 100644 --- a/services/identity/public/cpp/identity_manager.cc +++ b/services/identity/public/cpp/identity_manager.cc
@@ -463,14 +463,6 @@ } } -void IdentityManager::OnAddAccountToCookieCompleted( - const std::string& account_id, - const GoogleServiceAuthError& error) { - for (auto& observer : observer_list_) { - observer.OnAddAccountToCookieCompleted(account_id, error); - } -} - void IdentityManager::OnGaiaCookieDeletedByUserAction() { for (auto& observer : observer_list_) { observer.OnAccountsCookieDeletedByUserAction();
diff --git a/services/identity/public/cpp/identity_manager.h b/services/identity/public/cpp/identity_manager.h index 2fbd28d..7d58b9f 100644 --- a/services/identity/public/cpp/identity_manager.h +++ b/services/identity/public/cpp/identity_manager.h
@@ -138,13 +138,6 @@ const AccountsInCookieJarInfo& accounts_in_cookie_jar_info, const GoogleServiceAuthError& error) {} - // Called whenever an attempt to add |account_id| to the list of Gaia - // accounts in the cookie jar has finished. If |error| is equal to - // GoogleServiceAuthError::AuthErrorNone() then the addittion succeeded. - virtual void OnAddAccountToCookieCompleted( - const std::string& account_id, - const GoogleServiceAuthError& error) {} - // Called when the Gaia cookie has been deleted explicitly by a user // action, e.g. from the settings or by an extension. virtual void OnAccountsCookieDeletedByUserAction() {} @@ -525,9 +518,6 @@ const std::vector<gaia::ListedAccount>& signed_in_accounts, const std::vector<gaia::ListedAccount>& signed_out_accounts, const GoogleServiceAuthError& error) override; - void OnAddAccountToCookieCompleted( - const std::string& account_id, - const GoogleServiceAuthError& error) override; void OnGaiaCookieDeletedByUserAction() override; // OAuth2TokenService::DiagnosticsObserver:
diff --git a/services/identity/public/cpp/identity_manager_unittest.cc b/services/identity/public/cpp/identity_manager_unittest.cc index 9bda7898..aa48533d 100644 --- a/services/identity/public/cpp/identity_manager_unittest.cc +++ b/services/identity/public/cpp/identity_manager_unittest.cc
@@ -1934,32 +1934,48 @@ TEST_F(IdentityManagerTest, CallbackSentOnSuccessfulAdditionOfAccountToCookie) { const char kTestAccountId[] = "account_id"; - gaia_cookie_manager_service()->AddAccountToCookie(kTestAccountId, - gaia::GaiaSource::kChrome); + + std::string account_from_add_account_to_cookie_completed_callback; + GoogleServiceAuthError error_from_add_account_to_cookie_completed_callback; + auto completion_callback = base::BindLambdaForTesting( + [&](const std::string& account_id, const GoogleServiceAuthError& error) { + account_from_add_account_to_cookie_completed_callback = account_id; + error_from_add_account_to_cookie_completed_callback = error; + }); + + gaia_cookie_manager_service()->AddAccountToCookie( + kTestAccountId, gaia::GaiaSource::kChrome, + std::move(completion_callback)); SimulateAdditionOfAccountToCookieSuccess(gaia_cookie_manager_service(), "token"); - EXPECT_EQ(identity_manager_observer() - ->AccountFromAddAccountToCookieCompletedCallback(), + EXPECT_EQ(account_from_add_account_to_cookie_completed_callback, kTestAccountId); - EXPECT_EQ(identity_manager_observer() - ->ErrorFromAddAccountToCookieCompletedCallback(), + EXPECT_EQ(error_from_add_account_to_cookie_completed_callback, GoogleServiceAuthError::AuthErrorNone()); } TEST_F(IdentityManagerTest, CallbackSentOnFailureAdditionOfAccountToCookie) { const char kTestAccountId[] = "account_id"; - gaia_cookie_manager_service()->AddAccountToCookie(kTestAccountId, - gaia::GaiaSource::kChrome); + + std::string account_from_add_account_to_cookie_completed_callback; + GoogleServiceAuthError error_from_add_account_to_cookie_completed_callback; + auto completion_callback = base::BindLambdaForTesting( + [&](const std::string& account_id, const GoogleServiceAuthError& error) { + account_from_add_account_to_cookie_completed_callback = account_id; + error_from_add_account_to_cookie_completed_callback = error; + }); + + gaia_cookie_manager_service()->AddAccountToCookie( + kTestAccountId, gaia::GaiaSource::kChrome, + std::move(completion_callback)); GoogleServiceAuthError error(GoogleServiceAuthError::SERVICE_ERROR); SimulateAdditionOfAccountToCookieSuccessFailure(gaia_cookie_manager_service(), error); - EXPECT_EQ(identity_manager_observer() - ->AccountFromAddAccountToCookieCompletedCallback(), + + EXPECT_EQ(account_from_add_account_to_cookie_completed_callback, kTestAccountId); - EXPECT_EQ(identity_manager_observer() - ->ErrorFromAddAccountToCookieCompletedCallback(), - error); + EXPECT_EQ(error_from_add_account_to_cookie_completed_callback, error); } TEST_F(IdentityManagerTest,
diff --git a/services/identity/public/cpp/test_identity_manager_observer.cc b/services/identity/public/cpp/test_identity_manager_observer.cc index 2f57d1e..57d63a29 100644 --- a/services/identity/public/cpp/test_identity_manager_observer.cc +++ b/services/identity/public/cpp/test_identity_manager_observer.cc
@@ -105,23 +105,6 @@ return error_from_cookie_change_callback_; } -void TestIdentityManagerObserver::SetOnAddAccountToCookieCompletedCallback( - base::OnceClosure callback) { - on_add_account_to_cookie_completed_callback_ = std::move(callback); -} - -const std::string& -TestIdentityManagerObserver::AccountFromAddAccountToCookieCompletedCallback() - const { - return account_from_add_account_to_cookie_completed_callback_; -} - -const GoogleServiceAuthError& -TestIdentityManagerObserver::ErrorFromAddAccountToCookieCompletedCallback() - const { - return error_from_add_account_to_cookie_completed_callback_; -} - void TestIdentityManagerObserver::SetOnCookieDeletedByUserCallback( base::OnceClosure callback) { on_cookie_deleted_by_user_callback_ = std::move(callback); @@ -215,15 +198,6 @@ std::move(on_accounts_in_cookie_updated_callback_).Run(); } -void TestIdentityManagerObserver::OnAddAccountToCookieCompleted( - const std::string& account_id, - const GoogleServiceAuthError& error) { - account_from_add_account_to_cookie_completed_callback_ = account_id; - error_from_add_account_to_cookie_completed_callback_ = error; - if (on_add_account_to_cookie_completed_callback_) - std::move(on_add_account_to_cookie_completed_callback_).Run(); -} - void TestIdentityManagerObserver::OnAccountsCookieDeletedByUserAction() { std::move(on_cookie_deleted_by_user_callback_).Run(); }
diff --git a/services/identity/public/cpp/test_identity_manager_observer.h b/services/identity/public/cpp/test_identity_manager_observer.h index 28a4b9d..91cc2e6 100644 --- a/services/identity/public/cpp/test_identity_manager_observer.h +++ b/services/identity/public/cpp/test_identity_manager_observer.h
@@ -52,11 +52,6 @@ const GoogleServiceAuthError& ErrorFromAccountsInCookieUpdatedCallback() const; - void SetOnAddAccountToCookieCompletedCallback(base::OnceClosure callback); - const std::string& AccountFromAddAccountToCookieCompletedCallback() const; - const GoogleServiceAuthError& ErrorFromAddAccountToCookieCompletedCallback() - const; - void SetOnCookieDeletedByUserCallback(base::OnceClosure callback); const AccountInfo& AccountFromAccountUpdatedCallback(); @@ -87,9 +82,6 @@ void OnAccountsInCookieUpdated( const AccountsInCookieJarInfo& accounts_in_cookie_jar_info, const GoogleServiceAuthError& error) override; - void OnAddAccountToCookieCompleted( - const std::string& account_id, - const GoogleServiceAuthError& error) override; void OnAccountsCookieDeletedByUserAction() override; void OnExtendedAccountInfoUpdated(const AccountInfo& info) override; @@ -126,10 +118,6 @@ AccountsInCookieJarInfo accounts_info_from_cookie_change_callback_; GoogleServiceAuthError error_from_cookie_change_callback_; - base::OnceClosure on_add_account_to_cookie_completed_callback_; - std::string account_from_add_account_to_cookie_completed_callback_; - GoogleServiceAuthError error_from_add_account_to_cookie_completed_callback_; - base::OnceClosure on_cookie_deleted_by_user_callback_; AccountInfo account_from_account_updated_callback_;
diff --git a/services/tracing/BUILD.gn b/services/tracing/BUILD.gn index 3ca7786..fe6160c0 100644 --- a/services/tracing/BUILD.gn +++ b/services/tracing/BUILD.gn
@@ -64,6 +64,8 @@ sources = [ "agent_registry_unittest.cc", + "coordinator_test_util.cc", + "coordinator_test_util.h", "coordinator_unittest.cc", "public/cpp/trace_event_agent_unittest.cc", "recorder_unittest.cc", @@ -99,6 +101,7 @@ sources += [ "perfetto/json_trace_exporter_unittest.cc", "perfetto/perfetto_integration_unittest.cc", + "perfetto/perfetto_tracing_coordinator_unittest.cc", "perfetto/test_utils.cc", "perfetto/test_utils.h", ]
diff --git a/services/tracing/agent_registry.cc b/services/tracing/agent_registry.cc index 759aacc7..f1e4764 100644 --- a/services/tracing/agent_registry.cc +++ b/services/tracing/agent_registry.cc
@@ -16,6 +16,8 @@ namespace tracing { +const int32_t kAgentResponseTimeoutInSeconds = 10; + AgentRegistry::AgentEntry::AgentEntry(size_t id, AgentRegistry* agent_registry, mojom::AgentPtr agent, @@ -40,10 +42,17 @@ base::OnceClosure closure) { DCHECK_EQ(0u, closures_.count(closure_name)); closures_[closure_name] = std::move(closure); + + // Adding a disconnect closure means we're waiting for a response from the + // agent. If the client becomes unresponsive, we disconnect it. + timer_.Start(FROM_HERE, + base::TimeDelta::FromSeconds(kAgentResponseTimeoutInSeconds), + this, &AgentRegistry::AgentEntry::OnConnectionError); } bool AgentRegistry::AgentEntry::RemoveDisconnectClosure( const void* closure_name) { + timer_.Stop(); return closures_.erase(closure_name) > 0; }
diff --git a/services/tracing/agent_registry.h b/services/tracing/agent_registry.h index 523bc52..cb701f3c 100644 --- a/services/tracing/agent_registry.h +++ b/services/tracing/agent_registry.h
@@ -12,6 +12,7 @@ #include "base/callback_forward.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "base/timer/timer.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "services/service_manager/public/cpp/identity.h" #include "services/tracing/public/mojom/tracing.mojom.h" @@ -53,6 +54,7 @@ const mojom::TraceDataType type_; const base::ProcessId pid_; std::map<const void*, base::OnceClosure> closures_; + base::RepeatingTimer timer_; DISALLOW_COPY_AND_ASSIGN(AgentEntry); }; @@ -84,7 +86,7 @@ private: friend class AgentRegistryTest; // For testing. - friend class CoordinatorTest; // For testing. + friend class CoordinatorTestUtil; // For testing. // mojom::AgentRegistry void RegisterAgent(mojom::AgentPtr agent,
diff --git a/services/tracing/coordinator.cc b/services/tracing/coordinator.cc index 821f0de4..b426897 100644 --- a/services/tracing/coordinator.cc +++ b/services/tracing/coordinator.cc
@@ -37,11 +37,18 @@ const char kMetadataTraceLabel[] = "metadata"; const char kRequestBufferUsageClosureName[] = "RequestBufferUsageClosure"; +const char kStartTracingClosureName[] = "StartTracingClosure"; +const int32_t kBeginTracingTimeoutInSeconds = 10; } // namespace namespace tracing { +// static +const void* Coordinator::GetStartTracingClosureName() { + return &kStartTracingClosureName; +} + class Coordinator::TraceStreamer : public base::SupportsWeakPtr<TraceStreamer> { public: // Constructed on |main_task_runner_|. @@ -269,9 +276,9 @@ Coordinator::Coordinator(AgentRegistry* agent_registry, const base::RepeatingClosure& on_disconnect_callback) - : on_disconnect_callback_(std::move(on_disconnect_callback)), + : task_runner_(base::SequencedTaskRunnerHandle::Get()), + on_disconnect_callback_(std::move(on_disconnect_callback)), binding_(this), - task_runner_(base::SequencedTaskRunnerHandle::Get()), // USER_VISIBLE because the task posted from StopAndFlushInternal() is // required to stop tracing from the UI. // TODO(fdoray): Once we have support for dynamic priorities @@ -294,10 +301,14 @@ } void Coordinator::Reset() { + start_tracing_callback_timer_.Stop(); + if (!stop_and_flush_callback_.is_null()) { base::ResetAndReturn(&stop_and_flush_callback_) .Run(base::Value(base::Value::Type::DICTIONARY)); } + if (!start_tracing_callback_.is_null()) + base::ResetAndReturn(&start_tracing_callback_).Run(false); if (!request_buffer_usage_callback_.is_null()) base::ResetAndReturn(&request_buffer_usage_callback_).Run(false, 0, 0); @@ -326,8 +337,11 @@ &Coordinator::OnClientConnectionError, base::Unretained(this))); } -void Coordinator::StartTracing(const std::string& config) { - if ((is_tracing_ && config == config_)) { +void Coordinator::StartTracing(const std::string& config, + StartTracingCallback callback) { + bool is_initializing = !start_tracing_callback_.is_null(); + if (is_initializing || (is_tracing_ && config == config_)) { + std::move(callback).Run(config == config_); return; } @@ -338,13 +352,113 @@ base::BindRepeating(&Coordinator::SendStartTracingToAgent, weak_ptr_factory_.GetWeakPtr()), false /* call_on_new_agents_only */); + + SetStartTracingCallback(std::move(callback)); +} + +void Coordinator::SetStartTracingCallback(StartTracingCallback callback) { + start_tracing_callback_ = std::move(callback); + CallStartTracingCallbackIfNeeded(); + + if (!start_tracing_callback_) + return; + + // We can't know for sure whether all processses we request + // to connect to the tracing service will connect back, or + // if all the connected services will ACK our BeginTracing + // request eventually, so we'll add a timeout for that case. + start_tracing_callback_timer_.Start( + FROM_HERE, base::TimeDelta::FromSeconds(kBeginTracingTimeoutInSeconds), + this, &Coordinator::OnBeginTracingTimeout); +} + +void Coordinator::OnBeginTracingTimeout() { + if (start_tracing_callback_) + std::move(start_tracing_callback_).Run(true); +} + +void Coordinator::CallStartTracingCallbackIfNeeded() { + // We still have processes we've asked to begin tracing and + // need ACKs from. + if (agent_registry_->HasDisconnectClosure(&kStartTracingClosureName)) + return; + + // We're still waiting for the list of PIDs of the currently + // running services. + if (pending_currently_running_pids_) + return; + + // We're still waiting for processes to connect to the + // service. + for (auto& pid : pending_connected_pids_) { + if (parsed_config_.process_filter_config().IsEnabled(pid)) + return; + } + + if (start_tracing_callback_) + std::move(start_tracing_callback_).Run(true); + + start_tracing_callback_timer_.Stop(); +} + +void Coordinator::AddExpectedPID(base::ProcessId pid) { + if (!pid) + return; + + bool pid_is_connected = false; + agent_registry_->ForAllAgents( + [&pid_is_connected, pid](AgentRegistry::AgentEntry* agent_entry) { + if (pid == agent_entry->pid()) + pid_is_connected = true; + }); + + if (!pid_is_connected) + pending_connected_pids_.insert(pid); +} + +void Coordinator::RemoveExpectedPID(base::ProcessId pid) { + pending_connected_pids_.erase(pid); + CallStartTracingCallbackIfNeeded(); +} + +void Coordinator::FinishedReceivingRunningPIDs() { + pending_currently_running_pids_ = false; + CallStartTracingCallbackIfNeeded(); +} + +void Coordinator::ClearConnectedPIDs() { + if (!pending_connected_pids_.empty()) { + pending_connected_pids_.clear(); + CallStartTracingCallbackIfNeeded(); + } } void Coordinator::SendStartTracingToAgent( AgentRegistry::AgentEntry* agent_entry) { + if (agent_entry->HasDisconnectClosure(&kStartTracingClosureName)) + return; if (!parsed_config_.process_filter_config().IsEnabled(agent_entry->pid())) return; - agent_entry->agent()->StartTracing(config_, TRACE_TIME_TICKS_NOW()); + agent_entry->AddDisconnectClosure( + &kStartTracingClosureName, + base::BindOnce(&Coordinator::OnTracingStarted, + weak_ptr_factory_.GetWeakPtr(), + base::Unretained(agent_entry), false)); + RemoveExpectedPID(agent_entry->pid()); + + agent_entry->agent()->StartTracing( + config_, TRACE_TIME_TICKS_NOW(), + base::BindRepeating(&Coordinator::OnTracingStarted, + weak_ptr_factory_.GetWeakPtr(), + base::Unretained(agent_entry))); +} + +void Coordinator::OnTracingStarted(AgentRegistry::AgentEntry* agent_entry, + bool success) { + bool removed = + agent_entry->RemoveDisconnectClosure(&kStartTracingClosureName); + DCHECK(removed); + CallStartTracingCallbackIfNeeded(); } void Coordinator::StopAndFlush(mojo::ScopedDataPipeProducerHandle stream, @@ -363,6 +477,12 @@ DCHECK(!trace_streamer_); DCHECK(stream.is_valid()); is_tracing_ = false; + // If we get a Stop call and this is non-empty, it means we either + // hit a timeout waiting for processes to connect, or the trace + // client sent a stop without waiting for the BeginTracing callback + // to happen. In either case, we don't want/need to wait for additional + // processes to connect anymore. + ClearConnectedPIDs(); trace_streamer_.reset(new Coordinator::TraceStreamer( std::move(stream), agent_label, task_runner_, @@ -372,6 +492,18 @@ } void Coordinator::StopAndFlushInternal() { + if (start_tracing_callback_) { + // We received a |StopAndFlush| command before receiving |StartTracing| acks + // from all agents. Let's retry after a delay. + task_runner_->PostDelayedTask( + FROM_HERE, + base::BindRepeating(&Coordinator::StopAndFlushInternal, + weak_ptr_factory_.GetWeakPtr()), + base::TimeDelta::FromMilliseconds( + mojom::kStopTracingRetryTimeMilliseconds)); + return; + } + size_t num_initialized_agents = agent_registry_->SetAgentInitializationCallback( base::BindRepeating(&Coordinator::SendStopTracingToAgent,
diff --git a/services/tracing/coordinator.h b/services/tracing/coordinator.h index 842dc8c..50b5381 100644 --- a/services/tracing/coordinator.h +++ b/services/tracing/coordinator.h
@@ -14,6 +14,7 @@ #include "base/memory/weak_ptr.h" #include "base/sequenced_task_runner.h" #include "base/single_thread_task_runner.h" +#include "base/timer/timer.h" #include "base/trace_event/trace_config.h" #include "base/values.h" #include "mojo/public/cpp/system/data_pipe.h" @@ -50,21 +51,36 @@ bool IsConnected(); + void AddExpectedPID(base::ProcessId pid); + void RemoveExpectedPID(base::ProcessId pid); + void FinishedReceivingRunningPIDs(); + protected: ~Coordinator() override; + static const void* GetStartTracingClosureName(); + virtual void OnClientConnectionError(); + void CallStartTracingCallbackIfNeeded(); + void OnBeginTracingTimeout(); + void SetStartTracingCallback(StartTracingCallback callback); + void ClearConnectedPIDs(); + + base::trace_event::TraceConfig parsed_config_; + StartTracingCallback start_tracing_callback_; + const scoped_refptr<base::SequencedTaskRunner> task_runner_; private: friend std::default_delete<Coordinator>; - friend class CoordinatorTest; // For testing. + friend class CoordinatorTestUtil; // For testing. class TraceStreamer; void Reset(); // mojom::Coordinator - void StartTracing(const std::string& config) override; + void StartTracing(const std::string& config, + StartTracingCallback callback) override; void StopAndFlush(mojo::ScopedDataPipeProducerHandle stream, StopAndFlushCallback callback) override; void StopAndFlushAgent(mojo::ScopedDataPipeProducerHandle stream, @@ -75,6 +91,7 @@ // Internal methods for collecting events from agents. void SendStartTracingToAgent(AgentRegistry::AgentEntry* agent_entry); + void OnTracingStarted(AgentRegistry::AgentEntry* agent_entry, bool success); void StopAndFlushInternal(); void SendStopTracingToAgent(AgentRegistry::AgentEntry* agent_entry); void SendStopTracingWithNoOpRecorderToAgent( @@ -89,14 +106,15 @@ base::RepeatingClosure on_disconnect_callback_; mojo::Binding<mojom::Coordinator> binding_; - const scoped_refptr<base::SequencedTaskRunner> task_runner_; const scoped_refptr<base::SequencedTaskRunner> backend_task_runner_; AgentRegistry* agent_registry_; std::string config_; - base::trace_event::TraceConfig parsed_config_; bool is_tracing_ = false; std::unique_ptr<TraceStreamer> trace_streamer_; + std::set<base::ProcessId> pending_connected_pids_; + bool pending_currently_running_pids_ = true; + base::OneShotTimer start_tracing_callback_timer_; StopAndFlushCallback stop_and_flush_callback_; // For computing trace buffer usage.
diff --git a/services/tracing/coordinator_test_util.cc b/services/tracing/coordinator_test_util.cc new file mode 100644 index 0000000..41bdee5 --- /dev/null +++ b/services/tracing/coordinator_test_util.cc
@@ -0,0 +1,134 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/tracing/coordinator_test_util.h" + +#include <algorithm> +#include <set> +#include <utility> + +#include "base/bind.h" +#include "services/tracing/agent_registry.h" +#include "services/tracing/coordinator.h" +#include "services/tracing/public/mojom/tracing.mojom.h" +#include "services/tracing/test_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace tracing { + +CoordinatorTestUtil::CoordinatorTestUtil() {} +CoordinatorTestUtil::~CoordinatorTestUtil() {} + +// testing::Test +void CoordinatorTestUtil::SetUp() { + agent_registry_ = std::make_unique<AgentRegistry>(); + output_ = ""; + tracing_begin_callback_received_ = false; +} + +// testing::Test +void CoordinatorTestUtil::TearDown() { + agents_.clear(); + coordinator_.reset(); + agent_registry_.reset(); +} + +// mojo::DataPipeDrainer::Client +void CoordinatorTestUtil::OnDataAvailable(const void* data, size_t num_bytes) { + output_.append(static_cast<const char*>(data), num_bytes); +} + +// mojo::DataPipeDrainer::Client +void CoordinatorTestUtil::OnDataComplete() { + std::move(wait_for_data_closure_).Run(); +} + +MockAgent* CoordinatorTestUtil::AddArrayAgent(base::ProcessId pid) { + auto agent = std::make_unique<MockAgent>(); + agent_registry_->RegisterAgent(agent->CreateAgentPtr(), "traceEvents", + mojom::TraceDataType::ARRAY, pid); + agents_.push_back(std::move(agent)); + return agents_.back().get(); +} + +MockAgent* CoordinatorTestUtil::AddArrayAgent() { + return AddArrayAgent(base::kNullProcessId); +} + +MockAgent* CoordinatorTestUtil::AddObjectAgent() { + auto agent = std::make_unique<MockAgent>(); + agent_registry_->RegisterAgent(agent->CreateAgentPtr(), "systemTraceEvents", + mojom::TraceDataType::OBJECT, + base::kNullProcessId); + agents_.push_back(std::move(agent)); + return agents_.back().get(); +} + +MockAgent* CoordinatorTestUtil::AddStringAgent() { + auto agent = std::make_unique<MockAgent>(); + agent_registry_->RegisterAgent(agent->CreateAgentPtr(), "power", + mojom::TraceDataType::STRING, + base::kNullProcessId); + agents_.push_back(std::move(agent)); + return agents_.back().get(); +} + +void CoordinatorTestUtil::StartTracing(std::string config, + bool expected_response) { + wait_for_data_closure_ = tracing_loop_.QuitClosure(); + + coordinator_->StartTracing( + config, base::BindRepeating( + [](bool expected, bool* tracing_begin_callback_received, + bool actual) { + EXPECT_EQ(expected, actual); + *tracing_begin_callback_received = true; + }, + expected_response, &tracing_begin_callback_received_)); +} + +std::string CoordinatorTestUtil::StopAndFlush() { + mojo::DataPipe data_pipe; + auto dummy_callback = [](base::Value metadata) {}; + coordinator_->StopAndFlush(std::move(data_pipe.producer_handle), + base::BindRepeating(dummy_callback)); + drainer_.reset( + new mojo::DataPipeDrainer(this, std::move(data_pipe.consumer_handle))); + if (!wait_for_data_closure_.is_null()) + tracing_loop_.Run(); + + return output_; +} + +void CoordinatorTestUtil::IsTracing(bool expected_response) { + coordinator_->IsTracing(base::BindRepeating( + [](bool expected, bool actual) { EXPECT_EQ(expected, actual); }, + expected_response)); +} + +void CoordinatorTestUtil::RequestBufferUsage(float expected_usage, + uint32_t expected_count) { + coordinator_->RequestBufferUsage(base::BindRepeating( + [](float expected_usage, uint32_t expected_count, bool success, + float usage, uint32_t count) { + EXPECT_TRUE(success); + EXPECT_EQ(expected_usage, usage); + EXPECT_EQ(expected_count, count); + }, + expected_usage, expected_count)); +} + +void CoordinatorTestUtil::CheckDisconnectClosures(size_t num_agents) { + // Verify that all disconnect closures are cleared up. This means that, for + // each agent, either the tracing service is notified that the agent is + // disconnected or the agent has answered to all requests. + size_t count = 0; + agent_registry_->ForAllAgents([&count](AgentRegistry::AgentEntry* entry) { + count++; + EXPECT_EQ(0u, entry->num_disconnect_closures_for_testing()); + }); + EXPECT_EQ(num_agents, count); +} + +} // namespace tracing
diff --git a/services/tracing/coordinator_test_util.h b/services/tracing/coordinator_test_util.h new file mode 100644 index 0000000..21c08625 --- /dev/null +++ b/services/tracing/coordinator_test_util.h
@@ -0,0 +1,74 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_TRACING_COORDINATOR_TEST_UTIL_H_ +#define SERVICES_TRACING_COORDINATOR_TEST_UTIL_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" +#include "mojo/public/cpp/system/data_pipe.h" +#include "mojo/public/cpp/system/data_pipe_drainer.h" + +namespace tracing { + +class AgentRegistry; +class Coordinator; +class MockAgent; + +class CoordinatorTestUtil : public mojo::DataPipeDrainer::Client { + public: + CoordinatorTestUtil(); + ~CoordinatorTestUtil() override; + + void SetUp(); + void TearDown(); + + // mojo::DataPipeDrainer::Client + void OnDataAvailable(const void* data, size_t num_bytes) override; + + // mojo::DataPipeDrainer::Client + void OnDataComplete() override; + + MockAgent* AddArrayAgent(base::ProcessId pid); + MockAgent* AddArrayAgent(); + MockAgent* AddObjectAgent(); + MockAgent* AddStringAgent(); + + void StartTracing(std::string config, bool expected_response); + std::string StopAndFlush(); + + void IsTracing(bool expected_response); + + void RequestBufferUsage(float expected_usage, uint32_t expected_count); + + void CheckDisconnectClosures(size_t num_agents); + + AgentRegistry* agent_registry() { return agent_registry_.get(); } + bool tracing_begin_callback_received() const { + return tracing_begin_callback_received_; + } + + protected: + std::unique_ptr<Coordinator> coordinator_; + + private: + base::test::ScopedTaskEnvironment scoped_task_environment_; + + std::unique_ptr<AgentRegistry> agent_registry_; + std::vector<std::unique_ptr<MockAgent>> agents_; + std::unique_ptr<mojo::DataPipeDrainer> drainer_; + + base::RunLoop tracing_loop_; + base::RepeatingClosure wait_for_data_closure_; + std::string output_; + bool tracing_begin_callback_received_ = false; +}; + +} // namespace tracing + +#endif // SERVICES_TRACING_COORDINATOR_TEST_UTIL_H_
diff --git a/services/tracing/coordinator_unittest.cc b/services/tracing/coordinator_unittest.cc index 4063dd7c..beb9bca 100644 --- a/services/tracing/coordinator_unittest.cc +++ b/services/tracing/coordinator_unittest.cc
@@ -4,133 +4,30 @@ #include "services/tracing/coordinator.h" -#include <algorithm> #include <memory> -#include <set> -#include <string> -#include <utility> -#include <vector> -#include "base/bind.h" #include "base/run_loop.h" -#include "base/strings/string_split.h" -#include "base/test/scoped_task_environment.h" -#include "mojo/public/cpp/system/data_pipe.h" -#include "mojo/public/cpp/system/data_pipe_drainer.h" -#include "services/service_manager/public/cpp/service_context_ref.h" -#include "services/tracing/public/mojom/tracing.mojom.h" +#include "services/tracing/coordinator_test_util.h" #include "services/tracing/test_util.h" #include "testing/gtest/include/gtest/gtest.h" namespace tracing { -class CoordinatorTest : public testing::Test, - public mojo::DataPipeDrainer::Client { +class CoordinatorTest : public testing::Test, public CoordinatorTestUtil { public: - // testing::Test void SetUp() override { - agent_registry_ = std::make_unique<AgentRegistry>(); - coordinator_ = std::make_unique<Coordinator>(agent_registry_.get(), + CoordinatorTestUtil::SetUp(); + coordinator_ = std::make_unique<Coordinator>(agent_registry(), base::RepeatingClosure()); - output_ = ""; + coordinator_->FinishedReceivingRunningPIDs(); } - - // testing::Test - void TearDown() override { - agents_.clear(); - coordinator_.reset(); - agent_registry_.reset(); - } - - // mojo::DataPipeDrainer::Client - void OnDataAvailable(const void* data, size_t num_bytes) override { - output_.append(static_cast<const char*>(data), num_bytes); - } - - // mojo::DataPipeDrainer::Client - void OnDataComplete() override { std::move(quit_closure_).Run(); } - - MockAgent* AddArrayAgent(base::ProcessId pid) { - auto agent = std::make_unique<MockAgent>(); - agent_registry_->RegisterAgent(agent->CreateAgentPtr(), "traceEvents", - mojom::TraceDataType::ARRAY, pid); - agents_.push_back(std::move(agent)); - return agents_.back().get(); - } - - MockAgent* AddArrayAgent() { return AddArrayAgent(base::kNullProcessId); } - - MockAgent* AddObjectAgent() { - auto agent = std::make_unique<MockAgent>(); - agent_registry_->RegisterAgent(agent->CreateAgentPtr(), "systemTraceEvents", - mojom::TraceDataType::OBJECT, - base::kNullProcessId); - agents_.push_back(std::move(agent)); - return agents_.back().get(); - } - - MockAgent* AddStringAgent() { - auto agent = std::make_unique<MockAgent>(); - agent_registry_->RegisterAgent(agent->CreateAgentPtr(), "power", - mojom::TraceDataType::STRING, - base::kNullProcessId); - agents_.push_back(std::move(agent)); - return agents_.back().get(); - } - - void StartTracing(std::string config) { coordinator_->StartTracing(config); } - - void StopAndFlush() { - mojo::DataPipe data_pipe; - auto dummy_callback = [](base::Value metadata) {}; - coordinator_->StopAndFlush(std::move(data_pipe.producer_handle), - base::BindRepeating(dummy_callback)); - drainer_.reset( - new mojo::DataPipeDrainer(this, std::move(data_pipe.consumer_handle))); - } - - void IsTracing(bool expected_response) { - coordinator_->IsTracing(base::BindRepeating( - [](bool expected, bool actual) { EXPECT_EQ(expected, actual); }, - expected_response)); - } - - void RequestBufferUsage(float expected_usage, uint32_t expected_count) { - coordinator_->RequestBufferUsage(base::BindRepeating( - [](float expected_usage, uint32_t expected_count, bool success, - float usage, uint32_t count) { - EXPECT_TRUE(success); - EXPECT_EQ(expected_usage, usage); - EXPECT_EQ(expected_count, count); - }, - expected_usage, expected_count)); - } - - void CheckDisconnectClosures(size_t num_agents) { - // Verify that all disconnect closures are cleared up. This means that, for - // each agent, either the tracing service is notified that the agent is - // disconnected or the agent has answered to all requests. - size_t count = 0; - agent_registry_->ForAllAgents([&count](AgentRegistry::AgentEntry* entry) { - count++; - EXPECT_EQ(0u, entry->num_disconnect_closures_for_testing()); - }); - EXPECT_EQ(num_agents, count); - } - - base::test::ScopedTaskEnvironment scoped_task_environment_; - std::unique_ptr<AgentRegistry> agent_registry_; - std::unique_ptr<Coordinator> coordinator_; - std::vector<std::unique_ptr<MockAgent>> agents_; - std::unique_ptr<mojo::DataPipeDrainer> drainer_; - base::RepeatingClosure quit_closure_; - std::string output_; + void TearDown() override { CoordinatorTestUtil::TearDown(); } }; TEST_F(CoordinatorTest, StartTracingSimple) { base::RunLoop run_loop; auto* agent = AddArrayAgent(); - StartTracing("*"); + StartTracing("*", true); run_loop.RunUntilIdle(); // The agent should have received exactly one call from the coordinator. @@ -141,7 +38,7 @@ TEST_F(CoordinatorTest, StartTracingTwoAgents) { base::RunLoop run_loop; auto* agent1 = AddArrayAgent(); - StartTracing("*"); + StartTracing("*", true); auto* agent2 = AddStringAgent(); run_loop.RunUntilIdle(); @@ -156,13 +53,13 @@ base::RunLoop run_loop1; auto* agent1 = AddArrayAgent(static_cast<base::ProcessId>(1)); auto* agent2 = AddArrayAgent(static_cast<base::ProcessId>(2)); - StartTracing("{\"included_process_ids\":[2,4]}"); + StartTracing("{\"included_process_ids\":[2,4]}", true); run_loop1.RunUntilIdle(); base::RunLoop run_loop2; auto* agent3 = AddArrayAgent(static_cast<base::ProcessId>(3)); auto* agent4 = AddArrayAgent(static_cast<base::ProcessId>(4)); - StartTracing("{\"included_process_ids\":[4,6]}"); + StartTracing("{\"included_process_ids\":[4,6]}", true); run_loop2.RunUntilIdle(); base::RunLoop run_loop3; @@ -171,27 +68,38 @@ run_loop3.RunUntilIdle(); // StartTracing should only be received by agents 2, 4, and 6. - // Agent 4 should receive StartTracing twice, as it's - // included in both configs. EXPECT_EQ(0u, agent1->call_stat().size()); EXPECT_EQ(1u, agent2->call_stat().size()); EXPECT_EQ("StartTracing", agent2->call_stat()[0]); EXPECT_EQ(0u, agent3->call_stat().size()); - EXPECT_EQ(2u, agent4->call_stat().size()); + EXPECT_EQ(1u, agent4->call_stat().size()); EXPECT_EQ("StartTracing", agent4->call_stat()[0]); - EXPECT_EQ("StartTracing", agent4->call_stat()[1]); EXPECT_EQ(0u, agent5->call_stat().size()); EXPECT_EQ(1u, agent6->call_stat().size()); EXPECT_EQ("StartTracing", agent6->call_stat()[0]); } +TEST_F(CoordinatorTest, StartTracingWithDifferentConfigs) { + base::RunLoop run_loop; + auto* agent = AddArrayAgent(); + StartTracing("config 1", true); + // The 2nd |StartTracing| should return false. + StartTracing("config 2", false); + run_loop.RunUntilIdle(); + + // The agent should have received exactly one call from the coordinator + // because the 2nd |StartTracing| was aborted. + EXPECT_EQ(1u, agent->call_stat().size()); + EXPECT_EQ("StartTracing", agent->call_stat()[0]); +} + TEST_F(CoordinatorTest, StartTracingWithSameConfigs) { base::RunLoop run_loop; auto* agent = AddArrayAgent(); - StartTracing("config"); - // The 2nd |StartTracing| should succeed when we are not trying to change + StartTracing("config", true); + // The 2nd |StartTracing| should return true when we are not trying to change // the config. - StartTracing("config"); + StartTracing("config", true); run_loop.RunUntilIdle(); // The agent should have received exactly one call from the coordinator @@ -201,20 +109,15 @@ } TEST_F(CoordinatorTest, StopAndFlushObjectAgent) { - base::RunLoop run_loop; - quit_closure_ = run_loop.QuitClosure(); - auto* agent = AddObjectAgent(); agent->data_.push_back("\"content\":{\"a\":1}"); agent->data_.push_back("\"name\":\"etw\""); - StartTracing("config"); - StopAndFlush(); - if (!quit_closure_.is_null()) - run_loop.Run(); + StartTracing("config", true); + std::string output = StopAndFlush(); EXPECT_EQ("{\"systemTraceEvents\":{\"content\":{\"a\":1},\"name\":\"etw\"}}", - output_); + output); // Each agent should have received exactly two calls. EXPECT_EQ(2u, agent->call_stat().size()); @@ -223,9 +126,6 @@ } TEST_F(CoordinatorTest, StopAndFlushTwoArrayAgents) { - base::RunLoop run_loop; - quit_closure_ = run_loop.QuitClosure(); - auto* agent1 = AddArrayAgent(); agent1->data_.push_back("e1"); agent1->data_.push_back("e2"); @@ -234,22 +134,20 @@ agent2->data_.push_back("e3"); agent2->data_.push_back("e4"); - StartTracing("config"); - StopAndFlush(); - if (!quit_closure_.is_null()) - run_loop.Run(); + StartTracing("config", true); + std::string output = StopAndFlush(); - // |output_| should be of the form {"traceEvents":[ei,ej,ek,el]}, where + // |output| should be of the form {"traceEvents":[ei,ej,ek,el]}, where // ei,ej,ek,el is a permutation of e1,e2,e3,e4 such that e1 is before e2 and // e3 is before e4 since e1 and 2 come from the same agent and their order // should be preserved and, similarly, the order of e3 and e4 should be // preserved, too. - EXPECT_TRUE(output_ == "{\"traceEvents\":[e1,e2,e3,e4]}" || - output_ == "{\"traceEvents\":[e1,e3,e2,e4]}" || - output_ == "{\"traceEvents\":[e1,e3,e4,e2]}" || - output_ == "{\"traceEvents\":[e3,e1,e2,e4]}" || - output_ == "{\"traceEvents\":[e3,e1,e4,e2]}" || - output_ == "{\"traceEvents\":[e3,e4,e1,e2]}"); + EXPECT_TRUE(output == "{\"traceEvents\":[e1,e2,e3,e4]}" || + output == "{\"traceEvents\":[e1,e3,e2,e4]}" || + output == "{\"traceEvents\":[e1,e3,e4,e2]}" || + output == "{\"traceEvents\":[e3,e1,e2,e4]}" || + output == "{\"traceEvents\":[e3,e1,e4,e2]}" || + output == "{\"traceEvents\":[e3,e4,e1,e2]}"); // Each agent should have received exactly two calls. EXPECT_EQ(2u, agent1->call_stat().size()); @@ -262,9 +160,6 @@ } TEST_F(CoordinatorTest, StopAndFlushDifferentTypeAgents) { - base::RunLoop run_loop; - quit_closure_ = run_loop.QuitClosure(); - auto* agent1 = AddArrayAgent(); agent1->data_.push_back("e1"); agent1->data_.push_back("e2"); @@ -273,13 +168,11 @@ agent2->data_.push_back("e3"); agent2->data_.push_back("e4"); - StartTracing("config"); - StopAndFlush(); - if (!quit_closure_.is_null()) - run_loop.Run(); + StartTracing("config", true); + std::string output = StopAndFlush(); - EXPECT_TRUE(output_ == "{\"traceEvents\":[e1,e2],\"power\":\"e3e4\"}" || - output_ == "{\"power\":\"e3e4\",\"traceEvents\":[e1,e2]}"); + EXPECT_TRUE(output == "{\"traceEvents\":[e1,e2],\"power\":\"e3e4\"}" || + output == "{\"power\":\"e3e4\",\"traceEvents\":[e1,e2]}"); // Each agent should have received exactly two calls. EXPECT_EQ(2u, agent1->call_stat().size()); @@ -292,21 +185,16 @@ } TEST_F(CoordinatorTest, StopAndFlushWithMetadata) { - base::RunLoop run_loop; - quit_closure_ = run_loop.QuitClosure(); - auto* agent = AddArrayAgent(); agent->data_.push_back("event"); agent->metadata_.SetString("key", "value"); - StartTracing("config"); - StopAndFlush(); - if (!quit_closure_.is_null()) - run_loop.Run(); + StartTracing("config", true); + std::string output = StopAndFlush(); // Metadata is written at after trace data. EXPECT_EQ("{\"traceEvents\":[event],\"metadata\":{\"key\":\"value\"}}", - output_); + output); EXPECT_EQ(2u, agent->call_stat().size()); EXPECT_EQ("StartTracing", agent->call_stat()[0]); EXPECT_EQ("StopAndFlush", agent->call_stat()[1]); @@ -315,7 +203,7 @@ TEST_F(CoordinatorTest, IsTracing) { base::RunLoop run_loop; AddArrayAgent(); - StartTracing("config"); + StartTracing("config", true); IsTracing(true); run_loop.RunUntilIdle(); } @@ -361,18 +249,15 @@ } TEST_F(CoordinatorTest, LateAgents) { - base::RunLoop run_loop1; - quit_closure_ = run_loop1.QuitClosure(); auto* agent1 = AddArrayAgent(); - StartTracing("config"); - StopAndFlush(); - if (!quit_closure_.is_null()) - run_loop1.Run(); - base::RunLoop run_loop2; + StartTracing("config", true); + StopAndFlush(); + + base::RunLoop run_loop; auto* agent2 = AddArrayAgent(); agent2->data_.push_back("discarded data"); - run_loop2.RunUntilIdle(); + run_loop.RunUntilIdle(); EXPECT_EQ(2u, agent1->call_stat().size()); EXPECT_EQ("StartTracing", agent1->call_stat()[0]); @@ -384,4 +269,31 @@ EXPECT_EQ("StopAndFlush", agent2->call_stat()[0]); } +TEST_F(CoordinatorTest, WaitForSpecificPIDs) { + coordinator_->AddExpectedPID(42); + coordinator_->AddExpectedPID(4242); + + auto* agent1 = AddArrayAgent(42); + StartTracing("config", true); + base::RunLoop().RunUntilIdle(); + + EXPECT_FALSE(tracing_begin_callback_received()); + + auto* agent2 = AddArrayAgent(4242); + base::RunLoop().RunUntilIdle(); + + EXPECT_TRUE(tracing_begin_callback_received()); + + StopAndFlush(); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(2u, agent1->call_stat().size()); + EXPECT_EQ("StartTracing", agent1->call_stat()[0]); + EXPECT_EQ("StopAndFlush", agent1->call_stat()[1]); + + EXPECT_EQ(2u, agent2->call_stat().size()); + EXPECT_EQ("StartTracing", agent2->call_stat()[0]); + EXPECT_EQ("StopAndFlush", agent2->call_stat()[1]); +} + } // namespace tracing
diff --git a/services/tracing/perfetto/perfetto_tracing_coordinator.cc b/services/tracing/perfetto/perfetto_tracing_coordinator.cc index 3212cbe..d0ddfc7 100644 --- a/services/tracing/perfetto/perfetto_tracing_coordinator.cc +++ b/services/tracing/perfetto/perfetto_tracing_coordinator.cc
@@ -6,6 +6,7 @@ #include <algorithm> #include <utility> +#include <vector> #include "base/bind.h" #include "base/trace_event/trace_log.h" @@ -13,6 +14,7 @@ #include "mojo/public/cpp/system/data_pipe_utils.h" #include "services/tracing/perfetto/json_trace_exporter.h" #include "services/tracing/perfetto/perfetto_service.h" +#include "services/tracing/public/mojom/constants.mojom.h" #include "services/tracing/public/mojom/perfetto_service.mojom.h" #include "third_party/perfetto/include/perfetto/tracing/core/consumer.h" #include "third_party/perfetto/include/perfetto/tracing/core/trace_config.h" @@ -21,15 +23,6 @@ namespace tracing { -namespace { - -bool IsArgumentFilterEnabled(const std::string& config) { - base::trace_event::TraceConfig chrome_trace_config_obj(config); - return chrome_trace_config_obj.IsArgumentFilterEnabled(); -} - -} // namespace - // A TracingSession acts as a perfetto consumer and is used to wrap all the // associated state of an on-going tracing session, for easy setup and cleanup. // @@ -40,21 +33,26 @@ public: TracingSession(const std::string& config, base::OnceClosure tracing_over_callback) - : json_trace_exporter_(std::make_unique<JSONTraceExporter>( - IsArgumentFilterEnabled(config) - ? base::trace_event::TraceLog::GetInstance() - ->GetArgumentFilterPredicate() - : JSONTraceExporter::ArgumentFilterPredicate(), - base::BindRepeating(&TracingSession::OnJSONTraceEventCallback, - base::Unretained(this)))), - tracing_over_callback_(std::move(tracing_over_callback)) { + : tracing_over_callback_(std::move(tracing_over_callback)) { + base::trace_event::TraceConfig chrome_trace_config_obj(config); + json_trace_exporter_.reset(new JSONTraceExporter( + chrome_trace_config_obj.IsArgumentFilterEnabled() + ? base::trace_event::TraceLog::GetInstance() + ->GetArgumentFilterPredicate() + : JSONTraceExporter::ArgumentFilterPredicate(), + base::BindRepeating(&TracingSession::OnJSONTraceEventCallback, + base::Unretained(this)))); perfetto::TracingService* service = PerfettoService::GetInstance()->GetService(); consumer_endpoint_ = service->ConnectConsumer(this, /*uid=*/0); // Start tracing. perfetto::TraceConfig trace_config; - trace_config.add_buffers()->set_size_kb(4096 * 100); + size_t size_limit = chrome_trace_config_obj.GetTraceBufferSizeInKb(); + if (size_limit == 0) { + size_limit = 400 * 1024; + } + trace_config.add_buffers()->set_size_kb(size_limit); // Perfetto uses clock_gettime for its internal snapshotting, which gets // blocked by the sandboxed and isn't needed for Chrome regardless. @@ -200,6 +198,11 @@ binding_(this), weak_factory_(this) { DETACH_FROM_SEQUENCE(sequence_checker_); + + agent_registry->SetAgentInitializationCallback( + base::BindRepeating(&PerfettoTracingCoordinator::OnNewAgentConnected, + weak_factory_.GetWeakPtr()), + false /* call_on_new_agents_only */); } PerfettoTracingCoordinator::~PerfettoTracingCoordinator() { @@ -222,11 +225,44 @@ base::Unretained(this))); } -void PerfettoTracingCoordinator::StartTracing(const std::string& config) { +void PerfettoTracingCoordinator::StartTracing(const std::string& config, + StartTracingCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + parsed_config_ = base::trace_event::TraceConfig(config); tracing_session_ = std::make_unique<TracingSession>( config, base::BindOnce(&PerfettoTracingCoordinator::OnTracingOverCallback, weak_factory_.GetWeakPtr())); + + SetStartTracingCallback(std::move(callback)); +} + +void PerfettoTracingCoordinator::OnNewAgentConnected( + AgentRegistry::AgentEntry* agent_entry) { + // TODO(oysteine): While we're still using the Agent + // system as a fallback when using Perfetto, rather than + // the browser directly using a Consumer interface, we have to + // attempt to linearize with newly connected agents so we only + // call the BeginTracing callback when we can be fairly sure + // that all current agents have registered with Perfetto and + // started tracing if requested. We do this linearization + // by calling RequestBufferStatus but just throwing away the + // result. + agent_entry->AddDisconnectClosure(GetStartTracingClosureName(), + base::DoNothing()); + + agent_entry->agent()->RequestBufferStatus(base::BindRepeating( + [](base::WeakPtr<PerfettoTracingCoordinator> coordinator, + AgentRegistry::AgentEntry* agent_entry, uint32_t capacity, + uint32_t count) { + bool removed = + agent_entry->RemoveDisconnectClosure(GetStartTracingClosureName()); + DCHECK(removed); + + if (coordinator) { + coordinator->RemoveExpectedPID(agent_entry->pid()); + } + }, + weak_factory_.GetWeakPtr(), base::Unretained(agent_entry))); } void PerfettoTracingCoordinator::OnTracingOverCallback() { @@ -238,8 +274,25 @@ void PerfettoTracingCoordinator::StopAndFlush( mojo::ScopedDataPipeProducerHandle stream, StopAndFlushCallback callback) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(tracing_session_); + StopAndFlushAgent(std::move(stream), "", std::move(callback)); +} + +void PerfettoTracingCoordinator::StopAndFlushInternal( + mojo::ScopedDataPipeProducerHandle stream, + StopAndFlushCallback callback) { + if (start_tracing_callback_) { + // We received a |StopAndFlush| command before receiving |StartTracing| acks + // from all agents. Let's retry after a delay. + task_runner_->PostDelayedTask( + FROM_HERE, + base::BindOnce(&PerfettoTracingCoordinator::StopAndFlushInternal, + weak_factory_.GetWeakPtr(), std::move(stream), + std::move(callback)), + base::TimeDelta::FromMilliseconds( + mojom::kStopTracingRetryTimeMilliseconds)); + return; + } + tracing_session_->StopAndFlush(std::move(stream), std::move(callback)); } @@ -247,7 +300,11 @@ mojo::ScopedDataPipeProducerHandle stream, const std::string& agent_label, StopAndFlushCallback callback) { - NOTREACHED(); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(tracing_session_); + + ClearConnectedPIDs(); + StopAndFlushInternal(std::move(stream), std::move(callback)); } void PerfettoTracingCoordinator::IsTracing(IsTracingCallback callback) {
diff --git a/services/tracing/perfetto/perfetto_tracing_coordinator.h b/services/tracing/perfetto/perfetto_tracing_coordinator.h index 6db0495..554346b 100644 --- a/services/tracing/perfetto/perfetto_tracing_coordinator.h +++ b/services/tracing/perfetto/perfetto_tracing_coordinator.h
@@ -37,7 +37,8 @@ // mojom::Coordinator implementation. // Called by the tracing controller. - void StartTracing(const std::string& config) override; + void StartTracing(const std::string& config, + StartTracingCallback callback) override; void StopAndFlush(mojo::ScopedDataPipeProducerHandle stream, StopAndFlushCallback callback) override; void StopAndFlushAgent(mojo::ScopedDataPipeProducerHandle stream, @@ -49,6 +50,9 @@ private: void OnTracingOverCallback(); void OnClientConnectionError() override; + void OnNewAgentConnected(AgentRegistry::AgentEntry* agent_entry); + void StopAndFlushInternal(mojo::ScopedDataPipeProducerHandle stream, + StopAndFlushCallback callback); mojo::Binding<mojom::Coordinator> binding_;
diff --git a/services/tracing/perfetto/perfetto_tracing_coordinator_unittest.cc b/services/tracing/perfetto/perfetto_tracing_coordinator_unittest.cc new file mode 100644 index 0000000..ac471fd --- /dev/null +++ b/services/tracing/perfetto/perfetto_tracing_coordinator_unittest.cc
@@ -0,0 +1,49 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/tracing/perfetto/perfetto_tracing_coordinator.h" + +#include "base/json/json_reader.h" +#include "services/tracing/coordinator_test_util.h" +#include "services/tracing/test_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace tracing { + +class PerfettoCoordinatorTest : public testing::Test, + public CoordinatorTestUtil { + public: + void SetUp() override { + CoordinatorTestUtil::SetUp(); + coordinator_ = std::make_unique<PerfettoTracingCoordinator>( + agent_registry(), base::RepeatingClosure()); + coordinator_->FinishedReceivingRunningPIDs(); + } + void TearDown() override { CoordinatorTestUtil::TearDown(); } +}; + +TEST_F(PerfettoCoordinatorTest, TraceBufferSizeInBytes) { + auto* agent = AddArrayAgent(); + agent->data_.push_back("e1"); + + StartTracing("{\"trace_buffer_size_in_kb\":4}", true); + std::string output = StopAndFlush(); + + auto json_value = base::JSONReader::Read(output); + ASSERT_TRUE(json_value); + + const base::DictionaryValue* dict = nullptr; + json_value->GetAsDictionary(&dict); + ASSERT_TRUE(dict->GetDictionary("metadata", &dict)); + ASSERT_TRUE(dict->GetDictionary("perfetto_trace_stats", &dict)); + const base::ListValue* list = nullptr; + ASSERT_TRUE(dict->GetList("buffer_stats", &list)); + EXPECT_EQ(1u, list->GetSize()); + ASSERT_TRUE(list->GetDictionary(0, &dict)); + int buffer_size = 0; + ASSERT_TRUE(dict->GetInteger("buffer_size", &buffer_size)); + EXPECT_EQ(4096, buffer_size); +} + +} // namespace tracing
diff --git a/services/tracing/public/cpp/base_agent.cc b/services/tracing/public/cpp/base_agent.cc index 0e14ac9..d31c1a9b2 100644 --- a/services/tracing/public/cpp/base_agent.cc +++ b/services/tracing/public/cpp/base_agent.cc
@@ -39,7 +39,10 @@ } void BaseAgent::StartTracing(const std::string& config, - base::TimeTicks coordinator_time) {} + base::TimeTicks coordinator_time, + Agent::StartTracingCallback callback) { + std::move(callback).Run(true /* success */); +} void BaseAgent::StopAndFlush(tracing::mojom::RecorderPtr recorder) {}
diff --git a/services/tracing/public/cpp/base_agent.h b/services/tracing/public/cpp/base_agent.h index dc1325d..8be2cf54 100644 --- a/services/tracing/public/cpp/base_agent.h +++ b/services/tracing/public/cpp/base_agent.h
@@ -35,7 +35,8 @@ // tracing::mojom::Agent: void StartTracing(const std::string& config, - base::TimeTicks coordinator_time) override; + base::TimeTicks coordinator_time, + Agent::StartTracingCallback callback) override; void StopAndFlush(tracing::mojom::RecorderPtr recorder) override; void RequestBufferStatus( Agent::RequestBufferStatusCallback callback) override;
diff --git a/services/tracing/public/cpp/trace_event_agent.cc b/services/tracing/public/cpp/trace_event_agent.cc index 88e25d8..94cc70a 100644 --- a/services/tracing/public/cpp/trace_event_agent.cc +++ b/services/tracing/public/cpp/trace_event_agent.cc
@@ -72,7 +72,8 @@ } void TraceEventAgent::StartTracing(const std::string& config, - base::TimeTicks coordinator_time) { + base::TimeTicks coordinator_time, + StartTracingCallback callback) { DCHECK(!recorder_); #if defined(__native_client__) // NaCl and system times are offset by a bit, so subtract some time from @@ -87,6 +88,7 @@ enabled_tracing_modes_ |= base::trace_event::TraceLog::FILTERING_MODE; base::trace_event::TraceLog::GetInstance()->SetEnabled( trace_config, enabled_tracing_modes_); + std::move(callback).Run(true); } void TraceEventAgent::StopAndFlush(mojom::RecorderPtr recorder) {
diff --git a/services/tracing/public/cpp/trace_event_agent.h b/services/tracing/public/cpp/trace_event_agent.h index 1a7c8915..70063d2 100644 --- a/services/tracing/public/cpp/trace_event_agent.h +++ b/services/tracing/public/cpp/trace_event_agent.h
@@ -49,7 +49,8 @@ // mojom::Agent void StartTracing(const std::string& config, - base::TimeTicks coordinator_time) override; + base::TimeTicks coordinator_time, + StartTracingCallback callback) override; void StopAndFlush(mojom::RecorderPtr recorder) override; void RequestBufferStatus(RequestBufferStatusCallback callback) override;
diff --git a/services/tracing/public/cpp/trace_event_agent_unittest.cc b/services/tracing/public/cpp/trace_event_agent_unittest.cc index 443dd11..9749aac3 100644 --- a/services/tracing/public/cpp/trace_event_agent_unittest.cc +++ b/services/tracing/public/cpp/trace_event_agent_unittest.cc
@@ -90,7 +90,8 @@ void StartTracing(const std::string& categories) { TraceEventAgent::GetInstance()->StartTracing( base::trace_event::TraceConfig(categories, "").ToString(), - base::TimeTicks::Now()); + base::TimeTicks::Now(), + base::BindRepeating([](bool success) { EXPECT_TRUE(success); })); } void StopAndFlush(base::Closure quit_closure) {
diff --git a/services/tracing/public/mojom/constants.mojom b/services/tracing/public/mojom/constants.mojom index d258406d..f62a072 100644 --- a/services/tracing/public/mojom/constants.mojom +++ b/services/tracing/public/mojom/constants.mojom
@@ -4,6 +4,8 @@ module tracing.mojom; +const uint32 kStopTracingRetryTimeMilliseconds = 100; + const string kServiceName = "tracing"; // The label of agents that provide trace data of the format explained in
diff --git a/services/tracing/public/mojom/tracing.mojom b/services/tracing/public/mojom/tracing.mojom index 8c081774..3c282c4 100644 --- a/services/tracing/public/mojom/tracing.mojom +++ b/services/tracing/public/mojom/tracing.mojom
@@ -39,7 +39,8 @@ // close the recorder connection to signal the tracing service that no more data // will be sent. interface Agent { - StartTracing(string config, mojo_base.mojom.TimeTicks coordinator_time); + StartTracing(string config, mojo_base.mojom.TimeTicks coordinator_time) + => (bool success); StopAndFlush(Recorder recorder); RequestBufferStatus() => (uint32 capacity, uint32 count); }; @@ -60,7 +61,7 @@ // The return value is false if tracing is already enabled with a different // config. Otherwise, true is returned as soon as the service receives acks // from all existing agents and agents that connect during |StartTracing|. - StartTracing(string config); + StartTracing(string config) => (bool success); StopAndFlush(handle<data_pipe_producer> stream) => (mojo_base.mojom.DictionaryValue metadata); // Same as |StopAndFlush| but only write data from a certain |agent_label| to
diff --git a/services/tracing/test_util.cc b/services/tracing/test_util.cc index e514302..1bce1291 100644 --- a/services/tracing/test_util.cc +++ b/services/tracing/test_util.cc
@@ -21,8 +21,10 @@ } void MockAgent::StartTracing(const std::string& config, - base::TimeTicks coordinator_time) { + base::TimeTicks coordinator_time, + StartTracingCallback cb) { call_stat_.push_back("StartTracing"); + std::move(cb).Run(true); } void MockAgent::StopAndFlush(mojom::RecorderPtr recorder) {
diff --git a/services/tracing/test_util.h b/services/tracing/test_util.h index 948f30c..821a7eb0 100644 --- a/services/tracing/test_util.h +++ b/services/tracing/test_util.h
@@ -37,7 +37,8 @@ private: // mojom::Agent void StartTracing(const std::string& config, - base::TimeTicks coordinator_time) override; + base::TimeTicks coordinator_time, + StartTracingCallback cb) override; void StopAndFlush(mojom::RecorderPtr recorder) override; void RequestBufferStatus(RequestBufferStatusCallback cb) override;
diff --git a/services/tracing/tracing_service.cc b/services/tracing/tracing_service.cc index 1a08557..d277c63 100644 --- a/services/tracing/tracing_service.cc +++ b/services/tracing/tracing_service.cc
@@ -4,6 +4,7 @@ #include "services/tracing/tracing_service.h" +#include <map> #include <utility> #include <vector> @@ -25,10 +26,12 @@ class ServiceListener : public service_manager::mojom::ServiceManagerListener { public: ServiceListener(service_manager::Connector* connector, - AgentRegistry* agent_registry) + AgentRegistry* agent_registry, + Coordinator* coordinator) : binding_(this), connector_(connector), - agent_registry_(agent_registry) { + agent_registry_(agent_registry), + coordinator_(coordinator) { service_manager::mojom::ServiceManagerPtr service_manager; connector_->BindInterface(service_manager::mojom::kServiceName, &service_manager); @@ -58,31 +61,75 @@ traced_process->ConnectToTracingService(std::move(new_connection_request)); } + size_t CountServicesWithPID(uint32_t pid) { + return std::count_if(service_pid_map_.begin(), service_pid_map_.end(), + [pid](decltype(service_pid_map_)::value_type p) { + return p.second == pid; + }); + } + + void ServiceAddedWithPID(const service_manager::Identity& identity, + uint32_t pid) { + service_pid_map_[identity] = pid; + // First service with this PID added; expect a connection from it. + if (CountServicesWithPID(pid) == 1) { + coordinator_->AddExpectedPID(pid); + ConnectProcessToTracingService(identity); + } + } + + void ServiceRemoved(const service_manager::Identity& identity) { + auto entry = service_pid_map_.find(identity); + if (entry != service_pid_map_.end()) { + uint32_t pid = entry->second; + service_pid_map_.erase(entry); + // Last entry with this PID removed; stop expecting it + // to connect to the tracing service. + if (CountServicesWithPID(pid) == 0) { + coordinator_->RemoveExpectedPID(pid); + } + } + } + // service_manager::mojom::ServiceManagerListener implementation. void OnInit(std::vector<service_manager::mojom::RunningServiceInfoPtr> running_services) override { for (auto& service : running_services) { - ConnectProcessToTracingService(service->identity); + if (service->pid) { + ServiceAddedWithPID(service->identity, service->pid); + } } + + coordinator_->FinishedReceivingRunningPIDs(); + } + + void OnServicePIDReceived(const service_manager::Identity& identity, + uint32_t pid) override { + ServiceAddedWithPID(identity, pid); + } + + void OnServiceFailedToStart( + const service_manager::Identity& identity) override { + ServiceRemoved(identity); + } + + void OnServiceStopped(const service_manager::Identity& identity) override { + ServiceRemoved(identity); } void OnServiceStarted(const service_manager::Identity& identity, uint32_t pid) override { - ConnectProcessToTracingService(identity); } void OnServiceCreated( service_manager::mojom::RunningServiceInfoPtr service) override {} - void OnServicePIDReceived(const service_manager::Identity& identity, - uint32_t pid) override {} - void OnServiceFailedToStart( - const service_manager::Identity& identity) override {} - void OnServiceStopped(const service_manager::Identity& identity) override {} private: mojo::Binding<service_manager::mojom::ServiceManagerListener> binding_; service_manager::Connector* connector_; AgentRegistry* agent_registry_; + Coordinator* coordinator_; + std::map<service_manager::Identity, uint32_t> service_pid_map_; }; TracingService::TracingService(service_manager::mojom::ServiceRequest request) @@ -105,7 +152,7 @@ registry_.AddInterface( base::BindRepeating(&PerfettoTracingCoordinator::BindCoordinatorRequest, base::Unretained(perfetto_coordinator.get()))); - perfetto_tracing_coordinator_ = std::move(perfetto_coordinator); + tracing_coordinator_ = std::move(perfetto_coordinator); } else { auto tracing_coordinator = std::make_unique<Coordinator>( tracing_agent_registry_.get(), @@ -118,7 +165,8 @@ } service_listener_ = std::make_unique<ServiceListener>( - service_binding_.GetConnector(), tracing_agent_registry_.get()); + service_binding_.GetConnector(), tracing_agent_registry_.get(), + tracing_coordinator_.get()); } void TracingService::OnBindInterface(
diff --git a/services/tracing/tracing_service.h b/services/tracing/tracing_service.h index 298c504..0ff7bbfa3 100644 --- a/services/tracing/tracing_service.h +++ b/services/tracing/tracing_service.h
@@ -22,7 +22,6 @@ namespace tracing { class ServiceListener; -class PerfettoTracingCoordinator; class TracingService : public service_manager::Service { public: @@ -47,7 +46,6 @@ registry_; std::unique_ptr<tracing::AgentRegistry> tracing_agent_registry_; std::unique_ptr<Coordinator> tracing_coordinator_; - std::unique_ptr<PerfettoTracingCoordinator> perfetto_tracing_coordinator_; std::unique_ptr<ServiceListener> service_listener_;
diff --git a/services/video_capture/BUILD.gn b/services/video_capture/BUILD.gn index a8bdf6f..60a4948 100644 --- a/services/video_capture/BUILD.gn +++ b/services/video_capture/BUILD.gn
@@ -66,6 +66,10 @@ "//services/video_capture/public/uma", "//services/ws/public/cpp/gpu:gpu", ] + + if (is_chromeos) { + public_deps += [ "//media/capture/video/chromeos/mojo:cros_camera" ] + } } source_set("tests") {
diff --git a/services/video_capture/device_factory.h b/services/video_capture/device_factory.h index 07af7dd4..4fe8376 100644 --- a/services/video_capture/device_factory.h +++ b/services/video_capture/device_factory.h
@@ -8,12 +8,20 @@ #include "services/service_manager/public/cpp/service_context_ref.h" #include "services/video_capture/public/mojom/device_factory.mojom.h" +#if defined(OS_CHROMEOS) +#include "media/capture/video/chromeos/mojo/cros_image_capture.mojom.h" +#endif // defined(OS_CHROMEOS) + namespace video_capture { class DeviceFactory : public mojom::DeviceFactory { public: virtual void SetServiceRef( std::unique_ptr<service_manager::ServiceContextRef> service_ref) = 0; +#if defined(OS_CHROMEOS) + virtual void BindCrosImageCaptureRequest( + cros::mojom::CrosImageCaptureRequest request) = 0; +#endif // defined(OS_CHROMEOS) }; } // namespace video_capture
diff --git a/services/video_capture/device_factory_media_to_mojo_adapter.cc b/services/video_capture/device_factory_media_to_mojo_adapter.cc index ba80b1c..d8a6fdc 100644 --- a/services/video_capture/device_factory_media_to_mojo_adapter.cc +++ b/services/video_capture/device_factory_media_to_mojo_adapter.cc
@@ -5,6 +5,7 @@ #include "services/video_capture/device_factory_media_to_mojo_adapter.h" #include <sstream> +#include <utility> #include "base/bind.h" #include "base/logging.h" @@ -194,4 +195,13 @@ active_devices_by_id_.erase(device_id); } +#if defined(OS_CHROMEOS) +void DeviceFactoryMediaToMojoAdapter::BindCrosImageCaptureRequest( + cros::mojom::CrosImageCaptureRequest request) { + CHECK(capture_system_); + + capture_system_->BindCrosImageCaptureRequest(std::move(request)); +} +#endif // defined(OS_CHROMEOS) + } // namespace video_capture
diff --git a/services/video_capture/device_factory_media_to_mojo_adapter.h b/services/video_capture/device_factory_media_to_mojo_adapter.h index d2d0fa3..0122958 100644 --- a/services/video_capture/device_factory_media_to_mojo_adapter.h +++ b/services/video_capture/device_factory_media_to_mojo_adapter.h
@@ -13,6 +13,10 @@ #include "services/service_manager/public/cpp/service_context_ref.h" #include "services/video_capture/device_factory.h" +#if defined(OS_CHROMEOS) +#include "media/capture/video/chromeos/mojo/cros_image_capture.mojom.h" +#endif // defined(OS_CHROMEOS) + namespace video_capture { class DeviceMediaToMojoAdapter; @@ -48,6 +52,11 @@ mojom::DevicesChangedObserverPtr observer, bool raise_event_if_virtual_devices_already_present) override; +#if defined(OS_CHROMEOS) + void BindCrosImageCaptureRequest( + cros::mojom::CrosImageCaptureRequest request) override; +#endif // defined(OS_CHROMEOS) + private: struct ActiveDeviceEntry { ActiveDeviceEntry();
diff --git a/services/video_capture/device_factory_provider_impl.cc b/services/video_capture/device_factory_provider_impl.cc index 14ee298..c73f826 100644 --- a/services/video_capture/device_factory_provider_impl.cc +++ b/services/video_capture/device_factory_provider_impl.cc
@@ -4,6 +4,8 @@ #include "services/video_capture/device_factory_provider_impl.h" +#include <utility> + #include "base/bind.h" #include "base/task/post_task.h" #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" @@ -176,4 +178,13 @@ device_factory_->SetServiceRef(nullptr); } +#if defined(OS_CHROMEOS) +void DeviceFactoryProviderImpl::BindCrosImageCaptureRequest( + cros::mojom::CrosImageCaptureRequest request) { + CHECK(device_factory_); + + device_factory_->BindCrosImageCaptureRequest(std::move(request)); +} +#endif // defined(OS_CHROMEOS) + } // namespace video_capture
diff --git a/services/video_capture/device_factory_provider_impl.h b/services/video_capture/device_factory_provider_impl.h index e42a6188..5000a6a0 100644 --- a/services/video_capture/device_factory_provider_impl.h +++ b/services/video_capture/device_factory_provider_impl.h
@@ -18,6 +18,10 @@ #include "services/video_capture/public/mojom/device_factory_provider.mojom.h" #include "services/video_capture/public/mojom/video_source_provider.mojom.h" +#if defined(OS_CHROMEOS) +#include "media/capture/video/chromeos/mojo/cros_image_capture.mojom.h" +#endif // defined(OS_CHROMEOS) + namespace video_capture { class VirtualDeviceEnabledDeviceFactory; @@ -40,6 +44,11 @@ mojom::VideoSourceProviderRequest request) override; void ShutdownServiceAsap() override; +#if defined(OS_CHROMEOS) + void BindCrosImageCaptureRequest( + cros::mojom::CrosImageCaptureRequest request); +#endif // defined(OS_CHROMEOS) + private: class GpuDependenciesContext;
diff --git a/services/video_capture/public/cpp/BUILD.gn b/services/video_capture/public/cpp/BUILD.gn index 5388362..07fdfdaa 100644 --- a/services/video_capture/public/cpp/BUILD.gn +++ b/services/video_capture/public/cpp/BUILD.gn
@@ -34,6 +34,9 @@ "//services/video_capture/public/mojom", "//services/video_capture/public/mojom:constants", ] + if (is_chromeos) { + deps += [ "//media/capture/video/chromeos/mojo:cros_camera" ] + } } source_set("mocks") {
diff --git a/services/video_capture/public/cpp/manifest.cc b/services/video_capture/public/cpp/manifest.cc index 37a1937..89e38fc 100644 --- a/services/video_capture/public/cpp/manifest.cc +++ b/services/video_capture/public/cpp/manifest.cc
@@ -5,6 +5,9 @@ #include "services/video_capture/public/cpp/manifest.h" #include "base/no_destructor.h" +#if defined(OS_CHROMEOS) +#include "media/capture/video/chromeos/mojo/cros_image_capture.mojom.h" +#endif // defined(OS_CHROMEOS) #include "services/service_manager/public/cpp/manifest_builder.h" #include "services/video_capture/public/mojom/constants.mojom.h" #include "services/video_capture/public/mojom/device_factory_provider.mojom.h" @@ -14,22 +17,26 @@ const service_manager::Manifest& GetManifest() { static base::NoDestructor<service_manager::Manifest> manifest{ - service_manager::ManifestBuilder() - .WithServiceName(mojom::kServiceName) - .WithDisplayName("Video Capture") - .WithOptions(service_manager::ManifestOptionsBuilder() - .WithSandboxType("none") - .WithInstanceSharingPolicy( - service_manager::Manifest:: - InstanceSharingPolicy::kSharedAcrossGroups) - .Build()) - .ExposeCapability("capture", service_manager::Manifest::InterfaceList< - mojom::DeviceFactoryProvider>()) - .ExposeCapability( - "tests", - service_manager::Manifest::InterfaceList< - mojom::DeviceFactoryProvider, mojom::TestingControls>()) - .Build()}; + service_manager::ManifestBuilder() + .WithServiceName(mojom::kServiceName) + .WithDisplayName("Video Capture") + .WithOptions(service_manager::ManifestOptionsBuilder() + .WithSandboxType("none") + .WithInstanceSharingPolicy( + service_manager::Manifest::InstanceSharingPolicy:: + kSharedAcrossGroups) + .Build()) + .ExposeCapability("capture", service_manager::Manifest::InterfaceList< +#if defined(OS_CHROMEOS) + cros::mojom::CrosImageCapture, +#endif // defined(OS_CHROMEOS) + mojom::DeviceFactoryProvider>()) + .ExposeCapability( + "tests", + service_manager::Manifest::InterfaceList< + mojom::DeviceFactoryProvider, mojom::TestingControls>()) + .Build() + }; return *manifest; }
diff --git a/services/video_capture/service_impl.cc b/services/video_capture/service_impl.cc index 46eff00..5bf1432 100644 --- a/services/video_capture/service_impl.cc +++ b/services/video_capture/service_impl.cc
@@ -4,6 +4,8 @@ #include "services/video_capture/service_impl.h" +#include <utility> + #include "base/bind.h" #include "build/build_config.h" #include "mojo/public/cpp/bindings/strong_binding.h" @@ -12,6 +14,10 @@ #include "services/video_capture/public/uma/video_capture_service_event.h" #include "services/video_capture/testing_controls_impl.h" +#if defined(OS_CHROMEOS) +#include "media/capture/video/chromeos/mojo/cros_image_capture.mojom.h" +#endif // defined(OS_CHROMEOS) + namespace video_capture { namespace { @@ -92,6 +98,11 @@ base::BindRepeating(&ServiceImpl::OnTestingControlsRequest, base::Unretained(this))); +#if defined(OS_CHROMEOS) + registry_.AddInterface<cros::mojom::CrosImageCapture>(base::BindRepeating( + &ServiceImpl::OnCrosImageCaptureRequest, base::Unretained(this))); +#endif // defined(OS_CHROMEOS) + // Unretained |this| is safe because |factory_provider_bindings_| is owned by // |this|. factory_provider_bindings_.set_connection_error_handler(base::BindRepeating( @@ -145,6 +156,14 @@ std::move(request)); } +#if defined(OS_CHROMEOS) +void ServiceImpl::OnCrosImageCaptureRequest( + cros::mojom::CrosImageCaptureRequest request) { + LazyInitializeDeviceFactoryProvider(); + device_factory_provider_->BindCrosImageCaptureRequest(std::move(request)); +} +#endif // defined(OS_CHROMEOS) + void ServiceImpl::LazyInitializeDeviceFactoryProvider() { if (device_factory_provider_) return;
diff --git a/services/video_capture/service_impl.h b/services/video_capture/service_impl.h index b9f234f..65b2a12a 100644 --- a/services/video_capture/service_impl.h +++ b/services/video_capture/service_impl.h
@@ -24,6 +24,10 @@ #include "base/win/scoped_com_initializer.h" #endif +#if defined(OS_CHROMEOS) +#include "media/capture/video/chromeos/mojo/cros_image_capture.mojom.h" +#endif // defined(OS_CHROMEOS) + namespace base { class SingleThreadTaskRunner; } @@ -68,6 +72,9 @@ void OnDeviceFactoryProviderRequest( mojom::DeviceFactoryProviderRequest request); void OnTestingControlsRequest(mojom::TestingControlsRequest request); +#if defined(OS_CHROMEOS) + void OnCrosImageCaptureRequest(cros::mojom::CrosImageCaptureRequest request); +#endif // defined(OS_CHROMEOS) void MaybeRequestQuitDelayed(); void MaybeRequestQuit(); void LazyInitializeDeviceFactoryProvider();
diff --git a/services/video_capture/virtual_device_enabled_device_factory.cc b/services/video_capture/virtual_device_enabled_device_factory.cc index 3448093..131d981 100644 --- a/services/video_capture/virtual_device_enabled_device_factory.cc +++ b/services/video_capture/virtual_device_enabled_device_factory.cc
@@ -253,4 +253,13 @@ devices_changed_observers_.erase(iter); } +#if defined(OS_CHROMEOS) +void VirtualDeviceEnabledDeviceFactory::BindCrosImageCaptureRequest( + cros::mojom::CrosImageCaptureRequest request) { + CHECK(device_factory_); + + device_factory_->BindCrosImageCaptureRequest(std::move(request)); +} +#endif // defined(OS_CHROMEOS) + } // namespace video_capture
diff --git a/services/video_capture/virtual_device_enabled_device_factory.h b/services/video_capture/virtual_device_enabled_device_factory.h index ec508ea..ac6a644 100644 --- a/services/video_capture/virtual_device_enabled_device_factory.h +++ b/services/video_capture/virtual_device_enabled_device_factory.h
@@ -6,6 +6,7 @@ #define SERVICES_VIDEO_CAPTURE_VIRTUAL_DEVICE_ENABLED_DEVICE_FACTORY_H_ #include <map> +#include <utility> #include "mojo/public/cpp/bindings/binding.h" #include "services/service_manager/public/cpp/service_context_ref.h" @@ -13,6 +14,10 @@ #include "services/video_capture/public/mojom/device.mojom.h" #include "services/video_capture/public/mojom/virtual_device.mojom.h" +#if defined(OS_CHROMEOS) +#include "media/capture/video/chromeos/mojo/cros_image_capture.mojom.h" +#endif // defined(OS_CHROMEOS) + namespace video_capture { // Decorator that adds support for virtual devices to a given DeviceFactory. @@ -41,6 +46,11 @@ mojom::DevicesChangedObserverPtr observer, bool raise_event_if_virtual_devices_already_present) override; +#if defined(OS_CHROMEOS) + void BindCrosImageCaptureRequest( + cros::mojom::CrosImageCaptureRequest request) override; +#endif // defined(OS_CHROMEOS) + private: class VirtualDeviceEntry;
diff --git a/third_party/blink/public/web/web_widget.h b/third_party/blink/public/web/web_widget.h index a7da4679..42de1cd7 100644 --- a/third_party/blink/public/web/web_widget.h +++ b/third_party/blink/public/web/web_widget.h
@@ -101,9 +101,6 @@ virtual void BeginFrame(base::TimeTicks last_frame_time, bool record_main_frame_metrics) {} - // Called after UpdateAllLifecyclePhases has run in response to a BeginFrame. - virtual void DidBeginFrame() {} - // Called when main frame metrics are desired. The local frame's UKM // aggregator must be informed that collection is starting for the // frame.
diff --git a/third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h b/third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h index 6080546a..144b9e42 100644 --- a/third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h +++ b/third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h
@@ -6,8 +6,10 @@ #define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_ACTIVE_SCRIPT_WRAPPABLE_H_ #include "base/macros.h" +#include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h" +#include "third_party/blink/renderer/platform/wtf/casting.h" namespace blink { @@ -48,13 +50,31 @@ bool IsContextDestroyed() const final { const auto* execution_context = static_cast<const T*>(this)->GetExecutionContext(); - return !execution_context || execution_context->IsContextDestroyed(); + if (!execution_context) + return true; + + if (execution_context->IsContextDestroyed()) + return true; + + if (const auto* doc = DynamicTo<Document>(execution_context)) { + // Not all Document objects have an ExecutionContext that is actually + // destroyed. In such cases we defer to the ContextDocument if possible. + // If no such Document exists we consider the ExecutionContext as + // destroyed. This is needed to ensure that an ActiveScriptWrappable that + // always returns true in HasPendingActivity does not result in a memory + // leak. + const Document* context_doc = doc->ContextDocument(); + if (!context_doc) + return true; + return context_doc->IsContextDestroyed(); + } + + return false; } bool DispatchHasPendingActivity() const final { return static_cast<const T*>(this)->HasPendingActivity(); } - ScriptWrappable* ToScriptWrappable() final { return static_cast<T*>(this); } private:
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_threaded_test.cc b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_threaded_test.cc index 1fd3bfde..387060f 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_threaded_test.cc +++ b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_threaded_test.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h" +#include "base/synchronization/waitable_event.h" #include "build/build_config.h" #include "third_party/blink/renderer/bindings/core/v8/serialization/unpacked_serialized_script_value.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" @@ -68,10 +69,10 @@ // Wait for a subsequent task on the worker to finish, to ensure that the // references held by the task are dropped. - WaitableEvent done; + base::WaitableEvent done; worker_thread.GetWorkerBackingThread().BackingThread().PostTask( - FROM_HERE, - CrossThreadBind(&WaitableEvent::Signal, CrossThreadUnretained(&done))); + FROM_HERE, CrossThreadBind(&base::WaitableEvent::Signal, + CrossThreadUnretained(&done))); done.Wait(); // Now destroy the value on the main thread.
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h b/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h index 6b817eea..65f3e3f 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h +++ b/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h
@@ -177,6 +177,19 @@ V8SetReturnValueFast(callbackInfo, notShared.View(), wrappable); } +template <typename CallbackInfo, typename T> +inline void V8SetReturnValue(const CallbackInfo& callback_info, + MaybeShared<T> maybe_shared) { + V8SetReturnValue(callback_info, maybe_shared.View()); +} + +template <typename CallbackInfo, typename T> +inline void V8SetReturnValueFast(const CallbackInfo& callback_info, + MaybeShared<T> maybe_shared, + const ScriptWrappable* wrappable) { + V8SetReturnValueFast(callback_info, maybe_shared.View(), wrappable); +} + // Specialized overload, used by interface indexed property handlers in their // descriptor callbacks, which need an actual V8 Object with the properties of // a property descriptor.
diff --git a/third_party/blink/renderer/bindings/scripts/v8_methods.py b/third_party/blink/renderer/bindings/scripts/v8_methods.py index 6d067908..846035a 100644 --- a/third_party/blink/renderer/bindings/scripts/v8_methods.py +++ b/third_party/blink/renderer/bindings/scripts/v8_methods.py
@@ -188,7 +188,8 @@ 'arguments': argument_contexts, 'camel_case_name': NameStyleConverter(name).to_upper_camel_case(), 'cpp_type': (v8_types.cpp_template_type('base::Optional', idl_type.cpp_type) - if idl_type.is_explicit_nullable else idl_type.cpp_type), + if idl_type.is_explicit_nullable + else v8_types.cpp_type(idl_type, extended_attributes=extended_attributes)), 'cpp_value': this_cpp_value, 'cpp_type_initializer': idl_type.cpp_type_initializer, 'high_entropy': v8_utilities.high_entropy(method), # [HighEntropy]
diff --git a/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc b/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc index d276588..95bd0b92 100644 --- a/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc +++ b/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc
@@ -6,6 +6,7 @@ #include <memory> #include "base/single_thread_task_runner.h" +#include "base/synchronization/waitable_event.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/core/css/cssom/cross_thread_keyword_value.h" #include "third_party/blink/renderer/core/css/cssom/cross_thread_unit_value.h" @@ -15,21 +16,20 @@ #include "third_party/blink/renderer/core/css/cssom/css_unit_value.h" #include "third_party/blink/renderer/platform/cross_thread_functional.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/waitable_event.h" #include "third_party/blink/renderer/platform/web_thread_supporting_gc.h" namespace blink { class CrossThreadStyleValueTest : public testing::Test { public: - void ShutDown(WaitableEvent* waitable_event) { + void ShutDown(base::WaitableEvent* waitable_event) { DCHECK(!IsMainThread()); thread_->ShutdownOnThread(); waitable_event->Signal(); } void ShutDownThread() { - WaitableEvent waitable_event; + base::WaitableEvent waitable_event; thread_->PostTask(FROM_HERE, CrossThreadBind(&CrossThreadStyleValueTest::ShutDown, CrossThreadUnretained(this), @@ -38,7 +38,7 @@ } void CheckUnsupportedValue( - WaitableEvent* waitable_event, + base::WaitableEvent* waitable_event, std::unique_ptr<CrossThreadUnsupportedValue> value) { DCHECK(!IsMainThread()); thread_->InitializeOnThread(); @@ -47,7 +47,7 @@ waitable_event->Signal(); } - void CheckKeywordValue(WaitableEvent* waitable_event, + void CheckKeywordValue(base::WaitableEvent* waitable_event, std::unique_ptr<CrossThreadKeywordValue> value) { DCHECK(!IsMainThread()); thread_->InitializeOnThread(); @@ -56,7 +56,7 @@ waitable_event->Signal(); } - void CheckUnitValue(WaitableEvent* waitable_event, + void CheckUnitValue(base::WaitableEvent* waitable_event, std::unique_ptr<CrossThreadUnitValue> value) { DCHECK(!IsMainThread()); thread_->InitializeOnThread(); @@ -80,7 +80,7 @@ // Use a WebThreadSupportingGC to emulate worklet thread. thread_ = WebThreadSupportingGC::Create( ThreadCreationParams(WebThreadType::kTestThread)); - WaitableEvent waitable_event; + base::WaitableEvent waitable_event; thread_->PostTask( FROM_HERE, CrossThreadBind(&CrossThreadStyleValueTest::CheckUnsupportedValue, @@ -111,7 +111,7 @@ // Use a WebThreadSupportingGC to emulate worklet thread. thread_ = WebThreadSupportingGC::Create( ThreadCreationParams(WebThreadType::kTestThread)); - WaitableEvent waitable_event; + base::WaitableEvent waitable_event; thread_->PostTask( FROM_HERE, CrossThreadBind(&CrossThreadStyleValueTest::CheckKeywordValue, CrossThreadUnretained(this), @@ -142,7 +142,7 @@ // Use a WebThreadSupportingGC to emulate worklet thread. thread_ = WebThreadSupportingGC::Create( ThreadCreationParams(WebThreadType::kTestThread)); - WaitableEvent waitable_event; + base::WaitableEvent waitable_event; thread_->PostTask(FROM_HERE, CrossThreadBind(&CrossThreadStyleValueTest::CheckUnitValue, CrossThreadUnretained(this),
diff --git a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc index f44753b..2277f039 100644 --- a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc +++ b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc
@@ -6,6 +6,7 @@ #include <memory> #include "base/single_thread_task_runner.h" +#include "base/synchronization/waitable_event.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/core/css/css_computed_style_declaration.h" #include "third_party/blink/renderer/core/css/css_test_helpers.h" @@ -16,7 +17,6 @@ #include "third_party/blink/renderer/platform/cross_thread_functional.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/waitable_event.h" #include "third_party/blink/renderer/platform/web_thread_supporting_gc.h" namespace blink { @@ -29,14 +29,14 @@ Node* PageNode() { return GetDocument().documentElement(); } - void ShutDown(WaitableEvent* waitable_event) { + void ShutDown(base::WaitableEvent* waitable_event) { DCHECK(!IsMainThread()); thread_->ShutdownOnThread(); waitable_event->Signal(); } void ShutDownThread() { - WaitableEvent waitable_event; + base::WaitableEvent waitable_event; thread_->PostTask( FROM_HERE, CrossThreadBind(&PaintWorkletStylePropertyMapTest::ShutDown, CrossThreadUnretained(this), @@ -95,7 +95,7 @@ exception_state.ClearException(); } - void CheckStyleMap(WaitableEvent* waitable_event, + void CheckStyleMap(base::WaitableEvent* waitable_event, scoped_refptr<PaintWorkletInput> input) { DCHECK(!IsMainThread()); thread_->InitializeOnThread(); @@ -243,7 +243,7 @@ thread_ = WebThreadSupportingGC::Create( ThreadCreationParams(WebThreadType::kTestThread)); - WaitableEvent waitable_event; + base::WaitableEvent waitable_event; thread_->PostTask( FROM_HERE, CrossThreadBind( &PaintWorkletStylePropertyMapTest::CheckStyleMap,
diff --git a/third_party/blink/renderer/core/css/style_engine.cc b/third_party/blink/renderer/core/css/style_engine.cc index 71b8964..a08682a9 100644 --- a/third_party/blink/renderer/core/css/style_engine.cc +++ b/third_party/blink/renderer/core/css/style_engine.cc
@@ -671,9 +671,9 @@ return; } - TreeScopeStyleSheetCollection* collection = StyleSheetCollectionFor(scope); - DCHECK(collection); - collection->MarkSheetListDirty(); + TreeScopeStyleSheetCollection& collection = + EnsureStyleSheetCollectionFor(scope); + collection.MarkSheetListDirty(); dirty_tree_scopes_.insert(&scope); GetDocument().ScheduleLayoutTreeUpdateIfNeeded(); }
diff --git a/third_party/blink/renderer/core/css/threaded/multi_threaded_test_util.h b/third_party/blink/renderer/core/css/threaded/multi_threaded_test_util.h index b0e022ff..a65d8167 100644 --- a/third_party/blink/renderer/core/css/threaded/multi_threaded_test_util.h +++ b/third_party/blink/renderer/core/css/threaded/multi_threaded_test_util.h
@@ -10,12 +10,12 @@ #include <memory> #include "base/single_thread_task_runner.h" +#include "base/synchronization/waitable_event.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/platform/cross_thread_functional.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" #include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" -#include "third_party/blink/renderer/platform/waitable_event.h" #include "third_party/blink/renderer/platform/web_thread_supporting_gc.h" #include "third_party/blink/renderer/platform/wtf/functional.h" #include "third_party/blink/renderer/platform/wtf/ref_counted.h" @@ -55,12 +55,12 @@ template <typename FunctionType, typename... Ps> void RunOnThreads(FunctionType function, Ps&&... parameters) { Vector<std::unique_ptr<WebThreadSupportingGC>> threads; - Vector<std::unique_ptr<WaitableEvent>> waits; + Vector<std::unique_ptr<base::WaitableEvent>> waits; for (int i = 0; i < num_threads_; ++i) { threads.push_back(WebThreadSupportingGC::Create( ThreadCreationParams(WebThreadType::kTestThread))); - waits.push_back(std::make_unique<WaitableEvent>()); + waits.push_back(std::make_unique<base::WaitableEvent>()); } for (int i = 0; i < num_threads_; ++i) { @@ -82,7 +82,7 @@ PostCrossThreadTask( *task_runner, FROM_HERE, CrossThreadBind( - [](WebThreadSupportingGC* thread, WaitableEvent* w) { + [](WebThreadSupportingGC* thread, base::WaitableEvent* w) { thread->ShutdownOnThread(); w->Signal(); },
diff --git a/third_party/blink/renderer/core/dom/shadow_root.cc b/third_party/blink/renderer/core/dom/shadow_root.cc index 4b7d59d..54d246a 100644 --- a/third_party/blink/renderer/core/dom/shadow_root.cc +++ b/third_party/blink/renderer/core/dom/shadow_root.cc
@@ -167,6 +167,9 @@ if (!insertion_point.isConnected()) return kInsertionDone; + if (HasAdoptedStyleSheets()) + GetDocument().GetStyleEngine().SetNeedsActiveStyleUpdate(*this); + GetDocument().GetSlotAssignmentEngine().Connected(*this); // FIXME: When parsing <video controls>, InsertedInto() is called many times
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc index 54ad0cd3..e9544783c 100644 --- a/third_party/blink/renderer/core/exported/web_frame_test.cc +++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -10689,11 +10689,8 @@ void ExecuteScriptOnMainFrame(const WebScriptSource& script) { MainFrame()->ExecuteScript(script); - MainFrame()->View()->MainFrameWidget()->BeginFrame(base::TimeTicks::Now(), - false); MainFrame()->View()->MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest); - MainFrame()->View()->MainFrameWidget()->DidBeginFrame(); RunPendingTasks(); } @@ -10783,11 +10780,8 @@ void ExecuteScriptOnMainFrame(const WebScriptSource& script) { MainFrame()->ExecuteScript(script); - MainFrame()->View()->MainFrameWidget()->BeginFrame(base::TimeTicks::Now(), - false); MainFrame()->View()->MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest); - MainFrame()->View()->MainFrameWidget()->DidBeginFrame(); RunPendingTasks(); }
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc index 4321830..66748699 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -1521,13 +1521,6 @@ PageWidgetDelegate::Animate(*AsView().page, last_frame_time); } -void WebViewImpl::DidBeginFrame() { - DCHECK(MainFrameImpl()->GetFrame()); - DocumentLifecycle::AllowThrottlingScope throttling_scope( - MainFrameImpl()->GetFrame()->GetDocument()->Lifecycle()); - PageWidgetDelegate::DidBeginFrame(*MainFrameImpl()->GetFrame()); -} - void WebViewImpl::BeginRafAlignedInput() { raf_aligned_input_start_time_ = CurrentTimeTicks(); }
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h index 0a44b85..46a12c4 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.h +++ b/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -432,7 +432,6 @@ void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) override; void BeginFrame(base::TimeTicks last_frame_time, bool record_main_frame_metrics) override; - void DidBeginFrame() override; void BeginRafAlignedInput() override; void EndRafAlignedInput() override; void RecordStartOfFrameMetrics() override; @@ -485,7 +484,6 @@ friend class WebView; // So WebView::Create can call our constructor friend class WebViewFrameWidget; friend class WTF::RefCounted<WebViewImpl>; - friend class SimCompositor; WebViewImpl(WebViewClient*, bool is_hidden,
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc index 2612a2d..f5ce434 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -1037,29 +1037,6 @@ return frame_->GetDocument()->Lifecycle(); } -void LocalFrameView::RunPostLifecycleSteps() { - RunIntersectionObserverSteps(); - UpdateThrottlingStatusForSubtree(); -} - -void LocalFrameView::RunIntersectionObserverSteps() { -#if DCHECK_IS_ON() - bool was_dirty = NeedsLayout(); -#endif - if (ShouldThrottleRendering() || Lifecycle().LifecyclePostponed() || - !frame_->GetDocument()->IsActive()) { - return; - } - TRACE_EVENT0("blink,benchmark", - "LocalFrameView::UpdateViewportIntersectionsForSubtree"); - SCOPED_UMA_AND_UKM_TIMER(EnsureUkmAggregator(), - LocalFrameUkmAggregator::kIntersectionObservation); - UpdateViewportIntersectionsForSubtree(); -#if DCHECK_IS_ON() - DCHECK(was_dirty || !NeedsLayout()); -#endif -} - LayoutSVGRoot* LocalFrameView::EmbeddedReplacedContent() const { auto* layout_view = this->GetLayoutView(); if (!layout_view) @@ -2210,6 +2187,17 @@ // Run the lifecycle updates. UpdateLifecyclePhasesInternal(target_state); + // Update intersection observations if needed. + if (target_state == DocumentLifecycle::kPaintClean) { + TRACE_EVENT0("blink,benchmark", + "LocalFrameView::UpdateViewportIntersectionsForSubtree"); + SCOPED_UMA_AND_UKM_TIMER(EnsureUkmAggregator(), + LocalFrameUkmAggregator::kIntersectionObservation); + UpdateViewportIntersectionsForSubtree(); + } + + UpdateThrottlingStatusForSubtree(); + ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) { for (auto& observer : frame_view.lifecycle_observers_) observer->DidFinishLifecycleUpdate();
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.h b/third_party/blink/renderer/core/frame/local_frame_view.h index b4db161..4eac4650 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.h +++ b/third_party/blink/renderer/core/frame/local_frame_view.h
@@ -370,12 +370,6 @@ // desired state. bool UpdateLifecycleToLayoutClean(); - // This for doing work that needs to run synchronously at the end of lifecyle - // updates, but needs to happen outside of the lifecycle code. It's OK to - // schedule another animation frame here, but the layout tree should not be - // invalidated. - void RunPostLifecycleSteps(); - void ScheduleVisualUpdateForPaintInvalidationIfNeeded(); bool InvalidateViewportConstrainedObjects(); @@ -817,8 +811,6 @@ DocumentLifecycle& Lifecycle() const; - void RunIntersectionObserverSteps(); - // Methods to do point conversion via layoutObjects, in order to take // transforms into account. IntRect ConvertToContainingEmbeddedContentView(const IntRect&) const;
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc index 1b9051f..8fab72df6 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc +++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -300,11 +300,6 @@ GetPage()->GetValidationMessageClient().LayoutOverlay(); } -void WebFrameWidgetImpl::DidBeginFrame() { - DCHECK(LocalRootImpl()->GetFrame()); - PageWidgetDelegate::DidBeginFrame(*LocalRootImpl()->GetFrame()); -} - void WebFrameWidgetImpl::BeginRafAlignedInput() { raf_aligned_input_start_time_ = CurrentTimeTicks(); }
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h index 8c6b4ea..0ae71d3 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h +++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
@@ -85,7 +85,6 @@ void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) final; void BeginFrame(base::TimeTicks last_frame_time, bool record_main_frame_metrics) override; - void DidBeginFrame() override; void BeginRafAlignedInput() override; void EndRafAlignedInput() override; void RecordStartOfFrameMetrics() override;
diff --git a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc index 2d35cf4..a688b04b 100644 --- a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc +++ b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
@@ -61,10 +61,6 @@ web_view_->BeginFrame(last_frame_time, record_main_frame_metrics); } -void WebViewFrameWidget::DidBeginFrame() { - web_view_->DidBeginFrame(); -} - void WebViewFrameWidget::BeginRafAlignedInput() { web_view_->BeginRafAlignedInput(); }
diff --git a/third_party/blink/renderer/core/frame/web_view_frame_widget.h b/third_party/blink/renderer/core/frame/web_view_frame_widget.h index 5ea0099..f14a81cd 100644 --- a/third_party/blink/renderer/core/frame/web_view_frame_widget.h +++ b/third_party/blink/renderer/core/frame/web_view_frame_widget.h
@@ -50,7 +50,6 @@ void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) final; void BeginFrame(base::TimeTicks last_frame_time, bool record_main_frame_metrics) override; - void DidBeginFrame() override; void BeginRafAlignedInput() override; void EndRafAlignedInput() override; void RecordStartOfFrameMetrics() override;
diff --git a/third_party/blink/renderer/core/layout/api/line_layout_text.h b/third_party/blink/renderer/core/layout/api/line_layout_text.h index eb666a9..6f982e75 100644 --- a/third_party/blink/renderer/core/layout/api/line_layout_text.h +++ b/third_party/blink/renderer/core/layout/api/line_layout_text.h
@@ -33,7 +33,7 @@ InlineTextBox* LastTextBox() const { return ToText()->LastTextBox(); } - InlineTextBox* CreateInlineTextBox(int start, unsigned short length) { + InlineTextBox* CreateInlineTextBox(int start, uint16_t length) { return ToText()->CreateInlineTextBox(start, length); }
diff --git a/third_party/blink/renderer/core/layout/layout_text.cc b/third_party/blink/renderer/core/layout/layout_text.cc index 00b0c5d..2138b179f 100644 --- a/third_party/blink/renderer/core/layout/layout_text.cc +++ b/third_party/blink/renderer/core/layout/layout_text.cc
@@ -439,7 +439,7 @@ if (!box) return IntRect(); - unsigned short truncation = box->Truncation(); + uint16_t truncation = box->Truncation(); if (truncation == kCNoTruncation) return IntRect(); @@ -1909,12 +1909,11 @@ valid_ng_items_ = false; } -InlineTextBox* LayoutText::CreateTextBox(int start, unsigned short length) { +InlineTextBox* LayoutText::CreateTextBox(int start, uint16_t length) { return new InlineTextBox(LineLayoutItem(this), start, length); } -InlineTextBox* LayoutText::CreateInlineTextBox(int start, - unsigned short length) { +InlineTextBox* LayoutText::CreateInlineTextBox(int start, uint16_t length) { InlineTextBox* text_box = CreateTextBox(start, length); MutableTextBoxes().AppendLineBox(text_box); return text_box;
diff --git a/third_party/blink/renderer/core/layout/layout_text.h b/third_party/blink/renderer/core/layout/layout_text.h index 8a927685..0cc567b 100644 --- a/third_party/blink/renderer/core/layout/layout_text.h +++ b/third_party/blink/renderer/core/layout/layout_text.h
@@ -105,7 +105,7 @@ // Returns first letter part of |LayoutTextFragment|. virtual LayoutText* GetFirstLetterPart() const { return nullptr; } - InlineTextBox* CreateInlineTextBox(int start, unsigned short length); + InlineTextBox* CreateInlineTextBox(int start, uint16_t length); void DirtyOrDeleteLineBoxesIfNeeded(bool full_layout); void DirtyLineBoxes(); @@ -340,9 +340,8 @@ const LayoutRect& container_rect, TouchAction container_whitelisted_touch_action) const override; - virtual InlineTextBox* CreateTextBox( - int start, - unsigned short length); // Subclassed by SVG. + virtual InlineTextBox* CreateTextBox(int start, + uint16_t length); // Subclassed by SVG. void InvalidateDisplayItemClients(PaintInvalidationReason) const override;
diff --git a/third_party/blink/renderer/core/layout/line/inline_iterator.h b/third_party/blink/renderer/core/layout/line/inline_iterator.h index 95732c89..6a481c2 100644 --- a/third_party/blink/renderer/core/layout/line/inline_iterator.h +++ b/third_party/blink/renderer/core/layout/line/inline_iterator.h
@@ -760,7 +760,7 @@ while (end > start || add_empty_run) { add_empty_run = false; const int kLimit = - USHRT_MAX; // InlineTextBox stores text length as unsigned short. + USHRT_MAX; // InlineTextBox stores text length as uint16_t. unsigned limited_end = end; if (end - start > kLimit) limited_end = start + kLimit;
diff --git a/third_party/blink/renderer/core/layout/line/inline_text_box.cc b/third_party/blink/renderer/core/layout/line/inline_text_box.cc index 2b0157f7..678d192 100644 --- a/third_party/blink/renderer/core/layout/line/inline_text_box.cc +++ b/third_party/blink/renderer/core/layout/line/inline_text_box.cc
@@ -47,7 +47,7 @@ struct SameSizeAsInlineTextBox : public InlineBox { unsigned variables[1]; - unsigned short variables2[2]; + uint16_t variables2[2]; void* pointers[2]; };
diff --git a/third_party/blink/renderer/core/layout/line/inline_text_box.h b/third_party/blink/renderer/core/layout/line/inline_text_box.h index 6a8cd02c..15ed072 100644 --- a/third_party/blink/renderer/core/layout/line/inline_text_box.h +++ b/third_party/blink/renderer/core/layout/line/inline_text_box.h
@@ -39,7 +39,7 @@ class CORE_EXPORT InlineTextBox : public InlineBox { public: - InlineTextBox(LineLayoutItem item, int start, unsigned short length) + InlineTextBox(LineLayoutItem item, int start, uint16_t length) : InlineBox(item), prev_text_box_(nullptr), next_text_box_(nullptr), @@ -71,7 +71,7 @@ void OffsetRun(int delta); - unsigned short Truncation() const { return truncation_; } + uint16_t Truncation() const { return truncation_; } void MarkDirty() final; @@ -224,12 +224,12 @@ InlineTextBox* next_text_box_; int start_; - unsigned short len_; + uint16_t len_; // Where to truncate when text overflow is applied. We use special constants // to denote no truncation (the whole run paints) and full truncation (nothing // paints at all). - unsigned short truncation_; + uint16_t truncation_; private: TextRun::ExpansionBehavior GetExpansionBehavior() const {
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc index 26613a1a..ad531312 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
@@ -730,16 +730,15 @@ unsigned end_offset) { DCHECK(item_result.item); const NGInlineItem& item = *item_result.item; - const ShapeResult* source_result = item.TextShapeResult(); - DCHECK(source_result); // Check given offsets require to truncate |item_result.shape_result|. const unsigned start_offset = item_result.start_offset; - DCHECK(item_result.shape_result); - DCHECK_GE(start_offset, item_result.shape_result->StartIndex()); - DCHECK_LE(end_offset, item_result.shape_result->EndIndex()); - DCHECK(start_offset > item_result.shape_result->StartIndex() || - end_offset < item_result.shape_result->EndIndex()); + const ShapeResultView* source_result = item_result.shape_result.get(); + DCHECK(source_result); + DCHECK_GE(start_offset, source_result->StartIndex()); + DCHECK_LE(end_offset, source_result->EndIndex()); + DCHECK(start_offset > source_result->StartIndex() || + end_offset < source_result->EndIndex()); if (!NeedsAccurateEndPosition(*line_info_, item)) { return ShapeResultView::Create(source_result, start_offset, end_offset);
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.cc index c008a95..bf141df8a 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.cc
@@ -89,8 +89,7 @@ } } -InlineTextBox* LayoutSVGInlineText::CreateTextBox(int start, - unsigned short length) { +InlineTextBox* LayoutSVGInlineText::CreateTextBox(int start, uint16_t length) { InlineTextBox* box = new SVGInlineTextBox(LineLayoutItem(this), start, length); box->SetHasVirtualLogicalHeight();
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.h b/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.h index 3eaa0a5e..c31e7449 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.h
@@ -76,7 +76,7 @@ int caret_offset, LayoutUnit* extra_width_to_end_of_line = nullptr) const override; LayoutRect LinesBoundingBox() const override; - InlineTextBox* CreateTextBox(int start, unsigned short length) override; + InlineTextBox* CreateTextBox(int start, uint16_t length) override; LayoutRect VisualRectInDocument() const final; FloatRect VisualRectInLocalSVGCoordinates() const final;
diff --git a/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.cc b/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.cc index 44562a16..a01d167 100644 --- a/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.cc +++ b/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.cc
@@ -41,7 +41,7 @@ SVGInlineTextBox::SVGInlineTextBox(LineLayoutItem item, int start, - unsigned short length) + uint16_t length) : InlineTextBox(item, start, length), starts_new_text_chunk_(false) {} void SVGInlineTextBox::DirtyLineBoxes() {
diff --git a/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.h b/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.h index efaa8c5..320ea2c6 100644 --- a/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.h +++ b/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.h
@@ -31,7 +31,7 @@ class SVGInlineTextBox final : public InlineTextBox { public: - SVGInlineTextBox(LineLayoutItem, int start, unsigned short length); + SVGInlineTextBox(LineLayoutItem, int start, uint16_t length); bool IsSVGInlineTextBox() const override { return true; }
diff --git a/third_party/blink/renderer/core/loader/threadable_loader_test.cc b/third_party/blink/renderer/core/loader/threadable_loader_test.cc index b46ae03..5cb0456 100644 --- a/third_party/blink/renderer/core/loader/threadable_loader_test.cc +++ b/third_party/blink/renderer/core/loader/threadable_loader_test.cc
@@ -33,7 +33,6 @@ #include "third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.h" #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" #include "third_party/blink/renderer/platform/testing/url_test_helpers.h" -#include "third_party/blink/renderer/platform/waitable_event.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/weborigin/security_origin.h" #include "third_party/blink/renderer/platform/wtf/assertions.h"
diff --git a/third_party/blink/renderer/core/page/page_widget_delegate.cc b/third_party/blink/renderer/core/page/page_widget_delegate.cc index 4d98a13c..50d836f5 100644 --- a/third_party/blink/renderer/core/page/page_widget_delegate.cc +++ b/third_party/blink/renderer/core/page/page_widget_delegate.cc
@@ -74,11 +74,6 @@ } } -void PageWidgetDelegate::DidBeginFrame(LocalFrame& root) { - if (LocalFrameView* frame_view = root.View()) - frame_view->RunPostLifecycleSteps(); -} - void PageWidgetDelegate::PaintContent(cc::PaintCanvas* canvas, const WebRect& rect, LocalFrame& root) {
diff --git a/third_party/blink/renderer/core/page/page_widget_delegate.h b/third_party/blink/renderer/core/page/page_widget_delegate.h index 2f2bb41..926e97e 100644 --- a/third_party/blink/renderer/core/page/page_widget_delegate.h +++ b/third_party/blink/renderer/core/page/page_widget_delegate.h
@@ -85,9 +85,6 @@ WebWidget::LifecycleUpdate requested_update, WebWidget::LifecycleUpdateReason reason); - // See comment of WebWidget::DidBeginFrame - static void DidBeginFrame(LocalFrame& root); - // See documents of methods with the same names in FrameView class. static void PaintContent(cc::PaintCanvas*, const WebRect&, LocalFrame& root); // See FIXME in the function body about nullptr |root|.
diff --git a/third_party/blink/renderer/core/script/module_import_meta.h b/third_party/blink/renderer/core/script/module_import_meta.h index d6af2ba4..24b26bd 100644 --- a/third_party/blink/renderer/core/script/module_import_meta.h +++ b/third_party/blink/renderer/core/script/module_import_meta.h
@@ -13,6 +13,8 @@ // Represents import.meta data structure, which is the return value of // https://html.spec.whatwg.org/C/#hostgetimportmetaproperties class CORE_EXPORT ModuleImportMeta final { + STACK_ALLOCATED(); + public: explicit ModuleImportMeta(const String& url) : url_(url) {}
diff --git a/third_party/blink/renderer/core/script/parsed_specifier.h b/third_party/blink/renderer/core/script/parsed_specifier.h index 93c762e9..c95e30f8 100644 --- a/third_party/blink/renderer/core/script/parsed_specifier.h +++ b/third_party/blink/renderer/core/script/parsed_specifier.h
@@ -29,6 +29,8 @@ // instead of passing String with occasionally converting to KURL. // This avoid duplicated URL parsing. class ParsedSpecifier final { + STACK_ALLOCATED(); + public: // Parse |specifier|, which may be a non-bare or bare specifier. // This implements
diff --git a/third_party/blink/renderer/core/testing/page_test_base.cc b/third_party/blink/renderer/core/testing/page_test_base.cc index 8c8e8b25..5698d8f 100644 --- a/third_party/blink/renderer/core/testing/page_test_base.cc +++ b/third_party/blink/renderer/core/testing/page_test_base.cc
@@ -117,7 +117,6 @@ void PageTestBase::UpdateAllLifecyclePhasesForTest() { GetDocument().View()->UpdateAllLifecyclePhases( DocumentLifecycle::LifecycleUpdateReason::kTest); - GetDocument().View()->RunPostLifecycleSteps(); } StyleEngine& PageTestBase::GetStyleEngine() {
diff --git a/third_party/blink/renderer/core/testing/sim/sim_compositor.cc b/third_party/blink/renderer/core/testing/sim/sim_compositor.cc index ec460ab..e06c443 100644 --- a/third_party/blink/renderer/core/testing/sim/sim_compositor.cc +++ b/third_party/blink/renderer/core/testing/sim/sim_compositor.cc
@@ -60,9 +60,14 @@ last_frame_time_ += base::TimeDelta::FromSecondsD(time_delta_in_seconds); + SimCanvas::Commands commands; + paint_commands_ = &commands; + layer_tree_view_->layer_tree_host()->Composite(last_frame_time_, /*raster=*/false); - return PaintFrame(); + + paint_commands_ = nullptr; + return commands; } SimCanvas::Commands SimCompositor::PaintFrame() { @@ -99,6 +104,7 @@ web_view_->MainFrameWidget()->BeginFrame(last_frame_time_, false); web_view_->MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest); + *paint_commands_ = PaintFrame(); } } // namespace blink
diff --git a/third_party/blink/renderer/core/testing/sim/sim_compositor.h b/third_party/blink/renderer/core/testing/sim/sim_compositor.h index 259e28e..466733e 100644 --- a/third_party/blink/renderer/core/testing/sim/sim_compositor.h +++ b/third_party/blink/renderer/core/testing/sim/sim_compositor.h
@@ -98,7 +98,6 @@ void RequestNewLayerTreeFrameSink( LayerTreeFrameSinkCallback callback) override; void BeginMainFrame(base::TimeTicks frame_time) override; - void DidBeginMainFrame() override { web_view_->DidBeginFrame(); } WebViewImpl* web_view_ = nullptr; content::LayerTreeView* layer_tree_view_ = nullptr; @@ -107,6 +106,10 @@ base::TimeTicks last_frame_time_; + // During BeginFrame(), painting is done, and the result is stored here to + // be returned from BeginFrame(). + SimCanvas::Commands* paint_commands_; + std::unique_ptr<cc::ScopedDeferMainFrameUpdate> scoped_defer_main_frame_update_; };
diff --git a/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h b/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h index 382addc..975463ec 100644 --- a/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h +++ b/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h
@@ -53,6 +53,13 @@ // transfer that. bool Transfer(v8::Isolate*, WTF::ArrayBufferContents& result); + // Share the ArrayBuffer, even if it is non-shared. Such sharing is necessary + // for e.g. WebAudio which uses a separate thread for processing the + // ArrayBuffer while at the same time exposing a NonShared Float32Array. + bool ShareNonSharedForInternalUse(WTF::ArrayBufferContents& result) { + return Buffer()->ShareNonSharedForInternalUse(result); + } + v8::Local<v8::Object> Wrap(v8::Isolate*, v8::Local<v8::Object> creation_context) override; };
diff --git a/third_party/blink/renderer/core/workers/worker_thread.cc b/third_party/blink/renderer/core/workers/worker_thread.cc index b7d47b3..184e25a1 100644 --- a/third_party/blink/renderer/core/workers/worker_thread.cc +++ b/third_party/blink/renderer/core/workers/worker_thread.cc
@@ -54,7 +54,6 @@ #include "third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h" #include "third_party/blink/renderer/platform/scheduler/worker/worker_thread.h" #include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h" -#include "third_party/blink/renderer/platform/waitable_event.h" #include "third_party/blink/renderer/platform/web_thread_supporting_gc.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/wtf/functional.h"
diff --git a/third_party/blink/renderer/core/workers/worker_thread_test.cc b/third_party/blink/renderer/core/workers/worker_thread_test.cc index 0df86fe..8939e3b 100644 --- a/third_party/blink/renderer/core/workers/worker_thread_test.cc +++ b/third_party/blink/renderer/core/workers/worker_thread_test.cc
@@ -7,6 +7,7 @@ #include <memory> #include <utility> +#include "base/synchronization/waitable_event.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/bindings/core/v8/v8_cache_options.h" @@ -19,7 +20,6 @@ #include "third_party/blink/renderer/core/workers/worker_thread_test_helper.h" #include "third_party/blink/renderer/platform/scheduler/test/fake_task_runner.h" #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" -#include "third_party/blink/renderer/platform/waitable_event.h" using testing::_; using testing::AtMost; @@ -32,7 +32,7 @@ // Used as a debugger task. Waits for a signal from the main thread. void WaitForSignalTask(WorkerThread* worker_thread, - WaitableEvent* waitable_event) { + base::WaitableEvent* waitable_event) { EXPECT_TRUE(worker_thread->IsCurrentThread()); worker_thread->DebuggerTaskStarted(); @@ -46,7 +46,7 @@ } void TerminateParentOfNestedWorker(WorkerThread* parent_thread, - WaitableEvent* waitable_event) { + base::WaitableEvent* waitable_event) { EXPECT_TRUE(IsMainThread()); parent_thread->Terminate(); waitable_event->Signal(); @@ -99,7 +99,7 @@ nested_worker_helper->worker_thread->WaitForInit(); // Ask the main threat to terminate this parent thread. - WaitableEvent child_waitable; + base::WaitableEvent child_waitable; PostCrossThreadTask( *parent_thread->GetParentExecutionContextTaskRunners()->Get( TaskType::kInternalTest), @@ -120,7 +120,7 @@ void VerifyParentAndChildAreTerminated(WorkerThread* parent_thread, NestedWorkerHelper* nested_worker_helper, - WaitableEvent* waitable_event) { + base::WaitableEvent* waitable_event) { EXPECT_TRUE(parent_thread->IsCurrentThread()); EXPECT_EQ(ExitCode::kGracefullyTerminated, parent_thread->GetExitCodeForTesting()); @@ -386,7 +386,7 @@ // Used to wait for worker thread termination in a debugger task on the // worker thread. - WaitableEvent waitable_event; + base::WaitableEvent waitable_event; PostCrossThreadTask( *worker_thread_->GetTaskRunner(TaskType::kInternalInspector), FROM_HERE, CrossThreadBind(&WaitForSignalTask, @@ -433,7 +433,7 @@ // Used to wait for worker thread termination in a debugger task on the // worker thread. - WaitableEvent waitable_event; + base::WaitableEvent waitable_event; PostCrossThreadTask( *worker_thread_->GetTaskRunner(TaskType::kInternalInspector), FROM_HERE, CrossThreadBind(&WaitForSignalTask, @@ -484,7 +484,7 @@ CrossThreadUnretained(&nested_worker_helper))); test::EnterRunLoop(); - WaitableEvent waitable_event; + base::WaitableEvent waitable_event; worker_thread_->GetWorkerBackingThread().BackingThread().PostTask( FROM_HERE, CrossThreadBind(&VerifyParentAndChildAreTerminated, CrossThreadUnretained(worker_thread_.get()),
diff --git a/third_party/blink/renderer/core/workers/worker_thread_test_helper.h b/third_party/blink/renderer/core/workers/worker_thread_test_helper.h index 821ae55..743dd50 100644 --- a/third_party/blink/renderer/core/workers/worker_thread_test_helper.h +++ b/third_party/blink/renderer/core/workers/worker_thread_test_helper.h
@@ -8,6 +8,7 @@ #include <memory> #include "base/macros.h" +#include "base/synchronization/waitable_event.h" #include "testing/gmock/include/gmock/gmock.h" #include "third_party/blink/public/mojom/net/ip_address_space.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/source_location.h" @@ -29,7 +30,6 @@ #include "third_party/blink/renderer/platform/cross_thread_functional.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/network/content_security_policy_parsers.h" -#include "third_party/blink/renderer/platform/waitable_event.h" #include "third_party/blink/renderer/platform/web_thread_supporting_gc.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/weborigin/security_origin.h" @@ -115,9 +115,9 @@ } void WaitForInit() { - WaitableEvent completion_event; + base::WaitableEvent completion_event; GetWorkerBackingThread().BackingThread().PostTask( - FROM_HERE, CrossThreadBind(&WaitableEvent::Signal, + FROM_HERE, CrossThreadBind(&base::WaitableEvent::Signal, CrossThreadUnretained(&completion_event))); completion_event.Wait(); } @@ -160,7 +160,7 @@ void WaitUntilScriptEvaluation() { script_evaluation_event_.Wait(); } private: - WaitableEvent script_evaluation_event_; + base::WaitableEvent script_evaluation_event_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/workers/worklet_thread_holder.h b/third_party/blink/renderer/core/workers/worklet_thread_holder.h index 2a18f37c..121bb33 100644 --- a/third_party/blink/renderer/core/workers/worklet_thread_holder.h +++ b/third_party/blink/renderer/core/workers/worklet_thread_holder.h
@@ -5,10 +5,10 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKLET_THREAD_HOLDER_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKLET_THREAD_HOLDER_H_ +#include "base/synchronization/waitable_event.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/workers/worker_backing_thread.h" #include "third_party/blink/renderer/core/workers/worker_backing_thread_startup_data.h" -#include "third_party/blink/renderer/platform/waitable_event.h" #include "third_party/blink/renderer/platform/web_thread_supporting_gc.h" namespace blink { @@ -70,7 +70,7 @@ void ShutdownAndWait() { DCHECK(IsMainThread()); - WaitableEvent waitable_event; + base::WaitableEvent waitable_event; thread_->BackingThread().PostTask( FROM_HERE, CrossThreadBind(&WorkletThreadHolder::ShutdownOnWorkletThread, @@ -79,7 +79,7 @@ waitable_event.Wait(); } - void ShutdownOnWorkletThread(WaitableEvent* waitable_event) { + void ShutdownOnWorkletThread(base::WaitableEvent* waitable_event) { thread_->ShutdownOnBackingThread(); waitable_event->Signal(); }
diff --git a/third_party/blink/renderer/core/xml/document_xpath_evaluator.cc b/third_party/blink/renderer/core/xml/document_xpath_evaluator.cc index a2538cc..d884cf77 100644 --- a/third_party/blink/renderer/core/xml/document_xpath_evaluator.cc +++ b/third_party/blink/renderer/core/xml/document_xpath_evaluator.cc
@@ -72,7 +72,7 @@ const String& expression, Node* context_node, XPathNSResolver* resolver, - unsigned short type, + uint16_t type, const ScriptValue&, ExceptionState& exception_state) { DocumentXPathEvaluator& suplement = From(document);
diff --git a/third_party/blink/renderer/core/xml/document_xpath_evaluator.h b/third_party/blink/renderer/core/xml/document_xpath_evaluator.h index b4d892540..dd3895d 100644 --- a/third_party/blink/renderer/core/xml/document_xpath_evaluator.h +++ b/third_party/blink/renderer/core/xml/document_xpath_evaluator.h
@@ -55,7 +55,7 @@ const String& expression, Node* context_node, XPathNSResolver*, - unsigned short type, + uint16_t type, const ScriptValue&, ExceptionState&);
diff --git a/third_party/blink/renderer/core/xml/xpath_evaluator.cc b/third_party/blink/renderer/core/xml/xpath_evaluator.cc index f0dfb4b..3c1cede 100644 --- a/third_party/blink/renderer/core/xml/xpath_evaluator.cc +++ b/third_party/blink/renderer/core/xml/xpath_evaluator.cc
@@ -53,7 +53,7 @@ XPathResult* XPathEvaluator::evaluate(const String& expression, Node* context_node, XPathNSResolver* resolver, - unsigned short type, + uint16_t type, const ScriptValue&, ExceptionState& exception_state) { if (!IsValidContextNode(context_node)) {
diff --git a/third_party/blink/renderer/core/xml/xpath_evaluator.h b/third_party/blink/renderer/core/xml/xpath_evaluator.h index ecf02abc..cd932471 100644 --- a/third_party/blink/renderer/core/xml/xpath_evaluator.h +++ b/third_party/blink/renderer/core/xml/xpath_evaluator.h
@@ -56,7 +56,7 @@ XPathResult* evaluate(const String& expression, Node* context_node, XPathNSResolver*, - unsigned short type, + uint16_t type, const ScriptValue&, ExceptionState&); };
diff --git a/third_party/blink/renderer/core/xml/xpath_expression.cc b/third_party/blink/renderer/core/xml/xpath_expression.cc index a32a06c..7002fbb 100644 --- a/third_party/blink/renderer/core/xml/xpath_expression.cc +++ b/third_party/blink/renderer/core/xml/xpath_expression.cc
@@ -61,7 +61,7 @@ } XPathResult* XPathExpression::evaluate(Node* context_node, - unsigned short type, + uint16_t type, const ScriptValue&, ExceptionState& exception_state) { if (!IsValidContextNode(context_node)) {
diff --git a/third_party/blink/renderer/core/xml/xpath_expression.h b/third_party/blink/renderer/core/xml/xpath_expression.h index 0539ca6..5e6655f 100644 --- a/third_party/blink/renderer/core/xml/xpath_expression.h +++ b/third_party/blink/renderer/core/xml/xpath_expression.h
@@ -57,7 +57,7 @@ XPathExpression(); XPathResult* evaluate(Node* context_node, - unsigned short type, + uint16_t type, const ScriptValue&, ExceptionState&);
diff --git a/third_party/blink/renderer/core/xml/xpath_result.cc b/third_party/blink/renderer/core/xml/xpath_result.cc index 58785a13..3cc8ce4 100644 --- a/third_party/blink/renderer/core/xml/xpath_result.cc +++ b/third_party/blink/renderer/core/xml/xpath_result.cc
@@ -65,8 +65,7 @@ ScriptWrappable::Trace(visitor); } -void XPathResult::ConvertTo(unsigned short type, - ExceptionState& exception_state) { +void XPathResult::ConvertTo(uint16_t type, ExceptionState& exception_state) { switch (type) { case kAnyType: break; @@ -118,7 +117,7 @@ } } -unsigned short XPathResult::resultType() const { +uint16_t XPathResult::resultType() const { return result_type_; }
diff --git a/third_party/blink/renderer/core/xml/xpath_result.h b/third_party/blink/renderer/core/xml/xpath_result.h index 7fa3fc2..80b25fcf 100644 --- a/third_party/blink/renderer/core/xml/xpath_result.h +++ b/third_party/blink/renderer/core/xml/xpath_result.h
@@ -66,9 +66,9 @@ XPathResult(xpath::EvaluationContext&, const xpath::Value&); - void ConvertTo(unsigned short type, ExceptionState&); + void ConvertTo(uint16_t type, ExceptionState&); - unsigned short resultType() const; + uint16_t resultType() const; double numberValue(ExceptionState&) const; String stringValue(ExceptionState&) const; @@ -91,7 +91,7 @@ unsigned node_set_position_; // FIXME: why duplicate the node set stored in value_? Member<xpath::NodeSet> node_set_; - unsigned short result_type_; + uint16_t result_type_; Member<Document> document_; uint64_t dom_tree_version_; };
diff --git a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc index 34c72788..248edb75 100644 --- a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc +++ b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.h" +#include "base/synchronization/waitable_event.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/public/platform/web_url_request.h" @@ -25,7 +26,6 @@ #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/cross_thread_functional.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h" -#include "third_party/blink/renderer/platform/waitable_event.h" #include "third_party/blink/renderer/platform/wtf/text/text_position.h" #include <memory> @@ -73,15 +73,15 @@ reporting_proxy_ = std::make_unique<WorkerReportingProxy>(); } - using TestCalback = void (AnimationWorkletGlobalScopeTest::*)(WorkerThread*, - WaitableEvent*); + using TestCalback = void ( + AnimationWorkletGlobalScopeTest::*)(WorkerThread*, base::WaitableEvent*); // Create a new animation worklet and run the callback task on it. Terminate // the worklet once the task completion is signaled. void RunTestOnWorkletThread(TestCalback callback) { std::unique_ptr<WorkerThread> worklet = CreateAnimationAndPaintWorkletThread(&GetDocument(), reporting_proxy_.get()); - WaitableEvent waitable_event; + base::WaitableEvent waitable_event; PostCrossThreadTask( *worklet->GetTaskRunner(TaskType::kInternalTest), FROM_HERE, CrossThreadBind(callback, CrossThreadUnretained(this), @@ -95,7 +95,7 @@ void RunScriptOnWorklet(String source_code, WorkerThread* thread, - WaitableEvent* waitable_event) { + base::WaitableEvent* waitable_event) { ASSERT_TRUE(thread->IsCurrentThread()); auto* global_scope = To<AnimationWorkletGlobalScope>(thread->GlobalScope()); ScriptState* script_state = @@ -109,7 +109,7 @@ } void RunBasicParsingTestOnWorklet(WorkerThread* thread, - WaitableEvent* waitable_event) { + base::WaitableEvent* waitable_event) { ASSERT_TRUE(thread->IsCurrentThread()); auto* global_scope = To<AnimationWorkletGlobalScope>(thread->GlobalScope()); ScriptState* script_state = @@ -153,8 +153,9 @@ waitable_event->Signal(); } - void RunConstructAndAnimateTestOnWorklet(WorkerThread* thread, - WaitableEvent* waitable_event) { + void RunConstructAndAnimateTestOnWorklet( + WorkerThread* thread, + base::WaitableEvent* waitable_event) { ASSERT_TRUE(thread->IsCurrentThread()); auto* global_scope = To<AnimationWorkletGlobalScope>(thread->GlobalScope()); ScriptState* script_state = @@ -227,7 +228,7 @@ } void RunStateExistenceTestOnWorklet(WorkerThread* thread, - WaitableEvent* waitable_event) { + base::WaitableEvent* waitable_event) { ASSERT_TRUE(thread->IsCurrentThread()); auto* global_scope = To<AnimationWorkletGlobalScope>(thread->GlobalScope()); ScriptState* script_state = @@ -274,7 +275,7 @@ } void RunAnimateOutputTestOnWorklet(WorkerThread* thread, - WaitableEvent* waitable_event) { + base::WaitableEvent* waitable_event) { AnimationWorkletGlobalScope* global_scope = static_cast<AnimationWorkletGlobalScope*>(thread->GlobalScope()); ASSERT_TRUE(global_scope); @@ -317,8 +318,9 @@ // This test verifies that an animator instance is not created if // MutatorInputState does not have an animation in // added_and_updated_animations. - void RunAnimatorInstanceCreationTestOnWorklet(WorkerThread* thread, - WaitableEvent* waitable_event) { + void RunAnimatorInstanceCreationTestOnWorklet( + WorkerThread* thread, + base::WaitableEvent* waitable_event) { AnimationWorkletGlobalScope* global_scope = static_cast<AnimationWorkletGlobalScope*>(thread->GlobalScope()); ASSERT_TRUE(global_scope); @@ -371,8 +373,9 @@ // This test verifies that an animator instance is created and removed // properly. - void RunAnimatorInstanceUpdateTestOnWorklet(WorkerThread* thread, - WaitableEvent* waitable_event) { + void RunAnimatorInstanceUpdateTestOnWorklet( + WorkerThread* thread, + base::WaitableEvent* waitable_event) { AnimationWorkletGlobalScope* global_scope = static_cast<AnimationWorkletGlobalScope*>(thread->GlobalScope()); ASSERT_TRUE(global_scope); @@ -488,7 +491,7 @@ // creation. EXPECT_FALSE(proxy_client->did_add_global_scope()); - WaitableEvent waitable_event; + base::WaitableEvent waitable_event; String source_code = R"JS( registerAnimator('test', class {
diff --git a/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client_test.cc b/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client_test.cc index ea58bea..85f36abc 100644 --- a/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client_test.cc +++ b/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client_test.cc
@@ -7,6 +7,7 @@ #include <memory> #include <utility> +#include "base/synchronization/waitable_event.h" #include "base/test/test_simple_task_runner.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -54,7 +55,7 @@ void AddGlobalScopeForTesting(WorkerThread* thread, AnimationWorkletProxyClient* proxy_client, - WaitableEvent* waitable_event) { + base::WaitableEvent* waitable_event) { proxy_client->AddGlobalScopeForTesting( To<WorkletGlobalScope>(thread->GlobalScope())); waitable_event->Signal(); @@ -119,7 +120,7 @@ // Register global scopes with proxy client. This step must be performed on // the worker threads. - WaitableEvent waitable_event; + base::WaitableEvent waitable_event; PostCrossThreadTask( *first_worklet->GetTaskRunner(TaskType::kInternalTest), FROM_HERE, CrossThreadBind(
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_test.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_test.cc index 7ba26c6..5c5740c 100644 --- a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_test.cc +++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_test.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h" +#include "base/synchronization/waitable_event.h" #include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h" #include "third_party/blink/renderer/core/inspector/worker_devtools_params.h" #include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h" @@ -76,15 +77,15 @@ return thread; } - using TestCalback = void (PaintWorkletGlobalScopeTest::*)(WorkerThread*, - WaitableEvent*); + using TestCalback = void ( + PaintWorkletGlobalScopeTest::*)(WorkerThread*, base::WaitableEvent*); // Create a new paint worklet and run the callback task on it. Terminate the // worklet once the task completion is signaled. void RunTestOnWorkletThread(TestCalback callback) { std::unique_ptr<WorkerThread> worklet = CreateAnimationAndPaintWorkletThread(nullptr); - WaitableEvent waitable_event; + base::WaitableEvent waitable_event; PostCrossThreadTask( *worklet->GetTaskRunner(TaskType::kInternalTest), FROM_HERE, CrossThreadBind(callback, CrossThreadUnretained(this), @@ -98,7 +99,7 @@ void RunScriptOnWorklet(String source_code, WorkerThread* thread, - WaitableEvent* waitable_event) { + base::WaitableEvent* waitable_event) { ASSERT_TRUE(thread->IsCurrentThread()); auto* global_scope = To<PaintWorkletGlobalScope>(thread->GlobalScope()); ScriptState* script_state = @@ -112,7 +113,7 @@ } void RunBasicParsingTestOnWorklet(WorkerThread* thread, - WaitableEvent* waitable_event) { + base::WaitableEvent* waitable_event) { ASSERT_TRUE(thread->IsCurrentThread()); auto* global_scope = To<PaintWorkletGlobalScope>(thread->GlobalScope()); ScriptState* script_state =
diff --git a/third_party/blink/renderer/modules/imagecapture/image_capture.cc b/third_party/blink/renderer/modules/imagecapture/image_capture.cc index 523a49f..71ce2f0 100644 --- a/third_party/blink/renderer/modules/imagecapture/image_capture.cc +++ b/third_party/blink/renderer/modules/imagecapture/image_capture.cc
@@ -24,7 +24,6 @@ #include "third_party/blink/renderer/modules/mediastream/media_track_capabilities.h" #include "third_party/blink/renderer/modules/mediastream/media_track_constraints.h" #include "third_party/blink/renderer/platform/mojo/mojo_helper.h" -#include "third_party/blink/renderer/platform/waitable_event.h" #include "third_party/blink/renderer/platform/wtf/functional.h" namespace blink {
diff --git a/third_party/blink/renderer/modules/media_controls/resources/legacyMediaControls.css b/third_party/blink/renderer/modules/media_controls/resources/legacyMediaControls.css index 48efe33..f8a6e31 100644 --- a/third_party/blink/renderer/modules/media_controls/resources/legacyMediaControls.css +++ b/third_party/blink/renderer/modules/media_controls/resources/legacyMediaControls.css
@@ -638,7 +638,6 @@ display: inline; background-color: rgba(0, 0, 0, 0.8); - padding: 2px 2px; } video::-webkit-media-text-track-region {
diff --git a/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css b/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css index 30b9a61..3b25f7ae 100644 --- a/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css +++ b/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css
@@ -1168,7 +1168,6 @@ display: inline; background-color: rgba(0, 0, 0, 0.8); - padding: 2px 2px; } video::-webkit-media-text-track-region {
diff --git a/third_party/blink/renderer/modules/webaudio/audio_buffer.cc b/third_party/blink/renderer/modules/webaudio/audio_buffer.cc index ae02dde..a63be55 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_buffer.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_buffer.cc
@@ -346,4 +346,24 @@ } } +std::unique_ptr<SharedAudioBuffer> AudioBuffer::CreateSharedAudioBuffer() { + return std::unique_ptr<SharedAudioBuffer>(new SharedAudioBuffer(this)); +} + +SharedAudioBuffer::SharedAudioBuffer(AudioBuffer* buffer) + : sample_rate_(buffer->sampleRate()), length_(buffer->length()) { + channels_.resize(buffer->numberOfChannels()); + for (unsigned int i = 0; i < buffer->numberOfChannels(); ++i) { + buffer->getChannelData(i).View()->buffer()->ShareNonSharedForInternalUse( + channels_[i]); + } +} + +void SharedAudioBuffer::Zero() { + for (unsigned i = 0; i < channels_.size(); ++i) { + float* data = static_cast<float*>(channels_[i].Data()); + memset(data, 0, length() * sizeof(*data)); + } +} + } // namespace blink
diff --git a/third_party/blink/renderer/modules/webaudio/audio_buffer.h b/third_party/blink/renderer/modules/webaudio/audio_buffer.h index ae3389c..50eddb79 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_buffer.h +++ b/third_party/blink/renderer/modules/webaudio/audio_buffer.h
@@ -41,6 +41,7 @@ class AudioBus; class AudioBufferOptions; class ExceptionState; +class SharedAudioBuffer; class MODULES_EXPORT AudioBuffer final : public ScriptWrappable { DEFINE_WRAPPERTYPEINFO(); @@ -116,6 +117,8 @@ ScriptWrappable::Trace(visitor); } + std::unique_ptr<SharedAudioBuffer> CreateSharedAudioBuffer(); + private: static DOMFloat32Array* CreateFloat32ArrayOrNull( uint32_t length, @@ -129,6 +132,28 @@ HeapVector<Member<DOMFloat32Array>> channels_; }; +// Shared data that audio threads can hold onto. +class SharedAudioBuffer final { + public: + explicit SharedAudioBuffer(AudioBuffer*); + + unsigned numberOfChannels() const { return channels_.size(); } + uint32_t length() const { return length_; } + double duration() const { + return length() / static_cast<double>(sampleRate()); + } + float sampleRate() const { return sample_rate_; } + + const Vector<WTF::ArrayBufferContents>& channels() { return channels_; } + + void Zero(); + + private: + float sample_rate_; + uint32_t length_; + Vector<WTF::ArrayBufferContents> channels_; +}; + } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBAUDIO_AUDIO_BUFFER_H_
diff --git a/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.cc b/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.cc index 2f8dbf0..656d0c6 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.cc
@@ -61,7 +61,6 @@ : AudioScheduledSourceHandler(kNodeTypeAudioBufferSource, node, sample_rate), - buffer_(nullptr), playback_rate_(&playback_rate), detune_(&detune), is_looping_(false), @@ -115,7 +114,7 @@ // is updated to the new number of channels because of use of tryLocks() in // the context's updating system. In this case, if the the buffer has just // been changed and we're not quite ready yet, then just output silence. - if (NumberOfChannels() != Buffer()->numberOfChannels()) { + if (NumberOfChannels() != shared_buffer_->numberOfChannels()) { output_bus->Zero(); return; } @@ -223,8 +222,8 @@ // Offset the pointers to the correct offset frame. unsigned write_index = destination_frame_offset; - uint32_t buffer_length = Buffer()->length(); - double buffer_sample_rate = Buffer()->sampleRate(); + uint32_t buffer_length = shared_buffer_->length(); + double buffer_sample_rate = shared_buffer_->sampleRate(); // Avoid converting from time to sample-frames twice by computing // the grain end time first before computing the sample frame. @@ -248,8 +247,8 @@ if (Loop() && (loop_start_ || loop_end_) && loop_start_ >= 0 && loop_end_ > 0 && loop_start_ < loop_end_) { // Convert from seconds to sample-frames. - double loop_start_frame = loop_start_ * Buffer()->sampleRate(); - double loop_end_frame = loop_end_ * Buffer()->sampleRate(); + double loop_start_frame = loop_start_ * shared_buffer_->sampleRate(); + double loop_end_frame = loop_end_ * shared_buffer_->sampleRate(); virtual_end_frame = std::min(loop_end_frame, virtual_end_frame); virtual_delta_frames = virtual_end_frame - loop_start_frame; @@ -260,7 +259,7 @@ // needs to be done. if (Loop() && virtual_read_index_ >= virtual_end_frame) { virtual_read_index_ = - (loop_start_ < 0) ? 0 : (loop_start_ * Buffer()->sampleRate()); + (loop_start_ < 0) ? 0 : (loop_start_ * shared_buffer_->sampleRate()); virtual_read_index_ = std::min(virtual_read_index_, static_cast<double>(buffer_length - 1)); } @@ -439,35 +438,39 @@ return; } + shared_buffer_ = buffer->CreateSharedAudioBuffer(); + Output(0).SetNumberOfChannels(number_of_channels); source_channels_ = std::make_unique<const float* []>(number_of_channels); destination_channels_ = std::make_unique<float* []>(number_of_channels); - for (unsigned i = 0; i < number_of_channels; ++i) - source_channels_[i] = buffer->getChannelData(i).View()->Data(); + for (unsigned i = 0; i < number_of_channels; ++i) { + source_channels_[i] = + static_cast<float*>(shared_buffer_->channels()[i].Data()); + } // If this is a grain (as set by a previous call to start()), validate the // grain parameters now since it wasn't validated when start was called // (because there was no buffer then). if (is_grain_) - ClampGrainParameters(buffer); + ClampGrainParameters(shared_buffer_.get()); } virtual_read_index_ = 0; - buffer_ = buffer; } unsigned AudioBufferSourceHandler::NumberOfChannels() { return Output(0).NumberOfChannels(); } -void AudioBufferSourceHandler::ClampGrainParameters(const AudioBuffer* buffer) { +void AudioBufferSourceHandler::ClampGrainParameters( + const SharedAudioBuffer* buffer) { DCHECK(buffer); // We have a buffer so we can clip the offset and duration to lie within the // buffer. - double buffer_duration = buffer->duration(); + double buffer_duration = shared_buffer_->duration(); grain_offset_ = clampTo(grain_offset_, 0.0, buffer_duration); @@ -495,8 +498,8 @@ // degrade the quality. When aligned to the sample-frame the playback will be // identical to the PCM data stored in the buffer. Since playbackRate == 1 is // very common, it's worth considering quality. - virtual_read_index_ = - audio_utilities::TimeToSampleFrame(grain_offset_, buffer->sampleRate()); + virtual_read_index_ = audio_utilities::TimeToSampleFrame( + grain_offset_, shared_buffer_->sampleRate()); } void AudioBufferSourceHandler::Start(double when, @@ -507,8 +510,8 @@ void AudioBufferSourceHandler::Start(double when, double grain_offset, ExceptionState& exception_state) { - StartSource(when, grain_offset, Buffer() ? Buffer()->duration() : 0, false, - exception_state); + StartSource(when, grain_offset, Buffer() ? shared_buffer_->duration() : 0, + false, exception_state); } void AudioBufferSourceHandler::Start(double when, @@ -583,8 +586,8 @@ double sample_rate_factor = 1.0; if (Buffer()) { // Use doubles to compute this to full accuracy. - sample_rate_factor = - Buffer()->sampleRate() / static_cast<double>(Context()->sampleRate()); + sample_rate_factor = shared_buffer_->sampleRate() / + static_cast<double>(Context()->sampleRate()); } // Use finalValue() to incorporate changes of AudioParamTimeline and @@ -621,7 +624,7 @@ } bool AudioBufferSourceHandler::PropagatesSilence() const { - return !IsPlayingOrScheduled() || HasFinished() || !buffer_; + return !IsPlayingOrScheduled() || HasFinished() || !shared_buffer_.get(); } void AudioBufferSourceHandler::HandleStoppableSourceNode() { @@ -718,6 +721,7 @@ void AudioBufferSourceNode::Trace(blink::Visitor* visitor) { visitor->Trace(playback_rate_); visitor->Trace(detune_); + visitor->Trace(buffer_); AudioScheduledSourceNode::Trace(visitor); } @@ -727,12 +731,14 @@ } AudioBuffer* AudioBufferSourceNode::buffer() const { - return GetAudioBufferSourceHandler().Buffer(); + return buffer_.Get(); } void AudioBufferSourceNode::setBuffer(AudioBuffer* new_buffer, ExceptionState& exception_state) { GetAudioBufferSourceHandler().SetBuffer(new_buffer, exception_state); + if (!exception_state.HadException()) + buffer_ = new_buffer; } AudioParam* AudioBufferSourceNode::playbackRate() const {
diff --git a/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.h b/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.h index 4786354..1aef3bb 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.h +++ b/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.h
@@ -61,7 +61,7 @@ // setBuffer() is called on the main thread. This is the buffer we use for // playback. void SetBuffer(AudioBuffer*, ExceptionState&); - AudioBuffer* Buffer() { return buffer_.Get(); } + SharedAudioBuffer* Buffer() { return shared_buffer_.get(); } // numberOfChannels() returns the number of output channels. This value // equals the number of channels from the buffer. If a new buffer is set with @@ -134,13 +134,11 @@ uint32_t frames_to_process); // Clamps grain parameters to the duration of the given AudioBuffer. - void ClampGrainParameters(const AudioBuffer*); + void ClampGrainParameters(const SharedAudioBuffer*); - // m_buffer holds the sample data which this node outputs. - // This Persistent doesn't make a reference cycle including - // AudioBufferSourceNode. - // It is cross-thread, as it will be accessed by the audio and main threads. - CrossThreadPersistent<AudioBuffer> buffer_; + // Sample data for the outputs of this node. The shared buffer can safely be + // accessed from the audio thread. + std::unique_ptr<SharedAudioBuffer> shared_buffer_; // Pointers for the buffer and destination. std::unique_ptr<const float* []> source_channels_; @@ -229,6 +227,7 @@ private: Member<AudioParam> playback_rate_; Member<AudioParam> detune_; + Member<AudioBuffer> buffer_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc index 5beab54f..d75f8f7 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc
@@ -6,6 +6,7 @@ #include <memory> +#include "base/synchronization/waitable_event.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/public/platform/web_url_request.h" @@ -85,7 +86,7 @@ } void RunBasicTest(WorkerThread* thread) { - WaitableEvent waitable_event; + base::WaitableEvent waitable_event; PostCrossThreadTask( *thread->GetTaskRunner(TaskType::kInternalTest), FROM_HERE, CrossThreadBind( @@ -96,7 +97,7 @@ } void RunSimpleProcessTest(WorkerThread* thread) { - WaitableEvent waitable_event; + base::WaitableEvent waitable_event; PostCrossThreadTask( *thread->GetTaskRunner(TaskType::kInternalTest), FROM_HERE, CrossThreadBind( @@ -107,7 +108,7 @@ } void RunParsingTest(WorkerThread* thread) { - WaitableEvent waitable_event; + base::WaitableEvent waitable_event; PostCrossThreadTask( *thread->GetTaskRunner(TaskType::kInternalTest), FROM_HERE, CrossThreadBind( @@ -118,7 +119,7 @@ } void RunParsingParameterDescriptorTest(WorkerThread* thread) { - WaitableEvent waitable_event; + base::WaitableEvent waitable_event; PostCrossThreadTask( *thread->GetTaskRunner(TaskType::kInternalTest), FROM_HERE, CrossThreadBind(&AudioWorkletGlobalScopeTest:: @@ -153,7 +154,7 @@ // if the class definition is correctly registered, then instantiate an // AudioWorkletProcessor instance from the definition. void RunBasicTestOnWorkletThread(WorkerThread* thread, - WaitableEvent* wait_event) { + base::WaitableEvent* wait_event) { EXPECT_TRUE(thread->IsCurrentThread()); auto* global_scope = To<AudioWorkletGlobalScope>(thread->GlobalScope()); @@ -201,7 +202,7 @@ // Test if various class definition patterns are parsed correctly. void RunParsingTestOnWorkletThread(WorkerThread* thread, - WaitableEvent* wait_event) { + base::WaitableEvent* wait_event) { EXPECT_TRUE(thread->IsCurrentThread()); auto* global_scope = To<AudioWorkletGlobalScope>(thread->GlobalScope()); @@ -256,7 +257,7 @@ // Test if the invocation of process() method in AudioWorkletProcessor and // AudioWorkletGlobalScope is performed correctly. void RunSimpleProcessTestOnWorkletThread(WorkerThread* thread, - WaitableEvent* wait_event) { + base::WaitableEvent* wait_event) { EXPECT_TRUE(thread->IsCurrentThread()); auto* global_scope = To<AudioWorkletGlobalScope>(thread->GlobalScope()); @@ -322,7 +323,7 @@ void RunParsingParameterDescriptorTestOnWorkletThread( WorkerThread* thread, - WaitableEvent* wait_event) { + base::WaitableEvent* wait_event) { EXPECT_TRUE(thread->IsCurrentThread()); auto* global_scope = To<AudioWorkletGlobalScope>(thread->GlobalScope());
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_thread.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_thread.cc index 2778e171..80f8318c 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_worklet_thread.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_thread.cc
@@ -14,7 +14,6 @@ #include "third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.h" #include "third_party/blink/renderer/platform/cross_thread_functional.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" -#include "third_party/blink/renderer/platform/waitable_event.h" #include "third_party/blink/renderer/platform/web_thread_supporting_gc.h" #include "third_party/blink/renderer/platform/weborigin/security_origin.h" #include "third_party/blink/renderer/platform/wtf/assertions.h"
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc index 52503a9..55f4322b 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc
@@ -5,6 +5,7 @@ #include "third_party/blink/renderer/modules/webaudio/audio_worklet_thread.h" #include <memory> +#include "base/synchronization/waitable_event.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/web_url_request.h" @@ -29,7 +30,6 @@ #include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h" #include "third_party/blink/renderer/platform/testing/testing_platform_support.h" #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" -#include "third_party/blink/renderer/platform/waitable_event.h" #include "third_party/blink/renderer/platform/web_thread_supporting_gc.h" #include "third_party/blink/renderer/platform/wtf/text/text_position.h" @@ -70,7 +70,7 @@ // Attempts to run some simple script for |thread|. void CheckWorkletCanExecuteScript(WorkerThread* thread) { - WaitableEvent wait_event; + base::WaitableEvent wait_event; thread->GetWorkerBackingThread().BackingThread().PostTask( FROM_HERE, CrossThreadBind(&AudioWorkletThreadTest::ExecuteScriptInWorklet, @@ -81,7 +81,8 @@ } private: - void ExecuteScriptInWorklet(WorkerThread* thread, WaitableEvent* wait_event) { + void ExecuteScriptInWorklet(WorkerThread* thread, + base::WaitableEvent* wait_event) { ScriptState* script_state = thread->GlobalScope()->ScriptController()->GetScriptState(); EXPECT_TRUE(script_state);
diff --git a/third_party/blink/renderer/modules/webaudio/convolver_node.cc b/third_party/blink/renderer/modules/webaudio/convolver_node.cc index 26c4cc6..9131343 100644 --- a/third_party/blink/renderer/modules/webaudio/convolver_node.cc +++ b/third_party/blink/renderer/modules/webaudio/convolver_node.cc
@@ -96,7 +96,7 @@ if (!buffer) { reverb_.reset(); - buffer_ = buffer; + shared_buffer_ = nullptr; return; } @@ -132,9 +132,10 @@ // reference to it is kept for later use in that class. scoped_refptr<AudioBus> buffer_bus = AudioBus::Create(number_of_channels, buffer_length, false); - for (unsigned i = 0; i < number_of_channels; ++i) + for (unsigned i = 0; i < number_of_channels; ++i) { buffer_bus->SetChannelMemory(i, buffer->getChannelData(i).View()->Data(), buffer_length); + } buffer_bus->SetSampleRate(buffer->sampleRate()); @@ -151,21 +152,16 @@ // Synchronize with process(). MutexLocker locker(process_lock_); reverb_ = std::move(reverb); - buffer_ = buffer; + shared_buffer_ = buffer->CreateSharedAudioBuffer(); if (buffer) { // This will propagate the channel count to any nodes connected further // downstream in the graph. Output(0).SetNumberOfChannels(ComputeNumberOfOutputChannels( - Input(0).NumberOfChannels(), buffer_->numberOfChannels())); + Input(0).NumberOfChannels(), shared_buffer_->numberOfChannels())); } } } -AudioBuffer* ConvolverHandler::Buffer() { - DCHECK(IsMainThread()); - return buffer_.Get(); -} - bool ConvolverHandler::RequiresTailProcessing() const { // Always return true even if the tail time and latency might both be zero. return true; @@ -237,9 +233,9 @@ if (input != &this->Input(0)) return; - if (buffer_) { + if (shared_buffer_) { unsigned number_of_output_channels = ComputeNumberOfOutputChannels( - input->NumberOfChannels(), buffer_->numberOfChannels()); + input->NumberOfChannels(), shared_buffer_->numberOfChannels()); if (IsInitialized() && number_of_output_channels != Output(0).NumberOfChannels()) { @@ -294,12 +290,14 @@ } AudioBuffer* ConvolverNode::buffer() const { - return GetConvolverHandler().Buffer(); + return buffer_; } void ConvolverNode::setBuffer(AudioBuffer* new_buffer, ExceptionState& exception_state) { GetConvolverHandler().SetBuffer(new_buffer, exception_state); + if (!exception_state.HadException()) + buffer_ = new_buffer; } bool ConvolverNode::normalize() const { @@ -310,4 +308,9 @@ GetConvolverHandler().SetNormalize(normalize); } +void ConvolverNode::Trace(Visitor* visitor) { + visitor->Trace(buffer_); + AudioNode::Trace(visitor); +} + } // namespace blink
diff --git a/third_party/blink/renderer/modules/webaudio/convolver_node.h b/third_party/blink/renderer/modules/webaudio/convolver_node.h index d615533..22cf96b 100644 --- a/third_party/blink/renderer/modules/webaudio/convolver_node.h +++ b/third_party/blink/renderer/modules/webaudio/convolver_node.h
@@ -40,6 +40,7 @@ class ConvolverOptions; class ExceptionState; class Reverb; +class SharedAudioBuffer; class MODULES_EXPORT ConvolverHandler final : public AudioHandler { public: @@ -54,7 +55,6 @@ // Impulse responses void SetBuffer(AudioBuffer*, ExceptionState&); - AudioBuffer* Buffer(); bool Normalize() const { return normalize_; } void SetNormalize(bool normalize) { normalize_ = normalize; } @@ -74,10 +74,7 @@ unsigned response_channels) const; std::unique_ptr<Reverb> reverb_; - // This Persistent doesn't make a reference cycle including the owner - // ConvolverNode. - // It is cross-thread, as it will be accessed by the audio and main threads. - CrossThreadPersistent<AudioBuffer> buffer_; + std::unique_ptr<SharedAudioBuffer> shared_buffer_; // This synchronizes dynamic changes to the convolution impulse response with // process(). @@ -105,9 +102,13 @@ bool normalize() const; void setNormalize(bool); + void Trace(Visitor*) override; + private: ConvolverHandler& GetConvolverHandler() const; + Member<AudioBuffer> buffer_; + FRIEND_TEST_ALL_PREFIXES(ConvolverNodeTest, ReverbLifetime); };
diff --git a/third_party/blink/renderer/modules/webaudio/offline_audio_context.cc b/third_party/blink/renderer/modules/webaudio/offline_audio_context.cc index df4d7ae..6b8c8760 100644 --- a/third_party/blink/renderer/modules/webaudio/offline_audio_context.cc +++ b/third_party/blink/renderer/modules/webaudio/offline_audio_context.cc
@@ -216,6 +216,8 @@ // Start rendering and return the promise. is_rendering_started_ = true; SetContextState(kRunning); + static_cast<OfflineAudioDestinationNode*>(destination()) + ->SetDestinationBuffer(render_target); DestinationHandler().InitializeOfflineRenderThread(render_target); DestinationHandler().StartRendering(); @@ -359,8 +361,9 @@ // Avoid firing the event if the document has already gone away. if (GetExecutionContext()) { - AudioBuffer* rendered_buffer = DestinationHandler().RenderTarget(); - + AudioBuffer* rendered_buffer = + static_cast<OfflineAudioDestinationNode*>(destination()) + ->DestinationBuffer(); DCHECK(rendered_buffer); if (!rendered_buffer) return;
diff --git a/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc b/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc index d2ff67e..cb15f3e 100644 --- a/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc +++ b/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc
@@ -47,7 +47,6 @@ uint32_t frames_to_process, float sample_rate) : AudioDestinationHandler(node), - render_target_(nullptr), frames_processed_(0), frames_to_process_(frames_to_process), is_rendering_started_(false), @@ -109,7 +108,7 @@ void OfflineAudioDestinationHandler::StartRendering() { DCHECK(IsMainThread()); - DCHECK(render_target_); + DCHECK(shared_render_target_); DCHECK(render_thread_task_runner_); // Rendering was not started. Starting now. @@ -147,7 +146,7 @@ AudioBuffer* render_target) { DCHECK(IsMainThread()); - render_target_ = render_target; + shared_render_target_ = render_target->CreateSharedAudioBuffer(); render_bus_ = AudioBus::Create(render_target->numberOfChannels(), audio_utilities::kRenderQuantumFrames); DCHECK(render_bus_); @@ -167,8 +166,8 @@ if (!is_audio_context_initialized) return; - bool channels_match = - render_bus_->NumberOfChannels() == render_target_->numberOfChannels(); + bool channels_match = render_bus_->NumberOfChannels() == + shared_render_target_->numberOfChannels(); DCHECK(channels_match); if (!channels_match) return; @@ -203,10 +202,12 @@ return; } - number_of_channels = render_target_->numberOfChannels(); + number_of_channels = shared_render_target_->numberOfChannels(); destinations.ReserveInitialCapacity(number_of_channels); - for (unsigned i = 0; i < number_of_channels; ++i) - destinations.push_back(render_target_->getChannelData(i).View()->Data()); + for (unsigned i = 0; i < number_of_channels; ++i) { + destinations.push_back( + static_cast<float*>(shared_render_target_->channels()[i].Data())); + } ProcessHeap::CrossThreadPersistentMutex().unlock(); } @@ -417,4 +418,9 @@ *context, number_of_channels, frames_to_process, sample_rate); } +void OfflineAudioDestinationNode::Trace(Visitor* visitor) { + visitor->Trace(destination_buffer_); + AudioDestinationNode::Trace(visitor); +} + } // namespace blink
diff --git a/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.h b/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.h index dc22545..e4d2d8b 100644 --- a/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.h +++ b/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.h
@@ -79,7 +79,6 @@ // allows creation of the AudioBuffer when startRendering is called // instead of when the OfflineAudioContext is created. void InitializeOfflineRenderThread(AudioBuffer* render_target); - AudioBuffer* RenderTarget() const { return render_target_.Get(); } unsigned NumberOfChannels() const { return number_of_channels_; } @@ -125,10 +124,8 @@ // from AudioWorkletThread will be used until the rendering is finished. void PrepareTaskRunnerForRendering(); - // This AudioHandler renders into this AudioBuffer. - // This Persistent doesn't make a reference cycle including the owner - // OfflineAudioDestinationNode. It is accessed by both audio and main thread. - CrossThreadPersistent<AudioBuffer> render_target_; + // This AudioHandler renders into this SharedAudioBuffer. + std::unique_ptr<SharedAudioBuffer> shared_render_target_; // Temporary AudioBus for each render quantum. scoped_refptr<AudioBus> render_bus_; @@ -164,6 +161,17 @@ unsigned number_of_channels, uint32_t frames_to_process, float sample_rate); + + AudioBuffer* DestinationBuffer() const { return destination_buffer_; } + + void SetDestinationBuffer(AudioBuffer* buffer) { + destination_buffer_ = buffer; + } + + void Trace(Visitor* visitor) override; + + private: + Member<AudioBuffer> destination_buffer_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/webaudio/oscillator_node.cc b/third_party/blink/renderer/modules/webaudio/oscillator_node.cc index 76d7e06..c2b628f 100644 --- a/third_party/blink/renderer/modules/webaudio/oscillator_node.cc +++ b/third_party/blink/renderer/modules/webaudio/oscillator_node.cc
@@ -125,7 +125,7 @@ } } -bool OscillatorHandler::SetType(unsigned type) { +bool OscillatorHandler::SetType(uint8_t type) { PeriodicWave* periodic_wave = nullptr; switch (type) {
diff --git a/third_party/blink/renderer/modules/webaudio/oscillator_node.h b/third_party/blink/renderer/modules/webaudio/oscillator_node.h index a3840ec..40563bbe 100644 --- a/third_party/blink/renderer/modules/webaudio/oscillator_node.h +++ b/third_party/blink/renderer/modules/webaudio/oscillator_node.h
@@ -46,7 +46,13 @@ public: // The waveform type. // These must be defined as in the .idl file. - enum { SINE = 0, SQUARE = 1, SAWTOOTH = 2, TRIANGLE = 3, CUSTOM = 4 }; + enum : uint8_t { + SINE = 0, + SQUARE = 1, + SAWTOOTH = 2, + TRIANGLE = 3, + CUSTOM = 4 + }; static scoped_refptr<OscillatorHandler> Create(AudioNode&, float sample_rate, @@ -71,7 +77,7 @@ PeriodicWave* wave_table, AudioParamHandler& frequency, AudioParamHandler& detune); - bool SetType(unsigned); // Returns true on success. + bool SetType(uint8_t); // Returns true on success. // Returns true if there are sample-accurate timeline parameter changes. bool CalculateSampleAccuratePhaseIncrements(uint32_t frames_to_process); @@ -79,7 +85,7 @@ bool PropagatesSilence() const override; // One of the waveform types defined in the enum. - unsigned short type_; + uint8_t type_; // Frequency value in Hertz. scoped_refptr<AudioParamHandler> frequency_;
diff --git a/third_party/blink/renderer/modules/webaudio/script_processor_node.cc b/third_party/blink/renderer/modules/webaudio/script_processor_node.cc index b733e5a..3f3b28b 100644 --- a/third_party/blink/renderer/modules/webaudio/script_processor_node.cc +++ b/third_party/blink/renderer/modules/webaudio/script_processor_node.cc
@@ -39,7 +39,6 @@ #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/cross_thread_functional.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/waitable_event.h" namespace blink { @@ -48,11 +47,11 @@ float sample_rate, uint32_t buffer_size, uint32_t number_of_input_channels, - uint32_t number_of_output_channels) + uint32_t number_of_output_channels, + const HeapVector<Member<AudioBuffer>>& input_buffers, + const HeapVector<Member<AudioBuffer>>& output_buffers) : AudioHandler(kNodeTypeScriptProcessor, node, sample_rate), double_buffer_index_(0), - input_buffers_(MakeGarbageCollected<HeapVector<Member<AudioBuffer>>>()), - output_buffers_(MakeGarbageCollected<HeapVector<Member<AudioBuffer>>>()), buffer_size_(buffer_size), buffer_read_write_index_(0), number_of_input_channels_(number_of_input_channels), @@ -61,11 +60,7 @@ AudioBus::Create(number_of_input_channels, audio_utilities::kRenderQuantumFrames, false)) { - // Regardless of the allowed buffer sizes, we still need to process at the - // granularity of the AudioNode. - if (buffer_size_ < audio_utilities::kRenderQuantumFrames) - buffer_size_ = audio_utilities::kRenderQuantumFrames; - + DCHECK_GE(buffer_size_, audio_utilities::kRenderQuantumFrames); DCHECK_LE(number_of_input_channels, BaseAudioContext::MaxNumberOfChannels()); AddInput(); @@ -79,6 +74,15 @@ TaskType::kMediaElementEvent); } + for (uint32_t i = 0; i < 2; ++i) { + shared_input_buffers_.push_back( + input_buffers[i] ? input_buffers[i]->CreateSharedAudioBuffer() + : nullptr); + shared_output_buffers_.push_back( + output_buffers[i] ? output_buffers[i]->CreateSharedAudioBuffer() + : nullptr); + } + Initialize(); } @@ -87,10 +91,12 @@ float sample_rate, uint32_t buffer_size, uint32_t number_of_input_channels, - uint32_t number_of_output_channels) { + uint32_t number_of_output_channels, + const HeapVector<Member<AudioBuffer>>& input_buffers, + const HeapVector<Member<AudioBuffer>>& output_buffers) { return base::AdoptRef(new ScriptProcessorHandler( node, sample_rate, buffer_size, number_of_input_channels, - number_of_output_channels)); + number_of_output_channels, input_buffers, output_buffers)); } ScriptProcessorHandler::~ScriptProcessorHandler() { @@ -100,28 +106,6 @@ void ScriptProcessorHandler::Initialize() { if (IsInitialized()) return; - - float sample_rate = Context()->sampleRate(); - - // Create double buffers on both the input and output sides. - // These AudioBuffers will be directly accessed in the main thread by - // JavaScript. - for (uint32_t i = 0; i < 2; ++i) { - AudioBuffer* input_buffer = - number_of_input_channels_ - ? AudioBuffer::Create(number_of_input_channels_, BufferSize(), - sample_rate) - : nullptr; - AudioBuffer* output_buffer = - number_of_output_channels_ - ? AudioBuffer::Create(number_of_output_channels_, BufferSize(), - sample_rate) - : nullptr; - - input_buffers_->push_back(input_buffer); - output_buffers_->push_back(output_buffer); - } - AudioHandler::Initialize(); } @@ -142,25 +126,29 @@ // sides. uint32_t double_buffer_index = this->DoubleBufferIndex(); bool is_double_buffer_index_good = - double_buffer_index < 2 && double_buffer_index < input_buffers_->size() && - double_buffer_index < output_buffers_->size(); + double_buffer_index < 2 && + double_buffer_index < shared_input_buffers_.size() && + double_buffer_index < shared_output_buffers_.size(); DCHECK(is_double_buffer_index_good); if (!is_double_buffer_index_good) return; - AudioBuffer* input_buffer = input_buffers_->at(double_buffer_index).Get(); - AudioBuffer* output_buffer = output_buffers_->at(double_buffer_index).Get(); + SharedAudioBuffer* shared_input_buffer = + shared_input_buffers_.at(double_buffer_index).get(); + SharedAudioBuffer* shared_output_buffer = + shared_output_buffers_.at(double_buffer_index).get(); // Check the consistency of input and output buffers. uint32_t number_of_input_channels = internal_input_bus_->NumberOfChannels(); bool buffers_are_good = - output_buffer && BufferSize() == output_buffer->length() && + shared_output_buffer && BufferSize() == shared_output_buffer->length() && buffer_read_write_index_ + frames_to_process <= BufferSize(); // If the number of input channels is zero, it's ok to have inputBuffer = 0. - if (internal_input_bus_->NumberOfChannels()) - buffers_are_good = buffers_are_good && input_buffer && - BufferSize() == input_buffer->length(); + if (internal_input_bus_->NumberOfChannels()) { + buffers_are_good = buffers_are_good && shared_input_buffer && + BufferSize() == shared_input_buffer->length(); + } DCHECK(buffers_are_good); if (!buffers_are_good) @@ -187,7 +175,7 @@ for (uint32_t i = 0; i < number_of_input_channels; ++i) internal_input_bus_->SetChannelMemory( i, - input_buffer->getChannelData(i).View()->Data() + + static_cast<float*>(shared_input_buffer->channels()[i].Data()) + buffer_read_write_index_, frames_to_process); @@ -197,7 +185,7 @@ // Copy from the output buffer to the output. for (uint32_t i = 0; i < number_of_output_channels; ++i) { memcpy(output_bus->Channel(i)->MutableData(), - output_buffer->getChannelData(i).View()->Data() + + static_cast<float*>(shared_output_buffer->channels()[i].Data()) + buffer_read_write_index_, sizeof(float) * frames_to_process); } @@ -219,7 +207,7 @@ if (!try_locker.Locked()) { // We're late in handling the previous request. The main thread must be // very busy. The best we can do is clear out the buffer ourself here. - output_buffer->Zero(); + shared_output_buffer->Zero(); } else { // With the realtime context, execute the script code asynchronously // and do not wait. @@ -233,8 +221,8 @@ } else { // If this node is in the offline audio context, use the // waitable event to synchronize to the offline rendering thread. - std::unique_ptr<WaitableEvent> waitable_event = - std::make_unique<WaitableEvent>(); + std::unique_ptr<base::WaitableEvent> waitable_event = + std::make_unique<base::WaitableEvent>(); PostCrossThreadTask( *task_runner_, FROM_HERE, @@ -263,12 +251,6 @@ if (double_buffer_index > 1) return; - AudioBuffer* input_buffer = input_buffers_->at(double_buffer_index).Get(); - AudioBuffer* output_buffer = output_buffers_->at(double_buffer_index).Get(); - DCHECK(output_buffer); - if (!output_buffer) - return; - // Avoid firing the event if the document has already gone away. if (GetNode()) { // This synchronizes with process(). @@ -280,16 +262,14 @@ // double-buffering. double playback_time = (Context()->CurrentSampleFrame() + buffer_size_) / static_cast<double>(Context()->sampleRate()); - - // Call the JavaScript event handler which will do the audio processing. - GetNode()->DispatchEvent(*AudioProcessingEvent::Create( - input_buffer, output_buffer, playback_time)); + static_cast<ScriptProcessorNode*>(GetNode())->DispatchEvent( + playback_time, double_buffer_index); } } void ScriptProcessorHandler::FireProcessEventForOfflineAudioContext( uint32_t double_buffer_index, - WaitableEvent* waitable_event) { + base::WaitableEvent* waitable_event) { DCHECK(IsMainThread()); if (!Context() || !Context()->GetExecutionContext()) @@ -301,21 +281,13 @@ return; } - AudioBuffer* input_buffer = input_buffers_->at(double_buffer_index).Get(); - AudioBuffer* output_buffer = output_buffers_->at(double_buffer_index).Get(); - DCHECK(output_buffer); - if (!output_buffer) { - waitable_event->Signal(); - return; - } - if (GetNode()) { // We do not need a process lock here because the offline render thread // is locked by the waitable event. double playback_time = (Context()->CurrentSampleFrame() + buffer_size_) / static_cast<double>(Context()->sampleRate()); - GetNode()->DispatchEvent(*AudioProcessingEvent::Create( - input_buffer, output_buffer, playback_time)); + static_cast<ScriptProcessorNode*>(GetNode())->DispatchEvent( + playback_time, double_buffer_index); } waitable_event->Signal(); @@ -369,9 +341,31 @@ uint32_t number_of_input_channels, uint32_t number_of_output_channels) : AudioNode(context) { - SetHandler(ScriptProcessorHandler::Create(*this, sample_rate, buffer_size, - number_of_input_channels, - number_of_output_channels)); + // Regardless of the allowed buffer sizes, we still need to process at the + // granularity of the AudioNode. + if (buffer_size < audio_utilities::kRenderQuantumFrames) + buffer_size = audio_utilities::kRenderQuantumFrames; + + // Create double buffers on both the input and output sides. + // These AudioBuffers will be directly accessed in the main thread by + // JavaScript. + for (uint32_t i = 0; i < 2; ++i) { + AudioBuffer* input_buffer = + number_of_input_channels ? AudioBuffer::Create(number_of_input_channels, + buffer_size, sample_rate) + : nullptr; + AudioBuffer* output_buffer = + number_of_output_channels + ? AudioBuffer::Create(number_of_output_channels, buffer_size, + sample_rate) + : nullptr; + + input_buffers_.push_back(input_buffer); + output_buffers_.push_back(output_buffer); + } + SetHandler(ScriptProcessorHandler::Create( + *this, sample_rate, buffer_size, number_of_input_channels, + number_of_output_channels, input_buffers_, output_buffers_)); } static uint32_t ChooseBufferSize(uint32_t callback_buffer_size) { @@ -511,6 +505,15 @@ return static_cast<ScriptProcessorHandler&>(Handler()).BufferSize(); } +void ScriptProcessorNode::DispatchEvent(double playback_time, + uint32_t double_buffer_index) { + AudioBuffer* input_buffer = input_buffers_.at(double_buffer_index).Get(); + AudioBuffer* output_buffer = output_buffers_.at(double_buffer_index).Get(); + DCHECK(output_buffer); + AudioNode::DispatchEvent(*AudioProcessingEvent::Create( + input_buffer, output_buffer, playback_time)); +} + bool ScriptProcessorNode::HasPendingActivity() const { // To prevent the node from leaking after the context is closed. if (context()->IsContextClosed()) @@ -524,4 +527,10 @@ return false; } +void ScriptProcessorNode::Trace(Visitor* visitor) { + visitor->Trace(input_buffers_); + visitor->Trace(output_buffers_); + AudioNode::Trace(visitor); +} + } // namespace blink
diff --git a/third_party/blink/renderer/modules/webaudio/script_processor_node.h b/third_party/blink/renderer/modules/webaudio/script_processor_node.h index 6dc2433..99f1e3f 100644 --- a/third_party/blink/renderer/modules/webaudio/script_processor_node.h +++ b/third_party/blink/renderer/modules/webaudio/script_processor_node.h
@@ -28,6 +28,7 @@ #include "base/gtest_prod_util.h" #include "base/memory/scoped_refptr.h" +#include "base/synchronization/waitable_event.h" #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h" #include "third_party/blink/renderer/modules/webaudio/audio_node.h" #include "third_party/blink/renderer/platform/audio/audio_bus.h" @@ -37,8 +38,9 @@ namespace blink { -class BaseAudioContext; class AudioBuffer; +class BaseAudioContext; +class SharedAudioBuffer; class WaitableEvent; // ScriptProcessorNode is an AudioNode which allows for arbitrary synthesis or @@ -56,7 +58,9 @@ float sample_rate, uint32_t buffer_size, uint32_t number_of_input_channels, - uint32_t number_of_output_channels); + uint32_t number_of_output_channels, + const HeapVector<Member<AudioBuffer>>& input_buffers, + const HeapVector<Member<AudioBuffer>>& output_buffers); ~ScriptProcessorHandler() override; // AudioHandler @@ -77,23 +81,23 @@ float sample_rate, uint32_t buffer_size, uint32_t number_of_input_channels, - uint32_t number_of_output_channels); + uint32_t number_of_output_channels, + const HeapVector<Member<AudioBuffer>>& input_buffers, + const HeapVector<Member<AudioBuffer>>& output_buffers); double TailTime() const override; double LatencyTime() const override; bool RequiresTailProcessing() const final; void FireProcessEvent(uint32_t); - void FireProcessEventForOfflineAudioContext(uint32_t, WaitableEvent*); + void FireProcessEventForOfflineAudioContext(uint32_t, base::WaitableEvent*); // Double buffering uint32_t DoubleBufferIndex() const { return double_buffer_index_; } void SwapBuffers() { double_buffer_index_ = 1 - double_buffer_index_; } uint32_t double_buffer_index_; - // These Persistent don't make reference cycles including the owner - // ScriptProcessorNode. - CrossThreadPersistent<HeapVector<Member<AudioBuffer>>> input_buffers_; - CrossThreadPersistent<HeapVector<Member<AudioBuffer>>> output_buffers_; + WTF::Vector<std::unique_ptr<SharedAudioBuffer>> shared_input_buffers_; + WTF::Vector<std::unique_ptr<SharedAudioBuffer>> shared_output_buffers_; uint32_t buffer_size_; uint32_t buffer_read_write_index_; @@ -148,10 +152,16 @@ DEFINE_ATTRIBUTE_EVENT_LISTENER(audioprocess, kAudioprocess) uint32_t bufferSize() const; + void DispatchEvent(double playback_time, uint32_t double_buffer_index); + // ScriptWrappable bool HasPendingActivity() const final; - void Trace(blink::Visitor* visitor) override { AudioNode::Trace(visitor); } + void Trace(blink::Visitor* visitor) override; + + private: + HeapVector<Member<AudioBuffer>> input_buffers_; + HeapVector<Member<AudioBuffer>> output_buffers_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/webaudio/script_processor_node_test.cc b/third_party/blink/renderer/modules/webaudio/script_processor_node_test.cc index 01073040..d5cf3a6 100644 --- a/third_party/blink/renderer/modules/webaudio/script_processor_node_test.cc +++ b/third_party/blink/renderer/modules/webaudio/script_processor_node_test.cc
@@ -18,14 +18,14 @@ context->createScriptProcessor(ASSERT_NO_EXCEPTION); ScriptProcessorHandler& handler = static_cast<ScriptProcessorHandler&>(node->Handler()); - EXPECT_EQ(2u, handler.input_buffers_->size()); - EXPECT_EQ(2u, handler.output_buffers_->size()); + EXPECT_EQ(2u, handler.shared_input_buffers_.size()); + EXPECT_EQ(2u, handler.shared_input_buffers_.size()); BaseAudioContext::GraphAutoLocker locker(context); handler.Dispose(); // Buffers should live after dispose() because an audio thread is using // them. - EXPECT_EQ(2u, handler.input_buffers_->size()); - EXPECT_EQ(2u, handler.output_buffers_->size()); + EXPECT_EQ(2u, handler.shared_input_buffers_.size()); + EXPECT_EQ(2u, handler.shared_input_buffers_.size()); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/webdatabase/database.cc b/third_party/blink/renderer/modules/webdatabase/database.cc index 4448256..45e85eb 100644 --- a/third_party/blink/renderer/modules/webdatabase/database.cc +++ b/third_party/blink/renderer/modules/webdatabase/database.cc
@@ -27,6 +27,7 @@ #include <memory> +#include "base/synchronization/waitable_event.h" #include "base/thread_annotations.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/task_type.h" @@ -52,7 +53,6 @@ #include "third_party/blink/renderer/modules/webdatabase/storage_log.h" #include "third_party/blink/renderer/platform/cross_thread_functional.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/waitable_event.h" // Registering "opened" databases with the DatabaseTracker // ======================================================= @@ -279,7 +279,7 @@ DatabaseError& error, String& error_message, V8DatabaseCallback* creation_callback) { - WaitableEvent event; + base::WaitableEvent event; if (!GetDatabaseContext()->DatabaseThreadAvailable()) return false; @@ -901,7 +901,7 @@ // take strict turns in dealing with them. However, if the code changes, // this may not be true anymore. Vector<String> result; - WaitableEvent event; + base::WaitableEvent event; if (!GetDatabaseContext()->DatabaseThreadAvailable()) return result;
diff --git a/third_party/blink/renderer/modules/webdatabase/database_task.cc b/third_party/blink/renderer/modules/webdatabase/database_task.cc index 957f0d1..6b917f3 100644 --- a/third_party/blink/renderer/modules/webdatabase/database_task.cc +++ b/third_party/blink/renderer/modules/webdatabase/database_task.cc
@@ -28,6 +28,7 @@ #include "third_party/blink/renderer/modules/webdatabase/database_task.h" +#include "base/synchronization/waitable_event.h" #include "third_party/blink/renderer/modules/webdatabase/database.h" #include "third_party/blink/renderer/modules/webdatabase/database_context.h" #include "third_party/blink/renderer/modules/webdatabase/database_thread.h" @@ -35,7 +36,8 @@ namespace blink { -DatabaseTask::DatabaseTask(Database* database, WaitableEvent* complete_event) +DatabaseTask::DatabaseTask(Database* database, + base::WaitableEvent* complete_event) : database_(database), complete_event_(complete_event) #if DCHECK_IS_ON() @@ -85,12 +87,13 @@ // Opens the database file and verifies the version matches the expected // version. -Database::DatabaseOpenTask::DatabaseOpenTask(Database* database, - bool set_version_in_new_database, - WaitableEvent* complete_event, - DatabaseError& error, - String& error_message, - bool& success) +Database::DatabaseOpenTask::DatabaseOpenTask( + Database* database, + bool set_version_in_new_database, + base::WaitableEvent* complete_event, + DatabaseError& error, + String& error_message, + bool& success) : DatabaseTask(database, complete_event), set_version_in_new_database_(set_version_in_new_database), error_(error), @@ -117,8 +120,9 @@ // *** DatabaseCloseTask *** // Closes the database. -Database::DatabaseCloseTask::DatabaseCloseTask(Database* database, - WaitableEvent* complete_event) +Database::DatabaseCloseTask::DatabaseCloseTask( + Database* database, + base::WaitableEvent* complete_event) : DatabaseTask(database, complete_event) {} void Database::DatabaseCloseTask::DoPerformTask() { @@ -168,7 +172,7 @@ Database::DatabaseTableNamesTask::DatabaseTableNamesTask( Database* database, - WaitableEvent* complete_event, + base::WaitableEvent* complete_event, Vector<String>& names) : DatabaseTask(database, complete_event), table_names_(names) { DCHECK(complete_event); // A task with output parameters is supposed to be
diff --git a/third_party/blink/renderer/modules/webdatabase/database_task.h b/third_party/blink/renderer/modules/webdatabase/database_task.h index 992d23e9..6339445 100644 --- a/third_party/blink/renderer/modules/webdatabase/database_task.h +++ b/third_party/blink/renderer/modules/webdatabase/database_task.h
@@ -33,12 +33,12 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" +#include "base/synchronization/waitable_event.h" #include "third_party/blink/renderer/modules/webdatabase/database.h" #include "third_party/blink/renderer/modules/webdatabase/database_basic_types.h" #include "third_party/blink/renderer/modules/webdatabase/database_error.h" #include "third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.h" #include "third_party/blink/renderer/platform/heap/handle.h" -#include "third_party/blink/renderer/platform/waitable_event.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" #include "third_party/blink/renderer/platform/wtf/threading.h" #include "third_party/blink/renderer/platform/wtf/vector.h" @@ -56,14 +56,14 @@ Database* GetDatabase() const { return database_.Get(); } protected: - DatabaseTask(Database*, WaitableEvent* complete_event); + DatabaseTask(Database*, base::WaitableEvent* complete_event); private: virtual void DoPerformTask() = 0; virtual void TaskCancelled() {} CrossThreadPersistent<Database> database_; - WaitableEvent* complete_event_; + base::WaitableEvent* complete_event_; #if DCHECK_IS_ON() virtual const char* DebugTaskName() const = 0; @@ -78,7 +78,7 @@ static std::unique_ptr<DatabaseOpenTask> Create( Database* db, bool set_version_in_new_database, - WaitableEvent* complete_event, + base::WaitableEvent* complete_event, DatabaseError& error, String& error_message, bool& success) { @@ -90,7 +90,7 @@ private: DatabaseOpenTask(Database*, bool set_version_in_new_database, - WaitableEvent*, + base::WaitableEvent*, DatabaseError&, String& error_message, bool& success); @@ -110,12 +110,12 @@ public: static std::unique_ptr<DatabaseCloseTask> Create( Database* db, - WaitableEvent* synchronizer) { + base::WaitableEvent* synchronizer) { return base::WrapUnique(new DatabaseCloseTask(db, synchronizer)); } private: - DatabaseCloseTask(Database*, WaitableEvent*); + DatabaseCloseTask(Database*, base::WaitableEvent*); void DoPerformTask() override; #if DCHECK_IS_ON() @@ -149,14 +149,18 @@ class Database::DatabaseTableNamesTask final : public DatabaseTask { public: - static std::unique_ptr<DatabaseTableNamesTask> - Create(Database* db, WaitableEvent* synchronizer, Vector<String>& names) { + static std::unique_ptr<DatabaseTableNamesTask> Create( + Database* db, + base::WaitableEvent* synchronizer, + Vector<String>& names) { return base::WrapUnique( new DatabaseTableNamesTask(db, synchronizer, names)); } private: - DatabaseTableNamesTask(Database*, WaitableEvent*, Vector<String>& names); + DatabaseTableNamesTask(Database*, + base::WaitableEvent*, + Vector<String>& names); void DoPerformTask() override; #if DCHECK_IS_ON()
diff --git a/third_party/blink/renderer/modules/webdatabase/database_thread.cc b/third_party/blink/renderer/modules/webdatabase/database_thread.cc index 38671f3..c7411f5a 100644 --- a/third_party/blink/renderer/modules/webdatabase/database_thread.cc +++ b/third_party/blink/renderer/modules/webdatabase/database_thread.cc
@@ -29,6 +29,7 @@ #include "third_party/blink/renderer/modules/webdatabase/database_thread.h" #include <memory> +#include "base/synchronization/waitable_event.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/modules/webdatabase/database.h" #include "third_party/blink/renderer/modules/webdatabase/database_task.h" @@ -36,7 +37,6 @@ #include "third_party/blink/renderer/modules/webdatabase/sql_transaction_coordinator.h" #include "third_party/blink/renderer/modules/webdatabase/storage_log.h" #include "third_party/blink/renderer/platform/cross_thread_functional.h" -#include "third_party/blink/renderer/platform/waitable_event.h" #include "third_party/blink/renderer/platform/web_thread_supporting_gc.h" namespace blink { @@ -74,7 +74,7 @@ void DatabaseThread::Terminate() { DCHECK(IsMainThread()); - WaitableEvent sync; + base::WaitableEvent sync; { MutexLocker lock(termination_requested_mutex_); DCHECK(!termination_requested_);
diff --git a/third_party/blink/renderer/modules/webdatabase/database_thread.h b/third_party/blink/renderer/modules/webdatabase/database_thread.h index 168cc4ab..fc146e7 100644 --- a/third_party/blink/renderer/modules/webdatabase/database_thread.h +++ b/third_party/blink/renderer/modules/webdatabase/database_thread.h
@@ -29,6 +29,7 @@ #define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBDATABASE_DATABASE_THREAD_H_ #include <memory> +#include "base/synchronization/waitable_event.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/web_thread_supporting_gc.h" #include "third_party/blink/renderer/platform/wtf/hash_map.h" @@ -40,7 +41,6 @@ class DatabaseTask; class SQLTransactionClient; class SQLTransactionCoordinator; -class WaitableEvent; class DatabaseThread : public GarbageCollectedFinalized<DatabaseThread> { public: @@ -86,7 +86,7 @@ std::unique_ptr<SQLTransactionClient> transaction_client_; CrossThreadPersistent<SQLTransactionCoordinator> transaction_coordinator_; - WaitableEvent* cleanup_sync_; + base::WaitableEvent* cleanup_sync_; Mutex termination_requested_mutex_; bool termination_requested_;
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc index b45de597..52f2ef8a 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -104,7 +104,6 @@ #include "third_party/blink/renderer/platform/graphics/graphics_context.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/waitable_event.h" #include "third_party/blink/renderer/platform/wtf/functional.h" #include "third_party/blink/renderer/platform/wtf/text/string_builder.h" #include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h" @@ -622,7 +621,7 @@ static void CreateContextProviderOnMainThread( ContextProviderCreationInfo* creation_info, - WaitableEvent* waitable_event) { + base::WaitableEvent* waitable_event) { DCHECK(IsMainThread()); // Ask for gpu compositing mode when making the context. The context will be // lost if the mode changes. @@ -641,7 +640,7 @@ Platform::GraphicsInfo* gl_info, bool* using_gpu_compositing, const KURL& url) { - WaitableEvent waitable_event; + base::WaitableEvent waitable_event; ContextProviderCreationInfo creation_info; creation_info.context_attributes = context_attributes; creation_info.gl_info = gl_info;
diff --git a/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc b/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc index 1118ca1..4f648b5d 100644 --- a/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc +++ b/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc
@@ -275,7 +275,8 @@ bool WebSocketChannelImpl::Connect(const KURL& url, const String& protocol) { network::mojom::blink::WebSocketPtr socket_ptr; - auto socket_request = mojo::MakeRequest(&socket_ptr); + auto socket_request = mojo::MakeRequest( + &socket_ptr, execution_context_->GetTaskRunner(TaskType::kWebSocket)); service_manager::InterfaceProvider* interface_provider = execution_context_->GetInterfaceProvider(); if (interface_provider)
diff --git a/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread.cc b/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread.cc index 5b692654..58d7cc7 100644 --- a/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread.cc +++ b/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread.cc
@@ -5,6 +5,7 @@ #include "third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread.h" #include "base/memory/ptr_util.h" +#include "base/synchronization/waitable_event.h" #include "third_party/blink/renderer/core/workers/global_scope_creation_params.h" #include "third_party/blink/renderer/core/workers/worker_backing_thread.h" #include "third_party/blink/renderer/core/workers/worklet_thread_holder.h" @@ -64,14 +65,14 @@ ->GetThread(); } -static void CollectAllGarbageOnThread(WaitableEvent* done_event) { +static void CollectAllGarbageOnThread(base::WaitableEvent* done_event) { blink::ThreadState::Current()->CollectAllGarbage(); done_event->Signal(); } void AnimationAndPaintWorkletThread::CollectAllGarbage() { DCHECK(IsMainThread()); - WaitableEvent done_event; + base::WaitableEvent done_event; auto* holder = WorkletThreadHolder<AnimationAndPaintWorkletThread>::GetInstance(); if (!holder)
diff --git a/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc b/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc index c9f0ba8f..e3224671 100644 --- a/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc +++ b/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc
@@ -27,7 +27,6 @@ #include "third_party/blink/renderer/platform/cross_thread_functional.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h" #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" -#include "third_party/blink/renderer/platform/waitable_event.h" #include "third_party/blink/renderer/platform/web_thread_supporting_gc.h" #include "third_party/blink/renderer/platform/wtf/text/text_position.h" @@ -55,8 +54,8 @@ // Attempts to run some simple script for |thread|. void CheckWorkletCanExecuteScript(WorkerThread* thread) { - std::unique_ptr<WaitableEvent> wait_event = - std::make_unique<WaitableEvent>(); + std::unique_ptr<base::WaitableEvent> wait_event = + std::make_unique<base::WaitableEvent>(); thread->GetWorkerBackingThread().BackingThread().PostTask( FROM_HERE, CrossThreadBind( @@ -69,7 +68,8 @@ std::unique_ptr<WorkerReportingProxy> reporting_proxy_; private: - void ExecuteScriptInWorklet(WorkerThread* thread, WaitableEvent* wait_event) { + void ExecuteScriptInWorklet(WorkerThread* thread, + base::WaitableEvent* wait_event) { ScriptState* script_state = thread->GlobalScope()->ScriptController()->GetScriptState(); EXPECT_TRUE(script_state);
diff --git a/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc b/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc index faac2ca..050cbb4 100644 --- a/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc +++ b/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc
@@ -29,10 +29,10 @@ #include "third_party/blink/renderer/platform/audio/hrtf_database_loader.h" #include "base/location.h" +#include "base/synchronization/waitable_event.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/platform/cross_thread_functional.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/waitable_event.h" namespace blink { @@ -117,7 +117,7 @@ // This cleanup task is needed just to make sure that the loader thread finishes // the load task and thus the loader thread doesn't touch m_thread any more. -void HRTFDatabaseLoader::CleanupTask(WaitableEvent* sync) { +void HRTFDatabaseLoader::CleanupTask(base::WaitableEvent* sync) { sync->Signal(); } @@ -125,7 +125,7 @@ if (!thread_) return; - WaitableEvent sync; + base::WaitableEvent sync; // TODO(alexclarke): Should this be posted as a loading task? PostCrossThreadTask(*thread_->GetTaskRunner(), FROM_HERE, CrossThreadBind(&HRTFDatabaseLoader::CleanupTask,
diff --git a/third_party/blink/renderer/platform/audio/hrtf_database_loader.h b/third_party/blink/renderer/platform/audio/hrtf_database_loader.h index d1ac9dc..f7908dda 100644 --- a/third_party/blink/renderer/platform/audio/hrtf_database_loader.h +++ b/third_party/blink/renderer/platform/audio/hrtf_database_loader.h
@@ -30,6 +30,7 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_HRTF_DATABASE_LOADER_H_ #include <memory> +#include "base/synchronization/waitable_event.h" #include "third_party/blink/renderer/platform/audio/hrtf_database.h" #include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/wtf/hash_map.h" @@ -81,7 +82,7 @@ // Called in asynchronous loading thread. void LoadTask(); - void CleanupTask(WaitableEvent*); + void CleanupTask(base::WaitableEvent*); // Holding a m_lock is required when accessing m_hrtfDatabase since we access // it from multiple threads.
diff --git a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc index 02253633..06930f5 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc
@@ -760,7 +760,7 @@ HarfBuzzShaper shaper(string); scoped_refptr<ShapeResult> result = shaper.Shape(&font, data.direction); - auto& run = TestInfo(result)->RunInfoForTesting(data.run_index); + const auto& run = TestInfo(result)->RunInfoForTesting(data.run_index); auto glyphs = run.FindGlyphDataRange(data.start_offset, data.end_offset); unsigned start_glyph = std::distance(run.glyph_data_.begin(), glyphs.begin); EXPECT_EQ(data.start_glyph, start_glyph);
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result.h b/third_party/blink/renderer/platform/fonts/shaping/shape_result.h index 90861cb..20f5f6ed 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result.h +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result.h
@@ -438,6 +438,10 @@ float LineLeftBounds() const; float LineRightBounds() const; + // Common signatures with ShapeResultView, to templatize algorithms. + const Vector<scoped_refptr<RunInfo>>& RunsOrParts() const { return runs_; } + unsigned StartIndexOffsetForRun() const { return 0; } + float width_; FloatRect glyph_bounding_box_; Vector<scoped_refptr<RunInfo>> runs_;
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h b/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h index 30ab296..4be97d3 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h
@@ -169,41 +169,20 @@ // iterator pattern; i.e., |begin| is lower or equal to |end| in the address // space regardless of LTR/RTL. |begin| is inclusive, |end| is exclusive. struct GlyphDataRange { - HarfBuzzRunGlyphData* begin; - HarfBuzzRunGlyphData* end; + GlyphDataRange FindGlyphDataRange(bool is_rtl, + unsigned start_character_index, + unsigned end_character_index) const; + + const HarfBuzzRunGlyphData* begin; + const HarfBuzzRunGlyphData* end; }; // Find the range of HarfBuzzRunGlyphData for the specified character index // range. This function uses binary search twice, hence O(2 log n). GlyphDataRange FindGlyphDataRange(unsigned start_character_index, - unsigned end_character_index) { - const auto comparer = [](const HarfBuzzRunGlyphData& glyph_data, - unsigned index) { - return glyph_data.character_index < index; - }; - if (!Rtl()) { - HarfBuzzRunGlyphData* start_glyph = - std::lower_bound(glyph_data_.begin(), glyph_data_.end(), - start_character_index, comparer); - if (UNLIKELY(start_glyph == glyph_data_.end())) - return {nullptr, nullptr}; - HarfBuzzRunGlyphData* end_glyph = std::lower_bound( - start_glyph, glyph_data_.end(), end_character_index, comparer); - return {start_glyph, end_glyph}; - } - - // RTL needs to use reverse iterators because there maybe multiple glyphs - // for a character, and we want to find the first one in the logical order. - auto start_glyph = - std::lower_bound(glyph_data_.rbegin(), glyph_data_.rend(), - start_character_index, comparer); - if (UNLIKELY(start_glyph == glyph_data_.rend())) - return {nullptr, nullptr}; - auto end_glyph = std::lower_bound(start_glyph, glyph_data_.rend(), - end_character_index, comparer); - // Convert reverse iterators to pointers. Then increment to make |begin| - // inclusive and |end| exclusive. - return {&*end_glyph + 1, &*start_glyph + 1}; + unsigned end_character_index) const { + return GetGlyphDataRange().FindGlyphDataRange(Rtl(), start_character_index, + end_character_index); } // Creates a new RunInfo instance representing a subset of the current run. @@ -264,6 +243,13 @@ } } + // Common signatures with RunInfoPart, to templatize algorithms. + const RunInfo* GetRunInfo() const { return this; } + const GlyphDataRange GetGlyphDataRange() const { + return {glyph_data_.begin(), glyph_data_.end()}; + } + unsigned OffsetToRunStartIndex() const { return 0; } + scoped_refptr<SimpleFontData> font_data_; hb_direction_t direction_; // For upright-in-vertical we need to tell the ShapeResultBloberizer to rotate @@ -281,6 +267,42 @@ float width_; }; +// Find the range of HarfBuzzRunGlyphData for the specified character index +// range. This function uses binary search twice, hence O(2 log n). +inline ShapeResult::RunInfo::GlyphDataRange +ShapeResult::RunInfo::GlyphDataRange::FindGlyphDataRange( + bool is_rtl, + unsigned start_character_index, + unsigned end_character_index) const { + const auto comparer = [](const HarfBuzzRunGlyphData& glyph_data, + unsigned index) { + return glyph_data.character_index < index; + }; + if (!is_rtl) { + const HarfBuzzRunGlyphData* start_glyph = + std::lower_bound(begin, end, start_character_index, comparer); + if (UNLIKELY(start_glyph == end)) + return {nullptr, nullptr}; + const HarfBuzzRunGlyphData* end_glyph = + std::lower_bound(start_glyph, end, end_character_index, comparer); + return {start_glyph, end_glyph}; + } + + // RTL needs to use reverse iterators because there maybe multiple glyphs + // for a character, and we want to find the first one in the logical order. + const auto rbegin = std::reverse_iterator<const HarfBuzzRunGlyphData*>(end); + const auto rend = std::reverse_iterator<const HarfBuzzRunGlyphData*>(begin); + const auto start_glyph = + std::lower_bound(rbegin, rend, start_character_index, comparer); + if (UNLIKELY(start_glyph == rend)) + return {nullptr, nullptr}; + const auto end_glyph = + std::lower_bound(start_glyph, rend, end_character_index, comparer); + // Convert reverse iterators to pointers. Then increment to make |begin| + // inclusive and |end| exclusive. + return {&*end_glyph + 1, &*start_glyph + 1}; +} + } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_SHAPE_RESULT_INLINE_HEADERS_H_
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc b/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc index fad0549..88adc3a 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc
@@ -16,7 +16,7 @@ USING_FAST_MALLOC(RunInfoPart); public: - RunInfoPart(scoped_refptr<ShapeResult::RunInfo> run, + RunInfoPart(scoped_refptr<const ShapeResult::RunInfo> run, ShapeResult::RunInfo::GlyphDataRange range, unsigned start_index, unsigned offset, @@ -54,7 +54,20 @@ return run_->GlyphToCharacterIndex(i); } - scoped_refptr<ShapeResult::RunInfo> run_; + // Common signatures with RunInfo, to templatize algorithms. + const ShapeResult::RunInfo* GetRunInfo() const { return run_.get(); } + const ShapeResult::RunInfo::GlyphDataRange& GetGlyphDataRange() const { + return range_; + } + ShapeResult::RunInfo::GlyphDataRange FindGlyphDataRange( + unsigned start_character_index, + unsigned end_character_index) const { + return GetGlyphDataRange().FindGlyphDataRange(Rtl(), start_character_index, + end_character_index); + } + unsigned OffsetToRunStartIndex() const { return offset_; } + + scoped_refptr<const ShapeResult::RunInfo> run_; ShapeResult::RunInfo::GlyphDataRange range_; // Start index for partial run, adjusted to ensure that runs are continuous. @@ -87,7 +100,8 @@ return 0; } -ShapeResultView::ShapeResultView(const ShapeResult* other) +template <class ShapeResultType> +ShapeResultView::ShapeResultView(const ShapeResultType* other) : primary_font_(other->primary_font_), start_index_(0), num_characters_(0), @@ -128,28 +142,34 @@ return base::AdoptRef(new_result); } -void ShapeResultView::CreateViewsForResult(const ShapeResult* other, +template <class ShapeResultType> +void ShapeResultView::CreateViewsForResult(const ShapeResultType* other, unsigned start_index, unsigned end_index) { bool first_result = num_characters_ == 0; - for (const auto& run : other->runs_) { - if (!run) + for (const auto& run : other->RunsOrParts()) { + if (!run->GetRunInfo()) continue; - unsigned part_start = run->start_index_; + // Compute start/end of the run, or of the part if ShapeResultView. + unsigned part_start = run->start_index_ + other->StartIndexOffsetForRun(); unsigned run_end = part_start + run->num_characters_; if (start_index < run_end && end_index > part_start) { ShapeResult::RunInfo::GlyphDataRange range; + // Adjust start/end to the character index of |RunInfo|. The start index + // of |RunInfo| could be different from |part_start| for ShapeResultView. + DCHECK_GE(part_start, run->OffsetToRunStartIndex()); + unsigned run_start = part_start - run->OffsetToRunStartIndex(); unsigned adjusted_start = - start_index > part_start ? start_index - part_start : 0; - unsigned adjusted_end = std::min(end_index, run_end) - part_start; + start_index > run_start ? start_index - run_start : 0; + unsigned adjusted_end = std::min(end_index, run_end) - run_start; DCHECK(adjusted_end > adjusted_start); unsigned part_characters = adjusted_end - adjusted_start; float part_width; // Avoid O(log n) find operation if the entire run is in range. if (part_start >= start_index && run_end <= end_index) { - range = {run->glyph_data_.begin(), run->glyph_data_.end()}; + range = run->GetGlyphDataRange(); part_width = run->width_; } else { range = run->FindGlyphDataRange(adjusted_start, adjusted_end); @@ -170,8 +190,8 @@ } parts_.push_back(std::make_unique<RunInfoPart>( - run, range, part_start_index, part_offset, part_characters, - part_width)); + run->GetRunInfo(), range, part_start_index, part_offset, + part_characters, part_width)); num_characters_ += part_characters; num_glyphs_ += range.end - range.begin; @@ -185,7 +205,16 @@ scoped_refptr<ShapeResultView> ShapeResultView::Create(const Segment* segments, size_t segment_count) { - ShapeResultView* out = new ShapeResultView(segments[0].result); + DCHECK_GT(segment_count, 0u); +#if DCHECK_IS_ON() + for (unsigned i = 0; i < segment_count; ++i) { + DCHECK((segments[i].result || segments[i].view) && + (!segments[i].result || !segments[i].view)); + } +#endif + ShapeResultView* out = segments[0].result + ? new ShapeResultView(segments[0].result) + : new ShapeResultView(segments[0].view); out->AddSegments(segments, segment_count); return base::AdoptRef(out); } @@ -199,6 +228,14 @@ } scoped_refptr<ShapeResultView> ShapeResultView::Create( + const ShapeResultView* result, + unsigned start_index, + unsigned end_index) { + Segment segment = {result, start_index, end_index}; + return Create(&segment, 1); +} + +scoped_refptr<ShapeResultView> ShapeResultView::Create( const ShapeResult* result) { // This specialization is an optimization to allow the bounding box to be // re-used. @@ -223,18 +260,28 @@ // Compute start index offset for the overall run. This is added to the start // index of each glyph to ensure consistency with ShapeResult::SubRange if (!Rtl()) { // Left-to-right - char_index_offset_ = - std::max(segments[0].result->StartIndex(), segments[0].start_index); + char_index_offset_ = segments[0].result ? segments[0].result->StartIndex() + : segments[0].view->StartIndex(); + char_index_offset_ = std::max(char_index_offset_, segments[0].start_index); } else { // Right to left char_index_offset_ = 0; } for (unsigned i = 0; i < segment_count; i++) { const Segment& segment = segments[Rtl() ? last_segment_index - i : i]; - DCHECK_EQ(segment.result->Direction(), Direction()); - CreateViewsForResult(segment.result, segment.start_index, - segment.end_index); - has_vertical_offsets_ |= segment.result->has_vertical_offsets_; + if (segment.result) { + DCHECK_EQ(segment.result->Direction(), Direction()); + CreateViewsForResult(segment.result, segment.start_index, + segment.end_index); + has_vertical_offsets_ |= segment.result->has_vertical_offsets_; + } else if (segment.view) { + DCHECK_EQ(segment.view->Direction(), Direction()); + CreateViewsForResult(segment.view, segment.start_index, + segment.end_index); + has_vertical_offsets_ |= segment.view->has_vertical_offsets_; + } else { + NOTREACHED(); + } } float origin = 0;
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h b/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h index e6cbd2b..2fea4fe 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h
@@ -71,7 +71,21 @@ // Create a new ShapeResultView from a pre-defined list of segments. // The segments list is assumed to be in logical order. struct Segment { + Segment() = default; + Segment(const ShapeResult* result, unsigned start_index, unsigned end_index) + : result(result), + view(nullptr), + start_index(start_index), + end_index(end_index) {} + Segment(const ShapeResultView* view, + unsigned start_index, + unsigned end_index) + : result(nullptr), + view(view), + start_index(start_index), + end_index(end_index) {} const ShapeResult* result; + const ShapeResultView* view; unsigned start_index; unsigned end_index; }; @@ -82,6 +96,9 @@ static scoped_refptr<ShapeResultView> Create(const ShapeResult*, unsigned start_index, unsigned end_index); + static scoped_refptr<ShapeResultView> Create(const ShapeResultView*, + unsigned start_index, + unsigned end_index); ~ShapeResultView(); @@ -125,17 +142,25 @@ void GetRunFontData(Vector<ShapeResult::RunFontData>*) const; private: - ShapeResultView(const ShapeResult*); + template <class ShapeResultType> + ShapeResultView(const ShapeResultType*); unsigned ComputeStartIndex() const; struct RunInfoPart; - void CreateViewsForResult(const ShapeResult*, + template <class ShapeResultType> + void CreateViewsForResult(const ShapeResultType*, unsigned start_index, unsigned end_index); void AddSegments(const Segment*, size_t); template <bool is_horizontal_run> void ComputeBoundsForPart(const RunInfoPart&, float origin); + // Common signatures with ShapeResult, to templatize algorithms. + const Vector<std::unique_ptr<RunInfoPart>, 4>& RunsOrParts() const { + return parts_; + } + unsigned StartIndexOffsetForRun() const { return char_index_offset_; } + scoped_refptr<const SimpleFontData> primary_font_; mutable unsigned start_index_; // Cached and updated by ComputeStartIndex.
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_view_test.cc b/third_party/blink/renderer/platform/fonts/shaping/shape_result_view_test.cc index 8a96202..bed2c25 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_view_test.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_view_test.cc
@@ -289,4 +289,23 @@ reference_glyphs.size())); } +TEST_F(ShapeResultViewTest, TrimEndOfView) { + String string = To16Bit("12345678901234567890", 20); + TextDirection direction = TextDirection::kLtr; + HarfBuzzShaper shaper(string); + scoped_refptr<const ShapeResult> result = shaper.Shape(&font, direction); + + // Create a view from 5 to 20. + scoped_refptr<const ShapeResultView> view1 = + ShapeResultView::Create(result.get(), 5, 20); + EXPECT_EQ(view1->NumCharacters(), 15u); + EXPECT_EQ(view1->NumGlyphs(), 15u); + + // Trim the last character from the view. + scoped_refptr<const ShapeResultView> view2 = + ShapeResultView::Create(view1.get(), 5, 19); + EXPECT_EQ(view2->NumCharacters(), 14u); + EXPECT_EQ(view2->NumGlyphs(), 14u); +} + } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.cc b/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.cc index 50f2bac..02b1d00 100644 --- a/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.cc +++ b/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.cc
@@ -6,6 +6,7 @@ #include "base/barrier_closure.h" #include "base/metrics/histogram_macros.h" +#include "base/synchronization/waitable_event.h" #include "base/timer/elapsed_timer.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/platform/cross_thread_functional.h" @@ -15,7 +16,6 @@ #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" #include "third_party/blink/renderer/platform/scheduler/public/thread.h" -#include "third_party/blink/renderer/platform/waitable_event.h" namespace blink { @@ -108,9 +108,9 @@ if (mutator_input_map_.IsEmpty()) return; - WaitableEvent event; + base::WaitableEvent event; WTF::CrossThreadClosure on_done = CrossThreadBind( - &WaitableEvent::Signal, WTF::CrossThreadUnretained(&event)); + &base::WaitableEvent::Signal, WTF::CrossThreadUnretained(&event)); RequestMutations(std::move(on_done)); event.Wait();
diff --git a/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl_test.cc b/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl_test.cc index 87b8dcd7..7426c6d 100644 --- a/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl_test.cc +++ b/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl_test.cc
@@ -17,7 +17,6 @@ #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" #include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/testing/testing_platform_support.h" -#include "third_party/blink/renderer/platform/waitable_event.h" #include <memory> @@ -88,7 +87,7 @@ MOCK_METHOD0(NotifyAnimationsReadyRef, void()); - void SignalWhenComplete(WaitableEvent* done_event) { + void SignalWhenComplete(base::WaitableEvent* done_event) { done_event_ = done_event; } @@ -96,7 +95,7 @@ void(cc::MutatorOutputState* output_state)); private: - WaitableEvent* done_event_; // not owned. + base::WaitableEvent* done_event_; // not owned. }; class AnimationWorkletMutatorDispatcherImplTest : public ::testing::Test { @@ -352,7 +351,7 @@ // notification from the client. void CallMutateAndWaitForClientCompletion( MutateAsyncCallback mutate_callback) { - WaitableEvent done_event; + base::WaitableEvent done_event; client_->SignalWhenComplete(&done_event); PostCrossThreadTask(*Thread::CompositorThread()->GetTaskRunner(), FROM_HERE, std::move(mutate_callback)); @@ -364,16 +363,16 @@ // such as when there are no inputs. void CallMutateAndWaitForCallbackCompletion( MutateAsyncCallback mutate_callback) { - WaitableEvent done_event; - PostCrossThreadTask( - *Thread::CompositorThread()->GetTaskRunner(), FROM_HERE, - CrossThreadBind( - [](MutateAsyncCallback mutate_callback, WaitableEvent* done_event) { - mutate_callback.Run(); - done_event->Signal(); - }, - WTF::Passed(std::move(mutate_callback)), - WTF::CrossThreadUnretained(&done_event))); + base::WaitableEvent done_event; + PostCrossThreadTask(*Thread::CompositorThread()->GetTaskRunner(), FROM_HERE, + CrossThreadBind( + [](MutateAsyncCallback mutate_callback, + base::WaitableEvent* done_event) { + mutate_callback.Run(); + done_event->Signal(); + }, + WTF::Passed(std::move(mutate_callback)), + WTF::CrossThreadUnretained(&done_event))); done_event.Wait(); } };
diff --git a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc index 0e5a797..8724a3f 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
@@ -58,7 +58,6 @@ #include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" -#include "third_party/blink/renderer/platform/waitable_event.h" #include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/gpu/gl/GrGLTypes.h" @@ -971,8 +970,8 @@ bridge->SetLoggerForTesting(std::move(mock_logger)); // Test entering hibernation - std::unique_ptr<WaitableEvent> hibernation_started_event = - std::make_unique<WaitableEvent>(); + std::unique_ptr<base::WaitableEvent> hibernation_started_event = + std::make_unique<base::WaitableEvent>(); EXPECT_CALL( *mock_logger_ptr, ReportHibernationEvent(Canvas2DLayerBridge::kHibernationScheduled));
diff --git a/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.cc b/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.cc index 4ef2065b..2d8c47f 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.cc +++ b/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.cc
@@ -13,7 +13,6 @@ #include "third_party/blink/renderer/platform/cross_thread_functional.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" #include "third_party/blink/renderer/platform/scheduler/public/thread.h" -#include "third_party/blink/renderer/platform/waitable_event.h" namespace blink { @@ -52,7 +51,7 @@ bool only_if_gpu_compositing, bool* gpu_compositing_disabled, std::unique_ptr<WebGraphicsContext3DProviderWrapper>* wrapper, - WaitableEvent* waitable_event) { + base::WaitableEvent* waitable_event) { DCHECK(IsMainThread()); Platform::ContextAttributes context_attributes; @@ -122,7 +121,7 @@ // This synchronous round-trip to the main thread is the reason why // SharedGpuContext encasulates the context provider: so we only have to do // this once per thread. - WaitableEvent waitable_event; + base::WaitableEvent waitable_event; scoped_refptr<base::SingleThreadTaskRunner> task_runner = Thread::MainThread()->GetTaskRunner(); PostCrossThreadTask(
diff --git a/third_party/blink/renderer/platform/loader/testing/replaying_web_data_consumer_handle.cc b/third_party/blink/renderer/platform/loader/testing/replaying_web_data_consumer_handle.cc index 5091b0b..77bbd09b 100644 --- a/third_party/blink/renderer/platform/loader/testing/replaying_web_data_consumer_handle.cc +++ b/third_party/blink/renderer/platform/loader/testing/replaying_web_data_consumer_handle.cc
@@ -115,7 +115,7 @@ client_(nullptr), result_(kShouldWait), is_handle_attached_(true), - detached_(std::make_unique<WaitableEvent>()) {} + detached_(std::make_unique<base::WaitableEvent>()) {} const ReplayingWebDataConsumerHandle::Command& ReplayingWebDataConsumerHandle::Context::Top() {
diff --git a/third_party/blink/renderer/platform/loader/testing/replaying_web_data_consumer_handle.h b/third_party/blink/renderer/platform/loader/testing/replaying_web_data_consumer_handle.h index 1a6f643..59a471c 100644 --- a/third_party/blink/renderer/platform/loader/testing/replaying_web_data_consumer_handle.h +++ b/third_party/blink/renderer/platform/loader/testing/replaying_web_data_consumer_handle.h
@@ -7,8 +7,8 @@ #include <memory> #include "base/memory/scoped_refptr.h" +#include "base/synchronization/waitable_event.h" #include "third_party/blink/public/platform/web_data_consumer_handle.h" -#include "third_party/blink/renderer/platform/waitable_event.h" #include "third_party/blink/renderer/platform/wtf/deque.h" #include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h" #include "third_party/blink/renderer/platform/wtf/threading_primitives.h" @@ -74,7 +74,7 @@ void DetachHandle(); Result BeginRead(const void** buffer, Flags, size_t* available); Result EndRead(size_t read_size); - WaitableEvent* Detached() { return detached_.get(); } + base::WaitableEvent* Detached() { return detached_.get(); } private: Context(); @@ -92,7 +92,7 @@ Result result_; bool is_handle_attached_; Mutex mutex_; - std::unique_ptr<WaitableEvent> detached_; + std::unique_ptr<base::WaitableEvent> detached_; }; Context* GetContext() { return context_.get(); }
diff --git a/third_party/blink/renderer/platform/scheduler/common/worker_pool_unittest.cc b/third_party/blink/renderer/platform/scheduler/common/worker_pool_unittest.cc index e3fe93f..4e3d9398 100644 --- a/third_party/blink/renderer/platform/scheduler/common/worker_pool_unittest.cc +++ b/third_party/blink/renderer/platform/scheduler/common/worker_pool_unittest.cc
@@ -9,13 +9,12 @@ #include "base/test/scoped_task_environment.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/platform/cross_thread_functional.h" -#include "third_party/blink/renderer/platform/waitable_event.h" namespace blink { namespace { -void PingPongTask(WaitableEvent* done_event) { +void PingPongTask(base::WaitableEvent* done_event) { done_event->Signal(); } @@ -23,7 +22,8 @@ TEST(BackgroundSchedulerTest, RunOnBackgroundThread) { base::test::ScopedTaskEnvironment scoped_task_environment; - std::unique_ptr<WaitableEvent> done_event = std::make_unique<WaitableEvent>(); + std::unique_ptr<base::WaitableEvent> done_event = + std::make_unique<base::WaitableEvent>(); worker_pool::PostTask( FROM_HERE, CrossThreadBind(&PingPongTask, CrossThreadUnretained(done_event.get())));
diff --git a/third_party/blink/renderer/platform/scheduler/test/fuzzer/simple_thread_impl.h b/third_party/blink/renderer/platform/scheduler/test/fuzzer/simple_thread_impl.h index d19ec4c..0ef9d7e 100644 --- a/third_party/blink/renderer/platform/scheduler/test/fuzzer/simple_thread_impl.h +++ b/third_party/blink/renderer/platform/scheduler/test/fuzzer/simple_thread_impl.h
@@ -46,7 +46,7 @@ // Used by the Run function to only terminate when |this| is destructed, and // this is used so that |thread_data_| will live as long as |this|. - WaitableEvent thread_can_shutdown_; + base::WaitableEvent thread_can_shutdown_; ThreadCallback callback_; };
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_thread.h b/third_party/blink/renderer/platform/scheduler/worker/worker_thread.h index 811bef1..ae2150e 100644 --- a/third_party/blink/renderer/platform/scheduler/worker/worker_thread.h +++ b/third_party/blink/renderer/platform/scheduler/worker/worker_thread.h
@@ -9,6 +9,7 @@ #include "base/message_loop/message_loop_current.h" #include "base/single_thread_task_runner.h" #include "base/synchronization/atomic_flag.h" +#include "base/synchronization/waitable_event.h" #include "base/threading/thread.h" #include "third_party/blink/public/platform/web_private_ptr.h" #include "third_party/blink/renderer/platform/scheduler/public/thread.h"
diff --git a/third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.cc b/third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.cc index 8b5ae307..9fc93066 100644 --- a/third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.cc +++ b/third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.cc
@@ -8,7 +8,6 @@ #include "base/task/sequence_manager/test/sequence_manager_for_test.h" #include "base/test/test_mock_time_task_runner.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h" -#include "third_party/blink/renderer/platform/waitable_event.h" #include "third_party/blink/renderer/platform/wtf/time.h" namespace blink {
diff --git a/third_party/blink/renderer/platform/wtf/Allocator.md b/third_party/blink/renderer/platform/wtf/Allocator.md index 4523800..b8c7ab1 100644 --- a/third_party/blink/renderer/platform/wtf/Allocator.md +++ b/third_party/blink/renderer/platform/wtf/Allocator.md
@@ -19,7 +19,7 @@ * HeapVector<T>, HeapHashSet<T>, HeapHashMap<T, U> etc The implementation is in platform/heap/. -See [BlinkGCDesign.md](../platform/heap/BlinkGCDesign.md) to learn the design. +See [BlinkGCDesign.md](../heap/BlinkGCDesign.md) to learn the design. ### PartitionAlloc @@ -74,7 +74,7 @@ * Use Oilpan if you want a GC to manage the lifetime of the object. You need to make the object inherit from GarbageCollected<T> or GarbageCollectedFinalized<T>. See -[BlinkGCAPIReference.md](../platform/heap/BlinkGCAPIReference.md) to learn +[BlinkGCAPIReference.md](../heap/BlinkGCAPIReference.md) to learn programming with Oilpan. ```c++ @@ -88,8 +88,9 @@ ``` * Use PartitionAlloc if you don't need a GC to manage the lifetime of -the object (i.e., if RefPtr or OwnPtr is enough to manage the lifetime -of the object). You need to add a USING_FAST_MALLOC macro to the object. +the object (i.e., if scoped_refptr or unique_ptr is enough to manage the +lifetime of the object). You need to add a USING_FAST_MALLOC macro to the +object. ```c++ class X { @@ -159,7 +160,7 @@ } ``` -Note that these macros are inherited. See a comment in wtf/Allocator.h +Note that these macros are inherited. See a comment in wtf/allocator.h for more details about the relationship between the macros and Oilpan. If you have any question, ask oilpan-reviews@chromium.org.
diff --git a/third_party/blink/renderer/platform/wtf/README.md b/third_party/blink/renderer/platform/wtf/README.md index 6ea347a..4d9e25a 100644 --- a/third_party/blink/renderer/platform/wtf/README.md +++ b/third_party/blink/renderer/platform/wtf/README.md
@@ -47,29 +47,29 @@ * **Reference counting** - [RefCounted], [RefPtr] + [RefCounted] * **Memory** - [Allocator.h] (memory placement macros) + [allocator.h] (memory placement macros) * **Functors, binding** - [Functional.h] + [functional.h] * **Threading** - [Threading.h], [ThreadingPrimitives.h] + [threading.h], [threading_primitives.h] * **Compile-time switch macros** - [Compiler.h] (e.g. `COMPILER(GCC)`), - [CPU.h] (e.g. `WTF_CPU_ARM_NEON`), + [compiler.h] (e.g. `OBJC_CLASS`), + [cpu.h] (e.g. `WTF_CPU_ARM_NEON`), * **Miscellaneous** - [StdLibExtras.h] (`DEFINE_STATIC_LOCAL` etc.), - [Time.h] + [std_lib_extras.h] (`DEFINE_STATIC_LOCAL` etc.), + [time.h] ## History @@ -87,7 +87,7 @@ but it moved to Source/WTF/wtf in 2011-2012, then to Source/wtf in 2013. Blink forked WebKit in 2013. In 2017, the directory finally [moved to the -current location][4] Source/platform/wtf. +current location][4] platform/wtf. [the directory listing]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/ [base]: https://cs.chromium.org/chromium/src/base/ @@ -100,15 +100,15 @@ [StringBuilder]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/text/string_builder.h [CString]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/text/cstring.h [RefCounted]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/ref_counted.h -[Allocator.h]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/allocator.h -[Functional.h]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/functional.h -[Threading.h]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/threading.h -[ThreadingPrimitives.h]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/threading_primitives.h -[Compiler.h]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/compiler.h -[CPU.h]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/cpu.h +[allocator.h]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/allocator.h +[functional.h]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/functional.h +[threading.h]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/threading.h +[threading_primitives.h]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/threading_primitives.h +[compiler.h]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/compiler.h +[cpu.h]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/cpu.h [build_config.h]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/build_config.h -[StdLibExtras.h]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/std_lib_extras.h -[Time.h]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/time.h +[std_lib_extras.h]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/std_lib_extras.h +[time.h]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/time.h [1]: https://chromium.googlesource.com/chromium/src/+/e372c152fc6e57743ebc508fe17f6eb131b4ff8d [2]: https://chromium.googlesource.com/chromium/src/+/547a6ca360a56fbee3d5ea4a71ba18f91622455c [3]: https://chromium.googlesource.com/chromium/src/+/478890427ee03fd88e6f0f58ee8220512044bed9/third_party/WebKit/WebCore/kwq/KWQAssertions.h
diff --git a/third_party/blink/renderer/platform/wtf/ScopedLogger.md b/third_party/blink/renderer/platform/wtf/ScopedLogger.md index 3593e16..868ea26 100644 --- a/third_party/blink/renderer/platform/wtf/ScopedLogger.md +++ b/third_party/blink/renderer/platform/wtf/ScopedLogger.md
@@ -82,12 +82,11 @@ ## Requirements The ScopedLogger class and associated macros are defined in -[Assertions.h](Assertions.h), which most Blink source files already include -indirectly. ScopedLogger can't be used outside of Blink code yet. +[scoped_logger.h](scoped_logger.h). ScopedLogger can't be used outside of +Blink code yet. The ScopedLogger macros work in debug builds by default. They are compiled out -of release builds, unless your `GYP_DEFINES` or GN args file includes one of the -following: +of release builds, unless your GN args file includes one of the following: * `dcheck_always_on`: enables assertions and ScopedLogger
diff --git a/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer.cc b/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer.cc index 3a92200..7e58be3 100644 --- a/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer.cc +++ b/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer.cc
@@ -82,6 +82,19 @@ return true; } +bool ArrayBuffer::ShareNonSharedForInternalUse(ArrayBufferContents& result) { + DCHECK(!IsShared()); + scoped_refptr<ArrayBuffer> keep_alive(this); + + if (!contents_.Data()) { + result.Neuter(); + return false; + } + + contents_.ShareNonSharedForInternalUse(result); + return true; +} + void ArrayBuffer::AddView(ArrayBufferView* view) { view->buffer_ = this; view->prev_view_ = nullptr;
diff --git a/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer.h b/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer.h index fc67bba6..bd02fd17 100644 --- a/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer.h +++ b/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer.h
@@ -81,6 +81,8 @@ bool Transfer(ArrayBufferContents&); bool ShareContentsWith(ArrayBufferContents&); + // Documentation see DOMArrayBuffer. + bool ShareNonSharedForInternalUse(ArrayBufferContents&); bool IsNeutered() const { return is_neutered_; } bool IsShared() const { return contents_.IsShared(); }
diff --git a/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.cc b/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.cc index 5a8dbf1..00312421 100644 --- a/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.cc +++ b/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.cc
@@ -100,6 +100,14 @@ other.holder_ = holder_; } +void ArrayBufferContents::ShareNonSharedForInternalUse( + ArrayBufferContents& other) { + DCHECK(!IsShared()); + DCHECK(!other.holder_->Data()); + DCHECK(holder_->Data()); + other.holder_ = holder_; +} + void ArrayBufferContents::CopyTo(ArrayBufferContents& other) { DCHECK(!holder_->IsShared() && !other.holder_->IsShared()); other.holder_->CopyMemoryFrom(*holder_);
diff --git a/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.h b/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.h index 3cc1abe8..98bda66 100644 --- a/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.h +++ b/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.h
@@ -131,6 +131,7 @@ void Transfer(ArrayBufferContents& other); void ShareWith(ArrayBufferContents& other); + void ShareNonSharedForInternalUse(ArrayBufferContents& other); void CopyTo(ArrayBufferContents& other); static void* AllocateMemoryOrNull(size_t, InitializationPolicy);
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json index c8223f7..2a9c47c 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
@@ -57205,6 +57205,30 @@ {} ] ], + "css/css-pseudo/first-letter-background-image-dynamic.html": [ + [ + "/css/css-pseudo/first-letter-background-image-dynamic.html", + [ + [ + "/css/css-pseudo/first-letter-background-image-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-pseudo/first-letter-background-image.html": [ + [ + "/css/css-pseudo/first-letter-background-image.html", + [ + [ + "/css/css-pseudo/first-letter-background-image-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-pseudo/first-letter-block-to-inline.html": [ [ "/css/css-pseudo/first-letter-block-to-inline.html", @@ -60025,6 +60049,42 @@ {} ] ], + "css/css-tables/subpixel-collapsed-borders-001.html": [ + [ + "/css/css-tables/subpixel-collapsed-borders-001.html", + [ + [ + "/css/css-tables/subpixel-collapsed-borders-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-tables/subpixel-collapsed-borders-002.html": [ + [ + "/css/css-tables/subpixel-collapsed-borders-002.html", + [ + [ + "/css/css-tables/subpixel-collapsed-borders-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-tables/subpixel-collapsed-borders-003.html": [ + [ + "/css/css-tables/subpixel-collapsed-borders-003.html", + [ + [ + "/css/css-tables/subpixel-collapsed-borders-003-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-tables/subpixel-table-cell-height-001.html": [ [ "/css/css-tables/subpixel-table-cell-height-001.html", @@ -106225,6 +106285,18 @@ {} ] ], + "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue.html": [ + [ + "/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue.html", + [ + [ + "/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue-ref.html", + "==" + ] + ], + {} + ] + ], "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-line-doesnt-fit.html": [ [ "/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-line-doesnt-fit.html", @@ -107441,6 +107513,78 @@ {} ] ], + "mathml/presentation-markup/fractions/frac-color-001.html": [ + [ + "/mathml/presentation-markup/fractions/frac-color-001.html", + [ + [ + "/mathml/presentation-markup/fractions/frac-color-001-notref.html", + "!=" + ] + ], + {} + ] + ], + "mathml/presentation-markup/fractions/frac-linethickness-001.html": [ + [ + "/mathml/presentation-markup/fractions/frac-linethickness-001.html", + [ + [ + "/mathml/presentation-markup/fractions/frac-linethickness-001-ref.html", + "==" + ] + ], + {} + ] + ], + "mathml/presentation-markup/fractions/frac-linethickness-002.html": [ + [ + "/mathml/presentation-markup/fractions/frac-linethickness-002.html", + [ + [ + "/mathml/presentation-markup/fractions/frac-linethickness-002-ref.html", + "==" + ] + ], + {} + ] + ], + "mathml/presentation-markup/fractions/frac-linethickness-003.html": [ + [ + "/mathml/presentation-markup/fractions/frac-linethickness-003.html", + [ + [ + "/mathml/presentation-markup/fractions/frac-linethickness-003-notref.html", + "!=" + ] + ], + {} + ] + ], + "mathml/presentation-markup/fractions/frac-mrow-001.html": [ + [ + "/mathml/presentation-markup/fractions/frac-mrow-001.html", + [ + [ + "/mathml/presentation-markup/fractions/frac-mrow-001-ref.html", + "==" + ] + ], + {} + ] + ], + "mathml/presentation-markup/fractions/frac-numalign-denomalign-001.html": [ + [ + "/mathml/presentation-markup/fractions/frac-numalign-denomalign-001.html", + [ + [ + "/mathml/presentation-markup/fractions/frac-numalign-denomalign-001-ref.html", + "==" + ] + ], + {} + ] + ], "mathml/presentation-markup/spaces/space-2.html": [ [ "/mathml/presentation-markup/spaces/space-2.html", @@ -141468,6 +141612,11 @@ {} ] ], + "css/css-pseudo/first-letter-background-image-ref.html": [ + [ + {} + ] + ], "css/css-pseudo/first-letter-block-to-inline-ref.html": [ [ {} @@ -142818,6 +142967,16 @@ {} ] ], + "css/css-tables/subpixel-collapsed-borders-003-ref.html": [ + [ + {} + ] + ], + "css/css-tables/subpixel-collapsed-borders-ref.html": [ + [ + {} + ] + ], "css/css-tables/subpixel-table-cell-height-001-ref.html": [ [ {} @@ -170648,6 +170807,11 @@ {} ] ], + "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue-ref.html": [ + [ + {} + ] + ], "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-line-doesnt-fit-ref.html": [ [ {} @@ -175748,6 +175912,36 @@ {} ] ], + "mathml/presentation-markup/fractions/frac-color-001-notref.html": [ + [ + {} + ] + ], + "mathml/presentation-markup/fractions/frac-linethickness-001-ref.html": [ + [ + {} + ] + ], + "mathml/presentation-markup/fractions/frac-linethickness-002-ref.html": [ + [ + {} + ] + ], + "mathml/presentation-markup/fractions/frac-linethickness-003-notref.html": [ + [ + {} + ] + ], + "mathml/presentation-markup/fractions/frac-mrow-001-ref.html": [ + [ + {} + ] + ], + "mathml/presentation-markup/fractions/frac-numalign-denomalign-001-ref.html": [ + [ + {} + ] + ], "mathml/presentation-markup/spaces/space-2-ref.html": [ [ {} @@ -214188,6 +214382,12 @@ {} ] ], + "css/css-scroll-anchoring/device-pixel-adjustment.html": [ + [ + "/css/css-scroll-anchoring/device-pixel-adjustment.html", + {} + ] + ], "css/css-scroll-anchoring/exclude-fixed-position.html": [ [ "/css/css-scroll-anchoring/exclude-fixed-position.html", @@ -242456,12 +242656,6 @@ {} ] ], - "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue.html": [ - [ - "/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue.html", - {} - ] - ], "html/semantics/embedded-content/media-elements/track/track-element/track-cues-cuechange.html": [ [ "/html/semantics/embedded-content/media-elements/track/track-element/track-cues-cuechange.html", @@ -356549,6 +356743,18 @@ "a10612ac9731a7ecdf07416df23e802c131b7570", "reftest" ], + "css/css-pseudo/first-letter-background-image-dynamic.html": [ + "6f8a9378c5c2f041ae8be4bc0a4e22be8869a107", + "reftest" + ], + "css/css-pseudo/first-letter-background-image-ref.html": [ + "c235ba6eef6328f1b726acfe0076020bcd0b6f33", + "support" + ], + "css/css-pseudo/first-letter-background-image.html": [ + "aa9341df1bd7d97afd12f3896a645f008bdc8c50", + "reftest" + ], "css/css-pseudo/first-letter-block-to-inline-ref.html": [ "5c777f1a92e373042ffbfeb5604cc665013663f7", "support" @@ -357077,6 +357283,10 @@ "654f34a051dc39ea3506a73a1e96602d0c664c61", "testharness" ], + "css/css-scroll-anchoring/device-pixel-adjustment.html": [ + "4a135939fde657ab6819b167cfa72972373771b1", + "testharness" + ], "css/css-scroll-anchoring/exclude-fixed-position.html": [ "d48d3f7cedf19ce502a5087d945675b62e62fdf9", "testharness" @@ -357238,11 +357448,11 @@ "testharness" ], "css/css-scroll-snap/parsing/scroll-snap-align-invalid.html": [ - "c31aa3c17513b3bed1888c1d9becd5874ca470b6", + "9a1eeb77bbe481ec2ca842c86af45f6aa471e636", "testharness" ], "css/css-scroll-snap/parsing/scroll-snap-align-valid.html": [ - "163f786b7d45932dbede2fd2bc0a3b75e72a2f83", + "0201448825e67c055f78b8be8bd08531d9068e1d", "testharness" ], "css/css-scroll-snap/parsing/scroll-snap-stop-invalid.html": [ @@ -359709,6 +359919,26 @@ "a24556aa0dedfab35ff7792f03b804f44c0f4160", "reftest" ], + "css/css-tables/subpixel-collapsed-borders-001.html": [ + "a71f5cc698b74a518411e57974577b4f4c4dccda", + "reftest" + ], + "css/css-tables/subpixel-collapsed-borders-002.html": [ + "8f8292cd22becd3ddba61f5205828596a8995e44", + "reftest" + ], + "css/css-tables/subpixel-collapsed-borders-003-ref.html": [ + "78e0be389393e235781549cd90ea961385ec5c68", + "support" + ], + "css/css-tables/subpixel-collapsed-borders-003.html": [ + "358562cbd7ff49f43c234db502513faabc8390d1", + "reftest" + ], + "css/css-tables/subpixel-collapsed-borders-ref.html": [ + "0a2e7a8d95b95dc21ad1c103fdfba65b8f5b1b86", + "support" + ], "css/css-tables/subpixel-table-cell-height-001-ref.html": [ "3b6297fc4ab06643b2910194479b571ca3a462f2", "support" @@ -394626,7 +394856,7 @@ "support" ], "domparsing/DOMParser-parseFromString-html.html": [ - "ec424423a1d28988d2b949b51e9467f0cf702290", + "ad65cc58618462591568dda622f35b68a64c1d63", "testharness" ], "domparsing/DOMParser-parseFromString-xml-doctype.html": [ @@ -412845,12 +413075,16 @@ "76019c9b41e4fd4c56f4252d399f088b7b3e4470", "reftest" ], + "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue-ref.html": [ + "837c4fd7833d569f2949bf1c2a677836ac851597", + "support" + ], "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue.html": [ - "427189f6fc78074ae13c58e94ae3d02bc0e513b2", - "testharness" + "c2d300999eeaa207365b5c0b42f9b033e6b96446", + "reftest" ], "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-line-doesnt-fit-ref.html": [ - "8354041eb2a0aa57b283e12d9c0390f16327ac80", + "c4c14bc2a394ff19c14bfa76c4b59ad5d6ddb618", "support" ], "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-line-doesnt-fit.html": [ @@ -412858,7 +413092,7 @@ "reftest" ], "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-transformed-video-ref.html": [ - "39461350b089b9041a71a6ca9aad7f1cfc078d68", + "c3ee804c485b762d8b69614136558bbf2ed833a8", "support" ], "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-transformed-video.html": [ @@ -422078,11 +422312,11 @@ "manual" ], "input-events/input-events-exec-command-expected.txt": [ - "89da9dc6ef95591372c59492930e8d26bff84672", + "1e219ecd5bead581a7eca478bcefcdd72dc8c9be", "support" ], "input-events/input-events-exec-command.html": [ - "9ba423f4bade15ee47a099b611306b0e941af459", + "8f8493651e5af4b747d952ac786334ace8ed61c4", "testharness" ], "input-events/input-events-get-target-ranges-manual.html": [ @@ -423269,6 +423503,54 @@ "848eb5b144cef3740b794475f699229243c1287e", "testharness" ], + "mathml/presentation-markup/fractions/frac-color-001-notref.html": [ + "498d6277a3258c70882e7b2ec92e82e974bf9ab0", + "support" + ], + "mathml/presentation-markup/fractions/frac-color-001.html": [ + "bc61dbf51ffe487122859f189223b2ef43f88bb1", + "reftest" + ], + "mathml/presentation-markup/fractions/frac-linethickness-001-ref.html": [ + "c703edb764fe883e05e47e26464149aa64af1070", + "support" + ], + "mathml/presentation-markup/fractions/frac-linethickness-001.html": [ + "94111174c6aa3ecf1fff4982bfc9ecbf4a10c2ee", + "reftest" + ], + "mathml/presentation-markup/fractions/frac-linethickness-002-ref.html": [ + "69663938c1951a34a1e1134d549b610ea00c15e8", + "support" + ], + "mathml/presentation-markup/fractions/frac-linethickness-002.html": [ + "5bb0d6bfb9d6113a04b9d3160ccc9db80aceaaa6", + "reftest" + ], + "mathml/presentation-markup/fractions/frac-linethickness-003-notref.html": [ + "934d66633397313175e98c4bda871bb0a95e5db0", + "support" + ], + "mathml/presentation-markup/fractions/frac-linethickness-003.html": [ + "e535e703b52c75800155b5b25995730b2a236287", + "reftest" + ], + "mathml/presentation-markup/fractions/frac-mrow-001-ref.html": [ + "e42cb96fe8383959bef2d778cfb29d0638f1de03", + "support" + ], + "mathml/presentation-markup/fractions/frac-mrow-001.html": [ + "e5c6f52529443e881b8235a67f3e8cc7aa10fb51", + "reftest" + ], + "mathml/presentation-markup/fractions/frac-numalign-denomalign-001-ref.html": [ + "2fa978624dc206c834f70d4cf620b565f8f3ac12", + "support" + ], + "mathml/presentation-markup/fractions/frac-numalign-denomalign-001.html": [ + "61f49e2ff5381c9684e5b36d03a51daf7f8f3e74", + "reftest" + ], "mathml/presentation-markup/fractions/frac-parameters-1.html": [ "543017e19006377cac0c1a434bd43400467fac3b", "testharness"
diff --git a/third_party/blink/web_tests/external/wpt/css/css-pseudo/first-letter-background-image-dynamic.html b/third_party/blink/web_tests/external/wpt/css/css-pseudo/first-letter-background-image-dynamic.html new file mode 100644 index 0000000..6f8a937 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-pseudo/first-letter-background-image-dynamic.html
@@ -0,0 +1,24 @@ +<!doctype html> +<title>CSS Test: ::first-letter correctly applies background-image dynamically</title> +<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez"> +<link rel="author" href="https://mozilla.org" title="Mozilla"> +<link rel="help" href="https://drafts.csswg.org/css-pseudo-4/#first-letter-styling"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1528451"> +<link rel="match" href="first-letter-background-image-ref.html"> +<style> + div::first-letter { + color: lime; + } + div.image::first-letter { + /* Lime background */ + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M/wHwAEBgIApD5fRAAAAABJRU5ErkJggg=='); + } +</style> +<div> + A letter +</div> +<script> + let div = document.querySelector("div"); + getComputedStyle(div).color; + div.classList.add('image'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-pseudo/first-letter-background-image-ref.html b/third_party/blink/web_tests/external/wpt/css/css-pseudo/first-letter-background-image-ref.html new file mode 100644 index 0000000..c235ba6e --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-pseudo/first-letter-background-image-ref.html
@@ -0,0 +1,13 @@ +<!doctype html> +<title>CSS Test Reference</title> +<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez"> +<link rel="author" href="https://mozilla.org" title="Mozilla"> +<style> + div::first-letter { + color: lime; + background-color: lime; + } +</style> +<div> + A letter +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-pseudo/first-letter-background-image.html b/third_party/blink/web_tests/external/wpt/css/css-pseudo/first-letter-background-image.html new file mode 100644 index 0000000..aa9341df --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-pseudo/first-letter-background-image.html
@@ -0,0 +1,17 @@ +<!doctype html> +<title>CSS Test: ::first-letter correctly applies background-image</title> +<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez"> +<link rel="author" href="https://mozilla.org" title="Mozilla"> +<link rel="help" href="https://drafts.csswg.org/css-pseudo-4/#first-letter-styling"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1528451"> +<link rel="match" href="first-letter-background-image-ref.html"> +<style> + div::first-letter { + color: lime; + /* Lime background */ + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M/wHwAEBgIApD5fRAAAAABJRU5ErkJggg=='); + } +</style> +<div> + A letter +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scroll-anchoring/device-pixel-adjustment.html b/third_party/blink/web_tests/external/wpt/css/css-scroll-anchoring/device-pixel-adjustment.html new file mode 100644 index 0000000..4a13593 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-scroll-anchoring/device-pixel-adjustment.html
@@ -0,0 +1,77 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css-scroll-anchoring-1/"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> + +body { + height: 200vh; +} +#anchor { + width: 100px; + height: 100px; + background-color: blue; +} + +</style> +<div id="expander"></div> +<div id="anchor"></div> +<script> + +// This tests that scroll anchor adjustments can happen by quantities smaller +// than a device pixel. +// +// Unfortunately, we can't test this by simply reading 'scrollTop', because +// 'scrollTop' may be rounded to the nearest CSS pixel. So, to test that +// subpixel adjustments can in fact happen, we repeatedly trigger a scroll +// adjustment in a way that would produce a different final .scrollTop value, +// depending on whether or not we rounded each adjustment as we apply it. + +test(() => { + let scroller = document.scrollingElement; + let expander = document.querySelector("#expander"); + let anchor = document.querySelector("#anchor"); + const initialTop = 10; + + // Scroll 10px to activate scroll anchoring + scroller.scrollTop = initialTop; + + // Helper to insert a div with specified height before the anchor node + function addChild(height) { + let child = document.createElement("div"); + child.style.height = `${height}px`; + anchor.before(child); + } + + // Calculate what fraction of a CSS pixel corresponds to one device pixel + let devicePixel = 1.0 / window.devicePixelRatio; + assert_true(devicePixel <= 1.0, "there should be more device pixels than CSS pixels"); + + // The 0.5 is an arbitrary scale when creating the subpixel delta + let delta = 0.5 * devicePixel; + + // To help us check for for premature rounding of adjustments, we'll + // trigger "count" subpixel adjustments of size "delta", where "count" is + // the first positive integer such that: + // round(count * delta) != count * round(delta) + // As round(X) and count are integers, this happens when: + // count * delta = count * round(delta) +/- 1 + // Solving for count: + // count = 1 / abs(delta - round(delta)) + // Note that we don't need to worry about the denominator being zero, as: + // 0 < devicePixel <= 1 + // And so halving devicePixel should never yield a whole number. + let count = 1 / Math.abs(delta - Math.round(delta)); + + for (let i = 0; i < count; i++) { + addChild(delta); + // Trigger an anchor adjustment by forcing a layout flush + scroller.scrollTop; + } + + let destination = Math.round(initialTop + delta * count); + assert_equals(scroller.scrollTop, destination, + `adjusting by ${delta}px, ${count} times, should be the same as adjusting by ${delta * count}px, once.`); +}, "Test that scroll anchor adjustments can happen by a sub device-pixel amount."); + +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/parsing/scroll-snap-align-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/parsing/scroll-snap-align-invalid.html index c31aa3c1..9a1eeb77 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/parsing/scroll-snap-align-invalid.html +++ b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/parsing/scroll-snap-align-invalid.html
@@ -13,6 +13,8 @@ <script> test_invalid_value("scroll-snap-align", "auto"); +test_invalid_value("scroll-snap-align", "start invalid"); + test_invalid_value("scroll-snap-align", "start end center"); </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/parsing/scroll-snap-align-valid.html b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/parsing/scroll-snap-align-valid.html index 163f786..0201448 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/parsing/scroll-snap-align-valid.html +++ b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/parsing/scroll-snap-align-valid.html
@@ -18,6 +18,8 @@ test_valid_value("scroll-snap-align", "start none"); test_valid_value("scroll-snap-align", "center end"); +test_valid_value("scroll-snap-align", "start start", "start"); + </script> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable.html b/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable.html index e3083d2..80189fe 100644 --- a/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable.html +++ b/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable.html
@@ -14,7 +14,7 @@ <span class="yellow"></span> </div> </section> -<section id="secondSection"></section> +<section id="shadowHost"></section> <section id="thirdSection"></section> <script> @@ -27,7 +27,8 @@ const firstDiv = document.querySelector('#firstSection > div'); const secondDiv = firstDiv.cloneNode(true); -const shadowRoot = document.querySelector('#secondSection').attachShadow({mode: 'open'}); +const shadowHost = document.querySelector('#shadowHost'); +const shadowRoot = shadowHost.attachShadow({mode: 'open'}); shadowRoot.appendChild(secondDiv); const greenSpan = firstDiv.children[0]; @@ -210,6 +211,24 @@ }, 'Constructed style sheets can be applied on shadow root'); promise_test(() => { + return Promise.all(createAllSheetsPromise()).then(values => { + const greenStyleSheet = values[0]; + const redStyleSheet = values[1]; + shadowRoot.adoptedStyleSheets = [greenStyleSheet]; + assert_equals(getComputedStyle(greenShadowSpan).color, "rgb(0, 128, 0)", "Style applies connected"); + assert_equals(getComputedStyle(redShadowSpan).color, "rgb(0, 0, 0)", "Style applies when connected"); + let hostParent = shadowHost.parentNode; + hostParent.removeChild(shadowHost); + assert_equals(getComputedStyle(greenShadowSpan).color, "", "Style doesn't apply when detached"); + assert_equals(getComputedStyle(redShadowSpan).color, "", "Style doesn't apply when detached"); + shadowRoot.adoptedStyleSheets = [redStyleSheet, greenStyleSheet]; + hostParent.appendChild(shadowHost); + assert_equals(getComputedStyle(greenShadowSpan).color, "rgb(0, 128, 0)", "Style applies after reattach"); + assert_equals(getComputedStyle(redShadowSpan).color, "rgb(255, 0, 0)", "Style applies after reattach"); + }); +}, 'Re-attaching shadow host with adopted stylesheets work'); + +promise_test(() => { const plainSheet = new CSSStyleSheet(); const redStyleSheetPromise = plainSheet.replace(redStyleTexts[0]); return redStyleSheetPromise.then(function(redStyleSheet) {
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue-ref.html new file mode 100644 index 0000000..837c4fd --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue-ref.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<title>Reference for track rendering with empty cue</title> +<script src="/common/reftest-wait.js"></script> +<style> +html { overflow:hidden } +body { margin:0 } +.container { + display: inline-block; + position: relative; +} +</style> +<div class="container"> + <video width="320" height="180"> + <source src="/media/white.webm" type="video/webm"> + <source src="/media/white.mp4" type="video/mp4"> + <script> + var video = document.querySelector("video"); + video.addEventListener('playing', () => { + video.pause(); + takeScreenshot(); + }, { once: true}); + video.play(); + </script> + </video> +</div> +</html> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue.html index 427189f..c2d3009 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue.html
@@ -1,16 +1,26 @@ <!DOCTYPE html> -<title>Empty cues</title> -<script src="/common/media.js"></script> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script> -async_test(function(t) { - var video = document.createElement("video"); - video.src = getVideoURI("/media/test"); - video.addTextTrack("captions", "regular captions track", "en"); - video.textTracks[0].addCue(new VTTCue(0, 4, "")); +<html class="reftest-wait"> +<title>Track rendering with empty cue</title> +<link rel="match" href="track-cue-rendering-empty-cue-ref.html"> +<style> +html { overflow:hidden } +body { margin:0 } +</style> +<script src="/common/reftest-wait.js"></script> +<video width="320" height="180"> + <source src="/media/white.webm" type="video/webm"> + <source src="/media/white.mp4" type="video/mp4"> + <script> + var video = document.querySelector("video"); + var track = video.addTextTrack("captions", "regular captions track", "en"); + track.addCue(new VTTCue(0, 4, "")); + track.mode = "showing"; - video.onplaying = t.step_func_done(); + video.addEventListener('playing', () => { + video.pause(); + takeScreenshot(); + }, { once: true}); video.play(); -}); -</script> \ No newline at end of file + </script> +</video> +</html> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-line-doesnt-fit-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-line-doesnt-fit-ref.html index 8354041e..c4c14bc2 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-line-doesnt-fit-ref.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-line-doesnt-fit-ref.html
@@ -20,7 +20,6 @@ background: green; color: green; font-size: 120px; - padding: 2px; } </style> <div class="container">
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-transformed-video-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-transformed-video-ref.html index 39461350..c3ee804 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-transformed-video-ref.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-transformed-video-ref.html
@@ -22,7 +22,6 @@ background: green; color: green; font-size: 50px; - padding: 2px; } </style> <div class="container">
diff --git a/third_party/blink/web_tests/external/wpt/input-events/input-events-exec-command-expected.txt b/third_party/blink/web_tests/external/wpt/input-events/input-events-exec-command-expected.txt index 89da9dc..1e219ec 100644 --- a/third_party/blink/web_tests/external/wpt/input-events/input-events-exec-command-expected.txt +++ b/third_party/blink/web_tests/external/wpt/input-events/input-events-exec-command-expected.txt
@@ -1,49 +1,317 @@ This is a testharness.js-based test. -PASS Calling execCommand("insertText", false, a) -PASS Calling execCommand("insertText", false, bc) +Found 313 tests; 239 PASS, 74 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS Calling execCommand("insertText", false, a) (calling execCommand) +PASS Calling execCommand("insertText", false, a) (shouldn't fire beforeinput) +PASS Calling execCommand("insertText", false, a) (inputType value) +PASS Calling execCommand("insertText", false, a) (data value) +PASS Calling execCommand("insertText", false, a) (dataTransfer value) +PASS Calling execCommand("insertText", false, bc) (calling execCommand) +PASS Calling execCommand("insertText", false, bc) (shouldn't fire beforeinput) +PASS Calling execCommand("insertText", false, bc) (inputType value) +PASS Calling execCommand("insertText", false, bc) (data value) +PASS Calling execCommand("insertText", false, bc) (dataTransfer value) PASS execCommand("insertText") should insert "abc" into the editor -PASS Calling execCommand("insertOrderedList", false, null) +PASS Calling execCommand("insertOrderedList", false, null) (calling execCommand) +PASS Calling execCommand("insertOrderedList", false, null) (shouldn't fire beforeinput) +PASS Calling execCommand("insertOrderedList", false, null) (inputType value) +PASS Calling execCommand("insertOrderedList", false, null) (data value) +PASS Calling execCommand("insertOrderedList", false, null) (dataTransfer value) PASS execCommand("insertOrderedList") should make <ol> and wrap the text with it -PASS Calling execCommand("insertUnorderedList", false, null) +PASS Calling execCommand("insertUnorderedList", false, null) (calling execCommand) +PASS Calling execCommand("insertUnorderedList", false, null) (shouldn't fire beforeinput) +PASS Calling execCommand("insertUnorderedList", false, null) (inputType value) +PASS Calling execCommand("insertUnorderedList", false, null) (data value) +PASS Calling execCommand("insertUnorderedList", false, null) (dataTransfer value) PASS execCommand("insertUnorderedList") should make <ul> and wrap the text with it -PASS Calling execCommand("insertLineBreak", false, null) -PASS Calling execCommand("insertParagraph", false, null) -FAIL Calling execCommand("insertHorizontalRule", false, null) assert_equals: Calling execCommand("insertHorizontalRule", false, null) should produce inputType: insertHorizontalRule expected "insertHorizontalRule" but got "" -PASS Calling execCommand("bold", false, null) +PASS Calling execCommand("insertLineBreak", false, null) (calling execCommand) +PASS Calling execCommand("insertLineBreak", false, null) (shouldn't fire beforeinput) +PASS Calling execCommand("insertLineBreak", false, null) (inputType value) +PASS Calling execCommand("insertLineBreak", false, null) (data value) +PASS Calling execCommand("insertLineBreak", false, null) (dataTransfer value) +PASS Calling execCommand("insertParagraph", false, null) (calling execCommand) +PASS Calling execCommand("insertParagraph", false, null) (shouldn't fire beforeinput) +PASS Calling execCommand("insertParagraph", false, null) (inputType value) +PASS Calling execCommand("insertParagraph", false, null) (data value) +PASS Calling execCommand("insertParagraph", false, null) (dataTransfer value) +PASS Calling execCommand("insertHorizontalRule", false, null) (calling execCommand) +PASS Calling execCommand("insertHorizontalRule", false, null) (shouldn't fire beforeinput) +FAIL Calling execCommand("insertHorizontalRule", false, null) (inputType value) assert_equals: expected "insertHorizontalRule" but got "" +PASS Calling execCommand("insertHorizontalRule", false, null) (data value) +PASS Calling execCommand("insertHorizontalRule", false, null) (dataTransfer value) +PASS Calling execCommand("bold", false, null) (calling execCommand) +PASS Calling execCommand("bold", false, null) (shouldn't fire beforeinput) +PASS Calling execCommand("bold", false, null) (inputType value) +PASS Calling execCommand("bold", false, null) (data value) +PASS Calling execCommand("bold", false, null) (dataTransfer value) PASS execCommand("bold") should wrap selected text with <b> element -PASS Calling execCommand("italic", false, null) +PASS Calling execCommand("italic", false, null) (calling execCommand) +PASS Calling execCommand("italic", false, null) (shouldn't fire beforeinput) +PASS Calling execCommand("italic", false, null) (inputType value) +PASS Calling execCommand("italic", false, null) (data value) +PASS Calling execCommand("italic", false, null) (dataTransfer value) PASS execCommand("italic") should wrap selected text with <i> element -PASS Calling execCommand("underline", false, null) +PASS Calling execCommand("underline", false, null) (calling execCommand) +PASS Calling execCommand("underline", false, null) (shouldn't fire beforeinput) +PASS Calling execCommand("underline", false, null) (inputType value) +PASS Calling execCommand("underline", false, null) (data value) +PASS Calling execCommand("underline", false, null) (dataTransfer value) PASS execCommand("underline") should wrap selected text with <u> element -PASS Calling execCommand("strikeThrough", false, null) +PASS Calling execCommand("strikeThrough", false, null) (calling execCommand) +PASS Calling execCommand("strikeThrough", false, null) (shouldn't fire beforeinput) +PASS Calling execCommand("strikeThrough", false, null) (inputType value) +PASS Calling execCommand("strikeThrough", false, null) (data value) +PASS Calling execCommand("strikeThrough", false, null) (dataTransfer value) PASS execCommand("strikeThrough") should wrap selected text with <strike> element -PASS Calling execCommand("superscript", false, null) +PASS Calling execCommand("superscript", false, null) (calling execCommand) +PASS Calling execCommand("superscript", false, null) (shouldn't fire beforeinput) +PASS Calling execCommand("superscript", false, null) (inputType value) +PASS Calling execCommand("superscript", false, null) (data value) +PASS Calling execCommand("superscript", false, null) (dataTransfer value) PASS execCommand("superscript") should wrap selected text with <sup> element -PASS Calling execCommand("subscript", false, null) +PASS Calling execCommand("subscript", false, null) (calling execCommand) +PASS Calling execCommand("subscript", false, null) (shouldn't fire beforeinput) +PASS Calling execCommand("subscript", false, null) (inputType value) +PASS Calling execCommand("subscript", false, null) (data value) +PASS Calling execCommand("subscript", false, null) (dataTransfer value) PASS execCommand("subscript") should wrap selected text with <sub> element -FAIL Calling execCommand("backColor", false, #000000) assert_equals: Calling execCommand("backColor", false, #000000) should produce inputType: formatBackColor expected "formatBackColor" but got "" -FAIL Calling execCommand("foreColor", false, #FFFFFF) assert_equals: Calling execCommand("foreColor", false, #FFFFFF) should produce inputType: formatFontColor expected "formatFontColor" but got "" -FAIL Calling execCommand("hiliteColor", false, #FFFF00) assert_equals: Calling execCommand("hiliteColor", false, #FFFF00) should produce inputType: formatBackColor expected "formatBackColor" but got "" -FAIL Calling execCommand("fontName", false, monospace) assert_equals: Calling execCommand("fontName", false, monospace) should produce inputType: formatFontName expected "formatFontName" but got "" -PASS Calling execCommand("justifyCenter", false, null) +PASS Calling execCommand("backColor", false, #FF0000) (calling execCommand) +PASS Calling execCommand("backColor", false, #FF0000) (shouldn't fire beforeinput) +FAIL Calling execCommand("backColor", false, #FF0000) (inputType value) assert_equals: expected "formatBackColor" but got "" +FAIL Calling execCommand("backColor", false, #FF0000) (data value) assert_equals: expected (string) "rgb(255, 0, 0)" but got (object) null +PASS Calling execCommand("backColor", false, #FF0000) (dataTransfer value) +PASS Calling execCommand("backColor", false, #00FF00FF) (calling execCommand) +PASS Calling execCommand("backColor", false, #00FF00FF) (shouldn't fire beforeinput) +FAIL Calling execCommand("backColor", false, #00FF00FF) (inputType value) assert_equals: expected "formatBackColor" but got "" +FAIL Calling execCommand("backColor", false, #00FF00FF) (data value) assert_equals: expected (string) "rgb(0, 255, 0)" but got (object) null +PASS Calling execCommand("backColor", false, #00FF00FF) (dataTransfer value) +PASS Calling execCommand("backColor", false, #0000FF88) (calling execCommand) +PASS Calling execCommand("backColor", false, #0000FF88) (shouldn't fire beforeinput) +FAIL Calling execCommand("backColor", false, #0000FF88) (inputType value) assert_equals: expected "formatBackColor" but got "" +FAIL Calling execCommand("backColor", false, #0000FF88) (data value) assert_equals: expected (string) "rgba(0, 0, 255, 0.533)" but got (object) null +PASS Calling execCommand("backColor", false, #0000FF88) (dataTransfer value) +PASS Calling execCommand("backColor", false, orange) (calling execCommand) +PASS Calling execCommand("backColor", false, orange) (shouldn't fire beforeinput) +FAIL Calling execCommand("backColor", false, orange) (inputType value) assert_equals: expected "formatBackColor" but got "" +FAIL Calling execCommand("backColor", false, orange) (data value) assert_equals: expected (string) "rgb(255, 165, 0)" but got (object) null +PASS Calling execCommand("backColor", false, orange) (dataTransfer value) +PASS Calling execCommand("backColor", false, Inherit) (calling execCommand) +PASS Calling execCommand("backColor", false, Inherit) (shouldn't fire beforeinput) +FAIL Calling execCommand("backColor", false, Inherit) (inputType value) assert_equals: expected "formatBackColor" but got "" +FAIL Calling execCommand("backColor", false, Inherit) (data value) assert_equals: expected (string) "inherit" but got (object) null +PASS Calling execCommand("backColor", false, Inherit) (dataTransfer value) +PASS Calling execCommand("backColor", false, Initial) (calling execCommand) +PASS Calling execCommand("backColor", false, Initial) (shouldn't fire beforeinput) +FAIL Calling execCommand("backColor", false, Initial) (inputType value) assert_equals: expected "formatBackColor" but got "" +FAIL Calling execCommand("backColor", false, Initial) (data value) assert_equals: expected (string) "initial" but got (object) null +PASS Calling execCommand("backColor", false, Initial) (dataTransfer value) +PASS Calling execCommand("backColor", false, Reset) (calling execCommand) +PASS Calling execCommand("backColor", false, Reset) (shouldn't fire beforeinput) +FAIL Calling execCommand("backColor", false, Reset) (inputType value) assert_equals: expected "formatBackColor" but got "" +FAIL Calling execCommand("backColor", false, Reset) (data value) assert_equals: expected (string) "reset" but got (object) null +PASS Calling execCommand("backColor", false, Reset) (dataTransfer value) +PASS Calling execCommand("backColor", false, transparent) (calling execCommand) +PASS Calling execCommand("backColor", false, transparent) (shouldn't fire beforeinput) +FAIL Calling execCommand("backColor", false, transparent) (inputType value) assert_equals: expected "formatBackColor" but got "" +FAIL Calling execCommand("backColor", false, transparent) (data value) assert_equals: expected (string) "rgba(0, 0, 0, 0)" but got (object) null +PASS Calling execCommand("backColor", false, transparent) (dataTransfer value) +PASS Calling execCommand("backColor", false, CurrentColor) (calling execCommand) +PASS Calling execCommand("backColor", false, CurrentColor) (shouldn't fire beforeinput) +FAIL Calling execCommand("backColor", false, CurrentColor) (inputType value) assert_equals: expected "formatBackColor" but got "" +FAIL Calling execCommand("backColor", false, CurrentColor) (data value) assert_equals: expected (string) "currentcolor" but got (object) null +PASS Calling execCommand("backColor", false, CurrentColor) (dataTransfer value) +PASS Calling execCommand("backColor", false, Invalid-Value) (calling execCommand) +PASS Calling execCommand("backColor", false, Invalid-Value) (shouldn't fire beforeinput) +FAIL Calling execCommand("backColor", false, Invalid-Value) (inputType value) assert_equals: expected "formatBackColor" but got "" +FAIL Calling execCommand("backColor", false, Invalid-Value) (data value) assert_equals: expected (string) "Invalid-Value" but got (object) null +PASS Calling execCommand("backColor", false, Invalid-Value) (dataTransfer value) +PASS Calling execCommand("foreColor", false, #FF0000) (calling execCommand) +PASS Calling execCommand("foreColor", false, #FF0000) (shouldn't fire beforeinput) +FAIL Calling execCommand("foreColor", false, #FF0000) (inputType value) assert_equals: expected "formatFontColor" but got "" +FAIL Calling execCommand("foreColor", false, #FF0000) (data value) assert_equals: expected (string) "rgb(255, 0, 0)" but got (object) null +PASS Calling execCommand("foreColor", false, #FF0000) (dataTransfer value) +PASS Calling execCommand("foreColor", false, #00FF00FF) (calling execCommand) +PASS Calling execCommand("foreColor", false, #00FF00FF) (shouldn't fire beforeinput) +FAIL Calling execCommand("foreColor", false, #00FF00FF) (inputType value) assert_equals: expected "formatFontColor" but got "" +FAIL Calling execCommand("foreColor", false, #00FF00FF) (data value) assert_equals: expected (string) "rgb(0, 255, 0)" but got (object) null +PASS Calling execCommand("foreColor", false, #00FF00FF) (dataTransfer value) +PASS Calling execCommand("foreColor", false, #0000FF88) (calling execCommand) +PASS Calling execCommand("foreColor", false, #0000FF88) (shouldn't fire beforeinput) +FAIL Calling execCommand("foreColor", false, #0000FF88) (inputType value) assert_equals: expected "formatFontColor" but got "" +FAIL Calling execCommand("foreColor", false, #0000FF88) (data value) assert_equals: expected (string) "rgba(0, 0, 255, 0.533)" but got (object) null +PASS Calling execCommand("foreColor", false, #0000FF88) (dataTransfer value) +PASS Calling execCommand("foreColor", false, orange) (calling execCommand) +PASS Calling execCommand("foreColor", false, orange) (shouldn't fire beforeinput) +FAIL Calling execCommand("foreColor", false, orange) (inputType value) assert_equals: expected "formatFontColor" but got "" +FAIL Calling execCommand("foreColor", false, orange) (data value) assert_equals: expected (string) "rgb(255, 165, 0)" but got (object) null +PASS Calling execCommand("foreColor", false, orange) (dataTransfer value) +PASS Calling execCommand("foreColor", false, Inherit) (calling execCommand) +PASS Calling execCommand("foreColor", false, Inherit) (shouldn't fire beforeinput) +FAIL Calling execCommand("foreColor", false, Inherit) (inputType value) assert_equals: expected "formatFontColor" but got "" +FAIL Calling execCommand("foreColor", false, Inherit) (data value) assert_equals: expected (string) "inherit" but got (object) null +PASS Calling execCommand("foreColor", false, Inherit) (dataTransfer value) +PASS Calling execCommand("foreColor", false, Initial) (calling execCommand) +PASS Calling execCommand("foreColor", false, Initial) (shouldn't fire beforeinput) +FAIL Calling execCommand("foreColor", false, Initial) (inputType value) assert_equals: expected "formatFontColor" but got "" +FAIL Calling execCommand("foreColor", false, Initial) (data value) assert_equals: expected (string) "initial" but got (object) null +PASS Calling execCommand("foreColor", false, Initial) (dataTransfer value) +PASS Calling execCommand("foreColor", false, Reset) (calling execCommand) +PASS Calling execCommand("foreColor", false, Reset) (shouldn't fire beforeinput) +FAIL Calling execCommand("foreColor", false, Reset) (inputType value) assert_equals: expected "formatFontColor" but got "" +FAIL Calling execCommand("foreColor", false, Reset) (data value) assert_equals: expected (string) "reset" but got (object) null +PASS Calling execCommand("foreColor", false, Reset) (dataTransfer value) +PASS Calling execCommand("foreColor", false, transparent) (calling execCommand) +PASS Calling execCommand("foreColor", false, transparent) (shouldn't fire beforeinput) +FAIL Calling execCommand("foreColor", false, transparent) (inputType value) assert_equals: expected "formatFontColor" but got "" +FAIL Calling execCommand("foreColor", false, transparent) (data value) assert_equals: expected (string) "rgba(0, 0, 0, 0)" but got (object) null +PASS Calling execCommand("foreColor", false, transparent) (dataTransfer value) +PASS Calling execCommand("foreColor", false, CurrentColor) (calling execCommand) +PASS Calling execCommand("foreColor", false, CurrentColor) (shouldn't fire beforeinput) +FAIL Calling execCommand("foreColor", false, CurrentColor) (inputType value) assert_equals: expected "formatFontColor" but got "" +FAIL Calling execCommand("foreColor", false, CurrentColor) (data value) assert_equals: expected (string) "currentcolor" but got (object) null +PASS Calling execCommand("foreColor", false, CurrentColor) (dataTransfer value) +PASS Calling execCommand("foreColor", false, Invalid-Value) (calling execCommand) +PASS Calling execCommand("foreColor", false, Invalid-Value) (shouldn't fire beforeinput) +FAIL Calling execCommand("foreColor", false, Invalid-Value) (inputType value) assert_equals: expected "formatFontColor" but got "" +FAIL Calling execCommand("foreColor", false, Invalid-Value) (data value) assert_equals: expected (string) "Invalid-Value" but got (object) null +PASS Calling execCommand("foreColor", false, Invalid-Value) (dataTransfer value) +PASS Calling execCommand("hiliteColor", false, #FF0000) (calling execCommand) +PASS Calling execCommand("hiliteColor", false, #FF0000) (shouldn't fire beforeinput) +FAIL Calling execCommand("hiliteColor", false, #FF0000) (inputType value) assert_equals: expected "formatBackColor" but got "" +FAIL Calling execCommand("hiliteColor", false, #FF0000) (data value) assert_equals: expected (string) "rgb(255, 0, 0)" but got (object) null +PASS Calling execCommand("hiliteColor", false, #FF0000) (dataTransfer value) +PASS Calling execCommand("hiliteColor", false, #00FF00FF) (calling execCommand) +PASS Calling execCommand("hiliteColor", false, #00FF00FF) (shouldn't fire beforeinput) +FAIL Calling execCommand("hiliteColor", false, #00FF00FF) (inputType value) assert_equals: expected "formatBackColor" but got "" +FAIL Calling execCommand("hiliteColor", false, #00FF00FF) (data value) assert_equals: expected (string) "rgb(0, 255, 0)" but got (object) null +PASS Calling execCommand("hiliteColor", false, #00FF00FF) (dataTransfer value) +PASS Calling execCommand("hiliteColor", false, #0000FF88) (calling execCommand) +PASS Calling execCommand("hiliteColor", false, #0000FF88) (shouldn't fire beforeinput) +FAIL Calling execCommand("hiliteColor", false, #0000FF88) (inputType value) assert_equals: expected "formatBackColor" but got "" +FAIL Calling execCommand("hiliteColor", false, #0000FF88) (data value) assert_equals: expected (string) "rgba(0, 0, 255, 0.533)" but got (object) null +PASS Calling execCommand("hiliteColor", false, #0000FF88) (dataTransfer value) +PASS Calling execCommand("hiliteColor", false, orange) (calling execCommand) +PASS Calling execCommand("hiliteColor", false, orange) (shouldn't fire beforeinput) +FAIL Calling execCommand("hiliteColor", false, orange) (inputType value) assert_equals: expected "formatBackColor" but got "" +FAIL Calling execCommand("hiliteColor", false, orange) (data value) assert_equals: expected (string) "rgb(255, 165, 0)" but got (object) null +PASS Calling execCommand("hiliteColor", false, orange) (dataTransfer value) +PASS Calling execCommand("hiliteColor", false, Inherit) (calling execCommand) +PASS Calling execCommand("hiliteColor", false, Inherit) (shouldn't fire beforeinput) +FAIL Calling execCommand("hiliteColor", false, Inherit) (inputType value) assert_equals: expected "formatBackColor" but got "" +FAIL Calling execCommand("hiliteColor", false, Inherit) (data value) assert_equals: expected (string) "inherit" but got (object) null +PASS Calling execCommand("hiliteColor", false, Inherit) (dataTransfer value) +PASS Calling execCommand("hiliteColor", false, Initial) (calling execCommand) +PASS Calling execCommand("hiliteColor", false, Initial) (shouldn't fire beforeinput) +FAIL Calling execCommand("hiliteColor", false, Initial) (inputType value) assert_equals: expected "formatBackColor" but got "" +FAIL Calling execCommand("hiliteColor", false, Initial) (data value) assert_equals: expected (string) "initial" but got (object) null +PASS Calling execCommand("hiliteColor", false, Initial) (dataTransfer value) +PASS Calling execCommand("hiliteColor", false, Reset) (calling execCommand) +PASS Calling execCommand("hiliteColor", false, Reset) (shouldn't fire beforeinput) +FAIL Calling execCommand("hiliteColor", false, Reset) (inputType value) assert_equals: expected "formatBackColor" but got "" +FAIL Calling execCommand("hiliteColor", false, Reset) (data value) assert_equals: expected (string) "reset" but got (object) null +PASS Calling execCommand("hiliteColor", false, Reset) (dataTransfer value) +PASS Calling execCommand("hiliteColor", false, transparent) (calling execCommand) +PASS Calling execCommand("hiliteColor", false, transparent) (shouldn't fire beforeinput) +FAIL Calling execCommand("hiliteColor", false, transparent) (inputType value) assert_equals: expected "formatBackColor" but got "" +FAIL Calling execCommand("hiliteColor", false, transparent) (data value) assert_equals: expected (string) "rgba(0, 0, 0, 0)" but got (object) null +PASS Calling execCommand("hiliteColor", false, transparent) (dataTransfer value) +PASS Calling execCommand("hiliteColor", false, CurrentColor) (calling execCommand) +PASS Calling execCommand("hiliteColor", false, CurrentColor) (shouldn't fire beforeinput) +FAIL Calling execCommand("hiliteColor", false, CurrentColor) (inputType value) assert_equals: expected "formatBackColor" but got "" +FAIL Calling execCommand("hiliteColor", false, CurrentColor) (data value) assert_equals: expected (string) "currentcolor" but got (object) null +PASS Calling execCommand("hiliteColor", false, CurrentColor) (dataTransfer value) +PASS Calling execCommand("hiliteColor", false, Invalid-Value) (calling execCommand) +PASS Calling execCommand("hiliteColor", false, Invalid-Value) (shouldn't fire beforeinput) +FAIL Calling execCommand("hiliteColor", false, Invalid-Value) (inputType value) assert_equals: expected "formatBackColor" but got "" +FAIL Calling execCommand("hiliteColor", false, Invalid-Value) (data value) assert_equals: expected (string) "Invalid-Value" but got (object) null +PASS Calling execCommand("hiliteColor", false, Invalid-Value) (dataTransfer value) +PASS Calling execCommand("fontName", false, monospace) (calling execCommand) +PASS Calling execCommand("fontName", false, monospace) (shouldn't fire beforeinput) +FAIL Calling execCommand("fontName", false, monospace) (inputType value) assert_equals: expected "formatFontName" but got "" +FAIL Calling execCommand("fontName", false, monospace) (data value) assert_equals: expected (string) "monospace" but got (object) null +PASS Calling execCommand("fontName", false, monospace) (dataTransfer value) +PASS Calling execCommand("fontName", false, monospace ) (calling execCommand) +PASS Calling execCommand("fontName", false, monospace ) (shouldn't fire beforeinput) +FAIL Calling execCommand("fontName", false, monospace ) (inputType value) assert_equals: expected "formatFontName" but got "" +FAIL Calling execCommand("fontName", false, monospace ) (data value) assert_equals: expected (string) " monospace " but got (object) null +PASS Calling execCommand("fontName", false, monospace ) (dataTransfer value) +PASS Calling execCommand("fontName", false, monospace ) (calling execCommand) +PASS Calling execCommand("fontName", false, monospace ) (shouldn't fire beforeinput) +FAIL Calling execCommand("fontName", false, monospace ) (inputType value) assert_equals: expected "formatFontName" but got "" +FAIL Calling execCommand("fontName", false, monospace ) (data value) assert_equals: expected (string) " monospace " but got (object) null +PASS Calling execCommand("fontName", false, monospace ) (dataTransfer value) +PASS Calling execCommand("justifyCenter", false, null) (calling execCommand) +PASS Calling execCommand("justifyCenter", false, null) (shouldn't fire beforeinput) +PASS Calling execCommand("justifyCenter", false, null) (inputType value) +PASS Calling execCommand("justifyCenter", false, null) (data value) +PASS Calling execCommand("justifyCenter", false, null) (dataTransfer value) PASS execCommand("justifyCenter") should wrap the text with <div> element whose text-align is center -PASS Calling execCommand("justifyFull", false, null) +PASS Calling execCommand("justifyFull", false, null) (calling execCommand) +PASS Calling execCommand("justifyFull", false, null) (shouldn't fire beforeinput) +PASS Calling execCommand("justifyFull", false, null) (inputType value) +PASS Calling execCommand("justifyFull", false, null) (data value) +PASS Calling execCommand("justifyFull", false, null) (dataTransfer value) PASS execCommand("justifyFull") should wrap the text with <div> element whose text-align is justify -PASS Calling execCommand("justifyRight", false, null) +PASS Calling execCommand("justifyRight", false, null) (calling execCommand) +PASS Calling execCommand("justifyRight", false, null) (shouldn't fire beforeinput) +PASS Calling execCommand("justifyRight", false, null) (inputType value) +PASS Calling execCommand("justifyRight", false, null) (data value) +PASS Calling execCommand("justifyRight", false, null) (dataTransfer value) PASS execCommand("justifyRight") should wrap the text with <div> element whose text-align is right -PASS Calling execCommand("justifyLeft", false, null) +PASS Calling execCommand("justifyLeft", false, null) (calling execCommand) +PASS Calling execCommand("justifyLeft", false, null) (shouldn't fire beforeinput) +PASS Calling execCommand("justifyLeft", false, null) (inputType value) +PASS Calling execCommand("justifyLeft", false, null) (data value) +PASS Calling execCommand("justifyLeft", false, null) (dataTransfer value) PASS execCommand("justifyLeft") should wrap the text with <div> element whose text-align is left -PASS Calling execCommand("removeFormat", false, null) +PASS Calling execCommand("removeFormat", false, null) (calling execCommand) +PASS Calling execCommand("removeFormat", false, null) (shouldn't fire beforeinput) +PASS Calling execCommand("removeFormat", false, null) (inputType value) +PASS Calling execCommand("removeFormat", false, null) (data value) +PASS Calling execCommand("removeFormat", false, null) (dataTransfer value) PASS execCommand("removeFormat") should remove the style of current block -PASS Calling execCommand("indent", false, null) -PASS Calling execCommand("outdent", false, null) +PASS Calling execCommand("indent", false, null) (calling execCommand) +PASS Calling execCommand("indent", false, null) (shouldn't fire beforeinput) +PASS Calling execCommand("indent", false, null) (inputType value) +PASS Calling execCommand("indent", false, null) (data value) +PASS Calling execCommand("indent", false, null) (dataTransfer value) +PASS Calling execCommand("outdent", false, null) (calling execCommand) +PASS Calling execCommand("outdent", false, null) (shouldn't fire beforeinput) +PASS Calling execCommand("outdent", false, null) (inputType value) +PASS Calling execCommand("outdent", false, null) (data value) +PASS Calling execCommand("outdent", false, null) (dataTransfer value) PASS Set of execCommand("indent") and execCommand("outdent") should keep same DOM tree -PASS Calling execCommand("copy", false, null) -PASS Calling execCommand("cut", false, null) -PASS Calling execCommand("paste", false, null) -FAIL Calling execCommand("createLink", false, https://example.com/) assert_equals: Calling execCommand("createLink", false, https://example.com/) should produce inputType: insertLink expected "insertLink" but got "" -PASS execCommand("createLink") should create a link -PASS Calling execCommand("unlink", false, null) +PASS Calling execCommand("copy", false, null) (calling execCommand) +PASS Calling execCommand("copy", false, null) (shouldn't fire beforeinput) +PASS Calling execCommand("copy", false, null) (inputType value) +PASS Calling execCommand("cut", false, null) (calling execCommand) +PASS Calling execCommand("cut", false, null) (shouldn't fire beforeinput) +PASS Calling execCommand("cut", false, null) (inputType value) +PASS Calling execCommand("cut", false, null) (data value) +PASS Calling execCommand("cut", false, null) (dataTransfer value) +PASS Calling execCommand("paste", false, null) (calling execCommand) +PASS Calling execCommand("paste", false, null) (shouldn't fire beforeinput) +PASS Calling execCommand("paste", false, null) (inputType value) +PASS Calling execCommand("paste", false, null) (data value) +FAIL Calling execCommand("paste", false, null) (dataTransfer value, text/plain) assert_true: calling dataTransfer.getData(text/plain) caused exception: TypeError: Cannot read property 'getData' of null expected true got false +FAIL Calling execCommand("paste", false, null) (dataTransfer.clearData(text/plain)) assert_true: calling dataTransfer.clearData(text/plain) caused exception: TypeError: Cannot read property 'clearData' of null expected true got false +FAIL Calling execCommand("paste", false, null) (dataTransfer.setData(text/plain)) assert_true: calling dataTransfer.setData(text/plain) caused exception: TypeError: Cannot read property 'setData' of null expected true got false +PASS Calling execCommand("createLink", false, https://example.com/) (calling execCommand) +PASS Calling execCommand("createLink", false, https://example.com/) (shouldn't fire beforeinput) +FAIL Calling execCommand("createLink", false, https://example.com/) (inputType value) assert_equals: expected "insertLink" but got "" +FAIL Calling execCommand("createLink", false, https://example.com/) (data value) assert_equals: expected (string) "https://example.com/" but got (object) null +PASS Calling execCommand("createLink", false, https://example.com/) (dataTransfer value) +PASS execCommand("createLink") should create a link with absolute URL +PASS Calling execCommand("unlink", false, null) (calling execCommand) +PASS Calling execCommand("unlink", false, null) (shouldn't fire beforeinput) +PASS Calling execCommand("unlink", false, null) (inputType value) +PASS Calling execCommand("unlink", false, null) (data value) +PASS Calling execCommand("unlink", false, null) (dataTransfer value) PASS execCommand("createLink") should remove the link +PASS Calling execCommand("createLink", false, foo.html) (calling execCommand) +PASS Calling execCommand("createLink", false, foo.html) (shouldn't fire beforeinput) +FAIL Calling execCommand("createLink", false, foo.html) (inputType value) assert_equals: expected "insertLink" but got "" +FAIL Calling execCommand("createLink", false, foo.html) (data value) assert_equals: expected (string) "foo.html" but got (object) null +PASS Calling execCommand("createLink", false, foo.html) (dataTransfer value) +PASS execCommand("createLink") should create a link with relative URL Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/input-events/input-events-exec-command.html b/third_party/blink/web_tests/external/wpt/input-events/input-events-exec-command.html index 9ba423f..8f84936 100644 --- a/third_party/blink/web_tests/external/wpt/input-events/input-events-exec-command.html +++ b/third_party/blink/web_tests/external/wpt/input-events/input-events-exec-command.html
@@ -7,141 +7,224 @@ <script> (function() { let lastBeforeInputType = ''; + let lastBeforeInputData = ''; + let lastBeforeInputDataTransfer = undefined; let lastInputType = ''; + let lastInputData = ''; + let lastInputDataTransfer = undefined; const txt = document.getElementById('txt'); txt.addEventListener('beforeinput', function(event) { assert_true(event instanceof InputEvent); assert_false(event.isComposing); lastBeforeInputType = event.inputType; + lastBeforeInputData = event.data; + lastBeforeInputDataTransfer = event.dataTransfer; }); txt.addEventListener('input', function(event) { assert_true(event instanceof InputEvent); assert_false(event.isComposing); lastInputType = event.inputType; + lastInputData = event.data; + lastInputDataTransfer = event.dataTransfer; }); const NO_INPUT_EVENT_FIRED = 'NO_INPUT_EVENT_FIRED'; - function testExecCommandInputType(command, args, inputType) { + function testExecCommandInputType(command, args, inputType, data, dataTransfer) { const description = `Calling execCommand("${command}", false, ${args})`; + lastBeforeInputType = NO_INPUT_EVENT_FIRED; + lastBeforeInputData = NO_INPUT_EVENT_FIRED; + lastBeforeInputDataTransfer = NO_INPUT_EVENT_FIRED; + lastInputType = NO_INPUT_EVENT_FIRED; + lastInputData = NO_INPUT_EVENT_FIRED; + lastInputDataTransfer = NO_INPUT_EVENT_FIRED; test(function() { - lastBeforeInputType = NO_INPUT_EVENT_FIRED; - lastInputType = NO_INPUT_EVENT_FIRED; try { document.execCommand(command, false, args); } catch (e) { - assert(false, `execCommand shouldn't cause any exception: ${e}`); + assert_true(false, `execCommand shouldn't cause any exception: ${e}`); } - assert_equals(lastBeforeInputType, NO_INPUT_EVENT_FIRED, - `${description} shouldn't fire beforeinput`); - assert_equals(lastInputType, inputType, - `${description} should produce inputType: ${inputType}`); - }, description); + }, description + " (calling execCommand)"); + test(function() { + assert_equals(lastBeforeInputType, NO_INPUT_EVENT_FIRED); + assert_equals(lastBeforeInputData, NO_INPUT_EVENT_FIRED); + assert_equals(lastBeforeInputDataTransfer, NO_INPUT_EVENT_FIRED); + }, description + " (shouldn't fire beforeinput)"); + test(function() { + assert_equals(lastInputType, inputType); + }, description + " (inputType value)"); + if (lastInputType === NO_INPUT_EVENT_FIRED) { + return; + } + test(function() { + assert_equals(lastInputData, data); + }, description + " (data value)"); + if (dataTransfer === null) { + test(function() { + assert_equals(lastInputDataTransfer, dataTransfer, + `${description} should produce dataTransfer: null`); + }, description + " (dataTransfer value)"); + } else { + for (let item of dataTransfer) { + test(function() { + try { + assert_equals(lastInputDataTransfer.getData(item.type), item.data, + `${description} should produce dataTransfer.getData(${item.type}): ${item.data}`); + } catch (e) { + assert_true(false, `calling dataTransfer.getData(${item.type}) caused exception: ${e}`); + } + }, `${description} (dataTransfer value, ${item.type})`); + test(function() { + try { + lastInputDataTransfer.clearData(item.type); + } catch (e) { + assert_true(false, `calling dataTransfer.clearData(${item.type}) caused exception: ${e}`); + } + assert_equals(lastInputDataTransfer.getData(item.type), item.data, + `${description} dataTransfer.clearData(${item.type}) should do nothing`); + }, `${description} (dataTransfer.clearData(${item.type}))`); + test(function() { + try { + lastInputDataTransfer.setData(item.type, "foo"); + } catch (e) { + assert_true(false, `calling dataTransfer.setData(${item.type}) caused exception: ${e}`); + } + assert_equals(lastInputDataTransfer.getData(item.type), item.data, + `${description} dataTransfer.setData(${item.type}, "foo") should do nothing`); + }, `${description} (dataTransfer.setData(${item.type}))`); + } + } } txt.focus(); // InsertText - testExecCommandInputType('insertText', 'a', 'insertText'); - testExecCommandInputType('insertText', 'bc', 'insertText'); + testExecCommandInputType('insertText', 'a', 'insertText', 'a', null); + testExecCommandInputType('insertText', 'bc', 'insertText', 'bc', null); test(function() { assert_equals(txt.innerHTML, 'abc'); }, "execCommand(\"insertText\") should insert \"abc\" into the editor"); - testExecCommandInputType('insertOrderedList', null, 'insertOrderedList'); + testExecCommandInputType('insertOrderedList', null, 'insertOrderedList', null, null); test(function() { assert_equals(txt.innerHTML, '<ol><li>abc</li></ol>'); }, "execCommand(\"insertOrderedList\") should make <ol> and wrap the text with it"); - testExecCommandInputType('insertUnorderedList', null, 'insertUnorderedList'); + testExecCommandInputType('insertUnorderedList', null, 'insertUnorderedList', null, null); test(function() { assert_equals(txt.innerHTML, '<ul><li>abc</li></ul>'); }, "execCommand(\"insertUnorderedList\") should make <ul> and wrap the text with it"); - testExecCommandInputType('insertLineBreak', null, 'insertLineBreak'); - testExecCommandInputType('insertParagraph', null, 'insertParagraph'); + testExecCommandInputType('insertLineBreak', null, 'insertLineBreak', null, null); + testExecCommandInputType('insertParagraph', null, 'insertParagraph', null, null); txt.innerHTML = ''; - testExecCommandInputType('insertHorizontalRule', null, 'insertHorizontalRule'); + testExecCommandInputType('insertHorizontalRule', null, 'insertHorizontalRule', null, null); // Styling txt.innerHTML = 'abc'; var selection = window.getSelection(); selection.collapse(txt, 0); selection.extend(txt, 1); - testExecCommandInputType('bold', null, 'formatBold'); + testExecCommandInputType('bold', null, 'formatBold', null, null); test(function() { assert_equals(txt.innerHTML, '<b>abc</b>'); }, "execCommand(\"bold\") should wrap selected text with <b> element"); - testExecCommandInputType('italic', null, 'formatItalic'); + testExecCommandInputType('italic', null, 'formatItalic', null, null); test(function() { assert_equals(txt.innerHTML, '<b><i>abc</i></b>'); }, "execCommand(\"italic\") should wrap selected text with <i> element"); - testExecCommandInputType('underline', null, 'formatUnderline'); + testExecCommandInputType('underline', null, 'formatUnderline', null, null); test(function() { assert_equals(txt.innerHTML, '<b><i><u>abc</u></i></b>'); }, "execCommand(\"underline\") should wrap selected text with <u> element"); - testExecCommandInputType('strikeThrough', null, 'formatStrikeThrough'); + testExecCommandInputType('strikeThrough', null, 'formatStrikeThrough', null, null); test(function() { assert_equals(txt.innerHTML, '<b><i><u><strike>abc</strike></u></i></b>'); }, "execCommand(\"strikeThrough\") should wrap selected text with <strike> element"); - testExecCommandInputType('superscript', null, 'formatSuperscript'); + testExecCommandInputType('superscript', null, 'formatSuperscript', null, null); test(function() { assert_equals(txt.innerHTML, '<b><i><u><strike><sup>abc</sup></strike></u></i></b>'); }, "execCommand(\"superscript\") should wrap selected text with <sup> element"); - testExecCommandInputType('subscript', null, 'formatSubscript'); + testExecCommandInputType('subscript', null, 'formatSubscript', null, null); test(function() { assert_equals(txt.innerHTML, '<b><i><u><strike><sub>abc</sub></strike></u></i></b>'); }, "execCommand(\"subscript\") should wrap selected text with <sub> element"); txt.innerHTML = 'abc'; selection.collapse(txt, 0); selection.extend(txt, 1); - testExecCommandInputType('backColor', '#000000', 'formatBackColor'); - testExecCommandInputType('foreColor', '#FFFFFF', 'formatFontColor'); - testExecCommandInputType('hiliteColor', '#FFFF00', 'formatBackColor'); - testExecCommandInputType('fontName', 'monospace', 'formatFontName'); + for (let test of [{command: 'backColor', inputType: 'formatBackColor'}, + {command: 'foreColor', inputType: 'formatFontColor'}, + {command: 'hiliteColor', inputType: 'formatBackColor'}]) { + testExecCommandInputType(test.command, '#FF0000', test.inputType, 'rgb(255, 0, 0)', null); + testExecCommandInputType(test.command, '#00FF00FF', test.inputType, 'rgb(0, 255, 0)', null); + testExecCommandInputType(test.command, '#0000FF88', test.inputType, 'rgba(0, 0, 255, 0.533)', null); + testExecCommandInputType(test.command, 'orange', test.inputType, 'rgb(255, 165, 0)', null); + testExecCommandInputType(test.command, 'Inherit', test.inputType, 'inherit', null); + testExecCommandInputType(test.command, 'Initial', test.inputType, 'initial', null); + testExecCommandInputType(test.command, 'Reset', test.inputType, 'reset', null); + testExecCommandInputType(test.command, 'transparent', test.inputType, 'rgba(0, 0, 0, 0)', null); + testExecCommandInputType(test.command, 'CurrentColor', test.inputType, 'currentcolor', null); + testExecCommandInputType(test.command, 'Invalid-Value', test.inputType, 'Invalid-Value', null); + } + + testExecCommandInputType('fontName', 'monospace', 'formatFontName', 'monospace', null); + testExecCommandInputType('fontName', ' monospace ', 'formatFontName', ' monospace ', null); + testExecCommandInputType('fontName', ' monospace ', 'formatFontName', ' monospace ', null); // Formating txt.innerHTML = 'abc'; - testExecCommandInputType('justifyCenter', null, 'formatJustifyCenter'); + testExecCommandInputType('justifyCenter', null, 'formatJustifyCenter', null, null); test(function() { assert_equals(txt.innerHTML, '<div style="text-align: center;">abc</div>'); }, "execCommand(\"justifyCenter\") should wrap the text with <div> element whose text-align is center"); - testExecCommandInputType('justifyFull', null, 'formatJustifyFull'); + testExecCommandInputType('justifyFull', null, 'formatJustifyFull', null, null); test(function() { assert_equals(txt.innerHTML, '<div style="text-align: justify;">abc</div>'); }, "execCommand(\"justifyFull\") should wrap the text with <div> element whose text-align is justify"); - testExecCommandInputType('justifyRight', null, 'formatJustifyRight'); + testExecCommandInputType('justifyRight', null, 'formatJustifyRight', null, null); test(function() { assert_equals(txt.innerHTML, '<div style="text-align: right;">abc</div>'); }, "execCommand(\"justifyRight\") should wrap the text with <div> element whose text-align is right"); - testExecCommandInputType('justifyLeft', null, 'formatJustifyLeft'); + testExecCommandInputType('justifyLeft', null, 'formatJustifyLeft', null, null); test(function() { assert_equals(txt.innerHTML, '<div style="text-align: left;">abc</div>'); }, "execCommand(\"justifyLeft\") should wrap the text with <div> element whose text-align is left"); selection.collapse(txt, 0); selection.extend(txt, 1); - testExecCommandInputType('removeFormat', null, 'formatRemove'); + testExecCommandInputType('removeFormat', null, 'formatRemove', null, null); test(function() { assert_equals(txt.innerHTML, '<div style="">abc</div>'); }, "execCommand(\"removeFormat\") should remove the style of current block"); - testExecCommandInputType('indent', null, 'formatIndent'); - testExecCommandInputType('outdent', null, 'formatOutdent'); + testExecCommandInputType('indent', null, 'formatIndent', null, null); + testExecCommandInputType('outdent', null, 'formatOutdent', null, null); test(function() { assert_equals(txt.innerHTML, '<div style="">abc</div>'); }, "Set of execCommand(\"indent\") and execCommand(\"outdent\") should keep same DOM tree"); // Copy shouldn't fire 'input'. - testExecCommandInputType('copy', null, NO_INPUT_EVENT_FIRED); + txt.innerHTML = 'ab<b>c</b>def'; + selection.collapse(txt.firstChild, 1); + selection.extend(txt.firstChild.nextSibling.nextSibling, 1); + testExecCommandInputType('copy', null, NO_INPUT_EVENT_FIRED, NO_INPUT_EVENT_FIRED, NO_INPUT_EVENT_FIRED); // Cut/Paste should fire 'input'. - testExecCommandInputType('cut', null, 'deleteByCut'); - testExecCommandInputType('paste', null, 'insertFromPaste'); + testExecCommandInputType('cut', null, 'deleteByCut', null, null); + // XXX How can we test 'text/html' case? The detail of copied HTML fragment depends on browser. + testExecCommandInputType('paste', null, 'insertFromPaste', null, [{type: 'text/plain', data: 'bcd'}]); // Link and Unlink txt.innerHTML = 'abc'; selection.collapse(txt.firstChild, 1); selection.extend(txt.firstChild, 2); - testExecCommandInputType('createLink', 'https://example.com/', 'insertLink'); + testExecCommandInputType('createLink', 'https://example.com/', 'insertLink', 'https://example.com/', null); test(function() { assert_equals(txt.innerHTML, 'a<a href="https://example.com/">b</a>c'); - }, "execCommand(\"createLink\") should create a link"); - testExecCommandInputType('unlink', null, ''); + }, "execCommand(\"createLink\") should create a link with absolute URL"); + testExecCommandInputType('unlink', null, '', null, null); test(function() { assert_equals(txt.innerHTML, 'abc'); }, "execCommand(\"createLink\") should remove the link"); + + txt.innerHTML = 'abc'; + selection.collapse(txt.firstChild, 1); + selection.extend(txt.firstChild, 2); + testExecCommandInputType('createLink', 'foo.html', 'insertLink', 'foo.html', null); + test(function() { + assert_equals(txt.innerHTML, 'a<a href="foo.html">b</a>c'); + }, "execCommand(\"createLink\") should create a link with relative URL"); })(); </script>
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-color-001-notref.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-color-001-notref.html new file mode 100644 index 0000000..498d627 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-color-001-notref.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Fraction bar color</title> + </head> + <body style="font-size: 20pt;"> + <p>This test passes if you see a fraction with a blue fraction bar.</p> + <math> + <mfrac> + <mspace width="200px" height="20px" style="background: black"></mspace> + <mspace width="200px" height="20px" style="background: black"></mspace> + </mfrac> + </math> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-color-001.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-color-001.html new file mode 100644 index 0000000..bc61dbf5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-color-001.html
@@ -0,0 +1,19 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Fraction bar color</title> + <link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S3.html#SS3.SSS2"> + <meta name="assert" content="The CSS color property has an effect on the fraction bar."> + <link rel="mismatch" href="frac-color-001-notref.html"> + </head> + <body style="font-size: 20pt;"> + <p>This test passes if you see a fraction with a blue fraction bar.</p> + <math> + <mfrac style="color: blue;"> + <mspace width="200px" height="20px" style="background: black"></mspace> + <mspace width="200px" height="20px" style="background: black"></mspace> + </mfrac> + </math> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-001-ref.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-001-ref.html new file mode 100644 index 0000000..c703edb --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-001-ref.html
@@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>fractions linethickness</title> + <style type="text/css"> + @font-face { + font-family: TestFont; + src: url("/fonts/math/fraction-rulethickness10000.woff"); + } + math { + /* FractionRuleThickness = 10000 * 1 / 1000 = 10px; */ + font-family: "TestFont"; + font-size: 1px; + } + </style> + </head> + <body> + <p>This test passes if you see fractions with line thickness equal to the height of their blue numerator and cyan denominator.</p> + <math> + <mfrac linethickness="5px"> + <mspace width="20px" height="5px" style="background: blue"></mspace> + <mspace width="20px" height="5px" style="background: cyan"></mspace> + </mfrac> + <mfrac linethickness="10px"> + <mspace width="20px" height="10px" style="background: blue"></mspace> + <mspace width="20px" height="10px" style="background: cyan"></mspace> + </mfrac> + <mfrac linethickness="20px"> + <mspace width="20px" height="20px" style="background: blue"></mspace> + <mspace width="20px" height="20px" style="background: cyan"></mspace> + </mfrac> + <mfrac linethickness="50px"> + <mspace width="20px" height="50px" style="background: blue"></mspace> + <mspace width="20px" height="50px" style="background: cyan"></mspace> + </mfrac> + </math> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-001.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-001.html new file mode 100644 index 0000000..9411117 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-001.html
@@ -0,0 +1,42 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>fractions linethickness</title> + <link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S3.html#SS3.SSS2"> + <meta name="assert" content="Verifies 'thin', 'medium', 'thick' and unitless values for the linethickness attribute of the mfrac element"> + <link rel="match" href="frac-linethickness-001-ref.html"> + <style type="text/css"> + @font-face { + font-family: TestFont; + src: url("/fonts/math/fraction-rulethickness10000.woff"); + } + math { + /* FractionRuleThickness = 10000 * 1 / 1000 = 10px; */ + font-family: "TestFont"; + font-size: 1px; + } + </style> + </head> + <body> + <p>This test passes if you see fractions with line thickness equal to the height of their blue numerator and cyan denominator.</p> + <math> + <mfrac linethickness="thin"> + <mspace width="20px" height="5px" style="background: blue"></mspace> + <mspace width="20px" height="5px" style="background: cyan"></mspace> + </mfrac> + <mfrac linethickness="medium"> + <mspace width="20px" height="10px" style="background: blue"></mspace> + <mspace width="20px" height="10px" style="background: cyan"></mspace> + </mfrac> + <mfrac linethickness="thick"> + <mspace width="20px" height="20px" style="background: blue"></mspace> + <mspace width="20px" height="20px" style="background: cyan"></mspace> + </mfrac> + <mfrac linethickness="5"> + <mspace width="20px" height="50px" style="background: blue"></mspace> + <mspace width="20px" height="50px" style="background: cyan"></mspace> + </mfrac> + </math> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-002-ref.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-002-ref.html new file mode 100644 index 0000000..6966393 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-002-ref.html
@@ -0,0 +1,40 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>fractions linethickness</title> + <style type="text/css"> + @font-face { + font-family: TestFont; + src: url("/fonts/math/fraction-rulethickness10000.woff"); + } + math { + /* FractionRuleThickness = 10000 * 1 / 1000 = 10px; */ + font-family: "TestFont"; + font-size: 1px; + } + </style> + </head> + <body> + <p>This test passes if you see fraction with a cyan denominator and + a blue numerator as tall as its black bar.</p> + <math> + <mfrac linethickness="0px"> + <mspace width="20px" height="0px" style="background: blue"></mspace> + <mspace width="20px" height="10px" style="background: cyan"></mspace> + </mfrac> + </math> + <math> + <mfrac linethickness="50px"> + <mspace width="20px" height="50px" style="background: blue"></mspace> + <mspace width="20px" height="10px" style="background: cyan"></mspace> + </mfrac> + </math> + <math style="font-size: 180px"> + <mfrac linethickness="0.3888888888888889em"> + <mspace width="20px" height="70px" style="background: blue"></mspace> + <mspace width="20px" height="10px" style="background: cyan"></mspace> + </mfrac> + </math> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-002.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-002.html new file mode 100644 index 0000000..5bb0d6b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-002.html
@@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>fractions linethickness</title> + <link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S3.html#SS3.SSS2"> + <meta name="assert" content="Verifies fraction with negative, percent and named space linethickness values."> + <link rel="match" href="frac-linethickness-002-ref.html"> + <style type="text/css"> + @font-face { + font-family: TestFont; + src: url("/fonts/math/fraction-rulethickness10000.woff"); + } + math { + /* FractionRuleThickness = 10000 * 1 / 1000 = 10px; */ + font-family: "TestFont"; + font-size: 1px; + } + </style> + </head> + <body> + <p>This test passes if you see fraction with a cyan denominator and + a blue numerator as tall as its black bar.</p> + <math> + <mfrac linethickness="-1.23em"> + <mspace width="20px" height="0px" style="background: blue"></mspace> + <mspace width="20px" height="10px" style="background: cyan"></mspace> + </mfrac> + </math> + <math> + <mfrac linethickness="500%"> + <mspace width="20px" height="50px" style="background: blue"></mspace> + <mspace width="20px" height="10px" style="background: cyan"></mspace> + </mfrac> + </math> + <math style="font-size: 180px"> + <mfrac linethickness="veryverythickmathspace"> + <mspace width="20px" height="70px" style="background: blue"></mspace> + <mspace width="20px" height="10px" style="background: cyan"></mspace> + </mfrac> + </math> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-003-notref.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-003-notref.html new file mode 100644 index 0000000..934d666 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-003-notref.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>fractions linethickness</title> + </head> + <body> + <p>This test passes if you see a fraction without fraction bar.</p> + <math> + <mfrac> + <mspace width="20px" height="5px" style="background: blue"></mspace> + <mspace width="20px" height="5px" style="background: cyan"></mspace> + </mfrac> + </math> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-003.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-003.html new file mode 100644 index 0000000..e535e70 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-linethickness-003.html
@@ -0,0 +1,19 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>fractions linethickness</title> + <link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S3.html#SS3.SSS2"> + <meta name="assert" content="Verifies fraction with 0px bar."> + <link rel="mismatch" href="frac-linethickness-003-notref.html"> + </head> + <body> + <p>This test passes if you see a fraction without fraction bar.</p> + <math> + <mfrac linethickness="0px"> + <mspace width="20px" height="5px" style="background: blue"></mspace> + <mspace width="20px" height="5px" style="background: cyan"></mspace> + </mfrac> + </math> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-mrow-001-ref.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-mrow-001-ref.html new file mode 100644 index 0000000..e42cb96 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-mrow-001-ref.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Fraction mrow</title> + </head> + <body style="font-size: 20pt;"> + <p>This test passes if you see a fraction with a blue square as numerator and a cyan square as denominator.</p> + <math> + <mfrac> + <mspace width="60px" height="60px" style="background: blue"></mspace> + <mspace width="60px" height="60px" style="background: cyan"></mspace> + </mfrac> + </math> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-mrow-001.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-mrow-001.html new file mode 100644 index 0000000..e5c6f52 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-mrow-001.html
@@ -0,0 +1,25 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Fraction mrow</title> + <link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S3.html#SS3.SSS2"> + <meta name="assert" content="This test that <mrow> elements can be used as numerator and denominator of fractions."> + <link rel="match" href="frac-mrow-001-ref.html"> + </head> + <body style="font-size: 20pt;"> + <p>This test passes if you see a fraction with a blue square as numerator and a cyan square as denominator.</p> + <math> + <mfrac> + <mrow> + <mspace width="30px" height="60px" style="background: blue"></mspace> + <mspace width="30px" height="60px" style="background: blue "></mspace> + </mrow> + <mrow> + <mspace width="30px" height="60px" style="background: cyan"></mspace> + <mspace width="30px" height="60px" style="background: cyan "></mspace> + </mrow> + </mfrac> + </math> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-numalign-denomalign-001-ref.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-numalign-denomalign-001-ref.html new file mode 100644 index 0000000..2fa9786 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-numalign-denomalign-001-ref.html
@@ -0,0 +1,73 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Fraction numalign denomalign</title> + </head> + <body> + <p>This test passes if you see 3 fractions with a numerator respectively + aligned left/center/right with respect to the denominator ; + followed by 3 fractions with a denominator respectively aligned + left/center/right with respect to the numerator.</p> + <p> + <math> + <mfrac> + <mrow> + <mspace width="10px" height="20px" style="background: blue;"></mspace> + <mspace width="20px" height="20px"></mspace> + </mrow> + <mspace width="30px" height="20px" style="background: cyan;"></mspace> + </mfrac> + </math> + <math> + <mfrac> + <mrow> + <mspace width="10px" height="20px"></mspace> + <mspace width="10px" height="20px" style="background: blue;"></mspace> + <mspace width="10px" height="20px"></mspace> + </mrow> + <mspace width="30px" height="20px" style="background: cyan;"></mspace> + </mfrac> + </math> + <math> + <mfrac> + <mrow> + <mspace width="20px" height="20px"></mspace> + <mspace width="10px" height="20px" style="background: blue;"></mspace> + </mrow> + <mspace width="30px" height="20px" style="background: cyan;"></mspace> + </mfrac> + </math> + </p> + <p> + <math> + <mfrac> + <mspace width="30px" height="20px" style="background: cyan;"></mspace> + <mrow> + <mspace width="10px" height="20px" style="background: blue;"></mspace> + <mspace width="20px" height="20px"></mspace> + </mrow> + </mfrac> + </math> + <math> + <mfrac> + <mspace width="30px" height="20px" style="background: cyan;"></mspace> + <mrow> + <mspace width="10px" height="20px"></mspace> + <mspace width="10px" height="20px" style="background: blue;"></mspace> + <mspace width="10px" height="20px"></mspace> + </mrow> + </mfrac> + </math> + <math> + <mfrac> + <mspace width="30px" height="20px" style="background: cyan;"></mspace> + <mrow> + <mspace width="20px" height="20px"></mspace> + <mspace width="10px" height="20px" style="background: blue;"></mspace> + </mrow> + </mfrac> + </math> + </p> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-numalign-denomalign-001.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-numalign-denomalign-001.html new file mode 100644 index 0000000..61f49e2f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/fractions/frac-numalign-denomalign-001.html
@@ -0,0 +1,56 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Fraction numalign denomalign</title> + <link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S3.html#SS3.SSS2"> + <meta name="assert" content="This fraction alignment with the numalign/denomalign attributes."> + <link rel="match" href="frac-numalign-denomalign-001-ref.html"> + </head> + <body> + <p>This test passes if you see 3 fractions with a numerator respectively + aligned left/center/right with respect to the denominator ; + followed by 3 fractions with a denominator respectively aligned + left/center/right with respect to the numerator.</p> + <p> + <math> + <mfrac numalign="left"> + <mspace width="10px" height="20px" style="background: blue;"></mspace> + <mspace width="30px" height="20px" style="background: cyan;"></mspace> + </mfrac> + </math> + <math> + <mfrac numalign="center"> + <mspace width="10px" height="20px" style="background: blue;"></mspace> + <mspace width="30px" height="20px" style="background: cyan;"></mspace> + </mfrac> + </math> + <math> + <mfrac numalign="right"> + <mspace width="10px" height="20px" style="background: blue;"></mspace> + <mspace width="30px" height="20px" style="background: cyan;"></mspace> + </mfrac> + </math> + </p> + <p> + <math> + <mfrac denomalign="left"> + <mspace width="30px" height="20px" style="background: cyan;"></mspace> + <mspace width="10px" height="20px" style="background: blue;"></mspace> + </mfrac> + </math> + <math> + <mfrac denomalign="center"> + <mspace width="30px" height="20px" style="background: cyan;"></mspace> + <mspace width="10px" height="20px" style="background: blue;"></mspace> + </mfrac> + </math> + <math> + <mfrac denomalign="right"> + <mspace width="30px" height="20px" style="background: cyan;"></mspace> + <mspace width="10px" height="20px" style="background: blue;"></mspace> + </mfrac> + </math> + </p> + </body> +</html>
diff --git a/third_party/blink/web_tests/media/track/track-cue-rendering-position-auto-expected.html b/third_party/blink/web_tests/media/track/track-cue-rendering-position-auto-expected.html index 901df80ac..e0f988d 100644 --- a/third_party/blink/web_tests/media/track/track-cue-rendering-position-auto-expected.html +++ b/third_party/blink/web_tests/media/track/track-cue-rendering-position-auto-expected.html
@@ -30,7 +30,6 @@ background: green; color: green; font-size: 50px; - padding: 2px; } </style> <div class="container">
diff --git a/third_party/blink/web_tests/media/track/track-cue-rendering-position-auto-rtl-expected.html b/third_party/blink/web_tests/media/track/track-cue-rendering-position-auto-rtl-expected.html index 0654db4e..c71606a 100644 --- a/third_party/blink/web_tests/media/track/track-cue-rendering-position-auto-rtl-expected.html +++ b/third_party/blink/web_tests/media/track/track-cue-rendering-position-auto-rtl-expected.html
@@ -32,7 +32,6 @@ background: green; color: green; font-size: 50px; - padding: 2px; } </style> <div class="container">
diff --git a/third_party/blink/web_tests/media/track/track-cue-rendering-with-padding.html b/third_party/blink/web_tests/media/track/track-cue-rendering-with-padding.html index 9ccce45..70474ba 100644 --- a/third_party/blink/web_tests/media/track/track-cue-rendering-with-padding.html +++ b/third_party/blink/web_tests/media/track/track-cue-rendering-with-padding.html
@@ -5,7 +5,7 @@ <script src="../../resources/testharnessreport.js"></script> <style> video::-webkit-media-text-track-display { - padding: 15px; + padding: 10px; } </style> <video>
diff --git a/third_party/blink/web_tests/platform/linux/media/track/track-cue-rendering-horizontal-expected.png b/third_party/blink/web_tests/platform/linux/media/track/track-cue-rendering-horizontal-expected.png index 1c767b4..744f01f 100644 --- a/third_party/blink/web_tests/platform/linux/media/track/track-cue-rendering-horizontal-expected.png +++ b/third_party/blink/web_tests/platform/linux/media/track/track-cue-rendering-horizontal-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/media/track/track-cue-rendering-vertical-expected.png b/third_party/blink/web_tests/platform/linux/media/track/track-cue-rendering-vertical-expected.png index c53e8c5a..0fb28191 100644 --- a/third_party/blink/web_tests/platform/linux/media/track/track-cue-rendering-vertical-expected.png +++ b/third_party/blink/web_tests/platform/linux/media/track/track-cue-rendering-vertical-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/video-surface-layer/media/track/track-cue-rendering-horizontal-expected.png b/third_party/blink/web_tests/platform/linux/virtual/video-surface-layer/media/track/track-cue-rendering-horizontal-expected.png new file mode 100644 index 0000000..744f01f --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/virtual/video-surface-layer/media/track/track-cue-rendering-horizontal-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/video-surface-layer/media/track/track-cue-rendering-vertical-expected.png b/third_party/blink/web_tests/platform/linux/virtual/video-surface-layer/media/track/track-cue-rendering-vertical-expected.png index c53e8c5a..0fb28191 100644 --- a/third_party/blink/web_tests/platform/linux/virtual/video-surface-layer/media/track/track-cue-rendering-vertical-expected.png +++ b/third_party/blink/web_tests/platform/linux/virtual/video-surface-layer/media/track/track-cue-rendering-vertical-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/media/track/track-cue-rendering-vertical-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/media/track/track-cue-rendering-vertical-expected.png index 07055e21..9c2e12ea 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.10/media/track/track-cue-rendering-vertical-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.10/media/track/track-cue-rendering-vertical-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/video-surface-layer/media/track/track-cue-rendering-vertical-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/video-surface-layer/media/track/track-cue-rendering-vertical-expected.png index 07055e21..9c2e12ea 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/video-surface-layer/media/track/track-cue-rendering-vertical-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/video-surface-layer/media/track/track-cue-rendering-vertical-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/media/track/track-cue-rendering-vertical-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/media/track/track-cue-rendering-vertical-expected.png index 3a2ab97..08193f25 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.11/media/track/track-cue-rendering-vertical-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.11/media/track/track-cue-rendering-vertical-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/video-surface-layer/media/track/track-cue-rendering-vertical-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/video-surface-layer/media/track/track-cue-rendering-vertical-expected.png index 3a2ab97..08193f25 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/video-surface-layer/media/track/track-cue-rendering-vertical-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/video-surface-layer/media/track/track-cue-rendering-vertical-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/media/track/track-cue-rendering-horizontal-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/media/track/track-cue-rendering-horizontal-expected.png index 17b7f9d6..38d844e 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.12/media/track/track-cue-rendering-horizontal-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.12/media/track/track-cue-rendering-horizontal-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/video-surface-layer/media/track/track-cue-rendering-horizontal-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/video-surface-layer/media/track/track-cue-rendering-horizontal-expected.png index 17b7f9d6..38d844e 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/video-surface-layer/media/track/track-cue-rendering-horizontal-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/video-surface-layer/media/track/track-cue-rendering-horizontal-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/media/track/track-cue-rendering-horizontal-expected.png b/third_party/blink/web_tests/platform/mac/media/track/track-cue-rendering-horizontal-expected.png index 26a8ba6..112cac81 100644 --- a/third_party/blink/web_tests/platform/mac/media/track/track-cue-rendering-horizontal-expected.png +++ b/third_party/blink/web_tests/platform/mac/media/track/track-cue-rendering-horizontal-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/media/track/track-cue-rendering-vertical-expected.png b/third_party/blink/web_tests/platform/mac/media/track/track-cue-rendering-vertical-expected.png index 015250c..86a37f3 100644 --- a/third_party/blink/web_tests/platform/mac/media/track/track-cue-rendering-vertical-expected.png +++ b/third_party/blink/web_tests/platform/mac/media/track/track-cue-rendering-vertical-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/media/track/track-cue-rendering-horizontal-expected.png b/third_party/blink/web_tests/platform/win/media/track/track-cue-rendering-horizontal-expected.png index 021412e..5a483e8 100644 --- a/third_party/blink/web_tests/platform/win/media/track/track-cue-rendering-horizontal-expected.png +++ b/third_party/blink/web_tests/platform/win/media/track/track-cue-rendering-horizontal-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/media/track/track-cue-rendering-vertical-expected.png b/third_party/blink/web_tests/platform/win/media/track/track-cue-rendering-vertical-expected.png index 457955f..2196206d 100644 --- a/third_party/blink/web_tests/platform/win/media/track/track-cue-rendering-vertical-expected.png +++ b/third_party/blink/web_tests/platform/win/media/track/track-cue-rendering-vertical-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/media/track/track-cue-rendering-vertical-expected.png b/third_party/blink/web_tests/platform/win7/media/track/track-cue-rendering-vertical-expected.png index 12d70d3..950738b 100644 --- a/third_party/blink/web_tests/platform/win7/media/track/track-cue-rendering-vertical-expected.png +++ b/third_party/blink/web_tests/platform/win7/media/track/track-cue-rendering-vertical-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/video-surface-layer/media/track/track-cue-rendering-vertical-expected.png b/third_party/blink/web_tests/platform/win7/virtual/video-surface-layer/media/track/track-cue-rendering-vertical-expected.png index 12d70d3..950738b 100644 --- a/third_party/blink/web_tests/platform/win7/virtual/video-surface-layer/media/track/track-cue-rendering-vertical-expected.png +++ b/third_party/blink/web_tests/platform/win7/virtual/video-surface-layer/media/track/track-cue-rendering-vertical-expected.png Binary files differ
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 67421e85..136a8c8 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -6519,6 +6519,28 @@ <int value="10" label="FollowBookmark"/> <int value="11" label="PageSelectorNavigateFirst"/> <int value="12" label="PageSelectorNavigate"/> + <int value="13" label="SaveFirst"/> + <int value="14" label="Save"/> + <int value="15" label="SaveWithAnnotationFirst"/> + <int value="16" label="SaveWithAnnotation"/> + <int value="17" label="PrintFirst"/> + <int value="18" label="Print"/> + <int value="19" label="EnterAnnotationModeFirst"/> + <int value="20" label="EnterAnnotationMode"/> + <int value="21" label="ExitAnnotationModeFirst"/> + <int value="22" label="ExitAnnotationMode"/> + <int value="23" label="AnnotateStrokeToolPenFirst"/> + <int value="24" label="AnnotateStrokeToolPen"/> + <int value="25" label="AnnotateStrokeToolEraserFirst"/> + <int value="26" label="AnnotateStrokeToolEraser"/> + <int value="27" label="AnnotateStrokeToolHighlighterFirst"/> + <int value="28" label="AnnotateStrokeToolHighlighter"/> + <int value="29" label="AnnotateStrokeDeviceTouchFirst"/> + <int value="30" label="AnnotateStrokeDeviceTouch"/> + <int value="31" label="AnnotateStrokeDeviceMouseFirst"/> + <int value="32" label="AnnotateStrokeDeviceMouse"/> + <int value="33" label="AnnotateStrokeDevicePenFirst"/> + <int value="34" label="AnnotateStrokeDevicePen"/> </enum> <enum name="ChromePDFViewerAnnotationType"> @@ -31472,6 +31494,7 @@ label="kAutofillRationalizeRepeatedServerPredictions:disabled"/> <int value="-894214299" label="fill-on-account-select:enabled"/> <int value="-894185031" label="HighDynamicRange:disabled"/> + <int value="-892428689" label="ManualPasswordGenerationAndroid:enabled"/> <int value="-891856063" label="MidiManagerAndroid:enabled"/> <int value="-886912558" label="ChromeHomePromo:enabled"/> <int value="-885601782" label="enable-contextual-search"/> @@ -32739,6 +32762,7 @@ <int value="1298927156" label="TouchpadOverscrollHistoryNavigation:enabled"/> <int value="1298981651" label="disable-new-task-manager"/> <int value="1300282719" label="OfflinePagesBackgroundLoading:enabled"/> + <int value="1300753556" label="ManualPasswordGenerationAndroid:disabled"/> <int value="1302421166" label="NativeNotifications:disabled"/> <int value="1304636193" label="ArcEnableUnifiedAudioFocus:enabled"/> <int value="1307003774" label="AutofillEnableCompanyName:disabled"/>
diff --git a/tools/perf/scripts_smoke_unittest.py b/tools/perf/scripts_smoke_unittest.py index f776538c..a78ea68 100644 --- a/tools/perf/scripts_smoke_unittest.py +++ b/tools/perf/scripts_smoke_unittest.py
@@ -150,7 +150,9 @@ shutil.rmtree(tempdir) - @decorators.Disabled('win') # ".exe" is auto-added which breaks Windows. + # Windows: ".exe" is auto-added which breaks Windows. + # ChromeOS: crbug.com/754913. + @decorators.Disabled('win', 'chromeos') def testRunPerformanceTestsGtest_end2end(self): tempdir = tempfile.mkdtemp() benchmark = 'dummy_gtest'
diff --git a/tools/ubsan/blacklist.txt b/tools/ubsan/blacklist.txt index 68e25a21..13dce2bd 100644 --- a/tools/ubsan/blacklist.txt +++ b/tools/ubsan/blacklist.txt
@@ -12,9 +12,6 @@ ############################################################################# # V8 UBsan supressions -# UBSan bug, fixed in LLVM r350779. Drop this suppression when that -# revision has rolled into Chromium's bundled Clang. -fun:*v8*internal*NewArray* # Bug v8:8735: PropertyCallbackInfo<void> vs PropertyCallbackInfo<T>. fun:*v8*internal*PropertyCallbackArguments*CallAccessorSetter*
diff --git a/ui/file_manager/file_manager/foreground/css/file_manager.css b/ui/file_manager/file_manager/foreground/css/file_manager.css index b06bd5b..4fac7e0e 100644 --- a/ui/file_manager/file_manager/foreground/css/file_manager.css +++ b/ui/file_manager/file_manager/foreground/css/file_manager.css
@@ -1197,6 +1197,18 @@ background-color: rgb(221, 242, 253); } +.thumbnail-grid .thumbnail-item[selected] .shield { + background-color: rgba(51, 103, 214, 0.5); + +} +.thumbnail-grid .thumbnail-item[lead]:not([selected]) .shield { + background-color: rgba(51, 103, 214, 0.2); +} + +body.check-select .thumbnail-grid:focus .thumbnail-item[lead] { + outline: 1px solid rgba(51, 103, 214, 0.5); +} + .thumbnail-grid .checkmark { background-position: center; background-repeat: no-repeat; @@ -1274,7 +1286,8 @@ background-color: rgba(51, 103, 214, 0.5); } -.thumbnail-grid .thumbnail-item[selected] .shield { +.thumbnail-grid .thumbnail-item[selected] .shield, +.thumbnail-grid .thumbnail-item[lead] .shield { display: block; } @@ -1288,11 +1301,13 @@ background-color: rgb(255, 255, 255); } -.thumbnail-grid .thumbnail-item[selected].directory .thumbnail-bottom { +.thumbnail-grid .thumbnail-item[selected].directory .thumbnail-bottom, +.thumbnail-grid .thumbnail-item[lead].directory .thumbnail-bottom { background-color: rgb(232, 232, 232); } -.thumbnail-grid:focus .thumbnail-item[selected].directory .thumbnail-bottom { +.thumbnail-grid:focus .thumbnail-item[selected].directory .thumbnail-bottom, +.thumbnail-grid:focus .thumbnail-item[lead].directory .thumbnail-bottom { background-color: rgb(232, 246, 253); } @@ -1360,16 +1375,28 @@ #list-container list > li[selected], #list-container list > li:active, #list-container list > li.accepts, +#list-container list:focus > li[lead], #default-tasks-list > li[selected] { background-color: rgb(232, 232, 232); } #list-container list:focus > li[selected], #list-container list:focus > li.accepts[selected], +#list-container list:focus > li[lead], #default-tasks-list:focus > li[selected] { background-color: rgb(216, 223, 240); } +body.check-select #list-container list > li[lead], +#list-container list > li[lead]:not([selected]) { + background-color: rgba(232, 234, 237, 0.5); +} + +body.check-select #list-container list:focus > li[lead], +#list-container list > li[lead]:not([selected]):focus { + background-color: rgb(232, 234, 237); +} + #list-container.nohover grid > .accepts { background-color: transparent; }
diff --git a/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.html b/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.html deleted file mode 100644 index 4548367..0000000 --- a/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.html +++ /dev/null
@@ -1,10 +0,0 @@ -<!DOCTYPE html> -<!-- 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. - --> - -<script src="../../../../webui/resources/js/assert.js"></script> -<script src="../../../../webui/resources/js/util.js"></script> -<script src="../../../base/js/test_error_reporting.js"></script> -<script src="files_tooltip_unittest.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn index e0c18d6..e9b135b7 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
@@ -299,6 +299,18 @@ ] } +js_unittest("file_table_list_unittest") { + deps = [ + ":file_table_list", + ":file_table", + "../../../common/js:util", + "//ui/file_manager/base/js:test_error_reporting", + "//ui/webui/resources/js:webui_resource_test", + "//ui/file_manager/file_manager/background/js:mock_volume_manager", + "//ui/file_manager/file_manager/foreground/js/metadata:mock_metadata", + ] +} + js_library("file_tap_handler") { deps = [ "../../../common/js:util", @@ -464,6 +476,7 @@ ":file_table_unittest", ":file_tap_handler_unittest", ":list_container_unittest", + ":file_table_list_unittest", ":multi_menu_unittest", ] }
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_list_selection_model.js b/ui/file_manager/file_manager/foreground/js/ui/file_list_selection_model.js index 8c57553..fac679f 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_list_selection_model.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_list_selection_model.js
@@ -7,6 +7,14 @@ constructor(opt_length) { super(opt_length); + /** + * Overwrite ListSelectionModel to allow lead item to be independent of the + * current selected item(s). + * @private {boolean} + * @override + */ + this.independentLeadItem_ = true; + /** @private {boolean} */ this.isCheckSelectMode_ = false;
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_table_list.js b/ui/file_manager/file_manager/foreground/js/ui/file_table_list.js index 7d66b67..1994f9f2 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_table_list.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_table_list.js
@@ -496,8 +496,29 @@ if (e.key == ' ') { if (leadIndex != -1) { const selected = sm.getIndexSelected(leadIndex); - if (e.ctrlKey || !selected) { - sm.setIndexSelected(leadIndex, !selected || !sm.multiple); + if (e.ctrlKey) { + sm.beginChange(); + + // Force selecting if it's the first item selected, otherwise flip the + // "selected" status. + if (selected && sm.selectedIndexes.length === 1 && + !sm.getCheckSelectMode()) { + // It needs to go back/forth to trigger the 'change' event. + sm.setIndexSelected(leadIndex, false); + sm.setIndexSelected(leadIndex, true); + } else { + // Toggle the current one and make it anchor index. + sm.setIndexSelected(leadIndex, !selected); + } + + // Force check-select, FileListSelectionModel.onChangeEvent_ resets it + // if needed. + sm.setCheckSelectMode(true); + sm.endChange(); + + // Prevents space to opening quickview. + e.stopPropagation(); + e.preventDefault(); return; } } @@ -547,6 +568,9 @@ } else { sm.selectRange(anchorIndex, newIndex); } + } else if (e.ctrlKey) { + // While Ctrl is being held, only leadIndex and anchorIndex are moved. + sm.anchorIndex = newIndex; } else { // 1) When pressing direction key results in a single selection, the // check-select mode should be terminated.
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_table_list_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/file_table_list_unittest.js new file mode 100644 index 0000000..51deaeab --- /dev/null +++ b/ui/file_manager/file_manager/foreground/js/ui/file_table_list_unittest.js
@@ -0,0 +1,216 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +'use strict'; + +/** @type {!MockVolumeManager} */ +let volumeManager; + +/** @type {!DirectoryModel} */ +let directoryModel; + +/** @type {!MetadataModel} */ +let metadataModel; + +/** @type {!importer.HistoryLoader} */ +let historyLoader; + +/** @type {!HTMLElement} */ +let element; + +// Set up test components. +function setUp() { + // Mock LoadTimeData strings. + window.loadTimeData.getString = id => id; + window.loadTimeData.data = {}; + + // Setup mock components. + volumeManager = new MockVolumeManager(); + metadataModel = new MockMetadataModel({}); + historyLoader = /** @type {!importer.HistoryLoader} */ ({ + getHistory: () => { + return Promise.resolve(); + }, + }); + + // Create DOM element parent of the file list under test. + element = setupBody(); +} + +/** + * Returns the element used to parent the file list. The element is + * attached to the body, and styled for visual display. + * + * @return {!HTMLElement} + */ +function setupBody() { + const style = ` + <style> + list { + display: block; + height: 200px; + width: 800px; + } + </style> + `; + document.body.innerHTML = style; + + const element = document.createElement('div'); + document.body.appendChild(element); + return /** @type {!HTMLElement} */ (element); +} + +/** @param {string} keyName */ +function key(keyName) { + return { + bubbles: true, + composed: true, + key: keyName, + }; +} + +/** @param {string} keyName */ +function ctrlAndKey(keyName) { + return { + ctrlKey: true, + shiftKey: false, + altKey: false, + bubbles: true, + composed: true, + key: keyName, + }; +} + +/** + * Tests that the keyboard can be used to navigate the FileTableList. + */ +function testMultipleSelectionWithKeyboard() { + // Render the FileTable on |element|. + const fullPage = true; + FileTable.decorate( + element, metadataModel, volumeManager, historyLoader, fullPage); + + // Overwrite the selectionModel of the FileTable class (since events + // would be handled by cr.ui.ListSelectionModel otherwise). + const sm = new FileListSelectionModel(); + const table = /** @type {FileTable} */ (element); + table.selectionModel = sm; + + // Add FileTableList file entries, then draw and focus the table list. + const entries = [ + new FakeEntry('entry1-label', VolumeManagerCommon.RootType.CROSTINI), + new FakeEntry('entry2-label', VolumeManagerCommon.RootType.CROSTINI), + new FakeEntry('entry3-label', VolumeManagerCommon.RootType.CROSTINI), + ]; + const dataModel = new FileListModel(metadataModel); + dataModel.splice(0, 0, ...entries); + const tableList = /** @type {FileTableList} */ (element.list); + tableList.dataModel = dataModel; + tableList.redraw(); + tableList.focus(); + + // Grab all the elements in the file list. + const listItem0 = tableList.items[0]; + const listItem1 = tableList.items[1]; + const listItem2 = tableList.items[2]; + + // Assert file table list |item| selection state. + function assertItemIsSelected(item, selected = true) { + if (selected) { + assertTrue(item.hasAttribute('selected')); + assertEquals('true', item.getAttribute('aria-selected')); + } else { + assertFalse(item.hasAttribute('selected')); + assertEquals(null, item.getAttribute('aria-selected')); + } + } + + // Assert file table list |item| focus/lead state. + function assertItemIsTheLead(item, lead = true) { + if (lead) { + assertEquals('lead', item.getAttribute('lead')); + assertEquals(item.id, tableList.getAttribute('aria-activedescendant')); + } else { + assertFalse(item.hasAttribute('lead')); + assertFalse(item.id === tableList.getAttribute('aria-activedescendant')); + } + } + + // FileTableList always allows multiple selection. + assertEquals('true', tableList.getAttribute('aria-multiselectable')); + + // Home key selects the first item (listItem0). + tableList.dispatchEvent(new KeyboardEvent('keydown', key('Home'))); + // Only 1 item selected. + assertEquals(1, sm.selectedIndexes.length); + // listItem0 should be selected and focused. + assertEquals(0, sm.selectedIndexes[0]); + assertItemIsTheLead(listItem0); + assertItemIsSelected(listItem0); + // Only one item is selected: multiple selection should be inactive. + assertFalse(sm.getCheckSelectMode()); + + // ArrowDown moves and selects next item. + tableList.dispatchEvent(new KeyboardEvent('keydown', key('ArrowDown'))); + // Only listItem1 should be selected. + assertEquals(1, sm.selectedIndexes.length); + assertEquals(1, sm.selectedIndexes[0]); + // listItem1 should be focused. + assertItemIsTheLead(listItem1); + assertItemIsSelected(listItem1); + // Only one item is selected: multiple selection should be inactive. + assertFalse(sm.getCheckSelectMode()); + + // Ctrl+ArrowDown only moves the focus. + tableList.dispatchEvent( + new KeyboardEvent('keydown', ctrlAndKey('ArrowDown'))); + // listItem1 should be not focused but still selected. + assertEquals(1, sm.selectedIndexes.length); + assertEquals(1, sm.selectedIndexes[0]); + assertItemIsTheLead(listItem1, false); + assertItemIsSelected(listItem1); + // listItem2 should be focused but not selected. + assertItemIsTheLead(listItem2); + assertItemIsSelected(listItem2, false); + + // Only one item is selected: multiple selection should be inactive. + assertFalse(sm.getCheckSelectMode()); + + // Ctrl+Space selects the focused item. + tableList.dispatchEvent(new KeyboardEvent('keydown', ctrlAndKey(' '))); + // Multiple selection mode should now be activated. + assertTrue(sm.getCheckSelectMode()); + // Both listItem1 and listItem2 should be selected. + assertEquals(2, sm.selectedIndexes.length); + assertEquals(1, sm.selectedIndexes[0]); + assertEquals(2, sm.selectedIndexes[1]); + // listItem1 should not be focused. + assertItemIsTheLead(listItem1, false); + assertItemIsSelected(listItem1); + // listItem1 should be focused and selected. + assertItemIsTheLead(listItem2); + assertItemIsSelected(listItem2); + + // Hit Esc to cancel the whole selection. + tableList.dispatchEvent(new KeyboardEvent('keydown', key('Escape'))); + // The item with the focus should not change. + assertItemIsTheLead(listItem2); + // But there should be no selected items anymore. + assertFalse(sm.getCheckSelectMode()); + assertEquals(0, sm.selectedIndexes.length); + for (let i = 0; i < tableList.items.length; i++) { + if (i !== 2) { + // Item 2 should have focus. + assertFalse( + tableList.items[i].hasAttribute('lead'), + 'item ' + i + ' should not have focus'); + } + assertEquals( + 'false', tableList.items[i].getAttribute('aria-selected'), + 'item ' + i + ' should have aria-selected=false'); + assertFalse( + tableList.items[i].hasAttribute('selected'), + 'item ' + i + ' should not have selected attr'); + } +}
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn index 6f9b0c3f..78256bdf 100644 --- a/ui/gfx/BUILD.gn +++ b/ui/gfx/BUILD.gn
@@ -253,6 +253,7 @@ ] deps += [ ":gfx_export", + ":resize_image_dimensions", "//base", "//base:base_static", "//base:i18n", @@ -405,6 +406,14 @@ defines = [ "COLOR_SPACE_IMPLEMENTATION" ] } +# Depend on this to use image/resize_image_dimensions.h without pulling in +# all of gfx. +source_set("resize_image_dimensions") { + sources = [ + "image/resize_image_dimensions.h", + ] +} + # Depend on this to use native_widget_types.h without pulling in all of gfx. source_set("native_widget_types") { public = [
diff --git a/ui/gfx/image/image_util.cc b/ui/gfx/image/image_util.cc index b856788..80bca3ea 100644 --- a/ui/gfx/image/image_util.cc +++ b/ui/gfx/image/image_util.cc
@@ -15,6 +15,7 @@ #include "ui/gfx/codec/jpeg_codec.h" #include "ui/gfx/image/image.h" #include "ui/gfx/image/image_skia.h" +#include "ui/gfx/image/resize_image_dimensions.h" namespace {
diff --git a/ui/gfx/image/image_util.h b/ui/gfx/image/image_util.h index 5b48487b..e8593f4d 100644 --- a/ui/gfx/image/image_util.h +++ b/ui/gfx/image/image_util.h
@@ -18,11 +18,6 @@ namespace gfx { -// Dimensions to use when downsizing an image for search-by-image. -const int kSearchByImageMaxImageArea = 90000; -const int kSearchByImageMaxImageWidth = 600; -const int kSearchByImageMaxImageHeight = 400; - // Creates an image from the given JPEG-encoded input. If there was an error // creating the image, returns an IsEmpty() Image. GFX_EXPORT Image ImageFrom1xJPEGEncodedData(const unsigned char* input,
diff --git a/ui/gfx/image/image_util_ios.mm b/ui/gfx/image/image_util_ios.mm index adac57a..cc66b24 100644 --- a/ui/gfx/image/image_util_ios.mm +++ b/ui/gfx/image/image_util_ios.mm
@@ -7,6 +7,7 @@ #include "third_party/google_toolbox_for_mac/src/iPhone/GTMUIImage+Resize.h" #include "ui/gfx/image/image.h" #include "ui/gfx/image/image_util.h" +#include "ui/gfx/image/resize_image_dimensions.h" #include "base/logging.h"
diff --git a/ui/gfx/image/resize_image_dimensions.h b/ui/gfx/image/resize_image_dimensions.h new file mode 100644 index 0000000..65f7925 --- /dev/null +++ b/ui/gfx/image/resize_image_dimensions.h
@@ -0,0 +1,17 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_GFX_IMAGE_RESIZE_IMAGE_DIMENSIONS_H_ +#define UI_GFX_IMAGE_RESIZE_IMAGE_DIMENSIONS_H_ + +namespace gfx { + +// Dimensions to use when downsizing an image for search-by-image. +const int kSearchByImageMaxImageArea = 90000; +const int kSearchByImageMaxImageWidth = 600; +const int kSearchByImageMaxImageHeight = 400; + +} // namespace gfx + +#endif // UI_GFX_IMAGE_RESIZE_IMAGE_DIMENSIONS_H_
diff --git a/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js b/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js index 086b8bc..8d400af 100644 --- a/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js +++ b/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js
@@ -170,7 +170,7 @@ listeners: { 'keydown': 'onKeyDown_', 'mouseover': 'onMouseover_', - 'tap': 'onTap_', + 'click': 'onClick_', }, /** override */ @@ -224,7 +224,7 @@ * @param {!Event} e * @private */ - onTap_: function(e) { + onClick_: function(e) { if (e.target == this) { this.close(); e.stopPropagation();