diff --git a/DEPS b/DEPS index be26caa..92e42f7 100644 --- a/DEPS +++ b/DEPS
@@ -199,11 +199,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'db2dad5c644f5a57059ef57483d52090f0e3c0c9', + 'skia_revision': 'd2f51b18065a1ed93a4195afb8852b12e2fae1cd', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': 'd87c3006482190728da53f87875b2a528dfb7ef3', + 'v8_revision': 'ff24c7121a8adc0450e1368daf5e060b7b4f64ca', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -250,7 +250,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. - 'freetype_revision': 'cbc14b10e623a5d08c89a1323ae9c420c8492118', + 'freetype_revision': '0901a6f74c707f4e631d810b9f3ac7f0c0d2042e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. @@ -274,7 +274,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': 'b43fbe8a06ea52e110218c82644181ed12917400', + 'devtools_frontend_revision': '51690fcadbede4f2005aece3d76191b7464d367f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -314,11 +314,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '00fcab636a055c78036ee20bb1a89339b0a28bad', + 'dawn_revision': 'a2e02836a2600aa751f1b7eeb6bb56c4e573e230', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'quiche_revision': '63bdfe586f8ceddf5e0823b75b1c595cbd380b2e', + 'quiche_revision': '425c25a8ad2d190f61531fd46e0a65050cc1b98a', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ios_webkit # and whatever else without interference from each other. @@ -1266,7 +1266,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '070ef598892aee3d5cfb628f577867217c863142', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'afc78f5e6ae999fd26a7473e8e2b068b6e666063', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1344,7 +1344,7 @@ 'packages': [ { 'package': 'fuchsia/third_party/aemu/linux-amd64', - 'version': 'e-bgBYXeOkMw5xrqjCgQDp16bMPZeKKmilHzC-t2-1QC' + 'version': 'luM2HIHgfBKxr1C7UPo8RdQPAvyLNd74T9rYfhWFOC8C' }, ], 'condition': 'host_os == "linux" and checkout_fuchsia', @@ -1483,9 +1483,9 @@ }, 'src/third_party/usrsctp/usrsctplib': - Var('chromium_git') + '/external/github.com/sctplab/usrsctp' + '@' + '4191ca1784d8774dbf62d48ab9426c7311a91bc5', + Var('chromium_git') + '/external/github.com/sctplab/usrsctp' + '@' + 'a3c3ef666b7a5e4c93ebae5a7462add6f86f5cf2', - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@ffb3b84133b03dfc4b83a8430a418f4fa94308d8', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@e395b66ed41c80a28349f18f9b16bce6bd80e2b3', 'src/third_party/vulkan_memory_allocator': Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + '6c656df63da5995a932aafd45b32af1974e497d9', @@ -1518,7 +1518,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '3c2fe3888658d82b47ca831d59a2e07579619c2d', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'cdb3bc3b93dae5237610d0e45bccd900812a0cfe', + Var('webrtc_git') + '/src.git' + '@' + '1607b3aa8ccd55e48e2fc0204ee5cbe873d41928', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1590,7 +1590,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@8e33046d8bd53448771287085284e477d29aef1d', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@36b254fb9b13503b7b3b181da82ab3a626c770e6', 'condition': 'checkout_src_internal', }, @@ -1609,7 +1609,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/media_app/app', - 'version': 'mqExY_CKGV64CkBK6pxd74QrlY0Ui90tdf5wIZPeB38C', + 'version': 'G2hKrv9siNlrFfUOPnGITX-1vPXVfef552IDKjdJcgoC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java index 33c3deba..a8c68cc 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java
@@ -316,6 +316,12 @@ cl.appendSwitch(AwSwitches.WEBVIEW_SANDBOXED_RENDERER); } + // Enable modern SameSite cookie behavior if the app targets at least S. + if (BuildInfo.targetsAtLeastS()) { + CommandLine cl = CommandLine.getInstance(); + cl.appendSwitch(AwSwitches.WEBVIEW_ENABLE_MODERN_COOKIE_SAME_SITE); + } + int applicationFlags = ctx.getApplicationInfo().flags; boolean isAppDebuggable = (applicationFlags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; boolean isOsDebuggable = BuildInfo.isDebugAndroid();
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java index 1ed65800..b913b48 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java
@@ -177,8 +177,6 @@ @Test @MediumTest @Feature({"AndroidWebView", "Privacy"}) - @CommandLineFlags.Add({"enable-blink-features=CookieStoreDocument"}) - // TODO(https://crbug.com/968649) Remove switch when CookieStore launched. public void testAcceptCookie_falseWontSetCookies() throws Throwable { testAcceptCookieHelper(false, "-disabled"); } @@ -186,8 +184,6 @@ @Test @MediumTest @Feature({"AndroidWebView", "Privacy"}) - @CommandLineFlags.Add({"enable-blink-features=CookieStoreDocument"}) - // TODO(https://crbug.com/968649) Remove switch when CookieStore launched. public void testAcceptCookie_trueWillSetCookies() throws Throwable { testAcceptCookieHelper(true, "-enabled"); } @@ -686,8 +682,6 @@ @Test @MediumTest @Feature({"AndroidWebView", "Privacy"}) - @CommandLineFlags.Add({"enable-blink-features=CookieStoreDocument"}) - // TODO(https://crbug.com/968649) Remove switch when CookieStore launched. public void testCookieStoreListener() throws Throwable { TestWebServer webServer = TestWebServer.startSsl(); try { @@ -1005,8 +999,6 @@ @Test @MediumTest @Feature({"AndroidWebView", "Privacy"}) - @CommandLineFlags.Add({"enable-blink-features=CookieStoreDocument"}) - // TODO(https://crbug.com/968649) Remove switch when CookieStore launched. public void testThirdPartyJavascriptCookie() throws Throwable { // Using SSL server here since CookieStore API requires a secure schema. TestWebServer webServer = TestWebServer.startSsl(); @@ -1033,8 +1025,6 @@ @Test @MediumTest @Feature({"AndroidWebView", "Privacy"}) - @CommandLineFlags.Add({"enable-blink-features=CookieStoreDocument"}) - // TODO(https://crbug.com/968649) Remove switch when CookieStore launched. public void testThirdPartyCookiesArePerWebview() throws Throwable { // Using SSL server here since CookieStore API requires a secure schema. TestWebServer webServer = TestWebServer.startSsl();
diff --git a/ash/ash_strings_grd/IDS_ASH_PHONE_HUB_LOCATE_BUTTON_NOT_AVAILABLE_TOOLTIP.png.sha1 b/ash/ash_strings_grd/IDS_ASH_PHONE_HUB_LOCATE_BUTTON_NOT_AVAILABLE_TOOLTIP.png.sha1 index 834b4364..48675ec 100644 --- a/ash/ash_strings_grd/IDS_ASH_PHONE_HUB_LOCATE_BUTTON_NOT_AVAILABLE_TOOLTIP.png.sha1 +++ b/ash/ash_strings_grd/IDS_ASH_PHONE_HUB_LOCATE_BUTTON_NOT_AVAILABLE_TOOLTIP.png.sha1
@@ -1 +1 @@ -d7fa90d6f286617baaaef959c781bab2d64f43ad \ No newline at end of file +b0805735ec8f8c3fe148d54af99053ff89594236 \ No newline at end of file
diff --git a/ash/system/network/tray_network_state_model.cc b/ash/system/network/tray_network_state_model.cc index c71254c..7fc789b 100644 --- a/ash/system/network/tray_network_state_model.cc +++ b/ash/system/network/tray_network_state_model.cc
@@ -174,10 +174,10 @@ impl_->SetNetworkTypeEnabledState(type, enabled); } -bool TrayNetworkStateModel::IsBuiltinVpnEnabled() const { +bool TrayNetworkStateModel::IsBuiltinVpnProhibited() const { return TrayNetworkStateModel::GetDeviceState( chromeos::network_config::mojom::NetworkType::kVPN) == - chromeos::network_config::mojom::DeviceStateType::kEnabled; + chromeos::network_config::mojom::DeviceStateType::kProhibited; } chromeos::network_config::mojom::CrosNetworkConfig*
diff --git a/ash/system/network/tray_network_state_model.h b/ash/system/network/tray_network_state_model.h index 80e8f36..48d08064 100644 --- a/ash/system/network/tray_network_state_model.h +++ b/ash/system/network/tray_network_state_model.h
@@ -46,9 +46,9 @@ chromeos::network_config::mojom::NetworkType type, bool enabled); - // Returns true if built-in VPN is enabled. - // Note: Currently only built-in VPNs can be disabled by policy. - bool IsBuiltinVpnEnabled() const; + // Returns true if built-in VPN is prohibited. + // Note: Currently only built-in VPNs can be prohibited by policy. + bool IsBuiltinVpnProhibited() const; // This used to be inlined but now requires details from the Impl class. chromeos::network_config::mojom::CrosNetworkConfig* cros_network_config();
diff --git a/ash/system/network/vpn_feature_pod_controller.cc b/ash/system/network/vpn_feature_pod_controller.cc index d8973fc0..f53e8e3 100644 --- a/ash/system/network/vpn_feature_pod_controller.cc +++ b/ash/system/network/vpn_feature_pod_controller.cc
@@ -36,7 +36,7 @@ return true; // Note: At this point, only built-in VPNs are considered. - return model->IsBuiltinVpnEnabled() && model->has_vpn(); + return !model->IsBuiltinVpnProhibited() && model->has_vpn(); } } // namespace
diff --git a/ash/system/network/vpn_list_view.cc b/ash/system/network/vpn_list_view.cc index 8c70d3a1..1ad37729 100644 --- a/ash/system/network/vpn_list_view.cc +++ b/ash/system/network/vpn_list_view.cc
@@ -440,8 +440,8 @@ views::View* provider_view = nullptr; // Note: Currently only built-in VPNs can be disabled by policy. - bool vpn_enabled = - vpn_provider->type != VpnType::kOpenVPN || model()->IsBuiltinVpnEnabled(); + bool vpn_enabled = vpn_provider->type != VpnType::kOpenVPN || + !model()->IsBuiltinVpnProhibited(); provider_view = new VPNListProviderEntry(vpn_provider, list_empty_, vpn_name, vpn_enabled,
diff --git a/base/allocator/partition_allocator/partition_root.h b/base/allocator/partition_allocator/partition_root.h index e012c891..b236c35 100644 --- a/base/allocator/partition_allocator/partition_root.h +++ b/base/allocator/partition_allocator/partition_root.h
@@ -1102,7 +1102,18 @@ // a. Call to the thread cache, if it succeeds, go to step 3. // b. Otherwise, call the "raw" allocator <-- Locking // 3. Handle cookies/ref-count, zero allocation if required - size_t raw_size = AdjustSizeForExtrasAdd(requested_size); + + size_t raw_size = requested_size; +#if ENABLE_REF_COUNT_FOR_BACKUP_REF_PTR + // Without the size adjustment below, |Alloc()| returns a pointer past the end + // of a slot (most of the time a pointer to the beginning of the next slot) + // for zero-sized allocations when |PartitionRefCount| is used. The returned + // value may lead to incorrect results when passed to a function that performs + // bitwise operations on pointers, e.g., |PartitionAllocGetSlotOffset()|. + if (UNLIKELY(raw_size == 0)) + raw_size = 1; +#endif // ENABLE_REF_COUNT_FOR_BACKUP_REF_PTR + raw_size = AdjustSizeForExtrasAdd(raw_size); PA_CHECK(raw_size >= requested_size); // check for overflows uint16_t bucket_index = SizeToBucketIndex(raw_size);
diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java index b405d92..0f403f9 100644 --- a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java +++ b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
@@ -112,7 +112,7 @@ private final Object mNonMainDexLock = new Object(); // Mediates all communication between Linker instances in different processes. - private final MultiProcessMediator mMessageHandler = new MultiProcessMediator(); + private final MultiProcessMediator mMediator = new MultiProcessMediator(); // Guards all the fields below. private final Object mLock = new Object(); @@ -248,7 +248,7 @@ } public final MultiProcessMediator getMediator() { - return mMessageHandler; + return mMediator; } /**
diff --git a/base/files/important_file_writer.cc b/base/files/important_file_writer.cc index a4de2af9..1368e5b1 100644 --- a/base/files/important_file_writer.cc +++ b/base/files/important_file_writer.cc
@@ -124,12 +124,9 @@ if (tmp_file.IsValid()) { if (tmp_file.DeleteOnClose(true)) return; - // The file was opened with exclusive r/w access, so it would be very odd - // for this to fail. - UmaHistogramExactLinearWithSuffix( - "ImportantFile.DeleteOnCloseError", histogram_suffix, - -File::GetLastFileError(), -File::FILE_ERROR_MAX); - // Go ahead and close the file. The call to DeleteFile below will basically + // The file was opened with exclusive r/w access, so failures are primarily + // due to I/O errors or other phenomena out of the process's control. Go + // ahead and close the file. The call to DeleteFile below will basically // repeat the above, but maybe it will somehow succeed. tmp_file.Close(); }
diff --git a/base/memory/checked_ptr_unittest.cc b/base/memory/checked_ptr_unittest.cc index 064f48b..6d1bf09 100644 --- a/base/memory/checked_ptr_unittest.cc +++ b/base/memory/checked_ptr_unittest.cc
@@ -754,6 +754,26 @@ #endif // DCHECK_IS_ON() } +TEST(BackupRefPtrImpl, ZeroSized) { + // This test works only if GigaCage is enabled. Bail out otherwise. + if (!features::IsPartitionAllocGigaCageEnabled()) + return; + + // TODO(bartekn): Avoid using PartitionAlloc API directly. Switch to + // new/delete once PartitionAlloc Everywhere is fully enabled. + PartitionAllocGlobalInit(HandleOOM); + PartitionAllocator<ThreadSafe> allocator; + allocator.init({}); + + std::vector<CheckedPtr<void>> ptrs; + // Use a reasonable number of elements to fill up the slot span. + for (int i = 0; i < 128 * 1024; ++i) { + // Constructing a CheckedPtr instance from a zero-sized allocation should + // not result in a crash. + ptrs.emplace_back(allocator.root()->Alloc(0, "")); + } +} + #endif // BUILDFLAG(USE_PARTITION_ALLOC) && ENABLE_BACKUP_REF_PTR_IMPL && // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) } // namespace internal
diff --git a/base/strings/string16.cc b/base/strings/string16.cc index 64a5951..60f26f3 100644 --- a/base/strings/string16.cc +++ b/base/strings/string16.cc
@@ -4,86 +4,28 @@ #include "base/strings/string16.h" -#if defined(WCHAR_T_IS_UTF16) && !defined(_AIX) +#include <string> -#error This file should not be used on 2-byte wchar_t systems -// If this winds up being needed on 2-byte wchar_t systems, either the -// definitions below can be used, or the host system's wide character -// functions like wmemcmp can be wrapped. +#include "base/strings/utf_string_conversions.h" -#elif defined(WCHAR_T_IS_UTF32) - -#include <string.h> - -#include <ostream> - -#include "base/strings/string_piece.h" +#if defined(WCHAR_T_IS_UTF32) +std::ostream& std::operator<<(std::ostream& out, const std::u16string& str16) { + return out << base::UTF16ToUTF8(str16); +} +#endif namespace base { int c16memcmp(const char16* s1, const char16* s2, size_t n) { - // We cannot call memcmp because that changes the semantics. - while (n-- > 0) { - if (*s1 != *s2) { - // We cannot use (*s1 - *s2) because char16 is unsigned. - return ((*s1 < *s2) ? -1 : 1); - } - ++s1; - ++s2; - } - return 0; + return std::char_traits<char16>::compare(s1, s2, n); } size_t c16len(const char16* s) { - const char16 *s_orig = s; - while (*s) { - ++s; - } - return s - s_orig; -} - -const char16* c16memchr(const char16* s, char16 c, size_t n) { - while (n-- > 0) { - if (*s == c) { - return s; - } - ++s; - } - return nullptr; -} - -char16* c16memmove(char16* s1, const char16* s2, size_t n) { - return static_cast<char16*>(memmove(s1, s2, n * sizeof(char16))); + return std::char_traits<char16>::length(s); } char16* c16memcpy(char16* s1, const char16* s2, size_t n) { - return static_cast<char16*>(memcpy(s1, s2, n * sizeof(char16))); + return std::char_traits<char16>::copy(s1, s2, n); } -char16* c16memset(char16* s, char16 c, size_t n) { - char16 *s_orig = s; - while (n-- > 0) { - *s = c; - ++s; - } - return s_orig; -} - -namespace string16_internals { - -std::ostream& operator<<(std::ostream& out, const string16& str) { - return out << base::StringPiece16(str); -} - -void PrintTo(const string16& str, std::ostream* out) { - *out << str; -} - -} // namespace string16_internals - } // namespace base - -template class std:: - basic_string<base::char16, base::string16_internals::string16_char_traits>; - -#endif // WCHAR_T_IS_UTF32
diff --git a/base/strings/string16.h b/base/strings/string16.h index 3cb6c7c..212b01d 100644 --- a/base/strings/string16.h +++ b/base/strings/string16.h
@@ -31,6 +31,7 @@ #include <stdio.h> #include <functional> +#include <ostream> #include <string> #include "base/base_export.h" @@ -42,188 +43,40 @@ // a literal string. This indirection allows for an easier migration of // base::char16 to char16_t on platforms where WCHAR_T_IS_UTF16, as only a one // character change to the macro will be necessary. -// This macro does not exist when WCHAR_T_IS_UTF32, as it is currently not -// possible to create a char array form a literal in this case. // TODO(https://crbug.com/911896): Remove this macro once base::char16 is // char16_t on all platforms. #define STRING16_LITERAL(x) L##x namespace base { - -typedef wchar_t char16; -typedef std::wstring string16; - +using string16 = std::wstring; } // namespace base -#elif defined(WCHAR_T_IS_UTF32) +#else -#include <wchar.h> // for mbstate_t +#define STRING16_LITERAL(x) u##x + +namespace base { +using string16 = std::u16string; +} // namespace base + +// TODO(crbug.com/911896): Move this logging logic to base/logging.h. +namespace std { +BASE_EXPORT std::ostream& operator<<(std::ostream& out, + const std::u16string& str16); +} // namespace std + +#endif // WCHAR_T_IS_UTF16 namespace base { -typedef uint16_t char16; +using char16 = ::base::string16::value_type; -// char16 versions of the functions required by string16_char_traits; these -// are based on the wide character functions of similar names ("w" or "wcs" -// instead of "c16"). +// TODO(crbug.com/911896): Remove these functions in favor of using +// std::char_traits<base::char16> directly. BASE_EXPORT int c16memcmp(const char16* s1, const char16* s2, size_t n); BASE_EXPORT size_t c16len(const char16* s); -BASE_EXPORT const char16* c16memchr(const char16* s, char16 c, size_t n); -BASE_EXPORT char16* c16memmove(char16* s1, const char16* s2, size_t n); BASE_EXPORT char16* c16memcpy(char16* s1, const char16* s2, size_t n); -BASE_EXPORT char16* c16memset(char16* s, char16 c, size_t n); - -// This namespace contains the implementation of base::string16 along with -// things that need to be found via argument-dependent lookup from a -// base::string16. -namespace string16_internals { - -struct string16_char_traits { - typedef char16 char_type; - typedef int int_type; - - // int_type needs to be able to hold each possible value of char_type, and in - // addition, the distinct value of eof(). - static_assert(sizeof(int_type) > sizeof(char_type), - "int must be larger than 16 bits wide"); - - typedef std::streamoff off_type; - typedef mbstate_t state_type; - typedef std::fpos<state_type> pos_type; - - static void assign(char_type& c1, const char_type& c2) { - c1 = c2; - } - - static bool eq(const char_type& c1, const char_type& c2) { - return c1 == c2; - } - static bool lt(const char_type& c1, const char_type& c2) { - return c1 < c2; - } - - static int compare(const char_type* s1, const char_type* s2, size_t n) { - return c16memcmp(s1, s2, n); - } - - static size_t length(const char_type* s) { - return c16len(s); - } - - static const char_type* find(const char_type* s, size_t n, - const char_type& a) { - return c16memchr(s, a, n); - } - - static char_type* move(char_type* s1, const char_type* s2, size_t n) { - return c16memmove(s1, s2, n); - } - - static char_type* copy(char_type* s1, const char_type* s2, size_t n) { - return c16memcpy(s1, s2, n); - } - - static char_type* assign(char_type* s, size_t n, char_type a) { - return c16memset(s, a, n); - } - - static int_type not_eof(const int_type& c) { - return eq_int_type(c, eof()) ? 0 : c; - } - - static char_type to_char_type(const int_type& c) { - return char_type(c); - } - - static int_type to_int_type(const char_type& c) { - return int_type(c); - } - - static bool eq_int_type(const int_type& c1, const int_type& c2) { - return c1 == c2; - } - - static int_type eof() { - return static_cast<int_type>(EOF); - } -}; - -} // namespace string16_internals - -typedef std::basic_string<char16, - base::string16_internals::string16_char_traits> - string16; - -namespace string16_internals { - -BASE_EXPORT extern std::ostream& operator<<(std::ostream& out, - const string16& str); - -// This is required by googletest to print a readable output on test failures. -BASE_EXPORT extern void PrintTo(const string16& str, std::ostream* out); - -} // namespace string16_internals } // namespace base -// The string class will be explicitly instantiated only once, in string16.cc. -// -// std::basic_string<> in GNU libstdc++ contains a static data member, -// _S_empty_rep_storage, to represent empty strings. When an operation such -// as assignment or destruction is performed on a string, causing its existing -// data member to be invalidated, it must not be freed if this static data -// member is being used. Otherwise, it counts as an attempt to free static -// (and not allocated) data, which is a memory error. -// -// Generally, due to C++ template magic, _S_empty_rep_storage will be marked -// as a coalesced symbol, meaning that the linker will combine multiple -// instances into a single one when generating output. -// -// If a string class is used by multiple shared libraries, a problem occurs. -// Each library will get its own copy of _S_empty_rep_storage. When strings -// are passed across a library boundary for alteration or destruction, memory -// errors will result. GNU libstdc++ contains a configuration option, -// --enable-fully-dynamic-string (_GLIBCXX_FULLY_DYNAMIC_STRING), which -// disables the static data member optimization, but it's a good optimization -// and non-STL code is generally at the mercy of the system's STL -// configuration. Fully-dynamic strings are not the default for GNU libstdc++ -// libstdc++ itself or for the libstdc++ installations on the systems we care -// about, such as Mac OS X and relevant flavors of Linux. -// -// See also http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24196 . -// -// To avoid problems, string classes need to be explicitly instantiated only -// once, in exactly one library. All other string users see it via an "extern" -// declaration. This is precisely how GNU libstdc++ handles -// std::basic_string<char> (string) and std::basic_string<wchar_t> (wstring). -// -// This also works around a Mac OS X linker bug in ld64-85.2.1 (Xcode 3.1.2), -// in which the linker does not fully coalesce symbols when dead code -// stripping is enabled. This bug causes the memory errors described above -// to occur even when a std::basic_string<> does not cross shared library -// boundaries, such as in statically-linked executables. -// -// TODO(mark): File this bug with Apple and update this note with a bug number. - -extern template class BASE_EXPORT - std::basic_string<base::char16, - base::string16_internals::string16_char_traits>; - -// Specialize std::hash for base::string16. Although the style guide forbids -// this in general, it is necessary for consistency with WCHAR_T_IS_UTF16 -// platforms, where base::string16 is a type alias for std::wstring. -namespace std { -template <> -struct hash<base::string16> { - std::size_t operator()(const base::string16& s) const { - std::size_t result = 0; - for (base::char16 c : s) - result = (result * 131) + c; - return result; - } -}; -} // namespace std - -#endif // WCHAR_T_IS_UTF32 - #endif // BASE_STRINGS_STRING16_H_
diff --git a/base/strings/string16_unittest.cc b/base/strings/string16_unittest.cc index 0e41864..5c020e2a 100644 --- a/base/strings/string16_unittest.cc +++ b/base/strings/string16_unittest.cc
@@ -13,13 +13,15 @@ namespace base { -#if defined(WCHAR_T_IS_UTF16) TEST(String16Test, String16Literal) { static constexpr char16 kHelloWorld[] = STRING16_LITERAL("Hello, World"); + constexpr StringPiece16 kPiece = kHelloWorld; + static_assert(kHelloWorld == kPiece, ""); + static_assert(kHelloWorld == kPiece.data(), ""); + string16 hello_world = kHelloWorld; EXPECT_EQ(kHelloWorld, hello_world); } -#endif // We define a custom operator<< for string16 so we can use it with logging. // This tests that conversion.
diff --git a/base/task/sequence_manager/task_queue_impl.cc b/base/task/sequence_manager/task_queue_impl.cc index e4c9b00..b85c644 100644 --- a/base/task/sequence_manager/task_queue_impl.cc +++ b/base/task/sequence_manager/task_queue_impl.cc
@@ -1402,36 +1402,44 @@ void TaskQueueImpl::DelayedIncomingQueue::SweepCancelledTasks( SequenceManagerImpl* sequence_manager) { - // Under the hood a std::priority_queue is a heap and usually it's built on - // top of a std::vector. We poke at that vector directly here to filter out - // canceled tasks in place. + pending_high_res_tasks_ -= queue_.SweepCancelledTasks(sequence_manager); +} + +size_t TaskQueueImpl::DelayedIncomingQueue::PQueue::SweepCancelledTasks( + SequenceManagerImpl* sequence_manager) { + // Under the hood a std::priority_queue is a heap implemented top of a + // std::vector. We poke at that vector directly here to filter out canceled + // tasks in place. bool task_deleted = false; - auto it = queue_.c.begin(); - while (!queue_.c.empty() && it != queue_.c.end()) { - // TODO(crbug.com/1155905): Remove after figuring out the cause of the - // crash. - sequence_manager->RecordCrashKeys(*it); - if (it->task.IsCancelled()) { - if (it->is_high_res) - pending_high_res_tasks_--; - *it = std::move(queue_.c.back()); - queue_.c.pop_back(); - task_deleted = true; - // Note: if we just removed the last task in the queue, |it| is now - // invalid and shouldn't be used. - } else { - it++; - } - } + size_t num_high_res_tasks_swept = 0u; + auto is_cancelled = [sequence_manager, &num_high_res_tasks_swept, + &task_deleted](const Task& task) { + // TODO(crbug.com/1155905): Remove after figuring out + // the cause of the crash. + sequence_manager->RecordCrashKeys(task); + if (!task.task.IsCancelled()) + return false; + if (task.is_high_res) + num_high_res_tasks_swept++; + task_deleted = true; + return true; + }; + c.erase(std::remove_if(c.begin(), c.end(), is_cancelled), c.end()); // If we deleted something, re-enforce the heap property. if (task_deleted) - ranges::make_heap(queue_.c, queue_.comp); + ranges::make_heap(c, comp); + return num_high_res_tasks_swept; } Value TaskQueueImpl::DelayedIncomingQueue::AsValue(TimeTicks now) const { + return queue_.AsValue(now); +} + +Value TaskQueueImpl::DelayedIncomingQueue::PQueue::AsValue( + TimeTicks now) const { Value state(Value::Type::LIST); - for (const Task& task : queue_.c) + for (const Task& task : c) state.Append(TaskAsValue(task, now)); return state; }
diff --git a/base/task/sequence_manager/task_queue_impl.h b/base/task/sequence_manager/task_queue_impl.h index 8265ee6..82e5b58 100644 --- a/base/task/sequence_manager/task_queue_impl.h +++ b/base/task/sequence_manager/task_queue_impl.h
@@ -332,9 +332,14 @@ private: struct PQueue : public std::priority_queue<Task> { - // Expose the container and comparator. - using std::priority_queue<Task>::c; - using std::priority_queue<Task>::comp; + // Removes all cancelled tasks from the queue. Returns the number of + // removed high resolution tasks (which could be lower than the total + // number of removed tasks). + // + // TODO(crbug.com/1155905): we pass SequenceManager to be able to record + // crash keys. Remove this parameter after chasing down this crash. + size_t SweepCancelledTasks(SequenceManagerImpl* sequence_manager); + Value AsValue(TimeTicks now) const; }; PQueue queue_;
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h index 116eafeff..4926ea1e 100644 --- a/base/threading/thread_restrictions.h +++ b/base/threading/thread_restrictions.h
@@ -150,13 +150,14 @@ class BrowserTestBase; class CategorizedWorkerPool; class DesktopCaptureDevice; +class EmergencyTraceFinalisationCoordinator; class InProcessUtilityThread; class NestedMessagePumpAndroid; class NetworkServiceInstancePrivate; class PepperPrintSettingsManagerImpl; +class RTCVideoDecoder; class RenderProcessHostImpl; class RenderWidgetHostViewMac; -class RTCVideoDecoder; class SandboxHostLinux; class ScopedAllowWaitForDebugURL; class ServiceWorkerContextClient; @@ -530,6 +531,7 @@ friend class cc::TileTaskManagerImpl; friend class content::CategorizedWorkerPool; friend class content::DesktopCaptureDevice; + friend class content::EmergencyTraceFinalisationCoordinator; friend class content::InProcessUtilityThread; friend class content::RTCVideoDecoder; friend class content::SandboxHostLinux;
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 6d69793f..3629cf1 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -0.20210107.2.1 +0.20210108.1.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 6d69793f..3629cf1 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -0.20210107.2.1 +0.20210108.1.1
diff --git a/chrome/VERSION b/chrome/VERSION index eaff515..e372072 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=89 MINOR=0 -BUILD=4382 +BUILD=4383 PATCH=0
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index c5fd07d..1337737 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -1213,7 +1213,6 @@ "java/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProvider.java", "java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivity.java", "java/src/org/chromium/chrome/browser/services/AccountsChangedReceiver.java", - "java/src/org/chromium/chrome/browser/services/AndroidChildAccountHelper.java", "java/src/org/chromium/chrome/browser/services/gcm/ChromeGcmListenerServiceImpl.java", "java/src/org/chromium/chrome/browser/services/gcm/GCMBackgroundServiceImpl.java", "java/src/org/chromium/chrome/browser/services/gcm/GCMBackgroundTask.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni index d862b63a..3e2c05e 100644 --- a/chrome/android/chrome_junit_test_java_sources.gni +++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -44,6 +44,7 @@ "junit/src/org/chromium/chrome/browser/browserservices/ui/view/DisclosureInfobarTest.java", "junit/src/org/chromium/chrome/browser/browserservices/ui/view/DisclosureNotificationTest.java", "junit/src/org/chromium/chrome/browser/browserservices/ui/view/DisclosureSnackbarTest.java", + "junit/src/org/chromium/chrome/browser/childaccounts/ChildAccountServiceTest.java", "junit/src/org/chromium/chrome/browser/compositor/CompositorSurfaceManagerImplTest.java", "junit/src/org/chromium/chrome/browser/compositor/CompositorViewHolderUnitTest.java", "junit/src/org/chromium/chrome/browser/compositor/layouts/SceneOverlayTest.java",
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java index 7aeca2b..83dc4e5 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
@@ -384,6 +384,20 @@ return chip; } + /** + * Creates a feedback button button. It shows the feedback form and then *directly* executes + * {@code actionIndex}. + */ + @CalledByNative + private AssistantChip createFeedbackButton(int icon, String text, int actionIndex, + boolean disabled, boolean sticky, boolean visible, + @Nullable String contentDescription) { + AssistantChip chip = AssistantChip.createHairlineAssistantChip( + icon, text, disabled, sticky, visible, contentDescription); + chip.setSelectedListener(() -> safeNativeOnFeedbackButtonClicked(actionIndex)); + return chip; + } + // TODO(arbesser): Remove this and use methods in {@code AssistantChip} instead. @CalledByNative private static void appendChipToList(List<AssistantChip> chips, AssistantChip chip) { @@ -461,6 +475,13 @@ } } + private void safeNativeOnFeedbackButtonClicked(int index) { + if (mNativeUiController != 0) { + AutofillAssistantUiControllerJni.get().onFeedbackButtonClicked( + mNativeUiController, AutofillAssistantUiController.this, index); + } + } + private void safeNativeOnKeyboardVisibilityChanged(boolean visible) { if (mNativeUiController != 0) { AutofillAssistantUiControllerJni.get().onKeyboardVisibilityChanged( @@ -503,6 +524,8 @@ long nativeUiControllerAndroid, AutofillAssistantUiController caller, int index); void onCloseButtonClicked( long nativeUiControllerAndroid, AutofillAssistantUiController caller); + void onFeedbackButtonClicked( + long nativeUiControllerAndroid, AutofillAssistantUiController caller, int index); void onKeyboardVisibilityChanged(long nativeUiControllerAndroid, AutofillAssistantUiController caller, boolean visible); void setVisible(long nativeUiControllerAndroid, AutofillAssistantUiController caller,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/childaccounts/ChildAccountService.java b/chrome/android/java/src/org/chromium/chrome/browser/childaccounts/ChildAccountService.java index 891a578..4a192210 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/childaccounts/ChildAccountService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/childaccounts/ChildAccountService.java
@@ -7,12 +7,14 @@ import android.accounts.Account; import android.app.Activity; -import org.chromium.base.Callback; +import androidx.annotation.MainThread; + import org.chromium.base.ThreadUtils; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.NativeMethods; import org.chromium.base.task.PostTask; import org.chromium.components.signin.AccountManagerFacade; +import org.chromium.components.signin.AccountManagerFacade.ChildAccountStatusListener; import org.chromium.components.signin.AccountManagerFacadeProvider; import org.chromium.components.signin.AccountUtils; import org.chromium.components.signin.ChildAccountStatus; @@ -38,19 +40,30 @@ } /** - * Checks for the presence of child accounts on the device. + * Checks the child account status on device. * - * @param callback A callback which will be called with a @ChildAccountStatus.Status value. + * Since child accounts cannot share a device, the listener will be invoked with the status + * {@link ChildAccountStatus#NOT_CHILD} if there are no accounts or more than one account on + * device. If there is a single account on device, the listener will be passed to + * {@link AccountManagerFacade#checkChildAccountStatus} to check the child account status of + * the account. + * + * It should be safe to invoke this method before the native library is initialized (after + * AccountManagerFacade is set). + * + * @param listener The listener is called when the {@link ChildAccountStatus.Status} is ready. */ - public static void checkChildAccountStatus(final Callback<Integer> callback) { + @MainThread + public static void checkChildAccountStatus(ChildAccountStatusListener listener) { ThreadUtils.assertOnUiThread(); - final AccountManagerFacade accountManager = AccountManagerFacadeProvider.getInstance(); - accountManager.tryGetGoogleAccounts(accounts -> { - if (accounts.size() != 1) { + final AccountManagerFacade accountManagerFacade = + AccountManagerFacadeProvider.getInstance(); + accountManagerFacade.tryGetGoogleAccounts(accounts -> { + if (accounts.size() == 1) { // Child accounts can't share a device. - callback.onResult(ChildAccountStatus.NOT_CHILD); + accountManagerFacade.checkChildAccountStatus(accounts.get(0), listener); } else { - accountManager.checkChildAccountStatus(accounts.get(0), callback); + listener.onStatusReady(ChildAccountStatus.NOT_CHILD); } }); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java index 1114264..da1b36c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java
@@ -22,11 +22,11 @@ import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.LaunchIntentDispatcher; +import org.chromium.chrome.browser.childaccounts.ChildAccountService; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.locale.LocaleManager; import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings; import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.chrome.browser.services.AndroidChildAccountHelper; import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; import org.chromium.chrome.browser.signin.services.SigninManager; import org.chromium.chrome.browser.vr.VrModuleProvider; @@ -77,15 +77,12 @@ } long childAccountStatusStart = SystemClock.elapsedRealtime(); - new AndroidChildAccountHelper() { - @Override - public void onParametersReady() { - RecordHistogram.recordTimesHistogram("MobileFre.ChildAccountStatusDuration", - SystemClock.elapsedRealtime() - childAccountStatusStart); - initializeSharedState(getChildAccountStatus()); - processFreEnvironmentPreNative(); - } - }.start(); + ChildAccountService.checkChildAccountStatus(status -> { + RecordHistogram.recordTimesHistogram("MobileFre.ChildAccountStatusDuration", + SystemClock.elapsedRealtime() - childAccountStatusStart); + initializeSharedState(status); + processFreEnvironmentPreNative(); + }); } @VisibleForTesting
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ForcedSigninProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ForcedSigninProcessor.java index 75266016..3e0c60f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ForcedSigninProcessor.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ForcedSigninProcessor.java
@@ -10,8 +10,8 @@ import org.chromium.base.Log; import org.chromium.chrome.browser.SyncFirstSetupCompleteSource; +import org.chromium.chrome.browser.childaccounts.ChildAccountService; import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.chrome.browser.services.AndroidChildAccountHelper; import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; import org.chromium.chrome.browser.signin.services.SigninManager; import org.chromium.chrome.browser.sync.ProfileSyncService; @@ -48,16 +48,13 @@ * changes with early exit if an account has already been signed in. */ public static void start(@Nullable final Runnable onComplete) { - new AndroidChildAccountHelper() { - @Override - public void onParametersReady() { - boolean hasChildAccount = ChildAccountStatus.isChild(getChildAccountStatus()); - AccountManagementFragment.setSignOutAllowedPreferenceValue(!hasChildAccount); - if (hasChildAccount) { - processForcedSignIn(onComplete); - } + ChildAccountService.checkChildAccountStatus(status -> { + boolean hasChildAccount = ChildAccountStatus.isChild(status); + AccountManagementFragment.setSignOutAllowedPreferenceValue(!hasChildAccount); + if (hasChildAccount) { + processForcedSignIn(onComplete); } - }.start(); + }); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/services/AndroidChildAccountHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/services/AndroidChildAccountHelper.java deleted file mode 100644 index 6f6c62a..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/services/AndroidChildAccountHelper.java +++ /dev/null
@@ -1,43 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.services; - -import org.chromium.base.Callback; -import org.chromium.chrome.browser.childaccounts.ChildAccountService; -import org.chromium.components.signin.ChildAccountStatus; - -/** - * A helper for child account checks. - * Usage: - * new AndroidChildAccountHelper() { override onParametersReady() }.start(appContext). - */ -public abstract class AndroidChildAccountHelper implements Callback<Integer> { - private @ChildAccountStatus.Status Integer mChildAccountStatus; - - /** The callback called when child account parameters are known. */ - public abstract void onParametersReady(); - - /** @return The status of the device regarding child accounts. */ - protected @ChildAccountStatus.Status int getChildAccountStatus() { - return mChildAccountStatus; - } - - /** - * Starts fetching the child accounts information. - * Calls onParametersReady() once the information is fetched. - */ - public void start() { - ChildAccountService.checkChildAccountStatus(this); - } - - // Callback<Integer>: - @Override - public void onResult(@ChildAccountStatus.Status Integer status) { - mChildAccountStatus = status; - if (mChildAccountStatus != null) { - onParametersReady(); - } - } -}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/childaccounts/ChildAccountServiceTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/childaccounts/ChildAccountServiceTest.java new file mode 100644 index 0000000..18240c5 --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/childaccounts/ChildAccountServiceTest.java
@@ -0,0 +1,98 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.childaccounts; + +import static org.mockito.Mockito.verify; + +import android.accounts.Account; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule; +import org.chromium.components.signin.AccountManagerFacade.ChildAccountStatusListener; +import org.chromium.components.signin.AccountUtils; +import org.chromium.components.signin.ChildAccountStatus; +import org.chromium.components.signin.test.util.FakeAccountManagerFacade; + +/** + * Unit tests for {@link ChildAccountService}. + */ +@RunWith(BaseRobolectricTestRunner.class) +public class ChildAccountServiceTest { + private static final Account CHILD_ACCOUNT = + AccountUtils.createAccountFromName("child.account@gmail.com"); + + private final FakeAccountManagerFacade mFakeFacade = new FakeAccountManagerFacade(null) { + @Override + public void checkChildAccountStatus(Account account, ChildAccountStatusListener listener) { + listener.onStatusReady(account.name.startsWith("child") + ? ChildAccountStatus.REGULAR_CHILD + : ChildAccountStatus.NOT_CHILD); + } + }; + + @Rule + public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + + @Rule + public final AccountManagerTestRule mAccountManagerTestRule = + new AccountManagerTestRule(mFakeFacade); + + @Mock + private ChildAccountStatusListener mListenerMock; + + @Test + public void testChildAccountStatusWhenNoAccountsOnDevice() { + ChildAccountService.checkChildAccountStatus(mListenerMock); + verify(mListenerMock).onStatusReady(ChildAccountStatus.NOT_CHILD); + } + + @Test + public void testChildAccountStatusWhenTwoChildAccountsOnDevice() { + // For product reason, child account cannot share device, so as long + // as more than one account detected on device, the child account status + // on device should be NOT_CHILD. + mAccountManagerTestRule.addAccount(CHILD_ACCOUNT); + mAccountManagerTestRule.addAccount("child.account2@gmail.com"); + ChildAccountService.checkChildAccountStatus(mListenerMock); + verify(mListenerMock).onStatusReady(ChildAccountStatus.NOT_CHILD); + } + + @Test + public void testChildAccountStatusWhenOneChildAndOneAdultAccountsOnDevice() { + mAccountManagerTestRule.addAccount(CHILD_ACCOUNT); + mAccountManagerTestRule.addAccount("adult.account@gmail.com"); + ChildAccountService.checkChildAccountStatus(mListenerMock); + verify(mListenerMock).onStatusReady(ChildAccountStatus.NOT_CHILD); + } + + @Test + public void testChildAccountStatusWhenTwoAdultAccountsOnDevice() { + mAccountManagerTestRule.addAccount("adult.account1@gmail.com"); + mAccountManagerTestRule.addAccount("adult.account2@gmail.com"); + ChildAccountService.checkChildAccountStatus(mListenerMock); + verify(mListenerMock).onStatusReady(ChildAccountStatus.NOT_CHILD); + } + + @Test + public void testChildAccountStatusWhenOnlyOneAdultAccountOnDevice() { + mAccountManagerTestRule.addAccount("adult.account1@gmail.com"); + ChildAccountService.checkChildAccountStatus(mListenerMock); + verify(mListenerMock).onStatusReady(ChildAccountStatus.NOT_CHILD); + } + + @Test + public void testChildAccountStatusWhenOnlyOneChildAccountOnDevice() { + mAccountManagerTestRule.addAccount(CHILD_ACCOUNT); + ChildAccountService.checkChildAccountStatus(mListenerMock); + verify(mListenerMock).onStatusReady(ChildAccountStatus.REGULAR_CHILD); + } +} \ No newline at end of file
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerTest.java index 9903ddb..7e71670 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerTest.java
@@ -59,8 +59,9 @@ @Rule public final Features.JUnitProcessor processor = new Features.JUnitProcessor(); - private static final AccountInfo ACCOUNT_INFO = new AccountInfo( - new CoreAccountId("gaia-id-user"), "user@domain.com", "gaia-id-user", null); + private static final AccountInfo ACCOUNT_INFO = + new AccountInfo(new CoreAccountId("gaia-id-user"), "user@domain.com", "gaia-id-user", + "full name", "given name", null); private final SigninManagerImpl.Natives mNativeMock = mock(SigninManagerImpl.Natives.class); private final AccountTrackerService mAccountTrackerService = mock(AccountTrackerService.class); @@ -335,7 +336,7 @@ @Test public void callbackNotifiedOnSignin() { AccountInfo account = new AccountInfo(new CoreAccountId("test_at_gmail.com"), - "test@gmail.com", "test_at_gmail.com", null); + "test@gmail.com", "test_at_gmail.com", "full name", "given name", null); // No need to seed accounts to the native code. doReturn(true).when(mAccountTrackerService).checkAndSeedSystemAccounts(); @@ -370,7 +371,7 @@ @Test(expected = AssertionError.class) public void failIfAlreadySignedin() { AccountInfo account = new AccountInfo(new CoreAccountId("test_at_gmail.com"), - "test@gmail.com", "test_at_gmail.com", null); + "test@gmail.com", "test_at_gmail.com", "full name", "given name", null); // No need to seed accounts to the native code. doReturn(true).when(mAccountTrackerService).checkAndSeedSystemAccounts();
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt index 8835c567..e0d2f42 100644 --- a/chrome/android/profiles/newest.txt +++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-89.0.4380.0_rc-r1-merged.afdo.bz2 +chromeos-chrome-amd64-89.0.4381.0_rc-r1-merged.afdo.bz2
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index c50fad4..89e618b5 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -1228,6 +1228,7 @@ "policy/messaging_layer/storage/resources/resource_interface.h", "policy/messaging_layer/storage/storage.cc", "policy/messaging_layer/storage/storage.h", + "policy/messaging_layer/storage/storage_configuration.cc", "policy/messaging_layer/storage/storage_configuration.h", "policy/messaging_layer/storage/storage_module.cc", "policy/messaging_layer/storage/storage_module.h",
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.cc b/chrome/browser/android/autofill_assistant/ui_controller_android.cc index 334bf20c..98f058f 100644 --- a/chrome/browser/android/autofill_assistant/ui_controller_android.cc +++ b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
@@ -751,6 +751,18 @@ : nullptr); break; + case FEEDBACK_ACTION: + // A "Send feedback" button which will show the feedback form before + // executing the action. + jchip = Java_AutofillAssistantUiController_createFeedbackButton( + env, java_object_, chip.icon, + ConvertUTF8ToJavaString(env, chip.text), i, !action.enabled(), + chip.sticky, chip.visible, + chip.is_content_description_set + ? ConvertUTF8ToJavaString(env, chip.content_description) + : nullptr); + break; + case CANCEL_ACTION: // A Cancel button sneaks in an UNDO snackbar before executing the // action, while a close button behaves like a normal button. @@ -856,6 +868,22 @@ DestroySelf(); } +void UiControllerAndroid::OnFeedbackButtonClicked( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcaller, + jint index) { + // Show the feedback form then directly run the associated action. + // Unfortunately there is no way to associate a callback to run after the user + // actually sent (or close) the form, so we have to continue directly after + // showing it. It should be good enough, given that in most use cases we will + // directly stop. + Java_AutofillAssistantUiController_showFeedback( + env, java_object_, + ConvertUTF8ToJavaString(env, ui_delegate_->GetDebugContext())); + + OnUserActionSelected(env, jcaller, index); +} + void UiControllerAndroid::OnKeyboardVisibilityChanged( JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller,
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.h b/chrome/browser/android/autofill_assistant/ui_controller_android.h index ca52983..9f03a66 100644 --- a/chrome/browser/android/autofill_assistant/ui_controller_android.h +++ b/chrome/browser/android/autofill_assistant/ui_controller_android.h
@@ -194,6 +194,10 @@ void OnCloseButtonClicked( JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller); + void OnFeedbackButtonClicked( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcaller, + jint actionIndex); void OnKeyboardVisibilityChanged( JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller,
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android_utils.cc b/chrome/browser/android/autofill_assistant/ui_controller_android_utils.cc index 2b2fa51..241d351 100644 --- a/chrome/browser/android/autofill_assistant/ui_controller_android_utils.cc +++ b/chrome/browser/android/autofill_assistant/ui_controller_android_utils.cc
@@ -445,6 +445,7 @@ case NORMAL_ACTION: case CANCEL_ACTION: case CLOSE_ACTION: + case FEEDBACK_ACTION: return Java_AssistantChip_createHairlineAssistantChip( env, chip.icon(), base::android::ConvertUTF8ToJavaString(env, chip.text()),
diff --git a/chrome/browser/android/webapps/add_to_homescreen_mediator.cc b/chrome/browser/android/webapps/add_to_homescreen_mediator.cc index 84b78ca..7f063e6 100644 --- a/chrome/browser/android/webapps/add_to_homescreen_mediator.cc +++ b/chrome/browser/android/webapps/add_to_homescreen_mediator.cc
@@ -16,11 +16,9 @@ #include "chrome/browser/banners/app_banner_manager_android.h" #include "chrome/browser/banners/app_banner_metrics.h" #include "chrome/browser/banners/app_banner_settings_helper.h" -#include "chrome/browser/feature_engagement/tracker_factory.h" -#include "components/feature_engagement/public/event_constants.h" -#include "components/feature_engagement/public/tracker.h" #include "components/url_formatter/elide_url.h" #include "components/webapps/installable/installable_metrics.h" +#include "components/webapps/webapps_client.h" #include "content/public/browser/web_contents.h" #include "ui/gfx/android/java_bitmap.h" @@ -216,11 +214,8 @@ entry, AppTypeToMenuEntry::kAppTypeFinalEntry); if (is_webapk) { - DVLOG(2) << "Sending event: IPH used for Installing PWA"; - feature_engagement::Tracker* tracker = - feature_engagement::TrackerFactory::GetForBrowserContext( - data_fetcher_->web_contents()->GetBrowserContext()); - tracker->NotifyEvent(feature_engagement::events::kPwaInstallMenuSelected); + webapps::WebappsClient::Get()->OnWebApkInstallInitiatedFromAppMenu( + data_fetcher_->web_contents()); } }
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 243572a..b7c489d 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -209,6 +209,8 @@ <include name="IDR_SYNC_CONFIRMATION_APP_JS" file="${root_gen_dir}\chrome\browser\resources\signin\sync_confirmation\sync_confirmation_app.js" use_base_dir="false" preprocess="true" type="BINDATA" /> <include name="IDR_SYNC_CONFIRMATION_IMAGES_SYNC_CONFIRMATION_ILLUSTRATION_SVG" file="resources\signin\sync_confirmation\images\sync_confirmation_illustration.svg" type="BINDATA" /> <include name="IDR_SYNC_CONFIRMATION_IMAGES_SYNC_CONFIRMATION_ILLUSTRATION_DARK_SVG" file="resources\signin\sync_confirmation\images\sync_confirmation_illustration_dark.svg" type="BINDATA" /> + <include name="IDR_SYNC_CONFIRMATION_IMAGES_SYNC_CONFIRMATION_REFRESHED_ILLUSTRATION_SVG" file="resources\signin\sync_confirmation\images\sync_confirmation_refreshed_illustration.svg" type="BINDATA" /> + <include name="IDR_SYNC_CONFIRMATION_IMAGES_SYNC_CONFIRMATION_REFRESHED_ILLUSTRATION_DARK_SVG" file="resources\signin\sync_confirmation\images\sync_confirmation_refreshed_illustration_dark.svg" type="BINDATA" /> </if> <if expr="is_win or is_macosx or desktop_linux"> <include name="IDR_SIGNIN_DICE_WEB_INTERCEPT_HTML" file="resources\signin\dice_web_signin_intercept\dice_web_signin_intercept.html" type="BINDATA" />
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 1ca05604..c4647ab 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -408,6 +408,7 @@ #include "ash/public/cpp/tablet_mode.h" #include "chrome/app/chrome_crash_reporter_client.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/browser_process_platform_part.h" #include "chrome/browser/chromeos/arc/fileapi/arc_content_file_system_backend_delegate.h" #include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_backend_delegate.h" #include "chrome/browser/chromeos/chrome_browser_main_chromeos.h" @@ -425,6 +426,7 @@ #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" #include "chrome/browser/chromeos/policy/policy_cert_service_factory.h" #include "chrome/browser/chromeos/policy/system_features_disable_list_policy_handler.h" +#include "chrome/browser/chromeos/policy/system_proxy_manager.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/smb_client/fileapi/smbfs_file_system_backend_delegate.h" #include "chrome/browser/chromeos/system/input_device_settings.h" @@ -5095,6 +5097,21 @@ scoped_refptr<net::HttpResponseHeaders> response_headers, bool first_auth_attempt, LoginAuthRequiredCallback auth_required_callback) { +#if BUILDFLAG(IS_CHROMEOS_ASH) + policy::SystemProxyManager* system_proxy_manager = + g_browser_process->platform_part() + ->browser_policy_connector_chromeos() + ->GetSystemProxyManager(); + // For Managed Guest Session and Kiosk devices, the credentials configured + // via the policy SystemProxySettings may be used for proxy authentication. + // Note: |system_proxy_manager| may be missing in tests. + if (system_proxy_manager && system_proxy_manager->CanUsePolicyCredentials( + auth_info, first_auth_attempt)) { + return system_proxy_manager->CreateLoginDelegate( + std::move(auth_required_callback)); + } +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + // For subresources, create a LoginHandler directly, which may show a login // prompt to the user. Main frame resources go through LoginTabHelper, which // manages a more complicated flow to avoid confusion about which website is
diff --git a/chrome/browser/chromeos/crosapi/account_manager_ash.cc b/chrome/browser/chromeos/crosapi/account_manager_ash.cc index 65665ee..63c924c 100644 --- a/chrome/browser/chromeos/crosapi/account_manager_ash.cc +++ b/chrome/browser/chromeos/crosapi/account_manager_ash.cc
@@ -13,10 +13,8 @@ namespace crosapi { -AccountManagerAsh::AccountManagerAsh( - chromeos::AccountManager* account_manager, - mojo::PendingReceiver<mojom::AccountManager> receiver) - : account_manager_(account_manager), receiver_(this, std::move(receiver)) { +AccountManagerAsh::AccountManagerAsh(chromeos::AccountManager* account_manager) + : account_manager_(account_manager) { DCHECK(account_manager_); account_manager_->AddObserver(this); } @@ -25,6 +23,11 @@ account_manager_->RemoveObserver(this); } +void AccountManagerAsh::BindReceiver( + mojo::PendingReceiver<mojom::AccountManager> receiver) { + receivers_.Add(this, std::move(receiver)); +} + void AccountManagerAsh::IsInitialized(IsInitializedCallback callback) { std::move(callback).Run(account_manager_->IsInitialized()); }
diff --git a/chrome/browser/chromeos/crosapi/account_manager_ash.h b/chrome/browser/chromeos/crosapi/account_manager_ash.h index 6e79a8e..73529ea 100644 --- a/chrome/browser/chromeos/crosapi/account_manager_ash.h +++ b/chrome/browser/chromeos/crosapi/account_manager_ash.h
@@ -10,7 +10,7 @@ #include "chromeos/crosapi/mojom/account_manager.mojom.h" #include "components/account_manager_core/account.h" #include "mojo/public/cpp/bindings/pending_receiver.h" -#include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/receiver_set.h" #include "mojo/public/cpp/bindings/remote_set.h" namespace crosapi { @@ -21,12 +21,13 @@ class AccountManagerAsh : public mojom::AccountManager, public chromeos::AccountManager::Observer { public: - AccountManagerAsh(chromeos::AccountManager* account_manager, - mojo::PendingReceiver<mojom::AccountManager> receiver); + explicit AccountManagerAsh(chromeos::AccountManager* account_manager); AccountManagerAsh(const AccountManagerAsh&) = delete; AccountManagerAsh& operator=(const AccountManagerAsh&) = delete; ~AccountManagerAsh() override; + void BindReceiver(mojo::PendingReceiver<mojom::AccountManager> receiver); + // crosapi::mojom::AccountManager: void IsInitialized(IsInitializedCallback callback) override; void AddObserver(AddObserverCallback callback) override; @@ -42,7 +43,7 @@ void FlushMojoForTesting(); chromeos::AccountManager* const account_manager_; - mojo::Receiver<mojom::AccountManager> receiver_; + mojo::ReceiverSet<mojom::AccountManager> receivers_; mojo::RemoteSet<mojom::AccountManagerObserver> observers_; };
diff --git a/chrome/browser/chromeos/crosapi/account_manager_ash_unittest.cc b/chrome/browser/chromeos/crosapi/account_manager_ash_unittest.cc index 0e2bf03..d4f6b433 100644 --- a/chrome/browser/chromeos/crosapi/account_manager_ash_unittest.cc +++ b/chrome/browser/chromeos/crosapi/account_manager_ash_unittest.cc
@@ -93,8 +93,9 @@ protected: void SetUp() override { - account_manager_ash_ = std::make_unique<AccountManagerAsh>( - &account_manager_, remote_.BindNewPipeAndPassReceiver()); + account_manager_ash_ = + std::make_unique<AccountManagerAsh>(&account_manager_); + account_manager_ash_->BindReceiver(remote_.BindNewPipeAndPassReceiver()); account_manager_async_waiter_ = std::make_unique<mojom::AccountManagerAsyncWaiter>( account_manager_ash_.get());
diff --git a/chrome/browser/chromeos/crosapi/ash_chrome_service_impl.cc b/chrome/browser/chromeos/crosapi/ash_chrome_service_impl.cc index 41f78ad..9bdadfc2 100644 --- a/chrome/browser/chromeos/crosapi/ash_chrome_service_impl.cc +++ b/chrome/browser/chromeos/crosapi/ash_chrome_service_impl.cc
@@ -62,35 +62,38 @@ void AshChromeServiceImpl::BindAccountManager( mojo::PendingReceiver<mojom::AccountManager> receiver) { - DVLOG(1) << "Binding AccountManager receiver"; - // Assumptions: - // 1. TODO(https://crbug.com/1102768): Multi-Signin / Fast-User-Switching is - // disabled. - // 2. ash-chrome has 1 and only 1 "regular" |Profile|. + // TODO(https://crrev.com/c/2601750): Move AccountManagerAsh ownership to + // chromeos::AccountManager. + if (!account_manager_ash_) { + // Assumptions: + // 1. TODO(https://crbug.com/1102768): Multi-Signin / Fast-User-Switching is + // disabled. + // 2. ash-chrome has 1 and only 1 "regular" |Profile|. #if DCHECK_IS_ON() - int num_regular_profiles = 0; - for (const Profile* profile : - g_browser_process->profile_manager()->GetLoadedProfiles()) { - if (chromeos::ProfileHelper::IsRegularProfile(profile)) - num_regular_profiles++; - } - DCHECK_EQ(1, num_regular_profiles); + int num_regular_profiles = 0; + for (const Profile* profile : + g_browser_process->profile_manager()->GetLoadedProfiles()) { + if (chromeos::ProfileHelper::IsRegularProfile(profile)) + num_regular_profiles++; + } + DCHECK_EQ(1, num_regular_profiles); #endif // DCHECK_IS_ON() - // Given these assumptions, there is 1 and only 1 Account Manager that - // can/should be contacted - the one attached to the regular |Profile| in - // ash-chrome, for the current |User|. - const user_manager::User* const user = - user_manager::UserManager::Get()->GetActiveUser(); - const Profile* const profile = - chromeos::ProfileHelper::Get()->GetProfileByUser(user); - chromeos::AccountManager* const account_manager = - g_browser_process->platform_part() - ->GetAccountManagerFactory() - ->GetAccountManager(/* profile_path = */ profile->GetPath().value()); - // TODO(https://crbug.com/1148448): Convert this to allow multiple, - // simultaneous crosapi clients. See BindScreenManager for an example. - account_manager_ash_ = std::make_unique<crosapi::AccountManagerAsh>( - account_manager, std::move(receiver)); + // Given these assumptions, there is 1 and only 1 Account Manager that + // can/should be contacted - the one attached to the regular |Profile| in + // ash-chrome, for the current |User|. + const user_manager::User* const user = + user_manager::UserManager::Get()->GetActiveUser(); + const Profile* const profile = + chromeos::ProfileHelper::Get()->GetProfileByUser(user); + chromeos::AccountManager* const account_manager = + g_browser_process->platform_part() + ->GetAccountManagerFactory() + ->GetAccountManager( + /* profile_path = */ profile->GetPath().value()); + account_manager_ash_ = + std::make_unique<crosapi::AccountManagerAsh>(account_manager); + } + account_manager_ash_->BindReceiver(std::move(receiver)); } void AshChromeServiceImpl::BindFileManager(
diff --git a/chrome/browser/chromeos/input_method/autocorrect_manager.cc b/chrome/browser/chromeos/input_method/autocorrect_manager.cc index 2bf4d24..e3902b0 100644 --- a/chrome/browser/chromeos/input_method/autocorrect_manager.cc +++ b/chrome/browser/chromeos/input_method/autocorrect_manager.cc
@@ -7,11 +7,14 @@ #include "base/metrics/histogram_functions.h" #include "base/strings/strcat.h" #include "base/strings/utf_string_conversions.h" +#include "base/time/time.h" #include "chrome/browser/chromeos/input_method/assistive_window_properties.h" #include "chrome/browser/chromeos/input_method/suggestion_enums.h" #include "chrome/grit/generated_resources.h" +#include "ui/base/ime/chromeos/extension_ime_util.h" #include "ui/base/ime/chromeos/ime_bridge.h" #include "ui/base/ime/chromeos/ime_input_context_handler_interface.h" +#include "ui/base/ime/chromeos/input_method_manager.h" #include "ui/base/l10n/l10n_util.h" #include "ui/events/keycodes/dom/dom_code.h" @@ -28,9 +31,31 @@ kMaxValue = kReverted, }; +bool IsCurrentInputMethodExperimentalMultilingual() { + auto* input_method_manager = input_method::InputMethodManager::Get(); + if (!input_method_manager) { + return false; + } + return extension_ime_util::IsExperimentalMultilingual( + input_method_manager->GetActiveIMEState()->GetCurrentInputMethod().id()); +} + void LogAssistiveAutocorrectAction(AutocorrectActions action) { base::UmaHistogramEnumeration("InputMethod.Assistive.Autocorrect.Actions", action); + if (IsCurrentInputMethodExperimentalMultilingual()) { + base::UmaHistogramEnumeration( + "InputMethod.MultilingualExperiment.Autocorrect.Actions", action); + } +} + +void LogAssistiveAutocorrectDelay(base::TimeDelta delay) { + base::UmaHistogramMediumTimes("InputMethod.Assistive.Autocorrect.Delay", + delay); + if (IsCurrentInputMethodExperimentalMultilingual()) { + base::UmaHistogramMediumTimes( + "InputMethod.MultilingualExperiment.Autocorrect.Delay", delay); + } } void RecordAssistiveCoverage(AssistiveType type) { @@ -193,8 +218,7 @@ LogAssistiveAutocorrectAction(AutocorrectActions::kReverted); RecordAssistiveCoverage(AssistiveType::kAutocorrectReverted); RecordAssistiveSuccess(AssistiveType::kAutocorrectReverted); - base::UmaHistogramMediumTimes("InputMethod.Assistive.Autocorrect.Delay", - (base::TimeTicks::Now() - autocorrect_time_)); + LogAssistiveAutocorrectDelay(base::TimeTicks::Now() - autocorrect_time_); } } // namespace chromeos
diff --git a/chrome/browser/chromeos/net/network_health/network_health_unittest.cc b/chrome/browser/chromeos/net/network_health/network_health_unittest.cc index 4f6b281..80292df 100644 --- a/chrome/browser/chromeos/net/network_health/network_health_unittest.cc +++ b/chrome/browser/chromeos/net/network_health/network_health_unittest.cc
@@ -60,20 +60,14 @@ const auto& initial_network_health_state = network_health_.GetNetworkHealthState(); - ASSERT_EQ(std::size_t(2), initial_network_health_state->networks.size()); - - // Check that VPN device state is always reported even if no VPNs exist. - ASSERT_EQ(network_config::mojom::NetworkType::kVPN, - initial_network_health_state->networks[0]->type); - ASSERT_EQ(network_health::mojom::NetworkState::kNotConnected, - initial_network_health_state->networks[0]->state); + ASSERT_EQ(std::size_t(1), initial_network_health_state->networks.size()); // Check that the default wifi device created by CrosNetworkConfigTestHelper // exists. ASSERT_EQ(network_config::mojom::NetworkType::kWiFi, - initial_network_health_state->networks[1]->type); + initial_network_health_state->networks[0]->type); ASSERT_EQ(network_health::mojom::NetworkState::kNotConnected, - initial_network_health_state->networks[1]->state); + initial_network_health_state->networks[0]->state); } mojom::NetworkPtr GetNetworkHealthStateByType(
diff --git a/chrome/browser/chromeos/policy/system_proxy_manager.cc b/chrome/browser/chromeos/policy/system_proxy_manager.cc index d9c290a..6b73c06b 100644 --- a/chrome/browser/chromeos/policy/system_proxy_manager.cc +++ b/chrome/browser/chromeos/policy/system_proxy_manager.cc
@@ -5,6 +5,8 @@ #include "chrome/browser/chromeos/policy/system_proxy_manager.h" #include "base/bind.h" +#include "base/containers/contains.h" +#include "base/memory/weak_ptr.h" #include "base/strings/string16.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -17,8 +19,10 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/login/login_handler.h" #include "chrome/common/pref_names.h" #include "chromeos/dbus/system_proxy/system_proxy_client.h" +#include "chromeos/login/login_state/login_state.h" #include "chromeos/network/network_event_log.h" #include "chromeos/network/network_state.h" #include "chromeos/network/network_state_handler.h" @@ -46,6 +50,40 @@ namespace { const char kSystemProxyService[] = "system-proxy-service"; + +// A `content::LoginDelegate` implementation that returns to the caller the +// proxy credentials set by the policy `SystemProxySettings`. +class SystemProxyLoginHandler : public content::LoginDelegate { + public: + SystemProxyLoginHandler() = default; + ~SystemProxyLoginHandler() override = default; + + SystemProxyLoginHandler(const SystemProxyLoginHandler&) = delete; + SystemProxyLoginHandler& operator=(const SystemProxyLoginHandler&) = delete; + + void AuthenticateWithCredentials( + const std::string& username, + const std::string& password, + LoginAuthRequiredCallback auth_required_callback) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&SystemProxyLoginHandler::InvokeWithCredentials, + weak_factory_.GetWeakPtr(), username, password, + std::move(auth_required_callback))); + } + + private: + void InvokeWithCredentials(const std::string& username, + const std::string& password, + LoginAuthRequiredCallback auth_required_callback) { + std::move(auth_required_callback) + .Run(base::make_optional<net::AuthCredentials>( + base::UTF8ToUTF16(username), base::UTF8ToUTF16(password))); + } + + base::WeakPtrFactory<SystemProxyLoginHandler> weak_factory_{this}; +}; + } // namespace namespace policy { @@ -380,6 +418,47 @@ /*default_value=*/std::string()); } +bool SystemProxyManager::CanUsePolicyCredentials( + const net::AuthChallengeInfo& auth_info, + bool first_auth_attempt) { + if (!auth_info.is_proxy || !first_auth_attempt) + return false; + + if (!chromeos::LoginState::IsInitialized() || + (!chromeos::LoginState::Get()->IsPublicSessionUser() && + !chromeos::LoginState::Get()->IsKioskApp())) { + VLOG(1) << "Only kiosk app and MGS can reuse the policy provided proxy " + "credentials for authentication"; + return false; + } + + if (!system_proxy_enabled_ || system_services_username_.empty() || + system_services_password_.empty()) { + return false; + } + + if (!IsManagedProxyConfigured()) { + return false; + } + if (!policy_credentials_auth_schemes_.empty()) { + if (!base::Contains(policy_credentials_auth_schemes_, auth_info.scheme)) { + VLOG(1) << "Auth scheme not allowed by policy"; + return false; + } + } + + return true; +} + +std::unique_ptr<content::LoginDelegate> SystemProxyManager::CreateLoginDelegate( + LoginAuthRequiredCallback auth_required_callback) { + auto login_delegate = std::make_unique<SystemProxyLoginHandler>(); + login_delegate->AuthenticateWithCredentials( + system_services_username_, system_services_password_, + std::move(auth_required_callback)); + return std::move(login_delegate); +} + void SystemProxyManager::OnSetAuthenticationDetails( const system_proxy::SetAuthenticationDetailsResponse& response) { if (response.has_error_message()) {
diff --git a/chrome/browser/chromeos/policy/system_proxy_manager.h b/chrome/browser/chromeos/policy/system_proxy_manager.h index dbde688..2d131c27 100644 --- a/chrome/browser/chromeos/policy/system_proxy_manager.h +++ b/chrome/browser/chromeos/policy/system_proxy_manager.h
@@ -17,6 +17,8 @@ #include "chrome/browser/extensions/api/settings_private/prefs_util.h" #include "chromeos/dbus/system_proxy/system_proxy_service.pb.h" #include "chromeos/network/network_state_handler_observer.h" +#include "components/user_manager/user_manager.h" +#include "content/public/browser/content_browser_client.h" #include "net/base/auth.h" namespace chromeos { @@ -25,6 +27,10 @@ class SystemProxyNotification; } // namespace chromeos +namespace content { +class LoginDelegate; +} + namespace system_proxy { class SetAuthenticationDetailsResponse; class ShutDownResponse; @@ -81,6 +87,23 @@ // Registers prefs stored in user profiles. static void RegisterProfilePrefs(PrefRegistrySimple* registry); + // Indicates whether the credentials set via the device policy + // SystemProxySettings can be used for proxy authentication in Chrome. The + // following conditions must be true: + // - the current session must be Managed Guest Session (MGS) or Kiosk app; + // - the proxy is set via policy; + // - System-proxy is enabled and credentials are set via policy; + // - `first_auth_attempt` is true; + // - `auth_info.scheme` must be allowed by the SystemProxySettings policy. + bool CanUsePolicyCredentials(const net::AuthChallengeInfo& auth_info, + bool first_auth_attempt); + + // Returns a login delegate that posts `auth_required_callback` with the + // credentials provided by the policy SystemProxySettings. Callers must verify + // that `CanUsePolicyCredentials` is true before calling this method. + std::unique_ptr<content::LoginDelegate> CreateLoginDelegate( + LoginAuthRequiredCallback auth_required_callback); + private: // NetworkStateHandlerObserver implementation void DefaultNetworkChanged(const chromeos::NetworkState* network) override;
diff --git a/chrome/browser/chromeos/policy/system_proxy_manager_browsertest.cc b/chrome/browser/chromeos/policy/system_proxy_manager_browsertest.cc index 45bbc133..06a07168 100644 --- a/chrome/browser/chromeos/policy/system_proxy_manager_browsertest.cc +++ b/chrome/browser/chromeos/policy/system_proxy_manager_browsertest.cc
@@ -17,7 +17,10 @@ #include "chrome/browser/chromeos/policy/system_proxy_manager.h" #include "chrome/browser/chromeos/ui/request_system_proxy_credentials_view.h" #include "chrome/browser/notifications/notification_display_service_tester.h" +#include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_test_utils.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/login/login_handler.h" +#include "chrome/browser/ui/login/login_handler_test_utils.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/testing_browser_process.h" @@ -29,6 +32,7 @@ #include "chromeos/dbus/shill/shill_service_client.h" #include "chromeos/dbus/system_proxy/system_proxy_client.h" #include "chromeos/dbus/system_proxy/system_proxy_service.pb.h" +#include "chromeos/login/login_state/login_state.h" #include "chromeos/network/network_handler.h" #include "chromeos/network/network_state.h" #include "chromeos/network/network_state_handler.h" @@ -46,8 +50,16 @@ #include "components/proxy_config/proxy_prefs.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_service.h" +#include "content/public/browser/storage_partition.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" +#include "net/base/proxy_server.h" +#include "net/dns/mock_host_resolver.h" +#include "net/http/http_auth_cache.h" +#include "net/test/embedded_test_server/default_handlers.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "net/test/spawned_test_server/spawned_test_server.h" +#include "net/url_request/url_request_context.h" #include "ui/views/controls/label.h" #include "ui/views/controls/textfield/textfield.h" @@ -618,4 +630,167 @@ ExpectSystemCredentialsSent(kUsername, kPassword, {"ntlm"}); } +namespace { +constexpr char kProxyUsername[] = "foo"; +constexpr char kProxyPassword[] = "bar"; +constexpr char kBadUsername[] = "bad-username"; +constexpr char kBadPassword[] = "bad-pwd"; +constexpr char kOriginHostname[] = "a.test"; +} // namespace + +class SystemProxyCredentialsReuseBrowserTest + : public SystemProxyManagerPolicyCredentialsBrowserTest { + public: + SystemProxyCredentialsReuseBrowserTest() + : proxy_server_(std::make_unique<net::SpawnedTestServer>( + net::SpawnedTestServer::TYPE_BASIC_AUTH_PROXY, + base::FilePath())) {} + SystemProxyCredentialsReuseBrowserTest( + const SystemProxyCredentialsReuseBrowserTest&) = delete; + SystemProxyCredentialsReuseBrowserTest& operator=( + const SystemProxyCredentialsReuseBrowserTest&) = delete; + ~SystemProxyCredentialsReuseBrowserTest() override = default; + + void SetUpOnMainThread() override { + InProcessBrowserTest::SetUpOnMainThread(); + host_resolver()->AddRule(kOriginHostname, "127.0.0.1"); + proxy_server_->set_redirect_connect_to_localhost(true); + ASSERT_TRUE(proxy_server_->Start()); + + https_server_ = std::make_unique<net::EmbeddedTestServer>( + net::EmbeddedTestServer::TYPE_HTTPS); + https_server_->SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES); + https_server_->ServeFilesFromSourceDirectory("chrome/test/data"); + net::test_server::RegisterDefaultHandlers(https_server_.get()); + ASSERT_TRUE(https_server_->Start()); + } + + protected: + content::WebContents* GetWebContents() const { + return browser()->tab_strip_model()->GetActiveWebContents(); + } + + void SetManagedProxy() { + // Configure a proxy via user policy. + base::Value proxy_config(base::Value::Type::DICTIONARY); + proxy_config.SetKey("mode", + base::Value(ProxyPrefs::kFixedServersProxyModeName)); + proxy_config.SetKey( + "server", base::Value(proxy_server_->host_port_pair().ToString())); + browser()->profile()->GetPrefs()->Set(proxy_config::prefs::kProxy, + proxy_config); + RunUntilIdle(); + } + + GURL GetServerUrl(const std::string& page) { + return https_server_->GetURL(kOriginHostname, page); + } + + // Navigates to the test page "/simple.html" and authenticates in the proxy + // login dialog with `username` and `password`. + void LoginWithDialog(const std::string& username, + const std::string& password) { + LoginPromptBrowserTestObserver login_observer; + login_observer.Register(content::Source<content::NavigationController>( + &GetWebContents()->GetController())); + WindowedAuthNeededObserver auth_needed(&GetWebContents()->GetController()); + ui_test_utils::NavigateToURL(browser(), GetServerUrl("/simple.html")); + auth_needed.Wait(); + WindowedAuthSuppliedObserver auth_supplied( + &GetWebContents()->GetController()); + LoginHandler* login_handler = login_observer.handlers().front(); + login_handler->SetAuth(base::ASCIIToUTF16(username), + base::ASCIIToUTF16(password)); + auth_supplied.Wait(); + EXPECT_EQ(1, login_observer.auth_supplied_count()); + } + + void CheckEntryInHttpAuthCache(const std::string& auth_scheme, + const std::string& expected_username, + const std::string& expected_password) { + network::mojom::NetworkContext* network_context = + content::BrowserContext::GetDefaultStoragePartition( + browser()->profile()) + ->GetNetworkContext(); + std::string username; + std::string password; + base::RunLoop loop; + network_context->LookupProxyAuthCredentials( + net::ProxyServer(net::ProxyServer::SCHEME_HTTP, + proxy_server_->host_port_pair()), + auth_scheme, "MyRealm1", + base::BindOnce( + [](std::string* username, std::string* password, + base::OnceClosure closure, + const base::Optional<net::AuthCredentials>& credentials) { + if (credentials) { + *username = base::UTF16ToUTF8(credentials->username()); + *password = base::UTF16ToUTF8(credentials->password()); + } + std::move(closure).Run(); + }, + &username, &password, loop.QuitClosure())); + loop.Run(); + EXPECT_EQ(username, expected_username); + EXPECT_EQ(password, expected_password); + } + + SystemProxyManager* GetSystemProxyManager() { + return g_browser_process->platform_part() + ->browser_policy_connector_chromeos() + ->GetSystemProxyManager(); + } + + std::unique_ptr<net::EmbeddedTestServer> https_server_; + // A proxy server which requires authentication using the 'Basic' + // authentication method. + std::unique_ptr<net::SpawnedTestServer> proxy_server_; +}; + +// Verifies that the policy provided credentials are not used for regular users. +IN_PROC_BROWSER_TEST_F(SystemProxyCredentialsReuseBrowserTest, RegularUser) { + SetManagedProxy(); + SetPolicyCredentials(kProxyUsername, kProxyPassword); + LoginWithDialog(kProxyUsername, kProxyPassword); + CheckEntryInHttpAuthCache("Basic", kProxyUsername, kProxyPassword); +} + +// Verifies that the policy provided credentials are used for MGS. +IN_PROC_BROWSER_TEST_F(SystemProxyCredentialsReuseBrowserTest, + PolicyCredentialsUsed) { + SetManagedProxy(); + chromeos::LoginState::Get()->SetLoggedInState( + chromeos::LoginState::LOGGED_IN_ACTIVE, + chromeos::LoginState::LOGGED_IN_USER_PUBLIC_ACCOUNT_MANAGED); + SetPolicyCredentials(kProxyUsername, kProxyPassword); + ui_test_utils::NavigateToURL(browser(), GetServerUrl("/simple.html")); + CheckEntryInHttpAuthCache("Basic", kProxyUsername, kProxyPassword); +} + +// Verifies that if the policy provided proxy credentials are not correct in a +// MGS, then the user is prompted for credentials. +IN_PROC_BROWSER_TEST_F(SystemProxyCredentialsReuseBrowserTest, + BadPolicyCredentials) { + SetManagedProxy(); + chromeos::LoginState::Get()->SetLoggedInState( + chromeos::LoginState::LOGGED_IN_ACTIVE, + chromeos::LoginState::LOGGED_IN_USER_PUBLIC_ACCOUNT_MANAGED); + SetPolicyCredentials(kBadUsername, kBadPassword); + LoginWithDialog(kProxyUsername, kProxyPassword); + CheckEntryInHttpAuthCache("Basic", kProxyUsername, kProxyPassword); +} + +// Verifies that the policy provided proxy credentials are only used for +// authentication schemes allowed by the SystemProxySettings policy. +IN_PROC_BROWSER_TEST_F(SystemProxyCredentialsReuseBrowserTest, + RestrictedPolicyCredentials) { + SetManagedProxy(); + chromeos::LoginState::Get()->SetLoggedInState( + chromeos::LoginState::LOGGED_IN_ACTIVE, + chromeos::LoginState::LOGGED_IN_USER_PUBLIC_ACCOUNT_MANAGED); + SetPolicyCredentials(kProxyUsername, kProxyPassword, R"("ntlm","digest")"); + LoginWithDialog(kProxyUsername, kProxyPassword); + CheckEntryInHttpAuthCache("Basic", kProxyUsername, kProxyPassword); +} + } // namespace policy
diff --git a/chrome/browser/chromeos/policy/system_proxy_manager_unittest.cc b/chrome/browser/chromeos/policy/system_proxy_manager_unittest.cc index 741002e3..8080a24 100644 --- a/chrome/browser/chromeos/policy/system_proxy_manager_unittest.cc +++ b/chrome/browser/chromeos/policy/system_proxy_manager_unittest.cc
@@ -20,6 +20,8 @@ #include "chromeos/network/network_handler.h" #include "components/arc/arc_prefs.h" #include "components/prefs/pref_service.h" +#include "components/proxy_config/proxy_config_pref_names.h" +#include "components/proxy_config/proxy_prefs.h" #include "content/public/browser/network_service_instance.h" #include "content/public/browser/storage_partition.h" #include "content/public/test/browser_task_environment.h" @@ -43,6 +45,8 @@ namespace { constexpr char kBrowserUsername[] = "browser_username"; constexpr char kBrowserPassword[] = "browser_password"; +constexpr char kPolicyUsername[] = "policy_username"; +constexpr char kPolicyPassword[] = "policy_password"; constexpr char kKerberosActivePrincipalName[] = "kerberos_princ_name"; constexpr char kProxyAuthUrl[] = "http://example.com:3128"; constexpr char kProxyAuthEmptyPath[] = "http://example.com:3128/"; @@ -73,6 +77,22 @@ return network::NetworkService::GetNetworkServiceForTesting(); } +void SetManagedProxy(Profile* profile) { + // Configure a proxy via user policy. + base::Value proxy_config(base::Value::Type::DICTIONARY); + proxy_config.SetKey("mode", + base::Value(ProxyPrefs::kFixedServersProxyModeName)); + proxy_config.SetKey("server", base::Value(kProxyAuthUrl)); + profile->GetPrefs()->Set(proxy_config::prefs::kProxy, proxy_config); +} + +net::AuthChallengeInfo GetAuthInfo() { + net::AuthChallengeInfo auth_info; + auth_info.is_proxy = true; + auth_info.scheme = kScheme; + return auth_info; +} + } // namespace namespace policy { @@ -88,6 +108,7 @@ testing::Test::SetUp(); chromeos::shill_clients::InitializeFakes(); chromeos::NetworkHandler::Initialize(); + chromeos::LoginState::Initialize(); profile_ = std::make_unique<TestingProfile>(); chromeos::SystemProxyClient::InitializeFake(); @@ -95,11 +116,14 @@ chromeos::CrosSettings::Get(), local_state_.Get()); // Listen for pref changes for the primary profile. system_proxy_manager_->StartObservingPrimaryProfilePrefs(profile_.get()); + chromeos::NetworkHandler::Get()->InitializePrefServices( + profile_->GetPrefs(), local_state_.Get()); } void TearDown() override { system_proxy_manager_->StopObservingPrimaryProfilePrefs(); system_proxy_manager_.reset(); + chromeos::LoginState::Shutdown(); chromeos::SystemProxyClient::Shutdown(); chromeos::NetworkHandler::Shutdown(); chromeos::shill_clients::Shutdown(); @@ -334,4 +358,98 @@ .empty()); } +// Verifies that only MGS and Kiosk can use the policy provided credentials. +TEST_F(SystemProxyManagerTest, CanUsePolicyCredentialsUserType) { + SetPolicy(/*system_proxy_enabled=*/true, + /*system_services_username=*/kPolicyUsername, + /*system_services_password=*/kPolicyPassword); + SetManagedProxy(profile_.get()); + + chromeos::LoginState::Get()->SetLoggedInState( + chromeos::LoginState::LOGGED_IN_ACTIVE, + chromeos::LoginState::LOGGED_IN_USER_PUBLIC_ACCOUNT_MANAGED); + + EXPECT_TRUE(system_proxy_manager_->CanUsePolicyCredentials( + GetAuthInfo(), /*first_auth_attempt=*/true)); + + chromeos::LoginState::Get()->SetLoggedInState( + chromeos::LoginState::LOGGED_IN_ACTIVE, + chromeos::LoginState::LOGGED_IN_USER_KIOSK_APP); + + EXPECT_TRUE(system_proxy_manager_->CanUsePolicyCredentials( + GetAuthInfo(), /*first_auth_attempt=*/true)); + + chromeos::LoginState::Get()->SetLoggedInState( + chromeos::LoginState::LOGGED_IN_ACTIVE, + chromeos::LoginState::LOGGED_IN_USER_REGULAR); + + EXPECT_FALSE(system_proxy_manager_->CanUsePolicyCredentials( + GetAuthInfo(), /*first_auth_attempt=*/true)); +} + +// Verifies that the policy provided credentials are only used for proxy auth. +TEST_F(SystemProxyManagerTest, CanUsePolicyCredentialsOriginServer) { + SetPolicy(/*system_proxy_enabled=*/true, + /*system_services_username=*/kPolicyUsername, + /*system_services_password=*/kPolicyPassword); + SetManagedProxy(profile_.get()); + + net::AuthChallengeInfo auth_info = GetAuthInfo(); + auth_info.is_proxy = false; + chromeos::LoginState::Get()->SetLoggedInState( + chromeos::LoginState::LOGGED_IN_ACTIVE, + chromeos::LoginState::LOGGED_IN_USER_PUBLIC_ACCOUNT_MANAGED); + + EXPECT_FALSE(system_proxy_manager_->CanUsePolicyCredentials( + auth_info, /*first_auth_attempt=*/true)); +} + +// Verifies that the policy provided credentials are only used for managed +// proxies. +TEST_F(SystemProxyManagerTest, CanUsePolicyCredentialsNoManagedProxy) { + SetPolicy(/*system_proxy_enabled=*/true, + /*system_services_username=*/kPolicyUsername, + /*system_services_password=*/kPolicyPassword); + + chromeos::LoginState::Get()->SetLoggedInState( + chromeos::LoginState::LOGGED_IN_ACTIVE, + chromeos::LoginState::LOGGED_IN_USER_PUBLIC_ACCOUNT_MANAGED); + + EXPECT_FALSE(system_proxy_manager_->CanUsePolicyCredentials( + GetAuthInfo(), /*first_auth_attempt=*/true)); +} + +// Verifies that `CanUsePolicyCredentials` returns false if no credentials are +// specified by policy. +TEST_F(SystemProxyManagerTest, NoPolicyCredentials) { + SetPolicy(/*system_proxy_enabled=*/true, + /*system_services_username=*/"", + /*system_services_password=*/""); + SetManagedProxy(profile_.get()); + + chromeos::LoginState::Get()->SetLoggedInState( + chromeos::LoginState::LOGGED_IN_ACTIVE, + chromeos::LoginState::LOGGED_IN_USER_PUBLIC_ACCOUNT_MANAGED); + + EXPECT_FALSE(system_proxy_manager_->CanUsePolicyCredentials( + GetAuthInfo(), /*first_auth_attempt=*/true)); +} + +// Verifies that `CanUsePolicyCredentials` is only returning true for the first +// auth attempt. +TEST_F(SystemProxyManagerTest, CanUsePolicyCredentialsMgsMaxTries) { + SetPolicy(/*system_proxy_enabled=*/true, + /*system_services_username=*/kPolicyUsername, + /*system_services_password=*/kPolicyPassword); + SetManagedProxy(profile_.get()); + + chromeos::LoginState::Get()->SetLoggedInState( + chromeos::LoginState::LOGGED_IN_ACTIVE, + chromeos::LoginState::LOGGED_IN_USER_PUBLIC_ACCOUNT_MANAGED); + EXPECT_TRUE(system_proxy_manager_->CanUsePolicyCredentials( + GetAuthInfo(), /*first_auth_attempt=*/true)); + EXPECT_FALSE(system_proxy_manager_->CanUsePolicyCredentials( + GetAuthInfo(), /*first_auth_attempt=*/false)); +} + } // namespace policy
diff --git a/chrome/browser/content_settings/content_settings_browsertest.cc b/chrome/browser/content_settings/content_settings_browsertest.cc index f1dd0a6c..cd1fa520 100644 --- a/chrome/browser/content_settings/content_settings_browsertest.cc +++ b/chrome/browser/content_settings/content_settings_browsertest.cc
@@ -186,12 +186,6 @@ set_secure_scheme(); } - void SetUpCommandLine(base::CommandLine* cmd) override { - // Get access to CookieStore API. - cmd->AppendSwitch(switches::kEnableExperimentalWebPlatformFeatures); - ContentSettingsTest::SetUpCommandLine(cmd); - } - void set_secure_scheme() { secure_scheme_ = true; } std::string ReadCookie(Browser* browser) { @@ -963,13 +957,6 @@ ContentSettingsWorkerModulesBrowserTest() = default; ~ContentSettingsWorkerModulesBrowserTest() override = default; - void SetUpCommandLine(base::CommandLine* cmd) override { - // Module scripts on Dedicated Worker is still an experimental feature. - // Likewise for CookieStore. - // TODO(crbug/680046,crbug/729800): Remove this after shipping. - cmd->AppendSwitch(switches::kEnableExperimentalWebPlatformFeatures); - } - protected: void RegisterStaticFile(net::EmbeddedTestServer* server, const std::string& relative_url,
diff --git a/chrome/browser/enterprise/reporting/extension_request/extension_request_notification_unittest.cc b/chrome/browser/enterprise/reporting/extension_request/extension_request_notification_unittest.cc index fe22c062..ae1b741 100644 --- a/chrome/browser/enterprise/reporting/extension_request/extension_request_notification_unittest.cc +++ b/chrome/browser/enterprise/reporting/extension_request/extension_request_notification_unittest.cc
@@ -81,7 +81,6 @@ #else request_notification.Show(base::BindOnce(&OnNotificationClosed, false)); #endif - task_environment()->RunUntilIdle(); EXPECT_FALSE(GetNotification().has_value()); }
diff --git a/chrome/browser/extensions/chrome_component_extension_resource_manager.cc b/chrome/browser/extensions/chrome_component_extension_resource_manager.cc index c437624..7f7767a 100644 --- a/chrome/browser/extensions/chrome_component_extension_resource_manager.cc +++ b/chrome/browser/extensions/chrome_component_extension_resource_manager.cc
@@ -21,8 +21,13 @@ #include "content/public/browser/browser_thread.h" #include "extensions/common/constants.h" #include "pdf/buildflags.h" +#include "ppapi/buildflags/buildflags.h" #include "ui/base/resource/resource_bundle.h" +#if BUILDFLAG(ENABLE_PLUGINS) +#include "chrome/grit/pdf_resources_map.h" +#endif + #if BUILDFLAG(IS_CHROMEOS_ASH) #include "ash/keyboard/ui/resources/keyboard_resource_util.h" #include "base/command_line.h" @@ -111,6 +116,11 @@ kComponentExtensionResourcesSize); AddComponentResourceEntries(kExtraComponentExtensionResources, base::size(kExtraComponentExtensionResources)); + +#if BUILDFLAG(ENABLE_PLUGINS) + AddComponentResourceEntries(kPdfResources, kPdfResourcesSize); +#endif + #if BUILDFLAG(IS_CHROMEOS_ASH) // Add Files app JS modules resources. AddComponentResourceEntries(kFileManagerResources, kFileManagerResourcesSize); @@ -153,28 +163,13 @@ void ChromeComponentExtensionResourceManager::Data::AddComponentResourceEntries( const GritResourceMap* entries, size_t size) { - base::FilePath gen_folder_path = base::FilePath().AppendASCII( - "@out_folder@/gen/chrome/browser/resources/"); - gen_folder_path = gen_folder_path.NormalizePathSeparators(); - for (size_t i = 0; i < size; ++i) { base::FilePath resource_path = base::FilePath().AppendASCII(entries[i].name); resource_path = resource_path.NormalizePathSeparators(); - if (!gen_folder_path.IsParent(resource_path)) { - DCHECK(!base::Contains(path_to_resource_id_, resource_path)); - path_to_resource_id_[resource_path] = entries[i].value; - } else { - // If the resource is a generated file, strip the generated folder's path, - // so that it can be served from a normal URL (as if it were not - // generated). - base::FilePath effective_path = - base::FilePath().AppendASCII(resource_path.AsUTF8Unsafe().substr( - gen_folder_path.value().length())); - DCHECK(!base::Contains(path_to_resource_id_, effective_path)); - path_to_resource_id_[effective_path] = entries[i].value; - } + DCHECK(!base::Contains(path_to_resource_id_, resource_path)); + path_to_resource_id_[resource_path] = entries[i].value; } }
diff --git a/chrome/browser/extensions/chrome_component_extension_resource_manager_unittest.cc b/chrome/browser/extensions/chrome_component_extension_resource_manager_unittest.cc index 62f973f..8d169a5 100644 --- a/chrome/browser/extensions/chrome_component_extension_resource_manager_unittest.cc +++ b/chrome/browser/extensions/chrome_component_extension_resource_manager_unittest.cc
@@ -80,38 +80,4 @@ #endif } -TEST_F(ChromeComponentExtensionResourceManagerTest, - IsComponentExtensionResource_Generated) { - // Check that the file being used for testing is indeed a generated resource. - int generated_resource_id = IDR_PDF_SHARED_VARS_JS; - bool found_resource = false; - for (size_t i = 0; i < kComponentExtensionResourcesSize; ++i) { - if (kComponentExtensionResources[i].value == generated_resource_id) { - ASSERT_TRUE(base::StartsWith(kComponentExtensionResources[i].name, - "@out_folder@", - base::CompareCase::SENSITIVE)); - found_resource = true; - break; - } - } - ASSERT_TRUE(found_resource); - - const ComponentExtensionResourceManager* resource_manager = - ExtensionsBrowserClient::Get()->GetComponentExtensionResourceManager(); - ASSERT_TRUE(resource_manager); - - base::FilePath resources_dir; - base::PathService::Get(chrome::DIR_RESOURCES, &resources_dir); - - base::FilePath extension_path = resources_dir.AppendASCII("pdf"); - base::FilePath resource_path = - base::FilePath().AppendASCII("elements/shared-vars.js"); - - // Check that the resource is classified as a component resource. - int resource_id = 0; - ASSERT_TRUE(resource_manager->IsComponentExtensionResource( - extension_path, resource_path, &resource_id)); - ASSERT_EQ(generated_resource_id, resource_id); -} - } // namespace extensions
diff --git a/chrome/browser/extensions/forced_extensions/force_installed_metrics_unittest.cc b/chrome/browser/extensions/forced_extensions/force_installed_metrics_unittest.cc index 373a41f5..75ff7dd 100644 --- a/chrome/browser/extensions/forced_extensions/force_installed_metrics_unittest.cc +++ b/chrome/browser/extensions/forced_extensions/force_installed_metrics_unittest.cc
@@ -26,7 +26,6 @@ #include "extensions/browser/pref_names.h" #include "extensions/browser/updater/safe_manifest_parser.h" #include "extensions/common/extension.h" -#include "extensions/common/extension_builder.h" #include "extensions/common/manifest.h" #include "extensions/common/value_builder.h" #include "net/base/net_errors.h" @@ -122,6 +121,7 @@ namespace extensions { +using ExtensionStatus = ForceInstalledTracker::ExtensionStatus; using testing::_; using testing::Return; @@ -200,13 +200,13 @@ TEST_F(ForceInstalledMetricsTest, ExtensionsInstalled) { SetupForceList(true /*is_from_store */); - auto ext1 = ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - auto ext2 = ExtensionBuilder(kExtensionName2).SetID(kExtensionId2).Build(); histogram_tester_.ExpectTotalCount(kLoadTimeStats, 0); - force_installed_tracker()->OnExtensionLoaded(profile(), ext1.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::LOADED); histogram_tester_.ExpectTotalCount(kLoadTimeStats, 0); - force_installed_tracker()->OnExtensionLoaded(profile(), ext2.get()); + scoped_refptr<const Extension> ext2 = CreateNewExtension( + kExtensionName2, kExtensionId2, ExtensionStatus::LOADED); histogram_tester_.ExpectTotalCount(kLoadTimeStats, 1); histogram_tester_.ExpectTotalCount(kReadyTimeStats, 0); @@ -227,8 +227,8 @@ TEST_F(ForceInstalledMetricsTest, ExtensionSettingsOverrideForcedList) { SetupForceList(true /*is_from_store */); SetupExtensionManagementPref(); - auto ext2 = ExtensionBuilder(kExtensionName2).SetID(kExtensionId2).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), ext2.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName2, kExtensionId2, ExtensionStatus::LOADED); // ForceInstalledMetrics shuts down timer because all extension are either // loaded or failed. EXPECT_FALSE(fake_timer_->IsRunning()); @@ -239,8 +239,9 @@ TEST_F(ForceInstalledMetricsTest, ExtensionsInstallationTimedOut) { SetupForceList(true /*is_from_store */); - auto ext1 = ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - registry()->AddEnabled(ext1.get()); + scoped_refptr<const Extension> ext = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::PENDING); + registry()->AddEnabled(ext.get()); EXPECT_TRUE(fake_timer_->IsRunning()); fake_timer_->Fire(); // Metrics are reported due to timeout. @@ -267,8 +268,8 @@ task_environment_.FastForwardBy(manifest_download_time); install_stage_tracker()->ReportDownloadingStage( kExtensionId1, ExtensionDownloaderDelegate::Stage::MANIFEST_LOADED); - auto ext1 = ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), ext1.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::LOADED); install_stage_tracker()->ReportFailure( kExtensionId2, InstallStageTracker::FailureReason::MANIFEST_INVALID); // ForceInstalledMetrics shuts down timer because all extension are either @@ -286,8 +287,8 @@ ReportDownloadingManifestStage(); const base::TimeDelta install_time = base::TimeDelta::FromMilliseconds(200); ReportInstallationStarted(install_time); - auto ext1 = ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), ext1.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::LOADED); install_stage_tracker()->ReportFailure( kExtensionId2, InstallStageTracker::FailureReason::MANIFEST_INVALID); // ForceInstalledMetrics shuts down timer because all extension are either @@ -308,8 +309,8 @@ kExtensionId1, ExtensionDownloaderDelegate::Stage::FINISHED); install_stage_tracker()->ReportInstallationStage( kExtensionId1, InstallStageTracker::Stage::INSTALLING); - auto ext1 = ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), ext1.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::LOADED); install_stage_tracker()->ReportFailure( kExtensionId2, InstallStageTracker::FailureReason::MANIFEST_INVALID); // ForceInstalledMetrics shuts down timer because all extension are either @@ -351,8 +352,8 @@ install_stage_tracker()->ReportCRXInstallationStage( kExtensionId1, InstallationStage::kComplete); - auto ext1 = ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), ext1.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::LOADED); install_stage_tracker()->ReportFailure( kExtensionId2, InstallStageTracker::FailureReason::MANIFEST_INVALID); // ForceInstalledMetrics shuts down timer because all extension are either @@ -380,11 +381,13 @@ TEST_F(ForceInstalledMetricsTest, ExtensionsInstalledButNotLoadedUniqueDisableReason) { SetupForceList(true /*is_from_store */); - auto ext1 = ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::PENDING); registry()->AddDisabled(ext1.get()); ExtensionPrefs::Get(profile())->AddDisableReason( kExtensionId1, disable_reason::DisableReason::DISABLE_NOT_VERIFIED); - auto ext2 = ExtensionBuilder(kExtensionName2).SetID(kExtensionId2).Build(); + scoped_refptr<const Extension> ext2 = CreateNewExtension( + kExtensionName2, kExtensionId2, ExtensionStatus::PENDING); registry()->AddEnabled(ext2.get()); force_installed_tracker()->OnExtensionLoaded(profile(), ext2.get()); // ForceInstalledMetrics should still keep running as kExtensionId1 is @@ -400,13 +403,15 @@ TEST_F(ForceInstalledMetricsTest, ExtensionsInstalledButNotLoadedMultipleDisableReason) { SetupForceList(true /*is_from_store */); - auto ext1 = ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::PENDING); registry()->AddDisabled(ext1.get()); ExtensionPrefs::Get(profile())->AddDisableReasons( kExtensionId1, disable_reason::DisableReason::DISABLE_NOT_VERIFIED | disable_reason::DisableReason::DISABLE_UNSUPPORTED_REQUIREMENT); - auto ext2 = ExtensionBuilder(kExtensionName2).SetID(kExtensionId2).Build(); + scoped_refptr<const Extension> ext2 = CreateNewExtension( + kExtensionName2, kExtensionId2, ExtensionStatus::PENDING); registry()->AddEnabled(ext2.get()); force_installed_tracker()->OnExtensionLoaded(profile(), ext2.get()); // ForceInstalledMetrics should still keep running as kExtensionId1 is @@ -424,9 +429,11 @@ TEST_F(ForceInstalledMetricsTest, ExtensionsInstalledButNotLoadedNoDisableReason) { SetupForceList(true /*is_from_store */); - auto ext1 = ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::PENDING); registry()->AddEnabled(ext1.get()); - auto ext2 = ExtensionBuilder(kExtensionName2).SetID(kExtensionId2).Build(); + scoped_refptr<const Extension> ext2 = CreateNewExtension( + kExtensionName2, kExtensionId2, ExtensionStatus::PENDING); registry()->AddEnabled(ext2.get()); force_installed_tracker()->OnExtensionLoaded(profile(), ext2.get()); // ForceInstalledMetrics should still keep running as kExtensionId1 is @@ -439,9 +446,11 @@ TEST_F(ForceInstalledMetricsTest, ExtensionForceInstalledAndBlocklisted) { SetupForceList(true /*is_from_store */); - auto ext1 = ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::PENDING); registry()->AddBlocklisted(ext1.get()); - auto ext2 = ExtensionBuilder(kExtensionName2).SetID(kExtensionId2).Build(); + scoped_refptr<const Extension> ext2 = CreateNewExtension( + kExtensionName2, kExtensionId2, ExtensionStatus::PENDING); registry()->AddEnabled(ext2.get()); force_installed_tracker()->OnExtensionLoaded(profile(), ext2.get()); // ForceInstalledMetrics should still keep running as kExtensionId1 is @@ -475,9 +484,8 @@ EXPECT_TRUE(fake_timer_->IsRunning()); SetupForceList(true /*is_from_store */); - auto ext = ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), ext.get()); - force_installed_tracker()->OnExtensionReady(profile(), ext.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::READY); install_stage_tracker()->ReportFailure( kExtensionId2, InstallStageTracker::FailureReason::INVALID_ID); // ForceInstalledMetrics shuts down timer because kExtensionId1 was loaded and @@ -551,7 +559,8 @@ kExtensionId1, CrxInstallError(SandboxedUnpackerFailureReason::CRX_HEADER_INVALID, base::string16())); - auto ext2 = ExtensionBuilder(kExtensionName2).SetID(kExtensionId2).Build(); + scoped_refptr<const Extension> ext2 = CreateNewExtension( + kExtensionName2, kExtensionId2, ExtensionStatus::PENDING); registry()->AddEnabled(ext2.get()); force_installed_tracker()->OnExtensionLoaded(profile(), ext2.get()); // ForceInstalledMetrics shuts down timer because all extension are either @@ -576,7 +585,8 @@ kExtensionId1, CrxInstallError(SandboxedUnpackerFailureReason::CRX_HEADER_INVALID, base::string16())); - auto ext2 = ExtensionBuilder(kExtensionName2).SetID(kExtensionId2).Build(); + scoped_refptr<const Extension> ext2 = CreateNewExtension( + kExtensionName2, kExtensionId2, ExtensionStatus::PENDING); registry()->AddEnabled(ext2.get()); force_installed_tracker()->OnExtensionLoaded(profile(), ext2.get()); // ForceInstalledMetrics shuts down timer because all extension are either @@ -602,7 +612,8 @@ kExtensionId1, CrxInstallError(SandboxedUnpackerFailureReason::CRX_HEADER_INVALID, base::string16())); - auto ext2 = ExtensionBuilder(kExtensionName2).SetID(kExtensionId2).Build(); + scoped_refptr<const Extension> ext2 = CreateNewExtension( + kExtensionName2, kExtensionId2, ExtensionStatus::PENDING); registry()->AddEnabled(ext2.get()); force_installed_tracker()->OnExtensionLoaded(profile(), ext2.get()); // ForceInstalledMetrics shuts down timer because all extension are either @@ -649,12 +660,12 @@ TEST_F(ForceInstalledMetricsTest, ExtensionLoadedThenFailedWithAlreadyInstalledError) { SetupForceList(true /*is_from_store */); - auto ext1 = ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), ext1.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::LOADED); install_stage_tracker()->ReportFailure( kExtensionId1, InstallStageTracker::FailureReason::ALREADY_INSTALLED); - auto ext2 = ExtensionBuilder(kExtensionName2).SetID(kExtensionId2).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), ext2.get()); + scoped_refptr<const Extension> ext2 = CreateNewExtension( + kExtensionName2, kExtensionId2, ExtensionStatus::LOADED); // ForceInstalledMetrics shuts down timer because all extension are either // loaded or failed. EXPECT_FALSE(fake_timer_->IsRunning()); @@ -668,14 +679,12 @@ // after READY state is not reflected in the statistics. TEST_F(ForceInstalledMetricsTest, ExtensionsReady) { SetupForceList(true /*is_from_store */); - auto ext1 = ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), ext1.get()); - force_installed_tracker()->OnExtensionReady(profile(), ext1.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::READY); install_stage_tracker()->ReportFailure( kExtensionId1, InstallStageTracker::FailureReason::ALREADY_INSTALLED); - auto ext2 = ExtensionBuilder(kExtensionName2).SetID(kExtensionId2).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), ext2.get()); - force_installed_tracker()->OnExtensionReady(profile(), ext2.get()); + scoped_refptr<const Extension> ext2 = CreateNewExtension( + kExtensionName2, kExtensionId2, ExtensionStatus::READY); // ForceInstalledMetrics shuts down timer because all extension are either // loaded or failed. EXPECT_FALSE(fake_timer_->IsRunning()); @@ -690,9 +699,8 @@ // extensions are failed. TEST_F(ForceInstalledMetricsTest, AllExtensionsNotReady) { SetupForceList(true /*is_from_store */); - auto ext1 = ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), ext1.get()); - force_installed_tracker()->OnExtensionReady(profile(), ext1.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::READY); install_stage_tracker()->ReportFailure( kExtensionId2, InstallStageTracker::FailureReason::INVALID_ID); // ForceInstalledMetrics shuts down timer because all extension are either @@ -708,9 +716,8 @@ TEST_F(ForceInstalledMetricsTest, ExtensionsPreviousInstallationStageReportedAgain) { SetupForceList(true /*is_from_store */); - auto extension = - ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), extension.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::LOADED); install_stage_tracker()->ReportInstallationStage( kExtensionId2, InstallStageTracker::Stage::CREATED); install_stage_tracker()->ReportInstallationStage( @@ -729,9 +736,8 @@ // reported again after INSTALLING stage. TEST_F(ForceInstalledMetricsTest, ExtensionsDownloadingStageReportedAgain) { SetupForceList(true /*is_from_store */); - auto extension = - ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), extension.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::LOADED); install_stage_tracker()->ReportInstallationStage( kExtensionId2, InstallStageTracker::Stage::DOWNLOADING); install_stage_tracker()->ReportInstallationStage( @@ -775,9 +781,8 @@ TEST_F(ForceInstalledMetricsTest, ExtensionStuckInCreatedStage) { SetupForceList(true /*is_from_store */); - auto extension = - ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), extension.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::LOADED); install_stage_tracker()->ReportInstallationStage( kExtensionId2, InstallStageTracker::Stage::CREATED); install_stage_tracker()->ReportInstallCreationStage( @@ -937,9 +942,8 @@ // Errors occurred because the fetched update manifest was invalid. TEST_F(ForceInstalledMetricsTest, ExtensionManifestInvalid) { SetupForceList(true /*is_from_store */); - auto extension = - ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), extension.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::LOADED); install_stage_tracker()->ReportManifestInvalidFailure( kExtensionId2, ExtensionDownloaderDelegate::FailureData( @@ -957,9 +961,8 @@ // "error-unknownApplication" is considered as a misconfiguration. TEST_F(ForceInstalledMetricsTest, ExtensionManifestInvalidAppStatusError) { SetupForceList(true /*is_from_store */); - auto extension = - ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), extension.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::LOADED); install_stage_tracker()->ReportManifestInvalidFailure( kExtensionId2, ExtensionDownloaderDelegate::FailureData( @@ -986,9 +989,8 @@ TEST_F(ForceInstalledMetricsTest, NonMisconfigurationFailureNotPresentKioskModeOnlyError) { SetupForceList(true /*is_from_store */); - auto extension = - ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), extension.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::LOADED); install_stage_tracker()->ReportCrxInstallError( kExtensionId2, InstallStageTracker::FailureReason::CRX_INSTALL_ERROR_DECLINED, @@ -1013,9 +1015,8 @@ ListBuilder().Append("extension").Append("theme").Build(); prefs()->SetManagedPref(pref_names::kAllowedTypes, std::move(list)); - auto extension = - ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), extension.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::LOADED); // Hosted app is not a valid extension type, so this should report an error. install_stage_tracker()->ReportExtensionType(kExtensionId2, Manifest::Type::TYPE_HOSTED_APP); @@ -1044,9 +1045,8 @@ ListBuilder().Append("extension").Append("theme").Build(); prefs()->SetManagedPref(pref_names::kAllowedTypes, std::move(list)); - auto extension = - ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), extension.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::LOADED); install_stage_tracker()->ReportExtensionType(kExtensionId2, Manifest::Type::TYPE_EXTENSION); install_stage_tracker()->ReportCrxInstallError( @@ -1091,9 +1091,8 @@ prefs()->SetManagedPref(arc::prefs::kArcEnabled, std::make_unique<base::Value>(true)); SetupForceList(true /*is_from_store */); - auto extension = - ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), extension.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::LOADED); install_stage_tracker()->ReportFailure( kExtensionId2, InstallStageTracker::FailureReason::REPLACED_BY_ARC_APP); // ForceInstalledMetrics shuts down timer because all extension are either @@ -1112,9 +1111,8 @@ prefs()->SetManagedPref(arc::prefs::kArcEnabled, std::make_unique<base::Value>(false)); SetupForceList(true /*is_from_store */); - auto extension = - ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), extension.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::LOADED); install_stage_tracker()->ReportFailure( kExtensionId2, InstallStageTracker::FailureReason::REPLACED_BY_ARC_APP); // ForceInstalledMetrics shuts down timer because all extension are either @@ -1131,9 +1129,8 @@ TEST_F(ForceInstalledMetricsTest, NonMisconfigurationFailureNotPresentNotPerformingNewInstallError) { SetupForceList(true /*is_from_store */); - auto extension = - ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), extension.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::LOADED); install_stage_tracker()->ReportFailure( kExtensionId2, InstallStageTracker::FailureReason::NOT_PERFORMING_NEW_INSTALL); @@ -1150,9 +1147,8 @@ TEST_F(ForceInstalledMetricsTest, NonMisconfigurationFailureNotPresentCrxFetchUrlEmptyError) { SetupForceList(true /*is_from_store */); - auto extension = - ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), extension.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::LOADED); install_stage_tracker()->ReportInfoOnNoUpdatesFailure(kExtensionId2, ""); install_stage_tracker()->ReportFailure( kExtensionId2, InstallStageTracker::FailureReason::CRX_FETCH_URL_EMPTY); @@ -1168,9 +1164,8 @@ TEST_F(ForceInstalledMetricsTest, NonMisconfigurationFailurePresentCrxFetchUrlEmptyError) { SetupForceList(true /*is_from_store */); - auto extension = - ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), extension.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::LOADED); install_stage_tracker()->ReportInfoOnNoUpdatesFailure(kExtensionId2, "rate limit"); install_stage_tracker()->ReportFailure( @@ -1201,7 +1196,8 @@ kExtensionId1, ExtensionDownloaderDelegate::CacheStatus::CACHE_HIT); install_stage_tracker()->ReportDownloadingCacheStatus( kExtensionId2, ExtensionDownloaderDelegate::CacheStatus::CACHE_MISS); - auto ext1 = ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::PENDING); registry()->AddEnabled(ext1.get()); EXPECT_TRUE(fake_timer_->IsRunning()); fake_timer_->Fire();
diff --git a/chrome/browser/extensions/forced_extensions/force_installed_test_base.cc b/chrome/browser/extensions/forced_extensions/force_installed_test_base.cc index 25abd55b..2b5d322 100644 --- a/chrome/browser/extensions/forced_extensions/force_installed_test_base.cc +++ b/chrome/browser/extensions/forced_extensions/force_installed_test_base.cc
@@ -8,7 +8,6 @@ #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/extensions/external_provider_impl.h" -#include "chrome/browser/extensions/forced_extensions/force_installed_tracker.h" #include "chrome/browser/extensions/forced_extensions/install_stage_tracker.h" #include "chrome/test/base/testing_browser_process.h" #include "components/policy/core/common/policy_service_impl.h" @@ -16,7 +15,6 @@ #include "components/sync_preferences/testing_pref_service_syncable.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/pref_names.h" -#include "extensions/common/extension.h" #include "extensions/common/extension_builder.h" #include "testing/gmock/include/gmock/gmock.h" @@ -107,4 +105,23 @@ base::RunLoop().RunUntilIdle(); } +scoped_refptr<const Extension> ForceInstalledTestBase::CreateNewExtension( + const std::string& extension_name, + const std::string& extension_id, + const ForceInstalledTracker::ExtensionStatus& status) { + auto ext = ExtensionBuilder(extension_name).SetID(extension_id).Build(); + switch (status) { + case ForceInstalledTracker::ExtensionStatus::PENDING: + case ForceInstalledTracker::ExtensionStatus::FAILED: + break; + case ForceInstalledTracker::ExtensionStatus::LOADED: + force_installed_tracker()->OnExtensionLoaded(profile(), ext.get()); + break; + case ForceInstalledTracker::ExtensionStatus::READY: + force_installed_tracker()->OnExtensionLoaded(profile(), ext.get()); + force_installed_tracker()->OnExtensionReady(profile(), ext.get()); + } + return ext; +} + } // namespace extensions
diff --git a/chrome/browser/extensions/forced_extensions/force_installed_test_base.h b/chrome/browser/extensions/forced_extensions/force_installed_test_base.h index 61247c95..eac74ad 100644 --- a/chrome/browser/extensions/forced_extensions/force_installed_test_base.h +++ b/chrome/browser/extensions/forced_extensions/force_installed_test_base.h
@@ -5,10 +5,12 @@ #ifndef CHROME_BROWSER_EXTENSIONS_FORCED_EXTENSIONS_FORCE_INSTALLED_TEST_BASE_H_ #define CHROME_BROWSER_EXTENSIONS_FORCED_EXTENSIONS_FORCE_INSTALLED_TEST_BASE_H_ +#include "chrome/browser/extensions/forced_extensions/force_installed_tracker.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" #include "components/policy/core/common/mock_configuration_policy_provider.h" #include "content/public/test/browser_task_environment.h" +#include "extensions/common/extension.h" #include "testing/gtest/include/gtest/gtest.h" namespace sync_preferences { @@ -19,7 +21,6 @@ class ExtensionRegistry; class InstallStageTracker; -class ForceInstalledTracker; // This class is extended by tests to provide a setup for tracking installation // of force extensions. It also provides helper functions for creating and @@ -44,6 +45,14 @@ // kInstallForceList preference. void SetupEmptyForceList(); + // Creates a new extension with |extension_id| and |extension_name| and fakes + // its status by calling one of ForceInstalledTracker's + // ExtensionRegistryObserver override. + scoped_refptr<const Extension> CreateNewExtension( + const std::string& extension_name, + const std::string& extension_id, + const ForceInstalledTracker::ExtensionStatus& status); + Profile* profile() const { return profile_; } sync_preferences::TestingPrefServiceSyncable* prefs() const { return prefs_; }
diff --git a/chrome/browser/extensions/forced_extensions/force_installed_tracker_unittest.cc b/chrome/browser/extensions/forced_extensions/force_installed_tracker_unittest.cc index 14b3f1fdc..f6a67cf5 100644 --- a/chrome/browser/extensions/forced_extensions/force_installed_tracker_unittest.cc +++ b/chrome/browser/extensions/forced_extensions/force_installed_tracker_unittest.cc
@@ -8,11 +8,12 @@ #include "base/values.h" #include "chrome/browser/extensions/forced_extensions/force_installed_test_base.h" #include "extensions/common/extension.h" -#include "extensions/common/extension_builder.h" #include "testing/gtest/include/gtest/gtest.h" namespace extensions { +using ExtensionStatus = ForceInstalledTracker::ExtensionStatus; + class ForceInstalledTrackerTest : public ForceInstalledTestBase, public ForceInstalledTracker::Observer { public: @@ -56,8 +57,10 @@ // become ready for use. TEST_F(ForceInstalledTrackerTest, AllExtensionsInstalled) { SetupForceList(true /*is_from_store */); - auto ext1 = ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - auto ext2 = ExtensionBuilder(kExtensionName2).SetID(kExtensionId2).Build(); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::PENDING); + scoped_refptr<const Extension> ext2 = CreateNewExtension( + kExtensionName2, kExtensionId2, ExtensionStatus::PENDING); EXPECT_FALSE(loaded_called_); EXPECT_FALSE(ready_called_); EXPECT_FALSE(force_installed_tracker()->IsDoneLoading()); @@ -81,8 +84,8 @@ // all extensions have either successfully loaded or failed. TEST_F(ForceInstalledTrackerTest, ExtensionPendingInstall) { SetupForceList(true /*is_from_store */); - auto ext1 = ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), ext1.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::LOADED); EXPECT_FALSE(loaded_called_); EXPECT_FALSE(ready_called_); EXPECT_FALSE(force_installed_tracker()->IsDoneLoading()); @@ -100,10 +103,10 @@ // Start with a non-empty force-list, and install them, which triggers // observer. SetupForceList(true /*is_from_store */); - auto ext1 = ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - auto ext2 = ExtensionBuilder(kExtensionName2).SetID(kExtensionId2).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), ext1.get()); - force_installed_tracker()->OnExtensionLoaded(profile(), ext2.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::LOADED); + scoped_refptr<const Extension> ext2 = CreateNewExtension( + kExtensionName2, kExtensionId2, ExtensionStatus::LOADED); EXPECT_TRUE(loaded_called_); force_installed_tracker()->OnExtensionReady(profile(), ext1.get()); @@ -119,8 +122,8 @@ // either successfully loaded or failed. TEST_F(ForceInstalledTrackerTest, ExtensionsInstallationFailed) { SetupForceList(true /*is_from_store */); - auto ext1 = ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), ext1.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::LOADED); force_installed_tracker()->OnExtensionInstallationFailed( kExtensionId2, InstallStageTracker::FailureReason::INVALID_ID); EXPECT_TRUE(loaded_called_); @@ -134,22 +137,22 @@ TEST_F(ForceInstalledTrackerTest, ExtensionsStatus) { SetupForceList(true /*is_from_store */); EXPECT_EQ(force_installed_tracker()->extensions().at(kExtensionId1).status, - ForceInstalledTracker::ExtensionStatus::PENDING); + ExtensionStatus::PENDING); EXPECT_EQ(force_installed_tracker()->extensions().at(kExtensionId2).status, - ForceInstalledTracker::ExtensionStatus::PENDING); + ExtensionStatus::PENDING); - auto ext1 = ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), ext1.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::LOADED); force_installed_tracker()->OnExtensionInstallationFailed( kExtensionId2, InstallStageTracker::FailureReason::INVALID_ID); EXPECT_EQ(force_installed_tracker()->extensions().at(kExtensionId1).status, - ForceInstalledTracker::ExtensionStatus::LOADED); + ExtensionStatus::LOADED); EXPECT_EQ(force_installed_tracker()->extensions().at(kExtensionId2).status, - ForceInstalledTracker::ExtensionStatus::FAILED); + ExtensionStatus::FAILED); force_installed_tracker()->OnExtensionReady(profile(), ext1.get()); EXPECT_EQ(force_installed_tracker()->extensions().at(kExtensionId1).status, - ForceInstalledTracker::ExtensionStatus::READY); + ExtensionStatus::READY); } // This test verifies that resetting the policy before all force installed @@ -165,9 +168,8 @@ // installed extension is either ready for use or failed. TEST_F(ForceInstalledTrackerTest, AllExtensionsReady) { SetupForceList(true /*is_from_store */); - auto ext1 = ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build(); - force_installed_tracker()->OnExtensionLoaded(profile(), ext1.get()); - force_installed_tracker()->OnExtensionReady(profile(), ext1.get()); + scoped_refptr<const Extension> ext1 = CreateNewExtension( + kExtensionName1, kExtensionId1, ExtensionStatus::READY); force_installed_tracker()->OnExtensionInstallationFailed( kExtensionId2, InstallStageTracker::FailureReason::INVALID_ID); EXPECT_TRUE(loaded_called_);
diff --git a/chrome/browser/lacros/account_manager_facade_lacros.cc b/chrome/browser/lacros/account_manager_facade_lacros.cc index ad77517..dbaa6f30 100644 --- a/chrome/browser/lacros/account_manager_facade_lacros.cc +++ b/chrome/browser/lacros/account_manager_facade_lacros.cc
@@ -38,6 +38,18 @@ return is_initialized_; } +void AccountManagerFacadeLacros::ShowAddAccountDialog( + const AccountAdditionSource& source, + base::OnceCallback<void(const AccountAdditionResult& result)> callback) { + // TODO(crbug.com/1140469): implement this. +} + +void AccountManagerFacadeLacros::ShowReauthAccountDialog( + const AccountAdditionSource& source, + const std::string& email) { + // TODO(crbug.com/1140469): implement this. +} + void AccountManagerFacadeLacros::OnVersionCheck(uint32_t version) { if (version < kMinVersionWithObserver) { std::move(init_finished_).Run();
diff --git a/chrome/browser/lacros/account_manager_facade_lacros.h b/chrome/browser/lacros/account_manager_facade_lacros.h index 485efd7..6103c2f 100644 --- a/chrome/browser/lacros/account_manager_facade_lacros.h +++ b/chrome/browser/lacros/account_manager_facade_lacros.h
@@ -29,6 +29,12 @@ // AccountManagerFacade overrides: bool IsInitialized() override; + void ShowAddAccountDialog( + const AccountAdditionSource& source, + base::OnceCallback<void(const AccountAdditionResult& result)> callback) + override; + void ShowReauthAccountDialog(const AccountAdditionSource& source, + const std::string& email) override; // crosapi::mojom::AccountManagerObserver overrides: void OnTokenUpserted(crosapi::mojom::AccountPtr account) override;
diff --git a/chrome/browser/net/cookie_policy_browsertest.cc b/chrome/browser/net/cookie_policy_browsertest.cc index 57a9987..827a736 100644 --- a/chrome/browser/net/cookie_policy_browsertest.cc +++ b/chrome/browser/net/cookie_policy_browsertest.cc
@@ -51,8 +51,6 @@ // HTTPS server only serves a valid cert for localhost, so this is needed // to load pages from other hosts without an error. command_line->AppendSwitch(switches::kIgnoreCertificateErrors); - command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures, - "CookieStoreDocument"); } GURL GetURL(const std::string& host) {
diff --git a/chrome/browser/net/cookie_store_samesite_browsertest.cc b/chrome/browser/net/cookie_store_samesite_browsertest.cc index d88eec5e..70b44e42 100644 --- a/chrome/browser/net/cookie_store_samesite_browsertest.cc +++ b/chrome/browser/net/cookie_store_samesite_browsertest.cc
@@ -45,11 +45,6 @@ ASSERT_TRUE(https_server_.Start()); } - void SetUpCommandLine(base::CommandLine* command_line) override { - command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures, - "CookieStoreDocument"); - } - void NavigateToPageWithFrame(const std::string& host) { GURL main_url(https_server_.GetURL(host, "/iframe.html")); ui_test_utils::NavigateToURL(browser(), main_url);
diff --git a/chrome/browser/paint_preview/paint_preview_browsertest.cc b/chrome/browser/paint_preview/paint_preview_browsertest.cc index c5ab507b..d4bc4ff 100644 --- a/chrome/browser/paint_preview/paint_preview_browsertest.cc +++ b/chrome/browser/paint_preview/paint_preview_browsertest.cc
@@ -24,17 +24,44 @@ #include "components/paint_preview/common/test_utils.h" #include "components/ukm/test_ukm_recorder.h" #include "content/public/browser/notification_types.h" +#include "content/public/browser/render_process_host.h" #include "content/public/common/content_switches.h" #include "content/public/test/browser_test.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "services/metrics/public/cpp/ukm_builders.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "third_party/skia/include/core/SkPicture.h" #include "third_party/skia/include/core/SkStream.h" #include "url/gurl.h" namespace paint_preview { +class NoOpPaintPreviewRecorder : public mojom::PaintPreviewRecorder { + public: + NoOpPaintPreviewRecorder() = default; + ~NoOpPaintPreviewRecorder() override = default; + + NoOpPaintPreviewRecorder(const NoOpPaintPreviewRecorder&) = delete; + NoOpPaintPreviewRecorder& operator=(const NoOpPaintPreviewRecorder&) = delete; + + void CapturePaintPreview( + mojom::PaintPreviewCaptureParamsPtr params, + mojom::PaintPreviewRecorder::CapturePaintPreviewCallback callback) + override { + callback_ = std::move(callback); + } + + void BindRequest(mojo::ScopedInterfaceEndpointHandle handle) { + binding_.Bind(mojo::PendingAssociatedReceiver<mojom::PaintPreviewRecorder>( + std::move(handle))); + } + + private: + mojom::PaintPreviewRecorder::CapturePaintPreviewCallback callback_; + mojo::AssociatedReceiver<mojom::PaintPreviewRecorder> binding_{this}; +}; + // Test harness for a integration test of paint previews. In this test: // - Each RenderFrame has an instance of PaintPreviewRecorder attached. // - Each WebContents has an instance of PaintPreviewClient attached. @@ -42,6 +69,10 @@ class PaintPreviewBrowserTest : public InProcessBrowserTest, public testing::WithParamInterface<RecordingPersistence> { + public: + PaintPreviewBrowserTest(const PaintPreviewBrowserTest&) = delete; + PaintPreviewBrowserTest& operator=(const PaintPreviewBrowserTest&) = delete; + protected: PaintPreviewBrowserTest() = default; ~PaintPreviewBrowserTest() override = default; @@ -92,6 +123,15 @@ return params; } + void OverrideInterface(NoOpPaintPreviewRecorder* service) { + blink::AssociatedInterfaceProvider* remote_interfaces = + GetWebContents()->GetMainFrame()->GetRemoteAssociatedInterfaces(); + remote_interfaces->OverrideBinderForTesting( + mojom::PaintPreviewRecorder::Name_, + base::BindRepeating(&NoOpPaintPreviewRecorder::BindRequest, + base::Unretained(service))); + } + void WaitForLoadStopWithoutSuccessCheck() { // In many cases, the load may have finished before we get here. Only wait // if the tab still has a pending navigation. @@ -134,10 +174,6 @@ base::ScopedTempDir temp_dir_; net::EmbeddedTestServer http_server_; net::EmbeddedTestServer http_server_different_origin_; - - private: - PaintPreviewBrowserTest(const PaintPreviewBrowserTest&) = delete; - PaintPreviewBrowserTest& operator=(const PaintPreviewBrowserTest&) = delete; }; IN_PROC_BROWSER_TEST_P(PaintPreviewBrowserTest, CaptureFrame) { @@ -324,6 +360,79 @@ loop.Run(); } +// https://crbug.com/1146573 reproduction. If a renderer crashes, +// WebContentsObserver::RenderFrameDeleted. Paint preview implements this in an +// observer which in turn calls DecrementCapturerCount which can cause the +// WebContents to be reloaded on Android where we have auto-reload. This reload +// occurs *during* crash handling, leaving the frame in an invalid state and +// leading to a crash when it subsequently unloaded. +// This is fixed by deferring it to a PostTask. +// Flaky on Mac. TODO(https://crbug.com/1160608): Enabled this test. +#if defined(OS_MAC) +#define MAYBE_DontReloadInRenderProcessExit \ + DISABLED_DontReloadInRenderProcessExit +#else +#define MAYBE_DontReloadInRenderProcessExit DontReloadInRenderProcessExit +#endif +IN_PROC_BROWSER_TEST_P(PaintPreviewBrowserTest, + MAYBE_DontReloadInRenderProcessExit) { + LoadPage(http_server_.GetURL("a.com", "/title1.html")); + + content::WebContents* web_contents = GetWebContents(); + + // Override remote interfaces with a no-op. + NoOpPaintPreviewRecorder noop_recorder; + OverrideInterface(&noop_recorder); + + CreateClient(); + auto* client = PaintPreviewClient::FromWebContents(web_contents); + // Do this twice to simulate conditions for crash. + web_contents->IncrementCapturerCount(gfx::Size(), true); + web_contents->IncrementCapturerCount(gfx::Size(), true); + + // A callback that causes the frame to reload and end up in an invalid state + // if it is allowed to run during crash handling. + base::RunLoop loop; + auto params = MakeParams(); + bool did_run = false; + client->CapturePaintPreview( + params, web_contents->GetMainFrame(), + // This callback is now posted so it shouldn't cause a crash. + base::BindOnce( + [](content::WebContents* web_contents, bool* did_run_ptr, + base::UnguessableToken guid, mojom::PaintPreviewStatus status, + std::unique_ptr<CaptureResult> result) { + EXPECT_EQ(status, mojom::PaintPreviewStatus::kFailed); + EXPECT_EQ(result, nullptr); + // On Android crashed frames are marked as needing reload. + web_contents->GetController().SetNeedsReload(); + web_contents->DecrementCapturerCount(true); + web_contents->DecrementCapturerCount(true); + *did_run_ptr = true; + }, + web_contents, &did_run) + .Then(loop.QuitClosure())); + + // Crash the renderer. + { + base::ScopedAllowBlockingForTesting scope; + content::RenderProcessHost* process = + GetWebContents()->GetMainFrame()->GetProcess(); + content::RenderProcessHostWatcher crash_observer( + process, content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); + process->Shutdown(0); + crash_observer.Wait(); + } + + // The browser would have crashed before the loop exited if the callback was + // not posted. + if (!did_run) + loop.Run(); + + // Now navigate away and ensure that the frame unloads successfully. + LoadPage(http_server_.GetURL("a.com", "/title2.html")); +} + INSTANTIATE_TEST_SUITE_P(All, PaintPreviewBrowserTest, testing::Values(RecordingPersistence::kFileSystem,
diff --git a/chrome/browser/password_manager/generated_password_leak_detection_pref.cc b/chrome/browser/password_manager/generated_password_leak_detection_pref.cc index a016c56f..ea4c253 100644 --- a/chrome/browser/password_manager/generated_password_leak_detection_pref.cc +++ b/chrome/browser/password_manager/generated_password_leak_detection_pref.cc
@@ -141,14 +141,16 @@ identity_manager_observer_.RemoveAll(); } -void GeneratedPasswordLeakDetectionPref::OnPrimaryAccountSet( - const CoreAccountInfo& primary_account_info) { - NotifyObservers(kGeneratedPasswordLeakDetectionPref); -} - -void GeneratedPasswordLeakDetectionPref::OnPrimaryAccountCleared( - const CoreAccountInfo& previous_primary_account_info) { - NotifyObservers(kGeneratedPasswordLeakDetectionPref); +void GeneratedPasswordLeakDetectionPref::OnPrimaryAccountChanged( + const signin::PrimaryAccountChangeEvent& event_details) { + switch (event_details.GetEventTypeFor(signin::ConsentLevel::kSync)) { + case signin::PrimaryAccountChangeEvent::Type::kSet: + case signin::PrimaryAccountChangeEvent::Type::kCleared: + NotifyObservers(kGeneratedPasswordLeakDetectionPref); + break; + case signin::PrimaryAccountChangeEvent::Type::kNone: + break; + } } void GeneratedPasswordLeakDetectionPref::OnExtendedAccountInfoUpdated(
diff --git a/chrome/browser/password_manager/generated_password_leak_detection_pref.h b/chrome/browser/password_manager/generated_password_leak_detection_pref.h index f57e601..9cfe2b2 100644 --- a/chrome/browser/password_manager/generated_password_leak_detection_pref.h +++ b/chrome/browser/password_manager/generated_password_leak_detection_pref.h
@@ -39,10 +39,8 @@ void OnSourcePreferencesChanged(); // IdentityManager::Observer implementation. - void OnPrimaryAccountSet( - const CoreAccountInfo& primary_account_info) override; - void OnPrimaryAccountCleared( - const CoreAccountInfo& previous_primary_account_info) override; + void OnPrimaryAccountChanged( + const signin::PrimaryAccountChangeEvent& event_details) override; void OnExtendedAccountInfoUpdated(const AccountInfo& info) override; void OnExtendedAccountInfoRemoved(const AccountInfo& info) override;
diff --git a/chrome/browser/policy/messaging_layer/storage/storage.cc b/chrome/browser/policy/messaging_layer/storage/storage.cc index 9e5a41f..7f2c51b 100644 --- a/chrome/browser/policy/messaging_layer/storage/storage.cc +++ b/chrome/browser/policy/messaging_layer/storage/storage.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/policy/messaging_layer/storage/storage.h" +#include <cstdint> #include <utility> #include <vector> @@ -22,6 +23,7 @@ #include "base/threading/thread.h" #include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/policy/messaging_layer/encryption/encryption_module.h" +#include "chrome/browser/policy/messaging_layer/encryption/verification.h" #include "chrome/browser/policy/messaging_layer/storage/storage_configuration.h" #include "chrome/browser/policy/messaging_layer/storage/storage_queue.h" #include "chrome/browser/policy/messaging_layer/util/status.h" @@ -29,6 +31,7 @@ #include "chrome/browser/policy/messaging_layer/util/statusor.h" #include "chrome/browser/policy/messaging_layer/util/task_runner_context.h" #include "components/policy/proto/record.pb.h" +#include "third_party/boringssl/src/include/openssl/curve25519.h" #include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl.h" namespace reporting { @@ -157,8 +160,9 @@ class Storage::KeyInStorage { public: - explicit KeyInStorage(const base::FilePath& directory) - : directory_(directory) {} + explicit KeyInStorage(base::StringPiece signature_verification_public_key, + const base::FilePath& directory) + : verifier_(signature_verification_public_key), directory_(directory) {} ~KeyInStorage() = default; // Uploads signed encryption key to a file with an |index| >= @@ -219,6 +223,24 @@ signed_encryption_key_result.value().second.public_key_id()); } + Status VerifySignature(const SignedEncryptionInfo& signed_encryption_key) { + if (signed_encryption_key.public_asymmetric_key().size() != + X25519_PUBLIC_VALUE_LEN) { + return Status{error::FAILED_PRECONDITION, "Key size mismatch"}; + } + char value_to_verify[sizeof(Encryptor::PublicKeyId) + + X25519_PUBLIC_VALUE_LEN]; + const Encryptor::PublicKeyId public_key_id = + signed_encryption_key.public_key_id(); + memcpy(value_to_verify, &public_key_id, sizeof(Encryptor::PublicKeyId)); + memcpy(value_to_verify + sizeof(Encryptor::PublicKeyId), + signed_encryption_key.public_asymmetric_key().data(), + X25519_PUBLIC_VALUE_LEN); + return verifier_.Verify( + std::string(value_to_verify, sizeof(value_to_verify)), + signed_encryption_key.signature()); + } + private: // Writes key into file. Called during key upload. Status WriteKeyInfoFile(uint64_t new_file_index, @@ -375,8 +397,16 @@ } } - // Parsed successfully. - // TODO(b/170054326): Validate signature. + // Parsed successfully. Verify signature of the whole "id"+"key" string. + const auto signature_verification_status = + VerifySignature(signed_encryption_key); + if (!signature_verification_status.ok()) { + LOG(WARNING) << "Loaded key failed verification, status=" + << signature_verification_status << ", full_name='" + << key_file_it->second.MaybeAsASCII() << "'"; + continue; + } + // Validated successfully. Return file name and signed key proto. return std::make_pair(key_file_it->second, signed_encryption_key); } @@ -392,6 +422,8 @@ // to successfully encrypt records and for the server to then decrypt them. std::atomic<uint64_t> next_key_file_index_{0}; + SignatureVerifier verifier_; + const base::FilePath directory_; }; @@ -537,7 +569,9 @@ StartUploadCb start_upload_cb) : options_(options), encryption_module_(encryption_module), - key_in_storage_(std::make_unique<KeyInStorage>(options.directory())), + key_in_storage_(std::make_unique<KeyInStorage>( + options.signature_verification_public_key(), + options.directory())), start_upload_cb_(std::move(start_upload_cb)) {} Storage::~Storage() = default; @@ -571,7 +605,14 @@ } void Storage::UpdateEncryptionKey(SignedEncryptionInfo signed_encryption_key) { - // TODO(b/170054326): Verify received key signature. Bail out if failed. + // Verify received key signature. Bail out if failed. + const auto signature_verification_status = + key_in_storage_->VerifySignature(signed_encryption_key); + if (!signature_verification_status.ok()) { + LOG(WARNING) << "Key failed verification, status=" + << signature_verification_status; + return; + } // Assign the received key to encryption module. encryption_module_->UpdateAsymmetricKey(
diff --git a/chrome/browser/policy/messaging_layer/storage/storage_configuration.cc b/chrome/browser/policy/messaging_layer/storage/storage_configuration.cc new file mode 100644 index 0000000..96dfe382 --- /dev/null +++ b/chrome/browser/policy/messaging_layer/storage/storage_configuration.cc
@@ -0,0 +1,15 @@ +// Copyright 2020 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/policy/messaging_layer/storage/storage_configuration.h" + +namespace reporting { + +StorageOptions::StorageOptions() = default; +StorageOptions::StorageOptions(const StorageOptions& options) = default; +StorageOptions& StorageOptions::operator=(const StorageOptions& options) = + default; +StorageOptions::~StorageOptions() = default; + +} // namespace reporting
diff --git a/chrome/browser/policy/messaging_layer/storage/storage_configuration.h b/chrome/browser/policy/messaging_layer/storage/storage_configuration.h index 8c847bd..d47296a7 100644 --- a/chrome/browser/policy/messaging_layer/storage/storage_configuration.h +++ b/chrome/browser/policy/messaging_layer/storage/storage_configuration.h
@@ -5,6 +5,12 @@ #ifndef CHROME_BROWSER_POLICY_MESSAGING_LAYER_STORAGE_STORAGE_CONFIGURATION_H_ #define CHROME_BROWSER_POLICY_MESSAGING_LAYER_STORAGE_STORAGE_CONFIGURATION_H_ +#include <string> + +#include "base/files/file_path.h" +#include "base/strings/string_piece.h" +#include "base/time/time.h" + namespace reporting { // Storage options class allowing to set parameters individually, e.g.: @@ -16,13 +22,20 @@ // callback); class StorageOptions { public: - StorageOptions() = default; - StorageOptions(const StorageOptions& options) = default; - StorageOptions& operator=(const StorageOptions& options) = default; + StorageOptions(); + StorageOptions(const StorageOptions& options); + StorageOptions& operator=(const StorageOptions& options); + ~StorageOptions(); StorageOptions& set_directory(const base::FilePath& directory) { directory_ = directory; return *this; } + StorageOptions& set_signature_verification_public_key( + base::StringPiece signature_verification_public_key) { + signature_verification_public_key_ = + std::string(signature_verification_public_key); + return *this; + } StorageOptions& set_max_record_size(size_t max_record_size) { max_record_size_ = max_record_size; return *this; @@ -40,6 +53,9 @@ return *this; } const base::FilePath& directory() const { return directory_; } + base::StringPiece signature_verification_public_key() const { + return signature_verification_public_key_; + } size_t max_record_size() const { return max_record_size_; } uint64_t max_total_files_size() const { return max_total_files_size_; } uint64_t max_total_memory_size() const { return max_total_memory_size_; } @@ -49,6 +65,10 @@ // Subdirectory of the location assigned for this Storage. base::FilePath directory_; + // Public key for signature verification when encryption key + // is delivered to Storage. + std::string signature_verification_public_key_; + // Maximum record size. size_t max_record_size_ = 1 * 1024LL * 1024LL; // 1 MiB
diff --git a/chrome/browser/policy/messaging_layer/storage/storage_unittest.cc b/chrome/browser/policy/messaging_layer/storage/storage_unittest.cc index 5cf47df..eb4ccd9 100644 --- a/chrome/browser/policy/messaging_layer/storage/storage_unittest.cc +++ b/chrome/browser/policy/messaging_layer/storage/storage_unittest.cc
@@ -438,6 +438,8 @@ // Enable encryption. scoped_feature_list_.InitFromCommandLine( {EncryptionModule::kEncryptedReporting}, {}); + // Generate signing key pair. + ED25519_keypair(signature_verification_public_key_, signing_private_key_); // Create decryption module. auto decryptor_result = Decryptor::Create(); ASSERT_OK(decryptor_result.status()) << decryptor_result.status(); @@ -495,9 +497,16 @@ } StorageOptions BuildTestStorageOptions() const { - return StorageOptions() - .set_directory(base::FilePath(location_.GetPath())) - .set_single_file_size(::testing::get<1>(GetParam())); + auto options = StorageOptions() + .set_directory(base::FilePath(location_.GetPath())) + .set_single_file_size(::testing::get<1>(GetParam())); + if (::testing::get<0>(GetParam())) { + // Encryption enabled. + options.set_signature_verification_public_key(std::string( + reinterpret_cast<const char*>(signature_verification_public_key_), + ED25519_PUBLIC_KEY_LEN)); + } + return options; } StatusOr<std::unique_ptr<Storage::UploaderInterface>> BuildMockUploader( @@ -534,8 +543,9 @@ void GenerateAndDeliverKey(Storage* storage) { ASSERT_TRUE(decryptor_) << "Decryptor not created"; // Generate new pair of private key and public value. - uint8_t public_value[X25519_PUBLIC_VALUE_LEN]; uint8_t private_key[X25519_PRIVATE_KEY_LEN]; + Encryptor::PublicKeyId public_key_id; + uint8_t public_value[X25519_PUBLIC_VALUE_LEN]; X25519_keypair(public_value, private_key); TestEvent<StatusOr<Encryptor::PublicKeyId>> prepare_key_pair; decryptor_->RecordKeyPair( @@ -546,13 +556,28 @@ prepare_key_pair.cb()); auto prepare_key_result = prepare_key_pair.result(); ASSERT_OK(prepare_key_result.status()); - Encryptor::PublicKeyId new_public_key_id = prepare_key_result.ValueOrDie(); + public_key_id = prepare_key_result.ValueOrDie(); // Deliver public key to storage. SignedEncryptionInfo signed_encryption_key; signed_encryption_key.set_public_asymmetric_key(std::string( reinterpret_cast<const char*>(public_value), X25519_PUBLIC_VALUE_LEN)); - signed_encryption_key.set_public_key_id(new_public_key_id); - // TODO(b/170054326): Add key signature. + signed_encryption_key.set_public_key_id(public_key_id); + // Sign public key. + uint8_t + value_to_sign[sizeof(Encryptor::PublicKeyId) + X25519_PUBLIC_VALUE_LEN]; + memcpy(value_to_sign, &public_key_id, sizeof(Encryptor::PublicKeyId)); + memcpy(value_to_sign + sizeof(Encryptor::PublicKeyId), public_value, + X25519_PUBLIC_VALUE_LEN); + uint8_t signature[ED25519_SIGNATURE_LEN]; + ASSERT_THAT(ED25519_sign(signature, value_to_sign, sizeof(value_to_sign), + signing_private_key_), + Eq(1)); + signed_encryption_key.set_signature(std::string( + reinterpret_cast<const char*>(signature), ED25519_SIGNATURE_LEN)); + // Double check signature. + ASSERT_THAT(ED25519_verify(value_to_sign, sizeof(value_to_sign), signature, + signature_verification_public_key_), + Eq(1)); storage->UpdateEncryptionKey(signed_encryption_key); } @@ -561,6 +586,9 @@ base::test::ScopedFeatureList scoped_feature_list_; + uint8_t signature_verification_public_key_[ED25519_PUBLIC_KEY_LEN]; + uint8_t signing_private_key_[ED25519_PRIVATE_KEY_LEN]; + base::ScopedTempDir location_; scoped_refptr<Decryptor> decryptor_; scoped_refptr<Storage> storage_;
diff --git a/chrome/browser/policy/messaging_layer/upload/record_handler_impl.cc b/chrome/browser/policy/messaging_layer/upload/record_handler_impl.cc index 4815d57..e5fc66e 100644 --- a/chrome/browser/policy/messaging_layer/upload/record_handler_impl.cc +++ b/chrome/browser/policy/messaging_layer/upload/record_handler_impl.cc
@@ -257,17 +257,14 @@ signed_encryption_key_record->FindStringKey("publicKey"); const auto public_key_id_result = signed_encryption_key_record->FindIntKey("publicKeyId"); - // TODO(b/170054326): Make signature mandatory too. - // const std::string* public_key_signature_str = - // signed_encryption_key_record->FindStringKey("publicKeySignature"); + const std::string* public_key_signature_str = + signed_encryption_key_record->FindStringKey("publicKeySignature"); std::string public_key; std::string public_key_signature; if (public_key_str != nullptr && base::Base64Decode(*public_key_str, &public_key) && - // TODO(b/170054326): Make signature mandatory too. - // public_key_signature_str != nullptr - // base::Base64Decode(*public_key_signature_str, - // &public_key_signature) && + public_key_signature_str != nullptr && + base::Base64Decode(*public_key_signature_str, &public_key_signature) && public_key_id_result.has_value()) { SignedEncryptionInfo signed_encryption_key; signed_encryption_key.set_public_asymmetric_key(public_key);
diff --git a/chrome/browser/policy/messaging_layer/upload/record_handler_impl_unittest.cc b/chrome/browser/policy/messaging_layer/upload/record_handler_impl_unittest.cc index 4162b8e8..f8234f8 100644 --- a/chrome/browser/policy/messaging_layer/upload/record_handler_impl_unittest.cc +++ b/chrome/browser/policy/messaging_layer/upload/record_handler_impl_unittest.cc
@@ -28,9 +28,13 @@ #include "testing/gtest/include/gtest/gtest.h" using ::testing::_; +using ::testing::AllOf; using ::testing::Eq; +using ::testing::Gt; using ::testing::Invoke; +using ::testing::IsEmpty; using ::testing::MockFunction; +using ::testing::Not; using ::testing::Property; using ::testing::Return; using ::testing::StrictMock; @@ -132,7 +136,6 @@ encryption_settings.SetStringKey("publicKey", public_key); encryption_settings.SetIntKey("publicKeyId", 12345); std::string public_key_signature; - // TODO(b/170054326): Generate signature. base::Base64Encode("PUBLIC KEY SIG", &public_key_signature); encryption_settings.SetStringKey("publicKeySignature", public_key_signature); return encryption_settings; @@ -249,7 +252,12 @@ StrictMock<TestCompletionResponder> responder; TestCallbackWaiter responder_waiter; - EXPECT_CALL(encryption_key_attached, Call(_)) + EXPECT_CALL( + encryption_key_attached, + Call(AllOf(Property(&SignedEncryptionInfo::public_asymmetric_key, + Not(IsEmpty())), + Property(&SignedEncryptionInfo::public_key_id, Gt(0)), + Property(&SignedEncryptionInfo::signature, Not(IsEmpty()))))) .Times(need_encryption_key() ? 1 : 0); EXPECT_CALL( @@ -313,7 +321,12 @@ .WillOnce(Invoke([&responder_waiter]() { responder_waiter.Signal(); })); StrictMock<TestEncryptionKeyAttached> encryption_key_attached; - EXPECT_CALL(encryption_key_attached, Call(_)) + EXPECT_CALL( + encryption_key_attached, + Call(AllOf(Property(&SignedEncryptionInfo::public_asymmetric_key, + Not(IsEmpty())), + Property(&SignedEncryptionInfo::public_key_id, Gt(0)), + Property(&SignedEncryptionInfo::signature, Not(IsEmpty()))))) .Times(need_encryption_key() ? 1 : 0); auto encryption_key_attached_callback = @@ -389,7 +402,12 @@ .WillOnce(Invoke([&responder_waiter]() { responder_waiter.Signal(); })); StrictMock<TestEncryptionKeyAttached> encryption_key_attached; - EXPECT_CALL(encryption_key_attached, Call(_)) + EXPECT_CALL( + encryption_key_attached, + Call(AllOf(Property(&SignedEncryptionInfo::public_asymmetric_key, + Not(IsEmpty())), + Property(&SignedEncryptionInfo::public_key_id, Gt(0)), + Property(&SignedEncryptionInfo::signature, Not(IsEmpty()))))) .Times(need_encryption_key() ? 1 : 0); auto encryption_key_attached_callback = base::BindRepeating(&TestEncryptionKeyAttached::Call,
diff --git a/chrome/browser/policy/messaging_layer/upload/upload_client_unittest.cc b/chrome/browser/policy/messaging_layer/upload/upload_client_unittest.cc index 7b415dc..11bae9c0 100644 --- a/chrome/browser/policy/messaging_layer/upload/upload_client_unittest.cc +++ b/chrome/browser/policy/messaging_layer/upload/upload_client_unittest.cc
@@ -33,9 +33,14 @@ using ::policy::MockCloudPolicyClient; using ::testing::_; +using ::testing::AllOf; +using ::testing::Gt; using ::testing::Invoke; using ::testing::InvokeArgument; +using ::testing::IsEmpty; using ::testing::MockFunction; +using ::testing::Not; +using ::testing::Property; using ::testing::StrictMock; using ::testing::WithArgs; @@ -154,7 +159,6 @@ encryption_settings.SetStringKey("publicKey", public_key); encryption_settings.SetIntKey("publicKeyId", 12345); std::string public_key_signature; - // TODO(b/170054326): Generate signature. base::Base64Encode("PUBLIC KEY SIG", &public_key_signature); encryption_settings.SetStringKey("publicKeySignature", public_key_signature); @@ -240,7 +244,12 @@ TestCallbackWaiterWithCounter waiter(kExpectedCallTimes); StrictMock<TestEncryptionKeyAttached> encryption_key_attached; - EXPECT_CALL(encryption_key_attached, Call(_)) + EXPECT_CALL( + encryption_key_attached, + Call(AllOf(Property(&SignedEncryptionInfo::public_asymmetric_key, + Not(IsEmpty())), + Property(&SignedEncryptionInfo::public_key_id, Gt(0)), + Property(&SignedEncryptionInfo::signature, Not(IsEmpty()))))) .Times(need_encryption_key() ? 1 : 0); auto encryption_key_attached_cb = base::BindRepeating(&TestEncryptionKeyAttached::Call,
diff --git a/chrome/browser/profiles/profile_browsertest.cc b/chrome/browser/profiles/profile_browsertest.cc index 58e9e54..11c48ce 100644 --- a/chrome/browser/profiles/profile_browsertest.cc +++ b/chrome/browser/profiles/profile_browsertest.cc
@@ -48,6 +48,7 @@ #include "chrome/common/chrome_paths.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/testing_profile.h" #include "chrome/test/base/ui_test_utils.h" #include "components/prefs/pref_service.h" #include "components/version_info/version_info.h" @@ -947,17 +948,38 @@ #if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH) // TODO(https://crbug.com/1125474): Expand to cover ChromeOS. -IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, ProfileLifetimeTestUnderOneMinute) { +class GuestProfileLifetimeBrowserTest + : public ProfileBrowserTest, + public testing::WithParamInterface<bool> { + public: + GuestProfileLifetimeBrowserTest() : is_ephemeral_(GetParam()) { + // Change the value if Ephemeral is not supported. + is_ephemeral_ &= + TestingProfile::SetScopedFeatureListForEphemeralGuestProfiles( + scoped_feature_list_, is_ephemeral_); + } + + bool is_ephemeral() const { return is_ephemeral_; } + + private: + bool is_ephemeral_; + base::test::ScopedFeatureList scoped_feature_list_; +}; + +IN_PROC_BROWSER_TEST_P(GuestProfileLifetimeBrowserTest, UnderOneMinute) { base::HistogramTester tester; Browser* browser = CreateGuestBrowser(); BrowserCloseObserver close_observer(browser); BrowserList::CloseAllBrowsersWithProfile(browser->profile()); close_observer.Wait(); - tester.ExpectUniqueSample("Profile.Guest.OTR.Lifetime", 0, 1); + tester.ExpectUniqueSample("Profile.Guest.OTR.Lifetime", 0, + is_ephemeral() ? 0 : 1); + tester.ExpectUniqueSample("Profile.Guest.Ephemeral.Lifetime", 0, + is_ephemeral() ? 1 : 0); } -IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, ProfileLifetimeTestOneHour) { +IN_PROC_BROWSER_TEST_P(GuestProfileLifetimeBrowserTest, OneHour) { base::HistogramTester tester; Browser* browser = CreateGuestBrowser(); BrowserCloseObserver close_observer(browser); @@ -966,9 +988,16 @@ base::Time::Now() - base::TimeDelta::FromSeconds(60) * 60); BrowserList::CloseAllBrowsersWithProfile(browser->profile()); close_observer.Wait(); - tester.ExpectUniqueSample("Profile.Guest.OTR.Lifetime", 60, 1); + tester.ExpectUniqueSample("Profile.Guest.OTR.Lifetime", 60, + is_ephemeral() ? 0 : 1); + tester.ExpectUniqueSample("Profile.Guest.Ephemeral.Lifetime", 60, + is_ephemeral() ? 1 : 0); } +INSTANTIATE_TEST_SUITE_P(AllGuestTypes, + GuestProfileLifetimeBrowserTest, + /*is_ephemeral=*/testing::Bool()); + class EphemeralGuestProfileBrowserTest : public ProfileBrowserTest { public: EphemeralGuestProfileBrowserTest() { @@ -990,30 +1019,6 @@ EXPECT_TRUE(guest_profile->IsEphemeralGuestProfile()); } -IN_PROC_BROWSER_TEST_F(EphemeralGuestProfileBrowserTest, - ProfileLifetimeTestUnderOneMinute) { - base::HistogramTester tester; - Browser* browser = CreateGuestBrowser(); - BrowserCloseObserver close_observer(browser); - - BrowserList::CloseAllBrowsersWithProfile(browser->profile()); - close_observer.Wait(); - tester.ExpectUniqueSample("Profile.Guest.Ephemeral.Lifetime", 0, 1); -} - -IN_PROC_BROWSER_TEST_F(EphemeralGuestProfileBrowserTest, - ProfileLifetimeTestOneHour) { - base::HistogramTester tester; - Browser* browser = CreateGuestBrowser(); - BrowserCloseObserver close_observer(browser); - - browser->profile()->SetCreationTimeForTesting( - base::Time::Now() - base::TimeDelta::FromSeconds(60) * 60); - BrowserList::CloseAllBrowsersWithProfile(browser->profile()); - close_observer.Wait(); - tester.ExpectUniqueSample("Profile.Guest.Ephemeral.Lifetime", 60, 1); -} - // Tests if ephemeral Guest profile paths are persistent as long as one does not // close all Guest browsers. IN_PROC_BROWSER_TEST_F(EphemeralGuestProfileBrowserTest,
diff --git a/chrome/browser/profiles/profile_keep_alive_types.h b/chrome/browser/profiles/profile_keep_alive_types.h index 23e6ce6..1979c14 100644 --- a/chrome/browser/profiles/profile_keep_alive_types.h +++ b/chrome/browser/profiles/profile_keep_alive_types.h
@@ -9,22 +9,29 @@ // Refers to what a ScopedProfileKeepAlive's lifetime is tied to, to help // debugging. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +// +// Keep this in sync with ProfileKeepAliveOrigin in enums.xml. enum class ProfileKeepAliveOrigin { // When a Profile gets created by ProfileManager, it initially has this type // of keep-alive. This ensures that the Profile has a refcount >=1, at least // until RemoveKeepAlive() gets called. // // When a kBrowserWindow keep-alive gets added, this one gets removed. - kWaitingForFirstBrowserWindow, + kWaitingForFirstBrowserWindow = 0, // This Profile has browser windows open. - kBrowserWindow, + kBrowserWindow = 1, // This Profile is running extensions with persistent background scripts. - kBackgroundMode, + kBackgroundMode = 2, // A child off-the-record profile holds a strong reference to its parent. - kOffTheRecordProfile, + kOffTheRecordProfile = 3, + + kMaxValue = kOffTheRecordProfile, }; std::ostream& operator<<(std::ostream& out,
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc index 23380358..b8eb9ecd 100644 --- a/chrome/browser/profiles/profile_manager.cc +++ b/chrome/browser/profiles/profile_manager.cc
@@ -378,6 +378,20 @@ ProfileManager::~ProfileManager() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + if (base::FeatureList::IsEnabled(features::kDestroyProfileOnBrowserClose)) { + // Ideally, all the keepalives should've been cleared already. Report + // metrics for incorrect usage of ScopedProfileKeepAlive. + for (const auto& path_and_profile_info : profiles_info_) { + const ProfileInfo* profile_info = path_and_profile_info.second.get(); + for (const auto& origin_and_count : profile_info->keep_alives) { + ProfileKeepAliveOrigin origin = origin_and_count.first; + int count = origin_and_count.second; + if (count > 0) { + UMA_HISTOGRAM_ENUMERATION("Profile.KeepAliveLeakAtShutdown", origin); + } + } + } + } } // static @@ -1278,8 +1292,10 @@ int& waiting_for_first_browser_window = info->keep_alives[ProfileKeepAliveOrigin::kWaitingForFirstBrowserWindow]; - if (waiting_for_first_browser_window != 0) + if (origin == ProfileKeepAliveOrigin::kBrowserWindow && + waiting_for_first_browser_window != 0) { waiting_for_first_browser_window = 0; + } } void ProfileManager::RemoveKeepAlive(const Profile* profile,
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn index 54206f0..77e8483 100644 --- a/chrome/browser/resources/BUILD.gn +++ b/chrome/browser/resources/BUILD.gn
@@ -68,6 +68,10 @@ ] } + if (enable_pdf) { + public_deps += [ "pdf:pdf_resources" ] + } + if (enable_print_preview) { public_deps += [ "print_preview:print_preview_resources" ] } @@ -178,10 +182,6 @@ grit("component_extension_resources") { source = "component_extension_resources.grd" - if (enable_pdf) { - deps = [ "//chrome/browser/resources/pdf:web_components" ] - } - defines = chrome_grit_defines if (enable_hangout_services_extension) { defines += [ "enable_hangout_services_extension" ]
diff --git a/chrome/browser/resources/component_extension_resources.grd b/chrome/browser/resources/component_extension_resources.grd index e475112..d56d4e6 100644 --- a/chrome/browser/resources/component_extension_resources.grd +++ b/chrome/browser/resources/component_extension_resources.grd
@@ -93,9 +93,6 @@ <include name="IDR_ARC_SUPPORT_RECOMMEND_APP_LIST_VIEW_JS" file="chromeos/arc_support/recommend_app_list_view.js" type="BINDATA" /> <include name="IDR_ARC_SUPPORT_RECOMMEND_APP_LIST_VIEW_HTML" file="chromeos/arc_support/recommend_app_list_view.html" type="chrome_html" flattenhtml="true" /> </if> - <if expr="enable_plugins"> - <part file="pdf/pdf_resources.grdp" /> - </if> <include name="IDR_CRYPTOTOKEN_UTIL_JS" file="cryptotoken/util.js" type="BINDATA" /> <include name="IDR_CRYPTOTOKEN_B64_JS" file="cryptotoken/b64.js" type="BINDATA" /> <include name="IDR_CRYPTOTOKEN_COUNTDOWN_JS" file="cryptotoken/countdown.js" type="BINDATA" />
diff --git a/chrome/browser/resources/pdf/BUILD.gn b/chrome/browser/resources/pdf/BUILD.gn index da52f99..dd25aa9 100644 --- a/chrome/browser/resources/pdf/BUILD.gn +++ b/chrome/browser/resources/pdf/BUILD.gn
@@ -3,9 +3,122 @@ # found in the LICENSE file. import("//build/config/chromeos/ui_mode.gni") +import("//chrome/common/features.gni") import("//pdf/features.gni") import("//third_party/closure_compiler/compile_js.gni") +import("//tools/grit/grit_rule.gni") +import("//tools/grit/preprocess_if_expr.gni") import("//tools/polymer/html_to_js.gni") +import("//ui/webui/resources/tools/generate_grd.gni") + +preprocess_folder = "preprocessed" +preprocess_manifest = "preprocessed_manifest.json" +preprocess_gen_manifest = "preprocessed_gen_manifest.json" + +assert(enable_pdf, "enable_pdf check failed") + +preprocess_if_expr("preprocess") { + in_folder = "./" + out_folder = "$target_gen_dir/$preprocess_folder" + out_manifest = "$target_gen_dir/$preprocess_manifest" + in_files = [ + "bookmark_type.js", + "browser_api.js", + "constants.js", + "controller.js", + "gesture_detector.js", + "index.css", + "index.html", + "local_storage_proxy.js", + "main.js", + "metrics.js", + "navigator.js", + "open_pdf_params_parser.js", + "pdf_scripting_api.js", + "pdf_viewer_base.js", + "pdf_viewer_utils.js", + "toolbar_manager.js", + "viewport.js", + "viewport_scroller.js", + "zoom_manager.js", + ] + + if (is_chromeos) { + in_files += [ + "ink_controller.js", + "ink/index.html", + "ink/ink_api.js", + ] + } +} + +preprocess_if_expr("preprocess_generated") { + deps = [ ":web_components" ] + in_folder = target_gen_dir + out_folder = "$target_gen_dir/$preprocess_folder" + out_manifest = "$target_gen_dir/$preprocess_gen_manifest" + in_files = [ + "elements/icons.js", + "elements/shared-css.js", + "elements/shared-vars.js", + "elements/viewer-bookmark.js", + "elements/viewer-document-outline.js", + "elements/viewer-download-controls.js", + "elements/viewer-error-screen.js", + "elements/viewer-page-selector.js", + "elements/viewer-password-screen.js", + "elements/viewer-pdf-sidenav.js", + "elements/viewer-pdf-toolbar.js", + "elements/viewer-pdf-toolbar-new.js", + "elements/viewer-properties-dialog.js", + "elements/viewer-thumbnail-bar.js", + "elements/viewer-thumbnail.js", + "elements/viewer-toolbar-dropdown.js", + "elements/viewer-zoom-button.js", + "elements/viewer-zoom-toolbar.js", + "pdf_viewer.js", + "pdf_viewer_shared_style.js", + ] + if (is_chromeos) { + in_files += [ + "elements/viewer-annotations-bar.js", + "elements/viewer-annotations-mode-dialog.js", + "elements/viewer-form-warning.js", + "elements/viewer-ink-host.js", + "elements/viewer-pen-options.js", + ] + } +} + +generate_grd("build_grd") { + deps = [ + ":preprocess", + ":preprocess_generated", + ] + manifest_files = [ + "$target_gen_dir/$preprocess_manifest", + "$target_gen_dir/$preprocess_gen_manifest", + ] + grd_prefix = "pdf" + out_grd = "$target_gen_dir/resources.grd" + resource_path_prefix = "pdf" +} + +grit("pdf_resources") { + defines = chrome_grit_defines + + enable_input_discovery_for_gn_analyze = false + source = "$target_gen_dir/resources.grd" + deps = [ ":build_grd" ] + + outputs = [ + "grit/pdf_resources.h", + "grit/pdf_resources_map.cc", + "grit/pdf_resources_map.h", + "pdf_resources.pak", + ] + output_dir = "$root_gen_dir/chrome" +} assert(enable_pdf, "enable_pdf check failed") @@ -26,7 +139,7 @@ group("closure_compile") { deps = [ - ":pdf_resources", + ":closure_compile_local", "elements:closure_compile", ] if (is_chromeos_ash) { @@ -220,7 +333,7 @@ ] } -js_type_check("pdf_resources") { +js_type_check("closure_compile_local") { is_polymer3 = true deps = [ ":annotation_tool",
diff --git a/chrome/browser/resources/pdf/pdf_resources.grdp b/chrome/browser/resources/pdf/pdf_resources.grdp deleted file mode 100644 index 1016c65f..0000000 --- a/chrome/browser/resources/pdf/pdf_resources.grdp +++ /dev/null
@@ -1,55 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<grit-part> - <!-- Note that resources included here that are used in Print Preview - also must be included in print_preview_ui.cc such these resources - will be exposed to PDF in print preview. --> - <include name="IDR_PDF_INDEX_HTML" file="pdf/index.html" type="BINDATA" preprocess="true" /> - <include name="IDR_PDF_INDEX_CSS" file="pdf/index.css" type="BINDATA" /> - <include name="IDR_PDF_MAIN_JS" file="pdf/main.js" type="BINDATA" preprocess="true" /> - <include name="IDR_PDF_PDF_VIEWER_UTILS_JS" file="pdf/pdf_viewer_utils.js" type="BINDATA" /> - <include name="IDR_PDF_PDF_VIEWER_BASE_JS" file="pdf/pdf_viewer_base.js" type="BINDATA" /> - <include name="IDR_PDF_PDF_VIEWER_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/pdf_viewer.js" use_base_dir="false" type="BINDATA" preprocess="true" /> - <include name="IDR_PDF_PDF_VIEWER_SHARED_STYLE_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/pdf_viewer_shared_style.js" use_base_dir="false" type="BINDATA" /> - <include name="IDR_PDF_BOOKMARK_TYPE_JS" file="pdf/bookmark_type.js" type="BINDATA" /> - <include name="IDR_PDF_CONSTANTS_JS" file="pdf/constants.js" type="BINDATA" /> - <include name="IDR_PDF_CONTROLLER_JS" file="pdf/controller.js" type="BINDATA" /> - <include name="IDR_PDF_TOOLBAR_MANAGER_JS" file="pdf/toolbar_manager.js" type="BINDATA" /> - <include name="IDR_PDF_VIEWPORT_JS" file="pdf/viewport.js" type="BINDATA" /> - <include name="IDR_PDF_OPEN_PDF_PARAMS_PARSER_JS" file="pdf/open_pdf_params_parser.js" type="BINDATA" /> - <include name="IDR_PDF_NAVIGATOR_JS" file="pdf/navigator.js" type="BINDATA" /> - <include name="IDR_PDF_VIEWPORT_SCROLLER_JS" file="pdf/viewport_scroller.js" type="BINDATA" /> - <include name="IDR_PDF_PDF_SCRIPTING_API_JS" file="pdf/pdf_scripting_api.js" type="BINDATA" /> - <include name="IDR_PDF_ZOOM_MANAGER_JS" file="pdf/zoom_manager.js" type="BINDATA" /> - <include name="IDR_PDF_GESTURE_DETECTOR_JS" file="pdf/gesture_detector.js" type="BINDATA" /> - <include name="IDR_PDF_BROWSER_API_JS" file="pdf/browser_api.js" type="BINDATA" /> - <include name="IDR_PDF_METRICS_JS" file="pdf/metrics.js" type="BINDATA" /> - <include name="IDR_PDF_LOCAL_STORAGE_PROXY_JS" file="pdf/local_storage_proxy.js" type="BINDATA" /> - <include name="IDR_PDF_ELEMENTS_SHARED_CSS_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/shared-css.js" use_base_dir="false" type="BINDATA" /> - <include name="IDR_PDF_SHARED_VARS_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/shared-vars.js" use_base_dir="false" type="BINDATA" /> - <include name="IDR_PDF_ICONS_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/icons.js" use_base_dir="false" type="BINDATA" /> - <include name="IDR_PDF_VIEWER_BOOKMARK_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-bookmark.js" use_base_dir="false" type="BINDATA" /> - <include name="IDR_PDF_VIEWER_DOCUMENT_OUTLINE_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-document-outline.js" use_base_dir="false" type="BINDATA"/> - <include name="IDR_PDF_VIEWER_DOWNLOADS_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-download-controls.js" use_base_dir="false" type="BINDATA"/> - <include name="IDR_PDF_VIEWER_ERROR_SCREEN_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-error-screen.js" use_base_dir="false" type="BINDATA" /> - <if expr="chromeos"> - <include name="IDR_PDF_VIEWER_ANNOTATIONS_MODE_DIALOG_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-annotations-mode-dialog.js" use_base_dir="false" type="BINDATA"/> - <include name="IDR_PDF_VIEWER_ANNOTATIONS_BAR_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-annotations-bar.js" use_base_dir="false" type="BINDATA"/> - <include name="IDR_PDF_VIEWER_INK_CONTROLLER_JS" file="pdf/ink_controller.js" type="BINDATA" /> - <include name="IDR_PDF_VIEWER_INK_INDEX_HTML" file="pdf/ink/index.html" type="BINDATA" /> - <include name="IDR_PDF_VIEWER_INK_INK_API_JS" file="pdf/ink/ink_api.js" type="BINDATA" /> - <include name="IDR_PDF_VIEWER_INK_HOST_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-ink-host.js" use_base_dir="false" type="BINDATA" /> - <include name="IDR_PDF_VIEWER_PEN_OPTIONS_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-pen-options.js" use_base_dir="false" type="BINDATA" /> - <include name="IDR_PDF_VIEWER_FORM_WARNING_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-form-warning.js" use_base_dir="false" type="BINDATA" /> - </if> - <include name="IDR_PDF_VIEWER_PAGE_SELECTOR_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-page-selector.js" use_base_dir="false" type="BINDATA" /> - <include name="IDR_PDF_VIEWER_PASSWORD_SCREEN_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-password-screen.js" use_base_dir="false" type="BINDATA" /> - <include name="IDR_PDF_VIEWER_PDF_SIDENAV_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-pdf-sidenav.js" use_base_dir="false" type="BINDATA"/> - <include name="IDR_PDF_VIEWER_PDF_TOOLBAR_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.js" use_base_dir="false" type="BINDATA" preprocess="true"/> - <include name="IDR_PDF_VIEWER_PDF_TOOLBAR_NEW_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.js" use_base_dir="false" type="BINDATA" preprocess="true"/> - <include name="IDR_PDF_VIEWER_PROPERTIES_DIALOG_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-properties-dialog.js" use_base_dir="false" type="BINDATA" /> - <include name="IDR_PDF_VIEWER_THUMBNAIL_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-thumbnail.js" use_base_dir="false" type="BINDATA" /> - <include name="IDR_PDF_VIEWER_THUMBNAIL_BAR_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-thumbnail-bar.js" use_base_dir="false" type="BINDATA" /> - <include name="IDR_PDF_VIEWER_TOOLBAR_DROPDOWN_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown.js" use_base_dir="false" type="BINDATA" /> - <include name="IDR_PDF_VIEWER_ZOOM_BUTTON_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-zoom-button.js" use_base_dir="false" type="BINDATA" /> - <include name="IDR_PDF_VIEWER_ZOOM_SELECTOR_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.js" use_base_dir="false" type="BINDATA" /> -</grit-part>
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_page.html b/chrome/browser/resources/settings/chromeos/internet_page/internet_page.html index a0ab4d6b..b8e4fca 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/internet_page.html +++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_page.html
@@ -71,13 +71,13 @@ aria-labelledby="add-wifi-label"></cr-icon-button> </div> </template> - <div actionable$="[[vpnIsEnabled_]]" class="list-item" + <div actionable$="[[!vpnIsProhibited_]]" class="list-item" on-click="onAddVPNTap_"> <div class="start settings-box-text" id="add-vpn-label" aria-hidden="true"> $i18n{internetAddVPN} </div> - <template is="dom-if" if="[[!vpnIsEnabled_]]"> + <template is="dom-if" if="[[vpnIsProhibited_]]"> <cr-policy-indicator id="vpnPolicyIndicator" icon-aria-label="$i18n{networkVpnBuiltin}" indicator-type="devicePolicy" @@ -86,7 +86,7 @@ </template> <cr-icon-button class="icon-add-circle" aria-labelledby="add-vpn-label" - disabled="[[!vpnIsEnabled_]]"> + disabled="[[vpnIsProhibited_]]"> </cr-icon-button> </div> <template is="dom-repeat" items="[[vpnProviders_]]">
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_page.js b/chrome/browser/resources/settings/chromeos/internet_page/internet_page.js index cede6b2..ad4acad 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/internet_page.js +++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_page.js
@@ -81,10 +81,10 @@ }, /** - * False if VPN is disabled by policy. + * True if VPN is prohibited by policy. * @private {boolean} */ - vpnIsEnabled_: { + vpnIsProhibited_: { type: Boolean, value: false, }, @@ -502,9 +502,9 @@ } const vpn = this.deviceStates[mojom.NetworkType.kVPN]; - this.vpnIsEnabled_ = !!vpn && + this.vpnIsProhibited_ = !!vpn && vpn.deviceState === - chromeos.networkConfig.mojom.DeviceStateType.kEnabled; + chromeos.networkConfig.mojom.DeviceStateType.kProhibited; if (this.detailType_ && !this.deviceStates[this.detailType_]) { // If the device type associated with the current network has been @@ -541,7 +541,7 @@ /** @private */ onAddVPNTap_() { - if (this.vpnIsEnabled_) { + if (!this.vpnIsProhibited_) { this.showConfig_( true /* configAndConnect */, chromeos.networkConfig.mojom.NetworkType.kVPN);
diff --git a/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_app.html b/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_app.html index ab7a811e..b904f6c5 100644 --- a/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_app.html +++ b/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_app.html
@@ -165,7 +165,8 @@ </div> </div> <!-- TODO(https://crbug.com/1157764): Change to make only link clickable. --> - <template is="dom-if" if="[[shouldShowGuest_]]" restamp> + <template is="dom-if" if="[[interceptionParameters_.showGuestOption]]" + restamp> <div slot="footer"> <div class="divider"></div> <div id="footer-description" on-click="onGuest_"
diff --git a/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_app.js b/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_app.js index de500aa..9c0c79a 100644 --- a/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_app.js +++ b/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_app.js
@@ -35,14 +35,6 @@ value: false, }, - /** @private {boolean} */ - shouldShowGuest_: { - type: Boolean, - value() { - return loadTimeData.getBoolean('shouldShowGuest'); - }, - }, - /** @private {string} */ guestLink_: { type: String,
diff --git a/chrome/browser/resources/signin/sync_confirmation/images/sync_confirmation_refreshed_illustration.svg b/chrome/browser/resources/signin/sync_confirmation/images/sync_confirmation_refreshed_illustration.svg new file mode 100644 index 0000000..0faf745 --- /dev/null +++ b/chrome/browser/resources/signin/sync_confirmation/images/sync_confirmation_refreshed_illustration.svg
@@ -0,0 +1 @@ +<svg width="678" height="180" viewBox="0 0 678 180" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M275.704 64.913c0 3.852-3.185 7.037-7.111 6.963-3.853 0-7.038-3.185-6.964-7.112.074-3.926 3.186-7.037 7.112-6.963 3.926.074 7.037 3.185 6.963 7.112z" stroke="#8AB4F8" stroke-width="2"/><path d="M483.646 86.322c2 0 3.704-1.63 3.704-3.63s-1.63-3.704-3.63-3.704-3.704 1.63-3.704 3.63c-.074 2.074 1.556 3.704 3.63 3.704z" fill="#FBBC04"/><path d="M367.637 59.648c6.519.074 11.926-5.185 11.926-11.778 0-6.593-5.185-11.927-11.778-11.927-6.519-.074-11.927 5.186-11.927 11.779s5.186 11.852 11.779 11.926z" fill="#4285F4"/><path d="M461.491 84.54l9.63-18.594c2.592-4.816.666-10.89-4.149-13.409-4.815-2.592-10.889-.666-13.408 4.149l-9.704 18.593c-2.593 4.816-.667 10.89 4.148 13.409 4.964 2.592 10.89.666 13.483-4.149z" stroke="#34A853" stroke-width="2"/><path d="M311.121 71.321l-.004-.002-18.435-11.402c-1.273-.836-1.674-2.457-.874-3.737l.002-.004 11.402-18.435c.836-1.273 2.457-1.674 3.737-.874l.004.003 18.435 11.4c1.248.822 1.619 2.512.87 3.746l-.002.003-11.398 18.428c-.836 1.273-2.457 1.674-3.737.874z" stroke="#F0A3F8" stroke-width="2"/><path d="M330.298 40.543c.815-.815 2.222-.37 2.445.741l3.185 13.705c.296 1.11-.741 2.074-1.852 1.777l-13.482-4.074c-1.111-.296-1.408-1.704-.593-2.519l10.297-9.63z" fill="#5BB974"/><path d="M324.15 46.395l1.778 1.11c1.704 1.112 2.297 3.334 1.186 5.112l-1.038 1.704" stroke="#FDD663" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M406.231 66.248c.815-.074 1.63-.222 2.371-.518l2.518-.519c2.223-.518 4.593-.074 6.519 1.186l2.445 1.555 1.111.667c.296.148.593.222.889.37 3.852 1.26 7.926-.889 9.186-4.74 1.259-3.853-.889-7.927-4.741-9.186l-.889-.223-1.26-.148-2.963-.148c-2.296-.074-4.444-1.111-6-2.815l-1.778-1.926c-.444-.667-1.037-1.26-1.63-1.778a9.988 9.988 0 0 0-4.593-2.296c-4.963-1.111-10.074 1.63-11.926 6.37-2.222 5.63.889 11.927 6.519 13.705 1.407.444 2.889.593 4.222.444z" stroke="#8AB4F8" stroke-width="2"/><path d="M516.488 156.568l-25.483-12.519a6.08 6.08 0 0 1-2.815-8.148l32.742-66.819a6.08 6.08 0 0 1 8.149-2.815l25.483 12.52a6.08 6.08 0 0 1 2.815 8.148l-32.743 66.818a6.078 6.078 0 0 1-8.148 2.815z" stroke="#4285F4" stroke-width="2" stroke-linecap="round"/><path d="M517.53 153.17l-24.594-12.001c-1.408-.667-2-2.444-1.334-3.852l30.817-62.966c.667-1.408 2.444-2 3.852-1.334l24.594 12.075c1.407.667 2 2.445 1.333 3.852l-30.816 62.892c-.667 1.482-2.371 2.075-3.852 1.334z" fill="#D2E3FC"/><path d="M537.448 73.632l-.62 1.264 9.246 4.532.619-1.264-9.245-4.532zm-1.805-.106a.666.666 0 1 0-1.196-.587.666.666 0 0 0 1.196.587zm14.902 31.694l-1.929-.945-5.51 11.241 1.929.945 5.51-11.241zm5.575-11.467l-1.929-.946-3.195 6.519 1.929.945 3.195-6.518z" fill="#4285F4"/><path d="M516.634 138.052c3.482 1.704 7.704.296 9.408-3.186 1.704-3.481.296-7.704-3.185-9.407-3.482-1.704-7.704-.297-9.408 3.185-1.704 3.482-.297 7.704 3.185 9.408z" fill="#FBBC04"/><path d="M515.746 146.727l-5.408-2.667c-1.481-.741-2.074-2.592-1.333-4 .74-1.482 2.592-2.074 4-1.333l5.408 2.666c1.481.741 2.074 2.593 1.333 4.001-.667 1.407-2.445 2.074-4 1.333z" fill="#4285F4"/><path d="M499.227 128.131c-1.556 4.519.148 9.63 4.148 12.297.667.445 1.556.222 1.852-.518l3.556-7.26c.296-.667.074-1.408-.593-1.704l-7.259-3.556c-.593-.37-1.482 0-1.704.741z" fill="#34A853"/><path d="M248.32 117.005l-101.709 37.262c-1.334.518-2.889-.223-3.334-1.556l-23.853-64.818c-.518-1.334.222-2.89 1.556-3.334l101.709-37.261c1.333-.519 2.889.222 3.334 1.555l23.779 64.819c.592 1.333-.149 2.815-1.482 3.333z" stroke="#4285F4" stroke-width="2" stroke-linecap="round"/><path d="M222.533 52.028l-98.277 36.029 22.514 61.414 98.277-36.028-22.514-61.415z" fill="#D2E3FC"/><path d="M172.98 69.522a.592.592 0 1 0 0-1.185.592.592 0 0 0 0 1.185z" fill="#4285F4"/><path d="M141.575 161.375l57.707-21.186 57.781-21.187" stroke="#4285F4" stroke-width="2" stroke-linecap="round"/><path d="M167.717 126.557c4.371-1.629 6.593-6.444 4.963-10.741-1.629-4.371-6.444-6.593-10.741-4.963-4.37 1.63-6.593 6.445-4.963 10.741 1.63 4.297 6.445 6.519 10.741 4.963z" fill="#FBBC04"/><path d="M174.461 134.339l-6.741 2.519c-1.852.667-3.926-.296-4.593-2.148-.667-1.852.296-3.927 2.148-4.593l6.742-2.519c1.851-.667 3.926.296 4.592 2.148.667 1.852-.222 3.927-2.148 4.593z" fill="#4285F4"/><path d="M144.827 133.367c2.667 5.038 8.445 7.779 14.075 6.519.889-.222 1.407-1.185 1.111-2.074l-3.334-9.038c-.296-.814-1.185-1.185-2-.888l-9.037 3.333c-.815.296-1.26 1.333-.815 2.148z" fill="#34A853"/></svg> \ No newline at end of file
diff --git a/chrome/browser/resources/signin/sync_confirmation/images/sync_confirmation_refreshed_illustration_dark.svg b/chrome/browser/resources/signin/sync_confirmation/images/sync_confirmation_refreshed_illustration_dark.svg new file mode 100644 index 0000000..259c96e --- /dev/null +++ b/chrome/browser/resources/signin/sync_confirmation/images/sync_confirmation_refreshed_illustration_dark.svg
@@ -0,0 +1 @@ +<svg width="678" height="180" viewBox="0 0 678 180" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M275.704 64.913c0 3.852-3.185 7.037-7.111 6.963-3.853 0-7.038-3.185-6.964-7.112.074-3.926 3.186-7.037 7.112-6.963 3.926.074 7.037 3.185 6.963 7.112z" stroke="#8AB4F8" stroke-width="2"/><path d="M483.646 86.322c2.001 0 3.704-1.63 3.704-3.63s-1.629-3.704-3.63-3.704c-2 0-3.703 1.63-3.703 3.63-.074 2.074 1.555 3.704 3.629 3.704z" fill="#FBBC04"/><path d="M367.637 59.648c6.519.074 11.926-5.185 11.926-11.778 0-6.593-5.185-11.927-11.778-11.927-6.519-.074-11.927 5.186-11.927 11.779s5.186 11.852 11.779 11.926z" fill="#4285F4"/><path d="M461.491 84.54l9.63-18.594c2.593-4.816.667-10.89-4.148-13.409-4.816-2.592-10.89-.666-13.409 4.149l-9.704 18.593c-2.593 4.816-.667 10.89 4.149 13.409 4.963 2.592 10.889.666 13.482-4.149z" stroke="#34A853" stroke-width="2"/><path d="M311.121 71.321l-.004-.002-18.435-11.402c-1.273-.836-1.674-2.457-.874-3.737l.002-.004 11.402-18.435c.836-1.273 2.457-1.674 3.737-.874l.004.003 18.435 11.4c1.247.822 1.619 2.512.869 3.746l-.001.003-11.398 18.428c-.836 1.273-2.457 1.674-3.737.874z" stroke="#F0A3F8" stroke-width="2"/><path d="M330.298 40.543c.815-.815 2.222-.37 2.445.741l3.185 13.705c.296 1.11-.741 2.074-1.852 1.777l-13.482-4.074c-1.111-.296-1.408-1.704-.593-2.519l10.297-9.63z" fill="#5BB974"/><path d="M324.15 46.394l1.778 1.111c1.704 1.112 2.297 3.334 1.186 5.112l-1.038 1.704" stroke="#FDD663" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M406.231 66.249c.815-.075 1.63-.223 2.371-.519l2.518-.519c2.223-.518 4.593-.074 6.519 1.186l2.445 1.555 1.111.667c.296.148.593.222.889.37 3.852 1.26 7.926-.889 9.186-4.74 1.259-3.853-.889-7.927-4.741-9.186l-.889-.223-1.26-.148-2.963-.148c-2.296-.074-4.444-1.11-6-2.815l-1.778-1.926c-.444-.666-1.037-1.26-1.63-1.778a9.989 9.989 0 0 0-4.593-2.296c-4.963-1.111-10.074 1.63-11.926 6.37-2.222 5.63.889 11.927 6.519 13.705 1.407.445 2.889.593 4.222.445z" stroke="#8AB4F8" stroke-width="2"/><path d="M516.488 156.569l-25.483-12.52a6.08 6.08 0 0 1-2.815-8.148l32.743-66.819a6.08 6.08 0 0 1 8.148-2.815l25.483 12.52a6.08 6.08 0 0 1 2.815 8.148l-32.743 66.819a6.08 6.08 0 0 1-8.148 2.815z" stroke="#4285F4" stroke-width="2" stroke-linecap="round"/><path d="M517.53 153.17l-24.594-12.001c-1.408-.667-2-2.444-1.334-3.852l30.817-62.966c.666-1.408 2.444-2 3.852-1.334l24.594 12.075c1.407.667 2 2.445 1.333 3.852l-30.816 62.892c-.667 1.482-2.371 2.075-3.852 1.334z" fill="#D2E3FC"/><path d="M537.448 73.632l-.619 1.264 9.245 4.532.62-1.264-9.246-4.532zm-1.805-.105a.667.667 0 1 0-1.198-.587.667.667 0 0 0 1.198.587zm14.902 31.694l-1.929-.946-5.51 11.241 1.929.946 5.51-11.241zm5.575-11.469l-1.929-.945-3.195 6.518 1.929.946 3.195-6.519z" fill="#4285F4"/><path d="M516.634 138.052c3.482 1.703 7.704.296 9.408-3.186 1.704-3.481.296-7.704-3.185-9.408-3.482-1.704-7.704-.296-9.408 3.186-1.704 3.481-.297 7.704 3.185 9.408z" fill="#FBBC04"/><path d="M515.746 146.727l-5.408-2.667c-1.481-.74-2.074-2.592-1.333-4 .741-1.481 2.593-2.074 4-1.333l5.408 2.667c1.481.74 2.074 2.592 1.333 4-.666 1.407-2.444 2.074-4 1.333z" fill="#4285F4"/><path d="M499.227 128.131c-1.556 4.519.148 9.63 4.148 12.297.667.444 1.556.222 1.852-.519l3.556-7.259c.296-.667.074-1.408-.593-1.704l-7.259-3.556c-.593-.37-1.482 0-1.704.741z" fill="#34A853"/><path d="M248.32 117.005l-101.709 37.261c-1.334.519-2.889-.222-3.334-1.555l-23.853-64.819c-.518-1.333.222-2.889 1.556-3.333l101.709-37.261c1.333-.519 2.889.222 3.334 1.555l23.779 64.819c.592 1.333-.149 2.815-1.482 3.333z" stroke="#4285F4" stroke-width="2" stroke-linecap="round"/><path d="M222.533 52.028l-98.277 36.028 22.514 61.415 98.277-36.029-22.514-61.414z" fill="#D2E3FC"/><path d="M172.98 69.521a.592.592 0 1 0 0-1.184.592.592 0 0 0 0 1.184z" fill="#4285F4"/><path d="M141.575 161.375l57.707-21.186 57.781-21.187" stroke="#4285F4" stroke-width="2" stroke-linecap="round"/><path d="M167.717 126.557c4.371-1.63 6.593-6.445 4.963-10.741-1.629-4.371-6.444-6.593-10.741-4.963-4.37 1.629-6.593 6.444-4.963 10.741 1.63 4.296 6.445 6.519 10.741 4.963z" fill="#FBBC04"/><path d="M174.461 134.339l-6.741 2.519c-1.852.667-3.926-.296-4.593-2.148-.667-1.852.296-3.927 2.148-4.593l6.742-2.519c1.851-.667 3.926.296 4.592 2.148.667 1.852-.222 3.927-2.148 4.593z" fill="#4285F4"/><path d="M144.827 133.367c2.667 5.038 8.445 7.779 14.075 6.519.889-.222 1.407-1.185 1.111-2.074l-3.334-9.038c-.296-.814-1.185-1.185-2-.888l-9.037 3.333c-.815.296-1.26 1.333-.815 2.148z" fill="#34A853"/></svg> \ No newline at end of file
diff --git a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.html b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.html index 2141cd97..c4d55121 100644 --- a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.html +++ b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.html
@@ -7,8 +7,8 @@ <style> body { margin: 0; + min-width: 512px; padding: 0; - width: 512px; } @media (prefers-color-scheme: dark) { body {
diff --git a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.html b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.html index 3cc7d304..9eda3a29 100644 --- a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.html +++ b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.html
@@ -1,10 +1,33 @@ <style include="signin-dialog-shared"> :host { + --avatar-size: 100px; + --banner-height: 244px; + --footer-margin: 40px; + --text-font-size: 1.16em; color: var(--cr-primary-text-color); display: block; } - cr-button { + @media (prefers-color-scheme: dark) { + /* Old design */ + #illustration { + background-image: + url(./images/sync_confirmation_illustration_dark.svg); + } + + /* New design */ + #syncPromoBanner { + background-image: + url(images/sync_confirmation_refreshed_illustration_dark.svg); + } + } + + .secondary { + color: var(--cr-secondary-text-color); + } + + /* Old design */ + .action-container cr-button { padding-inline-end: 16px; padding-inline-start: 16px; } @@ -32,13 +55,6 @@ width: 100%; } - @media (prefers-color-scheme: dark) { - #illustration { - background-image: - url(./images/sync_confirmation_illustration_dark.svg); - } - } - #illustration-container > img { border-radius: 50%; height: 68px; @@ -70,10 +86,6 @@ padding: 0 24px; } - .secondary { - color: var(--cr-secondary-text-color); - } - @media (prefers-color-scheme: light) { #grey-banner { background: var(--paper-grey-50); @@ -83,20 +95,107 @@ } } - #footer { + #old-footer { margin-bottom: 0; padding-top: 12px; } - #settingsButton { + .action-container #settingsButton { left: 16px; position: absolute; } - :host-context([dir='rtl']) #settingsButton { + :host-context([dir='rtl']) .action-container #settingsButton { left: auto; right: 16px; } + + /* New design */ + #headerContainer { + background-color: var(--theme-frame-color); + height: var(--banner-height); + position: relative; + width: 100%; + } + + #syncPromoBanner { + background-image: url(images/sync_confirmation_refreshed_illustration.svg); + background-position: center; + background-repeat: no-repeat; + height: 100%; + position: absolute; + top: 0; + width: 100%; + z-index: 0; + } + + #avatar { + border: 2px solid var(--md-background-color); + border-radius: 50%; + bottom: calc(var(--avatar-size)/-2); + height: var(--avatar-size); + left: 0; + margin: auto; + position: absolute; + right: 0; + width: var(--avatar-size); + z-index: 1; + } + + #contentContainer { + margin-bottom: calc(48px + var(--footer-margin)); + margin-top: 104px; + text-align: center; + } + + #contentContainer h2 { + font-size: 1.85em; + font-weight: normal; + } + + #contentContainer h3 { + font-size: var(--text-font-size); + font-weight: normal; + } + + #confirmationDescription { + font-size: 1em; + margin-top: 16px; + } + + #footer { + bottom: 0; + display: flex; + font-size: var(--text-font-size); + margin-bottom: var(--footer-margin); + position: absolute; + width: 100%; + } + + #actionContainer { + display: flex; + flex-flow: row-reverse; + justify-content: flex-start; + width: 100%; + } + + #actionContainer cr-button { + min-width: 111px; + } + + #actionContainer #settingsButton { + font-weight: normal; + margin-inline-end: auto; + margin-inline-start: var(--footer-margin); + } + + #actionContainer #confirmButton { + margin-inline-end: var(--footer-margin); + } + + #actionContainer #notNowButton { + font-weight: normal; + } </style> <!-- @@ -106,35 +205,71 @@ which user clicks to indicate consent. --> -<div id="illustration-container"> - <div id="grey-banner"></div> - <div id="illustration"></div> - <img src="[[accountImageSrc_]]"> -</div> -<div id="content-container"> - <h1 id="syncConfirmationHeading" class="heading" consent-description> - $i18n{syncConfirmationTitle} - </h1> - <div class="message-container"> - <div consent-description>$i18n{syncConfirmationSyncInfoTitle}</div> - <div class="secondary" consent-description> +<template is="dom-if" if="[[!isProfileCreationFlow_]]"> + <div id="illustration-container"> + <div id="grey-banner"></div> + <div id="illustration"></div> + <img src="[[accountImageSrc_]]"> + </div> + <div id="content-container"> + <h1 id="syncConfirmationHeading" class="heading" consent-description> + $i18n{syncConfirmationTitle} + </h1> + <div class="message-container"> + <div consent-description>$i18n{syncConfirmationSyncInfoTitle}</div> + <div class="secondary" consent-description> + $i18n{syncConfirmationSyncInfoDesc} + </div> + </div> + <div id="old-footer" class="message-container secondary"> + $i18n{syncConfirmationSettingsInfo} + </div> + <div class="action-container"> + <cr-button class="action-button" id="confirmButton" + on-click="onConfirm_" consent-confirmation autofocus> + $i18n{syncConfirmationConfirmLabel} + </cr-button> + <cr-button id="cancelButton" on-click="onUndo_"> + $i18n{syncConfirmationUndoLabel} + </cr-button> + <cr-button id="settingsButton" on-click="onGoToSettings_" + consent-confirmation> + $i18n{syncConfirmationSettingsLabel} + </cr-button> + </div> + </div> +</template> + +<template is="dom-if" if="[[isProfileCreationFlow_]]"> + <div id="headerContainer" style$="--theme-frame-color:[[highlightColor_]]"> + <div id="syncPromoBanner"></div> + <img id="avatar" alt="" src="[[accountImageSrc_]]"> + </div> + + <div id="contentContainer"> + <h2 consent-description id="syncConfirmationHeading"> + $i18n{syncConfirmationTitle} + </h2> + <h3 class="secondary" consent-description> + $i18n{syncConfirmationSyncInfoTitle} + </h3> + <div id="confirmationDescription" class="secondary" consent-description> $i18n{syncConfirmationSyncInfoDesc} </div> </div> - <div id="footer" class="message-container secondary"> - $i18n{syncConfirmationSettingsInfo} + <div id="footer"> + <div id="actionContainer"> + <cr-button class="action-button" id="confirmButton" + on-click="onConfirm_" consent-confirmation autofocus> + $i18n{syncConfirmationConfirmLabel} + </cr-button> + <cr-button id="notNowButton" on-click="onUndo_"> + $i18n{syncConfirmationUndoLabel} + </cr-button> + <cr-button id="settingsButton" on-click="onGoToSettings_" + consent-confirmation> + $i18n{syncConfirmationSettingsLabel} + </cr-button> + </div> </div> - <div class="action-container"> - <cr-button class="action-button" id="confirmButton" - on-click="onConfirm_" consent-confirmation autofocus> - $i18n{syncConfirmationConfirmLabel} - </cr-button> - <cr-button id="cancelButton" on-click="onUndo_"> - $i18n{syncConfirmationUndoLabel} - </cr-button> - <cr-button id="settingsButton" on-click="onGoToSettings_" - consent-confirmation> - $i18n{syncConfirmationSettingsLabel} - </cr-button> - </div> -</div> +</template>
diff --git a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.js b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.js index 83d2ccc..2dc96fe 100644 --- a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.js +++ b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.js
@@ -31,6 +31,26 @@ return loadTimeData.getString('accountPictureUrl'); }, }, + + /** @private */ + isProfileCreationFlow_: { + type: Boolean, + value() { + return loadTimeData.getBoolean('isProfileCreationFlow'); + } + }, + + /** @private */ + highlightColor_: { + type: String, + value() { + if (!loadTimeData.valueExists('highlightColor')) { + return ''; + } + + return loadTimeData.getString('highlightColor'); + } + }, }, /** @private {?SyncConfirmationBrowserProxy} */ @@ -85,7 +105,7 @@ Array.from(this.shadowRoot.querySelectorAll('[consent-description]')) .filter(element => element.clientWidth * element.clientHeight > 0) .map(element => element.innerHTML.trim()); - assert(consentDescription); + assert(consentDescription.length); return consentDescription; },
diff --git a/chrome/browser/safe_browsing/download_protection/check_client_download_request_base.cc b/chrome/browser/safe_browsing/download_protection/check_client_download_request_base.cc index e3d79cc..8e22a9f 100644 --- a/chrome/browser/safe_browsing/download_protection/check_client_download_request_base.cc +++ b/chrome/browser/safe_browsing/download_protection/check_client_download_request_base.cc
@@ -170,8 +170,8 @@ signin::IdentityManager* identity_manager = IdentityManagerFactory::GetForProfile(profile); if (!profile->IsOffTheRecord() && identity_manager) { - token_fetcher_ = - std::make_unique<SafeBrowsingTokenFetcher>(identity_manager); + token_fetcher_ = std::make_unique<SafeBrowsingPrimaryAccountTokenFetcher>( + identity_manager); } } } @@ -461,7 +461,6 @@ if (is_enhanced_protection_ && token_fetcher_ && base::FeatureList::IsEnabled(kDownloadRequestWithToken)) { token_fetcher_->Start( - signin::ConsentLevel::kNotRequired, base::BindOnce(&CheckClientDownloadRequestBase::OnGotAccessToken, GetWeakPtr())); return; @@ -471,9 +470,8 @@ } void CheckClientDownloadRequestBase::OnGotAccessToken( - base::Optional<signin::AccessTokenInfo> access_token_info) { - if (access_token_info.has_value()) - access_token_ = access_token_info.value().token; + const std::string& access_token) { + access_token_ = access_token; SendRequest(); }
diff --git a/chrome/browser/safe_browsing/download_protection/check_client_download_request_base.h b/chrome/browser/safe_browsing/download_protection/check_client_download_request_base.h index 71b3a0e1..6d039065 100644 --- a/chrome/browser/safe_browsing/download_protection/check_client_download_request_base.h +++ b/chrome/browser/safe_browsing/download_protection/check_client_download_request_base.h
@@ -26,7 +26,7 @@ #include "chrome/services/file_util/public/cpp/sandboxed_rar_analyzer.h" #include "chrome/services/file_util/public/cpp/sandboxed_zip_analyzer.h" #include "components/history/core/browser/history_service.h" -#include "components/safe_browsing/core/browser/safe_browsing_token_fetcher.h" +#include "components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher.h" #include "components/safe_browsing/core/db/database_manager.h" #include "content/public/browser/browser_thread.h" #include "url/gurl.h" @@ -153,8 +153,7 @@ DownloadCheckResultReason reason) const = 0; // Called when |token_fetcher_| has finished fetching the access token. - void OnGotAccessToken( - base::Optional<signin::AccessTokenInfo> access_token_info); + void OnGotAccessToken(const std::string& access_token); // Called at the request start to determine if we should bailout due to the // file being whitelisted by policy
diff --git a/chrome/browser/sharesheet/sharesheet_action_cache.cc b/chrome/browser/sharesheet/sharesheet_action_cache.cc index b75e1cc0..b2c80e8 100644 --- a/chrome/browser/sharesheet/sharesheet_action_cache.cc +++ b/chrome/browser/sharesheet/sharesheet_action_cache.cc
@@ -38,7 +38,6 @@ AddShareAction(std::make_unique<ExampleAction>()); AddShareAction(std::make_unique<ExampleAction>()); AddShareAction(std::make_unique<ExampleAction>()); - AddShareAction(std::make_unique<ExampleAction>()); } #endif }
diff --git a/chrome/browser/signin/dice_web_signin_interceptor.cc b/chrome/browser/signin/dice_web_signin_interceptor.cc index 03ab3d0d..7db0265 100644 --- a/chrome/browser/signin/dice_web_signin_interceptor.cc +++ b/chrome/browser/signin/dice_web_signin_interceptor.cc
@@ -88,6 +88,11 @@ return chrome::FindBrowserWithWebContents(web_contents) == nullptr; } +bool GuestOptionAvailable() { + return Profile::IsEphemeralGuestProfileEnabled() && + !ProfileManager::GuestProfileExists(); +} + } // namespace ScopedDiceWebSigninInterceptionBubbleHandle:: @@ -239,7 +244,8 @@ Delegate::BubbleParameters bubble_parameters{ SigninInterceptionType::kProfileSwitch, *account_info, GetPrimaryAccountInfo(identity_manager_), - entry->GetProfileThemeColors().profile_highlight_color}; + entry->GetProfileThemeColors().profile_highlight_color, + /*show_guest_option=*/false}; interception_bubble_handle_ = delegate_->ShowSigninInterceptionBubble( web_contents, bubble_parameters, base::BindOnce(&DiceWebSigninInterceptor::OnProfileSwitchChoice, @@ -401,7 +407,8 @@ SkColor profile_color = GenerateNewProfileColor(entry).color; Delegate::BubbleParameters bubble_parameters{ *interception_type, info, GetPrimaryAccountInfo(identity_manager_), - GetAutogeneratedThemeColors(profile_color).frame_color}; + GetAutogeneratedThemeColors(profile_color).frame_color, + GuestOptionAvailable()}; interception_bubble_handle_ = delegate_->ShowSigninInterceptionBubble( web_contents(), bubble_parameters, base::BindOnce(&DiceWebSigninInterceptor::OnProfileCreationChoice,
diff --git a/chrome/browser/signin/dice_web_signin_interceptor.h b/chrome/browser/signin/dice_web_signin_interceptor.h index 42967f5..7c29c17c 100644 --- a/chrome/browser/signin/dice_web_signin_interceptor.h +++ b/chrome/browser/signin/dice_web_signin_interceptor.h
@@ -150,6 +150,7 @@ AccountInfo intercepted_account; AccountInfo primary_account; SkColor profile_highlight_color; + bool show_guest_option; }; virtual ~Delegate() = default;
diff --git a/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheRenderTest.java b/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheRenderTest.java index 6548970..5ea4988 100644 --- a/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheRenderTest.java +++ b/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheRenderTest.java
@@ -141,13 +141,14 @@ when(mIdentityManagerNativeMock .findExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress( anyLong(), eq(accountEmail))) - .thenReturn(new AccountInfo( - new CoreAccountId("gaia-id-test"), accountEmail, "gaia-id-test", null)); + .thenReturn(new AccountInfo(new CoreAccountId("gaia-id-test"), accountEmail, + "gaia-id-test", "full name", "given name", null)); mAccountManagerTestRule.addAccount( new ProfileDataSource.ProfileData(accountEmail, null, "Full Name", "Given Name")); - mIdentityManager.onExtendedAccountInfoUpdated(new AccountInfo( - new CoreAccountId("gaia-id-test"), accountEmail, "gaia-id-test", createAvatar())); + mIdentityManager.onExtendedAccountInfoUpdated( + new AccountInfo(new CoreAccountId("gaia-id-test"), accountEmail, "gaia-id-test", + "full name", "given name", createAvatar())); TestThreadUtils.runOnUiThreadBlocking(() -> { checkImageIsScaled(accountEmail); }); mRenderTestRule.render(mImageView, "profile_data_cache_avatar" + mImageSize); }
diff --git a/chrome/browser/storage_access_api/api_browsertest.cc b/chrome/browser/storage_access_api/api_browsertest.cc index 06fc0ecc..0ea9976 100644 --- a/chrome/browser/storage_access_api/api_browsertest.cc +++ b/chrome/browser/storage_access_api/api_browsertest.cc
@@ -63,8 +63,6 @@ // HTTPS server only serves a valid cert for localhost, so this is needed // to load pages from other hosts without an error. command_line->AppendSwitch(switches::kIgnoreCertificateErrors); - command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures, - "CookieStoreDocument"); } GURL GetURL(const std::string& host) {
diff --git a/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.cc b/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.cc index 62c520c7..9ac064f 100644 --- a/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.cc +++ b/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.cc
@@ -101,6 +101,10 @@ drive_service_->AddObserver(this); } } + if (base::FeatureList::IsEnabled( + app_list_features::kEnableLauncherSearchNormalization)) { + normalizer_.emplace("drive_zero_state_provider", profile); + } } DriveZeroStateProvider::~DriveZeroStateProvider() { @@ -214,6 +218,12 @@ } cache_results_.reset(); + + if (normalizer_.has_value()) { + normalizer_->Record(provider_results); + normalizer_->NormalizeResults(&provider_results); + } + SwapResults(&provider_results); LogStatus(Status::kOk);
diff --git a/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.h b/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.h index 3246e2b..c5e38810 100644 --- a/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.h +++ b/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.h
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "base/optional.h" #include "base/sequence_checker.h" #include "base/sequenced_task_runner.h" #include "base/strings/string16.h" @@ -16,6 +17,7 @@ #include "chrome/browser/chromeos/drive/drive_integration_service.h" #include "chrome/browser/ui/app_list/search/files/file_result.h" #include "chrome/browser/ui/app_list/search/files/item_suggest_cache.h" +#include "chrome/browser/ui/app_list/search/score_normalizer/score_normalizer.h" #include "chrome/browser/ui/app_list/search/search_provider.h" #include "chromeos/components/drivefs/mojom/drivefs.mojom.h" @@ -69,6 +71,9 @@ // Whether the suggested files experiment is enabled. const bool suggested_files_enabled_; + // The normalizer normalizes the relevance scores of Results + base::Optional<ScoreNormalizer> normalizer_; + // Whether we have sent at least one request to ItemSuggest to warm up the // results cache. bool have_warmed_up_cache_ = false;
diff --git a/chrome/browser/ui/app_list/search/omnibox_provider.cc b/chrome/browser/ui/app_list/search/omnibox_provider.cc index b19857e..f9c5351d 100644 --- a/chrome/browser/ui/app_list/search/omnibox_provider.cc +++ b/chrome/browser/ui/app_list/search/omnibox_provider.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/app_list/search/omnibox_provider.h" +#include "ash/public/cpp/app_list/app_list_features.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "chrome/browser/autocomplete/chrome_autocomplete_provider_client.h" @@ -37,6 +38,10 @@ std::make_unique<ChromeAutocompleteProviderClient>(profile), AutocompleteClassifier::DefaultOmniboxProviders())) { controller_->AddObserver(this); + if (base::FeatureList::IsEnabled( + app_list_features::kEnableLauncherSearchNormalization)) { + normalizer_.emplace("omnibox_provider", profile); + } } OmniboxProvider::~OmniboxProvider() {} @@ -87,6 +92,11 @@ is_zero_state_input_)); } + if (normalizer_.has_value()) { + normalizer_->Record(new_results); + normalizer_->NormalizeResults(&new_results); + } + SwapResults(&new_results); }
diff --git a/chrome/browser/ui/app_list/search/omnibox_provider.h b/chrome/browser/ui/app_list/search/omnibox_provider.h index c431e99..7576208 100644 --- a/chrome/browser/ui/app_list/search/omnibox_provider.h +++ b/chrome/browser/ui/app_list/search/omnibox_provider.h
@@ -8,6 +8,8 @@ #include <memory> #include "base/macros.h" +#include "base/optional.h" +#include "chrome/browser/ui/app_list/search/score_normalizer/score_normalizer.h" #include "chrome/browser/ui/app_list/search/search_provider.h" #include "components/omnibox/browser/autocomplete_controller.h" @@ -50,6 +52,9 @@ // eliminates the results as they come in. std::unique_ptr<AutocompleteController> controller_; + // The normalizer normalizes the relevance scores of Results + base::Optional<ScoreNormalizer> normalizer_; + DISALLOW_COPY_AND_ASSIGN(OmniboxProvider); };
diff --git a/chrome/browser/ui/app_list/search/zero_state_file_provider.cc b/chrome/browser/ui/app_list/search/zero_state_file_provider.cc index 2978f12..919bef9 100644 --- a/chrome/browser/ui/app_list/search/zero_state_file_provider.cc +++ b/chrome/browser/ui/app_list/search/zero_state_file_provider.cc
@@ -79,6 +79,11 @@ profile->GetPath().AppendASCII("zero_state_local_files.pb"), config, chromeos::ProfileHelper::IsEphemeralUserProfile(profile)); } + + if (base::FeatureList::IsEnabled( + app_list_features::kEnableLauncherSearchNormalization)) { + normalizer_.emplace("zero_state_file_provider", profile); + } } ZeroStateFileProvider::~ZeroStateFileProvider() = default; @@ -118,6 +123,11 @@ } } + if (normalizer_.has_value()) { + normalizer_->Record(new_results); + normalizer_->NormalizeResults(&new_results); + } + UMA_HISTOGRAM_TIMES("Apps.AppList.ZeroStateFileProvider.Latency", base::TimeTicks::Now() - query_start_time_); SwapResults(&new_results);
diff --git a/chrome/browser/ui/app_list/search/zero_state_file_provider.h b/chrome/browser/ui/app_list/search/zero_state_file_provider.h index 771be5a..7dfb815 100644 --- a/chrome/browser/ui/app_list/search/zero_state_file_provider.h +++ b/chrome/browser/ui/app_list/search/zero_state_file_provider.h
@@ -13,12 +13,14 @@ #include "base/macros.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" +#include "base/optional.h" #include "base/scoped_observer.h" #include "base/sequenced_task_runner.h" #include "base/strings/string16.h" #include "base/time/time.h" #include "chrome/browser/chromeos/file_manager/file_tasks_notifier.h" #include "chrome/browser/chromeos/file_manager/file_tasks_observer.h" +#include "chrome/browser/ui/app_list/search/score_normalizer/score_normalizer.h" #include "chrome/browser/ui/app_list/search/search_provider.h" class Profile; @@ -62,6 +64,9 @@ // empty query. std::unique_ptr<RecurrenceRanker> files_ranker_; + // The normalizer normalizes the relevance scores of Results + base::Optional<ScoreNormalizer> normalizer_; + base::TimeTicks query_start_time_; ScopedObserver<file_manager::file_tasks::FileTasksNotifier,
diff --git a/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.cc b/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.cc index ff324f88b..c50ce2b 100644 --- a/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.cc +++ b/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.cc
@@ -14,11 +14,13 @@ #include "base/strings/string16.h" #include "base/time/time.h" #include "chrome/app/vector_icons/vector_icons.h" +#include "chrome/browser/about_flags.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sharesheet/sharesheet_metrics.h" #include "chrome/browser/sharesheet/sharesheet_service_delegate.h" #include "chrome/browser/ui/ash/sharesheet/sharesheet_expand_button.h" #include "chrome/browser/ui/ash/sharesheet/sharesheet_target_button.h" +#include "chrome/common/chrome_features.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/theme_resources.h" #include "extensions/browser/app_window/app_window.h" @@ -165,6 +167,24 @@ title->SetHorizontalAlignment(gfx::ALIGN_LEFT); title->SetProperty(views::kMarginsKey, gfx::Insets(kSpacing)); + // Add content preview text descriptor. + if (base::FeatureList::IsEnabled(features::kSharesheetContentPreviews) && + (intent_->file_urls.has_value())) { + // Remove the margin under the title for file_title + title->SetProperty(views::kMarginsKey, + gfx::Insets(kSpacing, kSpacing, 0, kSpacing)); + // This displays text data only for the first file_url provided. + auto* file_title = main_view_->AddChildView(std::make_unique<views::Label>( + base::ASCIIToUTF16( + (intent_->file_urls.value().front().ExtractFileName())), + ash::CONTEXT_SHARESHEET_BUBBLE_BODY_SECONDARY)); + file_title->SetLineHeight(kTitleLineHeight); + file_title->SetEnabledColor(kShareTargetTitleColor); + file_title->SetHorizontalAlignment(gfx::ALIGN_LEFT); + file_title->SetProperty(views::kMarginsKey, + gfx::Insets(3, kSpacing, kSpacing, kSpacing)); + } + if (targets.empty()) { auto* image = main_view_->AddChildView(std::make_unique<views::ImageView>()); @@ -210,6 +230,11 @@ expand_button_separator_->SetVisible(false); } UpdateAnchorPosition(); + + // Expanding the sharesheet is needed for content previews + if (base::FeatureList::IsEnabled(features::kSharesheetContentPreviews)) { + ResizeBubble(kDefaultBubbleWidth, GetBubbleHeight()); + } } std::unique_ptr<views::View> SharesheetBubbleView::MakeScrollableTargetView( @@ -510,8 +535,7 @@ void SharesheetBubbleView::ExpandButtonPressed() { show_expanded_view_ = !show_expanded_view_; - ResizeBubble(kDefaultBubbleWidth, show_expanded_view_ ? kExpandedBubbleHeight - : kDefaultBubbleHeight); + ResizeBubble(kDefaultBubbleWidth, GetBubbleHeight()); // Scrollview has separators that overlaps with |expand_button_separator_| // to create a double line when both are visible, so when scrollview is @@ -580,7 +604,7 @@ void SharesheetBubbleView::SetToDefaultBubbleSizing() { width_ = kDefaultBubbleWidth; - height_ = kDefaultBubbleHeight; + height_ = GetBubbleHeight(); } void SharesheetBubbleView::ShowWidgetWithAnimateFadeIn() { @@ -641,6 +665,16 @@ delegate_->OnBubbleClosed(active_target_); } +int SharesheetBubbleView::GetBubbleHeight() { + int height = + show_expanded_view_ ? kExpandedBubbleHeight : kDefaultBubbleHeight; + + if (base::FeatureList::IsEnabled(features::kSharesheetContentPreviews)) { + height += kTitleLineHeight + 3; + } + return height; +} + void SharesheetBubbleView::RecordFormFactorMetric() { auto form_factor = ash::TabletMode::Get()->InTabletMode()
diff --git a/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.h b/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.h index b522443..5f0fea2 100644 --- a/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.h +++ b/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.h
@@ -73,6 +73,7 @@ void ShowWidgetWithAnimateFadeIn(); void CloseWidgetWithAnimateFadeOut(views::Widget::ClosedReason closed_reason); void CloseWidgetWithReason(views::Widget::ClosedReason closed_reason); + int GetBubbleHeight(); void RecordFormFactorMetric(); // Owns this class.
diff --git a/chrome/browser/ui/extensions/extensions_container.h b/chrome/browser/ui/extensions/extensions_container.h index b353378..f00cfe1 100644 --- a/chrome/browser/ui/extensions/extensions_container.h +++ b/chrome/browser/ui/extensions/extensions_container.h
@@ -75,6 +75,8 @@ // Same as above, but uses PostTask() in all cases. virtual void ShowToolbarActionBubbleAsync( std::unique_ptr<ToolbarActionsBarBubbleDelegate> bubble) = 0; + + virtual void ToggleExtensionsMenu() = 0; }; #endif // CHROME_BROWSER_UI_EXTENSIONS_EXTENSIONS_CONTAINER_H_
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc index 16d4c3b..77768513 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc +++ b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc
@@ -606,6 +606,12 @@ weak_ptr_factory_.GetWeakPtr(), std::move(bubble))); } +void ToolbarActionsBar::ToggleExtensionsMenu() { + // This is only implemented by |ExtensionsToolbarContainer|. + // TODO(crbug.com/943702): Remove this entire class. + NOTREACHED(); +} + bool ToolbarActionsBar::CloseOverflowMenuIfOpen() { return delegate_->CloseOverflowMenuIfOpen(); }
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar.h b/chrome/browser/ui/toolbar/toolbar_actions_bar.h index 4d61c0b..ccf320e 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_bar.h +++ b/chrome/browser/ui/toolbar/toolbar_actions_bar.h
@@ -248,6 +248,7 @@ std::unique_ptr<ToolbarActionsBarBubbleDelegate> bubble) override; void ShowToolbarActionBubbleAsync( std::unique_ptr<ToolbarActionsBarBubbleDelegate> bubble) override; + void ToggleExtensionsMenu() override; private: // Returns the insets by which the icon area bounds (See GetIconAreaRect())
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_view_browsertest.cc b/chrome/browser/ui/views/extensions/extensions_menu_view_browsertest.cc index bd3edb5..065b27f7 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_view_browsertest.cc +++ b/chrome/browser/ui/views/extensions/extensions_menu_view_browsertest.cc
@@ -296,6 +296,10 @@ // Removing the last extension. All actions now have the same state. RemoveExtension(method, extensions()[1]->id()); + + // Container should remain visible during the removal animation. + EXPECT_TRUE(GetExtensionsToolbarContainer()->IsDrawn()); + views::test::WaitForAnimatingLayoutManager(GetExtensionsToolbarContainer()); EXPECT_EQ(expected_visibility, GetExtensionsToolbarContainer()->IsDrawn()); }
diff --git a/chrome/browser/ui/views/extensions/extensions_toolbar_button.cc b/chrome/browser/ui/views/extensions/extensions_toolbar_button.cc index 4ac306b..b4f3658 100644 --- a/chrome/browser/ui/views/extensions/extensions_toolbar_button.cc +++ b/chrome/browser/ui/views/extensions/extensions_toolbar_button.cc
@@ -29,7 +29,7 @@ std::unique_ptr<views::MenuButtonController> menu_button_controller = std::make_unique<views::MenuButtonController>( this, - base::BindRepeating(&ExtensionsToolbarButton::ButtonPressed, + base::BindRepeating(&ExtensionsToolbarButton::ToggleExtensionsMenu, base::Unretained(this)), std::make_unique<views::Button::DefaultButtonControllerDelegate>( this)); @@ -95,6 +95,24 @@ void ExtensionsToolbarButton::OnWidgetDestroying(views::Widget* widget) { widget->RemoveObserver(this); pressed_lock_.reset(); + extensions_container_->OnMenuClosed(); +} + +void ExtensionsToolbarButton::ToggleExtensionsMenu() { + if (ExtensionsMenuView::IsShowing()) { + ExtensionsMenuView::Hide(); + return; + } + pressed_lock_ = menu_button_controller_->TakeLock(); + extensions_container_->OnMenuOpening(); + base::RecordAction(base::UserMetricsAction("Extensions.Toolbar.MenuOpened")); + ExtensionsMenuView::ShowBubble(this, browser_, extensions_container_, + extensions_container_->CanShowIconInToolbar()) + ->AddObserver(this); +} + +bool ExtensionsToolbarButton::IsExtensionsMenuShowing() const { + return pressed_lock_.get(); } int ExtensionsToolbarButton::GetIconSize() const { @@ -102,15 +120,3 @@ return (touch_ui && !browser_->app_controller()) ? kDefaultTouchableIconSize : kDefaultIconSize; } - -void ExtensionsToolbarButton::ButtonPressed() { - if (ExtensionsMenuView::IsShowing()) { - ExtensionsMenuView::Hide(); - return; - } - pressed_lock_ = menu_button_controller_->TakeLock(); - base::RecordAction(base::UserMetricsAction("Extensions.Toolbar.MenuOpened")); - ExtensionsMenuView::ShowBubble(this, browser_, extensions_container_, - extensions_container_->CanShowIconInToolbar()) - ->AddObserver(this); -}
diff --git a/chrome/browser/ui/views/extensions/extensions_toolbar_button.h b/chrome/browser/ui/views/extensions/extensions_toolbar_button.h index dfe81b2..3351f7e 100644 --- a/chrome/browser/ui/views/extensions/extensions_toolbar_button.h +++ b/chrome/browser/ui/views/extensions/extensions_toolbar_button.h
@@ -26,6 +26,12 @@ ExtensionsToolbarButton& operator=(const ExtensionsToolbarButton&) = delete; ~ExtensionsToolbarButton() override; + // Activate the Extensions menu. If the ExtensionsToolbarContainer is in + // kAutoHide mode this will cause it to show. + void ToggleExtensionsMenu(); + + bool IsExtensionsMenuShowing() const; + // ToolbarButton: gfx::Size CalculatePreferredSize() const override; gfx::Size GetMinimumSize() const override; @@ -39,8 +45,6 @@ private: int GetIconSize() const; - void ButtonPressed(); - // A lock to keep the button pressed when a popup is visible. std::unique_ptr<views::MenuButtonController::PressedLock> pressed_lock_;
diff --git a/chrome/browser/ui/views/extensions/extensions_toolbar_container.cc b/chrome/browser/ui/views/extensions/extensions_toolbar_container.cc index ccfdddf..9826b68 100644 --- a/chrome/browser/ui/views/extensions/extensions_toolbar_container.cc +++ b/chrome/browser/ui/views/extensions/extensions_toolbar_container.cc
@@ -23,6 +23,20 @@ #include "ui/views/layout/flex_layout_types.h" #include "ui/views/view_class_properties.h" +namespace { + +base::OnceClosure& GetOnVisibleCallbackForTesting() { + static base::NoDestructor<base::OnceClosure> callback; + return *callback; +} + +} // namespace + +void ExtensionsToolbarContainer::SetOnVisibleCallbackForTesting( + base::OnceClosure callback) { + GetOnVisibleCallbackForTesting() = std::move(callback); +} + struct ExtensionsToolbarContainer::DropInfo { DropInfo(ToolbarActionsModel::ActionId action_id, size_t index); @@ -64,8 +78,9 @@ views::FlexSpecification()); break; case DisplayMode::kCompact: - // In compact mode, the menu icon can be hidden but has the highest - // priority. + case DisplayMode::kAutoHide: + // In compact/auto hide mode, the menu icon can be hidden but has the + // highest priority. extensions_button_->SetProperty( views::kFlexBehaviorKey, hide_icon_flex_specification.WithOrder(1)); break; @@ -174,8 +189,9 @@ views::FlexSpecification()); break; case DisplayMode::kCompact: - // In compact mode, the icon can still drop out, but receives precedence - // over other actions. + case DisplayMode::kAutoHide: + // In compact/auto hide mode, the icon can still drop out, but receives + // precedence over other actions. action_view->SetProperty( views::kFlexBehaviorKey, views::FlexSpecification( @@ -291,6 +307,7 @@ ToolbarActionViewController* const popped_out_action = popped_out_action_; popped_out_action_ = nullptr; UpdateIconVisibility(popped_out_action->GetId()); + UpdateContainerVisibilityAfterAnimation(); } void ExtensionsToolbarContainer::SetPopupOwner( @@ -299,12 +316,21 @@ // never unsetting one when one wasn't set. DCHECK((popup_owner_ != nullptr) ^ (popup_owner != nullptr)); popup_owner_ = popup_owner; + + // Container should become visible if |popup_owner_| and may lose visibility + // if not |popup_owner_|. Visibility must be maintained during layout + // animations. + if (popup_owner_) + UpdateContainerVisibility(); + else + UpdateContainerVisibilityAfterAnimation(); } void ExtensionsToolbarContainer::HideActivePopup() { if (popup_owner_) popup_owner_->HidePopup(); DCHECK(!popup_owner_); + UpdateContainerVisibilityAfterAnimation(); } bool ExtensionsToolbarContainer::CloseOverflowMenuIfOpen() { @@ -324,6 +350,7 @@ popped_out_action_ = action; UpdateIconVisibility(action->GetId()); animating_layout_manager()->PostOrQueueAction(std::move(closure)); + UpdateContainerVisibility(); } bool ExtensionsToolbarContainer::ShowToolbarActionPopupForAPICall( @@ -360,6 +387,10 @@ ShowToolbarActionBubble(std::move(bubble)); } +void ExtensionsToolbarContainer::ToggleExtensionsMenu() { + extensions_button_->ToggleExtensionsMenu(); +} + void ExtensionsToolbarContainer::OnTabStripModelChanged( TabStripModel* tab_strip_model, const TabStripModelChange& change, @@ -400,7 +431,7 @@ RemoveChildViewT(GetViewForId(action_id)); icons_.erase(action_id); - UpdateContainerVisibility(); + UpdateContainerVisibilityAfterAnimation(); } void ExtensionsToolbarContainer::OnToolbarActionMoved( @@ -666,7 +697,56 @@ } void ExtensionsToolbarContainer::UpdateContainerVisibility() { - // The container (and extensions-menu button) should be visible if we have at - // least one extension. - SetVisible(!actions_.empty()); + bool was_visible = GetVisible(); + SetVisible(ShouldContainerBeVisible()); + + // Layout animation does not handle host view visibility changing; requires + // resetting. + if (was_visible != GetVisible()) + animating_layout_manager()->ResetLayout(); + + if (!was_visible && GetVisible() && GetOnVisibleCallbackForTesting()) + std::move(GetOnVisibleCallbackForTesting()).Run(); +} + +bool ExtensionsToolbarContainer::ShouldContainerBeVisible() const { + // The container (and extensions-menu button) should not be visible if we have + // no extensions. + if (actions_.empty()) + return false; + + // All other display modes are constantly visible. + if (display_mode_ != DisplayMode::kAutoHide) + return true; + + if (animating_layout_manager()->is_animating()) + return true; + + // Is menu showing. + if (extensions_button_->IsExtensionsMenuShowing()) + return true; + + // Is extension pop out is showing. + if (popped_out_action_) + return true; + + // Is extension pop up showing. + if (popup_owner_) + return true; + + return false; +} + +void ExtensionsToolbarContainer::UpdateContainerVisibilityAfterAnimation() { + animating_layout_manager()->PostOrQueueAction( + base::BindOnce(&ExtensionsToolbarContainer::UpdateContainerVisibility, + weak_ptr_factory_.GetWeakPtr())); +} + +void ExtensionsToolbarContainer::OnMenuOpening() { + UpdateContainerVisibility(); +} + +void ExtensionsToolbarContainer::OnMenuClosed() { + UpdateContainerVisibility(); }
diff --git a/chrome/browser/ui/views/extensions/extensions_toolbar_container.h b/chrome/browser/ui/views/extensions/extensions_toolbar_container.h index abdbb5a..c2f0bc5 100644 --- a/chrome/browser/ui/views/extensions/extensions_toolbar_container.h +++ b/chrome/browser/ui/views/extensions/extensions_toolbar_container.h
@@ -11,6 +11,7 @@ #include <string> #include <vector> +#include "base/callback_forward.h" #include "base/optional.h" #include "base/scoped_observation.h" #include "chrome/browser/ui/extensions/extensions_container.h" @@ -50,11 +51,21 @@ // always enough space to show at least two icons. kNormal, // In compact mode, one or both of the menu icon and popped-out action may - // be hidden. Compact mode is used in smaller windows (e.g. webapps) where + // be hidden if the available space does not allow for them. Compact mode is + // used in smaller windows (e.g. web apps) where // there may not be enough space to display the buttons. kCompact, + // In auto hide mode the menu icon is hidden until + // extensions_button()->ToggleExtensionsMenu() is called by the embedder. + // This + // is used for windows that want to minimize the number of visible icons in + // their + // toolbar (e.g. web apps). + kAutoHide, }; + static void SetOnVisibleCallbackForTesting(base::OnceClosure callback); + explicit ExtensionsToolbarContainer( Browser* browser, DisplayMode display_mode = DisplayMode::kNormal); @@ -80,6 +91,12 @@ void ShowWidgetForExtension(views::Widget* widget, const std::string& extension_id); + // Event handler for when the extensions menu is opened. + void OnMenuOpening(); + + // Event handler for when the extensions menu is closed. + void OnMenuClosed(); + // Gets the widget that anchors to the extension (or is about to anchor to the // extension, pending pop-out). views::Widget* GetAnchoredWidgetForExtensionForTesting( @@ -123,6 +140,7 @@ std::unique_ptr<ToolbarActionsBarBubbleDelegate> bubble) override; void ShowToolbarActionBubbleAsync( std::unique_ptr<ToolbarActionsBarBubbleDelegate> bubble) override; + void ToggleExtensionsMenu() override; // ToolbarActionView::Delegate: content::WebContents* GetCurrentWebContents() override; @@ -187,10 +205,17 @@ void SetExtensionIconVisibility(ToolbarActionsModel::ActionId id, bool visible); - // Calls SetVisible to make sure that the container is showing only when there - // are extensions available. + // Calls SetVisible() with ShouldContainerBeVisible(). void UpdateContainerVisibility(); + // Returns whether the contianer should be showing, e.g. not if there are no + // extensions installed, nor if the container is inactive in kAutoHide mode. + bool ShouldContainerBeVisible() const; + + // Queues up a call to UpdateContainerVisibility() for when the current layout + // animation ends. + void UpdateContainerVisibilityAfterAnimation(); + // TabStripModelObserver: void OnTabStripModelChanged( TabStripModel* tab_strip_model,
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_browsertest.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_browsertest.cc index 2e8eaeb..1ddaed15a 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_browsertest.cc +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_browsertest.cc
@@ -12,6 +12,7 @@ #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h" #include "chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.h" +#include "chrome/browser/ui/views/web_apps/frame_toolbar/web_app_toolbar_button_container.h" #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h" #include "chrome/browser/web_applications/components/web_application_info.h" #include "chrome/test/base/in_process_browser_test.h" @@ -168,7 +169,7 @@ // Add taller children to the web app frame toolbar RHS. const int container_height = web_app_frame_toolbar_->height(); - web_app_frame_toolbar_->GetRightContainerForTesting()->AddChildView( + web_app_frame_toolbar_->get_right_container_for_testing()->AddChildView( new views::StaticSizedView(gfx::Size(1, title_bar_height * 2))); opaque_browser_frame_view_->Layout();
diff --git a/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view.cc b/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view.cc index 940637d2..bc71c8f 100644 --- a/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view.cc +++ b/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view.cc
@@ -155,11 +155,10 @@ std::unique_ptr<views::WebView> web_view = std::make_unique<views::WebView>(profile); web_view->LoadInitialURL(GURL(chrome::kChromeUIDiceWebSigninInterceptURL)); - web_view->SetPreferredSize( - gfx::Size(kInterceptionBubbleWidth, - DiceWebSigninInterceptUI::ShouldShowGuestOption() - ? kInterceptionBubbleWithGuestHeight - : kInterceptionBubbleWithoutGuestHeight)); + web_view->SetPreferredSize(gfx::Size( + kInterceptionBubbleWidth, bubble_parameters.show_guest_option + ? kInterceptionBubbleWithGuestHeight + : kInterceptionBubbleWithoutGuestHeight)); DiceWebSigninInterceptUI* web_ui = web_view->GetWebContents() ->GetWebUI() ->GetController()
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view.cc b/chrome/browser/ui/views/profiles/profile_menu_view.cc index 6d109c4..ae0f53c 100644 --- a/chrome/browser/ui/views/profiles/profile_menu_view.cc +++ b/chrome/browser/ui/views/profiles/profile_menu_view.cc
@@ -63,6 +63,7 @@ #include "ui/native_theme/native_theme.h" #include "ui/strings/grit/ui_strings.h" #include "ui/views/accessibility/view_accessibility.h" +#include "ui/views/metadata/metadata_impl_macros.h" namespace { @@ -744,3 +745,7 @@ } } #endif // BUILDFLAG(IS_CHROMEOS_ASH) + +BEGIN_METADATA(ProfileMenuView, ProfileMenuViewBase) +ADD_READONLY_PROPERTY_METADATA(gfx::ImageSkia, SyncIcon) +END_METADATA
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view.h b/chrome/browser/ui/views/profiles/profile_menu_view.h index 279a495..e626eae9 100644 --- a/chrome/browser/ui/views/profiles/profile_menu_view.h +++ b/chrome/browser/ui/views/profiles/profile_menu_view.h
@@ -33,6 +33,8 @@ // It displays a list of profiles and allows users to switch between profiles. class ProfileMenuView : public ProfileMenuViewBase { public: + METADATA_HEADER(ProfileMenuView); + ProfileMenuView(views::Button* anchor_button, Browser* browser); ~ProfileMenuView() override;
diff --git a/chrome/browser/ui/views/profiles/profile_picker_view.cc b/chrome/browser/ui/views/profiles/profile_picker_view.cc index 9a92c63..db21b6f 100644 --- a/chrome/browser/ui/views/profiles/profile_picker_view.cc +++ b/chrome/browser/ui/views/profiles/profile_picker_view.cc
@@ -134,6 +134,25 @@ return signin_url; } +class ProfilePickerWidget : public views::Widget { + public: + explicit ProfilePickerWidget(ProfilePickerView* profile_picker_view) + : profile_picker_view_(profile_picker_view) { + views::Widget::InitParams params; + params.delegate = profile_picker_view_; + Init(std::move(params)); + } + ~ProfilePickerWidget() override = default; + + // views::Widget: + const ui::ThemeProvider* GetThemeProvider() const override { + return profile_picker_view_->GetThemeProviderForProfileBeingCreated(); + } + + private: + ProfilePickerView* const profile_picker_view_; +}; + } // namespace // static @@ -232,14 +251,22 @@ } } +const ui::ThemeProvider* +ProfilePickerView::GetThemeProviderForProfileBeingCreated() const { + if (!signed_in_profile_being_created_) + return nullptr; + return &ThemeService::GetThemeProviderForProfile( + signed_in_profile_being_created_); +} + ProfilePickerView::ProfilePickerView() : keep_alive_(KeepAliveOrigin::USER_MANAGER_VIEW, KeepAliveRestartOption::DISABLED), extended_account_info_timeout_(kExtendedAccountInfoTimeout) { + // Setup the WidgetDelegate. SetHasWindowSizeControls(true); - SetButtons(ui::DIALOG_BUTTON_NONE); SetTitle(IDS_PRODUCT_NAME); - set_use_custom_frame(false); + ConfigureAccelerators(); // TODO(crbug.com/1063856): Add |RecordDialogCreation|. } @@ -309,7 +336,8 @@ extensions::ChromeExtensionWebContentsObserver::CreateForWebContents( system_profile_contents_.get()); - CreateDialogWidget(this, nullptr, nullptr); + // The widget is owned by the native widget. + new ProfilePickerWidget(this); #if defined(OS_WIN) // Set the app id for the user manager to the app id of its parent. @@ -429,7 +457,23 @@ SyncConfirmationUI* sync_confirmation_ui = static_cast<SyncConfirmationUI*>( new_profile_contents_->GetWebUI()->GetController()); - sync_confirmation_ui->InitializeMessageHandlerForCreationFlow(); + sync_confirmation_ui->InitializeMessageHandlerForCreationFlow(profile_color_); +} + +void ProfilePickerView::WindowClosing() { + // Now that the window is closed, we can allow a new one to be opened. + // (WindowClosing comes in asynchronously from the call to Close() and we + // may have already opened a new instance). + if (g_profile_picker_view == this) + g_profile_picker_view = nullptr; +} + +views::ClientView* ProfilePickerView::CreateClientView(views::Widget* widget) { + return new views::ClientView(widget, TransferOwnershipOfContentsView()); +} + +views::View* ProfilePickerView::GetContentsView() { + return this; } gfx::Size ProfilePickerView::CalculatePreferredSize() const { @@ -443,14 +487,6 @@ return preferred_size; } -void ProfilePickerView::WindowClosing() { - // Now that the window is closed, we can allow a new one to be opened. - // (WindowClosing comes in asynchronously from the call to Close() and we - // may have already opened a new instance). - if (g_profile_picker_view == this) - g_profile_picker_view = nullptr; -} - gfx::Size ProfilePickerView::GetMinimumSize() const { // On small screens, the preferred size may be smaller than the picker // minimum size. In that case there will be scrollbars on the picker.
diff --git a/chrome/browser/ui/views/profiles/profile_picker_view.h b/chrome/browser/ui/views/profiles/profile_picker_view.h index effd6b9..91bb348 100644 --- a/chrome/browser/ui/views/profiles/profile_picker_view.h +++ b/chrome/browser/ui/views/profiles/profile_picker_view.h
@@ -15,7 +15,8 @@ #include "content/public/browser/web_contents_delegate.h" #include "ui/views/controls/webview/unhandled_keyboard_event_handler.h" #include "ui/views/controls/webview/webview.h" -#include "ui/views/window/dialog_delegate.h" +#include "ui/views/view.h" +#include "ui/views/widget/widget_delegate.h" struct AccountInfo; class Browser; @@ -31,12 +32,14 @@ } // namespace content // Dialog widget that contains the Desktop Profile picker webui. -class ProfilePickerView : public views::DialogDelegateView, +class ProfilePickerView : public views::WidgetDelegateView, public content::WebContentsDelegate, public signin::IdentityManager::Observer { public: using BrowserOpenedCallback = base::OnceCallback<void(Browser*)>; + const ui::ThemeProvider* GetThemeProviderForProfileBeingCreated() const; + private: friend class ProfilePicker; @@ -73,11 +76,13 @@ // Switches the layout to the sync confirmation screen. void SwitchToSyncConfirmation(); - // views::DialogDelegateView: - gfx::Size CalculatePreferredSize() const override; + // views::WidgetDelegate: void WindowClosing() override; + views::ClientView* CreateClientView(views::Widget* widget) override; + views::View* GetContentsView() override; - // views::View; + // views::View: + gfx::Size CalculatePreferredSize() const override; gfx::Size GetMinimumSize() const override; bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.h b/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.h index 42c77e4..6ef2ccf 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.h +++ b/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.h
@@ -57,6 +57,11 @@ return static_cast<views::AnimatingLayoutManager*>(GetLayoutManager()); } + const views::AnimatingLayoutManager* animating_layout_manager() const { + return static_cast<const views::AnimatingLayoutManager*>( + GetLayoutManager()); + } + // Provides access to the flex layout in the animating layout manager. views::FlexLayout* target_layout_manager() { return static_cast<views::FlexLayout*>(
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc index 2b281481..4589dba 100644 --- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc +++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc
@@ -5,12 +5,17 @@ #include <cmath> #include "base/optional.h" +#include "base/path_service.h" #include "base/run_loop.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" +#include "chrome/browser/extensions/chrome_test_extension_loader.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/view_ids.h" +#include "chrome/browser/ui/views/extensions/extensions_menu_view.h" +#include "chrome/browser/ui/views/extensions/extensions_toolbar_button.h" +#include "chrome/browser/ui/views/extensions/extensions_toolbar_container.h" #include "chrome/browser/ui/views/frame/app_menu_button.h" #include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" #include "chrome/browser/ui/views/frame/browser_view.h" @@ -18,6 +23,11 @@ #include "chrome/browser/ui/views/page_action/page_action_icon_controller.h" #include "chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_helper.h" #include "chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.h" +#include "chrome/browser/ui/views/web_apps/frame_toolbar/web_app_navigation_button_container.h" +#include "chrome/browser/ui/views/web_apps/frame_toolbar/web_app_toolbar_button_container.h" +#include "chrome/browser/ui/web_applications/web_app_menu_model.h" +#include "chrome/common/chrome_features.h" +#include "chrome/common/chrome_paths.h" #include "chrome/test/base/in_process_browser_test.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" @@ -26,6 +36,7 @@ #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_utils.h" #include "content/public/test/theme_change_waiter.h" +#include "extensions/test/test_extension_dir.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/geometry/size.h" @@ -50,6 +61,22 @@ return visible; } +void LoadTestPopUpExtension(Profile* profile) { + extensions::TestExtensionDir test_extension_dir; + test_extension_dir.WriteManifest( + R"({ + "name": "Pop up extension", + "version": "1.0", + "manifest_version": 2, + "browser_action": { + "default_popup": "popup.html" + } + })"); + test_extension_dir.WriteFile(FILE_PATH_LITERAL("popup.html"), ""); + extensions::ChromeTestExtensionLoader(profile).LoadExtension( + test_extension_dir.UnpackedPath()); +} + } // namespace class WebAppFrameToolbarBrowserTest : public InProcessBrowserTest { @@ -79,8 +106,8 @@ const GURL app_url("https://test.org"); helper()->InstallAndLaunchWebApp(browser(), app_url); - views::View* const toolbar_left_container = - helper()->web_app_frame_toolbar()->GetLeftContainerForTesting(); + WebAppNavigationButtonContainer* const toolbar_left_container = + helper()->web_app_frame_toolbar()->get_left_container_for_testing(); EXPECT_EQ(toolbar_left_container->parent(), helper()->web_app_frame_toolbar()); @@ -92,8 +119,8 @@ EXPECT_EQ(window_title->parent(), helper()->frame_view()); #endif - views::View* const toolbar_right_container = - helper()->web_app_frame_toolbar()->GetRightContainerForTesting(); + WebAppToolbarButtonContainer* const toolbar_right_container = + helper()->web_app_frame_toolbar()->get_right_container_for_testing(); EXPECT_EQ(toolbar_right_container->parent(), helper()->web_app_frame_toolbar()); @@ -226,10 +253,10 @@ const GURL app_url("https://test.org"); helper()->InstallAndLaunchWebApp(browser(), app_url); - views::View* const toolbar_left_container = - helper()->web_app_frame_toolbar()->GetLeftContainerForTesting(); - views::View* const toolbar_right_container = - helper()->web_app_frame_toolbar()->GetRightContainerForTesting(); + WebAppNavigationButtonContainer* const toolbar_left_container = + helper()->web_app_frame_toolbar()->get_left_container_for_testing(); + WebAppToolbarButtonContainer* const toolbar_right_container = + helper()->web_app_frame_toolbar()->get_right_container_for_testing(); auto* const window_title = static_cast<views::Label*>( helper()->frame_view()->GetViewByID(VIEW_ID_WINDOW_TITLE)); @@ -271,3 +298,85 @@ helper()->frame_view()->GetTooltipHandlerForPoint(window_title->origin()), window_title); } + +class WebAppFrameToolbarBrowserTest_ElidedExtensionsMenu + : public WebAppFrameToolbarBrowserTest { + public: + WebAppFrameToolbarBrowserTest_ElidedExtensionsMenu() { + scoped_feature_list_.InitAndEnableFeature( + features::kDesktopPWAsElidedExtensionsMenu); + } + base::test::ScopedFeatureList scoped_feature_list_; +}; + +IN_PROC_BROWSER_TEST_F(WebAppFrameToolbarBrowserTest_ElidedExtensionsMenu, + Test) { + LoadTestPopUpExtension(browser()->profile()); + helper()->InstallAndLaunchWebApp(browser(), GURL("https://test.org")); + + WebAppToolbarButtonContainer* toolbar_button_container = + helper()->web_app_frame_toolbar()->get_right_container_for_testing(); + + // There should be no visible Extensions icon. + EXPECT_FALSE(toolbar_button_container->extensions_container()->GetVisible()); + + // There should be a menu entry for opening the Extensions menu. + auto app_menu_model = std::make_unique<WebAppMenuModel>( + /*provider=*/nullptr, helper()->app_browser()); + app_menu_model->Init(); + ui::MenuModel* model = app_menu_model.get(); + int index = -1; + const bool found = app_menu_model->GetModelAndIndexForCommandId( + WebAppMenuModel::kExtensionsMenuCommandId, &model, &index); + EXPECT_TRUE(found); + EXPECT_TRUE(model->IsEnabledAt(index)); + + app_menu_model->ExecuteCommand(WebAppMenuModel::kExtensionsMenuCommandId, + /*event_flags=*/0); + + // Extensions icon and menu should be visible. + EXPECT_TRUE(toolbar_button_container->extensions_container()->GetVisible()); + EXPECT_TRUE(ExtensionsMenuView::IsShowing()); +} + +class WebAppFrameToolbarBrowserTest_NoElidedExtensionsMenu + : public WebAppFrameToolbarBrowserTest { + public: + WebAppFrameToolbarBrowserTest_NoElidedExtensionsMenu() { + scoped_feature_list_.InitAndDisableFeature( + features::kDesktopPWAsElidedExtensionsMenu); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +IN_PROC_BROWSER_TEST_F(WebAppFrameToolbarBrowserTest_NoElidedExtensionsMenu, + Test) { + helper()->InstallAndLaunchWebApp(browser(), GURL("https://test.org")); + + WebAppToolbarButtonContainer* toolbar_button_container = + helper()->web_app_frame_toolbar()->get_right_container_for_testing(); + + // Extensions toolbar should be hidden while there are no Extensions + // installed. + EXPECT_FALSE(toolbar_button_container->extensions_container()->GetVisible()); + + // Install Extension and wait for Extensions toolbar to appear. + base::RunLoop run_loop; + ExtensionsToolbarContainer::SetOnVisibleCallbackForTesting( + run_loop.QuitClosure()); + LoadTestPopUpExtension(browser()->profile()); + run_loop.Run(); + EXPECT_TRUE(toolbar_button_container->extensions_container()->GetVisible()); + + // There should be no menu entry for opening the Extensions menu. + auto app_menu_model = std::make_unique<WebAppMenuModel>( + /*provider=*/nullptr, helper()->app_browser()); + app_menu_model->Init(); + ui::MenuModel* model = app_menu_model.get(); + int index = -1; + const bool found = app_menu_model->GetModelAndIndexForCommandId( + WebAppMenuModel::kExtensionsMenuCommandId, &model, &index); + EXPECT_FALSE(found); +}
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.cc b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.cc index ca8d227..f21d4fa 100644 --- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.cc +++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.cc
@@ -223,14 +223,6 @@ return left_container_ ? left_container_->reload_button() : nullptr; } -views::View* WebAppFrameToolbarView::GetLeftContainerForTesting() { - return left_container_; -} - -views::View* WebAppFrameToolbarView::GetRightContainerForTesting() { - return right_container_; -} - PageActionIconController* WebAppFrameToolbarView::GetPageActionIconControllerForTesting() { return right_container_->page_action_icon_controller();
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.h b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.h index 8aecaa07..ae4108b 100644 --- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.h +++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.h
@@ -70,8 +70,12 @@ ToolbarButton* GetBackButton() override; ReloadButton* GetReloadButton() override; - views::View* GetLeftContainerForTesting(); - views::View* GetRightContainerForTesting(); + WebAppNavigationButtonContainer* get_left_container_for_testing() { + return left_container_; + } + WebAppToolbarButtonContainer* get_right_container_for_testing() { + return right_container_; + } PageActionIconController* GetPageActionIconControllerForTesting(); protected:
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_menu_button.h b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_menu_button.h index 9bee202..b36a13a 100644 --- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_menu_button.h +++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_menu_button.h
@@ -8,6 +8,7 @@ #include "base/strings/string16.h" #include "base/timer/timer.h" #include "chrome/browser/ui/views/frame/app_menu_button.h" +#include "chrome/browser/ui/web_applications/web_app_menu_model.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/color_palette.h"
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_toolbar_button_container.cc b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_toolbar_button_container.cc index df3a23b..8dcbd3c 100644 --- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_toolbar_button_container.cc +++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_toolbar_button_container.cc
@@ -9,6 +9,7 @@ #include "chrome/browser/ui/browser_content_setting_bubble_model_delegate.h" #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/view_ids.h" +#include "chrome/browser/ui/views/extensions/extensions_toolbar_button.h" #include "chrome/browser/ui/views/extensions/extensions_toolbar_container.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/toolbar_button_provider.h" @@ -19,6 +20,7 @@ #include "chrome/browser/ui/views/web_apps/frame_toolbar/web_app_menu_button.h" #include "chrome/browser/ui/views/web_apps/frame_toolbar/web_app_origin_text.h" #include "chrome/browser/ui/web_applications/system_web_app_ui_utils.h" +#include "chrome/common/chrome_features.h" #include "ui/base/hit_test.h" #include "ui/views/layout/flex_layout.h" #include "ui/views/window/hit_test_utils.h" @@ -104,11 +106,16 @@ // for example, the menu button or other toolbar buttons, and pinned // extensions should hide before other toolbar buttons. constexpr int kLowPriorityFlexOrder = 2; + if (base::FeatureList::IsEnabled(features::kExtensionsToolbarMenu)) { + auto display_mode = + base::FeatureList::IsEnabled( + features::kDesktopPWAsElidedExtensionsMenu) + ? ExtensionsToolbarContainer::DisplayMode::kAutoHide + : ExtensionsToolbarContainer::DisplayMode::kCompact; extensions_container_ = AddChildView(std::make_unique<ExtensionsToolbarContainer>( - browser_view_->browser(), - ExtensionsToolbarContainer::DisplayMode::kCompact)); + browser_view_->browser(), display_mode)); extensions_container_->SetProperty( views::kFlexBehaviorKey, views::FlexSpecification( @@ -349,6 +356,7 @@ return browser_view_->GetActiveWebContents(); } +// views::WidgetObserver: void WebAppToolbarButtonContainer::OnWidgetVisibilityChanged( views::Widget* widget, bool visible) {
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_toolbar_button_container.h b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_toolbar_button_container.h index d7e6df4a..1f15cb8 100644 --- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_toolbar_button_container.h +++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_toolbar_button_container.h
@@ -12,6 +12,7 @@ #include "chrome/browser/ui/views/page_action/page_action_icon_container.h" #include "chrome/browser/ui/views/page_action/page_action_icon_view.h" #include "chrome/browser/ui/views/toolbar/browser_actions_container.h" +#include "chrome/browser/ui/web_applications/web_app_menu_model.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/views/view.h" #include "ui/views/widget/widget.h"
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc index 2bac29f2..e0a6e95 100644 --- a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc +++ b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc
@@ -260,7 +260,7 @@ extensions::ScopedTestDialogAutoConfirm auto_confirm( extensions::ScopedTestDialogAutoConfirm::ACCEPT); auto app_menu_model = - std::make_unique<WebAppMenuModel>(nullptr, app_browser_); + std::make_unique<WebAppMenuModel>(/*provider=*/nullptr, app_browser_); app_menu_model->Init(); ui::MenuModel* model = app_menu_model.get(); int index = -1;
diff --git a/chrome/browser/ui/web_applications/web_app_browsertest.cc b/chrome/browser/ui/web_applications/web_app_browsertest.cc index 8084c50e..0efdc889 100644 --- a/chrome/browser/ui/web_applications/web_app_browsertest.cc +++ b/chrome/browser/ui/web_applications/web_app_browsertest.cc
@@ -698,7 +698,8 @@ Browser* const app_browser = LaunchWebAppBrowserAndWait(app_id); app_browser->tab_strip_model()->CloseAllTabs(); - auto app_menu_model = std::make_unique<WebAppMenuModel>(nullptr, app_browser); + auto app_menu_model = std::make_unique<WebAppMenuModel>( + /*provider=*/nullptr, app_browser); app_menu_model->Init(); } @@ -708,7 +709,8 @@ const AppId app_id = InstallPWA(app_url); Browser* const app_browser = LaunchWebAppBrowserAndWait(app_id); - auto app_menu_model = std::make_unique<WebAppMenuModel>(nullptr, app_browser); + auto app_menu_model = std::make_unique<WebAppMenuModel>( + /*provider=*/nullptr, app_browser); app_menu_model->Init(); ui::MenuModel* model = app_menu_model.get(); int index = -1;
diff --git a/chrome/browser/ui/web_applications/web_app_menu_model.cc b/chrome/browser/ui/web_applications/web_app_menu_model.cc index 979a42c..0e00a55 100644 --- a/chrome/browser/ui/web_applications/web_app_menu_model.cc +++ b/chrome/browser/ui/web_applications/web_app_menu_model.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/web_applications/web_app_menu_model.h" +#include "base/feature_list.h" #include "base/metrics/histogram_macros.h" #include "base/strings/utf_string_conversions.h" #include "build/chromeos_buildflags.h" @@ -12,7 +13,10 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/extensions/extensions_container.h" +#include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/web_applications/app_browser_controller.h" +#include "chrome/common/chrome_features.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "components/strings/grit/components_strings.h" @@ -28,6 +32,7 @@ #endif constexpr int WebAppMenuModel::kUninstallAppCommandId; +constexpr int WebAppMenuModel::kExtensionsMenuCommandId; WebAppMenuModel::WebAppMenuModel(ui::AcceleratorProvider* provider, Browser* browser) @@ -36,17 +41,30 @@ WebAppMenuModel::~WebAppMenuModel() {} bool WebAppMenuModel::IsCommandIdEnabled(int command_id) const { - return command_id == kUninstallAppCommandId - ? browser()->app_controller()->CanUninstall() - : AppMenuModel::IsCommandIdEnabled(command_id); + switch (command_id) { + case kUninstallAppCommandId: + return browser()->app_controller()->CanUninstall(); + case kExtensionsMenuCommandId: + return base::FeatureList::IsEnabled(features::kExtensionsToolbarMenu) && + base::FeatureList::IsEnabled( + features::kDesktopPWAsElidedExtensionsMenu); + default: + return AppMenuModel::IsCommandIdEnabled(command_id); + } } void WebAppMenuModel::ExecuteCommand(int command_id, int event_flags) { - if (command_id == kUninstallAppCommandId) { - LogMenuAction(MENU_ACTION_UNINSTALL_APP); - browser()->app_controller()->Uninstall(); - } else { - AppMenuModel::ExecuteCommand(command_id, event_flags); + switch (command_id) { + case kUninstallAppCommandId: + LogMenuAction(MENU_ACTION_UNINSTALL_APP); + browser()->app_controller()->Uninstall(); + break; + case kExtensionsMenuCommandId: + browser()->window()->GetExtensionsContainer()->ToggleExtensionsMenu(); + break; + default: + AppMenuModel::ExecuteCommand(command_id, event_flags); + break; } } @@ -70,6 +88,9 @@ browser()->location_bar_model()->GetVectorIcon())); AddSeparator(ui::NORMAL_SEPARATOR); + + if (IsCommandIdEnabled(kExtensionsMenuCommandId)) + AddItemWithStringId(kExtensionsMenuCommandId, IDS_SHOW_EXTENSIONS); AddItemWithStringId(IDC_COPY_URL, IDS_COPY_URL); AddItemWithStringId(IDC_OPEN_IN_CHROME, IDS_OPEN_IN_CHROME);
diff --git a/chrome/browser/ui/web_applications/web_app_menu_model.h b/chrome/browser/ui/web_applications/web_app_menu_model.h index 39ffe97..feba25f 100644 --- a/chrome/browser/ui/web_applications/web_app_menu_model.h +++ b/chrome/browser/ui/web_applications/web_app_menu_model.h
@@ -14,6 +14,7 @@ class WebAppMenuModel : public AppMenuModel { public: static constexpr int kUninstallAppCommandId = 1; + static constexpr int kExtensionsMenuCommandId = 2; WebAppMenuModel(ui::AcceleratorProvider* provider, Browser* browser); WebAppMenuModel(const WebAppMenuModel&) = delete;
diff --git a/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc b/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc index 6cb4b41..54a4949 100644 --- a/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc +++ b/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc
@@ -2,12 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/logging.h" #include "base/macros.h" #include "base/strings/string_piece.h" +#include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/browser/ui/webui/welcome/helpers.h" #include "chrome/common/url_constants.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" @@ -143,7 +146,14 @@ : public InProcessBrowserTest, public testing::WithParamInterface<const char*> { public: - ChromeURLDataManagerWebUITrustedTypesTest() = default; + ChromeURLDataManagerWebUITrustedTypesTest() { + std::vector<base::Feature> enabled_features; +#if !BUILDFLAG(IS_CHROMEOS_ASH) + if (GetParam() == std::string("chrome://welcome")) + enabled_features.push_back(welcome::kForceEnabled); +#endif + feature_list_.InitWithFeatures(enabled_features, {}); + } void CheckTrustedTypesViolation(base::StringPiece url) { std::string message_filter1 = "*This document requires*assignment*"; @@ -156,16 +166,26 @@ ASSERT_TRUE(embedded_test_server()->Start()); ui_test_utils::NavigateToURL(browser(), GURL(url)); - // We don't ASSERT_TRUE here because some WebUI pages are by design not - // PAGE_TYPE_NORMAL (e.g. chrome://interstitials/ssl). - content::WaitForLoadStop(content); + + if (url == "chrome://network-error" || url == "chrome://dino") { + // We don't ASSERT_TRUE here because some WebUI pages are + // PAGE_TYPE_ERROR by design. + content::WaitForLoadStop(content); + } else { + ASSERT_TRUE(content::WaitForLoadStop(content)); + } + EXPECT_TRUE(console_observer.messages().empty()); } + + private: + base::test::ScopedFeatureList feature_list_; }; // Verify that there's no Trusted Types violation in chrome://chrome-urls IN_PROC_BROWSER_TEST_P(ChromeURLDataManagerWebUITrustedTypesTest, NoTrustedTypesViolation) { + LOG(INFO) << "Navigating to " << GetParam(); CheckTrustedTypesViolation(GetParam()); } @@ -176,23 +196,18 @@ // TODO(crbug.com/1114074): DCHECK failure when opening // chrome://appcache-internals. // "chrome://appcache-internals", - "chrome://apps", "chrome://autofill-internals", "chrome://blob-internals", "chrome://bluetooth-internals", "chrome://bookmarks", - "chrome://browser-switch", "chrome://chrome-urls", "chrome://components", - "chrome://conflicts", "chrome://connection-help", "chrome://connection-monitoring-detected", "chrome://conversion-internals", "chrome://crashes", "chrome://credits", "chrome://device-log", - // TODO(crbug.com/1114062): Crash when closing chrome://devices. - // "chrome://devices", "chrome://dino", // TODO(crbug.com/1113446): Test failure due to excessive output. // "chrome://discards", @@ -215,21 +230,18 @@ "chrome://invalidations", "chrome://local-state", "chrome://management", - "chrome://md-user-manager", "chrome://media-engagement", "chrome://media-feeds", "chrome://media-history", "chrome://media-internals", "chrome://media-router-internals", "chrome://memory-internals", - "chrome://nacl", "chrome://net-export", "chrome://net-internals", "chrome://network-error", "chrome://network-errors", "chrome://new-tab-page", "chrome://newtab", - "chrome://notifications-internals", "chrome://ntp-tiles-internals", "chrome://omnibox", "chrome://password-manager-internals", @@ -241,16 +253,13 @@ "chrome://quota-internals", "chrome://reset-password", "chrome://safe-browsing", - "chrome://sandbox", "chrome://serviceworker-internals", "chrome://settings", // TODO(crbug.com/1115600): DCHECK failure when opening // chrome://signin-dice-web-intercept. // "chrome://signin-dice-web-intercept", - "chrome://signin-email-confirmation", "chrome://signin-internals", "chrome://site-engagement", - "chrome://snippets-internals", "chrome://suggestions", // TODO(crbug.com/1099564): Navigating to chrome://sync-confirmation and // quickly navigating away cause DCHECK failure. @@ -270,12 +279,12 @@ "chrome://version", "chrome://webrtc-internals", "chrome://webrtc-logs", - "chrome://welcome", #if defined(OS_ANDROID) "chrome://explore-sites-internals", "chrome://internals/notifications", "chrome://internals/query-tiles", "chrome://offline-internals", + "chrome://snippets-internals", "chrome://webapks", #endif #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -295,7 +304,6 @@ "chrome://crostini-installer", "chrome://cryptohome", "chrome://drive-internals", - "chrome://first-run", "chrome://help-app", "chrome://internet-config-dialog", "chrome://internet-detail-dialog", @@ -314,11 +322,22 @@ "chrome://smb-share-dialog", "chrome://supervised-user-internals", "chrome://sys-internals", - // TODO(crbug.com/1115643): DCHECK failure when opening - // chrome-untrusted://crosh. - // "chrome-untrusted://crosh", "chrome-untrusted://terminal", #endif +#if !BUILDFLAG(IS_CHROMEOS_ASH) + "chrome://apps", + "chrome://browser-switch", + "chrome://md-user-manager", + "chrome://signin-email-confirmation", + "chrome://welcome", +#endif +#if !defined(OS_MAC) + "chrome://sandbox", + "chrome://nacl", +#endif +#if defined(OS_WIN) + "chrome://conflicts", +#endif }; INSTANTIATE_TEST_SUITE_P(,
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc index ac1ba79..fb85417 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
@@ -48,8 +48,8 @@ #include "chrome/common/url_constants.h" #include "chrome/grit/browser_resources.h" #include "chrome/grit/chromium_strings.h" -#include "chrome/grit/component_extension_resources.h" #include "chrome/grit/generated_resources.h" +#include "chrome/grit/pdf_resources.h" #include "chrome/grit/print_preview_resources.h" #include "chrome/grit/print_preview_resources_map.h" #include "chromeos/constants/chromeos_features.h" @@ -415,11 +415,14 @@ {"pdf/browser_api.js", IDR_PDF_BROWSER_API_JS}, {"pdf/constants.js", IDR_PDF_CONSTANTS_JS}, {"pdf/controller.js", IDR_PDF_CONTROLLER_JS}, - {"pdf/elements/icons.js", IDR_PDF_ICONS_JS}, - {"pdf/elements/shared-vars.js", IDR_PDF_SHARED_VARS_JS}, - {"pdf/elements/viewer-error-screen.js", IDR_PDF_VIEWER_ERROR_SCREEN_JS}, - {"pdf/elements/viewer-zoom-button.js", IDR_PDF_VIEWER_ZOOM_BUTTON_JS}, - {"pdf/elements/viewer-zoom-toolbar.js", IDR_PDF_VIEWER_ZOOM_SELECTOR_JS}, + {"pdf/elements/icons.js", IDR_PDF_ELEMENTS_ICONS_JS}, + {"pdf/elements/shared-vars.js", IDR_PDF_ELEMENTS_SHARED_VARS_JS}, + {"pdf/elements/viewer-error-screen.js", + IDR_PDF_ELEMENTS_VIEWER_ERROR_SCREEN_JS}, + {"pdf/elements/viewer-zoom-button.js", + IDR_PDF_ELEMENTS_VIEWER_ZOOM_BUTTON_JS}, + {"pdf/elements/viewer-zoom-toolbar.js", + IDR_PDF_ELEMENTS_VIEWER_ZOOM_TOOLBAR_JS}, {"pdf/gesture_detector.js", IDR_PDF_GESTURE_DETECTOR_JS}, {"pdf/index.css", IDR_PDF_INDEX_CSS}, {"pdf/main.js", IDR_PDF_MAIN_JS},
diff --git a/chrome/browser/ui/webui/settings/chromeos/multidevice_section.cc b/chrome/browser/ui/webui/settings/chromeos/multidevice_section.cc index 756ee38d..a7d96dc 100644 --- a/chrome/browser/ui/webui/settings/chromeos/multidevice_section.cc +++ b/chrome/browser/ui/webui/settings/chromeos/multidevice_section.cc
@@ -36,6 +36,8 @@ namespace settings { namespace { +using FeatureState = multidevice_setup::mojom::FeatureState; + const std::vector<SearchConcept>& GetMultiDeviceOptedInSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags( {{IDS_OS_SETTINGS_TAG_MULTIDEVICE_FORGET, @@ -551,14 +553,11 @@ host_status_with_device) { SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); updater.RemoveSearchTags(GetMultiDeviceOptedOutSearchConcepts()); - updater.RemoveSearchTags(GetMultiDeviceOptedInPhoneHubSearchConcepts()); updater.RemoveSearchTags(GetMultiDeviceOptedInWifiSyncSearchConcepts()); updater.RemoveSearchTags(GetMultiDeviceOptedInSearchConcepts()); if (IsOptedIn(host_status_with_device.first)) { updater.AddSearchTags(GetMultiDeviceOptedInSearchConcepts()); - if (features::IsPhoneHubEnabled()) - updater.AddSearchTags(GetMultiDeviceOptedInPhoneHubSearchConcepts()); if (features::IsWifiSyncAndroidEnabled()) updater.AddSearchTags(GetMultiDeviceOptedInWifiSyncSearchConcepts()); } else { @@ -571,11 +570,14 @@ feature_states_map) { SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); updater.RemoveSearchTags(GetSmartLockOptionsSearchConcepts()); + updater.RemoveSearchTags(GetMultiDeviceOptedInPhoneHubSearchConcepts()); if (feature_states_map.at(multidevice_setup::mojom::Feature::kSmartLock) == multidevice_setup::mojom::FeatureState::kEnabledByUser) { updater.AddSearchTags(GetSmartLockOptionsSearchConcepts()); } + if (IsPhoneHubSupported()) + updater.AddSearchTags(GetMultiDeviceOptedInPhoneHubSearchConcepts()); } void MultiDeviceSection::OnNearbySharingEnabledChanged() { @@ -590,5 +592,12 @@ } } +bool MultiDeviceSection::IsPhoneHubSupported() { + const FeatureState feature_state = multidevice_setup_client_->GetFeatureState( + multidevice_setup::mojom::Feature::kPhoneHub); + return feature_state != FeatureState::kNotSupportedByPhone && + feature_state != FeatureState::kNotSupportedByChromebook; +} + } // namespace settings } // namespace chromeos
diff --git a/chrome/browser/ui/webui/settings/chromeos/multidevice_section.h b/chrome/browser/ui/webui/settings/chromeos/multidevice_section.h index f420b8a9..3663219 100644 --- a/chrome/browser/ui/webui/settings/chromeos/multidevice_section.h +++ b/chrome/browser/ui/webui/settings/chromeos/multidevice_section.h
@@ -68,6 +68,8 @@ // Nearby Share enabled pref change observer. void OnNearbySharingEnabledChanged(); + bool IsPhoneHubSupported(); + multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client_; phonehub::PhoneHubManager* phone_hub_manager_; android_sms::AndroidSmsService* android_sms_service_;
diff --git a/chrome/browser/ui/webui/settings/people_handler.cc b/chrome/browser/ui/webui/settings/people_handler.cc index 707c936..d4aa5a0 100644 --- a/chrome/browser/ui/webui/settings/people_handler.cc +++ b/chrome/browser/ui/webui/settings/people_handler.cc
@@ -817,22 +817,26 @@ web_contents->GetDelegate()->ActivateContents(web_contents); } -void PeopleHandler::OnPrimaryAccountSet( - const CoreAccountInfo& primary_account_info) { - // After a primary account was set, the Sync setup will start soon. Grab a - // SetupInProgressHandle right now to avoid a temporary "missing Sync - // confirmation" error in the avatar menu. See crbug.com/928696. - syncer::SyncService* service = GetSyncService(); - if (service && !sync_blocker_) - sync_blocker_ = service->GetSetupInProgressHandle(); - - UpdateSyncStatus(); -} - -void PeopleHandler::OnPrimaryAccountCleared( - const CoreAccountInfo& previous_primary_account_info) { - sync_blocker_.reset(); - UpdateSyncStatus(); +void PeopleHandler::OnPrimaryAccountChanged( + const signin::PrimaryAccountChangeEvent& event) { + switch (event.GetEventTypeFor(signin::ConsentLevel::kSync)) { + case signin::PrimaryAccountChangeEvent::Type::kSet: { + // After a primary account was set, the Sync setup will start soon. Grab a + // SetupInProgressHandle right now to avoid a temporary "missing Sync + // confirmation" error in the avatar menu. See crbug.com/928696. + syncer::SyncService* service = GetSyncService(); + if (service && !sync_blocker_) + sync_blocker_ = service->GetSetupInProgressHandle(); + UpdateSyncStatus(); + return; + } + case signin::PrimaryAccountChangeEvent::Type::kCleared: + sync_blocker_.reset(); + UpdateSyncStatus(); + return; + case signin::PrimaryAccountChangeEvent::Type::kNone: + return; + } } void PeopleHandler::OnStateChanged(syncer::SyncService* sync) {
diff --git a/chrome/browser/ui/webui/settings/people_handler.h b/chrome/browser/ui/webui/settings/people_handler.h index fdc26132..e189aec8 100644 --- a/chrome/browser/ui/webui/settings/people_handler.h +++ b/chrome/browser/ui/webui/settings/people_handler.h
@@ -126,10 +126,8 @@ void FocusUI() override; // IdentityManager::Observer implementation. - void OnPrimaryAccountSet( - const CoreAccountInfo& primary_account_info) override; - void OnPrimaryAccountCleared( - const CoreAccountInfo& previous_primary_account_info) override; + void OnPrimaryAccountChanged( + const signin::PrimaryAccountChangeEvent& event) override; void OnExtendedAccountInfoUpdated(const AccountInfo& info) override; void OnExtendedAccountInfoRemoved(const AccountInfo& info) override;
diff --git a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.cc b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.cc index 18421be..66553cd 100644 --- a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.cc +++ b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.cc
@@ -181,6 +181,8 @@ l10n_util::GetStringUTF8(confirmButtonStringID)); parameters.SetStringKey("cancelButtonLabel", l10n_util::GetStringUTF8(cancelButtonStringID)); + parameters.SetBoolKey("showGuestOption", + bubble_parameters_.show_guest_option); parameters.SetKey("interceptedAccount", GetAccountInfoValue(intercepted_account())); parameters.SetStringKey("headerBackgroundColor",
diff --git a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_ui.cc b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_ui.cc index f8e2153..09d0d15 100644 --- a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_ui.cc +++ b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_ui.cc
@@ -33,7 +33,6 @@ source->AddResourcePath("signin_vars_css.js", IDR_SIGNIN_VARS_CSS_JS); source->AddLocalizedString("guestLink", IDS_SIGNIN_DICE_WEB_INTERCEPT_BUBBLE_GUEST_LINK); - source->AddBoolean("shouldShowGuest", ShouldShowGuestOption()); source->UseStringsJs(); // Resources for testing. @@ -49,12 +48,6 @@ DiceWebSigninInterceptUI::~DiceWebSigninInterceptUI() = default; -// static -bool DiceWebSigninInterceptUI::ShouldShowGuestOption() { - return Profile::IsEphemeralGuestProfileEnabled() && - !ProfileManager::GuestProfileExists(); -} - void DiceWebSigninInterceptUI::Initialize( const DiceWebSigninInterceptor::Delegate::BubbleParameters& bubble_parameters,
diff --git a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_ui.h b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_ui.h index c2aafa7d..f937ed0 100644 --- a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_ui.h +++ b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_ui.h
@@ -28,8 +28,6 @@ bubble_parameters, base::OnceCallback<void(SigninInterceptionUserChoice)> callback); - static bool ShouldShowGuestOption(); - private: WEB_UI_CONTROLLER_TYPE_DECL(); };
diff --git a/chrome/browser/ui/webui/signin/login_ui_test_utils.cc b/chrome/browser/ui/webui/signin/login_ui_test_utils.cc index c0099ea..d82d5a5 100644 --- a/chrome/browser/ui/webui/signin/login_ui_test_utils.cc +++ b/chrome/browser/ui/webui/signin/login_ui_test_utils.cc
@@ -83,9 +83,14 @@ FAIL() << "Sign in observer timed out!"; } - void OnPrimaryAccountSet( - const CoreAccountInfo& primary_account_info) override { - DVLOG(1) << "Google signin succeeded."; + void OnPrimaryAccountChanged( + const signin::PrimaryAccountChangeEvent& event) override { + if (event.GetEventTypeFor(signin::ConsentLevel::kSync) != + signin::PrimaryAccountChangeEvent::Type::kSet) { + return; + } + + DVLOG(1) << "Sign in finished: Sync primary account was set."; signed_in_ = true; QuitLoopRunner(); }
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc b/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc index 79134b5..f21f622f 100644 --- a/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc +++ b/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc
@@ -163,18 +163,16 @@ return; } - std::string picture_url_to_load; GURL picture_gurl(picture_url); - if (picture_gurl.is_valid()) { - picture_url_to_load = - signin::GetAvatarImageURLWithOptions(picture_gurl, kProfileImageSize, - false /* no_silhouette */) - .spec(); - } else { - // Use the placeholder avatar icon until the account picture URL is fetched. - picture_url_to_load = profiles::GetPlaceholderAvatarIconUrl(); + if (!picture_gurl.is_valid()) { + // As long as the provided gaia picture is not valid, stick to the default + // avatar provided in the load-time data. + return; } - base::Value picture_url_value(picture_url_to_load); + + GURL picture_gurl_with_options = signin::GetAvatarImageURLWithOptions( + picture_gurl, kProfileImageSize, false /* no_silhouette */); + base::Value picture_url_value(picture_gurl_with_options.spec()); AllowJavascript(); FireWebUIListener("account-image-changed", picture_url_value); @@ -229,7 +227,6 @@ } if (!primary_account_info->IsValid()) { - SetUserImageURL(kNoPictureURLFound); identity_manager_->AddObserver(this); } else { SetUserImageURL(primary_account_info->picture_url);
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc b/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc index 2c334c7..ea69b790 100644 --- a/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc +++ b/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc
@@ -170,16 +170,14 @@ base::Optional<AccountInfo> primary_account = identity_manager->FindExtendedAccountInfoForAccountWithRefreshToken( identity_manager->GetPrimaryAccountInfo()); + EXPECT_TRUE(primary_account); - std::string original_picture_url = - primary_account ? primary_account->picture_url : std::string(); + std::string gaia_picture_url = primary_account->picture_url; std::string expected_picture_url = - original_picture_url.empty() - ? profiles::GetPlaceholderAvatarIconUrl() - : signin::GetAvatarImageURLWithOptions(GURL(original_picture_url), - kExpectedProfileImageSize, - false /* no_silhouette */) - .spec(); + signin::GetAvatarImageURLWithOptions(GURL(gaia_picture_url), + kExpectedProfileImageSize, + false /* no_silhouette */) + .spec(); std::string passed_picture_url; ASSERT_TRUE(call_data.arg2()->GetAsString(&passed_picture_url)); EXPECT_EQ(expected_picture_url, passed_picture_url); @@ -233,16 +231,16 @@ args.Set(0, std::make_unique<base::Value>(kDefaultDialogHeight)); handler()->HandleInitializedWithSize(&args); - ASSERT_EQ(1U, web_ui()->call_data().size()); - ExpectAccountImageChanged(*web_ui()->call_data()[0]); + // No callback called when there's no account image available. + ASSERT_EQ(0U, web_ui()->call_data().size()); identity_test_env()->SimulateSuccessfulFetchOfAccountInfo( account_info_.account_id, account_info_.email, account_info_.gaia, "", "full_name", "given_name", "locale", "http://picture.example.com/picture.jpg"); - ASSERT_EQ(2U, web_ui()->call_data().size()); - ExpectAccountImageChanged(*web_ui()->call_data()[1]); + ASSERT_EQ(1U, web_ui()->call_data().size()); + ExpectAccountImageChanged(*web_ui()->call_data()[0]); } TEST_F(SyncConfirmationHandlerTest, @@ -250,7 +248,7 @@ base::ListValue args; args.Set(0, std::make_unique<base::Value>(kDefaultDialogHeight)); handler()->HandleInitializedWithSize(&args); - EXPECT_EQ(1U, web_ui()->call_data().size()); + EXPECT_EQ(0U, web_ui()->call_data().size()); AccountInfo account_info = identity_test_env()->MakeAccountAvailable("bar@example.com"); @@ -261,7 +259,7 @@ // Updating the account info of a secondary account should not update the // image of the sync confirmation dialog. - EXPECT_EQ(1U, web_ui()->call_data().size()); + EXPECT_EQ(0U, web_ui()->call_data().size()); identity_test_env()->SimulateSuccessfulFetchOfAccountInfo( account_info_.account_id, account_info_.email, account_info_.gaia, "", @@ -270,8 +268,8 @@ // Updating the account info of the primary account should update the // image of the sync confirmation dialog. - ASSERT_EQ(2U, web_ui()->call_data().size()); - ExpectAccountImageChanged(*web_ui()->call_data()[1]); + ASSERT_EQ(1U, web_ui()->call_data().size()); + ExpectAccountImageChanged(*web_ui()->call_data()[0]); } TEST_F(SyncConfirmationHandlerTest, TestHandleUndo) {
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc b/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc index b4e0b72..0562c53a 100644 --- a/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc +++ b/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/signin/profile_colors_util.h" #include "chrome/browser/ui/webui/signin/sync_confirmation_handler.h" #include "chrome/common/url_constants.h" #include "chrome/grit/browser_resources.h" @@ -25,25 +26,32 @@ #include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/webui/web_ui_util.h" +#include "ui/gfx/color_utils.h" #include "ui/resources/grit/webui_generated_resources.h" #include "ui/resources/grit/webui_resources.h" SyncConfirmationUI::SyncConfirmationUI(content::WebUI* web_ui) : SigninWebDialogUI(web_ui), profile_(Profile::FromWebUI(web_ui)) { - Initialize(); + // Initializing the WebUIDataSource in the constructor is needed for polymer + // tests. + Initialize(/*profile_creation_flow_color=*/base::nullopt); } -SyncConfirmationUI::~SyncConfirmationUI() {} +SyncConfirmationUI::~SyncConfirmationUI() = default; void SyncConfirmationUI::InitializeMessageHandlerWithBrowser(Browser* browser) { InitializeMessageHandler(browser); } -void SyncConfirmationUI::InitializeMessageHandlerForCreationFlow() { +void SyncConfirmationUI::InitializeMessageHandlerForCreationFlow( + SkColor profile_color) { + // Redo the initialization with `profile_color`. + Initialize(profile_color); InitializeMessageHandler(/*browser=*/nullptr); } -void SyncConfirmationUI::Initialize() { +void SyncConfirmationUI::Initialize( + base::Optional<SkColor> profile_creation_flow_color) { const bool is_sync_allowed = ProfileSyncServiceFactory::IsSyncAllowed(profile_); @@ -58,7 +66,7 @@ source->AddResourcePath("sync_confirmation.js", IDR_SYNC_CONFIRMATION_JS); if (is_sync_allowed) { - InitializeForSyncConfirmation(source); + InitializeForSyncConfirmation(source, profile_creation_flow_color); } else { InitializeForSyncDisabled(source); } @@ -79,24 +87,15 @@ } void SyncConfirmationUI::InitializeForSyncConfirmation( - content::WebUIDataSource* source) { + content::WebUIDataSource* source, + base::Optional<SkColor> profile_creation_flow_color) { + // Resources for testing. source->AddResourcePath("test_loader.js", IDR_WEBUI_JS_TEST_LOADER_JS); source->AddResourcePath("test_loader.html", IDR_WEBUI_HTML_TEST_LOADER_HTML); source->OverrideContentSecurityPolicy( network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources chrome://test 'self';"); - source->SetDefaultResource(IDR_SYNC_CONFIRMATION_HTML); - source->AddResourcePath("sync_confirmation_app.js", - IDR_SYNC_CONFIRMATION_APP_JS); - - source->AddResourcePath( - "images/sync_confirmation_illustration.svg", - IDR_SYNC_CONFIRMATION_IMAGES_SYNC_CONFIRMATION_ILLUSTRATION_SVG); - source->AddResourcePath( - "images/sync_confirmation_illustration_dark.svg", - IDR_SYNC_CONFIRMATION_IMAGES_SYNC_CONFIRMATION_ILLUSTRATION_DARK_SVG); - AddStringResource(source, "syncConfirmationTitle", IDS_SYNC_CONFIRMATION_TITLE); AddStringResource(source, "syncConfirmationSyncInfoTitle", @@ -109,24 +108,48 @@ IDS_SYNC_CONFIRMATION_SETTINGS_BUTTON_LABEL); AddStringResource(source, "syncConfirmationConfirmLabel", IDS_SYNC_CONFIRMATION_CONFIRM_BUTTON_LABEL); - AddStringResource(source, "syncConfirmationUndoLabel", IDS_CANCEL); - constexpr int kAccountPictureSize = 68; - std::string custom_picture_url = profiles::GetPlaceholderAvatarIconUrl(); - signin::IdentityManager* identity_manager = - IdentityManagerFactory::GetForProfile(profile_); - base::Optional<AccountInfo> primary_account_info = - identity_manager->FindExtendedAccountInfoForAccountWithRefreshToken( - identity_manager->GetPrimaryAccountInfo()); - GURL account_picture_url( - primary_account_info ? primary_account_info->picture_url : std::string()); - if (account_picture_url.is_valid()) { - custom_picture_url = - signin::GetAvatarImageURLWithOptions( - account_picture_url, kAccountPictureSize, false /* no_silhouette */) - .spec(); + const int kAccountPictureSize = 128; + std::string avatar_picture_url; + if (profile_creation_flow_color.has_value()) { + SkColor fill_color = *profile_creation_flow_color; + gfx::Image avatar_picture = profiles::GetPlaceholderAvatarIconWithColors( + /*fill_color=*/fill_color, + /*stroke_color=*/GetAvatarStrokeColor(fill_color), kAccountPictureSize); + avatar_picture_url = webui::GetBitmapDataUrl(avatar_picture.AsBitmap()); + } else { + avatar_picture_url = profiles::GetPlaceholderAvatarIconUrl(); } - source->AddString("accountPictureUrl", custom_picture_url); + source->AddString("accountPictureUrl", avatar_picture_url); + + source->AddResourcePath("sync_confirmation_app.js", + IDR_SYNC_CONFIRMATION_APP_JS); + source->SetDefaultResource(IDR_SYNC_CONFIRMATION_HTML); + + source->AddBoolean("isProfileCreationFlow", + profile_creation_flow_color.has_value()); + if (!profile_creation_flow_color.has_value()) { + AddStringResource(source, "syncConfirmationUndoLabel", IDS_CANCEL); + + source->AddResourcePath( + "images/sync_confirmation_illustration.svg", + IDR_SYNC_CONFIRMATION_IMAGES_SYNC_CONFIRMATION_ILLUSTRATION_SVG); + source->AddResourcePath( + "images/sync_confirmation_illustration_dark.svg", + IDR_SYNC_CONFIRMATION_IMAGES_SYNC_CONFIRMATION_ILLUSTRATION_DARK_SVG); + return; + } + + AddStringResource(source, "syncConfirmationUndoLabel", IDS_NO_THANKS); + source->AddString("highlightColor", color_utils::SkColorToRgbaString( + *profile_creation_flow_color)); + + source->AddResourcePath( + "images/sync_confirmation_refreshed_illustration.svg", + IDR_SYNC_CONFIRMATION_IMAGES_SYNC_CONFIRMATION_REFRESHED_ILLUSTRATION_SVG); + source->AddResourcePath( + "images/sync_confirmation_refreshed_illustration_dark.svg", + IDR_SYNC_CONFIRMATION_IMAGES_SYNC_CONFIRMATION_REFRESHED_ILLUSTRATION_DARK_SVG); } void SyncConfirmationUI::InitializeForSyncDisabled(
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_ui.h b/chrome/browser/ui/webui/signin/sync_confirmation_ui.h index 3dd46725..923a0ac 100644 --- a/chrome/browser/ui/webui/signin/sync_confirmation_ui.h +++ b/chrome/browser/ui/webui/signin/sync_confirmation_ui.h
@@ -37,12 +37,14 @@ // Initializes the message handler for the profile creation flow (when there's // no browser available). - void InitializeMessageHandlerForCreationFlow(); + void InitializeMessageHandlerForCreationFlow(SkColor profile_color); private: - void Initialize(); + void Initialize(base::Optional<SkColor> profile_creation_flow_color); void InitializeMessageHandler(Browser* browser); - void InitializeForSyncConfirmation(content::WebUIDataSource* source); + void InitializeForSyncConfirmation( + content::WebUIDataSource* source, + base::Optional<SkColor> profile_creation_flow_color); void InitializeForSyncDisabled(content::WebUIDataSource* source); // Adds a string resource with the given GRD |ids| to the WebUI data |source|
diff --git a/chrome/browser/webapps/chrome_webapps_client.cc b/chrome/browser/webapps/chrome_webapps_client.cc index 9c0b640b..038dc5fb 100644 --- a/chrome/browser/webapps/chrome_webapps_client.cc +++ b/chrome/browser/webapps/chrome_webapps_client.cc
@@ -13,6 +13,9 @@ #include "chrome/browser/android/tab_android.h" #include "chrome/browser/android/tab_web_contents_delegate_android.h" #include "chrome/browser/android/webapk/webapk_install_service.h" +#include "chrome/browser/feature_engagement/tracker_factory.h" +#include "components/feature_engagement/public/event_constants.h" +#include "components/feature_engagement/public/tracker.h" #endif namespace webapps { @@ -84,6 +87,15 @@ tab->web_contents()->GetDelegate()) ->CanShowAppBanners(); } + +void ChromeWebappsClient::OnWebApkInstallInitiatedFromAppMenu( + content::WebContents* web_contents) { + DVLOG(2) << "Sending event: IPH used for Installing PWA"; + feature_engagement::Tracker* tracker = + feature_engagement::TrackerFactory::GetForBrowserContext( + web_contents->GetBrowserContext()); + tracker->NotifyEvent(feature_engagement::events::kPwaInstallMenuSelected); +} #endif } // namespace webapps
diff --git a/chrome/browser/webapps/chrome_webapps_client.h b/chrome/browser/webapps/chrome_webapps_client.h index 0227c9b..b12377f 100644 --- a/chrome/browser/webapps/chrome_webapps_client.h +++ b/chrome/browser/webapps/chrome_webapps_client.h
@@ -29,6 +29,8 @@ bool IsInstallationInProgress(content::WebContents* web_contents, const GURL& manifest_url) override; bool CanShowAppBanners(content::WebContents* web_contents) override; + void OnWebApkInstallInitiatedFromAppMenu( + content::WebContents* web_contents) override; #endif private:
diff --git a/chrome/browser/webshare/BUILD.gn b/chrome/browser/webshare/BUILD.gn index 72725dd9..c36e200 100644 --- a/chrome/browser/webshare/BUILD.gn +++ b/chrome/browser/webshare/BUILD.gn
@@ -4,8 +4,8 @@ import("//build/config/chromeos/ui_mode.gni") -static_library("storage") { - if (is_chromeos || is_mac) { +if (is_chromeos || is_mac) { + static_library("storage") { sources = [ "prepare_directory_task.cc", "prepare_directory_task.h",
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 3f5ab7e..b968fa66 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-master-1610063718-75764fb6f7cc7a2d4d8119e0952784a5ac3fa72a.profdata +chrome-linux-master-1610107094-a1b03a814715c7959032a16f0512a58b7ebd318d.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 498932ef..4f2aa6a 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-master-1610052964-246b43420c64aac53ecf14d1b97c19dc58b69e86.profdata +chrome-win32-master-1610096386-b7d9ff85a7e5a6b9d422dd8ae3e7ff1b6461dd2b.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 10b0b39b..b58e242 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-master-1610052964-a33bb7f09ef1aa4be028cda8573fe902d004ec4a.profdata +chrome-win64-master-1610074312-1e61cca385dcdccbd239aae3d699d6888b006a9e.profdata
diff --git a/chrome/chrome_paks.gni b/chrome/chrome_paks.gni index 58f9c54..6ad9c87 100644 --- a/chrome/chrome_paks.gni +++ b/chrome/chrome_paks.gni
@@ -268,6 +268,10 @@ "//extensions:extensions_resources", ] } + if (enable_plugins) { + sources += [ "$root_gen_dir/chrome/pdf_resources.pak" ] + deps += [ "//chrome/browser/resources/pdf:pdf_resources" ] + } if (enable_print_preview) { sources += [ "$root_gen_dir/chrome/print_preview_resources.pak" ] deps +=
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 5660057..982cd07 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -735,7 +735,13 @@ base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kRemoveStatusBarInWebApps{ - "RemoveStatusBarInWebApps", base::FEATURE_DISABLED_BY_DEFAULT}; + "RemoveStatusBarInWebApps", +#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS) + base::FEATURE_ENABLED_BY_DEFAULT +#else + base::FEATURE_DISABLED_BY_DEFAULT +#endif +}; #if BUILDFLAG(IS_CHROMEOS_ASH) // Enables permanent removal of Legacy Supervised Users on startup.
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 4d91fff3..0beadd9 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -5761,7 +5761,7 @@ "//components/safe_browsing/content/triggers:ad_redirect_trigger", "//components/safe_browsing/core:ping_manager_unittest", "//components/safe_browsing/core/browser:safe_browsing_url_checker_unittest", - "//components/safe_browsing/core/browser:token_fetcher_unittest", + "//components/safe_browsing/core/browser/sync:unittests", "//components/safe_browsing/core/db:v4_test_util", ] } else if (safe_browsing_mode == 2 && is_android) {
diff --git a/chrome/test/data/webui/signin/dice_web_signin_intercept_test.js b/chrome/test/data/webui/signin/dice_web_signin_intercept_test.js index fd8a52b..fcb41999 100644 --- a/chrome/test/data/webui/signin/dice_web_signin_intercept_test.js +++ b/chrome/test/data/webui/signin/dice_web_signin_intercept_test.js
@@ -8,7 +8,7 @@ import {AccountInfo, DiceWebSigninInterceptBrowserProxyImpl, InterceptionParameters} from 'chrome://signin-dice-web-intercept/dice_web_signin_intercept_browser_proxy.js'; import {assertEquals, assertFalse, assertTrue} from '../chai_assert.js'; -import {isChildVisible} from '../test_util.m.js'; +import {isChildVisible, waitAfterNextRender} from '../test_util.m.js'; import {TestDiceWebSigninInterceptBrowserProxy} from './test_dice_web_signin_intercept_browser_proxy.js'; @@ -29,7 +29,7 @@ /** @type {string} */ const AVATAR_URL_2 = 'chrome://theme/IDR_PROFILE_AVATAR_2'; - setup(function() { + setup(async function() { browserProxy = new TestDiceWebSigninInterceptBrowserProxy(); browserProxy.setInterceptionParameters({ headerText: 'header_text', @@ -37,6 +37,7 @@ bodyText: 'body_text', confirmButtonLabel: 'confirm_label', cancelButtonLabel: 'cancel_label', + showGuestOption: true, headerTextColor: 'rgba(255, 255, 255, 1)', headerBackgroundColor: 'rgba(255, 0, 0, 1)', interceptedAccount: {isManaged: false, pictureUrl: AVATAR_URL_1}, @@ -47,6 +48,7 @@ app = /** @type {!DiceWebSigninInterceptAppElement} */ ( document.createElement('dice-web-signin-intercept-app')); document.body.append(app); + await waitAfterNextRender(app); return browserProxy.whenCalled('pageLoaded'); }); @@ -134,9 +136,11 @@ bodyText: 'new_body_text', confirmButtonLabel: 'new_confirm_label', cancelButtonLabel: 'new_cancel_label', + showGuestOption: true, headerTextColor: 'rgba(255, 255, 255, 1)', headerBackgroundColor: 'rgba(255, 0, 0, 1)', interceptedAccount: {isManaged: false, pictureUrl: AVATAR_URL_1}, + primaryAccount: {isManaged: false, pictureUrl: AVATAR_URL_2} }); checkTextValues( 'new_header_text', 'new_body_title', 'new_body_text', @@ -154,9 +158,11 @@ bodyText: 'body_text', confirmButtonLabel: 'confirm_label', cancelButtonLabel: 'cancel_label', + showGuestOption: true, headerTextColor: 'rgba(255, 255, 255, 1)', headerBackgroundColor: 'rgba(255, 0, 0, 1)', interceptedAccount: {isManaged: false, pictureUrl: AVATAR_URL_2}, + primaryAccount: {isManaged: false, pictureUrl: AVATAR_URL_2} }; // Update urls.
diff --git a/chrome/test/data/webui/signin/sync_confirmation_test.js b/chrome/test/data/webui/signin/sync_confirmation_test.js index c21318ad..48d856e 100644 --- a/chrome/test/data/webui/signin/sync_confirmation_test.js +++ b/chrome/test/data/webui/signin/sync_confirmation_test.js
@@ -23,7 +23,7 @@ // Tests that no DCHECKS are thrown during initialization of the UI. test('LoadPage', function() { assertEquals( - 'Turn on sync?', app.$.syncConfirmationHeading.textContent.trim()); + 'Turn on sync?', app.$$('#syncConfirmationHeading').textContent.trim()); }); }); @@ -48,6 +48,9 @@ PolymerTest.clearBody(); app = document.createElement('sync-confirmation-app'); document.body.append(app); + // Wait for the app element to get attached to the document (which is when + // the account image gets requested). + return browserProxy.whenCalled('requestAccountImage'); }); const STANDARD_CONSENT_DESCRIPTION_TEXT = [
diff --git a/chrome/test/data/webui/signin/test_dice_web_signin_intercept_browser_proxy.js b/chrome/test/data/webui/signin/test_dice_web_signin_intercept_browser_proxy.js index d85ab32..bb92c87 100644 --- a/chrome/test/data/webui/signin/test_dice_web_signin_intercept_browser_proxy.js +++ b/chrome/test/data/webui/signin/test_dice_web_signin_intercept_browser_proxy.js
@@ -17,6 +17,7 @@ bodyText: '', cancelButtonLabel: '', confirmButtonLabel: '', + showGuestOption: false, headerTextColor: '', headerBackgroundColor: '', interceptedAccount: {isManaged: false, pictureUrl: ''},
diff --git a/chromeos/components/account_manager/account_manager_facade_ash.cc b/chromeos/components/account_manager/account_manager_facade_ash.cc index 7445979..65dd43a 100644 --- a/chromeos/components/account_manager/account_manager_facade_ash.cc +++ b/chromeos/components/account_manager/account_manager_facade_ash.cc
@@ -18,4 +18,16 @@ return account_manager_->IsInitialized(); } +void AccountManagerFacadeAsh::ShowAddAccountDialog( + const AccountAdditionSource& source, + base::OnceCallback<void(const AccountAdditionResult& result)> callback) { + // TODO(crbug.com/1140469): implement this. +} + +void AccountManagerFacadeAsh::ShowReauthAccountDialog( + const AccountAdditionSource& source, + const std::string& email) { + // TODO(crbug.com/1140469): implement this. +} + } // namespace chromeos
diff --git a/chromeos/components/account_manager/account_manager_facade_ash.h b/chromeos/components/account_manager/account_manager_facade_ash.h index 0177c75..bf1ac59 100644 --- a/chromeos/components/account_manager/account_manager_facade_ash.h +++ b/chromeos/components/account_manager/account_manager_facade_ash.h
@@ -23,6 +23,12 @@ // AccountManagerFacade overrides: bool IsInitialized() override; + void ShowAddAccountDialog( + const AccountAdditionSource& source, + base::OnceCallback<void(const AccountAdditionResult& result)> callback) + override; + void ShowReauthAccountDialog(const AccountAdditionSource& source, + const std::string& email) override; private: AccountManager* const account_manager_;
diff --git a/chromeos/components/camera_app_ui/resources/css/main.css b/chromeos/components/camera_app_ui/resources/css/main.css index e7d3b8e..9fd93a0 100644 --- a/chromeos/components/camera_app_ui/resources/css/main.css +++ b/chromeos/components/camera_app_ui/resources/css/main.css
@@ -1020,13 +1020,13 @@ width: 50%; } -#preview-grid-horizontal.animate, -#preview-grid-horizontal.animate::before { +#preview-grid-horizontal, +#preview-grid-horizontal::before { transition: height 500ms, visibility 500ms; } -#preview-grid-vertical.animate, -#preview-grid-vertical.animate::before { +#preview-grid-vertical, +#preview-grid-vertical::before { transition: width 500ms, visibility 500ms; }
diff --git a/chromeos/components/camera_app_ui/resources/js/views/camera/options.js b/chromeos/components/camera_app_ui/resources/js/views/camera/options.js index 6a181d5..20a54996 100644 --- a/chromeos/components/camera_app_ui/resources/js/views/camera/options.js +++ b/chromeos/components/camera_app_ui/resources/js/views/camera/options.js
@@ -95,7 +95,6 @@ this.audioTrack_ = null; [['#switch-device', () => this.switchDevice_()], - ['#toggle-grid', () => this.animatePreviewGrid_()], ['#open-settings', () => nav.open(ViewName.SETTINGS)], ] .forEach( @@ -167,15 +166,6 @@ } /** - * Animates the preview grid. - * @private - */ - animatePreviewGrid_() { - Array.from(document.querySelector('#preview-grid').children) - .forEach((grid) => util.animateOnce(grid)); - } - - /** * Maps MediaTrackSettings.facingMode to CCA facing type. * @param {string|undefined} facing The target facingMode to map. * @return {!Facing} The mapped CCA facing.
diff --git a/chromeos/profiles/atom.afdo.newest.txt b/chromeos/profiles/atom.afdo.newest.txt index 76d5229..a07ada52 100644 --- a/chromeos/profiles/atom.afdo.newest.txt +++ b/chromeos/profiles/atom.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-atom-89-4367.0-1609757097-benchmark-89.0.4380.0-r1-redacted.afdo.xz +chromeos-chrome-amd64-atom-89-4367.0-1609757097-benchmark-89.0.4381.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/bigcore.afdo.newest.txt b/chromeos/profiles/bigcore.afdo.newest.txt index af6bf85..122eb2b 100644 --- a/chromeos/profiles/bigcore.afdo.newest.txt +++ b/chromeos/profiles/bigcore.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-bigcore-89-4367.0-1609764762-benchmark-89.0.4380.0-r1-redacted.afdo.xz +chromeos-chrome-amd64-bigcore-89-4367.0-1609764762-benchmark-89.0.4381.0-r1-redacted.afdo.xz
diff --git a/chromeos/services/assistant/BUILD.gn b/chromeos/services/assistant/BUILD.gn index 6b9c2d5..fb2d342 100644 --- a/chromeos/services/assistant/BUILD.gn +++ b/chromeos/services/assistant/BUILD.gn
@@ -26,8 +26,6 @@ "fake_assistant_manager_service_impl.h", "fake_assistant_settings_impl.cc", "fake_assistant_settings_impl.h", - "platform/audio_devices.cc", - "platform/audio_devices.h", "service.cc", "service.h", "service_context.h", @@ -82,8 +80,8 @@ "media_session/assistant_media_session.h", "platform/audio_device_owner.cc", "platform/audio_device_owner.h", - "platform/audio_input_host_impl.cc", - "platform/audio_input_host_impl.h", + "platform/audio_input_host.cc", + "platform/audio_input_host.h", "platform/audio_input_impl.cc", "platform/audio_input_impl.h", "platform/audio_input_provider_impl.cc", @@ -176,7 +174,6 @@ ] sources = [ - "platform/audio_devices_unittest.cc", "service_unittest.cc", "test_support/fully_initialized_assistant_state.cc", "test_support/fully_initialized_assistant_state.h",
diff --git a/chromeos/services/assistant/assistant_manager_service_delegate_impl.cc b/chromeos/services/assistant/assistant_manager_service_delegate_impl.cc index 6f6a5ec..a4a82b9 100644 --- a/chromeos/services/assistant/assistant_manager_service_delegate_impl.cc +++ b/chromeos/services/assistant/assistant_manager_service_delegate_impl.cc
@@ -9,7 +9,6 @@ #include <utility> #include "ash/public/cpp/assistant/assistant_state_base.h" -#include "chromeos/services/assistant/platform/audio_input_host_impl.h" #include "chromeos/services/assistant/platform_api_impl.h" #include "chromeos/services/assistant/service_context.h" #include "libassistant/shared/internal_api/assistant_manager_internal.h" @@ -21,26 +20,21 @@ AssistantManagerServiceDelegateImpl::AssistantManagerServiceDelegateImpl( mojo::PendingRemote<device::mojom::BatteryMonitor> battery_monitor, ServiceContext* context) - : battery_monitor_(std::move(battery_monitor)), context_(context) {} + : battery_monitor_(std::move(battery_monitor)), + context_(context) {} AssistantManagerServiceDelegateImpl::~AssistantManagerServiceDelegateImpl() = default; -std::unique_ptr<AudioInputHost> -AssistantManagerServiceDelegateImpl::CreateAudioInputHost() { - return std::make_unique<AudioInputHostImpl>( - context_->cras_audio_handler(), context_->power_manager_client(), - context_->assistant_state()->locale().value()); -} - std::unique_ptr<CrosPlatformApi> AssistantManagerServiceDelegateImpl::CreatePlatformApi( AssistantMediaSession* media_session, scoped_refptr<base::SingleThreadTaskRunner> background_thread_task_runner) { return std::make_unique<PlatformApiImpl>( media_session, context_->power_manager_client(), - std::move(battery_monitor_), context_->main_task_runner(), - background_thread_task_runner); + context_->cras_audio_handler(), std::move(battery_monitor_), + context_->main_task_runner(), background_thread_task_runner, + context_->assistant_state()->locale().value()); } std::unique_ptr<assistant_client::AssistantManager>
diff --git a/chromeos/services/assistant/assistant_manager_service_delegate_impl.h b/chromeos/services/assistant/assistant_manager_service_delegate_impl.h index 82836437..1d0eb8586 100644 --- a/chromeos/services/assistant/assistant_manager_service_delegate_impl.h +++ b/chromeos/services/assistant/assistant_manager_service_delegate_impl.h
@@ -25,15 +25,15 @@ ServiceContext* context); ~AssistantManagerServiceDelegateImpl() override; - // AssistantManagerServiceDelegate implementation: - std::unique_ptr<AudioInputHost> CreateAudioInputHost() override; std::unique_ptr<CrosPlatformApi> CreatePlatformApi( AssistantMediaSession* media_session, scoped_refptr<base::SingleThreadTaskRunner> background_thread_task_runner) override; + std::unique_ptr<assistant_client::AssistantManager> CreateAssistantManager( assistant_client::PlatformApi* platform_api, const std::string& lib_assistant_config) override; + assistant_client::AssistantManagerInternal* UnwrapAssistantManagerInternal( assistant_client::AssistantManager* assistant_manager) override;
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.cc b/chromeos/services/assistant/assistant_manager_service_impl.cc index d4df871..413dd9d 100644 --- a/chromeos/services/assistant/assistant_manager_service_impl.cc +++ b/chromeos/services/assistant/assistant_manager_service_impl.cc
@@ -40,7 +40,6 @@ #include "chromeos/services/assistant/public/cpp/device_actions.h" #include "chromeos/services/assistant/public/cpp/features.h" #include "chromeos/services/assistant/public/cpp/migration/assistant_manager_service_delegate.h" -#include "chromeos/services/assistant/public/cpp/migration/audio_input_host.h" #include "chromeos/services/assistant/public/cpp/migration/libassistant_v1_api.h" #include "chromeos/services/assistant/public/shared/utils.h" #include "chromeos/services/assistant/service_context.h" @@ -199,10 +198,6 @@ // To solve this chicken-and-egg problem, we need a separe Initialize() call. assistant_proxy_->Initialize(libassistant_service_host_.get()); - audio_input_host_ = delegate_->CreateAudioInputHost(); - - platform_api_->InitializeAudioInputHost(*audio_input_host_); - settings_delegate_ = std::make_unique<AssistantDeviceSettingsDelegate>(context); @@ -366,7 +361,7 @@ } void AssistantManagerServiceImpl::EnableHotword(bool enable) { - audio_input_host_->OnHotwordEnabled(enable); + platform_api_->OnHotwordEnabled(enable); } void AssistantManagerServiceImpl::SetArcPlayStoreEnabled(bool enable) { @@ -454,14 +449,14 @@ DCHECK(assistant_manager()); DVLOG(1) << __func__; - audio_input_host_->SetMicState(true); + platform_api_->SetMicState(true); assistant_manager()->StartAssistantInteraction(); } void AssistantManagerServiceImpl::StopActiveInteraction( bool cancel_conversation) { DVLOG(1) << __func__; - audio_input_host_->SetMicState(false); + platform_api_->SetMicState(false); if (!assistant_manager_internal()) { VLOG(1) << "Stopping interaction without assistant manager."; @@ -583,7 +578,7 @@ &AssistantManagerServiceImpl::OnConversationTurnStartedInternal, metadata); - audio_input_host_->OnConversationTurnStarted(); + platform_api_->OnConversationTurnStarted(); // Retrieve the cached interaction metadata associated with this conversation // turn or construct a new instance if there's no match in the cache. @@ -612,10 +607,10 @@ if (resolution != Resolution::NORMAL_WITH_FOLLOW_ON && resolution != Resolution::CANCELLED && resolution != Resolution::BARGE_IN) { - audio_input_host_->SetMicState(false); + platform_api_->SetMicState(false); } - audio_input_host_->OnConversationTurnFinished(); + platform_api_->OnConversationTurnFinished(); switch (resolution) { // Interaction ended normally. @@ -1401,11 +1396,6 @@ return api ? api->assistant_manager_internal() : nullptr; } -void AssistantManagerServiceImpl::SetMicState(bool mic_open) { - DCHECK(audio_input_host_); - audio_input_host_->SetMicState(mic_open); -} - ServiceControllerProxy& AssistantManagerServiceImpl::service_controller() { return assistant_proxy_->service_controller(); }
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.h b/chromeos/services/assistant/assistant_manager_service_impl.h index cff59765..26a3d96 100644 --- a/chromeos/services/assistant/assistant_manager_service_impl.h +++ b/chromeos/services/assistant/assistant_manager_service_impl.h
@@ -63,7 +63,6 @@ class AssistantDeviceSettingsDelegate; class AssistantManagerServiceDelegate; class AssistantProxy; -class AudioInputHost; class CrosPlatformApi; class ServiceContext; class ServiceControllerProxy; @@ -221,7 +220,7 @@ assistant_client::AssistantManager* assistant_manager(); assistant_client::AssistantManagerInternal* assistant_manager_internal(); - void SetMicState(bool mic_open); + CrosPlatformApi* platform_api() { return platform_api_.get(); } // assistant_client::MediaManager::Listener overrides: void OnPlaybackStateChange( @@ -314,7 +313,6 @@ std::unique_ptr<AssistantSettingsImpl> assistant_settings_; std::unique_ptr<AssistantProxy> assistant_proxy_; - std::unique_ptr<AudioInputHost> audio_input_host_; base::ObserverList<AssistantInteractionSubscriber> interaction_subscribers_; mojo::Remote<media_session::mojom::MediaController> media_controller_;
diff --git a/chromeos/services/assistant/assistant_settings_impl.cc b/chromeos/services/assistant/assistant_settings_impl.cc index f064b87..e68eb8f1 100644 --- a/chromeos/services/assistant/assistant_settings_impl.cc +++ b/chromeos/services/assistant/assistant_settings_impl.cc
@@ -13,6 +13,7 @@ #include "chromeos/dbus/util/version_loader.h" #include "chromeos/services/assistant/assistant_manager_service_impl.h" #include "chromeos/services/assistant/public/cpp/features.h" +#include "chromeos/services/assistant/public/cpp/migration/cros_platform_api.h" #include "chromeos/services/assistant/public/proto/assistant_device_settings_ui.pb.h" #include "chromeos/services/assistant/public/proto/settings_ui.pb.h" #include "chromeos/services/assistant/service_context.h" @@ -123,7 +124,7 @@ DCHECK(main_task_runner()->RunsTasksInCurrentSequence()); DCHECK(!speaker_id_enrollment_client_); - assistant_manager_service_->SetMicState(true); + assistant_manager_service_->platform_api()->SetMicState(true); if (!assistant_manager_service_->assistant_manager_internal()) return; @@ -152,7 +153,7 @@ DCHECK(HasStarted(assistant_manager_service_)); DCHECK(main_task_runner()->RunsTasksInCurrentSequence()); - assistant_manager_service_->SetMicState(false); + assistant_manager_service_->platform_api()->SetMicState(false); if (!assistant_manager_service_->assistant_manager_internal()) return;
diff --git a/chromeos/services/assistant/platform/audio_devices.cc b/chromeos/services/assistant/platform/audio_devices.cc deleted file mode 100644 index 0fa34fd..0000000 --- a/chromeos/services/assistant/platform/audio_devices.cc +++ /dev/null
@@ -1,291 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/services/assistant/platform/audio_devices.h" - -#include "base/metrics/histogram_functions.h" -#include "base/optional.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_split.h" -#include "base/strings/string_util.h" -#include "base/system/sys_info.h" -#include "chromeos/audio/audio_device.h" -#include "chromeos/audio/cras_audio_handler.h" -#include "chromeos/services/assistant/public/cpp/features.h" - -namespace chromeos { -namespace assistant { - -namespace { - -constexpr const char kDefaultLocale[] = "en_us"; - -// Hotword model is expected to have <language>_<region> format with lower -// case, while the locale in pref is stored as <language>-<region> with region -// code in capital letters. So we need to convert the pref locale to the -// correct format. -// Examples: -// "fr" -> "fr_fr" -// "nl-BE" -> "nl_be" -base::Optional<std::string> ToHotwordModel(std::string pref_locale) { - std::vector<std::string> code_strings = base::SplitString( - pref_locale, "-", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); - - if (code_strings.size() == 0) { - // Note: I am not sure this happens during real operations, but it - // definitely happens during the ChromeOS performance tests. - return base::nullopt; - } - - DCHECK_LT(code_strings.size(), 3u); - - // For locales with language code "en", use "en_all" hotword model. - if (code_strings[0] == "en") - return "en_all"; - - // If the language code and country code happen to be the same, e.g. - // France (FR) and French (fr), the locale will be stored as "fr" instead - // of "fr-FR" in the profile on Chrome OS. - if (code_strings.size() == 1) - return code_strings[0] + "_" + code_strings[0]; - - return code_strings[0] + "_" + base::ToLowerASCII(code_strings[1]); -} - -const chromeos::AudioDevice* GetHighestPriorityDevice( - const chromeos::AudioDevice* left, - const chromeos::AudioDevice* right) { - if (!left) - return right; - if (!right) - return left; - return left->priority < right->priority ? right : left; -} - -base::Optional<uint64_t> IdToOptional(const AudioDevice* device) { - if (!device) - return base::nullopt; - return device->id; -} - -base::Optional<uint64_t> GetHotwordDeviceId( - const chromeos::AudioDeviceList& devices) { - const chromeos::AudioDevice* result = nullptr; - - for (const chromeos::AudioDevice& device : devices) { - if (!device.is_input) - continue; - - switch (device.type) { - case chromeos::AUDIO_TYPE_HOTWORD: - result = GetHighestPriorityDevice(result, &device); - break; - default: - // ignore other devices - break; - } - } - - return IdToOptional(result); -} - -base::Optional<uint64_t> GetPreferredDeviceId( - const chromeos::AudioDeviceList& devices) { - const chromeos::AudioDevice* result = nullptr; - - for (const chromeos::AudioDevice& device : devices) { - if (!device.is_input) - continue; - - switch (device.type) { - case chromeos::AUDIO_TYPE_USB: - case chromeos::AUDIO_TYPE_HEADPHONE: - case chromeos::AUDIO_TYPE_INTERNAL_MIC: - case chromeos::AUDIO_TYPE_FRONT_MIC: - result = GetHighestPriorityDevice(result, &device); - break; - default: - // ignore other devices - break; - } - } - - return IdToOptional(result); -} - -base::Optional<std::string> ToString(base::Optional<uint64_t> int_value) { - if (!int_value) - return base::nullopt; - return base::NumberToString(int_value.value()); -} - -} // namespace - -// Observer that will report all changes to the audio devices. -// It will automatically be triggered when it's created, -// and will unsubscribe from |CrasAudioHandler| in its destructor. -class AudioDevices::ScopedCrasAudioHandlerObserver - : private CrasAudioHandler::AudioObserver { - public: - ScopedCrasAudioHandlerObserver(CrasAudioHandler* cras_audio_handler, - AudioDevices* parent) - : parent_(parent), cras_audio_handler_(cras_audio_handler) { - scoped_observer_.Observe(cras_audio_handler); - FetchAudioNodes(); - } - ScopedCrasAudioHandlerObserver(const ScopedCrasAudioHandlerObserver&) = - delete; - ScopedCrasAudioHandlerObserver& operator=( - const ScopedCrasAudioHandlerObserver&) = delete; - ~ScopedCrasAudioHandlerObserver() override = default; - - private: - // CrasAudioHandler::AudioObserver implementation: - void OnAudioNodesChanged() override { FetchAudioNodes(); } - - void FetchAudioNodes() { - if (!base::SysInfo::IsRunningOnChromeOS()) - return; - - chromeos::AudioDeviceList audio_devices; - cras_audio_handler_->GetAudioDevices(&audio_devices); - parent_->SetAudioDevices(audio_devices); - } - - AudioDevices* const parent_; - // Owned by |AssistantManagerServiceImpl|. - CrasAudioHandler* const cras_audio_handler_; - base::ScopedObservation<CrasAudioHandler, - CrasAudioHandler::AudioObserver, - &CrasAudioHandler::AddAudioObserver, - &CrasAudioHandler::RemoveAudioObserver> - scoped_observer_{this}; -}; - -// Sends the new hotword model to |cras_audio_handler|. If that fails this class -// will attempt to set the hotword model to |kDefaultLocale|. -class AudioDevices::HotwordModelUpdater { - public: - HotwordModelUpdater(CrasAudioHandler* cras_audio_handler, - uint64_t hotword_device, - const std::string& locale) - : cras_audio_handler_(cras_audio_handler), - hotword_device_(hotword_device), - locale_(locale) { - SendUpdate(); - } - - HotwordModelUpdater(const HotwordModelUpdater&) = delete; - HotwordModelUpdater& operator=(const HotwordModelUpdater&) = delete; - ~HotwordModelUpdater() = default; - - private: - void SendUpdate() { - std::string hotword_model = - ToHotwordModel(locale_).value_or(kDefaultLocale); - - cras_audio_handler_->SetHotwordModel( - hotword_device_, hotword_model, - base::BindOnce(&HotwordModelUpdater::SetDspHotwordLocaleCallback, - weak_factory_.GetWeakPtr(), hotword_model)); - } - - void SetDspHotwordLocaleCallback(std::string pref_locale, bool success) { - base::UmaHistogramBoolean("Assistant.SetDspHotwordLocale", success); - if (success) { - VLOG(2) << "Successfully changed audio hotword model"; - return; - } - - LOG(ERROR) << "Set " << pref_locale - << " hotword model failed, fallback to default locale."; - // Reset the locale to the default value if we failed to sync it to the - // locale stored in user's pref. - cras_audio_handler_->SetHotwordModel( - hotword_device_, /* hotword_model */ kDefaultLocale, - base::BindOnce([](bool success) { - if (!success) - LOG(ERROR) << "Reset to default hotword model failed."; - })); - } - - CrasAudioHandler* const cras_audio_handler_; - uint64_t hotword_device_; - std::string locale_; - - base::WeakPtrFactory<HotwordModelUpdater> weak_factory_{this}; -}; - -AudioDevices::AudioDevices(CrasAudioHandler* cras_audio_handler, - const std::string& locale) - : scoped_cras_audio_handler_observer_( - std::make_unique<ScopedCrasAudioHandlerObserver>(cras_audio_handler, - this)), - cras_audio_handler_(cras_audio_handler), - locale_(locale) {} - -AudioDevices::~AudioDevices() = default; - -void AudioDevices::AddAndFireObserver(Observer* observer) { - DCHECK(observer); - observers_.AddObserver(observer); - - observer->SetHotwordDeviceId(ToString(hotword_device_id_)); - observer->SetDeviceId(ToString(device_id_)); -} - -void AudioDevices::RemoveObserver(Observer* observer) { - observers_.RemoveObserver(observer); -} - -void AudioDevices::SetLocale(const std::string& locale) { - locale_ = locale; - UpdateHotwordModel(); -} - -void AudioDevices::SetAudioDevicesForTest( - const chromeos::AudioDeviceList& audio_devices) { - SetAudioDevices(audio_devices); -} - -void AudioDevices::SetAudioDevices(const chromeos::AudioDeviceList& devices) { - UpdateHotwordDeviceId(devices); - UpdateDeviceId(devices); - UpdateHotwordModel(); -} - -void AudioDevices::UpdateHotwordDeviceId( - const chromeos::AudioDeviceList& devices) { - hotword_device_id_ = GetHotwordDeviceId(devices); - - VLOG(2) << "Changed audio hotword input device to " - << ToString(hotword_device_id_).value_or("<none>"); - - for (auto& observer : observers_) - observer.SetHotwordDeviceId(ToString(hotword_device_id_)); -} - -void AudioDevices::UpdateDeviceId(const chromeos::AudioDeviceList& devices) { - device_id_ = GetPreferredDeviceId(devices); - - VLOG(2) << "Changed audio input device to " - << ToString(device_id_).value_or("<none>"); - - for (auto& observer : observers_) - observer.SetDeviceId(ToString(device_id_)); -} - -void AudioDevices::UpdateHotwordModel() { - if (!hotword_device_id_) - return; - - if (!features::IsDspHotwordEnabled()) - return; - - hotword_model_updater_ = std::make_unique<HotwordModelUpdater>( - cras_audio_handler_, hotword_device_id_.value(), locale_); -} - -} // namespace assistant -} // namespace chromeos
diff --git a/chromeos/services/assistant/platform/audio_devices.h b/chromeos/services/assistant/platform/audio_devices.h deleted file mode 100644 index f0d70d5..0000000 --- a/chromeos/services/assistant/platform/audio_devices.h +++ /dev/null
@@ -1,93 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_SERVICES_ASSISTANT_PLATFORM_AUDIO_DEVICES_H_ -#define CHROMEOS_SERVICES_ASSISTANT_PLATFORM_AUDIO_DEVICES_H_ - -#include <cstdint> -#include "base/component_export.h" -#include "base/observer_list.h" -#include "base/optional.h" -#include "base/scoped_observation.h" -#include "chromeos/audio/audio_device.h" - -namespace chromeos { -class CrasAudioHandler; -} // namespace chromeos - -namespace chromeos { -namespace assistant { - -// This class will monitor the available audio devices (through -// |CrasAudioHandler|), and select the devices to use for audio input (both -// regular input and hotword detection). -// When the selected devices change, this class will: -// - Inform the observers. -// - Find the hotword model to use, and send it to -// CrasAudioHandler::SetHotwordModel(). -class COMPONENT_EXPORT(ASSISTANT_SERVICE) AudioDevices { - public: - class Observer : public base::CheckedObserver { - public: - ~Observer() override = default; - - // Set the input device to use for audio capture. - virtual void SetDeviceId(const base::Optional<std::string>& device_id) = 0; - // Set the input device to use for hardware based hotword detection. - virtual void SetHotwordDeviceId( - const base::Optional<std::string>& device_id) = 0; - }; - - AudioDevices(CrasAudioHandler* cras_audio_handler, const std::string& locale); - AudioDevices(const AudioDevices&) = delete; - AudioDevices& operator=(const AudioDevices&) = delete; - ~AudioDevices(); - - void AddAndFireObserver(Observer*); - void RemoveObserver(Observer*); - - void SetLocale(const std::string& locale); - - // Used during unittests to simulate an update to the list of available audio - // devices. - void SetAudioDevicesForTest(const chromeos::AudioDeviceList& audio_devices); - - using ScopedObservation = - base::ScopedObservation<AudioDevices, - Observer, - &AudioDevices::AddAndFireObserver, - &AudioDevices::RemoveObserver>; - - private: - class ScopedCrasAudioHandlerObserver; - class HotwordModelUpdater; - - void SetAudioDevices(const chromeos::AudioDeviceList& audio_devices); - void UpdateHotwordDeviceId(const chromeos::AudioDeviceList& devices); - void UpdateDeviceId(const chromeos::AudioDeviceList& devices); - void UpdateHotwordModel(); - - // Observes changes to the available audio devices, and sends the list of - // devices to SetAudioDevices(). - std::unique_ptr<ScopedCrasAudioHandlerObserver> - scoped_cras_audio_handler_observer_; - - // Handles the asynchronous nature of sending a new hotword model to - // |cras_audio_handler_|. - std::unique_ptr<HotwordModelUpdater> hotword_model_updater_; - - base::ObserverList<Observer> observers_; - - // Owned by |AssistantManagerServiceImpl|. - CrasAudioHandler* const cras_audio_handler_; - - std::string locale_; - base::Optional<uint64_t> hotword_device_id_; - base::Optional<uint64_t> device_id_; -}; - -} // namespace assistant -} // namespace chromeos - -#endif // CHROMEOS_SERVICES_ASSISTANT_PLATFORM_AUDIO_DEVICES_H_
diff --git a/chromeos/services/assistant/platform/audio_devices_unittest.cc b/chromeos/services/assistant/platform/audio_devices_unittest.cc deleted file mode 100644 index dd1cb9f..0000000 --- a/chromeos/services/assistant/platform/audio_devices_unittest.cc +++ /dev/null
@@ -1,373 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/services/assistant/platform/audio_devices.h" - -#include "base/run_loop.h" -#include "base/test/scoped_feature_list.h" -#include "base/test/task_environment.h" -#include "chromeos/audio/audio_device.h" -#include "chromeos/audio/cras_audio_handler.h" -#include "chromeos/dbus/audio/fake_cras_audio_client.h" -#include "chromeos/services/assistant/public/cpp/features.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace chromeos { -namespace assistant { - -namespace { - -using ::testing::_; - -constexpr const char kDefaultLocale[] = "en_us"; - -class FakeAudioDevicesObserver : public AudioDevices::Observer { - public: - FakeAudioDevicesObserver() = default; - FakeAudioDevicesObserver(const FakeAudioDevicesObserver&) = delete; - FakeAudioDevicesObserver& operator=(const FakeAudioDevicesObserver&) = delete; - ~FakeAudioDevicesObserver() override = default; - - // AudioDevices::Observer implementation - void SetDeviceId(const base::Optional<std::string>& device_id) override { - preferred_device_id_ = device_id; - } - void SetHotwordDeviceId( - const base::Optional<std::string>& device_id) override { - hotword_device_id_ = device_id; - } - - std::string preferred_device_id() { - return preferred_device_id_.value_or("<none>"); - } - - std::string hotword_device_id() { - return hotword_device_id_.value_or("<none>"); - } - - private: - base::Optional<std::string> preferred_device_id_; - base::Optional<std::string> hotword_device_id_; -}; - -class DeviceBuilder { - public: - explicit DeviceBuilder(AudioDeviceType type) { - result_.type = type; - result_.is_input = true; - } - DeviceBuilder(const DeviceBuilder&) = delete; - DeviceBuilder& operator=(const DeviceBuilder&) = delete; - ~DeviceBuilder() = default; - - DeviceBuilder& WithId(int id) { - result_.id = id; - return *this; - } - - DeviceBuilder& WithPriority(int priority) { - result_.priority = priority; - return *this; - } - - DeviceBuilder& WithIsInput(bool is_input) { - result_.is_input = is_input; - return *this; - } - - AudioDevice Build() const { return result_; } - - private: - AudioDevice result_; -}; - -// Mock for |CrosAudioClient|. This inherits from |FakeCrasAudioClient| so we -// only have to mock the methods we're interested in. -// It will automatically be installed as the global singleton in its -// constructor, and removed in the destructor. -class ScopedCrasAudioClientMock : public FakeCrasAudioClient { - public: - ScopedCrasAudioClientMock() = default; - ScopedCrasAudioClientMock(ScopedCrasAudioClientMock&) = delete; - ScopedCrasAudioClientMock& operator=(ScopedCrasAudioClientMock&) = delete; - ~ScopedCrasAudioClientMock() override = default; - - MOCK_METHOD(void, - SetHotwordModel, - (uint64_t node_id, - const std::string& hotword_model, - VoidDBusMethodCallback callback)); -}; - -class ScopedCrasAudioHandler { - public: - ScopedCrasAudioHandler() { CrasAudioHandler::InitializeForTesting(); } - ScopedCrasAudioHandler(const ScopedCrasAudioHandler&) = delete; - ScopedCrasAudioHandler& operator=(const ScopedCrasAudioHandler&) = delete; - ~ScopedCrasAudioHandler() { CrasAudioHandler::Shutdown(); } - - CrasAudioHandler* Get() { return CrasAudioHandler::Get(); } -}; - -} // namespace - -class AssistantAudioDevicesTest : public testing::Test { - public: - AssistantAudioDevicesTest() - : audio_devices_(cras_audio_handler_.Get(), "pref-locale") { - // Enable DSP feature flag. - scoped_feature_list_.InitAndEnableFeature(features::kEnableDspHotword); - } - - AssistantAudioDevicesTest(const AssistantAudioDevicesTest&) = delete; - AssistantAudioDevicesTest& operator=(const AssistantAudioDevicesTest&) = - delete; - ~AssistantAudioDevicesTest() override = default; - - AudioDevices& audio_devices() { return audio_devices_; } - - ScopedCrasAudioClientMock& cras_audio_client_mock() { - return cras_audio_client_mock_; - } - - void UpdateDeviceList(const AudioDeviceList& devices) { - audio_devices().SetAudioDevicesForTest(devices); - } - - private: - base::test::TaskEnvironment task_environment_; - base::test::ScopedFeatureList scoped_feature_list_; - testing::NiceMock<ScopedCrasAudioClientMock> cras_audio_client_mock_; - ScopedCrasAudioHandler cras_audio_handler_; - AudioDevices audio_devices_; -}; - -TEST_F(AssistantAudioDevicesTest, ShouldSendHotwordDeviceToObserver) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - UpdateDeviceList({DeviceBuilder(AUDIO_TYPE_HOTWORD).WithId(111).Build()}); - - EXPECT_EQ("111", observer.hotword_device_id()); - EXPECT_EQ("<none>", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldSendUsbDeviceToObserver) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - UpdateDeviceList({DeviceBuilder(AUDIO_TYPE_USB).WithId(222).Build()}); - - EXPECT_EQ("<none>", observer.hotword_device_id()); - EXPECT_EQ("222", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldSendHeadphonesDeviceToObserver) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - UpdateDeviceList({DeviceBuilder(AUDIO_TYPE_HEADPHONE).WithId(333).Build()}); - - EXPECT_EQ("<none>", observer.hotword_device_id()); - EXPECT_EQ("333", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldSendInternalMicDeviceToObserver) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - UpdateDeviceList( - {DeviceBuilder(AUDIO_TYPE_INTERNAL_MIC).WithId(444).Build()}); - - EXPECT_EQ("<none>", observer.hotword_device_id()); - EXPECT_EQ("444", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldSendFrontMicDeviceToObserver) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - UpdateDeviceList({DeviceBuilder(AUDIO_TYPE_FRONT_MIC).WithId(555).Build()}); - - EXPECT_EQ("<none>", observer.hotword_device_id()); - EXPECT_EQ("555", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldUseHighestPriorityHotwordDevice) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - UpdateDeviceList({ - DeviceBuilder(AUDIO_TYPE_HOTWORD).WithId(111).WithPriority(1).Build(), - DeviceBuilder(AUDIO_TYPE_HOTWORD).WithId(555).WithPriority(5).Build(), - DeviceBuilder(AUDIO_TYPE_HOTWORD).WithId(222).WithPriority(2).Build(), - }); - - EXPECT_EQ("555", observer.hotword_device_id()); - EXPECT_EQ("<none>", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldIgnoreNonInputHotwordDevices) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - UpdateDeviceList({ - DeviceBuilder(AUDIO_TYPE_HOTWORD).WithId(111).WithIsInput(false).Build(), - DeviceBuilder(AUDIO_TYPE_HOTWORD).WithId(222).WithIsInput(true).Build(), - DeviceBuilder(AUDIO_TYPE_HOTWORD).WithId(333).WithIsInput(false).Build(), - }); - - EXPECT_EQ("222", observer.hotword_device_id()); - EXPECT_EQ("<none>", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldUseHighestPriorityDevice) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - UpdateDeviceList({ - DeviceBuilder(AUDIO_TYPE_USB).WithId(111).WithPriority(1).Build(), - DeviceBuilder(AUDIO_TYPE_USB).WithId(555).WithPriority(5).Build(), - DeviceBuilder(AUDIO_TYPE_USB).WithId(222).WithPriority(2).Build(), - }); - - EXPECT_EQ("<none>", observer.hotword_device_id()); - EXPECT_EQ("555", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldIgnoreNonInputDevices) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - UpdateDeviceList({ - DeviceBuilder(AUDIO_TYPE_USB).WithId(111).WithIsInput(false).Build(), - DeviceBuilder(AUDIO_TYPE_USB).WithId(222).WithIsInput(true).Build(), - DeviceBuilder(AUDIO_TYPE_USB).WithId(333).WithIsInput(false).Build(), - }); - - EXPECT_EQ("<none>", observer.hotword_device_id()); - EXPECT_EQ("222", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldIgnoreUnsupportedDeviceTypes) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - UpdateDeviceList({ - DeviceBuilder(AUDIO_TYPE_BLUETOOTH).WithId(2).Build(), - DeviceBuilder(AUDIO_TYPE_BLUETOOTH_NB_MIC).WithId(3).Build(), - DeviceBuilder(AUDIO_TYPE_HDMI).WithId(4).Build(), - DeviceBuilder(AUDIO_TYPE_INTERNAL_SPEAKER).WithId(5).Build(), - DeviceBuilder(AUDIO_TYPE_REAR_MIC).WithId(6).Build(), - DeviceBuilder(AUDIO_TYPE_KEYBOARD_MIC).WithId(7).Build(), - DeviceBuilder(AUDIO_TYPE_LINEOUT).WithId(8).Build(), - DeviceBuilder(AUDIO_TYPE_POST_MIX_LOOPBACK).WithId(9).Build(), - DeviceBuilder(AUDIO_TYPE_POST_DSP_LOOPBACK).WithId(10).Build(), - DeviceBuilder(AUDIO_TYPE_ALSA_LOOPBACK).WithId(11).Build(), - DeviceBuilder(AUDIO_TYPE_OTHER).WithId(12).Build(), - }); - - EXPECT_EQ("<none>", observer.hotword_device_id()); - EXPECT_EQ("<none>", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldFireObserverWhenAdded) { - UpdateDeviceList({ - DeviceBuilder(AUDIO_TYPE_HOTWORD).WithId(111).Build(), - DeviceBuilder(AUDIO_TYPE_USB).WithId(222).Build(), - }); - - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - EXPECT_EQ("111", observer.hotword_device_id()); - EXPECT_EQ("222", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldNotFireObserverAfterItsRemoved) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - audio_devices().RemoveObserver(&observer); - - UpdateDeviceList({ - DeviceBuilder(AUDIO_TYPE_HOTWORD).WithId(111).Build(), - DeviceBuilder(AUDIO_TYPE_USB).WithId(222).Build(), - }); - - EXPECT_EQ("<none>", observer.hotword_device_id()); - EXPECT_EQ("<none>", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, - ShouldUpdateHotwordModelWhenHotwordDeviceIsAdded) { - EXPECT_CALL(cras_audio_client_mock(), SetHotwordModel); - - UpdateDeviceList({DeviceBuilder(AUDIO_TYPE_HOTWORD).Build()}); -} - -TEST_F(AssistantAudioDevicesTest, ShouldFormatLocaleToHotwordModel) { - UpdateDeviceList({DeviceBuilder(AUDIO_TYPE_HOTWORD).WithId(111).Build()}); - - // Normal case - EXPECT_CALL(cras_audio_client_mock(), SetHotwordModel(111, "nl_be", _)); - audio_devices().SetLocale("nl-BE"); - base::RunLoop().RunUntilIdle(); - - // Handle the case where country code and language code are the same - EXPECT_CALL(cras_audio_client_mock(), SetHotwordModel(111, "fr_fr", _)); - audio_devices().SetLocale("fr"); - base::RunLoop().RunUntilIdle(); - - // use "en_all" for all english locales - EXPECT_CALL(cras_audio_client_mock(), SetHotwordModel(111, "en_all", _)); - audio_devices().SetLocale("en-US"); - base::RunLoop().RunUntilIdle(); -} - -TEST_F(AssistantAudioDevicesTest, ShouldUseDefaultLocaleIfUserPrefIsRejected) { - UpdateDeviceList({DeviceBuilder(AUDIO_TYPE_HOTWORD).WithId(222).Build()}); - - EXPECT_CALL(cras_audio_client_mock(), - SetHotwordModel(_, "rejected_locale", _)) - .WillOnce([](uint64_t node_id, const std::string&, - VoidDBusMethodCallback callback) { - // Report failure to change the locale - std::move(callback).Run(/*success=*/false); - }); - - EXPECT_CALL(cras_audio_client_mock(), - SetHotwordModel(222, kDefaultLocale, _)); - - audio_devices().SetLocale("rejected-LOCALE"); -} - -TEST_F(AssistantAudioDevicesTest, ShouldUseDefaultLocaleIfUserPrefIsEmpty) { - UpdateDeviceList({DeviceBuilder(AUDIO_TYPE_HOTWORD).Build()}); - - EXPECT_CALL(cras_audio_client_mock(), SetHotwordModel(_, kDefaultLocale, _)); - - audio_devices().SetLocale(""); -} - -TEST_F(AssistantAudioDevicesTest, ShouldDoNothingIfUserPrefIsAccepted) { - UpdateDeviceList({DeviceBuilder(AUDIO_TYPE_HOTWORD).Build()}); - - EXPECT_CALL(cras_audio_client_mock(), - SetHotwordModel(_, "accepted_locale", _)) - .WillOnce([](uint64_t node_id, const std::string&, - VoidDBusMethodCallback callback) { - // Accept the change to the locale. - std::move(callback).Run(/*success=*/true); - }); - - // Do not expect a second call if change of locale is accepted - EXPECT_CALL(cras_audio_client_mock(), SetHotwordModel(_, kDefaultLocale, _)) - .Times(0); - - audio_devices().SetLocale("accepted-LOCALE"); -} - -} // namespace assistant -} // namespace chromeos
diff --git a/chromeos/services/assistant/platform/audio_input_host.cc b/chromeos/services/assistant/platform/audio_input_host.cc new file mode 100644 index 0000000..cb67acd --- /dev/null +++ b/chromeos/services/assistant/platform/audio_input_host.cc
@@ -0,0 +1,174 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/services/assistant/platform/audio_input_host.h" + +#include "base/check.h" +#include "base/metrics/histogram_functions.h" +#include "base/optional.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "chromeos/audio/cras_audio_handler.h" +#include "chromeos/services/assistant/platform/audio_input_impl.h" +#include "chromeos/services/assistant/public/cpp/features.h" + +namespace chromeos { +namespace assistant { + +namespace { + +constexpr const char kDefaultLocale[] = "en_us"; + +AudioInputImpl::LidState ConvertLidState( + chromeos::PowerManagerClient::LidState state) { + switch (state) { + case chromeos::PowerManagerClient::LidState::CLOSED: + return AudioInputImpl::LidState::kClosed; + case chromeos::PowerManagerClient::LidState::OPEN: + return AudioInputImpl::LidState::kOpen; + case chromeos::PowerManagerClient::LidState::NOT_PRESENT: + // If there is no lid, it can't be closed. + return AudioInputImpl::LidState::kOpen; + } +} + +// Hotword model is expected to have <language>_<region> format with lower +// case, while the locale in pref is stored as <language>-<region> with region +// code in capital letters. So we need to convert the pref locale to the +// correct format. +// Examples: +// "fr" -> "fr_fr" +// "nl-BE" -> "nl_be" +base::Optional<std::string> ToHotwordModel(std::string pref_locale) { + std::vector<std::string> code_strings = base::SplitString( + pref_locale, "-", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + + if (code_strings.size() == 0) { + // Note: I am not sure this happens during real operations, but it + // definitely happens during the ChromeOS performance tests. + return base::nullopt; + } + + DCHECK_LT(code_strings.size(), 3u); + + // For locales with language code "en", use "en_all" hotword model. + if (code_strings[0] == "en") + return "en_all"; + + // If the language code and country code happen to be the same, e.g. + // France (FR) and French (fr), the locale will be stored as "fr" instead + // of "fr-FR" in the profile on Chrome OS. + if (code_strings.size() == 1) + return code_strings[0] + "_" + code_strings[0]; + + return code_strings[0] + "_" + base::ToLowerASCII(code_strings[1]); +} + +} // namespace + +chromeos::assistant::AudioInputHost::AudioInputHost( + AudioInputImpl* audio_input, + CrasAudioHandler* cras_audio_handler, + chromeos::PowerManagerClient* power_manager_client) + : audio_input_(audio_input), + cras_audio_handler_(cras_audio_handler), + power_manager_client_(power_manager_client), + power_manager_client_observer_(this) { + DCHECK(audio_input_); + DCHECK(cras_audio_handler_); + DCHECK(power_manager_client_); + + power_manager_client_observer_.Observe(power_manager_client); + power_manager_client->GetSwitchStates(base::BindOnce( + &AudioInputHost::OnInitialLidStateReceived, weak_factory_.GetWeakPtr())); +} + +AudioInputHost::~AudioInputHost() = default; + +void AudioInputHost::SetMicState(bool mic_open) { + audio_input_->SetMicState(mic_open); +} + +void AudioInputHost::SetDeviceId(const std::string& device_id) { + audio_input_->SetDeviceId(device_id); +} + +void AudioInputHost::OnConversationTurnStarted() { + audio_input_->OnConversationTurnStarted(); + // Inform power manager of a wake notification when Libassistant + // recognized hotword and started a conversation. We intentionally + // avoid using |NotifyUserActivity| because it is not suitable for + // this case according to the Platform team. + power_manager_client_->NotifyWakeNotification(); +} + +void AudioInputHost::OnConversationTurnFinished() { + audio_input_->OnConversationTurnFinished(); +} + +void AudioInputHost::OnHotwordEnabled(bool enable) { + audio_input_->OnHotwordEnabled(enable); +} + +void AudioInputHost::SetHotwordDeviceId(const std::string& device_id) { + hotword_device_id_ = device_id; + audio_input_->SetHotwordDeviceId(device_id); +} + +void AudioInputHost::SetDspHotwordLocale(std::string pref_locale) { + if (!features::IsDspHotwordEnabled()) + return; + + std::string hotword_model = + ToHotwordModel(pref_locale).value_or(kDefaultLocale); + + cras_audio_handler_->SetHotwordModel( + GetDspNodeId(), hotword_model, + base::BindOnce(&AudioInputHost::SetDspHotwordLocaleCallback, + weak_factory_.GetWeakPtr(), hotword_model)); +} + +void AudioInputHost::SetDspHotwordLocaleCallback(std::string pref_locale, + bool success) { + base::UmaHistogramBoolean("Assistant.SetDspHotwordLocale", success); + if (success) + return; + + LOG(ERROR) << "Set " << pref_locale + << " hotword model failed, fallback to default locale."; + // Reset the locale to the default value if we failed to sync it to the locale + // stored in user's pref. + cras_audio_handler_->SetHotwordModel( + GetDspNodeId(), /* hotword_model */ kDefaultLocale, + base::BindOnce([](bool success) { + if (!success) + LOG(ERROR) << "Reset to default hotword model failed."; + })); +} + +uint64_t AudioInputHost::GetDspNodeId() const { + DCHECK(!hotword_device_id_.empty()); + uint64_t result; + bool success = base::StringToUint64(hotword_device_id_, &result); + DCHECK(success) << "Invalid hotword device id '" << hotword_device_id_ << "'"; + return result; +} + +void AudioInputHost::LidEventReceived( + chromeos::PowerManagerClient::LidState state, + base::TimeTicks timestamp) { + // Lid switch event still gets fired during system suspend, which enables + // us to stop DSP recording correctly when user closes lid after the device + // goes to sleep. + audio_input_->OnLidStateChanged(ConvertLidState(state)); +} + +void AudioInputHost::OnInitialLidStateReceived( + base::Optional<chromeos::PowerManagerClient::SwitchStates> switch_states) { + if (switch_states.has_value()) + audio_input_->OnLidStateChanged(ConvertLidState(switch_states->lid_state)); +} + +} // namespace assistant +} // namespace chromeos
diff --git a/chromeos/services/assistant/platform/audio_input_host.h b/chromeos/services/assistant/platform/audio_input_host.h new file mode 100644 index 0000000..2c0c710 --- /dev/null +++ b/chromeos/services/assistant/platform/audio_input_host.h
@@ -0,0 +1,86 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_SERVICES_ASSISTANT_PLATFORM_AUDIO_INPUT_HOST_H_ +#define CHROMEOS_SERVICES_ASSISTANT_PLATFORM_AUDIO_INPUT_HOST_H_ + +#include <string> + +#include "base/component_export.h" +#include "base/memory/weak_ptr.h" +#include "base/scoped_observation.h" +#include "chromeos/dbus/power/power_manager_client.h" + +namespace chromeos { +class CrasAudioHandler; +} // namespace chromeos + +namespace chromeos { +namespace assistant { + +class AudioInputImpl; + +// Class that provides the bridge between the ChromeOS UI thread and the +// Libassistant audio input class. +// The goal is that |AudioInputImpl| no longer depends on any external events. +// This will allow us to move it to the Libassistant mojom service (at which +// point this class will talk to the Libassistant mojom service). +class COMPONENT_EXPORT(ASSISTANT_SERVICE) AudioInputHost + : public chromeos::PowerManagerClient::Observer { + public: + AudioInputHost(AudioInputImpl* audio_input, + CrasAudioHandler* cras_audio_handler, + chromeos::PowerManagerClient* power_manager_client); + AudioInputHost(AudioInputHost&) = delete; + AudioInputHost& operator=(AudioInputHost&) = delete; + ~AudioInputHost() override; + + // Called when the mic state associated with the interaction is changed. + void SetMicState(bool mic_open); + + // Setting the input device to use for audio capture. + void SetDeviceId(const std::string& device_id); + + // Called when hotword enabled status changed. + void OnHotwordEnabled(bool enable); + + // Setting the hotword input device with hardware based hotword detection. + void SetHotwordDeviceId(const std::string& device_id); + + // Setting the hotword locale for the input device with DSP support. + void SetDspHotwordLocale(std::string pref_locale); + + void OnConversationTurnStarted(); + void OnConversationTurnFinished(); + + private: + void SetDspHotwordLocaleCallback(std::string pref_locale, bool success); + + uint64_t GetDspNodeId() const; + + // chromeos::PowerManagerClient::Observer overrides: + void LidEventReceived(chromeos::PowerManagerClient::LidState state, + base::TimeTicks timestamp) override; + + void OnInitialLidStateReceived( + base::Optional<chromeos::PowerManagerClient::SwitchStates> switch_states); + + // Owned by |PlatformApiImpl| which also owns |this|. + AudioInputImpl* const audio_input_; + CrasAudioHandler* const cras_audio_handler_; + chromeos::PowerManagerClient* const power_manager_client_; + base::ScopedObservation<chromeos::PowerManagerClient, + chromeos::PowerManagerClient::Observer> + power_manager_client_observer_; + + // Hotword input device used for hardware based hotword detection. + std::string hotword_device_id_; + + base::WeakPtrFactory<AudioInputHost> weak_factory_{this}; +}; + +} // namespace assistant +} // namespace chromeos + +#endif // CHROMEOS_SERVICES_ASSISTANT_PLATFORM_AUDIO_INPUT_HOST_H_
diff --git a/chromeos/services/assistant/platform/audio_input_host_impl.cc b/chromeos/services/assistant/platform/audio_input_host_impl.cc deleted file mode 100644 index 4f6dcd6e..0000000 --- a/chromeos/services/assistant/platform/audio_input_host_impl.cc +++ /dev/null
@@ -1,102 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/services/assistant/platform/audio_input_host_impl.h" - -#include "base/check.h" -#include "base/optional.h" -#include "chromeos/services/assistant/platform/audio_devices.h" -#include "chromeos/services/assistant/platform/audio_input_impl.h" -#include "chromeos/services/assistant/public/cpp/features.h" - -namespace chromeos { -namespace assistant { - -namespace { - -AudioInputImpl::LidState ConvertLidState( - chromeos::PowerManagerClient::LidState state) { - switch (state) { - case chromeos::PowerManagerClient::LidState::CLOSED: - return AudioInputImpl::LidState::kClosed; - case chromeos::PowerManagerClient::LidState::OPEN: - return AudioInputImpl::LidState::kOpen; - case chromeos::PowerManagerClient::LidState::NOT_PRESENT: - // If there is no lid, it can't be closed. - return AudioInputImpl::LidState::kOpen; - } -} - -} // namespace - -chromeos::assistant::AudioInputHostImpl::AudioInputHostImpl( - CrasAudioHandler* cras_audio_handler, - chromeos::PowerManagerClient* power_manager_client, - const std::string& locale) - : power_manager_client_(power_manager_client), - power_manager_client_observer_(this), - audio_devices_(cras_audio_handler, locale) { - DCHECK(power_manager_client_); -} - -AudioInputHostImpl::~AudioInputHostImpl() = default; - -void AudioInputHostImpl::Initialize(AudioInputImpl* audio_input) { - DCHECK(audio_input); - audio_input_ = audio_input; - audio_devices_observation_.Observe(&audio_devices_); - power_manager_client_observer_.Observe(power_manager_client_); - power_manager_client_->GetSwitchStates( - base::BindOnce(&AudioInputHostImpl::OnInitialLidStateReceived, - weak_factory_.GetWeakPtr())); -} - -void AudioInputHostImpl::SetMicState(bool mic_open) { - audio_input_->SetMicState(mic_open); -} - -void AudioInputHostImpl::SetDeviceId( - const base::Optional<std::string>& device_id) { - audio_input_->SetDeviceId(device_id.value_or("")); -} - -void AudioInputHostImpl::OnConversationTurnStarted() { - audio_input_->OnConversationTurnStarted(); - // Inform power manager of a wake notification when Libassistant - // recognized hotword and started a conversation. We intentionally - // avoid using |NotifyUserActivity| because it is not suitable for - // this case according to the Platform team. - power_manager_client_->NotifyWakeNotification(); -} - -void AudioInputHostImpl::OnConversationTurnFinished() { - audio_input_->OnConversationTurnFinished(); -} - -void AudioInputHostImpl::OnHotwordEnabled(bool enable) { - audio_input_->OnHotwordEnabled(enable); -} - -void AudioInputHostImpl::SetHotwordDeviceId( - const base::Optional<std::string>& device_id) { - audio_input_->SetHotwordDeviceId(device_id.value_or("")); -} - -void AudioInputHostImpl::LidEventReceived( - chromeos::PowerManagerClient::LidState state, - base::TimeTicks timestamp) { - // Lid switch event still gets fired during system suspend, which enables - // us to stop DSP recording correctly when user closes lid after the device - // goes to sleep. - audio_input_->OnLidStateChanged(ConvertLidState(state)); -} - -void AudioInputHostImpl::OnInitialLidStateReceived( - base::Optional<chromeos::PowerManagerClient::SwitchStates> switch_states) { - if (switch_states.has_value()) - audio_input_->OnLidStateChanged(ConvertLidState(switch_states->lid_state)); -} - -} // namespace assistant -} // namespace chromeos
diff --git a/chromeos/services/assistant/platform/audio_input_host_impl.h b/chromeos/services/assistant/platform/audio_input_host_impl.h deleted file mode 100644 index fc3583a..0000000 --- a/chromeos/services/assistant/platform/audio_input_host_impl.h +++ /dev/null
@@ -1,73 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_SERVICES_ASSISTANT_PLATFORM_AUDIO_INPUT_HOST_IMPL_H_ -#define CHROMEOS_SERVICES_ASSISTANT_PLATFORM_AUDIO_INPUT_HOST_IMPL_H_ - -#include "chromeos/services/assistant/public/cpp/migration/audio_input_host.h" - -#include <string> - -#include "base/component_export.h" -#include "base/memory/weak_ptr.h" -#include "base/optional.h" -#include "base/scoped_observation.h" -#include "base/time/time.h" -#include "chromeos/dbus/power/power_manager_client.h" -#include "chromeos/services/assistant/platform/audio_devices.h" - -namespace chromeos { -namespace assistant { - -class COMPONENT_EXPORT(ASSISTANT_SERVICE) AudioInputHostImpl - : public AudioInputHost, - private chromeos::PowerManagerClient::Observer, - private AudioDevices::Observer { - public: - AudioInputHostImpl(CrasAudioHandler* cras_audio_handler, - chromeos::PowerManagerClient* power_manager_client, - const std::string& locale); - AudioInputHostImpl(const AudioInputHostImpl&) = delete; - AudioInputHostImpl& operator=(const AudioInputHostImpl&) = delete; - ~AudioInputHostImpl() override; - - // AudioInputHost implementation: - void Initialize(AudioInputImpl* audio_input) override; - void SetMicState(bool mic_open) override; - void OnHotwordEnabled(bool enable) override; - void OnConversationTurnStarted() override; - void OnConversationTurnFinished() override; - - // AudioDevices::Observer implementation: - void SetDeviceId(const base::Optional<std::string>& device_id) override; - void SetHotwordDeviceId( - const base::Optional<std::string>& device_id) override; - - private: - // chromeos::PowerManagerClient::Observer overrides: - void LidEventReceived(chromeos::PowerManagerClient::LidState state, - base::TimeTicks timestamp) override; - - void OnInitialLidStateReceived( - base::Optional<chromeos::PowerManagerClient::SwitchStates> switch_states); - - // Owned by |PlatformApiImpl| which also owns |this|. - AudioInputImpl* audio_input_ = nullptr; - chromeos::PowerManagerClient* const power_manager_client_; - base::ScopedObservation<chromeos::PowerManagerClient, - chromeos::PowerManagerClient::Observer> - power_manager_client_observer_; - - // Observes available audio devices and will set device-id/hotword-device-id - // accordingly. - AudioDevices audio_devices_; - AudioDevices::ScopedObservation audio_devices_observation_{this}; - - base::WeakPtrFactory<AudioInputHostImpl> weak_factory_{this}; -}; - -} // namespace assistant -} // namespace chromeos - -#endif // CHROMEOS_SERVICES_ASSISTANT_PLATFORM_AUDIO_INPUT_HOST_IMPL_H_
diff --git a/chromeos/services/assistant/platform/audio_input_impl.cc b/chromeos/services/assistant/platform/audio_input_impl.cc index 1e14738b..66b944b 100644 --- a/chromeos/services/assistant/platform/audio_input_impl.cc +++ b/chromeos/services/assistant/platform/audio_input_impl.cc
@@ -283,7 +283,6 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(observer_sequence_checker_); if (open_audio_stream_) VLOG(1) << open_audio_stream_->device_id() << " remove observer"; - bool have_no_observer = false; { base::AutoLock lock(lock_);
diff --git a/chromeos/services/assistant/platform/audio_input_impl_unittest.cc b/chromeos/services/assistant/platform/audio_input_impl_unittest.cc index 28b6d5f..5d264cb 100644 --- a/chromeos/services/assistant/platform/audio_input_impl_unittest.cc +++ b/chromeos/services/assistant/platform/audio_input_impl_unittest.cc
@@ -11,8 +11,9 @@ #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "chromeos/audio/cras_audio_handler.h" +#include "chromeos/dbus/audio/fake_cras_audio_client.h" #include "chromeos/dbus/power/fake_power_manager_client.h" -#include "chromeos/services/assistant/platform/audio_input_host_impl.h" +#include "chromeos/services/assistant/platform/audio_input_host.h" #include "chromeos/services/assistant/platform/audio_stream_factory_delegate.h" #include "chromeos/services/assistant/public/cpp/features.h" #include "chromeos/services/assistant/test_support/scoped_assistant_client.h" @@ -47,14 +48,22 @@ DISALLOW_COPY_AND_ASSIGN(ScopedFakeAssistantClient); }; -class ScopedCrasAudioHandler { +// Mock for |CrosAudioClient|. This inherits from |FakeCrasAudioClient| so we +// only have to mock the methods we're interested in. +// It will automatically be installed as the global singleton in its +// constructor, and removed in the destructor. +class ScopedCrasAudioClientMock : public FakeCrasAudioClient { public: - ScopedCrasAudioHandler() { CrasAudioHandler::InitializeForTesting(); } - ScopedCrasAudioHandler(const ScopedCrasAudioHandler&) = delete; - ScopedCrasAudioHandler& operator=(const ScopedCrasAudioHandler&) = delete; - ~ScopedCrasAudioHandler() { CrasAudioHandler::Shutdown(); } + ScopedCrasAudioClientMock() = default; + ScopedCrasAudioClientMock(ScopedCrasAudioClientMock&) = delete; + ScopedCrasAudioClientMock& operator=(ScopedCrasAudioClientMock&) = delete; + ~ScopedCrasAudioClientMock() override = default; - CrasAudioHandler* Get() { return CrasAudioHandler::Get(); } + MOCK_METHOD(void, + SetHotwordModel, + (uint64_t node_id, + const std::string& hotword_model, + VoidDBusMethodCallback callback)); }; } // namespace @@ -67,6 +76,7 @@ scoped_feature_list_.InitAndEnableFeature(features::kEnableDspHotword); PowerManagerClient::InitializeFake(); + CrasAudioHandler::InitializeForTesting(); CreateNewAudioInputImpl(); } @@ -77,6 +87,7 @@ // |audio_input_host_| uses the fake power manager client, so must be // destroyed before the power manager client. audio_input_host_.reset(); + CrasAudioHandler::Shutdown(); chromeos::PowerManagerClient::Shutdown(); } @@ -101,11 +112,9 @@ audio_input_impl_ = std::make_unique<AudioInputImpl>( &audio_stream_factory_delegate_, "fake-device-id"); - audio_input_host_ = std::make_unique<AudioInputHostImpl>( - cras_audio_handler_.Get(), FakePowerManagerClient::Get(), - "initial-locale"); - audio_input_host_->Initialize(audio_input_impl_.get()); - audio_input_host_->SetDeviceId("initial-device-id"); + audio_input_host_ = std::make_unique<AudioInputHost>( + audio_input_impl_.get(), CrasAudioHandler::Get(), + FakePowerManagerClient::Get()); audio_input_impl_->AddObserver(this); @@ -123,6 +132,10 @@ AudioInputHost& audio_input_host() { return *audio_input_host_; } + ScopedCrasAudioClientMock& cras_audio_client_mock() { + return cras_audio_client_mock_; + } + // assistant_client::AudioInput::Observer overrides: void OnAudioBufferAvailable(const assistant_client::AudioBuffer& buffer, int64_t timestamp) override {} @@ -151,9 +164,9 @@ base::test::ScopedFeatureList scoped_feature_list_; ScopedFakeAssistantClient fake_assistant_client_; DefaultAudioStreamFactoryDelegate audio_stream_factory_delegate_; - ScopedCrasAudioHandler cras_audio_handler_; + ::testing::NiceMock<ScopedCrasAudioClientMock> cras_audio_client_mock_; std::unique_ptr<AudioInputImpl> audio_input_impl_; - std::unique_ptr<AudioInputHostImpl> audio_input_host_; + std::unique_ptr<AudioInputHost> audio_input_host_; DISALLOW_COPY_AND_ASSIGN(AudioInputImplTest); }; @@ -277,5 +290,81 @@ EXPECT_FALSE(IsUsingDeadStreamDetection()); } +TEST_F(AudioInputImplTest, ShouldSendHotwordLocaleToCrasAudioClient) { + StopAudioRecording(); + + audio_input_host().SetHotwordDeviceId("111"); + + EXPECT_CALL(cras_audio_client_mock(), SetHotwordModel); + audio_input_host().SetDspHotwordLocale("bla"); +} + +TEST_F(AudioInputImplTest, + ShouldFormatHotwordLocaleAndSendItToCrasAudioClient) { + StopAudioRecording(); + audio_input_host().SetHotwordDeviceId("111"); + + // Normal case + EXPECT_CALL(cras_audio_client_mock(), SetHotwordModel(111, "nl_be", _)); + audio_input_host().SetDspHotwordLocale("nl-BE"); + + // Handle the case where country code and language code are the same + EXPECT_CALL(cras_audio_client_mock(), SetHotwordModel(111, "fr_fr", _)); + audio_input_host().SetDspHotwordLocale("fr"); + + // use "en_all" for all english locales + EXPECT_CALL(cras_audio_client_mock(), SetHotwordModel(111, "en_all", _)); + audio_input_host().SetDspHotwordLocale("en-US"); +} + +TEST_F(AudioInputImplTest, ShouldUseDefaultLocaleIfUserPrefIsRejected) { + const std::string default_locale = "en_us"; + StopAudioRecording(); + audio_input_host().SetHotwordDeviceId("222"); + + EXPECT_CALL(cras_audio_client_mock(), + SetHotwordModel(222, "rejected_locale", _)) + .WillOnce([](uint64_t node_id, const std::string&, + VoidDBusMethodCallback callback) { + // Report failure to change the locale + std::move(callback).Run(/*success=*/false); + }); + + EXPECT_CALL(cras_audio_client_mock(), + SetHotwordModel(222, default_locale, _)); + + audio_input_host().SetDspHotwordLocale("rejected-LOCALE"); +} + +TEST_F(AudioInputImplTest, ShouldUseDefaultLocaleIfUserPrefIsEmpty) { + const std::string default_locale = "en_us"; + StopAudioRecording(); + audio_input_host().SetHotwordDeviceId("222"); + + EXPECT_CALL(cras_audio_client_mock(), + SetHotwordModel(222, default_locale, _)); + + audio_input_host().SetDspHotwordLocale(""); +} + +TEST_F(AudioInputImplTest, ShouldDoNothingIfUserPrefIsAccepted) { + const std::string default_locale = "en_us"; + StopAudioRecording(); + audio_input_host().SetHotwordDeviceId("222"); + + EXPECT_CALL(cras_audio_client_mock(), + SetHotwordModel(222, "accepted_locale", _)) + .WillOnce([](uint64_t node_id, const std::string&, + VoidDBusMethodCallback callback) { + // Accept the change to the locale. + std::move(callback).Run(/*success=*/true); + }); + + // Do not expect a second call if change of locale is accepted + EXPECT_CALL(cras_audio_client_mock(), SetHotwordModel(222, default_locale, _)) + .Times(0); + + audio_input_host().SetDspHotwordLocale("accepted-LOCALE"); +} } // namespace assistant } // namespace chromeos
diff --git a/chromeos/services/assistant/platform_api_impl.cc b/chromeos/services/assistant/platform_api_impl.cc index dc59df3..63c38759 100644 --- a/chromeos/services/assistant/platform_api_impl.cc +++ b/chromeos/services/assistant/platform_api_impl.cc
@@ -8,11 +8,11 @@ #include <utility> #include <vector> +#include "base/system/sys_info.h" +#include "chromeos/audio/cras_audio_handler.h" #include "chromeos/services/assistant/media_session/assistant_media_session.h" -#include "chromeos/services/assistant/platform/audio_devices.h" #include "chromeos/services/assistant/platform/power_manager_provider_impl.h" #include "chromeos/services/assistant/public/cpp/features.h" -#include "chromeos/services/assistant/public/cpp/migration/audio_input_host.h" #include "chromeos/services/assistant/utils.h" #include "libassistant/shared/public/assistant_export.h" #include "libassistant/shared/public/platform_api.h" @@ -79,13 +79,20 @@ PlatformApiImpl::PlatformApiImpl( AssistantMediaSession* media_session, PowerManagerClient* power_manager_client, + CrasAudioHandler* cras_audio_handler, mojo::PendingRemote<device::mojom::BatteryMonitor> battery_monitor, scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner, - scoped_refptr<base::SingleThreadTaskRunner> background_task_runner) + scoped_refptr<base::SingleThreadTaskRunner> background_task_runner, + std::string pref_locale) : audio_input_provider_(), audio_output_provider_(media_session, background_task_runner, - media::AudioDeviceDescription::kDefaultDeviceId) { + media::AudioDeviceDescription::kDefaultDeviceId), + audio_input_host_(&audio_input_provider_.GetAudioInput(), + cras_audio_handler, + power_manager_client), + pref_locale_(pref_locale), + cras_audio_handler_(cras_audio_handler) { // Only enable native power features if they are supported by the UI. std::unique_ptr<PowerManagerProviderImpl> provider; if (features::IsPowerManagerEnabled()) { @@ -94,9 +101,14 @@ } system_provider_ = std::make_unique<SystemProviderImpl>( std::move(provider), std::move(battery_monitor)); + + cras_audio_handler_->AddAudioObserver(this); + OnAudioNodesChanged(); } -PlatformApiImpl::~PlatformApiImpl() = default; +PlatformApiImpl::~PlatformApiImpl() { + cras_audio_handler_->RemoveAudioObserver(this); +} AudioInputProviderImpl& PlatformApiImpl::GetAudioInputProvider() { return audio_input_provider_; @@ -122,8 +134,64 @@ return *system_provider_; } -void PlatformApiImpl::InitializeAudioInputHost(AudioInputHost& host) { - host.Initialize(&audio_input_provider_.GetAudioInput()); +void PlatformApiImpl::OnAudioNodesChanged() { + if (!base::SysInfo::IsRunningOnChromeOS()) + return; + + chromeos::AudioDeviceList devices; + cras_audio_handler_->GetAudioDevices(&devices); + + const chromeos::AudioDevice* input_device = nullptr; + const chromeos::AudioDevice* hotword_device = nullptr; + + for (const chromeos::AudioDevice& device : devices) { + if (!device.is_input) + continue; + + switch (device.type) { + case chromeos::AUDIO_TYPE_USB: + case chromeos::AUDIO_TYPE_HEADPHONE: + case chromeos::AUDIO_TYPE_INTERNAL_MIC: + case chromeos::AUDIO_TYPE_FRONT_MIC: + if (!input_device || input_device->priority < device.priority) + input_device = &device; + break; + case chromeos::AUDIO_TYPE_HOTWORD: + if (!hotword_device || hotword_device->priority < device.priority) + hotword_device = &device; + break; + default: + // ignore other devices + break; + } + } + + audio_input_host_.SetDeviceId( + input_device ? base::NumberToString(input_device->id) : std::string()); + + if (hotword_device) { + audio_input_host_.SetHotwordDeviceId( + base::NumberToString(hotword_device->id)); + audio_input_host_.SetDspHotwordLocale(pref_locale_); + } else { + audio_input_host_.SetHotwordDeviceId(std::string()); + } +} + +void PlatformApiImpl::SetMicState(bool mic_open) { + audio_input_host_.SetMicState(mic_open); +} + +void PlatformApiImpl::OnConversationTurnStarted() { + audio_input_host_.OnConversationTurnStarted(); +} + +void PlatformApiImpl::OnConversationTurnFinished() { + audio_input_host_.OnConversationTurnFinished(); +} + +void PlatformApiImpl::OnHotwordEnabled(bool enable) { + audio_input_host_.OnHotwordEnabled(enable); } } // namespace assistant
diff --git a/chromeos/services/assistant/platform_api_impl.h b/chromeos/services/assistant/platform_api_impl.h index 782ddc8..ffcaeb1 100644 --- a/chromeos/services/assistant/platform_api_impl.h +++ b/chromeos/services/assistant/platform_api_impl.h
@@ -10,6 +10,8 @@ #include <utility> #include <vector> +#include "chromeos/audio/cras_audio_handler.h" +#include "chromeos/services/assistant/platform/audio_input_host.h" #include "chromeos/services/assistant/platform/audio_input_provider_impl.h" #include "chromeos/services/assistant/platform/audio_output_provider_impl.h" #include "chromeos/services/assistant/platform/file_provider_impl.h" @@ -29,14 +31,17 @@ class AssistantMediaSession; // Platform API required by the voice assistant. -class PlatformApiImpl : public CrosPlatformApi { +class PlatformApiImpl : public CrosPlatformApi, + CrasAudioHandler::AudioObserver { public: PlatformApiImpl( AssistantMediaSession* media_session, PowerManagerClient* power_manager_client, + CrasAudioHandler* cras_audio_handler, mojo::PendingRemote<device::mojom::BatteryMonitor> battery_monitor, scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner, - scoped_refptr<base::SingleThreadTaskRunner> background_task_runner); + scoped_refptr<base::SingleThreadTaskRunner> background_task_runner, + std::string pref_locale); ~PlatformApiImpl() override; // assistant_client::PlatformApi overrides @@ -47,7 +52,17 @@ assistant_client::NetworkProvider& GetNetworkProvider() override; assistant_client::SystemProvider& GetSystemProvider() override; - void InitializeAudioInputHost(AudioInputHost& host) override; + // chromeos::CrasAudioHandler::AudioObserver overrides + void OnAudioNodesChanged() override; + + // Called when the mic state associated with the interaction is changed. + void SetMicState(bool mic_open) override; + + void OnConversationTurnStarted() override; + void OnConversationTurnFinished() override; + + // Called when hotword enabled status changed. + void OnHotwordEnabled(bool enable) override; private: // ChromeOS does not use auth manager, so we don't yet need to implement a @@ -87,7 +102,11 @@ FakeAuthProvider auth_provider_; FileProviderImpl file_provider_; NetworkProviderImpl network_provider_; + AudioInputHost audio_input_host_; std::unique_ptr<SystemProviderImpl> system_provider_; + std::string pref_locale_; + + CrasAudioHandler* const cras_audio_handler_; DISALLOW_COPY_AND_ASSIGN(PlatformApiImpl); };
diff --git a/chromeos/services/assistant/public/cpp/migration/BUILD.gn b/chromeos/services/assistant/public/cpp/migration/BUILD.gn index 910c427..d901cdc 100644 --- a/chromeos/services/assistant/public/cpp/migration/BUILD.gn +++ b/chromeos/services/assistant/public/cpp/migration/BUILD.gn
@@ -11,7 +11,6 @@ sources = [ "assistant_manager_service_delegate.h", - "audio_input_host.h", "cros_platform_api.h", "libassistant_v1_api.cc", "libassistant_v1_api.h",
diff --git a/chromeos/services/assistant/public/cpp/migration/assistant_manager_service_delegate.h b/chromeos/services/assistant/public/cpp/migration/assistant_manager_service_delegate.h index f92b2f2..446616a 100644 --- a/chromeos/services/assistant/public/cpp/migration/assistant_manager_service_delegate.h +++ b/chromeos/services/assistant/public/cpp/migration/assistant_manager_service_delegate.h
@@ -20,7 +20,6 @@ namespace assistant { class AssistantMediaSession; -class AudioInputHost; class CrosPlatformApi; // Interface class that provides factory methods for assistant internal @@ -30,8 +29,6 @@ AssistantManagerServiceDelegate() = default; virtual ~AssistantManagerServiceDelegate() = default; - virtual std::unique_ptr<AudioInputHost> CreateAudioInputHost() = 0; - virtual std::unique_ptr<CrosPlatformApi> CreatePlatformApi( AssistantMediaSession* media_session, scoped_refptr<base::SingleThreadTaskRunner>
diff --git a/chromeos/services/assistant/public/cpp/migration/audio_input_host.h b/chromeos/services/assistant/public/cpp/migration/audio_input_host.h deleted file mode 100644 index 2314831..0000000 --- a/chromeos/services/assistant/public/cpp/migration/audio_input_host.h +++ /dev/null
@@ -1,41 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_SERVICES_ASSISTANT_PUBLIC_CPP_MIGRATION_AUDIO_INPUT_HOST_H_ -#define CHROMEOS_SERVICES_ASSISTANT_PUBLIC_CPP_MIGRATION_AUDIO_INPUT_HOST_H_ - -#include <string> - -#include "base/component_export.h" - -namespace chromeos { -namespace assistant { - -class AudioInputImpl; - -// Class that provides the bridge between the ChromeOS UI thread and the -// Libassistant audio input class. -class COMPONENT_EXPORT(ASSISTANT_SERVICE) AudioInputHost { - public: - virtual ~AudioInputHost() = default; - - // Initialize this class by setting the backend that it's supposed to use. - // TODO(b/171748795): Should be gone when the Libassistant V2 migration is - // completed. - virtual void Initialize(AudioInputImpl* audio_input) = 0; - - // Called when the mic state associated with the interaction is changed. - virtual void SetMicState(bool mic_open) = 0; - - // Called when hotword enabled status changed. - virtual void OnHotwordEnabled(bool enable) = 0; - - virtual void OnConversationTurnStarted() = 0; - virtual void OnConversationTurnFinished() = 0; -}; - -} // namespace assistant -} // namespace chromeos - -#endif // CHROMEOS_SERVICES_ASSISTANT_PUBLIC_CPP_MIGRATION_AUDIO_INPUT_HOST_H_
diff --git a/chromeos/services/assistant/public/cpp/migration/cros_platform_api.h b/chromeos/services/assistant/public/cpp/migration/cros_platform_api.h index 41f4ee12..409e7a10 100644 --- a/chromeos/services/assistant/public/cpp/migration/cros_platform_api.h +++ b/chromeos/services/assistant/public/cpp/migration/cros_platform_api.h
@@ -19,8 +19,6 @@ namespace chromeos { namespace assistant { -class AudioInputHost; - // Platform API required by the voice assistant, extended with some methods used // when ChromeOS needs to make changes to the platform state. // Note that this no longer inherits from |assistant_client::PlatformApi|, @@ -31,10 +29,14 @@ CrosPlatformApi() = default; virtual ~CrosPlatformApi() = default; - // Initialize the AudioInputHost. - // TODO(b/171748795): Should be gone when the Libassistant V2 migration is - // completed. - virtual void InitializeAudioInputHost(AudioInputHost&) = 0; + // Called when the mic state associated with the interaction is changed. + virtual void SetMicState(bool mic_open) = 0; + + virtual void OnConversationTurnStarted() = 0; + virtual void OnConversationTurnFinished() = 0; + + // Called when hotword enabled status changed. + virtual void OnHotwordEnabled(bool enable) = 0; // Returns the platform's audio input provider. virtual assistant_client::AudioInputProvider& GetAudioInputProvider() = 0;
diff --git a/chromeos/services/assistant/public/cpp/migration/fake_assistant_manager_service_delegate.cc b/chromeos/services/assistant/public/cpp/migration/fake_assistant_manager_service_delegate.cc index 73c9b52..4e0a16e 100644 --- a/chromeos/services/assistant/public/cpp/migration/fake_assistant_manager_service_delegate.cc +++ b/chromeos/services/assistant/public/cpp/migration/fake_assistant_manager_service_delegate.cc
@@ -9,30 +9,10 @@ #include "chromeos/assistant/internal/test_support/fake_assistant_manager.h" #include "chromeos/assistant/internal/test_support/fake_assistant_manager_internal.h" #include "chromeos/services/assistant//public/cpp/migration/fake_platform_api.h" -#include "chromeos/services/assistant/public/cpp/migration/audio_input_host.h" namespace chromeos { namespace assistant { -namespace { - -class FakeAudioInputHost : public AudioInputHost { - public: - FakeAudioInputHost() = default; - FakeAudioInputHost(const FakeAudioInputHost&) = delete; - FakeAudioInputHost& operator=(const FakeAudioInputHost&) = delete; - ~FakeAudioInputHost() override = default; - - // AudioInputHost implementation: - void Initialize(AudioInputImpl* audio_input) override {} - void SetMicState(bool mic_open) override {} - void OnHotwordEnabled(bool enable) override {} - void OnConversationTurnStarted() override {} - void OnConversationTurnFinished() override {} -}; - -} // namespace - FakeAssistantManagerServiceDelegate::FakeAssistantManagerServiceDelegate() { // We start by creating a pending assistant manager, as our unittests // might need to access the assistant manager before it is created through @@ -43,11 +23,6 @@ FakeAssistantManagerServiceDelegate::~FakeAssistantManagerServiceDelegate() = default; -std::unique_ptr<AudioInputHost> -FakeAssistantManagerServiceDelegate::CreateAudioInputHost() { - return std::make_unique<FakeAudioInputHost>(); -} - std::unique_ptr<CrosPlatformApi> FakeAssistantManagerServiceDelegate::CreatePlatformApi( AssistantMediaSession* media_session,
diff --git a/chromeos/services/assistant/public/cpp/migration/fake_assistant_manager_service_delegate.h b/chromeos/services/assistant/public/cpp/migration/fake_assistant_manager_service_delegate.h index 1adddb28..1ba87f1e 100644 --- a/chromeos/services/assistant/public/cpp/migration/fake_assistant_manager_service_delegate.h +++ b/chromeos/services/assistant/public/cpp/migration/fake_assistant_manager_service_delegate.h
@@ -26,7 +26,6 @@ FakeAssistantManager* assistant_manager(); // AssistantManagerServiceDelegate: - std::unique_ptr<AudioInputHost> CreateAudioInputHost() override; std::unique_ptr<CrosPlatformApi> CreatePlatformApi( AssistantMediaSession* media_session, scoped_refptr<base::SingleThreadTaskRunner> background_thread_task_runner)
diff --git a/chromeos/services/assistant/public/cpp/migration/fake_platform_api.h b/chromeos/services/assistant/public/cpp/migration/fake_platform_api.h index b730a4c..49fde32a 100644 --- a/chromeos/services/assistant/public/cpp/migration/fake_platform_api.h +++ b/chromeos/services/assistant/public/cpp/migration/fake_platform_api.h
@@ -28,7 +28,10 @@ assistant_client::FileProvider& GetFileProvider() override; assistant_client::NetworkProvider& GetNetworkProvider() override; assistant_client::SystemProvider& GetSystemProvider() override; - void InitializeAudioInputHost(AudioInputHost&) override {} + void SetMicState(bool mic_open) override {} + void OnHotwordEnabled(bool enable) override {} + void OnConversationTurnStarted() override {} + void OnConversationTurnFinished() override {} private: DISALLOW_COPY_AND_ASSIGN(FakePlatformApi);
diff --git a/chromeos/services/network_config/cros_network_config.cc b/chromeos/services/network_config/cros_network_config.cc index dc4704a..214ba25 100644 --- a/chromeos/services/network_config/cros_network_config.cc +++ b/chromeos/services/network_config/cros_network_config.cc
@@ -274,21 +274,24 @@ return base::EmptyString(); } -mojom::DeviceStatePropertiesPtr GetVpnState() { - auto result = mojom::DeviceStateProperties::New(); - result->type = mojom::NetworkType::kVPN; - - bool vpn_disabled = false; +bool IsVpnProhibited() { + bool vpn_prohibited = false; if (NetworkHandler::IsInitialized()) { std::vector<std::string> prohibited_technologies = NetworkHandler::Get() ->prohibited_technologies_handler() ->GetCurrentlyProhibitedTechnologies(); - vpn_disabled = base::Contains(prohibited_technologies, shill::kTypeVPN); + vpn_prohibited = base::Contains(prohibited_technologies, shill::kTypeVPN); } + return vpn_prohibited; +} - result->device_state = vpn_disabled ? mojom::DeviceStateType::kProhibited - : mojom::DeviceStateType::kEnabled; +mojom::DeviceStatePropertiesPtr GetVpnState() { + auto result = mojom::DeviceStateProperties::New(); + result->type = mojom::NetworkType::kVPN; + + result->device_state = IsVpnProhibited() ? mojom::DeviceStateType::kProhibited + : mojom::DeviceStateType::kEnabled; return result; } @@ -1861,7 +1864,15 @@ // Handle VPN state separately because VPN is not considered a device by shill // and thus will not be included in the |devices| list returned by network // state handler. In the UI code, it is treated as a "device" for consistency. - result.emplace_back(GetVpnState()); + // In the UI code, knowing whether a device is prohibited or not is done by + // checking |device_state| field of the DeviceStateProperties of the + // corresponding device. A VPN device state is returned if built-in VPN + // services are prohibited by policy even if no VPN services exist in order to + // indicate that adding a VPN is prohibited in the UI. + if (network_state_handler_->FirstNetworkByType(NetworkTypePattern::VPN()) || + IsVpnProhibited()) { + result.emplace_back(GetVpnState()); + } std::move(callback).Run(std::move(result)); }
diff --git a/chromeos/services/network_config/cros_network_config_unittest.cc b/chromeos/services/network_config/cros_network_config_unittest.cc index 342fbc1..8d95848 100644 --- a/chromeos/services/network_config/cros_network_config_unittest.cc +++ b/chromeos/services/network_config/cros_network_config_unittest.cc
@@ -25,6 +25,7 @@ #include "chromeos/network/network_state_test_helper.h" #include "chromeos/network/network_type_pattern.h" #include "chromeos/network/onc/onc_utils.h" +#include "chromeos/network/prohibited_technologies_handler.h" #include "chromeos/network/proxy/ui_proxy_config_service.h" #include "chromeos/services/network_config/public/cpp/cros_network_config_test_observer.h" #include "components/onc/onc_constants.h" @@ -485,6 +486,16 @@ run_loop.Run(); } + bool ContainsVpnDeviceState( + std::vector<mojom::DeviceStatePropertiesPtr> devices) { + for (auto& device : devices) { + if (device->type == mojom::NetworkType::kVPN) { + return true; + } + } + return false; + } + NetworkStateTestHelper& helper() { return helper_; } CrosNetworkConfigTestObserver* observer() { return observer_.get(); } CrosNetworkConfig* cros_network_config() { @@ -684,6 +695,32 @@ EXPECT_EQ(mojom::DeviceStateType::kDisabled, devices[0]->device_state); } +// Tests that no VPN device state is returned by GetDeviceStateList if no VPN +// services exist and built-in VPN is not prohibited. +TEST_F(CrosNetworkConfigTest, GetDeviceStateListNoVpnServices) { + helper().ClearServices(); + + std::vector<std::string> prohibited_technologies = + NetworkHandler::Get() + ->prohibited_technologies_handler() + ->GetCurrentlyProhibitedTechnologies(); + ASSERT_FALSE(base::Contains(prohibited_technologies, shill::kTypeVPN)); + + EXPECT_FALSE(ContainsVpnDeviceState(GetDeviceStateList())); +} + +// Tests that a VPN device state is returned by GetDeviceStateList if built-in +// VPN is not prohibited even if no VPN services exist. +TEST_F(CrosNetworkConfigTest, GetDeviceStateListNoVpnServicesAndVpnProhibited) { + helper().ClearServices(); + + NetworkHandler::Get() + ->prohibited_technologies_handler() + ->AddGloballyProhibitedTechnology(shill::kTypeVPN); + + EXPECT_TRUE(ContainsVpnDeviceState(GetDeviceStateList())); +} + // Test a sampling of properties, ensuring that string property types are // translated as strings and not enum values (See ManagedProperties definition // in cros_network_config.mojom for details).
diff --git a/components/account_manager_core/BUILD.gn b/components/account_manager_core/BUILD.gn index 665ab81..b16801c 100644 --- a/components/account_manager_core/BUILD.gn +++ b/components/account_manager_core/BUILD.gn
@@ -20,6 +20,7 @@ deps = [ "//base", "//chromeos/crosapi/mojom", + "//google_apis:google_apis", ] defines = [ "IS_ACCOUNT_MANAGER_CORE_IMPL" ]
diff --git a/components/account_manager_core/DEPS b/components/account_manager_core/DEPS index 1b72be6..1709b49 100644 --- a/components/account_manager_core/DEPS +++ b/components/account_manager_core/DEPS
@@ -1,3 +1,4 @@ include_rules = [ "+chromeos/crosapi/mojom/account_manager.mojom.h", + "+google_apis/gaia/google_service_auth_error.h", ]
diff --git a/components/account_manager_core/account_manager_facade.cc b/components/account_manager_core/account_manager_facade.cc index eb8eea7e..f154ff8 100644 --- a/components/account_manager_core/account_manager_facade.cc +++ b/components/account_manager_core/account_manager_facade.cc
@@ -6,6 +6,17 @@ namespace account_manager { +AccountManagerFacade::AccountAdditionResult::AccountAdditionResult() = default; +AccountManagerFacade::AccountAdditionResult::AccountAdditionResult( + Status status, + AccountKey account) + : status(status), account(account) {} +AccountManagerFacade::AccountAdditionResult::AccountAdditionResult( + Status status, + GoogleServiceAuthError error) + : status(status), error(error) {} +AccountManagerFacade::AccountAdditionResult::~AccountAdditionResult() = default; + AccountManagerFacade::AccountManagerFacade() = default; AccountManagerFacade::~AccountManagerFacade() = default;
diff --git a/components/account_manager_core/account_manager_facade.h b/components/account_manager_core/account_manager_facade.h index 4408ea0..ea0d886 100644 --- a/components/account_manager_core/account_manager_facade.h +++ b/components/account_manager_core/account_manager_facade.h
@@ -5,7 +5,12 @@ #ifndef COMPONENTS_ACCOUNT_MANAGER_CORE_ACCOUNT_MANAGER_FACADE_H_ #define COMPONENTS_ACCOUNT_MANAGER_CORE_ACCOUNT_MANAGER_FACADE_H_ +#include <string> + +#include "base/callback.h" #include "base/component_export.h" +#include "components/account_manager_core/account.h" +#include "google_apis/gaia/google_service_auth_error.h" namespace account_manager { @@ -42,6 +47,31 @@ kMaxValue = kOnboarding }; + // The result of account addition request. + struct AccountAdditionResult { + enum class Status : int { + // The account was added successfully. + kSuccess = 0, + // The dialog is already open. + kAlreadyInProgress = 1, + // User closed the dialog. + kCancelledByUser = 2, + // Network error. + kNetworkError = 3, + }; + + Status status; + // The account that was added. + base::Optional<AccountKey> account; + // The error is set only if `status` is set to `kNetworkError`. + base::Optional<GoogleServiceAuthError> error; + + AccountAdditionResult(); + AccountAdditionResult(Status status, AccountKey account); + AccountAdditionResult(Status status, GoogleServiceAuthError error); + ~AccountAdditionResult(); + }; + AccountManagerFacade(); AccountManagerFacade(const AccountManagerFacade&) = delete; AccountManagerFacade& operator=(const AccountManagerFacade&) = delete; @@ -52,6 +82,18 @@ // Note: For out-of-process implementations, it returns |false| if the IPC // pipe to |AccountManager| is disconnected. virtual bool IsInitialized() = 0; + + // Launches account addition dialog and calls the `callback` with the result. + // If `result` is `kSuccess`, the added account will be passed to the + // callback. Otherwise `account` will be set to `base::nullopt`. + virtual void ShowAddAccountDialog( + const AccountAdditionSource& source, + base::OnceCallback<void(const AccountAdditionResult& result)> + callback) = 0; + + // Launches account reauthentication dialog for provided `email`. + virtual void ShowReauthAccountDialog(const AccountAdditionSource& source, + const std::string& email) = 0; }; } // namespace account_manager
diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn index 3115136..293c7dd 100644 --- a/components/arc/BUILD.gn +++ b/components/arc/BUILD.gn
@@ -143,6 +143,7 @@ "//ui/base:base", "//ui/base/clipboard", "//ui/base/ime", + "//ui/base/ime/chromeos:chromeos", "//ui/chromeos/strings", "//ui/display/manager", "//ui/events",
diff --git a/components/arc/ime/arc_ime_service.cc b/components/arc/ime/arc_ime_service.cc index 7cf6412..4ded456 100644 --- a/components/arc/ime/arc_ime_service.cc +++ b/components/arc/ime/arc_ime_service.cc
@@ -25,6 +25,8 @@ #include "ui/aura/env.h" #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" +#include "ui/base/ime/chromeos/extension_ime_util.h" +#include "ui/base/ime/chromeos/input_method_manager.h" #include "ui/base/ime/input_method.h" #include "ui/base/ime/input_method_delegate.h" #include "ui/base/ime/text_input_flags.h" @@ -633,6 +635,18 @@ if (!range.is_empty()) { base::UmaHistogramEnumeration("InputMethod.Assistive.Autocorrect.Count", TextInputClient::SubClass::kArcImeService); + + auto* input_method_manager = + chromeos::input_method::InputMethodManager::Get(); + if (input_method_manager && + chromeos::extension_ime_util::IsExperimentalMultilingual( + input_method_manager->GetActiveIMEState() + ->GetCurrentInputMethod() + .id())) { + base::UmaHistogramEnumeration( + "InputMethod.MultilingualExperiment.Autocorrect.Count", + TextInputClient::SubClass::kArcImeService); + } } // TODO(https:://crbug.com/1091088): Implement this method. NOTIMPLEMENTED_LOG_ONCE();
diff --git a/components/autofill/ios/browser/js_suggestion_manager.h b/components/autofill/ios/browser/js_suggestion_manager.h index 953742fe..425e4ae 100644 --- a/components/autofill/ios/browser/js_suggestion_manager.h +++ b/components/autofill/ios/browser/js_suggestion_manager.h
@@ -5,70 +5,90 @@ #ifndef COMPONENTS_AUTOFILL_IOS_BROWSER_JS_SUGGESTION_MANAGER_H_ #define COMPONENTS_AUTOFILL_IOS_BROWSER_JS_SUGGESTION_MANAGER_H_ -#import "ios/web/public/deprecated/crw_js_injection_receiver.h" +#include "base/callback.h" +#include "base/memory/weak_ptr.h" +#import "ios/web/public/web_state_user_data.h" + +namespace base { +class Value; +} // namespace base namespace web { -class WebFramesManager; -} // namespace +class WebFrame; +class WebState; +} // namespace web -// Loads the JavaScript file, suggestion_manager.js, which contains form parsing -// and autofill functions. -@interface JsSuggestionManager : NSObject +namespace autofill { -// Designated initializer. |receiver| should not be nil. -- (instancetype)initWithReceiver:(CRWJSInjectionReceiver*)receiver - NS_DESIGNATED_INITIALIZER; +class JsSuggestionManager : public web::WebStateUserData<JsSuggestionManager> { + public: + ~JsSuggestionManager() override; -- (instancetype)init NS_UNAVAILABLE; + static JsSuggestionManager* GetOrCreateForWebState(web::WebState* web_state); -// Sets the WebFrames manager associated with the receiver. -- (void)setWebFramesManager:(web::WebFramesManager*)framesManager; + // Focuses the next focusable element in tab order inside the web frame with + // frame id |frame_ID|. No action if there is no such element. + void SelectNextElementInFrameWithID(const std::string& frame_ID); -// Focuses the next focusable element in tab order inside the web frame with -// frame id |frameID|. No action if there is no such element. -- (void)selectNextElementInFrameWithID:(NSString*)frameID; + // Focuses the next focusable element in tab order after the element specified + // by |form_name| and |field_name| in tab order inside the web frame with + // frame id |frame_ID|. No action if there is no such element. + void SelectNextElementInFrameWithID(const std::string& frame_ID, + const std::string& form_name, + const std::string& field_name); -// Focuses the next focusable element in tab order after the element specified -// by |formName| and |fieldName| in tab order inside the web frame with frame id -// |frameID|. No action if there is no such element. -- (void)selectNextElementInFrameWithID:(NSString*)frameID - afterForm:(NSString*)formName - field:(NSString*)fieldName; + // Focuses the previous focusable element in tab order inside the web frame + // with frame id |frame_ID|. No action if there is no such element. + void SelectPreviousElementInFrameWithID(const std::string& frame_ID); -// Focuses the previous focusable element in tab order inside the web frame with -// frame id |frameID|. No action if there is no such element. -- (void)selectPreviousElementInFrameWithID:(NSString*)frameID; + // Focuses the previous focusable element in tab order from the element + // specified by |form_name| and |field_name| in tab order inside the web frame + // with frame id |frame_ID|. No action if there is no such element. + void SelectPreviousElementInFrameWithID(const std::string& frame_ID, + const std::string& form_name, + const std::string& field_name); -// Focuses the previous focusable element in tab order from the element -// specified by |formName| and |fieldName| in tab order inside the web frame -// with frame id |frameID|. No action if there is no such element. -- (void)selectPreviousElementInFrameWithID:(NSString*)frameID - beforeForm:(NSString*)formName - field:(NSString*)fieldName; + // Checks if the frame with frame id |frame_ID| contains a next and previous + // element. |completionHandler| is called with 2 bools, the first indicating + // if a previous element was found, and the second indicating if a next + // element was found. |completionHcompletion_handlerandler| cannot be nil. + void FetchPreviousAndNextElementsPresenceInFrameWithID( + const std::string& frame_ID, + base::OnceCallback<void(bool, bool)> completion_handler); -// Checks if the frame with frame id |frameID| contains a next and previous -// element. |completionHandler| is called with 2 BOOLs, the first indicating if -// a previous element was found, and the second indicating if a next element was -// found. |completionHandler| cannot be nil. -- (void)fetchPreviousAndNextElementsPresenceInFrameWithID:(NSString*)frameID - completionHandler:(void (^)(BOOL, BOOL)) - completionHandler; + // Checks if the frame with frame id |frame_ID| contains a next and previous + // element starting from the field specified by |form_name| and |field_name|. + // |completionHandler| is called with 2 BOOLs, the first indicating if a + // previous element was found, and the second indicating if a next element was + // found. |completion_handler| cannot be nil. + void FetchPreviousAndNextElementsPresenceInFrameWithID( + const std::string& frame_ID, + const std::string& form_name, + const std::string& field_name, + base::OnceCallback<void(bool, bool)> completion_handler); -// Checks if the frame with frame id |frameID| contains a next and previous -// element starting from the field specified by |formName| and |fieldName|. -// |completionHandler| is called with 2 BOOLs, the first indicating if a -// previous element was found, and the second indicating if a next element was -// found. |completionHandler| cannot be nil. -- (void)fetchPreviousAndNextElementsPresenceInFrameWithID:(NSString*)frameID - forForm:(NSString*)formName - field:(NSString*)fieldName - completionHandler:(void (^)(BOOL, BOOL)) - completionHandler; + // Closes the keyboard and defocuses the active input element in the frame + // with frame id |frame_ID|. + void CloseKeyboardForFrameWithID(const std::string& frame_ID); -// Closes the keyboard and defocuses the active input element in the frame with -// frame id |frameID|. -- (void)closeKeyboardForFrameWithID:(NSString*)frameID; + private: + explicit JsSuggestionManager(web::WebState* web_state); -@end + void PreviousAndNextElementsPresenceResult( + base::OnceCallback<void(bool, bool)> completion_handler, + const base::Value* res); + + web::WebFrame* GetFrameWithFrameID(const std::string& frame_ID); + + web::WebState* web_state_; + + base::WeakPtrFactory<JsSuggestionManager> weak_ptr_factory_; + + friend class web::WebStateUserData<JsSuggestionManager>; + + WEB_STATE_USER_DATA_KEY_DECL(); +}; + +} // namespace autofill #endif // COMPONENTS_AUTOFILL_IOS_BROWSER_JS_SUGGESTION_MANAGER_H_
diff --git a/components/autofill/ios/browser/js_suggestion_manager.mm b/components/autofill/ios/browser/js_suggestion_manager.mm index 41edcd0..2b207468 100644 --- a/components/autofill/ios/browser/js_suggestion_manager.mm +++ b/components/autofill/ios/browser/js_suggestion_manager.mm
@@ -4,6 +4,7 @@ #import "components/autofill/ios/browser/js_suggestion_manager.h" +#import <Foundation/Foundation.h> #include <vector> #include "base/bind.h" @@ -21,115 +22,125 @@ #error "This file requires ARC support." #endif -@implementation JsSuggestionManager { - // The injection receiver used to evaluate JavaScript. - __weak CRWJSInjectionReceiver* _receiver; - web::WebFramesManager* _webFramesManager; -} +namespace autofill { -- (instancetype)initWithReceiver:(CRWJSInjectionReceiver*)receiver { - DCHECK(receiver); - self = [super init]; - if (self) { - _receiver = receiver; +JsSuggestionManager::JsSuggestionManager(web::WebState* web_state) + : web_state_(web_state), weak_ptr_factory_(this) {} + +JsSuggestionManager::~JsSuggestionManager() = default; + +// static +JsSuggestionManager* JsSuggestionManager::GetOrCreateForWebState( + web::WebState* web_state) { + JsSuggestionManager* helper = FromWebState(web_state); + if (!helper) { + CreateForWebState(web_state); + helper = FromWebState(web_state); + DCHECK(helper); } - return self; + return helper; } -- (void)setWebFramesManager:(web::WebFramesManager*)framesManager { - _webFramesManager = framesManager; +void JsSuggestionManager::SelectNextElementInFrameWithID( + const std::string& frame_ID) { + SelectNextElementInFrameWithID(frame_ID, "", ""); } -#pragma mark - -#pragma mark ProtectedMethods - -- (void)selectNextElementInFrameWithID:(NSString*)frameID { - [self selectNextElementInFrameWithID:frameID afterForm:@"" field:@""]; -} - -- (void)selectNextElementInFrameWithID:(NSString*)frameID - afterForm:(NSString*)formName - field:(NSString*)fieldName { +void JsSuggestionManager::SelectNextElementInFrameWithID( + const std::string& frame_ID, + const std::string& form_name, + const std::string& field_name) { std::vector<base::Value> parameters; - parameters.push_back(base::Value(base::SysNSStringToUTF8(formName))); - parameters.push_back(base::Value(base::SysNSStringToUTF8(fieldName))); - autofill::ExecuteJavaScriptFunction( - "suggestion.selectNextElement", parameters, - [self frameWithFrameID:frameID], autofill::JavaScriptResultCallback()); + parameters.push_back(base::Value(form_name)); + parameters.push_back(base::Value(field_name)); + autofill::ExecuteJavaScriptFunction("suggestion.selectNextElement", + parameters, GetFrameWithFrameID(frame_ID), + autofill::JavaScriptResultCallback()); } -- (void)selectPreviousElementInFrameWithID:(NSString*)frameID { - [self selectPreviousElementInFrameWithID:frameID beforeForm:@"" field:@""]; +void JsSuggestionManager::SelectPreviousElementInFrameWithID( + const std::string& frame_ID) { + SelectPreviousElementInFrameWithID(frame_ID, "", ""); } -- (void)selectPreviousElementInFrameWithID:(NSString*)frameID - beforeForm:(NSString*)formName - field:(NSString*)fieldName { +void JsSuggestionManager::SelectPreviousElementInFrameWithID( + const std::string& frame_ID, + const std::string& form_name, + const std::string& field_name) { std::vector<base::Value> parameters; - parameters.push_back(base::Value(base::SysNSStringToUTF8(formName))); - parameters.push_back(base::Value(base::SysNSStringToUTF8(fieldName))); - autofill::ExecuteJavaScriptFunction( - "suggestion.selectPreviousElement", parameters, - [self frameWithFrameID:frameID], autofill::JavaScriptResultCallback()); + parameters.push_back(base::Value(form_name)); + parameters.push_back(base::Value(field_name)); + autofill::ExecuteJavaScriptFunction("suggestion.selectPreviousElement", + parameters, GetFrameWithFrameID(frame_ID), + autofill::JavaScriptResultCallback()); } -- (void)fetchPreviousAndNextElementsPresenceInFrameWithID:(NSString*)frameID - completionHandler: - (void (^)(BOOL, - BOOL))completionHandler { - [self fetchPreviousAndNextElementsPresenceInFrameWithID:frameID - forForm:@"" - field:@"" - completionHandler:completionHandler]; +void JsSuggestionManager::FetchPreviousAndNextElementsPresenceInFrameWithID( + const std::string& frame_ID, + base::OnceCallback<void(bool, bool)> completion_handler) { + FetchPreviousAndNextElementsPresenceInFrameWithID( + frame_ID, "", "", std::move(completion_handler)); } -- (void)fetchPreviousAndNextElementsPresenceInFrameWithID:(NSString*)frameID - forForm:(NSString*)formName - field:(NSString*)fieldName - completionHandler: - (void (^)(BOOL, - BOOL))completionHandler { - DCHECK(completionHandler); +void JsSuggestionManager::FetchPreviousAndNextElementsPresenceInFrameWithID( + const std::string& frame_ID, + const std::string& form_name, + const std::string& field_name, + base::OnceCallback<void(bool, bool)> completion_handler) { + DCHECK(completion_handler); std::vector<base::Value> parameters; - parameters.push_back(base::Value(base::SysNSStringToUTF8(formName))); - parameters.push_back(base::Value(base::SysNSStringToUTF8(fieldName))); + parameters.push_back(base::Value(form_name)); + parameters.push_back(base::Value(field_name)); autofill::ExecuteJavaScriptFunction( "suggestion.hasPreviousNextElements", parameters, - [self frameWithFrameID:frameID], - autofill::CreateStringCallback(^(NSString* result) { - // The result maybe an empty string here due to 2 reasons: - // 1) When there is an exception running the JS - // 2) There is a race when the page is changing due to which - // JSSuggestionManager has not yet injected __gCrWeb.suggestion - // object Handle this case gracefully. If a page has overridden - // Array.toString, the string returned may not contain a ",", - // hence this is a defensive measure to early return. - NSArray* components = [result componentsSeparatedByString:@","]; - if (components.count != 2) { - completionHandler(NO, NO); - return; - } - - DCHECK([components[0] isEqualToString:@"true"] || - [components[0] isEqualToString:@"false"]); - BOOL hasPreviousElement = [components[0] isEqualToString:@"true"]; - DCHECK([components[1] isEqualToString:@"true"] || - [components[1] isEqualToString:@"false"]); - BOOL hasNextElement = [components[1] isEqualToString:@"true"]; - completionHandler(hasPreviousElement, hasNextElement); - })); + GetFrameWithFrameID(frame_ID), + base::BindOnce( + &JsSuggestionManager::PreviousAndNextElementsPresenceResult, + weak_ptr_factory_.GetWeakPtr(), std::move(completion_handler))); } -- (void)closeKeyboardForFrameWithID:(NSString*)frameID { +void JsSuggestionManager::PreviousAndNextElementsPresenceResult( + base::OnceCallback<void(bool, bool)> completion_handler, + const base::Value* res) { + NSString* result = nil; + if (res && res->is_string()) { + result = base::SysUTF8ToNSString(res->GetString()); + } + // The result maybe an empty string here due to 2 reasons: + // 1) When there is an exception running the JS + // 2) There is a race when the page is changing due to which + // JSSuggestionManager has not yet injected __gCrWeb.suggestion + // object Handle this case gracefully. If a page has overridden + // Array.toString, the string returned may not contain a ",", + // hence this is a defensive measure to early return. + NSArray* components = [result componentsSeparatedByString:@","]; + if (components.count != 2) { + std::move(completion_handler).Run(false, false); + return; + } + + DCHECK([components[0] isEqualToString:@"true"] || + [components[0] isEqualToString:@"false"]); + bool has_previous_element = [components[0] isEqualToString:@"true"]; + DCHECK([components[1] isEqualToString:@"true"] || + [components[1] isEqualToString:@"false"]); + bool has_next_element = [components[1] isEqualToString:@"true"]; + std::move(completion_handler).Run(has_previous_element, has_next_element); +} + +void JsSuggestionManager::CloseKeyboardForFrameWithID( + const std::string& frame_ID) { std::vector<base::Value> parameters; - autofill::ExecuteJavaScriptFunction( - "suggestion.blurActiveElement", parameters, - [self frameWithFrameID:frameID], autofill::JavaScriptResultCallback()); + autofill::ExecuteJavaScriptFunction("suggestion.blurActiveElement", + parameters, GetFrameWithFrameID(frame_ID), + autofill::JavaScriptResultCallback()); } -- (web::WebFrame*)frameWithFrameID:(NSString*)frameID { - DCHECK(_webFramesManager); - return _webFramesManager->GetFrameWithId(base::SysNSStringToUTF8(frameID)); +web::WebFrame* JsSuggestionManager::GetFrameWithFrameID( + const std::string& frame_ID) { + return web_state_->GetWebFramesManager()->GetFrameWithId(frame_ID); } -@end +WEB_STATE_USER_DATA_KEY_IMPL(JsSuggestionManager) + +} // namspace autofill
diff --git a/components/autofill_assistant/browser/model.proto b/components/autofill_assistant/browser/model.proto index b5441d6..876ffe4 100644 --- a/components/autofill_assistant/browser/model.proto +++ b/components/autofill_assistant/browser/model.proto
@@ -271,6 +271,12 @@ // HIGHLIGHTED_ACTION. DONE_ACTION = 6; + // A "Send feedback" chip, which will show the feedback form when clicked. + // + // Note that when this is used inside a script, we will continue the script + // normally once the user has clicked the chip. + FEEDBACK_ACTION = 7; + reserved 2; }
diff --git a/components/autofill_assistant/browser/service/lite_service_util.cc b/components/autofill_assistant/browser/service/lite_service_util.cc index 3bd4846b..18aec34 100644 --- a/components/autofill_assistant/browser/service/lite_service_util.cc +++ b/components/autofill_assistant/browser/service/lite_service_util.cc
@@ -117,6 +117,7 @@ case HIGHLIGHTED_ACTION: case NORMAL_ACTION: case CANCEL_ACTION: + case FEEDBACK_ACTION: return ActionResponseType::UNKNOWN; case CLOSE_ACTION: return ActionResponseType::PROMPT_CLOSE;
diff --git a/components/performance_manager/public/mojom/web_memory.mojom b/components/performance_manager/public/mojom/web_memory.mojom index 7b3888b..b3110b1 100644 --- a/components/performance_manager/public/mojom/web_memory.mojom +++ b/components/performance_manager/public/mojom/web_memory.mojom
@@ -47,13 +47,21 @@ string? id; }; +// The amount of memory used by a breakdown. +struct WebMemoryUsage { + uint64 bytes; +}; + // Describes a memory region and attributes it to a set of contexts. // Usually the set consists of a single context. If there are multiple // contexts then this means that the memory may be owned by any of them. struct WebMemoryBreakdownEntry { - uint64 bytes; - array<WebMemoryAttribution> attribution; + // The memory used in this breakdown. It is null for breakdowns that did not + // have a memory measurement (for example a frame that was added after the + // measurement started). + WebMemoryUsage? memory; + array<WebMemoryAttribution> attribution; // TODO(1085129): Add memory types once they are implemented. };
diff --git a/components/performance_manager/v8_memory/v8_memory_test_helpers.cc b/components/performance_manager/v8_memory/v8_memory_test_helpers.cc index d73875e..89eb97b 100644 --- a/components/performance_manager/v8_memory/v8_memory_test_helpers.cc +++ b/components/performance_manager/v8_memory/v8_memory_test_helpers.cc
@@ -19,6 +19,7 @@ #include "components/performance_manager/graph/process_node_impl.h" #include "components/performance_manager/public/mojom/v8_contexts.mojom.h" #include "components/performance_manager/public/performance_manager.h" +#include "components/performance_manager/v8_memory/v8_context_tracker.h" #include "content/public/browser/render_process_host.h" #include "content/public/test/navigation_simulator.h" #include "content/public/test/test_renderer_host.h" @@ -226,6 +227,7 @@ GetGraphFeaturesHelper().EnableV8ContextTracker(); Super::SetUp(); process_ = CreateNode<ProcessNodeImpl>(); + other_process_ = CreateNode<ProcessNodeImpl>(); pages_.push_back(CreateNode<PageNodeImpl>()); } @@ -239,6 +241,7 @@ Bytes memory_usage, FrameNodeImpl* parent, FrameNodeImpl* opener, + ProcessNodeImpl* process, base::Optional<std::string> id_attribute, base::Optional<std::string> src_attribute) { // If there's an opener, the new frame is also a new page. @@ -252,14 +255,16 @@ int frame_tree_node_id = GetNextUniqueId(); int frame_routing_id = GetNextUniqueId(); auto frame_token = blink::LocalFrameToken(); - auto frame = CreateNode<FrameNodeImpl>(process_.get(), page, parent, + auto frame = CreateNode<FrameNodeImpl>(process, page, parent, frame_tree_node_id, frame_routing_id, frame_token, browsing_instance_id); if (url) { frame->OnNavigationCommitted(GURL(*url), /*same document*/ true); } - V8DetailedMemoryExecutionContextData::CreateForTesting(frame.get()) - ->set_v8_bytes_used(memory_usage.bytes); + if (memory_usage) { + V8DetailedMemoryExecutionContextData::CreateForTesting(frame.get()) + ->set_v8_bytes_used(memory_usage.value()); + } frames_.push_back(std::move(frame)); FrameNodeImpl* frame_impl = frames_.back().get(); @@ -284,9 +289,20 @@ DCHECK(!id_attribute); DCHECK(!src_attribute); } + + // If the frame is in the same process as its parent include the attribution + // in OnV8ContextCreated, otherwise it must be attached separately with + // OnRemoteIframeAttached. DCHECK(frame_impl->process_node()); - frame_impl->process_node()->OnV8ContextCreated(std::move(description), - std::move(attribution)); + if (parent && parent->process_node() != frame_impl->process_node()) { + frame_impl->process_node()->OnV8ContextCreated( + std::move(description), mojom::IframeAttributionDataPtr()); + V8ContextTracker::GetFromGraph(graph())->OnRemoteIframeAttachedForTesting( + frame_impl, parent, blink::RemoteFrameToken(), std::move(attribution)); + } else { + frame_impl->process_node()->OnV8ContextCreated(std::move(description), + std::move(attribution)); + } return frame_impl; }
diff --git a/components/performance_manager/v8_memory/v8_memory_test_helpers.h b/components/performance_manager/v8_memory/v8_memory_test_helpers.h index fdae0c8..90810172 100644 --- a/components/performance_manager/v8_memory/v8_memory_test_helpers.h +++ b/components/performance_manager/v8_memory/v8_memory_test_helpers.h
@@ -225,10 +225,7 @@ using Super = GraphTestHarness; // Wrapper for memory usage bytes to improve test readability. - struct Bytes { - uint64_t bytes; - bool operator==(const Bytes& other) const { return bytes == other.bytes; } - }; + using Bytes = base::Optional<uint64_t>; WebMemoryTestHarness(); ~WebMemoryTestHarness() override; @@ -243,7 +240,8 @@ base::Optional<std::string> id_attribute = base::nullopt, base::Optional<std::string> src_attribute = base::nullopt) { return AddFrameNodeImpl(url, kDefaultBrowsingInstanceId, bytes, parent, - /*opener=*/nullptr, id_attribute, src_attribute); + /*opener=*/nullptr, process_.get(), id_attribute, + src_attribute); } // Creates a frame node as if from window.open and adds it to the graph. @@ -251,7 +249,9 @@ Bytes bytes, FrameNodeImpl* opener) { return AddFrameNodeImpl(url, kDefaultBrowsingInstanceId, bytes, - /*parent=*/nullptr, opener); + /*parent=*/nullptr, opener, process_.get(), + /*id_attribute=*/base::nullopt, + /*src_attribute=*/base::nullopt); } // Creates a frame node in a different browsing instance and adds it to the @@ -263,7 +263,8 @@ base::Optional<std::string> id_attribute = base::nullopt, base::Optional<std::string> src_attribute = base::nullopt) { return AddFrameNodeImpl(url, kDefaultBrowsingInstanceId + 1, bytes, parent, - /*opener=*/nullptr, id_attribute, src_attribute); + /*opener=*/nullptr, process_.get(), id_attribute, + src_attribute); } // Creates a frame node in a different browsing instance as if from @@ -273,7 +274,21 @@ Bytes bytes, FrameNodeImpl* opener) { return AddFrameNodeImpl(url, kDefaultBrowsingInstanceId + 1, bytes, - /*parent=*/nullptr, opener); + /*parent=*/nullptr, opener, process_.get(), + /*id_attribute=*/base::nullopt, + /*src_attribute=*/base::nullopt); + } + + // Creates a frame node in a different process and adds it to the graph. + FrameNodeImpl* AddCrossProcessFrameNode( + std::string url, + Bytes bytes, + FrameNodeImpl* parent, + base::Optional<std::string> id_attribute = base::nullopt, + base::Optional<std::string> src_attribute = base::nullopt) { + return AddFrameNodeImpl(url, kDefaultBrowsingInstanceId, bytes, parent, + /*opener=*/nullptr, other_process_.get(), + id_attribute, src_attribute); } ProcessNode* process_node() const { return process_.get(); } @@ -282,16 +297,17 @@ static constexpr int kDefaultBrowsingInstanceId = 0; // Creates and adds a new frame node to the graph. - FrameNodeImpl* AddFrameNodeImpl( - base::Optional<std::string> url, - int browsing_instance_id, - Bytes bytes, - FrameNodeImpl* parent = nullptr, - FrameNodeImpl* opener = nullptr, - base::Optional<std::string> id_attribute = base::nullopt, - base::Optional<std::string> src_attribute = base::nullopt); + FrameNodeImpl* AddFrameNodeImpl(base::Optional<std::string> url, + int browsing_instance_id, + Bytes bytes, + FrameNodeImpl* parent, + FrameNodeImpl* opener, + ProcessNodeImpl* process, + base::Optional<std::string> id_attribute, + base::Optional<std::string> src_attribute); int GetNextUniqueId(); TestNodeWrapper<ProcessNodeImpl> process_; + TestNodeWrapper<ProcessNodeImpl> other_process_; std::vector<TestNodeWrapper<PageNodeImpl>> pages_; std::vector<TestNodeWrapper<FrameNodeImpl>> frames_; int next_unique_id_ = 0;
diff --git a/components/performance_manager/v8_memory/web_memory_aggregator.cc b/components/performance_manager/v8_memory/web_memory_aggregator.cc index ebd5529..845cc36 100644 --- a/components/performance_manager/v8_memory/web_memory_aggregator.cc +++ b/components/performance_manager/v8_memory/web_memory_aggregator.cc
@@ -141,13 +141,6 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); aggregation_result_ = mojom::WebMemoryMeasurement::New(); VisitFrame(nullptr, aggregation_start_node_); - - // Don't report breakdowns without any memory use. - base::EraseIf(aggregation_result_->breakdown, - [](const mojom::WebMemoryBreakdownEntryPtr& entry) { - return entry->bytes == 0; - }); - return std::move(aggregation_result_); } @@ -221,7 +214,18 @@ DCHECK(aggregation_point); if (auto* frame_data = V8DetailedMemoryExecutionContextData::ForFrameNode(frame_node)) { - aggregation_point->bytes += frame_data->v8_bytes_used(); + if (!aggregation_point->memory) { + aggregation_point->memory = mojom::WebMemoryUsage::New(); + } + + // Ensure this frame is actually in the same process as the requesting + // frame. If not it should be considered to have 0 bytes. + // (https://github.com/WICG/performance-measure-memory/issues/20). + uint64_t bytes_used = (frame_node->GetProcessNode() == + aggregation_start_node_->GetProcessNode()) + ? frame_data->v8_bytes_used() + : 0; + aggregation_point->memory->bytes += bytes_used; } // Recurse into children and opened pages. This node's aggregation point @@ -269,10 +273,16 @@ // Follow parent and opener links to find the most general same-site node to // start the aggregation traversal from. - const FrameNode* start_node = requesting_node; - while (auto* parent_or_opener = - GetSameOriginParentOrOpener(start_node, requesting_origin)) { - start_node = parent_or_opener; + const FrameNode* start_node = nullptr; + for (auto* parent_or_opener = requesting_node; parent_or_opener; + parent_or_opener = + GetSameOriginParentOrOpener(parent_or_opener, requesting_origin)) { + // Only consider nodes in the same process as potential start nodes. + // (https://github.com/WICG/performance-measure-memory/issues/20). + if (parent_or_opener->GetProcessNode() == + requesting_node->GetProcessNode()) { + start_node = parent_or_opener; + } } DCHECK(start_node);
diff --git a/components/performance_manager/v8_memory/web_memory_aggregator_unittest.cc b/components/performance_manager/v8_memory/web_memory_aggregator_unittest.cc index c41f2c9..0590a640 100644 --- a/components/performance_manager/v8_memory/web_memory_aggregator_unittest.cc +++ b/components/performance_manager/v8_memory/web_memory_aggregator_unittest.cc
@@ -30,7 +30,7 @@ using WebMemoryAggregatorTest = WebMemoryTestHarness; struct ExpectedMemoryBreakdown { - uint64_t bytes = 0U; + WebMemoryTestHarness::Bytes bytes; AttributionScope scope = AttributionScope::kWindow; base::Optional<std::string> url; base::Optional<std::string> id; @@ -38,7 +38,7 @@ ExpectedMemoryBreakdown() = default; ExpectedMemoryBreakdown( - uint64_t expected_bytes, + WebMemoryTestHarness::Bytes expected_bytes, AttributionScope expected_scope, base::Optional<std::string> expected_url = base::nullopt, base::Optional<std::string> expected_id = base::nullopt, @@ -59,7 +59,10 @@ auto expected_measurement = mojom::WebMemoryMeasurement::New(); for (const auto& breakdown : breakdowns) { auto expected_breakdown = mojom::WebMemoryBreakdownEntry::New(); - expected_breakdown->bytes = breakdown.bytes; + if (breakdown.bytes) { + expected_breakdown->memory = mojom::WebMemoryUsage::New(); + expected_breakdown->memory->bytes = breakdown.bytes.value(); + } auto attribution = mojom::WebMemoryAttribution::New(); attribution->scope = breakdown.scope; @@ -129,15 +132,18 @@ internal::CopyBreakdownAttribution(breakdown_with_url, breakdown_with_empty_url); - // All measurements should be created with 0 bytes. + // All measurements should be created without measurement results. auto expected_result = CreateExpectedMemoryMeasurement({ - ExpectedMemoryBreakdown(0, AttributionScope::kCrossOriginAggregated, + ExpectedMemoryBreakdown(/*bytes=*/base::nullopt, + AttributionScope::kCrossOriginAggregated, /*expected_url=*/base::nullopt, /*expected_id=*/base::nullopt, /*expected_src=*/base::nullopt), - ExpectedMemoryBreakdown(0, AttributionScope::kWindow, + ExpectedMemoryBreakdown(/*bytes=*/base::nullopt, + AttributionScope::kWindow, "https://example.com", attribute, attribute), - ExpectedMemoryBreakdown(0, AttributionScope::kWindow, + ExpectedMemoryBreakdown(/*bytes=*/base::nullopt, + AttributionScope::kWindow, /*expected_url=*/"", attribute, attribute), }); EXPECT_EQ(MeasurementToJSON(measurement), @@ -293,10 +299,21 @@ AddFrameNode("https://example.com/iframe3", Bytes{6}, subframe3, "example-id6", "https://example.com/iframe3"); - // A frame with 0 bytes of memory use (eg. a frame that's added to the frame - // tree during the measurement) should not appear in the result. + // To test aggregation all the frames above are in the same process, even + // though in production frames with different origins will be in different + // processes whenever possible. Frames in a different process from the + // requesting frame should all have 0 bytes reported. + FrameNodeImpl* cross_process_frame = + AddCrossProcessFrameNode("https://example.com/cross_process", Bytes{100}, + subframe3, "cross-process-id1"); + FrameNodeImpl* cross_process_frame2 = + AddCrossProcessFrameNode("https://foo.com/cross_process", Bytes{200}, + subframe3, "cross-process-id2"); + + // A frame without a memory measurement (eg. a frame that's added to the frame + // tree during the measurement) should not have a memory entry in the result. FrameNodeImpl* empty_frame = - AddFrameNode("https://example.com/empty_frame", Bytes{0}, subframe3); + AddFrameNode("https://example.com/empty_frame", base::nullopt, subframe3); EXPECT_EQ(internal::FindAggregationStartNode(main_frame), main_frame); WebMemoryAggregator aggregator(main_frame); @@ -339,6 +356,16 @@ EXPECT_EQ(internal::GetSameOriginParentOrOpener( empty_frame, aggregator.requesting_origin()), subframe3); + EXPECT_EQ(aggregator.FindNodeAggregationType(cross_process_frame), + NodeAggregationType::kSameOriginAggregationPoint); + EXPECT_EQ(internal::GetSameOriginParentOrOpener( + cross_process_frame, aggregator.requesting_origin()), + subframe3); + EXPECT_EQ(aggregator.FindNodeAggregationType(cross_process_frame2), + NodeAggregationType::kCrossOriginAggregationPoint); + EXPECT_EQ(internal::GetSameOriginParentOrOpener( + cross_process_frame2, aggregator.requesting_origin()), + subframe3); auto expected_result = CreateExpectedMemoryMeasurement({ ExpectedMemoryBreakdown(10, AttributionScope::kWindow, @@ -358,6 +385,13 @@ ExpectedMemoryBreakdown(6, AttributionScope::kWindow, "https://example.com/iframe3", "example-id6", "https://example.com/iframe3"), + ExpectedMemoryBreakdown(0, AttributionScope::kWindow, + "https://example.com/cross_process", + "cross-process-id1"), + ExpectedMemoryBreakdown(0, AttributionScope::kCrossOriginAggregated, + base::nullopt, "cross-process-id2"), + ExpectedMemoryBreakdown(base::nullopt, AttributionScope::kWindow, + "https://example.com/empty_frame"), }); auto result = aggregator.AggregateMeasureMemoryResult(); EXPECT_EQ(MeasurementToJSON(result), MeasurementToJSON(expected_result)); @@ -407,6 +441,29 @@ MeasurementToJSON(main_frame_expected_result)); } +TEST_F(WebMemoryAggregatorTest, FindCrossProcessAggregationStartNode) { + FrameNodeImpl* main_frame = AddFrameNode("https://example.com/", Bytes{1}); + FrameNodeImpl* cross_process_child = AddCrossProcessFrameNode( + "https://example.com/cross_process.html", Bytes{2}, main_frame); + FrameNodeImpl* same_process_child = AddFrameNode( + "https://example.com/same_process.html", Bytes{3}, cross_process_child); + + auto origin = url::Origin::Create(GURL("https://example.com")); + ASSERT_EQ(internal::GetSameOriginParentOrOpener(cross_process_child, origin), + main_frame); + ASSERT_EQ(internal::GetSameOriginParentOrOpener(same_process_child, origin), + cross_process_child); + + // |cross_process_child| has no ancestor in the same process as it. + EXPECT_EQ(internal::FindAggregationStartNode(cross_process_child), + cross_process_child); + + // The search starting from |same_process_child| should skip over + // |cross_process_child|, which is in a different process, and find + // |main_frame| which is in the same process. + EXPECT_EQ(internal::FindAggregationStartNode(same_process_child), main_frame); +} + TEST_F(WebMemoryAggregatorTest, AggregateWindowOpener) { FrameNodeImpl* main_frame = AddFrameNode("https://example.com/", Bytes{10}); FrameNodeImpl* child_frame = AddFrameNode("https://example.com/iframe.html",
diff --git a/components/performance_manager/v8_memory/web_memory_impl_unittest.cc b/components/performance_manager/v8_memory/web_memory_impl_unittest.cc index d2dc784..a9718ace 100644 --- a/components/performance_manager/v8_memory/web_memory_impl_unittest.cc +++ b/components/performance_manager/v8_memory/web_memory_impl_unittest.cc
@@ -70,12 +70,13 @@ base::flat_map<std::string, Bytes> actual; for (const auto& entry : result->breakdown) { EXPECT_EQ(1u, entry->attribution.size()); - if (mojom::WebMemoryAttribution::Scope::kWindow == - entry->attribution[0]->scope) { - actual[*entry->attribution[0]->url] = Bytes{entry->bytes}; - } else { - actual[*entry->attribution[0]->src] = Bytes{entry->bytes}; - } + std::string attribution_tag = + (mojom::WebMemoryAttribution::Scope::kWindow == + entry->attribution[0]->scope) + ? *entry->attribution[0]->url + : *entry->attribution[0]->src; + actual[attribution_tag] = + entry->memory ? Bytes{entry->memory->bytes} : base::nullopt; } EXPECT_EQ(expected, actual); measurement_done = true; @@ -130,7 +131,8 @@ const auto& entry = result->breakdown[0]; EXPECT_EQ(1u, entry->attribution.size()); EXPECT_EQ(kMainFrameUrl, *(entry->attribution[0]->url)); - EXPECT_EQ(1001u, entry->bytes); + ASSERT_TRUE(entry->memory); + EXPECT_EQ(1001u, entry->memory->bytes); run_loop.Quit(); }); auto bad_message_callback =
diff --git a/components/safe_browsing/core/browser/BUILD.gn b/components/safe_browsing/core/browser/BUILD.gn index 7d110830..c7dba7f 100644 --- a/components/safe_browsing/core/browser/BUILD.gn +++ b/components/safe_browsing/core/browser/BUILD.gn
@@ -77,28 +77,7 @@ } source_set("token_fetcher") { - sources = [ - "safe_browsing_token_fetcher.cc", - "safe_browsing_token_fetcher.h", - ] + sources = [ "safe_browsing_token_fetcher.h" ] - deps = [ - "//base", - "//components/safe_browsing/core/common:thread_utils", - "//components/signin/public/identity_manager", - "//google_apis", - ] -} - -source_set("token_fetcher_unittest") { - testonly = true - sources = [ "safe_browsing_token_fetcher_unittest.cc" ] - - deps = [ - ":token_fetcher", - "//base/test:test_support", - "//components/safe_browsing/core/common:test_support", - "//components/signin/public/identity_manager:test_support", - "//testing/gtest", - ] + deps = [ "//base" ] }
diff --git a/components/safe_browsing/core/browser/safe_browsing_token_fetcher.h b/components/safe_browsing/core/browser/safe_browsing_token_fetcher.h index de5f5a8..13fab0f 100644 --- a/components/safe_browsing/core/browser/safe_browsing_token_fetcher.h +++ b/components/safe_browsing/core/browser/safe_browsing_token_fetcher.h
@@ -5,65 +5,24 @@ #ifndef COMPONENTS_SAFE_BROWSING_CORE_BROWSER_SAFE_BROWSING_TOKEN_FETCHER_H_ #define COMPONENTS_SAFE_BROWSING_CORE_BROWSER_SAFE_BROWSING_TOKEN_FETCHER_H_ -#include <memory> - #include "base/callback.h" -#include "base/containers/flat_map.h" -#include "base/memory/weak_ptr.h" -#include "base/optional.h" -#include "components/signin/public/identity_manager/access_token_info.h" -#include "components/signin/public/identity_manager/consent_level.h" -#include "google_apis/gaia/google_service_auth_error.h" - -namespace signin { -class IdentityManager; -class AccessTokenFetcher; -} // namespace signin namespace safe_browsing { -// This class is used to fetch access tokens for communcations with Safe -// Browsing. It asynchronously returns the access token for the current -// primary account, or nullopt if an error occurred. This must be -// run on the UI thread. +// This interface is used to fetch access tokens for communcations with Safe +// Browsing. It asynchronously returns an access token for the current account +// (as determined in concrete implementations), or the empty string if no access +// token is available (e.g., an error occurred). +// This must be run on the UI thread. class SafeBrowsingTokenFetcher { public: - using Callback = - base::OnceCallback<void(base::Optional<signin::AccessTokenInfo>)>; + using Callback = base::OnceCallback<void(const std::string& access_token)>; - // Create a SafeBrowsingTokenFetcher for the primary account of - // |identity_manager|. |identity_manager| is unowned, and must outlive this - // object. - explicit SafeBrowsingTokenFetcher(signin::IdentityManager* identity_manager); + virtual ~SafeBrowsingTokenFetcher() = default; - ~SafeBrowsingTokenFetcher(); - - // Begin fetching a token for the account with the given |consent_level|. The + // Begin fetching a token for the account. The // result will be returned in |callback|. Must be called on the UI thread. - void Start(signin::ConsentLevel consent_level, Callback callback); - - private: - void OnTokenFetched(int request_id, - GoogleServiceAuthError error, - signin::AccessTokenInfo access_token_info); - void OnTokenTimeout(int request_id); - void Finish(int request_id, - base::Optional<signin::AccessTokenInfo> token_info); - - // Reference to the identity manager to fetch from. - signin::IdentityManager* identity_manager_; - - // The count of requests sent. This is used as an ID for requests. - int requests_sent_; - - // Active fetchers, keyed by ID. - base::flat_map<int, std::unique_ptr<signin::AccessTokenFetcher>> - token_fetchers_; - - // Active callbacks, keyed by ID. - base::flat_map<int, Callback> callbacks_; - - base::WeakPtrFactory<SafeBrowsingTokenFetcher> weak_ptr_factory_; + virtual void Start(Callback callback) = 0; }; } // namespace safe_browsing
diff --git a/components/safe_browsing/core/browser/safe_browsing_token_fetcher_unittest.cc b/components/safe_browsing/core/browser/safe_browsing_token_fetcher_unittest.cc deleted file mode 100644 index 77137ed9..0000000 --- a/components/safe_browsing/core/browser/safe_browsing_token_fetcher_unittest.cc +++ /dev/null
@@ -1,103 +0,0 @@ -// Copyright 2020 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/safe_browsing/core/browser/safe_browsing_token_fetcher.h" -#include <memory> - -#include "base/run_loop.h" -#include "base/test/task_environment.h" -#include "components/safe_browsing/core/common/test_task_environment.h" -#include "components/signin/public/identity_manager/identity_test_environment.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace safe_browsing { - -class SafeBrowsingTokenFetcherTest : public ::testing::Test { - public: - SafeBrowsingTokenFetcherTest() - : task_environment_(CreateTestTaskEnvironment()) {} - - protected: - std::unique_ptr<base::test::TaskEnvironment> task_environment_; - signin::IdentityTestEnvironment identity_test_environment_; -}; - -TEST_F(SafeBrowsingTokenFetcherTest, Success) { - identity_test_environment_.MakeUnconsentedPrimaryAccountAvailable( - "test@example.com"); - base::Optional<signin::AccessTokenInfo> maybe_account_info; - SafeBrowsingTokenFetcher fetcher( - identity_test_environment_.identity_manager()); - fetcher.Start(signin::ConsentLevel::kNotRequired, - base::BindOnce( - [](base::Optional<signin::AccessTokenInfo>* target_info, - base::Optional<signin::AccessTokenInfo> info) { - *target_info = info; - }, - &maybe_account_info)); - identity_test_environment_ - .WaitForAccessTokenRequestIfNecessaryAndRespondWithToken( - "token", base::Time::Now()); - ASSERT_TRUE(maybe_account_info.has_value()); - EXPECT_EQ(maybe_account_info.value().token, "token"); -} - -TEST_F(SafeBrowsingTokenFetcherTest, Failure) { - identity_test_environment_.MakeUnconsentedPrimaryAccountAvailable( - "test@example.com"); - base::Optional<signin::AccessTokenInfo> maybe_account_info; - SafeBrowsingTokenFetcher fetcher( - identity_test_environment_.identity_manager()); - fetcher.Start(signin::ConsentLevel::kNotRequired, - base::BindOnce( - [](base::Optional<signin::AccessTokenInfo>* target_info, - base::Optional<signin::AccessTokenInfo> info) { - *target_info = info; - }, - &maybe_account_info)); - identity_test_environment_ - .WaitForAccessTokenRequestIfNecessaryAndRespondWithError( - GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED)); - ASSERT_FALSE(maybe_account_info.has_value()); -} - -TEST_F(SafeBrowsingTokenFetcherTest, NoSyncingAccount) { - identity_test_environment_.MakeUnconsentedPrimaryAccountAvailable( - "test@example.com"); - base::Optional<signin::AccessTokenInfo> maybe_account_info; - SafeBrowsingTokenFetcher fetcher( - identity_test_environment_.identity_manager()); - fetcher.Start(signin::ConsentLevel::kSync, - base::BindOnce( - [](base::Optional<signin::AccessTokenInfo>* target_info, - base::Optional<signin::AccessTokenInfo> info) { - *target_info = info; - }, - &maybe_account_info)); - identity_test_environment_ - .WaitForAccessTokenRequestIfNecessaryAndRespondWithToken( - "token", base::Time::Now()); - ASSERT_FALSE(maybe_account_info.has_value()); -} - -TEST_F(SafeBrowsingTokenFetcherTest, SyncSuccess) { - identity_test_environment_.MakePrimaryAccountAvailable("test@example.com"); - base::Optional<signin::AccessTokenInfo> maybe_account_info; - SafeBrowsingTokenFetcher fetcher( - identity_test_environment_.identity_manager()); - fetcher.Start(signin::ConsentLevel::kSync, - base::BindOnce( - [](base::Optional<signin::AccessTokenInfo>* target_info, - base::Optional<signin::AccessTokenInfo> info) { - *target_info = info; - }, - &maybe_account_info)); - identity_test_environment_ - .WaitForAccessTokenRequestIfNecessaryAndRespondWithToken( - "token", base::Time::Now()); - ASSERT_TRUE(maybe_account_info.has_value()); - EXPECT_EQ(maybe_account_info.value().token, "token"); -} - -} // namespace safe_browsing
diff --git a/components/safe_browsing/core/browser/sync/BUILD.gn b/components/safe_browsing/core/browser/sync/BUILD.gn new file mode 100644 index 0000000..68a0503 --- /dev/null +++ b/components/safe_browsing/core/browser/sync/BUILD.gn
@@ -0,0 +1,33 @@ +# Copyright 2021 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. + +import("//build/config/features.gni") + +source_set("sync") { + sources = [ + "safe_browsing_primary_account_token_fetcher.cc", + "safe_browsing_primary_account_token_fetcher.h", + ] + + deps = [ + "//base", + "//components/safe_browsing/core/browser:token_fetcher", + "//components/safe_browsing/core/common:thread_utils", + "//components/signin/public/identity_manager", + "//google_apis", + ] +} + +source_set("unittests") { + testonly = true + sources = [ "safe_browsing_primary_account_token_fetcher_unittest.cc" ] + + deps = [ + ":sync", + "//base/test:test_support", + "//components/safe_browsing/core/common:test_support", + "//components/signin/public/identity_manager:test_support", + "//testing/gtest", + ] +}
diff --git a/components/safe_browsing/core/browser/sync/README.md b/components/safe_browsing/core/browser/sync/README.md new file mode 100644 index 0000000..6f45bc4 --- /dev/null +++ b/components/safe_browsing/core/browser/sync/README.md
@@ -0,0 +1 @@ +Holds touchpoints for safe_browsing's integration with signin and sync.
diff --git a/components/safe_browsing/core/browser/safe_browsing_token_fetcher.cc b/components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher.cc similarity index 67% rename from components/safe_browsing/core/browser/safe_browsing_token_fetcher.cc rename to components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher.cc index 97a18d0c..f2e12675 100644 --- a/components/safe_browsing/core/browser/safe_browsing_token_fetcher.cc +++ b/components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/safe_browsing/core/browser/safe_browsing_token_fetcher.h" +#include "components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher.h" #include "base/bind.h" #include "base/memory/weak_ptr.h" @@ -33,7 +33,7 @@ } // namespace -SafeBrowsingTokenFetcher::SafeBrowsingTokenFetcher( +SafeBrowsingPrimaryAccountTokenFetcher::SafeBrowsingPrimaryAccountTokenFetcher( signin::IdentityManager* identity_manager) : identity_manager_(identity_manager), requests_sent_(0), @@ -41,54 +41,56 @@ DCHECK(CurrentlyOnThread(ThreadID::UI)); } -SafeBrowsingTokenFetcher::~SafeBrowsingTokenFetcher() { +SafeBrowsingPrimaryAccountTokenFetcher:: + ~SafeBrowsingPrimaryAccountTokenFetcher() { for (auto& id_and_callback : callbacks_) { - std::move(id_and_callback.second).Run(base::nullopt); + std::move(id_and_callback.second).Run(std::string()); } } -void SafeBrowsingTokenFetcher::Start(signin::ConsentLevel consent_level, - Callback callback) { +void SafeBrowsingPrimaryAccountTokenFetcher::Start( + Callback callback) { DCHECK(CurrentlyOnThread(ThreadID::UI)); const int request_id = requests_sent_; requests_sent_++; - CoreAccountId account_id = - identity_manager_->GetPrimaryAccountId(consent_level); + CoreAccountId account_id = identity_manager_->GetPrimaryAccountId( + signin::ConsentLevel::kNotRequired); callbacks_[request_id] = std::move(callback); token_fetchers_[request_id] = identity_manager_->CreateAccessTokenFetcherForAccount( account_id, "safe_browsing_service", {kAPIScope}, - base::BindOnce(&SafeBrowsingTokenFetcher::OnTokenFetched, - weak_ptr_factory_.GetWeakPtr(), request_id), + base::BindOnce( + &SafeBrowsingPrimaryAccountTokenFetcher::OnTokenFetched, + weak_ptr_factory_.GetWeakPtr(), request_id), signin::AccessTokenFetcher::Mode::kImmediate); base::PostDelayedTask( FROM_HERE, CreateTaskTraits(ThreadID::UI), - base::BindOnce(&SafeBrowsingTokenFetcher::OnTokenTimeout, + base::BindOnce(&SafeBrowsingPrimaryAccountTokenFetcher::OnTokenTimeout, weak_ptr_factory_.GetWeakPtr(), request_id), base::TimeDelta::FromMilliseconds(kTimeoutDelayFromMilliseconds)); } -void SafeBrowsingTokenFetcher::OnTokenFetched( +void SafeBrowsingPrimaryAccountTokenFetcher::OnTokenFetched( int request_id, GoogleServiceAuthError error, signin::AccessTokenInfo access_token_info) { UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.TokenFetcher.ErrorType", error.state(), GoogleServiceAuthError::NUM_STATES); if (error.state() == GoogleServiceAuthError::NONE) - Finish(request_id, access_token_info); + Finish(request_id, access_token_info.token); else - Finish(request_id, base::nullopt); + Finish(request_id, std::string()); } -void SafeBrowsingTokenFetcher::OnTokenTimeout(int request_id) { - Finish(request_id, base::nullopt); +void SafeBrowsingPrimaryAccountTokenFetcher::OnTokenTimeout(int request_id) { + Finish(request_id, std::string()); } -void SafeBrowsingTokenFetcher::Finish( +void SafeBrowsingPrimaryAccountTokenFetcher::Finish( int request_id, - base::Optional<signin::AccessTokenInfo> token_info) { + const std::string& access_token) { if (callbacks_.contains(request_id)) { - std::move(callbacks_[request_id]).Run(token_info); + std::move(callbacks_[request_id]).Run(access_token); } token_fetchers_.erase(request_id);
diff --git a/components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher.h b/components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher.h new file mode 100644 index 0000000..8aebacd --- /dev/null +++ b/components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher.h
@@ -0,0 +1,64 @@ +// Copyright 2021 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_SAFE_BROWSING_CORE_BROWSER_SYNC_SAFE_BROWSING_PRIMARY_ACCOUNT_TOKEN_FETCHER_H_ +#define COMPONENTS_SAFE_BROWSING_CORE_BROWSER_SYNC_SAFE_BROWSING_PRIMARY_ACCOUNT_TOKEN_FETCHER_H_ + +#include <memory> + +#include "base/containers/flat_map.h" +#include "base/memory/weak_ptr.h" +#include "components/safe_browsing/core/browser/safe_browsing_token_fetcher.h" +#include "components/signin/public/identity_manager/access_token_info.h" +#include "google_apis/gaia/google_service_auth_error.h" + +namespace signin { +class AccessTokenFetcher; +class IdentityManager; +} // namespace signin + +namespace safe_browsing { + +// This class fetches access tokens for Safe Browsing for the current +// primary account. +class SafeBrowsingPrimaryAccountTokenFetcher : public SafeBrowsingTokenFetcher { + public: + // Create a SafeBrowsingPrimaryAccountTokenFetcher for the primary account of + // |identity_manager|. |identity_manager| is unowned, and must outlive this + // object. + explicit SafeBrowsingPrimaryAccountTokenFetcher( + signin::IdentityManager* identity_manager); + + ~SafeBrowsingPrimaryAccountTokenFetcher() override; + + // SafeBrowsingTokenFetcher: + void Start(Callback callback) override; + + private: + void OnTokenFetched(int request_id, + GoogleServiceAuthError error, + signin::AccessTokenInfo access_token_info); + void OnTokenTimeout(int request_id); + void Finish(int request_id, const std::string& access_token); + + // Reference to the identity manager to fetch from. + signin::IdentityManager* identity_manager_; + + // The count of requests sent. This is used as an ID for requests. + int requests_sent_; + + // Active fetchers, keyed by ID. + base::flat_map<int, std::unique_ptr<signin::AccessTokenFetcher>> + token_fetchers_; + + // Active callbacks, keyed by ID. + base::flat_map<int, Callback> callbacks_; + + base::WeakPtrFactory<SafeBrowsingPrimaryAccountTokenFetcher> + weak_ptr_factory_; +}; + +} // namespace safe_browsing + +#endif // COMPONENTS_SAFE_BROWSING_CORE_BROWSER_SYNC_SAFE_BROWSING_PRIMARY_ACCOUNT_TOKEN_FETCHER_H_
diff --git a/components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher_unittest.cc b/components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher_unittest.cc new file mode 100644 index 0000000..bf8418b0 --- /dev/null +++ b/components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher_unittest.cc
@@ -0,0 +1,74 @@ +// Copyright 2020 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/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher.h" +#include <memory> + +#include "base/run_loop.h" +#include "base/test/task_environment.h" +#include "components/safe_browsing/core/common/test_task_environment.h" +#include "components/signin/public/identity_manager/identity_test_environment.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace safe_browsing { + +class SafeBrowsingPrimaryAccountTokenFetcherTest : public ::testing::Test { + public: + SafeBrowsingPrimaryAccountTokenFetcherTest() + : task_environment_(CreateTestTaskEnvironment()) {} + + protected: + std::unique_ptr<base::test::TaskEnvironment> task_environment_; + signin::IdentityTestEnvironment identity_test_environment_; +}; + +TEST_F(SafeBrowsingPrimaryAccountTokenFetcherTest, Success) { + identity_test_environment_.MakeUnconsentedPrimaryAccountAvailable( + "test@example.com"); + std::string access_token; + SafeBrowsingPrimaryAccountTokenFetcher fetcher( + identity_test_environment_.identity_manager()); + fetcher.Start( + base::BindOnce([](std::string* target_token, + const std::string& token) { *target_token = token; }, + &access_token)); + identity_test_environment_ + .WaitForAccessTokenRequestIfNecessaryAndRespondWithToken( + "token", base::Time::Now()); + EXPECT_EQ(access_token, "token"); +} + +TEST_F(SafeBrowsingPrimaryAccountTokenFetcherTest, Failure) { + identity_test_environment_.MakeUnconsentedPrimaryAccountAvailable( + "test@example.com"); + std::string access_token; + SafeBrowsingPrimaryAccountTokenFetcher fetcher( + identity_test_environment_.identity_manager()); + fetcher.Start( + base::BindOnce([](std::string* target_token, + const std::string& token) { *target_token = token; }, + &access_token)); + identity_test_environment_ + .WaitForAccessTokenRequestIfNecessaryAndRespondWithError( + GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED)); + ASSERT_TRUE(access_token.empty()); +} + +TEST_F(SafeBrowsingPrimaryAccountTokenFetcherTest, + SuccessWithConsentedPrimaryAccount) { + identity_test_environment_.MakePrimaryAccountAvailable("test@example.com"); + std::string access_token; + SafeBrowsingPrimaryAccountTokenFetcher fetcher( + identity_test_environment_.identity_manager()); + fetcher.Start( + base::BindOnce([](std::string* target_token, + const std::string& token) { *target_token = token; }, + &access_token)); + identity_test_environment_ + .WaitForAccessTokenRequestIfNecessaryAndRespondWithToken( + "token", base::Time::Now()); + EXPECT_EQ(access_token, "token"); +} + +} // namespace safe_browsing
diff --git a/components/safe_browsing/core/realtime/BUILD.gn b/components/safe_browsing/core/realtime/BUILD.gn index 1a0aa02..f600bd8c 100644 --- a/components/safe_browsing/core/realtime/BUILD.gn +++ b/components/safe_browsing/core/realtime/BUILD.gn
@@ -38,7 +38,7 @@ "//components/safe_browsing/core:csd_proto", "//components/safe_browsing/core:realtimeapi_proto", "//components/safe_browsing/core:verdict_cache_manager", - "//components/safe_browsing/core/browser:token_fetcher", + "//components/safe_browsing/core/browser/sync", "//components/safe_browsing/core/common:safe_browsing_prefs", "//components/safe_browsing/core/common:thread_utils", "//components/safe_browsing/core/db:v4_protocol_manager_util",
diff --git a/components/safe_browsing/core/realtime/url_lookup_service.cc b/components/safe_browsing/core/realtime/url_lookup_service.cc index 6d0851c..1c796a7 100644 --- a/components/safe_browsing/core/realtime/url_lookup_service.cc +++ b/components/safe_browsing/core/realtime/url_lookup_service.cc
@@ -13,7 +13,7 @@ #include "base/time/time.h" #include "components/prefs/pref_service.h" #include "components/safe_browsing/buildflags.h" -#include "components/safe_browsing/core/browser/safe_browsing_token_fetcher.h" +#include "components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher.h" #include "components/safe_browsing/core/common/safe_browsing_prefs.h" #include "components/safe_browsing/core/common/thread_utils.h" #include "components/safe_browsing/core/db/v4_protocol_manager_util.h" @@ -54,8 +54,8 @@ pref_service_(pref_service), is_off_the_record_(is_off_the_record), variations_(variations_service) { - token_fetcher_ = - std::make_unique<SafeBrowsingTokenFetcher>(identity_manager_); + token_fetcher_ = std::make_unique<SafeBrowsingPrimaryAccountTokenFetcher>( + identity_manager_); } void RealTimeUrlLookupService::GetAccessToken( @@ -63,7 +63,6 @@ RTLookupRequestCallback request_callback, RTLookupResponseCallback response_callback) { token_fetcher_->Start( - signin::ConsentLevel::kNotRequired, base::BindOnce(&RealTimeUrlLookupService::OnGetAccessToken, weak_factory_.GetWeakPtr(), url, std::move(request_callback), std::move(response_callback), @@ -75,14 +74,12 @@ RTLookupRequestCallback request_callback, RTLookupResponseCallback response_callback, base::TimeTicks get_token_start_time, - base::Optional<signin::AccessTokenInfo> access_token_info) { + const std::string& access_token) { base::UmaHistogramTimes("SafeBrowsing.RT.GetToken.Time", base::TimeTicks::Now() - get_token_start_time); base::UmaHistogramBoolean("SafeBrowsing.RT.HasTokenFromFetcher", - access_token_info.has_value()); - std::string access_token_string = - access_token_info.value_or(signin::AccessTokenInfo()).token; - SendRequest(url, access_token_string, std::move(request_callback), + !access_token.empty()); + SendRequest(url, access_token, std::move(request_callback), std::move(response_callback)); }
diff --git a/components/safe_browsing/core/realtime/url_lookup_service.h b/components/safe_browsing/core/realtime/url_lookup_service.h index 5f4de4d..2eebf4a 100644 --- a/components/safe_browsing/core/realtime/url_lookup_service.h +++ b/components/safe_browsing/core/realtime/url_lookup_service.h
@@ -84,12 +84,11 @@ bool ShouldIncludeCredentials() const override; // Called when the access token is obtained from |token_fetcher_|. - void OnGetAccessToken( - const GURL& url, - RTLookupRequestCallback request_callback, - RTLookupResponseCallback response_callback, - base::TimeTicks get_token_start_time, - base::Optional<signin::AccessTokenInfo> access_token_info); + void OnGetAccessToken(const GURL& url, + RTLookupRequestCallback request_callback, + RTLookupResponseCallback response_callback, + base::TimeTicks get_token_start_time, + const std::string& access_token); // Unowned object used for getting access token when real time url check with // token is enabled.
diff --git a/components/services/storage/dom_storage/session_storage_impl.cc b/components/services/storage/dom_storage/session_storage_impl.cc index 5238f8e..40e8a56 100644 --- a/components/services/storage/dom_storage/session_storage_impl.cc +++ b/components/services/storage/dom_storage/session_storage_impl.cc
@@ -995,19 +995,21 @@ std::move(callbacks[i]).Run(); } +void SessionStorageImpl::PurgeAllNamespaces() { + for (const auto& it : data_maps_) + it.second->storage_area()->CancelAllPendingRequests(); + for (const auto& namespace_pair : namespaces_) + namespace_pair.second->Reset(); + DCHECK(data_maps_.empty()); +} + void SessionStorageImpl::DeleteAndRecreateDatabase(const char* histogram_name) { if (connection_state_ == CONNECTION_SHUTDOWN) return; // We're about to set database_ to null, so delete the StorageAreas // that might still be using the old database. - for (const auto& it : data_maps_) - it.second->storage_area()->CancelAllPendingRequests(); - - for (const auto& namespace_pair : namespaces_) { - namespace_pair.second->Reset(); - } - DCHECK(data_maps_.empty()); + PurgeAllNamespaces(); // Reset state to be in process of connecting. This will cause requests for // StorageAreas to be queued until the connection is complete. @@ -1059,6 +1061,7 @@ void SessionStorageImpl::OnShutdownComplete() { DCHECK(shutdown_complete_callback_); // Flush any final tasks on the DB task runner before invoking the callback. + PurgeAllNamespaces(); database_.reset(); leveldb_task_runner_->PostTaskAndReply( FROM_HERE, base::DoNothing(), std::move(shutdown_complete_callback_));
diff --git a/components/services/storage/dom_storage/session_storage_impl.h b/components/services/storage/dom_storage/session_storage_impl.h index 4d2cb96..206ddae 100644 --- a/components/services/storage/dom_storage/session_storage_impl.h +++ b/components/services/storage/dom_storage/session_storage_impl.h
@@ -221,6 +221,7 @@ MetadataParseResult ParseNextMapId(ValueAndStatus next_map_id); void OnConnectionFinished(); + void PurgeAllNamespaces(); void DeleteAndRecreateDatabase(const char* histogram_name); void OnDBDestroyed(bool recreate_in_memory, leveldb::Status status);
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacade.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacade.java index afcaf9a..e847b80 100644 --- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacade.java +++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacade.java
@@ -24,6 +24,16 @@ */ public interface AccountManagerFacade { /** + * Listener for {@link ChildAccountStatus.Status}. + */ + interface ChildAccountStatusListener { + /** + * The method is called when child account status is ready. + */ + void onStatusReady(@ChildAccountStatus.Status int status); + } + + /** * Adds an observer to receive accounts change notifications. * @param observer the observer to add. */ @@ -118,13 +128,13 @@ void invalidateAccessToken(String accessToken) throws AuthException; /** - * Checks the child account status in background. + * Checks the child account status of the given account. * - * @param account The account to check the child account status - * @param callback The callback takes the ChildAccountStatus.Status as argument + * @param account The account to check the child account status. + * @param listener The listener is called when the {@link ChildAccountStatus.Status} is ready. */ @MainThread - void checkChildAccountStatus(Account account, Callback<Integer> callback); + void checkChildAccountStatus(Account account, ChildAccountStatusListener listener); /** * Creates an intent that will ask the user to add a new account to the device. See
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacadeImpl.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacadeImpl.java index 59163fa..2c8b62a 100644 --- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacadeImpl.java +++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacadeImpl.java
@@ -221,7 +221,7 @@ // overriding. @SuppressWarnings("WrongThread") @Override - public void checkChildAccountStatus(Account account, Callback<Integer> callback) { + public void checkChildAccountStatus(Account account, ChildAccountStatusListener listener) { ThreadUtils.assertOnUiThread(); new AsyncTask<Integer>() { @Override @@ -236,8 +236,8 @@ } @Override - public void onPostExecute(@ChildAccountStatus.Status Integer value) { - callback.onResult(value); + public void onPostExecute(@ChildAccountStatus.Status Integer status) { + listener.onStatusReady(status); } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); }
diff --git a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerFacade.java b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerFacade.java index 82f4cb7..116bd424 100644 --- a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerFacade.java +++ b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerFacade.java
@@ -127,7 +127,7 @@ } @Override - public void checkChildAccountStatus(Account account, Callback<Integer> callback) {} + public void checkChildAccountStatus(Account account, ChildAccountStatusListener listener) {} @Override public void createAddAccountIntent(Callback<Intent> callback) {}
diff --git a/components/signin/core/browser/android/junit/src/org/chromium/components/signin/test/AccountManagerFacadeRobolectricTest.java b/components/signin/core/browser/android/junit/src/org/chromium/components/signin/test/AccountManagerFacadeRobolectricTest.java index f5f0b7f..c946d08 100644 --- a/components/signin/core/browser/android/junit/src/org/chromium/components/signin/test/AccountManagerFacadeRobolectricTest.java +++ b/components/signin/core/browser/android/junit/src/org/chromium/components/signin/test/AccountManagerFacadeRobolectricTest.java
@@ -271,8 +271,7 @@ mDelegate.removeAccountHolderExplicitly(AccountHolder.builder(account).build()); } - private void assertChildAccountStatus( - Account account, @ChildAccountStatus.Status Integer status) { + private void assertChildAccountStatus(Account account, @ChildAccountStatus.Status int status) { final AtomicInteger callCount = new AtomicInteger(); mFacade.checkChildAccountStatus(account, result -> { callCount.incrementAndGet();
diff --git a/components/signin/internal/identity_manager/primary_account_manager.cc b/components/signin/internal/identity_manager/primary_account_manager.cc index a3f3a572..7b95c04 100644 --- a/components/signin/internal/identity_manager/primary_account_manager.cc +++ b/components/signin/internal/identity_manager/primary_account_manager.cc
@@ -328,7 +328,6 @@ if (primary_account_info().IsEmpty()) { return; } - // TODO(crbug.com/887756): Consider moving this higher up, or document why // the above blocks are exempt from the |signout_decision| early return. if (signout_decision == SigninClient::SignoutDecision::DISALLOW_SIGNOUT) { @@ -351,6 +350,12 @@ kPrimaryAccountManager_ClearAccount); break; case RemoveAccountsOption::kKeepAllAccounts: + if (previous_state.consent_level == signin::ConsentLevel::kNotRequired) { + // Nothing to update as the primary account is already at kNotRequired + // consent level. Prefer returning to avoid firing useless + // OnPrimaryAccountChanged() notifications. + return; + } SetPrimaryAccountInternal(primary_account_info(), /*consented_to_sync=*/false); break;
diff --git a/components/signin/internal/identity_manager/primary_account_manager_unittest.cc b/components/signin/internal/identity_manager/primary_account_manager_unittest.cc index 89a4638..f067f52 100644 --- a/components/signin/internal/identity_manager/primary_account_manager_unittest.cc +++ b/components/signin/internal/identity_manager/primary_account_manager_unittest.cc
@@ -43,9 +43,7 @@ : test_signin_client_(&user_prefs_), token_service_( &user_prefs_, - std::make_unique<FakeProfileOAuth2TokenServiceDelegate>()), - num_successful_signins_(0), - num_unconsented_account_changed_(0) { + std::make_unique<FakeProfileOAuth2TokenServiceDelegate>()) { AccountFetcherService::RegisterPrefs(user_prefs_.registry()); AccountTrackerService::RegisterPrefs(user_prefs_.registry()); ProfileOAuth2TokenService::RegisterProfilePrefs(user_prefs_.registry()); @@ -135,7 +133,7 @@ num_successful_signins_++; break; case signin::PrimaryAccountChangeEvent::Type::kCleared: - // ignored + num_successful_signouts_++; break; case signin::PrimaryAccountChangeEvent::Type::kNone: break; @@ -163,8 +161,9 @@ std::unique_ptr<PrimaryAccountManager> manager_; std::vector<std::string> oauth_tokens_fetched_; std::vector<std::string> cookies_; - int num_successful_signins_; - int num_unconsented_account_changed_; + int num_successful_signins_{0}; + int num_successful_signouts_{0}; + int num_unconsented_account_changed_{0}; }; #if !BUILDFLAG(IS_CHROMEOS_ASH) @@ -176,6 +175,7 @@ account_tracker()->GetAccountInfo(main_account_id)); manager_->ClearPrimaryAccount(signin_metrics::SIGNOUT_TEST, signin_metrics::SignoutDelete::IGNORE_METRIC); + EXPECT_EQ(1, num_successful_signouts_); EXPECT_FALSE(manager_->HasPrimaryAccount(ConsentLevel::kSync)); EXPECT_TRUE( manager_->GetPrimaryAccountInfo(ConsentLevel::kSync).email.empty()); @@ -211,6 +211,7 @@ signin_metrics::SignoutDelete::IGNORE_METRIC); // Tokens are revoked. + EXPECT_EQ(1, num_successful_signouts_); EXPECT_FALSE(manager_->HasPrimaryAccount(ConsentLevel::kSync)); EXPECT_TRUE(token_service_.GetAccounts().empty()); } @@ -229,10 +230,12 @@ signin_client()->set_is_signout_allowed(false); manager_->ClearPrimaryAccount(signin_metrics::SIGNOUT_TEST, signin_metrics::SignoutDelete::IGNORE_METRIC); + EXPECT_EQ(0, num_successful_signouts_); EXPECT_TRUE(manager_->HasPrimaryAccount(ConsentLevel::kSync)); signin_client()->set_is_signout_allowed(true); manager_->ClearPrimaryAccount(signin_metrics::SIGNOUT_TEST, signin_metrics::SignoutDelete::IGNORE_METRIC); + EXPECT_EQ(1, num_successful_signouts_); EXPECT_FALSE(manager_->HasPrimaryAccount(ConsentLevel::kSync)); } @@ -282,6 +285,26 @@ } #endif +// Regression test for https://crbug.com/1155519. +TEST_F(PrimaryAccountManagerTest, NoopSignOutDoesNotNotifyObservers) { + CreatePrimaryAccountManager(); + EXPECT_FALSE(manager_->HasPrimaryAccount(ConsentLevel::kSync)); + + CoreAccountId account_id = AddToAccountTracker("gaia_id", "user@gmail.com"); + CoreAccountInfo account_info = account_tracker()->GetAccountInfo(account_id); + manager_->SetUnconsentedPrimaryAccountInfo(account_info); + EXPECT_EQ(1, num_unconsented_account_changed_); + EXPECT_TRUE(manager_->HasPrimaryAccount(ConsentLevel::kNotRequired)); + EXPECT_FALSE(manager_->HasPrimaryAccount(ConsentLevel::kSync)); + + manager_->RevokeSyncConsent(signin_metrics::SIGNOUT_TEST, + signin_metrics::SignoutDelete::IGNORE_METRIC); + + // Since there was no sync consent, observers shouldn't be notified. + EXPECT_EQ(0, num_successful_signouts_); + EXPECT_EQ(1, num_unconsented_account_changed_); +} + TEST_F(PrimaryAccountManagerTest, SignIn) { CreatePrimaryAccountManager(); EXPECT_EQ("", manager_->GetPrimaryAccountInfo(ConsentLevel::kSync).email); @@ -472,6 +495,7 @@ account_info.email = "user@gmail.com"; manager_->SetUnconsentedPrimaryAccountInfo(account_info); EXPECT_EQ(0, num_successful_signins_); + EXPECT_EQ(0, num_successful_signouts_); EXPECT_EQ(1, num_unconsented_account_changed_); EXPECT_EQ(account_info, manager_->GetPrimaryAccountInfo(ConsentLevel::kNotRequired)); @@ -481,6 +505,7 @@ // Set the same account again. manager_->SetUnconsentedPrimaryAccountInfo(account_info); EXPECT_EQ(0, num_successful_signins_); + EXPECT_EQ(0, num_successful_signouts_); EXPECT_EQ(1, num_unconsented_account_changed_); EXPECT_EQ(account_info, manager_->GetPrimaryAccountInfo(ConsentLevel::kNotRequired)); @@ -492,6 +517,7 @@ account_info.email = "us.er@gmail.com"; manager_->SetUnconsentedPrimaryAccountInfo(account_info); EXPECT_EQ(0, num_successful_signins_); + EXPECT_EQ(0, num_successful_signouts_); EXPECT_EQ(1, num_unconsented_account_changed_); EXPECT_EQ(account_info, manager_->GetPrimaryAccountInfo(ConsentLevel::kNotRequired)); @@ -501,6 +527,7 @@ // Clear it. manager_->SetUnconsentedPrimaryAccountInfo(CoreAccountInfo()); EXPECT_EQ(0, num_successful_signins_); + EXPECT_EQ(0, num_successful_signouts_); EXPECT_EQ(2, num_unconsented_account_changed_); EXPECT_EQ(CoreAccountInfo(), manager_->GetPrimaryAccountInfo(ConsentLevel::kNotRequired)); @@ -517,6 +544,7 @@ manager_->RevokeSyncConsent(signin_metrics::ProfileSignout::SIGNOUT_TEST, signin_metrics::SignoutDelete::IGNORE_METRIC); + EXPECT_EQ(1, num_successful_signouts_); EXPECT_FALSE(manager_->HasPrimaryAccount(ConsentLevel::kSync)); EXPECT_TRUE(manager_->HasPrimaryAccount(ConsentLevel::kNotRequired)); EXPECT_EQ( @@ -534,6 +562,7 @@ manager_->ClearPrimaryAccount(signin_metrics::ProfileSignout::SIGNOUT_TEST, signin_metrics::SignoutDelete::IGNORE_METRIC); + EXPECT_EQ(1, num_successful_signouts_); EXPECT_FALSE(manager_->HasPrimaryAccount(ConsentLevel::kSync)); EXPECT_FALSE(manager_->HasPrimaryAccount(ConsentLevel::kNotRequired)); }
diff --git a/components/signin/public/android/java/src/org/chromium/components/signin/base/AccountInfo.java b/components/signin/public/android/java/src/org/chromium/components/signin/base/AccountInfo.java index 87b5b5f..aa6fab7 100644 --- a/components/signin/public/android/java/src/org/chromium/components/signin/base/AccountInfo.java +++ b/components/signin/public/android/java/src/org/chromium/components/signin/base/AccountInfo.java
@@ -17,17 +17,35 @@ * This class has a native counterpart called AccountInfo. */ public class AccountInfo extends CoreAccountInfo { + private final String mFullName; + private final String mGivenName; private final @Nullable Bitmap mAccountImage; @VisibleForTesting @CalledByNative - public AccountInfo( - CoreAccountId id, String email, String gaiaId, @Nullable Bitmap accountImage) { + public AccountInfo(CoreAccountId id, String email, String gaiaId, String fullName, + String givenName, @Nullable Bitmap accountImage) { super(id, email, gaiaId); + mFullName = fullName; + mGivenName = givenName; mAccountImage = accountImage; } /** + * @return Full name of the account. + */ + public String getFullName() { + return mFullName; + } + + /** + * @return Given name of the account. + */ + public String getGivenName() { + return mGivenName; + } + + /** * Gets the account's image. * It can be the image user uploaded, monogram or null. */
diff --git a/components/signin/public/identity_manager/account_info.cc b/components/signin/public/identity_manager/account_info.cc index 3ee85a7..9f6f24dc 100644 --- a/components/signin/public/identity_manager/account_info.cc +++ b/components/signin/public/identity_manager/account_info.cc
@@ -157,6 +157,8 @@ env, ConvertToJavaCoreAccountId(env, account_info.account_id), base::android::ConvertUTF8ToJavaString(env, account_info.email), base::android::ConvertUTF8ToJavaString(env, account_info.gaia), + base::android::ConvertUTF8ToJavaString(env, account_info.full_name), + base::android::ConvertUTF8ToJavaString(env, account_info.given_name), avatar_image.IsEmpty() ? nullptr : gfx::ConvertToJavaBitmap(*avatar_image.AsImageSkia().bitmap()));
diff --git a/components/signin/public/identity_manager/primary_account_access_token_fetcher.cc b/components/signin/public/identity_manager/primary_account_access_token_fetcher.cc index e96ecfc9..df2d6e02 100644 --- a/components/signin/public/identity_manager/primary_account_access_token_fetcher.cc +++ b/components/signin/public/identity_manager/primary_account_access_token_fetcher.cc
@@ -77,25 +77,15 @@ AccessTokenFetcher::Mode::kImmediate); } -void PrimaryAccountAccessTokenFetcher::OnPrimaryAccountSet( - const CoreAccountInfo& primary_account_info) { - // When sync consent is not required the signin is handled in - // OnUnconsentedPrimaryAccountChanged() below. - if (consent_ == ConsentLevel::kNotRequired) +void PrimaryAccountAccessTokenFetcher::OnPrimaryAccountChanged( + const PrimaryAccountChangeEvent& event) { + // We're only interested when the account is set for the |consent_| + // consent level. + if (event.GetEventTypeFor(consent_) != + PrimaryAccountChangeEvent::Type::kSet) { return; - DCHECK(!primary_account_info.account_id.empty()); - ProcessSigninStateChange(); -} - -void PrimaryAccountAccessTokenFetcher::OnUnconsentedPrimaryAccountChanged( - const CoreAccountInfo& primary_account_info) { - // This method is called after both SetPrimaryAccount and - // SetUnconsentedPrimaryAccount. - if (consent_ == ConsentLevel::kSync) - return; - // We're only interested when the account is set. - if (primary_account_info.account_id.empty()) - return; + } + DCHECK(!event.GetCurrentState().primary_account.account_id.empty()); ProcessSigninStateChange(); }
diff --git a/components/signin/public/identity_manager/primary_account_access_token_fetcher.h b/components/signin/public/identity_manager/primary_account_access_token_fetcher.h index 36d37f9..e982fa4 100644 --- a/components/signin/public/identity_manager/primary_account_access_token_fetcher.h +++ b/components/signin/public/identity_manager/primary_account_access_token_fetcher.h
@@ -177,10 +177,7 @@ void StartAccessTokenRequest(); // IdentityManager::Observer implementation. - void OnPrimaryAccountSet( - const CoreAccountInfo& primary_account_info) override; - void OnUnconsentedPrimaryAccountChanged( - const CoreAccountInfo& primary_account_info) override; + void OnPrimaryAccountChanged(const PrimaryAccountChangeEvent& event) override; void OnRefreshTokenUpdatedForAccount( const CoreAccountInfo& account_info) override;
diff --git a/components/signin/public/identity_manager/test_identity_manager_observer.cc b/components/signin/public/identity_manager/test_identity_manager_observer.cc index afa01cb..6fcdd672 100644 --- a/components/signin/public/identity_manager/test_identity_manager_observer.cc +++ b/components/signin/public/identity_manager/test_identity_manager_observer.cc
@@ -133,25 +133,38 @@ } // IdentityManager::Observer: -void TestIdentityManagerObserver::OnPrimaryAccountSet( - const CoreAccountInfo& primary_account_info) { - primary_account_from_set_callback_ = primary_account_info; - if (on_primary_account_set_callback_) - std::move(on_primary_account_set_callback_).Run(); -} - -void TestIdentityManagerObserver::OnPrimaryAccountCleared( - const CoreAccountInfo& previous_primary_account_info) { - primary_account_from_cleared_callback_ = previous_primary_account_info; - if (on_primary_account_cleared_callback_) - std::move(on_primary_account_cleared_callback_).Run(); -} - -void TestIdentityManagerObserver::OnUnconsentedPrimaryAccountChanged( - const CoreAccountInfo& unconsented_primary_account_info) { - unconsented_primary_account_from_callback_ = unconsented_primary_account_info; - if (on_unconsented_primary_account_callback_) - std::move(on_unconsented_primary_account_callback_).Run(); +void TestIdentityManagerObserver::OnPrimaryAccountChanged( + const PrimaryAccountChangeEvent& event) { + // TODO(https://crbug.com/1158855): Refactor this test observer to + // have a single on_primary_account_changed_callback_ and a single + // on_primary_account_changed_event_. + switch (event.GetEventTypeFor(ConsentLevel::kNotRequired)) { + case PrimaryAccountChangeEvent::Type::kSet: + case PrimaryAccountChangeEvent::Type::kCleared: + unconsented_primary_account_from_callback_ = + event.GetCurrentState().primary_account; + if (on_unconsented_primary_account_callback_) + std::move(on_unconsented_primary_account_callback_).Run(); + break; + case PrimaryAccountChangeEvent::Type::kNone: + break; + } + switch (event.GetEventTypeFor(ConsentLevel::kSync)) { + case PrimaryAccountChangeEvent::Type::kSet: + primary_account_from_set_callback_ = + event.GetCurrentState().primary_account; + if (on_primary_account_set_callback_) + std::move(on_primary_account_set_callback_).Run(); + break; + case PrimaryAccountChangeEvent::Type::kCleared: + primary_account_from_cleared_callback_ = + event.GetPreviousState().primary_account; + if (on_primary_account_cleared_callback_) + std::move(on_primary_account_cleared_callback_).Run(); + break; + case PrimaryAccountChangeEvent::Type::kNone: + break; + } } void TestIdentityManagerObserver::OnRefreshTokenUpdatedForAccount(
diff --git a/components/signin/public/identity_manager/test_identity_manager_observer.h b/components/signin/public/identity_manager/test_identity_manager_observer.h index 506e246..91479fe 100644 --- a/components/signin/public/identity_manager/test_identity_manager_observer.h +++ b/components/signin/public/identity_manager/test_identity_manager_observer.h
@@ -64,12 +64,8 @@ private: // IdentityManager::Observer: - void OnPrimaryAccountSet( - const CoreAccountInfo& primary_account_info) override; - void OnPrimaryAccountCleared( - const CoreAccountInfo& previous_primary_account_info) override; - void OnUnconsentedPrimaryAccountChanged( - const CoreAccountInfo& unconsented_primary_account_info) override; + void OnPrimaryAccountChanged( + const PrimaryAccountChangeEvent& event_details) override; void OnRefreshTokenUpdatedForAccount( const CoreAccountInfo& account_info) override; void OnRefreshTokenRemovedForAccount(
diff --git a/components/sync/protocol/proto_visitors.h b/components/sync/protocol/proto_visitors.h index c03cda90..4b5da2b 100644 --- a/components/sync/protocol/proto_visitors.h +++ b/components/sync/protocol/proto_visitors.h
@@ -818,6 +818,8 @@ VISIT(navigation_time_usec); VISIT(device_name); VISIT(target_device_sync_cache_guid); + VISIT(opened); + VISIT(notification_dismissed); } VISIT_PROTO_FIELDS(const sync_pb::SessionHeader& proto) {
diff --git a/components/sync/trusted_vault/standalone_trusted_vault_client.cc b/components/sync/trusted_vault/standalone_trusted_vault_client.cc index f49bb8c..98a8eda 100644 --- a/components/sync/trusted_vault/standalone_trusted_vault_client.cc +++ b/components/sync/trusted_vault/standalone_trusted_vault_client.cc
@@ -54,12 +54,8 @@ ~PrimaryAccountObserver() override; // signin::IdentityManager::Observer implementation. - void OnPrimaryAccountSet( - const CoreAccountInfo& primary_account_info) override; - void OnPrimaryAccountCleared( - const CoreAccountInfo& previous_primary_account_info) override; - void OnUnconsentedPrimaryAccountChanged( - const CoreAccountInfo& unconsented_primary_account_info) override; + void OnPrimaryAccountChanged( + const signin::PrimaryAccountChangeEvent& event) override; private: void UpdatePrimaryAccountIfNeeded(); @@ -89,18 +85,8 @@ identity_manager_->RemoveObserver(this); } -void PrimaryAccountObserver::OnPrimaryAccountSet( - const CoreAccountInfo& primary_account_info) { - UpdatePrimaryAccountIfNeeded(); -} - -void PrimaryAccountObserver::OnPrimaryAccountCleared( - const CoreAccountInfo& previous_primary_account_info) { - UpdatePrimaryAccountIfNeeded(); -} - -void PrimaryAccountObserver::OnUnconsentedPrimaryAccountChanged( - const CoreAccountInfo& unconsented_primary_account_info) { +void PrimaryAccountObserver::OnPrimaryAccountChanged( + const signin::PrimaryAccountChangeEvent& event) { UpdatePrimaryAccountIfNeeded(); }
diff --git a/components/sync/trusted_vault/trusted_vault_access_token_fetcher_frontend.cc b/components/sync/trusted_vault/trusted_vault_access_token_fetcher_frontend.cc index 96f7f619..3a329d8ed 100644 --- a/components/sync/trusted_vault/trusted_vault_access_token_fetcher_frontend.cc +++ b/components/sync/trusted_vault/trusted_vault_access_token_fetcher_frontend.cc
@@ -50,18 +50,8 @@ } } -void TrustedVaultAccessTokenFetcherFrontend::OnPrimaryAccountSet( - const CoreAccountInfo& primary_account_info) { - UpdatePrimaryAccountIfNeeded(); -} - -void TrustedVaultAccessTokenFetcherFrontend::OnPrimaryAccountCleared( - const CoreAccountInfo& previous_primary_account_info) { - UpdatePrimaryAccountIfNeeded(); -} - -void TrustedVaultAccessTokenFetcherFrontend::OnUnconsentedPrimaryAccountChanged( - const CoreAccountInfo& unconsented_primary_account_info) { +void TrustedVaultAccessTokenFetcherFrontend::OnPrimaryAccountChanged( + const signin::PrimaryAccountChangeEvent& event) { UpdatePrimaryAccountIfNeeded(); }
diff --git a/components/sync/trusted_vault/trusted_vault_access_token_fetcher_frontend.h b/components/sync/trusted_vault/trusted_vault_access_token_fetcher_frontend.h index b0e0b25..7f882be7 100644 --- a/components/sync/trusted_vault/trusted_vault_access_token_fetcher_frontend.h +++ b/components/sync/trusted_vault/trusted_vault_access_token_fetcher_frontend.h
@@ -46,12 +46,8 @@ TrustedVaultAccessTokenFetcher::TokenCallback callback); // signin::IdentityManager::Observer implementation. - void OnPrimaryAccountSet( - const CoreAccountInfo& primary_account_info) override; - void OnPrimaryAccountCleared( - const CoreAccountInfo& previous_primary_account_info) override; - void OnUnconsentedPrimaryAccountChanged( - const CoreAccountInfo& unconsented_primary_account_info) override; + void OnPrimaryAccountChanged( + const signin::PrimaryAccountChangeEvent& event) override; private: // Updates |primary_account_| and runs |pending_requests_| in case
diff --git a/components/tracing/common/trace_startup_config.cc b/components/tracing/common/trace_startup_config.cc index 59c1e6e..e9d0e43 100644 --- a/components/tracing/common/trace_startup_config.cc +++ b/components/tracing/common/trace_startup_config.cc
@@ -90,11 +90,11 @@ DCHECK(IsEnabled()); DCHECK(!IsTracingStartupForDuration()); DCHECK_EQ(SessionOwner::kBackgroundTracing, session_owner_); - CHECK(!ShouldTraceToResultFile()); + CHECK(GetResultFile().empty()); } else if (EnableFromATrace()) { DCHECK(IsEnabled()); DCHECK_EQ(SessionOwner::kSystemTracing, session_owner_); - CHECK(!ShouldTraceToResultFile()); + CHECK(GetResultFile().empty()); } } @@ -128,20 +128,11 @@ return output_format_; } -bool TraceStartupConfig::ShouldTraceToResultFile() const { - return IsEnabled() && should_trace_to_result_file_; -} - base::FilePath TraceStartupConfig::GetResultFile() const { DCHECK(IsEnabled()); - DCHECK(ShouldTraceToResultFile()); return result_file_; } -void TraceStartupConfig::OnTraceToResultFileFinished() { - finished_writing_to_file_ = true; -} - void TraceStartupConfig::SetBackgroundStartupTracingEnabled(bool enabled) { #if defined(OS_ANDROID) base::android::SetBackgroundStartupTracingFlag(enabled); @@ -174,25 +165,41 @@ << "=" << startup_duration_str << " defaulting to 5 (secs)"; startup_duration_in_seconds_ = kDefaultStartupDurationInSeconds; } + } else if (command_line->HasSwitch(switches::kEnableTracing)) { + // For --enable-tracing, tracing should last until browser shutdown. + startup_duration_in_seconds_ = 0; } - if (command_line->GetSwitchValueASCII(switches::kTraceStartupFormat) == - "proto") { - // Default is "json". + if (command_line->HasSwitch(switches::kTraceStartupFormat)) { + if (command_line->GetSwitchValueASCII(switches::kTraceStartupFormat) == + "proto") { + // Default is "json". + output_format_ = OutputFormat::kProto; + } + } else if (command_line->GetSwitchValueASCII( + switches::kEnableTracingFormat) == "proto") { output_format_ = OutputFormat::kProto; } - if (!command_line->HasSwitch(switches::kTraceStartup)) + if (!command_line->HasSwitch(switches::kTraceStartup) && + !command_line->HasSwitch(switches::kEnableTracing)) { return false; + } + + std::string categories; + if (command_line->HasSwitch(switches::kTraceStartup)) { + categories = command_line->GetSwitchValueASCII(switches::kTraceStartup); + } else { + categories = command_line->GetSwitchValueASCII(switches::kEnableTracing); + } trace_config_ = base::trace_event::TraceConfig( - command_line->GetSwitchValueASCII(switches::kTraceStartup), + categories, command_line->GetSwitchValueASCII(switches::kTraceStartupRecordMode)); result_file_ = command_line->GetSwitchValuePath(switches::kTraceStartupFile); is_enabled_ = true; - should_trace_to_result_file_ = true; return true; } @@ -227,7 +234,6 @@ if (trace_config_file.empty()) { is_enabled_ = true; - should_trace_to_result_file_ = true; DLOG(WARNING) << "Use default trace config."; return true; } @@ -247,7 +253,6 @@ is_enabled_ = ParseTraceConfigFileContent(trace_config_file_content); if (!is_enabled_) DLOG(WARNING) << "Cannot parse the trace config file correctly."; - should_trace_to_result_file_ = is_enabled_; return is_enabled_; } @@ -269,7 +274,6 @@ is_enabled_ = true; session_owner_ = SessionOwner::kBackgroundTracing; - should_trace_to_result_file_ = false; // Set startup duration to 0 since background tracing config will configure // the durations later. startup_duration_in_seconds_ = 0;
diff --git a/components/tracing/common/trace_startup_config.h b/components/tracing/common/trace_startup_config.h index 8f0c3e8c..74e6f31 100644 --- a/components/tracing/common/trace_startup_config.h +++ b/components/tracing/common/trace_startup_config.h
@@ -126,21 +126,12 @@ base::trace_event::TraceConfig GetTraceConfig() const; int GetStartupDuration() const; - // Returns true while startup tracing is not finished, if trace should be - // saved to result file. - bool ShouldTraceToResultFile() const; + // Returns the name of the file to write the trace result into. base::FilePath GetResultFile() const; - void OnTraceToResultFileFinished(); // Set the background tracing config in preferences for the next session. void SetBackgroundStartupTracingEnabled(bool enabled); - // Returns when the startup tracing is finished and written to file, false on - // all other cases. - bool finished_writing_to_file_for_testing() const { - return finished_writing_to_file_; - } - SessionOwner GetSessionOwner() const; OutputFormat GetOutputFormat() const; @@ -173,9 +164,7 @@ bool enable_background_tracing_for_testing_ = false; base::trace_event::TraceConfig trace_config_; int startup_duration_in_seconds_ = kDefaultStartupDurationInSeconds; - bool should_trace_to_result_file_ = false; base::FilePath result_file_; - bool finished_writing_to_file_ = false; SessionOwner session_owner_ = SessionOwner::kTracingController; bool session_adopted_ = false; OutputFormat output_format_ = OutputFormat::kLegacyJSON;
diff --git a/components/tracing/common/tracing_switches.cc b/components/tracing/common/tracing_switches.cc index 1d545b1..6b2d8137 100644 --- a/components/tracing/common/tracing_switches.cc +++ b/components/tracing/common/tracing_switches.cc
@@ -18,14 +18,25 @@ // specify the specific trace categories to include (e.g. // --trace-startup=base,net) otherwise, all events are recorded. Setting this // flag results in the first call to BeginTracing() to receive all trace events -// since startup. In Chrome, you may find --trace-startup-file and +// since startup. +// +// Historically, --trace-startup was used for browser startup profiling and +// --enable-tracing was used for browsertest tracing. Now they are share the +// same implementation, but both are still supported to avoid disrupting +// existing workflows. The only difference between them is the default duration +// (5 seconds for trace-startup, unlimited for enable-tracing). If both are +// specified, 'trace-startup' takes precedence. +// +// In Chrome, you may find --trace-startup-file and // --trace-startup-duration to control the auto-saving of the trace (not // supported in the base-only TraceLog component). -const char kTraceStartup[] = "trace-startup"; +const char kTraceStartup[] = "trace-startup"; +const char kEnableTracing[] = "enable-tracing"; -// Sets the time in seconds until startup tracing ends. If omitted a default of -// 5 seconds is used. Has no effect without --trace-startup, or if -// --startup-trace-file=none was supplied. +// Sets the time in seconds until startup tracing ends. If omitted: +// - if --trace-startup is specified, a default of 5 seconds is used. +// - if --enable-tracing is specified, tracing lasts until the browser is +// closed. Has no effect otherwise. const char kTraceStartupDuration[] = "trace-startup-duration"; // If supplied, sets the file which startup tracing will be stored into, if @@ -35,7 +46,16 @@ // As a special case, can be set to 'none' - this disables automatically saving // the result to a file and the first manually recorded trace will then receive // all events since startup. -const char kTraceStartupFile[] = "trace-startup-file"; +const char kTraceStartupFile[] = "trace-startup-file"; + +// Similar to the flag above, with the following differences: +// - A more detailed basename will be generated. +// - If the value is empty or ends with path separator, the provided directory +// will be used (with empty standing for current directory) and a detailed +// basename file will be generated. +// +// It is ignored if --trace-startup-file is specified. +const char kEnableTracingOutput[] = "enable-tracing-output"; // Sets the output format for the trace, valid values are "json" and "proto". // If not set, the current default is "json". @@ -44,6 +64,7 @@ // unexpectedly terminates. // Ignored if "trace-startup-owner" is not "controller". const char kTraceStartupFormat[] = "trace-startup-format"; +const char kEnableTracingFormat[] = "enable-tracing-format"; // If supplied, sets the tracing record mode and options; otherwise, the default // "record-until-full" mode will be used.
diff --git a/components/tracing/common/tracing_switches.h b/components/tracing/common/tracing_switches.h index 05ee0b9..d0ae956 100644 --- a/components/tracing/common/tracing_switches.h +++ b/components/tracing/common/tracing_switches.h
@@ -12,10 +12,13 @@ TRACING_EXPORT extern const char kEnableBackgroundTracing[]; TRACING_EXPORT extern const char kTraceConfigFile[]; TRACING_EXPORT extern const char kTraceStartup[]; +TRACING_EXPORT extern const char kEnableTracing[]; TRACING_EXPORT extern const char kTraceStartupDuration[]; TRACING_EXPORT extern const char kTraceStartupFile[]; +TRACING_EXPORT extern const char kEnableTracingOutput[]; TRACING_EXPORT extern const char kTraceStartupRecordMode[]; TRACING_EXPORT extern const char kTraceStartupFormat[]; +TRACING_EXPORT extern const char kEnableTracingFormat[]; TRACING_EXPORT extern const char kTraceStartupOwner[]; TRACING_EXPORT extern const char kTraceStartupEnablePrivacyFiltering[]; TRACING_EXPORT extern const char kPerfettoDisableInterning[];
diff --git a/components/ukm/ukm_recorder_impl.cc b/components/ukm/ukm_recorder_impl.cc index 0871b25e..aaa28a3 100644 --- a/components/ukm/ukm_recorder_impl.cc +++ b/components/ukm/ukm_recorder_impl.cc
@@ -59,8 +59,9 @@ // new ones being added. size_t GetMaxSources() { constexpr size_t kDefaultMaxSources = 500; - return static_cast<size_t>(base::GetFieldTrialParamByFeatureAsInt( + static auto value = static_cast<size_t>(base::GetFieldTrialParamByFeatureAsInt( kUkmFeature, "MaxSources", kDefaultMaxSources)); + return value; } // Gets the maximum number of Sources we can keep in memory at the end of the @@ -68,16 +69,18 @@ // interval. size_t GetMaxKeptSources() { constexpr size_t kDefaultMaxKeptSources = 100; - return static_cast<size_t>(base::GetFieldTrialParamByFeatureAsInt( + static auto value = static_cast<size_t>(base::GetFieldTrialParamByFeatureAsInt( kUkmFeature, "MaxKeptSources", kDefaultMaxKeptSources)); + return value; } // Gets the maximum number of Entries we'll keep in memory before discarding any // new ones being added. size_t GetMaxEntries() { constexpr size_t kDefaultMaxEntries = 5000; - return static_cast<size_t>(base::GetFieldTrialParamByFeatureAsInt( + static auto value = static_cast<size_t>(base::GetFieldTrialParamByFeatureAsInt( kUkmFeature, "MaxEntries", kDefaultMaxEntries)); + return value; } // Returns whether |url| has one of the schemes supported for logging to UKM.
diff --git a/components/webapps/webapps_client.h b/components/webapps/webapps_client.h index 9e850e1..a9b3f3f2 100644 --- a/components/webapps/webapps_client.h +++ b/components/webapps/webapps_client.h
@@ -50,6 +50,9 @@ const GURL& manifest_url) = 0; virtual bool CanShowAppBanners(content::WebContents* web_contents) = 0; + + virtual void OnWebApkInstallInitiatedFromAppMenu( + content::WebContents* web_contents) = 0; #endif };
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 0f6a9b7..6fc3a0e 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -2101,6 +2101,10 @@ deps += [ "//ui/ozone:buildflags" ] } + if (is_chromeos) { + deps += [ "//ui/base/ime/chromeos:chromeos" ] + } + if (is_linux || is_chromeos) { sources += [ "child_process_launcher_helper_linux.cc",
diff --git a/content/browser/loader/cross_site_document_blocking_browsertest.cc b/content/browser/loader/cross_site_document_blocking_browsertest.cc index a673e7d..fbc123c 100644 --- a/content/browser/loader/cross_site_document_blocking_browsertest.cc +++ b/content/browser/loader/cross_site_document_blocking_browsertest.cc
@@ -1632,4 +1632,110 @@ LoadBasicRequest(partition->GetNetworkContext(), test_url)); } +// This test class sets up a link element for webbundle subresource loading. +// e.g. <link rel=webbundle href=".../foo.wbn" resources="...">. +class CrossSiteDocumentBlockingWebBundleTest + : public CrossSiteDocumentBlockingTestBase { + public: + CrossSiteDocumentBlockingWebBundleTest() { + scoped_feature_list_.InitAndEnableFeature(features::kSubresourceWebBundles); + } + ~CrossSiteDocumentBlockingWebBundleTest() override = default; + + CrossSiteDocumentBlockingWebBundleTest( + const CrossSiteDocumentBlockingWebBundleTest&) = delete; + CrossSiteDocumentBlockingWebBundleTest& operator=( + const CrossSiteDocumentBlockingWebBundleTest&) = delete; + + protected: + void SetupLinkWebBundleElementAndImgElement(const GURL& bundle_url, + const GURL subresource_url) { + // Navigate to the test page. + ASSERT_TRUE(NavigateToURL(shell(), GURL("http://foo.com/title1.html"))); + + const char kScriptTemplate[] = R"( + const link = document.createElement('link'); + link.rel = 'webbundle'; + link.href = $1; + link.resources.add($2); + document.body.appendChild(link); + + const img = document.createElement('img'); + img.src = $2; + document.body.appendChild(img); +)"; + // Insert a <link> element for webbundle subresoruce loading, and insert an + // <img> element which loads a resource from the webbundle. + ASSERT_TRUE(ExecJs( + shell(), JsReplace(kScriptTemplate, bundle_url, subresource_url))); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +// CrossSiteDocumentBlockingWebBundleTest has 4 tests; a cartesian product of +// 1) cross-origin bundle, 2) same-origin bundle +// X +// A). CORB-protected MIME type (e.g. text/json), B) other type (e.g. image/png) +IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingWebBundleTest, + CrossOriginWebBundleSubresoruceJson) { + embedded_test_server()->StartAcceptingConnections(); + + GURL bundle_url("http://cross-origin.com/web_bundle/cross_origin.wbn"); + GURL subresource_url("http://cross-origin.com/web_bundle/resource.json"); + RequestInterceptor interceptor(subresource_url); + SetupLinkWebBundleElementAndImgElement(bundle_url, subresource_url); + interceptor.WaitForRequestCompletion(); + + EXPECT_EQ(0, interceptor.completion_status().error_code); + EXPECT_EQ("", interceptor.response_body()) + << "JSON in a cross-origin webbundle should be blocked by CORB"; +} + +IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingWebBundleTest, + CrossOriginWebBundleSubresorucePng) { + embedded_test_server()->StartAcceptingConnections(); + + GURL bundle_url("http://cross-origin.com/web_bundle/cross_origin.wbn"); + GURL subresource_url("http://cross-origin.com/web_bundle/resource.png"); + RequestInterceptor interceptor(subresource_url); + SetupLinkWebBundleElementAndImgElement(bundle_url, subresource_url); + interceptor.WaitForRequestCompletion(); + + EXPECT_EQ(0, interceptor.completion_status().error_code); + EXPECT_EQ("broken png", interceptor.response_body()) + << "PNG in a cross-origin webbundle should not be blocked"; +} + +IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingWebBundleTest, + SameOriginWebBundleSubresoruceJson) { + embedded_test_server()->StartAcceptingConnections(); + + GURL bundle_url("http://foo.com/web_bundle/same_origin.wbn"); + GURL subresource_url("http://foo.com/web_bundle/resource.json"); + RequestInterceptor interceptor(subresource_url); + SetupLinkWebBundleElementAndImgElement(bundle_url, subresource_url); + interceptor.WaitForRequestCompletion(); + + EXPECT_EQ(0, interceptor.completion_status().error_code); + EXPECT_EQ("{ secret: 1 }", interceptor.response_body()) + << "JSON in a same-origin webbundle should not be blocked"; +} + +IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingWebBundleTest, + SameOriginWebBundleSubresorucePng) { + embedded_test_server()->StartAcceptingConnections(); + + GURL bundle_url("http://foo.com/web_bundle/same_origin.wbn"); + GURL subresource_url("http://foo.com/web_bundle/resource.png"); + RequestInterceptor interceptor(subresource_url); + SetupLinkWebBundleElementAndImgElement(bundle_url, subresource_url); + interceptor.WaitForRequestCompletion(); + + EXPECT_EQ(0, interceptor.completion_status().error_code); + EXPECT_EQ("broken png", interceptor.response_body()) + << "PNG in a same-origin webbundle should not be blocked"; +} + } // namespace content
diff --git a/content/browser/prerender/prerender_browsertest.cc b/content/browser/prerender/prerender_browsertest.cc index fb3996a..2ae486f 100644 --- a/content/browser/prerender/prerender_browsertest.cc +++ b/content/browser/prerender/prerender_browsertest.cc
@@ -386,6 +386,30 @@ EXPECT_EQ(GetRequestCount(kPrerenderingUrl), 2); } +// Tests that back-forward history is preserved after activation. +IN_PROC_BROWSER_TEST_P(PrerenderBrowserTest, HistoryAfterActivation) { + // This test is only meaningful with activation. + if (IsActivationDisabled()) + return; + + const GURL kInitialUrl = GetUrl("/prerender/add_prerender.html"); + const GURL kPrerenderingUrl = GetUrl("/empty.html"); + + // Navigate to an initial page. + ASSERT_TRUE(NavigateToURL(shell(), kInitialUrl)); + + // Make and activate a prerendered page. + AddPrerender(kPrerenderingUrl); + NavigateWithLocation(kPrerenderingUrl); + EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), kPrerenderingUrl); + + // Navigate back to the initial page. + content::TestNavigationObserver observer(shell()->web_contents()); + shell()->GoBackOrForward(-1); + observer.Wait(); + EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), kInitialUrl); +} + // TODO(https://crbug.com/1132746): Test canceling prerendering. // TODO(https://crbug.com/1132746): Test prerendering for 404 page, redirection,
diff --git a/content/browser/prerender/prerender_host.cc b/content/browser/prerender/prerender_host.cc index aad841f..a4a58cb 100644 --- a/content/browser/prerender/prerender_host.cc +++ b/content/browser/prerender/prerender_host.cc
@@ -82,6 +82,10 @@ if (!current_web_contents) return false; + // Merge browsing history. + prerendered_contents_->GetController().CopyStateFromAndPrune( + ¤t_web_contents->GetController(), /*replace_entry=*/false); + // Activate the prerendered contents. WebContentsDelegate* delegate = current_web_contents->GetDelegate(); DCHECK(delegate);
diff --git a/content/browser/prerender/prerender_host.h b/content/browser/prerender/prerender_host.h index 5e66730..8b320eed 100644 --- a/content/browser/prerender/prerender_host.h +++ b/content/browser/prerender/prerender_host.h
@@ -47,7 +47,8 @@ // Activates the prerendered contents. Returns false when activation didn't // occur for some reason. This must be called after this host gets ready for - // activation. + // activation. `current_render_frame_host` is the RenderFrameHost that will + // be swapped out and destroyed by the activation. bool ActivatePrerenderedContents( RenderFrameHostImpl& current_render_frame_host);
diff --git a/content/browser/prerender/prerender_host_unittest.cc b/content/browser/prerender/prerender_host_unittest.cc index fbbaaa8..b21b7fb 100644 --- a/content/browser/prerender/prerender_host_unittest.cc +++ b/content/browser/prerender/prerender_host_unittest.cc
@@ -6,6 +6,7 @@ #include "base/test/scoped_feature_list.h" #include "content/browser/site_instance_impl.h" +#include "content/public/test/navigation_simulator.h" #include "content/public/test/test_browser_context.h" #include "content/test/test_render_frame_host.h" #include "content/test/test_render_view_host.h" @@ -54,7 +55,7 @@ std::unique_ptr<TestWebContentsDelegate> web_contents_delegate_; }; -TEST_F(PrerenderHostTest, StartPrerendering) { +TEST_F(PrerenderHostTest, PrerenderAndActivate) { std::unique_ptr<TestWebContents> web_contents = CreateWebContents(GURL("https://example.com/")); RenderFrameHostImpl* initiator_rfh = web_contents->GetMainFrame(); @@ -67,17 +68,25 @@ std::move(attributes), initiator_rfh->GetGlobalFrameRoutingId(), initiator_rfh->GetLastCommittedOrigin()); + // Start the prerendering navigation. prerender_host->StartPrerendering(); - // Prepare a fake response so as to commit the navigation. - TestRenderFrameHost* prerendering_rfh = static_cast<TestRenderFrameHost*>( + + // Finish the prerendering navigation. Normally we could use + // EmbeddedTestServer to provide a response, but this test uses + // RenderViewHostImplTestHarness so the load goes through a + // TestNavigationURLLoader which we don't have access to in order + // to complete. Use NavigationSimulator to finish the navigation on the + // WebContents. + WebContents* prerender_contents = WebContents::FromRenderFrameHost( prerender_host->GetPrerenderedMainFrameHostForTesting()); - ASSERT_TRUE(prerendering_rfh); - prerendering_rfh->PrepareForCommit(); + ASSERT_TRUE(prerender_contents); + std::unique_ptr<NavigationSimulator> sim = + NavigationSimulator::CreateFromPending(prerender_contents); + sim->ReadyToCommit(); + sim->Commit(); + EXPECT_TRUE(prerender_host->is_ready_for_activation()); - // Artificially finish navigation to make the prerender host ready to provide - // the prerendered contents. - prerender_host->DidFinishNavigation(nullptr); - + // Activate. EXPECT_TRUE(prerender_host->ActivatePrerenderedContents(*initiator_rfh)); }
diff --git a/content/browser/renderer_host/policy_container_host.cc b/content/browser/renderer_host/policy_container_host.cc index 2c39717..0dbba08b 100644 --- a/content/browser/renderer_host/policy_container_host.cc +++ b/content/browser/renderer_host/policy_container_host.cc
@@ -8,7 +8,7 @@ PolicyContainerHost::PolicyContainerHost() = default; PolicyContainerHost::PolicyContainerHost( - PolicyContainerHost::DocumentPolicies document_policies) + const PolicyContainerHost::DocumentPolicies& document_policies) : document_policies_(document_policies) {} PolicyContainerHost::~PolicyContainerHost() = default;
diff --git a/content/browser/renderer_host/policy_container_host.h b/content/browser/renderer_host/policy_container_host.h index 191ad644..36ec0238 100644 --- a/content/browser/renderer_host/policy_container_host.h +++ b/content/browser/renderer_host/policy_container_host.h
@@ -41,7 +41,7 @@ }; PolicyContainerHost(); - explicit PolicyContainerHost(DocumentPolicies document_policies); + explicit PolicyContainerHost(const DocumentPolicies& document_policies); PolicyContainerHost(const PolicyContainerHost&) = delete; PolicyContainerHost& operator=(const PolicyContainerHost&) = delete; ~PolicyContainerHost() override;
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index 552ba42..1b7f87f 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -2477,6 +2477,12 @@ } void RenderFrameHostImpl::RenderFrameCreated() { + // In https://crbug.com/1146573 a WebContentsObserver was causing the frame to + // be reinitialized during deletion. It is not valid to re-enter navigation + // code like that and it led to an invalid state. This is not a DCHECK because + // the corruption will not be visible until later, making the bug very + // difficult to understand. + CHECK_NE(render_frame_state_, RenderFrameState::kDeleting); // We should not create new RenderFrames while our delegate is being destroyed // (e.g., via a WebContentsObserver during WebContents shutdown). This seems // to have caused crashes in https://crbug.com/717650. @@ -2522,17 +2528,25 @@ } void RenderFrameHostImpl::RenderFrameDeleted() { + // In https://crbug.com/1146573 a WebContentsObserver was causing the frame to + // be reinitialized during deletion. It is not valid to re-enter navigation + // code like that and it led to an invalid state. This is not a DCHECK because + // the corruption will cause a crash but later, making the bug very + // difficult to understand. + CHECK_NE(render_frame_state_, RenderFrameState::kDeleting); bool was_created = is_render_frame_created(); - render_frame_state_ = RenderFrameState::kDeleted; + render_frame_state_ = RenderFrameState::kDeleting; // If the current status is different than the new status, the delegate // needs to be notified. if (was_created) { delegate_->RenderFrameDeleted(this); } + if (web_ui_) { web_ui_->InvalidateMojoConnection(); } + render_frame_state_ = RenderFrameState::kDeleted; } void RenderFrameHostImpl::SwapIn() {
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h index 49dad88..1221c604 100644 --- a/content/browser/renderer_host/render_frame_host_impl.h +++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -2737,11 +2737,21 @@ // state will be kCreated or kDeleted. kNeverCreated = 0, // A RenderFrame has been created in the renderer and is still in that - // state. The next state will be kDeleted. + // state. The next state will be kDeleting. kCreated, - // A RenderFrame has either been cleanly deleted or its renderer process has - // exited or crashed. The next state may be kCreated or the RenderFrameHost - // may be destroyed. + // A RenderFrame has either + // - been cleanly deleted + // - its renderer process has exited or crashed + // We will call observers of RenderFrameDeleted in this state and this + // allows us to CHECK if an observer causes us to attempt to change state + // during deletion. See https://crbug.com/1146573. The next state will + // be kDeleted and we will move to that before exiting RenderFrameDeleted. + kDeleting, + // A RenderFrame has either + // - been cleanly deleted + // - its renderer process has exited or crashed + // The next state may be kCreated if the RenderFrameHost is being reused + // after a crash or the RenderFrameHost may be destroyed. kDeleted, }; RenderFrameState render_frame_state_ = RenderFrameState::kNeverCreated;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index 42f70e7..fdd49c9 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -125,6 +125,11 @@ #include "ui/base/ime/virtual_keyboard_controller.h" #endif +#if defined(OS_CHROMEOS) +#include "ui/base/ime/chromeos/extension_ime_util.h" +#include "ui/base/ime/chromeos/input_method_manager.h" +#endif + using gfx::RectToSkIRect; using gfx::SkIRectToRect; @@ -1498,6 +1503,20 @@ base::UmaHistogramEnumeration( "InputMethod.Assistive.Autocorrect.Count", TextInputClient::SubClass::kRenderWidgetHostViewAura); + +#if defined(OS_CHROMEOS) + auto* input_method_manager = + chromeos::input_method::InputMethodManager::Get(); + if (input_method_manager && + chromeos::extension_ime_util::IsExperimentalMultilingual( + input_method_manager->GetActiveIMEState() + ->GetCurrentInputMethod() + .id())) { + base::UmaHistogramEnumeration( + "InputMethod.MultilingualExperiment.Autocorrect.Count", + TextInputClient::SubClass::kRenderWidgetHostViewAura); + } +#endif } auto* input_handler = GetFrameWidgetInputHandlerForFocusedWidget();
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index a7281479..fe24c5ce 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -813,23 +813,6 @@ } }; -// SitePerProcessEmbedderCSPEnforcementBrowserTest - -class SitePerProcessEmbedderCSPEnforcementBrowserTest - : public SitePerProcessBrowserTest { - public: - SitePerProcessEmbedderCSPEnforcementBrowserTest() {} - - protected: - void SetUpCommandLine(base::CommandLine* command_line) override { - SitePerProcessBrowserTestBase::SetUpCommandLine(command_line); - // TODO(amalika): Remove this switch when the EmbedderCSPEnforcement becomes - // stable - command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures, - "EmbedderCSPEnforcement"); - } -}; - // SitePerProcessProgrammaticScrollTest. class SitePerProcessProgrammaticScrollTest : public SitePerProcessBrowserTest { @@ -4173,7 +4156,7 @@ // Verify that "csp" property on frame elements propagates to child frames // correctly. See https://crbug.com/647588 -IN_PROC_BROWSER_TEST_P(SitePerProcessEmbedderCSPEnforcementBrowserTest, +IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest, FrameOwnerPropertiesPropagationCSP) { GURL main_url(embedded_test_server()->GetURL( "a.com", "/frame_owner_properties_csp.html")); @@ -16678,9 +16661,6 @@ SitePerProcessBrowserTouchActionTest, testing::ValuesIn(RenderDocumentFeatureLevelValues())); INSTANTIATE_TEST_SUITE_P(All, - SitePerProcessEmbedderCSPEnforcementBrowserTest, - testing::ValuesIn(RenderDocumentFeatureLevelValues())); -INSTANTIATE_TEST_SUITE_P(All, SitePerProcessHighDPIBrowserTest, testing::ValuesIn(RenderDocumentFeatureLevelValues())); INSTANTIATE_TEST_SUITE_P(All,
diff --git a/content/browser/tracing/startup_tracing_browsertest.cc b/content/browser/tracing/startup_tracing_browsertest.cc index eac323c2..bc1e63e 100644 --- a/content/browser/tracing/startup_tracing_browsertest.cc +++ b/content/browser/tracing/startup_tracing_browsertest.cc
@@ -5,13 +5,16 @@ #include "base/files/file_util.h" #include "base/json/json_reader.h" #include "base/run_loop.h" +#include "base/test/bind.h" #include "base/test/scoped_feature_list.h" +#include "base/test/scoped_run_loop_timeout.h" #include "base/test/test_timeouts.h" #include "base/threading/thread_restrictions.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "components/tracing/common/trace_startup_config.h" #include "components/tracing/common/tracing_switches.h" +#include "content/browser/tracing/startup_tracing_controller.h" #include "content/browser/tracing/tracing_controller_impl.h" #include "content/public/test/browser_test.h" #include "content/public/test/content_browser_test.h" @@ -42,52 +45,6 @@ } // namespace -class CommandlineStartupTracingTest : public ContentBrowserTest { - public: - CommandlineStartupTracingTest() = default; - - void SetUpCommandLine(base::CommandLine* command_line) override { - base::CreateTemporaryFile(&temp_file_path_); - command_line->AppendSwitch(switches::kTraceStartup); - command_line->AppendSwitchASCII(switches::kTraceStartupDuration, "3"); - command_line->AppendSwitchASCII(switches::kTraceStartupFile, - temp_file_path_.AsUTF8Unsafe()); - } - - protected: - base::FilePath temp_file_path_; - - private: - DISALLOW_COPY_AND_ASSIGN(CommandlineStartupTracingTest); -}; - -// Failing on Android/Win ASAN, Linux TSAN. crbug.com/1041392 -#if (defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)) || \ - (defined(OS_WIN) && defined(ADDRESS_SANITIZER)) || \ - ((defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(THREAD_SANITIZER)) -#define MAYBE_TestStartupTracing DISABLED_TestStartupTracing -#else -#define MAYBE_TestStartupTracing TestStartupTracing -#endif -IN_PROC_BROWSER_TEST_F(CommandlineStartupTracingTest, - MAYBE_TestStartupTracing) { - EXPECT_TRUE(NavigateToURL(shell(), GetTestUrl("", "title1.html"))); - WaitForCondition(base::BindRepeating([]() { - return tracing::TraceStartupConfig::GetInstance() - ->finished_writing_to_file_for_testing(); - }), - "finish file write"); - - std::string trace; - base::ScopedAllowBlockingForTesting allow_blocking; - ASSERT_TRUE(base::ReadFileToString(temp_file_path_, &trace)); - EXPECT_TRUE(base::JSONReader::Read(trace)); - EXPECT_TRUE(trace.find("StartupTracingController::Start") != - std::string::npos); -} - -#undef MAYBE_TestStartupTracing - class StartupTracingInProcessTest : public ContentBrowserTest { public: StartupTracingInProcessTest() { @@ -154,4 +111,263 @@ wait_for_stop.Run(); } +namespace { + +enum class FinishType { + kWaitForTimeout, + kStopExplicitly, +}; + +std::ostream& operator<<(std::ostream& o, FinishType type) { + switch (type) { + case FinishType::kStopExplicitly: + o << "Stop"; + return o; + case FinishType::kWaitForTimeout: + o << "Wait"; + return o; + } +} + +enum class OutputType { + kProto, + kJSON, +}; + +std::ostream& operator<<(std::ostream& o, OutputType type) { + switch (type) { + case OutputType::kJSON: + o << "json"; + return o; + case OutputType::kProto: + o << "proto"; + return o; + } +} + +enum class OutputLocation { + // Write trace to a given file. + kGivenFile, + // Write trace into a given directory (basename will be set to trace1 before + // starting). + kDirectoryWithDefaultBasename, + // Write trace into a given directory (basename will be set to trace1 before + // starting, and updated to trace2 before calling Stop()). + kDirectoryWithBasenameUpdatedBeforeStop, +}; + +std::ostream& operator<<(std::ostream& o, OutputLocation type) { + switch (type) { + case OutputLocation::kGivenFile: + o << "file"; + return o; + case OutputLocation::kDirectoryWithDefaultBasename: + o << "dir/trace1"; + return o; + case OutputLocation::kDirectoryWithBasenameUpdatedBeforeStop: + o << "dir/trace2"; + return o; + } +} + +} // namespace + +class StartupTracingTest + : public ContentBrowserTest, + public testing::WithParamInterface< + std::tuple<FinishType, OutputType, OutputLocation>> { + public: + StartupTracingTest() = default; + + void SetUpCommandLine(base::CommandLine* command_line) override { + command_line->AppendSwitch(switches::kTraceStartup); + if (GetFinishType() == FinishType::kWaitForTimeout) { + command_line->AppendSwitchASCII(switches::kTraceStartupDuration, "3"); + } else { + command_line->AppendSwitchASCII(switches::kTraceStartupDuration, "0"); + } + command_line->AppendSwitchASCII(switches::kTraceStartupFormat, + GetOutputTypeAsString()); + + if (GetOutputLocation() == OutputLocation::kGivenFile) { + base::CreateTemporaryFile(&temp_file_path_); + } else { + base::CreateNewTempDirectory(base::FilePath::StringType(), + &temp_file_path_); + temp_file_path_ = temp_file_path_.AsEndingWithSeparator(); + } + + command_line->AppendSwitchASCII(switches::kEnableTracingOutput, + temp_file_path_.AsUTF8Unsafe()); + + if (GetOutputLocation() != OutputLocation::kGivenFile) { + // --enable-tracing-format switch should be initialised before + // calling SetDefaultBasenameForTest, which forces the creation of + // TraceStartupConfig, which queries the command line flags and + // stores the snapshot. + StartupTracingController::GetInstance().SetDefaultBasenameForTest( + "trace1", + StartupTracingController::ExtensionType::kAppendAppropriate); + } + } + + FinishType GetFinishType() { return std::get<0>(GetParam()); } + + OutputType GetOutputType() { return std::get<1>(GetParam()); } + + std::string GetOutputTypeAsString() { + switch (GetOutputType()) { + case OutputType::kJSON: + return "json"; + case OutputType::kProto: + return "proto"; + } + } + + OutputLocation GetOutputLocation() { return std::get<2>(GetParam()); } + + base::FilePath GetExpectedPath() { + std::string filename; + + switch (GetOutputLocation()) { + case OutputLocation::kGivenFile: + return temp_file_path_; + case OutputLocation::kDirectoryWithDefaultBasename: + filename = "trace1"; + break; + case OutputLocation::kDirectoryWithBasenameUpdatedBeforeStop: + filename = "trace2"; + break; + } + + // Renames are not supported together with timeouts. + if (GetFinishType() == FinishType::kWaitForTimeout) + filename = "trace1"; + + return temp_file_path_.AppendASCII(filename + "." + + GetOutputTypeAsString()); + } + + static void CheckOutput(base::FilePath path, OutputType output_type) { + std::string trace; + base::ScopedAllowBlockingForTesting allow_blocking; + ASSERT_TRUE(base::ReadFileToString(path, &trace)) + << "Failed to read file " << path; + + if (output_type == OutputType::kJSON) { + EXPECT_TRUE(base::JSONReader::Read(trace)); + } + + // Both proto and json should have the trace event name recorded somewhere + // as a substring. + EXPECT_TRUE(trace.find("StartupTracingController::Start") != + std::string::npos); + } + + void Wait() { + if (GetFinishType() == FinishType::kWaitForTimeout) { + WaitForCondition(base::BindRepeating([]() { + return StartupTracingController::GetInstance() + .is_finished_for_testing(); + }), + "finish file write"); + } else { + StartupTracingController::GetInstance().WaitUntilStopped(); + } + } + + protected: + base::FilePath temp_file_path_; + + private: + base::test::ScopedRunLoopTimeout increased_timeout_{ + FROM_HERE, TestTimeouts::test_launcher_timeout()}; + + DISALLOW_COPY_AND_ASSIGN(StartupTracingTest); +}; + +INSTANTIATE_TEST_SUITE_P( + All, + StartupTracingTest, + testing::Combine( + testing::Values(FinishType::kStopExplicitly, + FinishType::kWaitForTimeout), + testing::Values(OutputType::kJSON, OutputType::kProto), + testing::Values( + OutputLocation::kGivenFile, + OutputLocation::kDirectoryWithDefaultBasename, + OutputLocation::kDirectoryWithBasenameUpdatedBeforeStop))); + +IN_PROC_BROWSER_TEST_P(StartupTracingTest, TestEnableTracing) { + EXPECT_TRUE(NavigateToURL(shell(), GetTestUrl("", "title1.html"))); + + if (GetOutputLocation() == + OutputLocation::kDirectoryWithBasenameUpdatedBeforeStop) { + StartupTracingController::GetInstance().SetDefaultBasenameForTest( + "trace2", StartupTracingController::ExtensionType::kAppendAppropriate); + } + + Wait(); + + CheckOutput(GetExpectedPath(), GetOutputType()); +} + +class EmergencyStopTracingTest : public StartupTracingTest {}; + +INSTANTIATE_TEST_SUITE_P( + All, + EmergencyStopTracingTest, + testing::Combine( + testing::Values(FinishType::kStopExplicitly), + testing::Values(OutputType::kJSON, OutputType::kProto), + testing::Values(OutputLocation::kDirectoryWithDefaultBasename))); + +IN_PROC_BROWSER_TEST_P(EmergencyStopTracingTest, StopOnUIThread) { + EXPECT_TRUE(NavigateToURL(shell(), GetTestUrl("", "title1.html"))); + + StartupTracingController::EmergencyStop(); + CheckOutput(GetExpectedPath(), GetOutputType()); +} + +IN_PROC_BROWSER_TEST_P(EmergencyStopTracingTest, StopOnThreadPool) { + EXPECT_TRUE(NavigateToURL(shell(), GetTestUrl("", "title1.html"))); + + auto expected_path = GetExpectedPath(); + auto output_type = GetOutputType(); + + base::RunLoop run_loop; + + base::ThreadPool::PostTask(FROM_HERE, base::BindLambdaForTesting([&]() { + StartupTracingController::EmergencyStop(); + CheckOutput(expected_path, output_type); + run_loop.Quit(); + })); + + run_loop.Run(); +} + +IN_PROC_BROWSER_TEST_P(EmergencyStopTracingTest, StopOnThreadPoolTwice) { + EXPECT_TRUE(NavigateToURL(shell(), GetTestUrl("", "title1.html"))); + + auto expected_path = GetExpectedPath(); + auto output_type = GetOutputType(); + + base::RunLoop run_loop1; + base::RunLoop run_loop2; + + base::ThreadPool::PostTask(FROM_HERE, base::BindLambdaForTesting([&]() { + StartupTracingController::EmergencyStop(); + CheckOutput(expected_path, output_type); + run_loop1.Quit(); + })); + base::ThreadPool::PostTask(FROM_HERE, base::BindLambdaForTesting([&]() { + StartupTracingController::EmergencyStop(); + CheckOutput(expected_path, output_type); + run_loop2.Quit(); + })); + + run_loop1.Run(); + run_loop2.Run(); +} + } // namespace content
diff --git a/content/browser/tracing/startup_tracing_controller.cc b/content/browser/tracing/startup_tracing_controller.cc index f745fd2..a9adf2e1 100644 --- a/content/browser/tracing/startup_tracing_controller.cc +++ b/content/browser/tracing/startup_tracing_controller.cc
@@ -3,14 +3,19 @@ // found in the LICENSE file. #include "content/browser/tracing/startup_tracing_controller.h" +#include "base/bind_post_task.h" #include "base/command_line.h" #include "base/files/file.h" #include "base/files/file_util.h" #include "base/logging.h" #include "base/no_destructor.h" #include "base/run_loop.h" +#include "base/synchronization/waitable_event.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" +#include "base/thread_annotations.h" +#include "base/threading/thread_restrictions.h" +#include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/typed_macros.h" #include "build/build_config.h" #include "components/tracing/common/trace_startup_config.h" @@ -29,17 +34,87 @@ namespace content { +// A helper class responsible for coordinating emergency trace finalisation +// (e.g. when the process is about to be killed), which can be initiated from +// any thread. +class EmergencyTraceFinalisationCoordinator { + public: + static EmergencyTraceFinalisationCoordinator& GetInstance() { + static base::NoDestructor<EmergencyTraceFinalisationCoordinator> g_instance; + return *g_instance; + } + + void OnTracingStarted(scoped_refptr<base::SequencedTaskRunner> task_runner, + base::OnceClosure stop_tracing) { + tracing_started_.Set(); + base::AutoLock lock(lock_); + startup_tracing_controller_task_runner_ = std::move(task_runner); + stop_tracing_ = std::move(stop_tracing); + } + + void OnTracingStopped() { finalisation_.Signal(); } + + // May be called multiple times per session, e.g. if a second thread + // encounters a crash after the first. + void StopAndBlockUntilStopped() { + // If DCHECK fires before tracing has started, there isn't much for us to + // do. + if (!tracing_started_.IsSet()) + return; + + base::trace_event::TraceLog::GetInstance() + ->SetCurrentThreadBlocksMessageLoop(); + + base::OnceClosure stop_tracing; + scoped_refptr<base::SequencedTaskRunner> task_runner; + { + base::AutoLock lock(lock_); + task_runner = startup_tracing_controller_task_runner_; + stop_tracing = std::move(stop_tracing_); + } + + if (task_runner->RunsTasksInCurrentSequence()) { + VLOG(0) << "Ignored an emergency tracing stop request from the " + "StartupTracingController sequence"; + return; + } + + if (stop_tracing) + task_runner->PostTask(FROM_HERE, std::move(stop_tracing)); + + base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_wait; + + // Wait for the tracing to be finished before processing. + // Note that we should wait even if |stop_tracing| is null — if a second + // thread hits DCHECK while the first has posted a task and waits for the + // trace to be written, the second one should wait as well to avoid crashing + // the process. + finalisation_.Wait(); + } + + private: + base::WaitableEvent finalisation_; + base::AtomicFlag tracing_started_; + + base::Lock lock_; + scoped_refptr<base::SequencedTaskRunner> + startup_tracing_controller_task_runner_ GUARDED_BY(lock_); + base::OnceClosure stop_tracing_ GUARDED_BY(lock_); +}; + class StartupTracingController::BackgroundTracer { public: enum class WriteMode { kAfterStopping, kStreaming }; BackgroundTracer(WriteMode write_mode, + TempFilePolicy temp_file_policy, base::FilePath output_file, tracing::TraceStartupConfig::OutputFormat output_format, perfetto::TraceConfig trace_config, base::OnceClosure on_tracing_finished) : state_(State::kTracing), write_mode_(write_mode), + temp_file_policy_(temp_file_policy), task_runner_(base::SequencedTaskRunnerHandle::Get()), output_file_(output_file), output_format_(output_format), @@ -57,17 +132,33 @@ tracing_session_->Setup(trace_config); } - tracing_session_->StartBlocking(); + // |StartBlocking| can take a non-trivial amount of time, so + // EmergencyTraceFinalisationController should be set up before it to catch + // DCHECKs early. + EmergencyTraceFinalisationCoordinator::GetInstance().OnTracingStarted( + task_runner_, + base::BindOnce(&BackgroundTracer::Stop, weak_ptr_factory_.GetWeakPtr(), + base::nullopt)); + tracing_session_->SetOnStopCallback([&]() { OnTracingStopped(); }); + tracing_session_->StartBlocking(); TRACE_EVENT("startup", "StartupTracingController::Start"); } - void Stop() { + void Stop(base::Optional<base::FilePath> output_file) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (state_ != State::kTracing) - return; + // Tracing might have already been finished due to a timeout. + if (state_ != State::kTracing) { + // Note: updating output files is not supported together with + // timeout-based tracing. + return; + } + state_ = State::kStopping; + + if (output_file) + output_file_ = output_file.value(); tracing_session_->StopBlocking(); } @@ -82,11 +173,13 @@ } DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK_EQ(state_, State::kTracing); + // State will be kStopping if Stop() is called and kTracing if tracing + // finishes due to a timeout. + DCHECK(state_ == State::kStopping || state_ == State::kTracing); if (write_mode_ == WriteMode::kStreaming) { // No need to explicitly call ReadTrace as Perfetto has already written // the file. - Finalise(output_file_); + Finalise(); return; } state_ = State::kWritingToFile; @@ -102,7 +195,7 @@ if (args.has_more) return; - Finalise(output_file_); + Finalise(); }); } @@ -138,15 +231,15 @@ // In order to atomically commit the trace file, create a temporary file first // which then will be subsequently renamed. void OpenFile(const base::FilePath& path) { - file_ = base::CreateAndOpenTemporaryFileInDir(path.DirName(), - &written_to_file_); - if (file_.IsValid()) { - LOG(ERROR) << "Created valid file"; - return; - } + if (temp_file_policy_ == TempFilePolicy::kUseTemporaryFile) { + file_ = base::CreateAndOpenTemporaryFileInDir(path.DirName(), + &written_to_file_); + if (file_.IsValid()) + return; - VLOG(1) << "Failed to create temporary file, using file '" << path - << "' directly instead"; + VLOG(1) << "Failed to create temporary file, using file '" << path + << "' directly instead"; + } // On Android, it might not be possible to create a temporary file. // In that case, we should use the file directly. @@ -159,38 +252,48 @@ } // Close the file and rename if needed. - void Finalise(const base::FilePath& path) { + void Finalise() { DCHECK_NE(state_, State::kFinished); file_.Close(); - if (written_to_file_ != path) { + if (written_to_file_ != output_file_) { base::File::Error error; if (!base::ReplaceFile(written_to_file_, output_file_, &error)) { LOG(ERROR) << "Cannot move file '" << written_to_file_ << "' to '" << output_file_ << "' : " << base::File::ErrorToString(error); + } else { + written_to_file_ = output_file_; } } + VLOG(0) << "Completed startup tracing to " << written_to_file_; + EmergencyTraceFinalisationCoordinator::GetInstance().OnTracingStopped(); + state_ = State::kFinished; std::move(on_tracing_finished_).Run(); - - VLOG(0) << "Completed startup tracing to " << path; } enum class State { kTracing, + kStopping, kWritingToFile, kFinished, }; State state_; const WriteMode write_mode_; + const TempFilePolicy temp_file_policy_; scoped_refptr<base::SequencedTaskRunner> task_runner_; + // Output file might be customised during the execution (e.g. test result + // becomes available), which means that if Perfetto has already started + // streaming the trace, the trace file should be renamed after trace + // completes. base::FilePath output_file_; base::FilePath written_to_file_; + base::File file_; const tracing::TraceStartupConfig::OutputFormat output_format_; @@ -200,27 +303,32 @@ std::unique_ptr<tracing::TracePacketTokenizer> trace_packet_tokenizer_; base::OnceClosure on_tracing_finished_; + std::unique_ptr<perfetto::TracingSession> tracing_session_; SEQUENCE_CHECKER(sequence_checker_); + + base::WeakPtrFactory<BackgroundTracer> weak_ptr_factory_{this}; }; +// static +StartupTracingController& StartupTracingController::GetInstance() { + // Note: no DCHECK_CURRENTLY_ON, as it can be called prior to initialisation + // of BrowserThreads. + + static base::NoDestructor<StartupTracingController> g_instance; + return *g_instance; +} + namespace { -base::FilePath GetStartupTraceFileName() { - base::FilePath trace_file; - - trace_file = tracing::TraceStartupConfig::GetInstance()->GetResultFile(); - if (trace_file.empty()) { +base::FilePath BasenameToPath(std::string basename) { #if defined(OS_ANDROID) - trace_file = TracingControllerAndroid::GenerateTracingFilePath(""); + return TracingControllerAndroid::GenerateTracingFilePath(basename); #else - // Default to saving the startup trace into the current dir. - trace_file = base::FilePath().AppendASCII("chrometrace.log"); + // Default to saving the startup trace into the current dir. + return base::FilePath().AppendASCII(basename); #endif - } - - return trace_file; } } // namespace @@ -228,12 +336,46 @@ StartupTracingController::StartupTracingController() = default; StartupTracingController::~StartupTracingController() = default; -// static -StartupTracingController& StartupTracingController::GetInstance() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); +base::FilePath StartupTracingController::GetOutputPath() { + auto* command_line = base::CommandLine::ForCurrentProcess(); - static base::NoDestructor<StartupTracingController> g_instance; - return *g_instance; + base::FilePath path_from_config = + tracing::TraceStartupConfig::GetInstance()->GetResultFile(); + if (!path_from_config.empty()) + return path_from_config; + + // If --trace-startup-file is specified, use it. + if (command_line->HasSwitch(switches::kTraceStartupFile)) { + base::FilePath result = + command_line->GetSwitchValuePath(switches::kTraceStartupFile); + if (result.empty()) + return BasenameToPath("chrometrace.log"); + return result; + } + + base::FilePath result = + command_line->GetSwitchValuePath(switches::kEnableTracingOutput); + if (result.empty() && command_line->HasSwitch(switches::kTraceStartup)) { + // If --trace-startup is present, return chrometrace.log for backwards + // compatibility. + return BasenameToPath("chrometrace.log"); + } + + // If a non-directory path is specified, use it. + if (!result.empty() && !result.EndsWithSeparator()) + return result; + + std::string basename = default_basename_; + if (basename.empty()) + basename = "chrometrace.log"; + + // If a non-empty directory is specified, use it. + if (!result.empty()) + return result.AppendASCII(basename); + + // If the directory is empty, go through BasenameToPath to generate a valid + // path on Android. + return BasenameToPath(basename); } void StartupTracingController::StartIfNeeded() { @@ -283,12 +425,9 @@ tracing::TraceStartupConfig::GetInstance()->GetStartupDuration(); perfetto_config.set_duration_ms(duration_in_seconds * 1000); - if (output_file_.empty()) - output_file_ = GetStartupTraceFileName(); - background_tracer_ = base::SequenceBound<BackgroundTracer>( - std::move(background_task_runner), write_mode, output_file_, - output_format, perfetto_config, + std::move(background_task_runner), write_mode, temp_file_policy_, + GetOutputPath(), output_format, perfetto_config, base::BindOnce( [](StartupTracingController* controller) { GetUIThreadTaskRunner({})->PostTask( @@ -302,7 +441,8 @@ void StartupTracingController::Stop(base::OnceClosure on_tracing_finished) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (state_ == State::kNotRunning) { + if (state_ != State::kRunning) { + // Both kStopped and kNotRunning are valid states. std::move(on_tracing_finished).Run(); return; } @@ -310,22 +450,58 @@ DCHECK(!on_tracing_finished_) << "Stop() should be called only once."; on_tracing_finished_ = std::move(on_tracing_finished); - background_tracer_.AsyncCall(&BackgroundTracer::Stop); + background_tracer_.AsyncCall(&BackgroundTracer::Stop) + .WithArgs(GetOutputPath()); } void StartupTracingController::OnStoppedOnUIThread() { DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_EQ(state_, State::kRunning); - state_ = State::kNotRunning; + state_ = State::kStopped; background_tracer_.Reset(); if (on_tracing_finished_) std::move(on_tracing_finished_).Run(); - tracing::TraceStartupConfig::GetInstance()->OnTraceToResultFileFinished(); tracing::TraceStartupConfig::GetInstance()->SetDisabled(); } +void StartupTracingController::SetUsingTemporaryFile( + StartupTracingController::TempFilePolicy temp_file_policy) { + DCHECK_EQ(state_, State::kNotEnabled) << "Should be called before Start()"; + temp_file_policy_ = temp_file_policy; +} + +void StartupTracingController::SetDefaultBasename( + std::string basename, + ExtensionType extension_type) { + if (!tracing::TraceStartupConfig::GetInstance()->IsEnabled()) + return; + + if (basename_for_test_set_) + return; + + if (extension_type == ExtensionType::kAppendAppropriate) { + switch (tracing::TraceStartupConfig::GetInstance()->GetOutputFormat()) { + case tracing::TraceStartupConfig::OutputFormat::kLegacyJSON: + basename += ".json"; + break; + case tracing::TraceStartupConfig::OutputFormat::kProto: + basename += ".proto"; + break; + } + } + default_basename_ = basename; +} + +void StartupTracingController::SetDefaultBasenameForTest( + std::string basename, + ExtensionType extension_type) { + basename_for_test_set_ = false; + SetDefaultBasename(basename, extension_type); + basename_for_test_set_ = true; +} + void StartupTracingController::WaitUntilStopped() { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -334,4 +510,16 @@ run_loop.Run(); } +// static +void StartupTracingController::EmergencyStop() { + if (GetIOThreadTaskRunner({})->RunsTasksInCurrentSequence()) { + VLOG(0) << "Emergency tracing stop request from IO thread is ignored - not " + "possible to finalise trace without running tasks on IO thread"; + return; + } + + EmergencyTraceFinalisationCoordinator::GetInstance() + .StopAndBlockUntilStopped(); +} + } // namespace content
diff --git a/content/browser/tracing/startup_tracing_controller.h b/content/browser/tracing/startup_tracing_controller.h index 744a14b..d7d69f6 100644 --- a/content/browser/tracing/startup_tracing_controller.h +++ b/content/browser/tracing/startup_tracing_controller.h
@@ -6,32 +6,80 @@ #define CONTENT_BROWSER_TRACING_STARTUP_TRACING_CONTROLLER_H_ #include "base/threading/sequence_bound.h" +#include "content/common/content_export.h" namespace content { // Class responsible for starting and stopping startup tracing as configured by // StartupTracingConfig. All interactions with it are limited to UI thread, but // the actual logic lives on a background ThreadPool sequence. -class StartupTracingController { +class CONTENT_EXPORT StartupTracingController { public: StartupTracingController(); ~StartupTracingController(); static StartupTracingController& GetInstance(); + // Stop the trace recording, write the trace to disk and block until complete. + // Intended to be used in the situation when the browser process is going to + // crash (e.g. DCHECK failure) and we want to avoid losing the trace data. Can + // be called from any thread. + // May not succeed if called from a sequence that is required to be responsive + // during trace finalisation. + static void EmergencyStop(); + void StartIfNeeded(); void WaitUntilStopped(); + // By default, a trace is written into a temporary file which then is renamed, + // however this can lead to data loss when the browser process crashes. + // Embedders can disable this (especially if a name provided to + // SetDefaultBasename makes it clear that the trace is incomplete and final + // name will be provided via SetDefaultBasename call before calling Stop). + enum class TempFilePolicy { + kUseTemporaryFile, + kWriteDirectly, + }; + void SetUsingTemporaryFile(TempFilePolicy temp_file_policy); + + // Set default basename for the trace output file to allow //content embedders + // to customise it using some metadata (like test names). + // + // If --enable-trace-output is a directory (default value, empty, designated + // "current directory"), then the startup trace will be written in a file with + // the given basename in this directory. Depending on the |extension_type|, + // an appropriate extension (.json or .proto) will be added. + // + // Note that embedders can call it even after tracing has started and Perfetto + // started streaming the trace into it — in that case, + // StartupTracingController will rename the file after finishing. However, + // this is guaranteed to work only when tracing lasts until Stop() (not with + // duration-based tracing). + enum class ExtensionType { + kAppendAppropriate, + kNone, + }; + void SetDefaultBasename(std::string basename, ExtensionType extension_type); + // As the test harness calls SetDefaultBasename, expose ForTest() version for + // the tests checking the StartupTracingController logic itself. + void SetDefaultBasenameForTest(std::string basename, + ExtensionType extension_type); + + bool is_finished_for_testing() const { return state_ == State::kStopped; } + private: void Stop(base::OnceClosure on_finished_callback); void OnStoppedOnUIThread(); + base::FilePath GetOutputPath(); + enum class State { + kNotEnabled, kRunning, - kNotRunning, + kStopped, }; - State state_ = State::kNotRunning; + State state_ = State::kNotEnabled; // All actual interactions with the tracing service and the process of writing // files happens on a background thread. @@ -40,6 +88,11 @@ base::OnceClosure on_tracing_finished_; base::FilePath output_file_; + + std::string default_basename_; + bool basename_for_test_set_ = false; + + TempFilePolicy temp_file_policy_ = TempFilePolicy::kUseTemporaryFile; }; } // namespace content
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc index 3139a07..4d26731 100644 --- a/content/public/common/content_switches.cc +++ b/content/public/common/content_switches.cc
@@ -402,14 +402,6 @@ // Enabled threaded compositing for web tests. const char kEnableThreadedCompositing[] = "enable-threaded-compositing"; -// Enable tracing during the execution of browser tests. -const char kEnableTracing[] = "enable-tracing"; - -// The filename to write the output of the test tracing to. If it is empty -// or it ends in a directory separator then an auto-generated filename will be -// appended. -const char kEnableTracingOutput[] = "enable-tracing-output"; - // Enable screen capturing support for MediaStream API. const char kEnableUserMediaScreenCapturing[] = "enable-usermedia-screen-capturing";
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h index a48873f..ae35cec5 100644 --- a/content/public/common/content_switches.h +++ b/content/public/common/content_switches.h
@@ -123,8 +123,6 @@ CONTENT_EXPORT extern const char kEnableStrictMixedContentChecking[]; CONTENT_EXPORT extern const char kEnableStrictPowerfulFeatureRestrictions[]; CONTENT_EXPORT extern const char kEnableThreadedCompositing[]; -CONTENT_EXPORT extern const char kEnableTracing[]; -CONTENT_EXPORT extern const char kEnableTracingOutput[]; CONTENT_EXPORT extern const char kEnableUserMediaScreenCapturing[]; CONTENT_EXPORT extern const char kEnableUseZoomForDSF[]; CONTENT_EXPORT extern const char kEnableViewport[];
diff --git a/content/public/test/DEPS b/content/public/test/DEPS index 2dc6203..a9f5558 100644 --- a/content/public/test/DEPS +++ b/content/public/test/DEPS
@@ -33,6 +33,7 @@ ".*\.(cc|mm)": [ # Testing utilities can access anything in content/ "+content", + "+components/tracing/common", "+gin/v8_initializer.h", "+services/network/network_context.h", "+third_party/iaccessible2",
diff --git a/content/public/test/browser_test_base.cc b/content/public/test/browser_test_base.cc index eb959bf2..6bc7162 100644 --- a/content/public/test/browser_test_base.cc +++ b/content/public/test/browser_test_base.cc
@@ -21,6 +21,7 @@ #include "base/files/scoped_file.h" #include "base/i18n/icu_util.h" #include "base/location.h" +#include "base/logging.h" #include "base/macros.h" #include "base/rand_util.h" #include "base/run_loop.h" @@ -37,6 +38,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" +#include "components/tracing/common/tracing_switches.h" #include "content/browser/browser_main_loop.h" #include "content/browser/browser_thread_impl.h" #include "content/browser/network_service_instance_impl.h" @@ -46,6 +48,7 @@ #include "content/browser/startup_helper.h" #include "content/browser/storage_partition_impl.h" #include "content/browser/tracing/memory_instrumentation_util.h" +#include "content/browser/tracing/startup_tracing_controller.h" #include "content/browser/tracing/tracing_controller_impl.h" #include "content/public/app/content_main.h" #include "content/public/browser/browser_task_traits.h" @@ -166,10 +169,47 @@ GetUIThreadTaskRunner({})->PostTask(FROM_HERE, std::move(quit_task)); } -void TraceStopTracingComplete(base::OnceClosure quit, - const base::FilePath& file_path) { - LOG(ERROR) << "Tracing written to: " << file_path.value(); - std::move(quit).Run(); +enum class TraceBasenameType { + kWithoutTestStatus, + kWithTestStatus, +}; + +std::string GetDefaultTraceBasename(TraceBasenameType type) { + std::string test_suite_name = ::testing::UnitTest::GetInstance() + ->current_test_info() + ->test_suite_name(); + std::string test_name = + ::testing::UnitTest::GetInstance()->current_test_info()->name(); + // Parameterised tests might have slashes in their full name — replace them + // before using it as a file name to avoid trying to write to an incorrect + // location. + base::ReplaceChars(test_suite_name, "/", "_", &test_suite_name); + base::ReplaceChars(test_name, "/", "_", &test_name); + // Add random number to the trace file to distinguish traces from different + // test runs. We don't use timestamp here to avoid collisions with parallel + // runs of the same test. Browser test runner runs one test per browser + // process instantiation, so saving the seed here is appopriate. + // GetDefaultTraceBasename() is going to be called twice: + // - for the first time, before the test starts to get the name of the file to + // stream the results (to avoid losing them if test crashes). + // - the second time, if test execution finishes normally, to calculate the + // resulting name of the file, including test result. + static std::string random_seed = + base::NumberToString(base::RandInt(1e7, 1e8 - 1)); + std::string status; + if (type == TraceBasenameType::kWithTestStatus) { + status = ::testing::UnitTest::GetInstance() + ->current_test_info() + ->result() + ->Passed() + ? "OK" + : "FAIL"; + } else { + // In order to be able to stream the test to the file, + status = "NOT_FINISHED"; + } + return "trace_test_" + test_suite_name + "_" + test_name + "_" + random_seed + + "_" + status; } // See SetInitialWebContents comment for more information. @@ -483,6 +523,32 @@ std::make_unique<CreatedMainPartsClosure>(base::BindOnce( &BrowserTestBase::CreatedBrowserMainParts, base::Unretained(this))); + // If tracing is enabled, customise the output filename based on the name of + // the test. + StartupTracingController::GetInstance().SetDefaultBasename( + GetDefaultTraceBasename(TraceBasenameType::kWithoutTestStatus), + StartupTracingController::ExtensionType::kAppendAppropriate); + // Write to the provided file directly to recover at least some data when the + // test crashes or times out. + StartupTracingController::GetInstance().SetUsingTemporaryFile( + StartupTracingController::TempFilePolicy::kWriteDirectly); + // Set a logging handler to flush a trace before crashing the test when + // hitting a DCHECK / LOG(FATAL). + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableTracing)) { + DCHECK(!logging::GetLogMessageHandler()); + logging::SetLogMessageHandler([](int severity, const char* file, int line, + size_t message_start, + const std::string& str) { + // TODO(crbug.com/1157954): Print the message to the console before + // calling this to ensure that the message is still printed if something + // goes wrong. + if (severity == logging::LOGGING_FATAL) + StartupTracingController::EmergencyStop(); + return false; + }); + } + #if defined(OS_ANDROID) // For all other platforms, we call ContentMain for browser tests which goes // through the normal browser initialization paths. For Android, we must set @@ -670,36 +736,6 @@ } #endif -namespace { - -std::string GetDefaultTraceFilename() { - std::string test_suite_name = ::testing::UnitTest::GetInstance() - ->current_test_info() - ->test_suite_name(); - std::string test_name = - ::testing::UnitTest::GetInstance()->current_test_info()->name(); - // Parameterised tests might have slashes in their full name — replace them - // before using it as a file name to avoid trying to write to an incorrect - // location. - base::ReplaceChars(test_suite_name, "/", "_", &test_suite_name); - base::ReplaceChars(test_name, "/", "_", &test_name); - // Add random number to the trace file to distinguish traces from different - // test runs. - // We don't use timestamp here to avoid collisions with parallel runs of the - // same test. - std::string random_seed = base::NumberToString(base::RandInt(1e7, 1e8 - 1)); - std::string status = ::testing::UnitTest::GetInstance() - ->current_test_info() - ->result() - ->Passed() - ? "OK" - : "FAIL"; - return "trace_test_" + test_suite_name + "_" + test_name + "_" + random_seed + - "_" + status + ".json"; -} - -} // namespace - void BrowserTestBase::ProxyRunTestOnMainThreadLoop() { #if !defined(OS_ANDROID) // All FeatureList overrides should have been registered prior to browser test @@ -728,17 +764,6 @@ signal(SIGTERM, DumpStackTraceSignalHandler); #endif // defined(OS_POSIX) - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableTracing)) { - base::trace_event::TraceConfig trace_config( - base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - switches::kEnableTracing), - base::trace_event::RECORD_CONTINUOUSLY); - TracingController::GetInstance()->StartTracing( - trace_config, - TracingController::StartTracingDoneCallback()); - } - { // This can be called from a posted task. Allow nested tasks here, because // otherwise the test body will have to do it in order to use RunLoop for @@ -782,31 +807,23 @@ TearDownOnMainThread(); } - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableTracing)) { - base::FilePath trace_file = - base::CommandLine::ForCurrentProcess()->GetSwitchValuePath( - switches::kEnableTracingOutput); - // If |trace_file| ends in a directory separator or is empty use a generated - // name in that directory (empty means current directory). - if (trace_file.empty() || trace_file.EndsWithSeparator()) - trace_file = trace_file.AppendASCII(GetDefaultTraceFilename()); - - // Wait for tracing to collect results from the renderers. - base::RunLoop run_loop; - TracingController::GetInstance()->StopTracing( - TracingControllerImpl::CreateFileEndpoint( - trace_file, base::BindOnce(&TraceStopTracingComplete, - run_loop.QuitClosure(), trace_file))); - run_loop.Run(); - } - PostRunTestOnMainThread(); // Sometimes tests initialize a storage partition and the initialization // schedules some tasks which need to be executed before finishing tests. // Run these tasks. content::RunAllPendingInMessageLoop(); + + // Update the trace output filename to include the test result. + StartupTracingController::GetInstance().SetDefaultBasename( + GetDefaultTraceBasename(TraceBasenameType::kWithTestStatus), + StartupTracingController::ExtensionType::kAppendAppropriate); + +#if defined(OS_ANDROID) + // On Android, browser main runner is not shut down, so stop trace recording + // here. + StartupTracingController::GetInstance().WaitUntilStopped(); +#endif } void BrowserTestBase::SetAllowNetworkAccessToHostResolutions() {
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc index 4a53c9a..903703fe 100644 --- a/content/renderer/renderer_blink_platform_impl.cc +++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -963,11 +963,18 @@ return render_thread->GetGpuFactories(); } -media::DecoderFactory* RendererBlinkPlatformImpl::GetMediaDecoderFactory() { +scoped_refptr<base::SingleThreadTaskRunner> +RendererBlinkPlatformImpl::MediaThreadTaskRunner() { auto* render_thread = RenderThreadImpl::current(); if (!render_thread) return nullptr; + return render_thread->GetMediaThreadTaskRunner(); +} + +media::DecoderFactory* RendererBlinkPlatformImpl::GetMediaDecoderFactory() { + auto* render_thread = RenderThreadImpl::current(); + DCHECK(!!render_thread); return render_thread->GetMediaDecoderFactory(); }
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h index 8f83462..b854f5b 100644 --- a/content/renderer/renderer_blink_platform_impl.h +++ b/content/renderer/renderer_blink_platform_impl.h
@@ -210,6 +210,7 @@ blink::MediaInspectorContext* inspector_context, scoped_refptr<base::SingleThreadTaskRunner> owner_task_runner) override; media::GpuVideoAcceleratorFactories* GetGpuFactories() override; + scoped_refptr<base::SingleThreadTaskRunner> MediaThreadTaskRunner() override; media::DecoderFactory* GetMediaDecoderFactory() override; void SetRenderingColorSpace(const gfx::ColorSpace& color_space) override; void SetActiveURL(const blink::WebURL& url,
diff --git a/content/test/data/web_bundle/cross_origin.har b/content/test/data/web_bundle/cross_origin.har new file mode 100644 index 0000000..8966449 --- /dev/null +++ b/content/test/data/web_bundle/cross_origin.har
@@ -0,0 +1,44 @@ +{ + "log": { + "entries": [ + { + "request": { + "method": "GET", + "url": "http://cross-origin.com/web_bundle/resource.json", + "headers": [] + }, + "response": { + "status": 200, + "headers": [ + { + "name": "Content-type", + "value": "application/json" + } + ], + "content": { + "text": "{ secret: 1 }" + } + } + }, + { + "request": { + "method": "GET", + "url": "http://cross-origin.com/web_bundle/resource.png", + "headers": [] + }, + "response": { + "status": 200, + "headers": [ + { + "name": "Content-type", + "value": "image/png" + } + ], + "content": { + "text": "broken png" + } + } + } + ] + } +}
diff --git a/content/test/data/web_bundle/cross_origin.wbn b/content/test/data/web_bundle/cross_origin.wbn new file mode 100644 index 0000000..7b97d8ae --- /dev/null +++ b/content/test/data/web_bundle/cross_origin.wbn Binary files differ
diff --git a/content/test/data/web_bundle/cross_origin.wbn.mock-http-headers b/content/test/data/web_bundle/cross_origin.wbn.mock-http-headers new file mode 100644 index 0000000..f2c3f09 --- /dev/null +++ b/content/test/data/web_bundle/cross_origin.wbn.mock-http-headers
@@ -0,0 +1,3 @@ +HTTP/1.1 200 OK +Content-Type: application/webbundle +Access-Control-Allow-Origin: *
diff --git a/content/test/data/web_bundle/generate-test-wbns.sh b/content/test/data/web_bundle/generate-test-wbns.sh index 22e52a6f..cde6825 100755 --- a/content/test/data/web_bundle/generate-test-wbns.sh +++ b/content/test/data/web_bundle/generate-test-wbns.sh
@@ -52,3 +52,17 @@ -primaryURL https://test.example.org/ \ -har variants_test.har \ -o variants_test.wbn + +# Generate a WBN which will be used as a cross origin bundle. +gen-bundle \ + -version b1 \ + -har cross_origin.har \ + -primaryURL http://cross-origin.com/web_bundle/resource.json \ + -o cross_origin.wbn + +# Generate a WBN which will be used as a same origin bundle. +gen-bundle \ + -version b1 \ + -har same_origin.har \ + -primaryURL http://foo.com/web_bundle/resource.json \ + -o same_origin.wbn
diff --git a/content/test/data/web_bundle/same_origin.har b/content/test/data/web_bundle/same_origin.har new file mode 100644 index 0000000..ba07848 --- /dev/null +++ b/content/test/data/web_bundle/same_origin.har
@@ -0,0 +1,44 @@ +{ + "log": { + "entries": [ + { + "request": { + "method": "GET", + "url": "http://foo.com/web_bundle/resource.json", + "headers": [] + }, + "response": { + "status": 200, + "headers": [ + { + "name": "Content-type", + "value": "application/json" + } + ], + "content": { + "text": "{ secret: 1 }" + } + } + }, + { + "request": { + "method": "GET", + "url": "http://foo.com/web_bundle/resource.png", + "headers": [] + }, + "response": { + "status": 200, + "headers": [ + { + "name": "Content-type", + "value": "image/png" + } + ], + "content": { + "text": "broken png" + } + } + } + ] + } +}
diff --git a/content/test/data/web_bundle/same_origin.wbn b/content/test/data/web_bundle/same_origin.wbn new file mode 100644 index 0000000..dd8aced --- /dev/null +++ b/content/test/data/web_bundle/same_origin.wbn Binary files differ
diff --git a/content/web_test/renderer/web_frame_test_proxy.cc b/content/web_test/renderer/web_frame_test_proxy.cc index 92d0b04..0c52cd9 100644 --- a/content/web_test/renderer/web_frame_test_proxy.cc +++ b/content/web_test/renderer/web_frame_test_proxy.cc
@@ -263,7 +263,7 @@ GetWebFrame()->SetName(blink::WebString()); GetWebFrame()->ClearOpener(); - blink::WebTestingSupport::ResetInternalsObject(GetWebFrame()); + blink::WebTestingSupport::ResetMainFrame(GetWebFrame()); // Resetting the internals object also overrides the WebPreferences, so we // have to sync them to WebKit again. blink::WebView* web_view = GetWebFrame()->View();
diff --git a/docs/webui_explainer.md b/docs/webui_explainer.md index f62e208..cc01a79 100644 --- a/docs/webui_explainer.md +++ b/docs/webui_explainer.md
@@ -883,28 +883,34 @@ Chrome's sandbox. To make sure that the special powers granted to WebUI pages are safe, WebUI pages are restricted in what they can do: -* WebUI pages cannot embed http/https resources or frames +* WebUI pages cannot embed http/https resources * WebUI pages cannot issue http/https fetches In the rare case that a WebUI page really needs to include web content, the safe -way to do this is by using a `<webview>` tag. Using a `<webview>` tag is more -secure than using an iframe for multiple reasons, even if Site Isolation and -out-of-process iframes keep the web content out of the privileged WebUI process. +way to do this is by using an `<iframe>` tag. Chrome's security model gives +process isolation between the WebUI and the web content. However, some extra +precautions need to be taken, because there are properties of the page that are +accessible cross-origin and malicious code can take advantage of such data to +attack the WebUI. Here are some things to keep in mind: -First, the content inside the `<webview>` tag has a much reduced attack surface, -since it does not have a window reference to its embedder or any other frames. -Only postMessage channel is supported, and this needs to be initiated by the -embedder, not the guest. +* The WebUI page can receive postMessage payloads from the web and should + ensure it verifies any messages as they are not trustworthy. +* The entire frame tree is visible to the embedded web content, including + ancestor origins. +* The web content runs in the same StoragePartition and Profile as the WebUI, + which reflect where the WebUI page was loaded (e.g., the default profile, + Incognito, etc). The corresponding user credentials will thus be available to + the web content inside the WebUI, possibly showing the user as signed in. -Second, the content inside the `<webview>` tag is hosted in a separate -StoragePartition. Thus, cookies and other persistent storage for both the WebUI -page and other browser tabs are inaccessible to it. +Note: WebUIs have a default Content Security Policy which disallows embedding +any frames. If you want to include any web content in an <iframe> you will need +to update the policy for your WebUI. When doing so, allow only known origins and +avoid making the policy more permissive than strictly necessary. -This greater level of isolation makes it safer to load possibly untrustworthy or -compromised web content, reducing the risk of sandbox escapes. - -For an example of switching from iframe to webview tag see -https://crrev.com/c/710738. +Alternatively, a `<webview>` tag can be used, which runs in a separate +StoragePartition, a separate frame tree, and restricts postMessage communication +by default. However, `<webview>` does not support Site Isolation and +therefore it is not advisable to use for any sensitive content. ## See also
diff --git a/gin/gin_features.cc b/gin/gin_features.cc index b200a04..570eaef1 100644 --- a/gin/gin_features.cc +++ b/gin/gin_features.cc
@@ -50,4 +50,8 @@ const base::Feature kV8TurboDirectHeapAccess{"V8TurboDirectHeapAccess", base::FEATURE_ENABLED_BY_DEFAULT}; +// Enables fallback to a breadth-first regexp engine on excessive backtracking. +const base::Feature kV8ExperimentalRegexpEngine{ + "V8ExperimentalRegexpEngine", base::FEATURE_ENABLED_BY_DEFAULT}; + } // namespace features
diff --git a/gin/gin_features.h b/gin/gin_features.h index 0e2b51c8..69bc3b9 100644 --- a/gin/gin_features.h +++ b/gin/gin_features.h
@@ -21,6 +21,7 @@ GIN_EXPORT extern const base::Feature kV8NoReclaimUnmodifiedWrappers; GIN_EXPORT extern const base::Feature kV8LocalHeaps; GIN_EXPORT extern const base::Feature kV8TurboDirectHeapAccess; +GIN_EXPORT extern const base::Feature kV8ExperimentalRegexpEngine; } // namespace features
diff --git a/gin/v8_initializer.cc b/gin/v8_initializer.cc index 4174fd9..3967c18d 100644 --- a/gin/v8_initializer.cc +++ b/gin/v8_initializer.cc
@@ -288,6 +288,16 @@ v8::V8::SetFlagsFromString(no_direct_access, sizeof(no_direct_access) - 1); } + if (!base::FeatureList::IsEnabled(features::kV8ExperimentalRegexpEngine)) { + // The --enable-experimental-regexp-engine-on-excessive-backtracks flag is + // enabled by default, so we need to explicitly disable it if + // kV8ExperimentalRegexpEngine is disabled. + static constexpr char no_experimental_regexp_engine[] = + "--no-enable-experimental-regexp-engine-on-excessive-backtracks"; + v8::V8::SetFlagsFromString(no_experimental_regexp_engine, + sizeof(no_experimental_regexp_engine) - 1); + } + if (IsolateHolder::kStrictMode == mode) { static const char use_strict[] = "--use_strict"; v8::V8::SetFlagsFromString(use_strict, sizeof(use_strict) - 1);
diff --git a/headless/lib/browser/headless_web_contents_impl.cc b/headless/lib/browser/headless_web_contents_impl.cc index 1eb384ea..af6718c 100644 --- a/headless/lib/browser/headless_web_contents_impl.cc +++ b/headless/lib/browser/headless_web_contents_impl.cc
@@ -177,6 +177,13 @@ ->block_new_web_contents(); } + void RequestToLockMouse(content::WebContents* web_contents, + bool user_gesture, + bool last_unlocked_by_target) override { + web_contents->GotResponseToLockMouseRequest( + blink::mojom::PointerLockResult::kSuccess); + } + private: HeadlessBrowserImpl* browser() { return headless_web_contents_->browser(); }
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg index d8d94921..5fe4dd11 100644 --- a/infra/config/generated/cr-buildbucket.cfg +++ b/infra/config/generated/cr-buildbucket.cfg
@@ -27321,110 +27321,6 @@ } } builders { - name: "Win7 Builder (dbg) Goma Canary" - swarming_host: "chromium-swarm.appspot.com" - swarming_tags: "vpython:native-python-wrapper" - dimensions: "builder:Win7 Builder (dbg) Goma Canary" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Windows-7" - dimensions: "pool:luci.chromium.ci" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/master" - cmd: "recipes" - } - properties: "{\"$build/goma\":{\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}" - execution_timeout_secs: 36000 - build_numbers: YES - service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.use_realms" - value: 100 - } - resultdb { - enable: true - } - } - builders { - name: "Win7 Builder (dbg) Goma Latest Client" - swarming_host: "chromium-swarm.appspot.com" - swarming_tags: "vpython:native-python-wrapper" - dimensions: "builder:Win7 Builder (dbg) Goma Latest Client" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Windows-7" - dimensions: "pool:luci.chromium.ci" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/master" - cmd: "recipes" - } - properties: "{\"$build/goma\":{\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}" - execution_timeout_secs: 36000 - build_numbers: YES - service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.use_realms" - value: 100 - } - resultdb { - enable: true - } - } - builders { - name: "Win7 Builder Goma Canary" - swarming_host: "chromium-swarm.appspot.com" - swarming_tags: "vpython:native-python-wrapper" - dimensions: "builder:Win7 Builder Goma Canary" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Windows-7" - dimensions: "pool:luci.chromium.ci" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/master" - cmd: "recipes" - } - properties: "{\"$build/goma\":{\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}" - execution_timeout_secs: 36000 - build_numbers: YES - service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.use_realms" - value: 100 - } - resultdb { - enable: true - } - } - builders { - name: "Win7 Builder Goma Latest Client" - swarming_host: "chromium-swarm.appspot.com" - swarming_tags: "vpython:native-python-wrapper" - dimensions: "builder:Win7 Builder Goma Latest Client" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Windows-7" - dimensions: "pool:luci.chromium.ci" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/master" - cmd: "recipes" - } - properties: "{\"$build/goma\":{\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}" - execution_timeout_secs: 36000 - build_numbers: YES - service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.use_realms" - value: 100 - } - resultdb { - enable: true - } - } - builders { name: "android-archive-dbg-goma-canary" swarming_host: "chromium-swarm.appspot.com" swarming_tags: "vpython:native-python-wrapper"
diff --git a/infra/config/generated/luci-milo.cfg b/infra/config/generated/luci-milo.cfg index 5ac10ba..993cd27c 100644 --- a/infra/config/generated/luci-milo.cfg +++ b/infra/config/generated/luci-milo.cfg
@@ -6731,14 +6731,6 @@ short_name: "loc" } builders { - name: "buildbucket/luci.chromium.goma/Win7 Builder Goma Canary" - category: "win7|rel" - } - builders { - name: "buildbucket/luci.chromium.goma/Win7 Builder (dbg) Goma Canary" - category: "win7|dbg" - } - builders { name: "buildbucket/luci.chromium.goma/Mac Builder Goma Canary" category: "mac|rel" } @@ -11458,14 +11450,6 @@ short_name: "loc" } builders { - name: "buildbucket/luci.chromium.goma/Win7 Builder Goma Latest Client" - category: "win7|rel" - } - builders { - name: "buildbucket/luci.chromium.goma/Win7 Builder (dbg) Goma Latest Client" - category: "win7|dbg" - } - builders { name: "buildbucket/luci.chromium.goma/Mac Builder Goma Latest Client" category: "mac|rel" }
diff --git a/infra/config/generated/luci-scheduler.cfg b/infra/config/generated/luci-scheduler.cfg index b49f2fb..fa0d744 100644 --- a/infra/config/generated/luci-scheduler.cfg +++ b/infra/config/generated/luci-scheduler.cfg
@@ -4011,46 +4011,6 @@ } } job { - id: "Win7 Builder (dbg) Goma Canary" - realm: "goma" - acl_sets: "goma" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "luci.chromium.goma" - builder: "Win7 Builder (dbg) Goma Canary" - } -} -job { - id: "Win7 Builder (dbg) Goma Latest Client" - realm: "goma" - acl_sets: "goma" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "luci.chromium.goma" - builder: "Win7 Builder (dbg) Goma Latest Client" - } -} -job { - id: "Win7 Builder Goma Canary" - realm: "goma" - acl_sets: "goma" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "luci.chromium.goma" - builder: "Win7 Builder Goma Canary" - } -} -job { - id: "Win7 Builder Goma Latest Client" - realm: "goma" - acl_sets: "goma" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "luci.chromium.goma" - builder: "Win7 Builder Goma Latest Client" - } -} -job { id: "Win7 FYI Debug (AMD)" realm: "ci" acls { @@ -7257,10 +7217,6 @@ triggers: "Win Builder Goma Canary" triggers: "Win Builder Goma Latest Client" triggers: "Win Builder Goma RBE Latest Client" - triggers: "Win7 Builder (dbg) Goma Canary" - triggers: "Win7 Builder (dbg) Goma Latest Client" - triggers: "Win7 Builder Goma Canary" - triggers: "Win7 Builder Goma Latest Client" triggers: "android-archive-dbg-goma-canary" triggers: "android-archive-dbg-goma-latest" triggers: "android-archive-dbg-goma-rbe-ats-canary"
diff --git a/infra/config/subprojects/goma/consoles/chromium.goma.fyi.star b/infra/config/subprojects/goma/consoles/chromium.goma.fyi.star index f1588ce..a734330 100644 --- a/infra/config/subprojects/goma/consoles/chromium.goma.fyi.star +++ b/infra/config/subprojects/goma/consoles/chromium.goma.fyi.star
@@ -24,14 +24,6 @@ short_name = "loc", ), luci.console_view_entry( - builder = "goma/Win7 Builder Goma Canary", - category = "win7|rel", - ), - luci.console_view_entry( - builder = "goma/Win7 Builder (dbg) Goma Canary", - category = "win7|dbg", - ), - luci.console_view_entry( builder = "goma/Mac Builder Goma Canary", category = "mac|rel", ),
diff --git a/infra/config/subprojects/goma/consoles/goma.latest.star b/infra/config/subprojects/goma/consoles/goma.latest.star index 4bf267b..133e1a3 100644 --- a/infra/config/subprojects/goma/consoles/goma.latest.star +++ b/infra/config/subprojects/goma/consoles/goma.latest.star
@@ -23,14 +23,6 @@ short_name = "loc", ), luci.console_view_entry( - builder = "goma/Win7 Builder Goma Latest Client", - category = "win7|rel", - ), - luci.console_view_entry( - builder = "goma/Win7 Builder (dbg) Goma Latest Client", - category = "win7|dbg", - ), - luci.console_view_entry( builder = "goma/Mac Builder Goma Latest Client", category = "mac|rel", ),
diff --git a/infra/config/subprojects/goma/goma.star b/infra/config/subprojects/goma/goma.star index 83dc774..dd1f5a7a 100644 --- a/infra/config/subprojects/goma/goma.star +++ b/infra/config/subprojects/goma/goma.star
@@ -91,16 +91,6 @@ ) fyi_goma_canary_builder( - name = "Win7 Builder (dbg) Goma Canary", - os = os.WINDOWS_7, -) - -fyi_goma_canary_builder( - name = "Win7 Builder Goma Canary", - os = os.WINDOWS_7, -) - -fyi_goma_canary_builder( name = "android-archive-dbg-goma-canary", ) @@ -245,16 +235,6 @@ ) fyi_goma_latest_client_builder( - name = "Win7 Builder (dbg) Goma Latest Client", - os = os.WINDOWS_7, -) - -fyi_goma_latest_client_builder( - name = "Win7 Builder Goma Latest Client", - os = os.WINDOWS_7, -) - -fyi_goma_latest_client_builder( name = "android-archive-dbg-goma-latest", )
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index 6f3023c..bb34afe 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -95,6 +95,7 @@ #import "ios/chrome/browser/ui/main/scene_delegate.h" #import "ios/chrome/browser/ui/ui_feature_flags.h" #include "ios/chrome/browser/ui/util/multi_window_support.h" +#include "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/browser/ui/webui/chrome_web_ui_ios_controller_factory.h" #import "ios/chrome/browser/url_loading/url_loading_params.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" @@ -733,9 +734,8 @@ } - (void)orientationDidChange:(NSNotification*)notification { - crash_keys::SetCurrentOrientation( - [[UIApplication sharedApplication] statusBarOrientation], - [[UIDevice currentDevice] orientation]); + crash_keys::SetCurrentOrientation(GetInterfaceOrientation(), + [[UIDevice currentDevice] orientation]); } - (void)registerForOrientationChangeNotifications {
diff --git a/ios/chrome/browser/autofill/autofill_controller_unittest.mm b/ios/chrome/browser/autofill/autofill_controller_unittest.mm index 4c8c0639..b97f0e7 100644 --- a/ios/chrome/browser/autofill/autofill_controller_unittest.mm +++ b/ios/chrome/browser/autofill/autofill_controller_unittest.mm
@@ -292,10 +292,6 @@ [accessory_mediator_ injectWebState:web_state()]; [accessory_mediator_ injectProvider:suggestion_controller_]; - auto suggestionManager = base::mac::ObjCCastStrict<JsSuggestionManager>( - [web_state()->GetJSInjectionReceiver() - instanceOfClass:[JsSuggestionManager class]]); - [accessory_mediator_ injectSuggestionManager:suggestionManager]; histogram_tester_.reset(new base::HistogramTester()); }
diff --git a/ios/chrome/browser/autofill/form_input_accessory_view_handler.h b/ios/chrome/browser/autofill/form_input_accessory_view_handler.h index fd4b04f..3df1a7a 100644 --- a/ios/chrome/browser/autofill/form_input_accessory_view_handler.h +++ b/ios/chrome/browser/autofill/form_input_accessory_view_handler.h
@@ -7,13 +7,15 @@ #import "ios/chrome/browser/autofill/form_input_navigator.h" -@class JsSuggestionManager; +namespace autofill { +class JsSuggestionManager; +} // namespace autofill // This handles user actions in the default keyboard accessory view buttons. @interface FormInputAccessoryViewHandler : NSObject <FormInputNavigator> // The JS manager for interacting with the underlying form. -@property(nonatomic, weak) JsSuggestionManager* JSSuggestionManager; +@property(nonatomic) autofill::JsSuggestionManager* JSSuggestionManager; // Resets the metrics logger of the instance. - (void)reset;
diff --git a/ios/chrome/browser/autofill/form_input_accessory_view_handler.mm b/ios/chrome/browser/autofill/form_input_accessory_view_handler.mm index a26bdfa..2d8b585 100644 --- a/ios/chrome/browser/autofill/form_input_accessory_view_handler.mm +++ b/ios/chrome/browser/autofill/form_input_accessory_view_handler.mm
@@ -9,6 +9,7 @@ #include "base/mac/foundation_util.h" #include "base/metrics/histogram_macros.h" #include "base/notreached.h" +#include "base/strings/sys_string_conversions.h" #import "components/autofill/core/browser/keyboard_accessory_metrics_logger.h" #import "components/autofill/ios/browser/js_suggestion_manager.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" @@ -255,12 +256,17 @@ } - (void)fetchPreviousAndNextElementsPresenceWithCompletionHandler: - (void (^)(BOOL, BOOL))completionHandler { + (void (^)(bool, bool))completionHandler { DCHECK(completionHandler); - [_JSSuggestionManager - fetchPreviousAndNextElementsPresenceInFrameWithID: - _lastFocusFormActivityWebFrameID - completionHandler:completionHandler]; + + if (!_JSSuggestionManager) { + completionHandler(false, false); + return; + } + + _JSSuggestionManager->FetchPreviousAndNextElementsPresenceInFrameWithID( + base::SysNSStringToUTF8(_lastFocusFormActivityWebFrameID), + base::BindOnce(completionHandler)); } #pragma mark - Private @@ -272,11 +278,12 @@ NSString* actionName = kFormSuggestionAssistButtonDone; BOOL performedAction = [self executeFormAssistAction:actionName]; - if (!performedAction && [_lastFocusFormActivityWebFrameID length]) { + if (!performedAction && [_lastFocusFormActivityWebFrameID length] && + _JSSuggestionManager) { // We could not find the built-in form assist controls, so try to focus // the next or previous control using JavaScript. - [_JSSuggestionManager - closeKeyboardForFrameWithID:_lastFocusFormActivityWebFrameID]; + _JSSuggestionManager->CloseKeyboardForFrameWithID( + base::SysNSStringToUTF8(_lastFocusFormActivityWebFrameID)); } if (loggingButtonPressed) { _keyboardAccessoryMetricsLogger->OnCloseButtonPressed(); @@ -290,11 +297,11 @@ NSString* actionName = kFormSuggestionAssistButtonPreviousElement; BOOL performedAction = [self executeFormAssistAction:actionName]; - if (!performedAction) { + if (!performedAction && _JSSuggestionManager) { // We could not find the built-in form assist controls, so try to focus // the next or previous control using JavaScript. - [_JSSuggestionManager - selectPreviousElementInFrameWithID:_lastFocusFormActivityWebFrameID]; + _JSSuggestionManager->SelectPreviousElementInFrameWithID( + base::SysNSStringToUTF8(_lastFocusFormActivityWebFrameID)); } if (loggingButtonPressed) { _keyboardAccessoryMetricsLogger->OnPreviousButtonPressed(); @@ -308,11 +315,11 @@ NSString* actionName = kFormSuggestionAssistButtonNextElement; BOOL performedAction = [self executeFormAssistAction:actionName]; - if (!performedAction) { + if (!performedAction && _JSSuggestionManager) { // We could not find the built-in form assist controls, so try to focus // the next or previous control using JavaScript. - [_JSSuggestionManager - selectNextElementInFrameWithID:_lastFocusFormActivityWebFrameID]; + _JSSuggestionManager->SelectNextElementInFrameWithID( + base::SysNSStringToUTF8(_lastFocusFormActivityWebFrameID)); } if (loggingButtonPressed) { _keyboardAccessoryMetricsLogger->OnNextButtonPressed();
diff --git a/ios/chrome/browser/autofill/form_input_accessory_view_handler_unittest.mm b/ios/chrome/browser/autofill/form_input_accessory_view_handler_unittest.mm index 22f9c78..54472cf 100644 --- a/ios/chrome/browser/autofill/form_input_accessory_view_handler_unittest.mm +++ b/ios/chrome/browser/autofill/form_input_accessory_view_handler_unittest.mm
@@ -23,10 +23,7 @@ [[FormInputAccessoryViewHandler alloc] init]; ASSERT_TRUE(accessory_view_delegate); [accessory_view_delegate closeKeyboardWithoutButtonPress]; - CRWJSInjectionReceiver* injection_receiver = - web_state()->GetJSInjectionReceiver(); accessory_view_delegate.JSSuggestionManager = - base::mac::ObjCCastStrict<JsSuggestionManager>( - [injection_receiver instanceOfClass:[JsSuggestionManager class]]); + autofill::JsSuggestionManager::GetOrCreateForWebState(web_state()); [accessory_view_delegate closeKeyboardWithoutButtonPress]; }
diff --git a/ios/chrome/browser/autofill/form_input_navigator.h b/ios/chrome/browser/autofill/form_input_navigator.h index e0dc03b..f03704f 100644 --- a/ios/chrome/browser/autofill/form_input_navigator.h +++ b/ios/chrome/browser/autofill/form_input_navigator.h
@@ -30,11 +30,11 @@ // Called when updating the keyboard view. Checks if the page contains a next // and a previous element. -// |completionHandler| is called with 2 BOOLs, the first indicating if a +// |completionHandler| is called with 2 bools, the first indicating if a // previous element was found, and the second indicating if a next element was // found. |completionHandler| cannot be nil. - (void)fetchPreviousAndNextElementsPresenceWithCompletionHandler: - (void (^)(BOOL, BOOL))completionHandler; + (void (^)(bool, bool))completionHandler; @end
diff --git a/ios/chrome/browser/autofill/form_suggestion_controller.h b/ios/chrome/browser/autofill/form_suggestion_controller.h index 41e0889..2d1755b 100644 --- a/ios/chrome/browser/autofill/form_suggestion_controller.h +++ b/ios/chrome/browser/autofill/form_suggestion_controller.h
@@ -52,12 +52,6 @@ @interface FormSuggestionController (ForTesting) -// Initializes a new controller in the same way as the public initializer, but -// supports specifying a JsSuggestionManager for testing. -- (instancetype)initWithWebState:(web::WebState*)webState - providers:(NSArray*)providers - JsSuggestionManager:(JsSuggestionManager*)jsSuggestionManager; - // Overrides the web view proxy. - (void)setWebViewProxy:(id<CRWWebViewProxy>)webViewProxy;
diff --git a/ios/chrome/browser/autofill/form_suggestion_controller.mm b/ios/chrome/browser/autofill/form_suggestion_controller.mm index e6a36bb..c6e29fd 100644 --- a/ios/chrome/browser/autofill/form_suggestion_controller.mm +++ b/ios/chrome/browser/autofill/form_suggestion_controller.mm
@@ -110,9 +110,6 @@ // Bridge to observe the web state from Objective-C. std::unique_ptr<web::WebStateObserverBridge> _webStateObserverBridge; - // Manager for FormSuggestion JavaScripts. - JsSuggestionManager* _jsSuggestionManager; - // The provider for the current set of suggestions. __weak id<FormSuggestionProvider> _provider; } @@ -120,8 +117,7 @@ @synthesize formInputNavigator = _formInputNavigator; - (instancetype)initWithWebState:(web::WebState*)webState - providers:(NSArray*)providers - JsSuggestionManager:(JsSuggestionManager*)jsSuggestionManager { + providers:(NSArray*)providers { self = [super init]; if (self) { DCHECK(webState); @@ -130,24 +126,11 @@ std::make_unique<web::WebStateObserverBridge>(self); _webState->AddObserver(_webStateObserverBridge.get()); _webViewProxy = webState->GetWebViewProxy(); - _jsSuggestionManager = jsSuggestionManager; _suggestionProviders = [providers copy]; } return self; } -- (instancetype)initWithWebState:(web::WebState*)webState - providers:(NSArray*)providers { - JsSuggestionManager* jsSuggestionManager = - base::mac::ObjCCast<JsSuggestionManager>( - [webState->GetJSInjectionReceiver() - instanceOfClass:[JsSuggestionManager class]]); - [jsSuggestionManager setWebFramesManager:webState->GetWebFramesManager()]; - return [self initWithWebState:webState - providers:providers - JsSuggestionManager:jsSuggestionManager]; -} - - (void)dealloc { if (_webState) { _webState->RemoveObserver(_webStateObserverBridge.get());
diff --git a/ios/chrome/browser/autofill/form_suggestion_controller_unittest.mm b/ios/chrome/browser/autofill/form_suggestion_controller_unittest.mm index a4289e4a..2da9678 100644 --- a/ios/chrome/browser/autofill/form_suggestion_controller_unittest.mm +++ b/ios/chrome/browser/autofill/form_suggestion_controller_unittest.mm
@@ -156,10 +156,6 @@ void SetUp() override { PlatformTest::SetUp(); - // Mock out the JsSuggestionManager. - mock_js_suggestion_manager_ = - [OCMockObject niceMockForClass:[JsSuggestionManager class]]; - fake_web_state_.SetWebViewProxy(mock_web_view_proxy_); } @@ -172,10 +168,9 @@ // Sets up |suggestion_controller_| with the specified array of // FormSuggestionProviders. void SetUpController(NSArray* providers) { - suggestion_controller_ = [[FormSuggestionController alloc] - initWithWebState:&fake_web_state_ - providers:providers - JsSuggestionManager:mock_js_suggestion_manager_]; + suggestion_controller_ = + [[FormSuggestionController alloc] initWithWebState:&fake_web_state_ + providers:providers]; [suggestion_controller_ setWebViewProxy:mock_web_view_proxy_]; id mock_consumer = [OCMockObject @@ -217,7 +212,6 @@ [accessory_mediator_ injectWebState:&fake_web_state_]; [accessory_mediator_ injectProvider:suggestion_controller_]; - [accessory_mediator_ injectSuggestionManager:mock_js_suggestion_manager_]; } // The FormSuggestionController under test. @@ -226,9 +220,6 @@ // The suggestions the controller sent to the client, if any. NSArray* received_suggestions_; - // Mock JsSuggestionManager for verifying interactions. - id mock_js_suggestion_manager_; - // Mock CRWWebViewProxy for verifying interactions. id mock_web_view_proxy_; @@ -253,7 +244,6 @@ fake_web_state_.SetCurrentURL(GURL("data:text/html;charset=utf8;base64,")); fake_web_state_.OnPageLoaded(web::PageLoadCompletionStatus::SUCCESS); EXPECT_FALSE(received_suggestions_.count); - EXPECT_OCMOCK_VERIFY(mock_js_suggestion_manager_); } // Tests that pages whose content isn't HTML aren't processed.
diff --git a/ios/chrome/browser/autofill/js_suggestion_manager_unittest.mm b/ios/chrome/browser/autofill/js_suggestion_manager_unittest.mm index 99937d4..a1641ea 100644 --- a/ios/chrome/browser/autofill/js_suggestion_manager_unittest.mm +++ b/ios/chrome/browser/autofill/js_suggestion_manager_unittest.mm
@@ -31,7 +31,7 @@ JsSuggestionManagerTest() : ChromeWebTest(std::make_unique<ChromeWebClient>()) {} // Returns the frame ID for the main frame of |web_state()|'s current page. - NSString* GetFrameIdForMainFrame(); + std::string GetFrameIdForMainFrame(); // Helper method that initializes a form with three fields. Can be used to // test whether adding an attribute on the second field causes it to be // skipped (or not, as is appropriate) by selectNextElement. @@ -47,19 +47,17 @@ return [GetActiveElementName() isEqualToString:name]; }); } - JsSuggestionManager* manager_; + autofill::JsSuggestionManager* manager_; }; void JsSuggestionManagerTest::SetUp() { ChromeWebTest::SetUp(); - manager_ = [[JsSuggestionManager alloc] - initWithReceiver:web_state()->GetJSInjectionReceiver()]; - [manager_ setWebFramesManager:web_state()->GetWebFramesManager()]; + manager_ = autofill::JsSuggestionManager::GetOrCreateForWebState(web_state()); } -NSString* JsSuggestionManagerTest::GetFrameIdForMainFrame() { +std::string JsSuggestionManagerTest::GetFrameIdForMainFrame() { web::WebFramesManager* manager = web_state()->GetWebFramesManager(); - return base::SysUTF8ToNSString(manager->GetMainWebFrame()->GetFrameId()); + return manager->GetMainWebFrame()->GetFrameId(); } TEST_F(JsSuggestionManagerTest, InitAndInject) { @@ -234,24 +232,22 @@ ExecuteJavaScript(@"document.getElementsByName('firstname')[0].focus()"); - [manager_ selectNextElementInFrameWithID:GetFrameIdForMainFrame()]; + manager_->SelectNextElementInFrameWithID(GetFrameIdForMainFrame()); EXPECT_TRUE(WaitUntilElementSelected(@"lastname")); __block BOOL block_was_called = NO; - [manager_ - fetchPreviousAndNextElementsPresenceInFrameWithID:GetFrameIdForMainFrame() - completionHandler:^void( - BOOL has_previous_element, - BOOL has_next_element) { - block_was_called = YES; - EXPECT_TRUE(has_previous_element); - EXPECT_TRUE(has_next_element); - }]; + manager_->FetchPreviousAndNextElementsPresenceInFrameWithID( + GetFrameIdForMainFrame(), + base::BindOnce(^void(bool has_previous_element, bool has_next_element) { + block_was_called = YES; + EXPECT_TRUE(has_previous_element); + EXPECT_TRUE(has_next_element); + })); base::test::ios::WaitUntilCondition(^bool() { return block_was_called; }); - [manager_ selectNextElementInFrameWithID:GetFrameIdForMainFrame()]; + manager_->SelectNextElementInFrameWithID(GetFrameIdForMainFrame()); EXPECT_TRUE(WaitUntilElementSelected(@"email")); - [manager_ selectPreviousElementInFrameWithID:GetFrameIdForMainFrame()]; + manager_->SelectPreviousElementInFrameWithID(GetFrameIdForMainFrame()); EXPECT_TRUE(WaitUntilElementSelected(@"lastname")); } @@ -266,7 +262,7 @@ attribute]); ExecuteJavaScript(@"document.getElementsByName('firstname')[0].focus()"); EXPECT_NSEQ(@"firstname", GetActiveElementName()); - [manager_ selectNextElementInFrameWithID:GetFrameIdForMainFrame()]; + manager_->SelectNextElementInFrameWithID(GetFrameIdForMainFrame()); if (shouldSkip) EXPECT_TRUE(WaitUntilElementSelected(@"lastname")); else @@ -331,7 +327,7 @@ @"select.onblur = function(){window.location.href = '#test'}"); ExecuteJavaScript(@"select.focus()"); // In the failure condition the app will crash during the next line. - [manager_ closeKeyboardForFrameWithID:GetFrameIdForMainFrame()]; + manager_->CloseKeyboardForFrameWithID(GetFrameIdForMainFrame()); // TODO(crbug.com/661624): add a check for the keyboard actually being // dismissed; unfortunately it is not known how to adapt // WaitForBackgroundTasks to yield for events wrapped with window.setTimeout() @@ -339,7 +335,7 @@ } // Test fixture to test -// |fetchPreviousAndNextElementsPresenceWithCompletionHandler|. +// |FetchPreviousAndNextElementsPresenceInFrameWithID|. class FetchPreviousAndNextExceptionTest : public JsSuggestionManagerTest { public: void SetUp() override { @@ -349,20 +345,18 @@ protected: // Evaluates JS and tests that the completion handler passed to - // |fetchPreviousAndNextElementsPresenceWithCompletionHandler| is called with - // (NO, NO) indicating no previous and next element. + // |FetchPreviousAndNextElementsPresenceInFrameWithID| is called with + // (false, false) indicating no previous and next element. void EvaluateJavaScriptAndExpectNoPreviousAndNextElement(NSString* js) { ExecuteJavaScript(js); __block BOOL block_was_called = NO; - id completionHandler = ^(BOOL hasPreviousElement, BOOL hasNextElement) { - EXPECT_FALSE(hasPreviousElement); - EXPECT_FALSE(hasNextElement); - block_was_called = YES; - }; - [manager_ - fetchPreviousAndNextElementsPresenceInFrameWithID: - GetFrameIdForMainFrame() - completionHandler:completionHandler]; + manager_->FetchPreviousAndNextElementsPresenceInFrameWithID( + GetFrameIdForMainFrame(), + base::BindOnce(^(bool hasPreviousElement, bool hasNextElement) { + EXPECT_FALSE(hasPreviousElement); + EXPECT_FALSE(hasNextElement); + block_was_called = YES; + })); base::test::ios::WaitUntilCondition(^bool() { base::RunLoop().RunUntilIdle(); return block_was_called;
diff --git a/ios/chrome/browser/passwords/password_controller_unittest.mm b/ios/chrome/browser/passwords/password_controller_unittest.mm index 491b312..d621f52 100644 --- a/ios/chrome/browser/passwords/password_controller_unittest.mm +++ b/ios/chrome/browser/passwords/password_controller_unittest.mm
@@ -1226,11 +1226,6 @@ ON_CALL(*store_, IsAbleToSavePasswords).WillByDefault(Return(true)); std::unique_ptr<TestChromeBrowserState> browser_state(builder.Build()); - id mock_js_injection_receiver = - [OCMockObject mockForClass:[CRWJSInjectionReceiver class]]; - [[mock_js_injection_receiver expect] executeJavaScript:[OCMArg any] - completionHandler:[OCMArg any]]; - web_state_.SetJSInjectionReceiver(mock_js_injection_receiver); ON_CALL(web_state_, GetBrowserState) .WillByDefault(testing::Return(browser_state.get())); UniqueIDDataTabHelper::CreateForWebState(&web_state_);
diff --git a/ios/chrome/browser/prerender/preload_controller.mm b/ios/chrome/browser/prerender/preload_controller.mm index 5adbd51..62b108c 100644 --- a/ios/chrome/browser/prerender/preload_controller.mm +++ b/ios/chrome/browser/prerender/preload_controller.mm
@@ -144,7 +144,7 @@ // Maximum time to let a cancelled webState attempt to finish restore. static const size_t kMaximumCancelledWebStateDelay = 2; -// Used to enable the workaround for a WebKit crash, see crbug.com/1032928. +// Kill switch guarding a workaround for a WebKit crash, see crbug.com/1032928. const base::Feature kPreloadDelayWebStateReset{ "PreloadDelayWebStateReset", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/ios/chrome/browser/ui/alert_view/alert_view_controller.mm b/ios/chrome/browser/ui/alert_view/alert_view_controller.mm index fd34467..1538693 100644 --- a/ios/chrome/browser/ui/alert_view/alert_view_controller.mm +++ b/ios/chrome/browser/ui/alert_view/alert_view_controller.mm
@@ -144,8 +144,7 @@ self.contentView = [[UIView alloc] init]; self.contentView.accessibilityIdentifier = self.alertAccessibilityIdentifier; self.contentView.clipsToBounds = YES; - self.contentView.backgroundColor = - [UIColor colorNamed:kPrimaryBackgroundColor]; + self.contentView.backgroundColor = UIColor.cr_systemBackgroundColor; self.contentView.layer.cornerRadius = kCornerRadius; self.contentView.layer.shadowOffset = CGSizeMake(kShadowOffsetX, kShadowOffsetY); @@ -295,8 +294,7 @@ } stackHolder.layer.borderWidth = 1.0 / [UIScreen mainScreen].scale; stackHolder.clipsToBounds = YES; - stackHolder.backgroundColor = - [UIColor colorNamed:kSecondaryBackgroundColor]; + stackHolder.backgroundColor = UIColor.cr_secondarySystemBackgroundColor; stackHolder.translatesAutoresizingMaskIntoConstraints = NO; self.textFieldStackHolder = stackHolder;
diff --git a/ios/chrome/browser/ui/authentication/signin/user_signin/gradient_view.mm b/ios/chrome/browser/ui/authentication/signin/user_signin/gradient_view.mm index 220c77a..44cb6fd 100644 --- a/ios/chrome/browser/ui/authentication/signin/user_signin/gradient_view.mm +++ b/ios/chrome/browser/ui/authentication/signin/user_signin/gradient_view.mm
@@ -5,7 +5,7 @@ #import "ios/chrome/browser/ui/authentication/signin/user_signin/gradient_view.h" #import "base/mac/foundation_util.h" -#import "ios/chrome/common/ui/colors/semantic_color_names.h" +#import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -53,9 +53,8 @@ [CATransaction setDisableActions:YES]; self.gradientLayer.colors = @[ - (id)[[UIColor colorNamed:kPrimaryBackgroundColor] colorWithAlphaComponent:0] - .CGColor, - (id)[UIColor colorNamed:kPrimaryBackgroundColor].CGColor, + (id)[UIColor.cr_systemBackgroundColor colorWithAlphaComponent:0].CGColor, + (id)UIColor.cr_systemBackgroundColor.CGColor, ]; [CATransaction commit]; }
diff --git a/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_coordinator.mm b/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_coordinator.mm index 5bd1c58..87f3094a 100644 --- a/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_coordinator.mm +++ b/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_coordinator.mm
@@ -23,6 +23,7 @@ #import "ios/chrome/browser/ui/authentication/unified_consent/unified_consent_coordinator.h" #import "ios/chrome/browser/ui/commands/browsing_data_commands.h" #import "ios/chrome/browser/ui/commands/command_dispatcher.h" +#import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/browser/unified_consent/unified_consent_service_factory.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -213,6 +214,15 @@ [self interruptUserSigninUIWithAction:action completion:completion]; } +- (void)stop { + DCHECK(!self.viewController); + DCHECK(!self.mediator); + DCHECK(!self.unifiedConsentCoordinator); + DCHECK(!self.addAccountSigninCoordinator); + DCHECK(!self.advancedSettingsSigninCoordinator); + [super stop]; +} + #pragma mark - UnifiedConsentCoordinatorDelegate - (void)unifiedConsentCoordinatorDidTapSettingsLink: @@ -432,8 +442,7 @@ // Avoid presenting the promo if the current device orientation is not // supported. The promo will be presented at a later moment, when the // device orientation is supported. - UIInterfaceOrientation orientation = - [UIApplication sharedApplication].statusBarOrientation; + UIInterfaceOrientation orientation = GetInterfaceOrientation(); NSUInteger supportedOrientationsMask = [self.viewController supportedInterfaceOrientations]; if (!((1 << orientation) & supportedOrientationsMask)) { @@ -505,10 +514,10 @@ __weak UserSigninCoordinator* weakSelf = self; ProceduralBlock runCompletionCallback = ^{ [weakSelf - runCompletionCallbackWithSigninResult:SigninCoordinatorResultInterrupted - identity:self.unifiedConsentCoordinator - .selectedIdentity - showAdvancedSettingsSignin:NO]; + viewControllerDismissedWithResult:SigninCoordinatorResultInterrupted + identity:weakSelf.unifiedConsentCoordinator + .selectedIdentity + settingsLinkWasTapped:NO]; if (completion) { completion(); }
diff --git a/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_view_controller.mm b/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_view_controller.mm index 90ad96b..c93c77f 100644 --- a/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_view_controller.mm +++ b/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_view_controller.mm
@@ -12,6 +12,7 @@ #import "ios/chrome/browser/ui/authentication/signin/user_signin/gradient_view.h" #import "ios/chrome/browser/ui/util/rtl_geometry.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" +#import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" #import "ios/chrome/common/ui/colors/semantic_color_names.h" #import "ios/chrome/common/ui/util/constraints_ui_util.h" #import "ios/chrome/common/ui/util/pointer_interaction_util.h" @@ -306,7 +307,7 @@ #pragma mark - Properties - (UIColor*)systemBackgroundColor { - return [UIColor colorNamed:kPrimaryBackgroundColor]; + return UIColor.cr_systemBackgroundColor; } - (NSString*)confirmationButtonTitle {
diff --git a/ios/chrome/browser/ui/authentication/unified_consent/identity_picker_view.mm b/ios/chrome/browser/ui/authentication/unified_consent/identity_picker_view.mm index 6d8ccf65..538e5e1 100644 --- a/ios/chrome/browser/ui/authentication/unified_consent/identity_picker_view.mm +++ b/ios/chrome/browser/ui/authentication/unified_consent/identity_picker_view.mm
@@ -12,7 +12,6 @@ #import "ios/chrome/browser/ui/authentication/unified_consent/unified_consent_constants.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" -#import "ios/chrome/common/ui/colors/semantic_color_names.h" #import "ios/chrome/common/ui/util/constraints_ui_util.h" #import "ios/chrome/common/ui/util/pointer_interaction_util.h" @@ -48,7 +47,7 @@ if (self) { self.accessibilityIdentifier = kIdentityPickerViewIdentifier; self.layer.cornerRadius = kIdentityPickerViewRadius; - self.backgroundColor = [UIColor colorNamed:kSecondaryBackgroundColor]; + self.backgroundColor = UIColor.cr_secondarySystemBackgroundColor; // Adding view elements inside. // Ink view. _rippleView = [[MDCRippleView alloc] initWithFrame:CGRectZero];
diff --git a/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.mm b/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.mm index 10c7f11..1f2f4900 100644 --- a/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.mm +++ b/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.mm
@@ -193,7 +193,7 @@ // Separator. UIView* separator = [[UIView alloc] initWithFrame:CGRectZero]; separator.translatesAutoresizingMaskIntoConstraints = NO; - separator.backgroundColor = [UIColor colorNamed:kSecondaryBackgroundColor]; + separator.backgroundColor = UIColor.cr_secondarySystemBackgroundColor; [container addSubview:separator]; // Customize label.
diff --git a/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.mm b/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.mm index f4f718d..b40bbe9 100644 --- a/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.mm +++ b/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.mm
@@ -22,6 +22,7 @@ #import "ios/chrome/browser/ui/collection_view/collection_view_controller.h" #import "ios/chrome/browser/ui/collection_view/collection_view_model.h" #import "ios/chrome/browser/ui/util/rtl_geometry.h" +#import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/common/ui/colors/semantic_color_names.h" #include "ui/base/l10n/l10n_util.h" @@ -363,8 +364,7 @@ // Focus the first visible input, unless the orientation is landscape. In // landscape, the keyboard covers up the storage checkbox shown below this // view and the user might never see it. - if (UIInterfaceOrientationIsPortrait( - [UIApplication sharedApplication].statusBarOrientation)) { + if (UIInterfaceOrientationIsPortrait(GetInterfaceOrientation())) { // Also check whether any of the inputs are already the first responder and // are non-empty, in which case the focus should be left there. if ((!CVC.monthInput.isFirstResponder || CVC.monthInput.text.length == 0) &&
diff --git a/ios/chrome/browser/ui/autofill/form_input_accessory/form_input_accessory_mediator.h b/ios/chrome/browser/ui/autofill/form_input_accessory/form_input_accessory_mediator.h index 63bbcbf..40d289a0 100644 --- a/ios/chrome/browser/ui/autofill/form_input_accessory/form_input_accessory_mediator.h +++ b/ios/chrome/browser/ui/autofill/form_input_accessory/form_input_accessory_mediator.h
@@ -18,7 +18,6 @@ @protocol FormInputAccessoryConsumer; @class FormInputAccessoryMediator; @protocol FormInputSuggestionsProvider; -@class JsSuggestionManager; @class ReauthenticationModule; @protocol SecurityAlertCommands; @@ -86,9 +85,6 @@ // The WebState this instance is observing. Can be null. - (void)injectWebState:(web::WebState*)webState; -// The JS manager for interacting with the underlying form. -- (void)injectSuggestionManager:(JsSuggestionManager*)JSSuggestionManager; - // Replaces the object in charge of providing suggestions. - (void)injectProvider:(id<FormInputSuggestionsProvider>)provider;
diff --git a/ios/chrome/browser/ui/autofill/form_input_accessory/form_input_accessory_mediator.mm b/ios/chrome/browser/ui/autofill/form_input_accessory/form_input_accessory_mediator.mm index eb1d693..2ecaa70 100644 --- a/ios/chrome/browser/ui/autofill/form_input_accessory/form_input_accessory_mediator.mm +++ b/ios/chrome/browser/ui/autofill/form_input_accessory/form_input_accessory_mediator.mm
@@ -73,9 +73,6 @@ @property(nonatomic, strong) FormInputAccessoryViewHandler* formInputAccessoryHandler; -// The JS manager for interacting with the underlying form. -@property(nonatomic, weak) JsSuggestionManager* JSSuggestionManager; - // The observer to determine when the keyboard dissapears and when it stays. @property(nonatomic, strong) KeyboardObserverHelper* keyboardObserver; @@ -164,12 +161,6 @@ web::WebState* webState = webStateList->GetActiveWebState(); if (webState) { _webState = webState; - CRWJSInjectionReceiver* injectionReceiver = - webState->GetJSInjectionReceiver(); - _JSSuggestionManager = base::mac::ObjCCastStrict<JsSuggestionManager>( - [injectionReceiver instanceOfClass:[JsSuggestionManager class]]); - [_JSSuggestionManager - setWebFramesManager:webState->GetWebFramesManager()]; FormSuggestionTabHelper* tabHelper = FormSuggestionTabHelper::FromWebState(webState); if (tabHelper) { @@ -184,7 +175,10 @@ } } _formInputAccessoryHandler = [[FormInputAccessoryViewHandler alloc] init]; - _formInputAccessoryHandler.JSSuggestionManager = _JSSuggestionManager; + _formInputAccessoryHandler.JSSuggestionManager = + _webState + ? autofill::JsSuggestionManager::GetOrCreateForWebState(_webState) + : nullptr; NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter]; [defaultCenter addObserver:self @@ -464,7 +458,7 @@ __weak __typeof(self) weakSelf = self; [self.formInputAccessoryHandler fetchPreviousAndNextElementsPresenceWithCompletionHandler:^( - BOOL previousButtonEnabled, BOOL nextButtonEnabled) { + bool previousButtonEnabled, bool nextButtonEnabled) { weakSelf.consumer.formInputNextButtonEnabled = nextButtonEnabled; weakSelf.consumer.formInputPreviousButtonEnabled = previousButtonEnabled; @@ -483,21 +477,15 @@ webState->AddObserver(_webStateObserverBridge.get()); _formActivityObserverBridge = std::make_unique<autofill::FormActivityObserverBridge>(webState, self); - CRWJSInjectionReceiver* injectionReceiver = - webState->GetJSInjectionReceiver(); - self.JSSuggestionManager = base::mac::ObjCCastStrict<JsSuggestionManager>( - [injectionReceiver instanceOfClass:[JsSuggestionManager class]]); - [self.JSSuggestionManager - setWebFramesManager:webState->GetWebFramesManager()]; FormSuggestionTabHelper* tabHelper = FormSuggestionTabHelper::FromWebState(webState); if (tabHelper) { self.provider = tabHelper->GetAccessoryViewProvider(); } - _formInputAccessoryHandler.JSSuggestionManager = self.JSSuggestionManager; + _formInputAccessoryHandler.JSSuggestionManager = + autofill::JsSuggestionManager::GetOrCreateForWebState(webState); } else { self.webState = nullptr; - self.JSSuggestionManager = nil; self.provider = nil; } } @@ -703,11 +691,6 @@ std::make_unique<autofill::FormActivityObserverBridge>(_webState, self); } -- (void)injectSuggestionManager:(JsSuggestionManager*)JSSuggestionManager { - _JSSuggestionManager = JSSuggestionManager; - _formInputAccessoryHandler.JSSuggestionManager = _JSSuggestionManager; -} - - (void)injectProvider:(id<FormInputSuggestionsProvider>)provider { self.provider = provider; }
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_injection_handler.mm b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_injection_handler.mm index ff0ac7a..11f389b 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_injection_handler.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_injection_handler.mm
@@ -55,7 +55,7 @@ @property(nonatomic, readonly) CRWJSInjectionReceiver* injectionReceiver; // Convenience getter for the current suggestion manager. -@property(nonatomic, readonly) JsSuggestionManager* suggestionManager; +@property(nonatomic, readonly) autofill::JsSuggestionManager* suggestionManager; // Interface for |reauthenticationModule|, handling mostly the case when no // hardware for authentication is available. @@ -192,14 +192,14 @@ return nil; } -- (JsSuggestionManager*)suggestionManager { - JsSuggestionManager* manager = base::mac::ObjCCastStrict<JsSuggestionManager>( - [self.injectionReceiver instanceOfClass:[JsSuggestionManager class]]); +- (autofill::JsSuggestionManager*)suggestionManager { + autofill::JsSuggestionManager* suggestionManager = nullptr; web::WebState* webState = self.webStateList->GetActiveWebState(); if (webState) { - [manager setWebFramesManager:webState->GetWebFramesManager()]; + suggestionManager = + autofill::JsSuggestionManager::GetOrCreateForWebState(webState); } - return manager; + return suggestionManager; } #pragma mark - Private
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_navigation_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_navigation_controller.mm index 7cd5405d..f09595a 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_navigation_controller.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_navigation_controller.mm
@@ -6,7 +6,7 @@ #import "ios/chrome/browser/ui/bookmarks/bookmark_ui_constants.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h" -#import "ios/chrome/common/ui/colors/semantic_color_names.h" +#import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -16,7 +16,7 @@ - (void)viewDidLoad { [super viewDidLoad]; - self.view.backgroundColor = [UIColor colorNamed:kPrimaryBackgroundColor]; + self.view.backgroundColor = UIColor.cr_systemBackgroundColor; self.navigationBar.accessibilityIdentifier = kBookmarkNavigationBarIdentifier; }
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm index e493c7e..3c24886 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -606,6 +606,11 @@ @property(nonatomic, strong) BrowserViewHiderCoordinator* browserViewHiderCoordinator; +// Whether the view has been translated for thumb strip usage when smooth +// scrolling has been enabled. This allows the correct setup to be done when +// displaying a new web state. +@property(nonatomic, assign) BOOL viewTranslatedForSmoothScrolling; + // BVC initialization // ------------------ // If the BVC is initialized with a valid browser state & tab model immediately, @@ -1439,7 +1444,6 @@ [self installFakeStatusBar]; [self buildToolbarAndTabStrip]; [self setUpViewLayout:YES]; - [self addConstraintsToTabStrip]; [self addConstraintsToToolbar]; // If the tab model and browser state are valid, finish initialization. @@ -2282,6 +2286,7 @@ [self addChildViewController:self.tabStripCoordinator.viewController]; self.tabStripView = self.tabStripCoordinator.view; [self.view addSubview:self.tabStripView]; + [self addConstraintsToTabStrip]; } [self.view insertSubview:primaryToolbarView aboveSubview:self.tabStripView]; @@ -2408,7 +2413,15 @@ // Make new content visible, resizing it first as the orientation may // have changed from the last time it was displayed. CGRect webStateViewFrame = self.contentArea.bounds; - if (!fullscreen::features::ShouldUseSmoothScrolling()) { + if (fullscreen::features::ShouldUseSmoothScrolling()) { + // If the view was translated for the thumb strip, make sure to re-apply + // that translation here. + if (self.viewTranslatedForSmoothScrolling) { + CGFloat toolbarHeight = [self expandedTopToolbarHeight]; + webStateViewFrame = UIEdgeInsetsInsetRect( + webStateViewFrame, UIEdgeInsetsMake(toolbarHeight, 0, 0, 0)); + } + } else { // If the Smooth Scrolling is on, the WebState view is not // resized, and should always match the bounds of the content area. When // the provider is not initialized, viewport insets resize the webview, so @@ -2908,25 +2921,32 @@ // frame must be moved down and the content inset is decreased. To prevent // the actual web content from jumping, the content offset must be moved up // by a corresponding amount. - if (self.currentWebState && ![self isNTPActiveForCurrentWebState] && - fullscreen::features::ShouldUseSmoothScrolling()) { + if (fullscreen::features::ShouldUseSmoothScrolling()) { + self.viewTranslatedForSmoothScrolling = YES; CGFloat toolbarHeight = [self expandedTopToolbarHeight]; - CGRect webStateViewFrame = UIEdgeInsetsInsetRect( - [self viewForWebState:self.currentWebState].frame, - UIEdgeInsetsMake(toolbarHeight, 0, 0, 0)); - [self viewForWebState:self.currentWebState].frame = webStateViewFrame; + if (self.currentWebState) { + CGRect webStateViewFrame = UIEdgeInsetsInsetRect( + [self viewForWebState:self.currentWebState].frame, + UIEdgeInsetsMake(toolbarHeight, 0, 0, 0)); + [self viewForWebState:self.currentWebState].frame = webStateViewFrame; + } - CRWWebViewScrollViewProxy* scrollProxy = - self.currentWebState->GetWebViewProxy().scrollViewProxy; - CGPoint scrollOffset = scrollProxy.contentOffset; - scrollOffset.y += toolbarHeight; - scrollProxy.contentOffset = scrollOffset; - - // TODO(crbug.com/1155536): Inform FullscreenController about these - // changes and allow it to calculate the correct overall contentInset. - UIEdgeInsets contentInset = scrollProxy.contentInset; - contentInset.top -= toolbarHeight; - scrollProxy.contentInset = contentInset; + // Translate all web states' offset so web states from other tabs are also + // updated. + if (self.browser) { + WebStateList* webStateList = self.browser->GetWebStateList(); + for (int index = 0; index < webStateList->count(); ++index) { + web::WebState* webState = webStateList->GetWebStateAt(index); + CRWWebViewScrollViewProxy* scrollProxy = + webState->GetWebViewProxy().scrollViewProxy; + CGPoint scrollOffset = scrollProxy.contentOffset; + scrollOffset.y += toolbarHeight; + scrollProxy.contentOffset = scrollOffset; + } + } + // This alerts the fullscreen controller to use the correct new content + // insets. + self.fullscreenController->FreezeToolbarHeight(true); } } } @@ -2973,25 +2993,31 @@ [self installFakeStatusBar]; [self setupStatusBarLayout]; - // See the comments in |-willAnimateViewReveal:| for the explantation of why + // See the comments in |-willAnimateViewReveal:| for the explanation of why // this is necessary. - if (self.currentWebState && ![self isNTPActiveForCurrentWebState] && - fullscreen::features::ShouldUseSmoothScrolling()) { + if (fullscreen::features::ShouldUseSmoothScrolling()) { + self.viewTranslatedForSmoothScrolling = NO; + self.fullscreenController->FreezeToolbarHeight(false); CGFloat toolbarHeight = [self expandedTopToolbarHeight]; - CGRect webStateViewFrame = UIEdgeInsetsInsetRect( - [self viewForWebState:self.currentWebState].frame, - UIEdgeInsetsMake(-toolbarHeight, 0, 0, 0)); - [self viewForWebState:self.currentWebState].frame = webStateViewFrame; + if (self.currentWebState) { + CGRect webStateViewFrame = UIEdgeInsetsInsetRect( + [self viewForWebState:self.currentWebState].frame, + UIEdgeInsetsMake(-toolbarHeight, 0, 0, 0)); + [self viewForWebState:self.currentWebState].frame = webStateViewFrame; + } - CRWWebViewScrollViewProxy* scrollProxy = - self.currentWebState->GetWebViewProxy().scrollViewProxy; - UIEdgeInsets contentInset = scrollProxy.contentInset; - contentInset.top += toolbarHeight; - scrollProxy.contentInset = contentInset; + if (self.browser) { + WebStateList* webStateList = self.browser->GetWebStateList(); + for (int index = 0; index < webStateList->count(); ++index) { + web::WebState* webState = webStateList->GetWebStateAt(index); + CRWWebViewScrollViewProxy* scrollProxy = + webState->GetWebViewProxy().scrollViewProxy; - CGPoint scrollOffset = scrollProxy.contentOffset; - scrollOffset.y -= toolbarHeight; - scrollProxy.contentOffset = scrollOffset; + CGPoint scrollOffset = scrollProxy.contentOffset; + scrollOffset.y -= toolbarHeight; + scrollProxy.contentOffset = scrollOffset; + } + } } } }
diff --git a/ios/chrome/browser/ui/collection_view/collection_view_controller.mm b/ios/chrome/browser/ui/collection_view/collection_view_controller.mm index a62dbb3..efe8c6ee 100644 --- a/ios/chrome/browser/ui/collection_view/collection_view_controller.mm +++ b/ios/chrome/browser/ui/collection_view/collection_view_controller.mm
@@ -13,7 +13,7 @@ #import "ios/chrome/browser/ui/collection_view/collection_view_model.h" #import "ios/chrome/browser/ui/material_components/chrome_app_bar_view_controller.h" #import "ios/chrome/browser/ui/material_components/utils.h" -#import "ios/chrome/common/ui/colors/semantic_color_names.h" +#import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -65,10 +65,9 @@ } // Suport dark mode. - self.collectionView.backgroundColor = - [UIColor colorNamed:kGroupedPrimaryBackgroundColor]; + self.collectionView.backgroundColor = UIColor.cr_systemGroupedBackgroundColor; self.styler.cellBackgroundColor = - [UIColor colorNamed:kGroupedSecondaryBackgroundColor]; + UIColor.cr_secondarySystemGroupedBackgroundColor; } - (void)contentSizeCategoryDidChange:(id)sender {
diff --git a/ios/chrome/browser/ui/fancy_ui/primary_action_button.mm b/ios/chrome/browser/ui/fancy_ui/primary_action_button.mm index a87ae86..29a07fc 100644 --- a/ios/chrome/browser/ui/fancy_ui/primary_action_button.mm +++ b/ios/chrome/browser/ui/fancy_ui/primary_action_button.mm
@@ -5,6 +5,7 @@ #import "ios/chrome/browser/ui/fancy_ui/primary_action_button.h" #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" +#import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" #import "ios/chrome/common/ui/colors/semantic_color_names.h" #import "ios/chrome/common/ui/util/pointer_interaction_util.h" @@ -42,7 +43,7 @@ } #endif // defined(__IPHONE_13_4) - UIColor* hintColor = [UIColor colorNamed:kPrimaryBackgroundColor]; + UIColor* hintColor = UIColor.cr_systemBackgroundColor; UIColor* inkColor = [UIColor colorWithWhite:1 alpha:0.2f]; UIColor* backgroundColor = [UIColor colorNamed:kBlueColor]; UIColor* disabledColor = [UIColor colorNamed:kDisabledTintColor];
diff --git a/ios/chrome/browser/ui/first_run/static_file_view_controller.mm b/ios/chrome/browser/ui/first_run/static_file_view_controller.mm index b61597a..68958ff 100644 --- a/ios/chrome/browser/ui/first_run/static_file_view_controller.mm +++ b/ios/chrome/browser/ui/first_run/static_file_view_controller.mm
@@ -13,7 +13,7 @@ #import "ios/chrome/browser/ui/icons/chrome_icon.h" #import "ios/chrome/browser/ui/material_components/utils.h" #include "ios/chrome/browser/ui/util/rtl_geometry.h" -#import "ios/chrome/common/ui/colors/semantic_color_names.h" +#import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" #import "ios/web/common/web_view_creation_util.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -70,7 +70,7 @@ cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60.0]; [_webView loadRequest:request]; - [_webView setBackgroundColor:[UIColor colorNamed:kPrimaryBackgroundColor]]; + [_webView setBackgroundColor:UIColor.cr_systemBackgroundColor]; [self.view addSubview:_webView]; ConfigureAppBarViewControllerWithCardStyle(_appBarViewController);
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_controller.h b/ios/chrome/browser/ui/fullscreen/fullscreen_controller.h index 89a4c71..5777475 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_controller.h +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_controller.h
@@ -87,6 +87,8 @@ // 1.0. virtual void ExitFullscreen() = 0; + virtual void FreezeToolbarHeight(bool freeze_toolbar_height) = 0; + // Force horizontal content resize, when content isn't tracking resize by // itself. virtual void ResizeHorizontalViewport() = 0;
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.h b/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.h index de79087..495bf30 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.h +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.h
@@ -48,6 +48,7 @@ void EnterFullscreen() override; void ExitFullscreen() override; void ResizeHorizontalViewport() override; + void FreezeToolbarHeight(bool freeze_toolbar_height) override; private:
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.mm index 9148bf6..a226ac2 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.mm +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.mm
@@ -177,3 +177,7 @@ // two relayouts. mediator_.ResizeHorizontalInsets(); } + +void FullscreenControllerImpl::FreezeToolbarHeight(bool freeze_toolbar_height) { + model_.SetFreezeToolbarHeight(freeze_toolbar_height); +}
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_model.h b/ios/chrome/browser/ui/fullscreen/fullscreen_model.h index 3b2d83b..cd4ee0e7 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_model.h +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_model.h
@@ -46,7 +46,7 @@ // Returns the difference between the max and min toolbar heights. CGFloat toolbar_height_delta() const { - return expanded_toolbar_height_ - collapsed_toolbar_height_; + return GetExpandedToolbarHeight() - GetCollapsedToolbarHeight(); } // Returns whether the page content is tall enough for the toolbar to be @@ -57,7 +57,7 @@ // Whether the view is scrolled all the way to the top. bool is_scrolled_to_top() const { - return y_content_offset_ <= -expanded_toolbar_height_; + return y_content_offset_ <= -GetExpandedToolbarHeight(); } // Whether the view is scrolled all the way to the bottom. @@ -79,8 +79,8 @@ // Returns the toolbar insets at |progress|. UIEdgeInsets GetToolbarInsetsAtProgress(CGFloat progress) const { return UIEdgeInsetsMake( - collapsed_toolbar_height_ + - progress * (expanded_toolbar_height_ - collapsed_toolbar_height_), + GetCollapsedToolbarHeight() + progress * (GetExpandedToolbarHeight() - + GetCollapsedToolbarHeight()), 0, progress * bottom_toolbar_height_, 0); } @@ -157,6 +157,9 @@ void SetWebViewSafeAreaInsets(UIEdgeInsets safe_area_insets); UIEdgeInsets GetWebViewSafeAreaInsets() const; + void SetFreezeToolbarHeight(bool freeze_toolbar_height); + bool GetFreezeToolbarHeight() const; + private: // Returns how a scroll to the current |y_content_offset_| from |from_offset| // should be handled. @@ -234,6 +237,7 @@ UIEdgeInsets safe_area_insets_ = UIEdgeInsetsZero; // The number of FullscreenModelObserver callbacks currently being executed. size_t observer_callback_count_ = 0; + bool freeze_toolbar_height_ = false; DISALLOW_COPY_AND_ASSIGN(FullscreenModel); };
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm index e24cfa52..74f4bb3 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm
@@ -79,7 +79,7 @@ } void FullscreenModel::SetCollapsedToolbarHeight(CGFloat height) { - if (AreCGFloatsEqual(collapsed_toolbar_height_, height)) + if (AreCGFloatsEqual(GetCollapsedToolbarHeight(), height)) return; DCHECK_GE(height, 0.0); collapsed_toolbar_height_ = height; @@ -91,11 +91,11 @@ } CGFloat FullscreenModel::GetCollapsedToolbarHeight() const { - return collapsed_toolbar_height_; + return GetFreezeToolbarHeight() ? 0 : collapsed_toolbar_height_; } void FullscreenModel::SetExpandedToolbarHeight(CGFloat height) { - if (AreCGFloatsEqual(expanded_toolbar_height_, height)) + if (AreCGFloatsEqual(GetExpandedToolbarHeight(), height)) return; DCHECK_GE(height, 0.0); expanded_toolbar_height_ = height; @@ -107,7 +107,7 @@ } CGFloat FullscreenModel::GetExpandedToolbarHeight() const { - return expanded_toolbar_height_; + return GetFreezeToolbarHeight() ? 0 : expanded_toolbar_height_; } void FullscreenModel::SetBottomToolbarHeight(CGFloat height) { @@ -247,6 +247,22 @@ return safe_area_insets_; } +void FullscreenModel::SetFreezeToolbarHeight(bool freeze_toolbar_height) { + if (freeze_toolbar_height_ == freeze_toolbar_height) { + return; + } + freeze_toolbar_height_ = freeze_toolbar_height; + base_offset_ = NAN; + ScopedIncrementer toolbar_height_incrementer(&observer_callback_count_); + for (auto& observer : observers_) { + observer.FullscreenModelToolbarHeightsUpdated(this); + } +} + +bool FullscreenModel::GetFreezeToolbarHeight() const { + return freeze_toolbar_height_; +} + FullscreenModel::ScrollAction FullscreenModel::ActionForScrollFromOffset( CGFloat from_offset) const { // Update the base offset but don't recalculate progress if: @@ -309,7 +325,7 @@ // When Smooth Scrolling is disabled, the scroll view can sometimes be // resized to account for the viewport insets after the page has been // rendered, so account for the maximum toolbar insets in the threshold. - disabling_threshold += expanded_toolbar_height_ + bottom_toolbar_height_; + disabling_threshold += GetExpandedToolbarHeight() + bottom_toolbar_height_; } else { // After reloads, pages whose viewports fit the screen are sometimes resized // to account for the safe area insets. Adding these to the threshold helps
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_model_unittest.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_model_unittest.mm index 0e7b994..f066e91 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_model_unittest.mm +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_model_unittest.mm
@@ -314,3 +314,16 @@ EXPECT_FALSE(model().is_scrolled_to_top()); EXPECT_TRUE(model().is_scrolled_to_bottom()); } + +// Tests that when the toolbar height is frozen, setting the height doesn't +// change the returned height until the toolbar is unfrozen. +TEST_F(FullscreenModelTest, FreezeToolbarHeight) { + model().SetFreezeToolbarHeight(true); + EXPECT_EQ(model().GetExpandedToolbarHeight(), 0); + + model().SetExpandedToolbarHeight(100); + EXPECT_EQ(model().GetExpandedToolbarHeight(), 0); + + model().SetFreezeToolbarHeight(false); + EXPECT_EQ(model().GetExpandedToolbarHeight(), 100); +}
diff --git a/ios/chrome/browser/ui/fullscreen/test/test_fullscreen_controller.h b/ios/chrome/browser/ui/fullscreen/test/test_fullscreen_controller.h index c157f265..02a711be 100644 --- a/ios/chrome/browser/ui/fullscreen/test/test_fullscreen_controller.h +++ b/ios/chrome/browser/ui/fullscreen/test/test_fullscreen_controller.h
@@ -41,6 +41,7 @@ void EnterFullscreen() override; void ExitFullscreen() override; void ResizeHorizontalViewport() override; + void FreezeToolbarHeight(bool freeze_toolbar_height) override; // Calls FullscreenViewportInsetRangeChanged() on observers. void OnFullscreenViewportInsetRangeChanged(UIEdgeInsets min_viewport_insets,
diff --git a/ios/chrome/browser/ui/fullscreen/test/test_fullscreen_controller.mm b/ios/chrome/browser/ui/fullscreen/test/test_fullscreen_controller.mm index 78f30cf7..62206ea2 100644 --- a/ios/chrome/browser/ui/fullscreen/test/test_fullscreen_controller.mm +++ b/ios/chrome/browser/ui/fullscreen/test/test_fullscreen_controller.mm
@@ -126,3 +126,9 @@ void TestFullscreenController::ResizeHorizontalViewport() { // NOOP in tests. } + +void TestFullscreenController::FreezeToolbarHeight(bool freeze_toolbar_height) { + if (model_) { + model_->SetFreezeToolbarHeight(freeze_toolbar_height); + } +}
diff --git a/ios/chrome/browser/ui/material_components/utils.mm b/ios/chrome/browser/ui/material_components/utils.mm index b9c6a6d..bee7e27 100644 --- a/ios/chrome/browser/ui/material_components/utils.mm +++ b/ios/chrome/browser/ui/material_components/utils.mm
@@ -15,7 +15,6 @@ #include "base/mac/foundation_util.h" #import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" -#import "ios/chrome/common/ui/colors/semantic_color_names.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -45,7 +44,7 @@ viewController.headerView.shiftBehavior = MDCFlexibleHeaderShiftBehaviorDisabled; viewController.headerView.backgroundColor = - [UIColor colorNamed:kSecondaryBackgroundColor]; + UIColor.cr_secondarySystemBackgroundColor; viewController.navigationBar.tintColor = UIColor.cr_labelColor; viewController.navigationBar.titleAlignment = MDCNavigationBarTitleAlignmentLeading;
diff --git a/ios/chrome/browser/ui/page_info/page_info_view_controller.mm b/ios/chrome/browser/ui/page_info/page_info_view_controller.mm index 059d1c0..ad13ac93 100644 --- a/ios/chrome/browser/ui/page_info/page_info_view_controller.mm +++ b/ios/chrome/browser/ui/page_info/page_info_view_controller.mm
@@ -68,9 +68,9 @@ - (void)viewDidLoad { [super viewDidLoad]; + self.navigationItem.titleView = + [self titleViewLabelForURL:self.pageInfoSecurityDescription.siteURL]; self.title = l10n_util::GetNSString(IDS_IOS_PAGE_INFO_SITE_INFORMATION); - self.navigationItem.prompt = self.pageInfoSecurityDescription.siteURL; - self.navigationController.navigationBar.prefersLargeTitles = NO; self.tableView.accessibilityIdentifier = kPageInfoViewAccessibilityIdentifier; UIBarButtonItem* dismissButton = [[UIBarButtonItem alloc] @@ -147,4 +147,17 @@ [self.handler showSecurityHelpPage]; } +#pragma mark - Private + +// Returns the navigationItem titleView for |siteURL|. +- (UILabel*)titleViewLabelForURL:(NSString*)siteURL { + UILabel* labelURL = [[UILabel alloc] init]; + labelURL.lineBreakMode = NSLineBreakByTruncatingHead; + labelURL.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; + labelURL.text = siteURL; + labelURL.adjustsFontSizeToFitWidth = YES; + labelURL.minimumScaleFactor = 0.7; + return labelURL; +} + @end
diff --git a/ios/chrome/browser/ui/scanner/camera_controller.mm b/ios/chrome/browser/ui/scanner/camera_controller.mm index 0ee910c..201492b2 100644 --- a/ios/chrome/browser/ui/scanner/camera_controller.mm +++ b/ios/chrome/browser/ui/scanner/camera_controller.mm
@@ -8,6 +8,7 @@ #include "base/mac/foundation_util.h" #include "base/notreached.h" #include "base/strings/stringprintf.h" +#include "ios/chrome/browser/ui/util/uikit_ui_util.h" #include "ios/chrome/common/ios_app_bundle_id_prefix_buildflags.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -329,8 +330,7 @@ } - (AVCaptureVideoOrientation)videoOrientationForCurrentInterfaceOrientation { - UIInterfaceOrientation orientation = - [[UIApplication sharedApplication] statusBarOrientation]; + UIInterfaceOrientation orientation = GetInterfaceOrientation(); switch (orientation) { case UIInterfaceOrientationUnknown: return AVCaptureVideoOrientationPortrait;
diff --git a/ios/chrome/browser/ui/send_tab_to_self/send_tab_to_self_table_view_controller.mm b/ios/chrome/browser/ui/send_tab_to_self/send_tab_to_self_table_view_controller.mm index 46a28fc..31fdb75c 100644 --- a/ios/chrome/browser/ui/send_tab_to_self/send_tab_to_self_table_view_controller.mm +++ b/ios/chrome/browser/ui/send_tab_to_self/send_tab_to_self_table_view_controller.mm
@@ -19,6 +19,7 @@ #include "ios/chrome/browser/ui/table_view/cells/table_view_url_item.h" #import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" +#import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" #import "ios/chrome/common/ui/colors/semantic_color_names.h" #include "ios/chrome/grit/ios_strings.h" #include "ui/base/l10n/l10n_util.h" @@ -81,9 +82,8 @@ - (void)viewDidLoad { [super viewDidLoad]; - self.view.backgroundColor = [UIColor colorNamed:kPrimaryBackgroundColor]; - self.styler.cellBackgroundColor = - [UIColor colorNamed:kPrimaryBackgroundColor]; + self.view.backgroundColor = UIColor.cr_systemBackgroundColor; + self.styler.cellBackgroundColor = UIColor.cr_systemBackgroundColor; self.tableView.sectionHeaderHeight = 0; self.tableView.sectionFooterHeight = 0; [self.tableView
diff --git a/ios/chrome/browser/ui/settings/autofill/autofill_add_credit_card_view_controller.mm b/ios/chrome/browser/ui/settings/autofill/autofill_add_credit_card_view_controller.mm index d8ce2948..dea998e 100644 --- a/ios/chrome/browser/ui/settings/autofill/autofill_add_credit_card_view_controller.mm +++ b/ios/chrome/browser/ui/settings/autofill/autofill_add_credit_card_view_controller.mm
@@ -16,6 +16,7 @@ #import "ios/chrome/browser/ui/table_view/chrome_table_view_controller.h" #import "ios/chrome/browser/ui/table_view/table_view_utils.h" #include "ios/chrome/browser/ui/ui_feature_flags.h" +#import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" #import "ios/chrome/common/ui/colors/semantic_color_names.h" #include "ios/chrome/grit/ios_strings.h" #include "ui/base/l10n/l10n_util_mac.h" @@ -87,8 +88,7 @@ - (void)viewDidLoad { [super viewDidLoad]; - self.view.backgroundColor = - [UIColor colorNamed:kGroupedPrimaryBackgroundColor]; + self.view.backgroundColor = UIColor.cr_systemGroupedBackgroundColor; self.tableView.accessibilityIdentifier = kAddCreditCardViewID; self.navigationItem.title = l10n_util::GetNSString(
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_table_view_controller.mm b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_table_view_controller.mm index e45bdec..2e822f9 100644 --- a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_table_view_controller.mm
@@ -139,10 +139,10 @@ if (!base::FeatureList::IsEnabled(kSettingsRefresh)) { self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + self.styler.cellBackgroundColor = UIColor.cr_systemBackgroundColor; + self.styler.tableViewBackgroundColor = UIColor.cr_systemBackgroundColor; self.tableView.accessibilityIdentifier = kClearBrowsingDataViewAccessibilityIdentifier; - self.styler.tableViewBackgroundColor = - [UIColor colorNamed:kPrimaryBackgroundColor]; self.tableView.backgroundColor = self.styler.tableViewBackgroundColor; // TableView configuration
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/time_range_selector_table_view_controller.mm b/ios/chrome/browser/ui/settings/clear_browsing_data/time_range_selector_table_view_controller.mm index 09d8f10..7002d7d 100644 --- a/ios/chrome/browser/ui/settings/clear_browsing_data/time_range_selector_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/clear_browsing_data/time_range_selector_table_view_controller.mm
@@ -15,7 +15,6 @@ #import "ios/chrome/browser/ui/table_view/table_view_utils.h" #include "ios/chrome/browser/ui/ui_feature_flags.h" #import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" -#import "ios/chrome/common/ui/colors/semantic_color_names.h" #include "ios/chrome/grit/ios_strings.h" #include "ui/base/l10n/l10n_util_mac.h" @@ -79,8 +78,7 @@ - (void)viewDidLoad { [super viewDidLoad]; if (!base::FeatureList::IsEnabled(kSettingsRefresh)) { - self.styler.tableViewBackgroundColor = - [UIColor colorNamed:kPrimaryBackgroundColor]; + self.styler.tableViewBackgroundColor = UIColor.cr_systemBackgroundColor; self.tableView.backgroundColor = self.styler.tableViewBackgroundColor; } [self loadModel];
diff --git a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm index 7fa7884..befb055 100644 --- a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
@@ -25,6 +25,7 @@ #include "ios/chrome/browser/ui/ui_feature_flags.h" #include "ios/chrome/browser/ui/util/ui_util.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" +#import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" #import "ios/chrome/common/ui/colors/semantic_color_names.h" #import "ios/chrome/common/ui/util/constraints_ui_util.h" #include "ios/chrome/grit/ios_strings.h" @@ -288,7 +289,7 @@ - (void)viewDidLoad { [super viewDidLoad]; - self.view.backgroundColor = [UIColor colorNamed:kPrimaryBackgroundColor]; + self.view.backgroundColor = UIColor.cr_systemBackgroundColor; if (base::FeatureList::IsEnabled(kSettingsRefresh)) { self.navigationBar.translucent = NO;
diff --git a/ios/chrome/browser/ui/settings/settings_root_table_view_controller.mm b/ios/chrome/browser/ui/settings/settings_root_table_view_controller.mm index f20c692..29cbff5 100644 --- a/ios/chrome/browser/ui/settings/settings_root_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_root_table_view_controller.mm
@@ -117,7 +117,7 @@ - (void)viewDidLoad { if (!base::FeatureList::IsEnabled(kSettingsRefresh)) { self.styler.tableViewBackgroundColor = - [UIColor colorNamed:kGroupedPrimaryBackgroundColor]; + UIColor.cr_systemGroupedBackgroundColor; } UIBarButtonItem* flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace @@ -128,7 +128,7 @@ [super viewDidLoad]; self.styler.cellBackgroundColor = - [UIColor colorNamed:kGroupedSecondaryBackgroundColor]; + UIColor.cr_secondarySystemGroupedBackgroundColor; self.styler.cellTitleColor = UIColor.cr_labelColor; self.tableView.estimatedSectionHeaderHeight = kEstimatedHeaderFooterHeight; self.tableView.estimatedRowHeight = kSettingsCellDefaultHeight;
diff --git a/ios/chrome/browser/ui/table_view/chrome_table_view_styler.mm b/ios/chrome/browser/ui/table_view/chrome_table_view_styler.mm index 6ee04a2..fb2725c 100644 --- a/ios/chrome/browser/ui/table_view/chrome_table_view_styler.mm +++ b/ios/chrome/browser/ui/table_view/chrome_table_view_styler.mm
@@ -6,6 +6,7 @@ #include "ios/chrome/browser/ui/ui_feature_flags.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" +#import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" #import "ios/chrome/common/ui/colors/semantic_color_names.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -19,10 +20,9 @@ if (base::FeatureList::IsEnabled(kSettingsRefresh)) { _tableViewBackgroundColor = [UIColor colorNamed:kSecondaryBackgroundColor]; - _cellBackgroundColor = - [UIColor colorNamed:kGroupedSecondaryBackgroundColor]; + _cellBackgroundColor = UIColor.cr_secondarySystemGroupedBackgroundColor; } else { - _tableViewBackgroundColor = [UIColor colorNamed:kPrimaryBackgroundColor]; + _tableViewBackgroundColor = UIColor.cr_systemBackgroundColor; } } return self;
diff --git a/ios/chrome/browser/ui/table_view/table_view_navigation_controller.mm b/ios/chrome/browser/ui/table_view/table_view_navigation_controller.mm index 08c4369..416f3ef 100644 --- a/ios/chrome/browser/ui/table_view/table_view_navigation_controller.mm +++ b/ios/chrome/browser/ui/table_view/table_view_navigation_controller.mm
@@ -8,6 +8,7 @@ #import "ios/chrome/browser/ui/table_view/chrome_table_view_controller.h" #import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h" #include "ios/chrome/browser/ui/ui_feature_flags.h" +#import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" #import "ios/chrome/common/ui/colors/semantic_color_names.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -42,10 +43,9 @@ self.toolbar.barTintColor = [UIColor colorNamed:kSecondaryBackgroundColor]; self.view.backgroundColor = [UIColor colorNamed:kSecondaryBackgroundColor]; } else { - self.navigationBar.barTintColor = - [UIColor colorNamed:kPrimaryBackgroundColor]; - self.toolbar.barTintColor = [UIColor colorNamed:kPrimaryBackgroundColor]; - self.view.backgroundColor = [UIColor colorNamed:kPrimaryBackgroundColor]; + self.navigationBar.barTintColor = UIColor.cr_systemBackgroundColor; + self.toolbar.barTintColor = UIColor.cr_systemBackgroundColor; + self.view.backgroundColor = UIColor.cr_systemBackgroundColor; } }
diff --git a/ios/chrome/browser/ui/thumb_strip/BUILD.gn b/ios/chrome/browser/ui/thumb_strip/BUILD.gn index 931de5a..84f20fd 100644 --- a/ios/chrome/browser/ui/thumb_strip/BUILD.gn +++ b/ios/chrome/browser/ui/thumb_strip/BUILD.gn
@@ -51,6 +51,7 @@ "//base", "//base/test:test_support", "//ios/chrome/browser/ui:feature_flags", + "//ios/chrome/browser/ui/fullscreen:feature_flags", "//ios/chrome/test:eg_test_support+eg2", "//ios/chrome/test/earl_grey:eg_test_support+eg2", "//ios/testing/earl_grey:eg_test_support+eg2",
diff --git a/ios/chrome/browser/ui/thumb_strip/thumb_strip_egtest.mm b/ios/chrome/browser/ui/thumb_strip/thumb_strip_egtest.mm index d317681..dc426c8 100644 --- a/ios/chrome/browser/ui/thumb_strip/thumb_strip_egtest.mm +++ b/ios/chrome/browser/ui/thumb_strip/thumb_strip_egtest.mm
@@ -4,6 +4,7 @@ #include "base/ios/ios_util.h" #import "base/test/ios/wait_util.h" +#import "ios/chrome/browser/ui/fullscreen/fullscreen_features.h" #import "ios/chrome/browser/ui/thumb_strip/thumb_strip_feature.h" #import "ios/chrome/browser/ui/ui_feature_flags.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" @@ -55,6 +56,8 @@ // See crbug.com/1143299. if (base::ios::IsRunningOnIOS13OrLater()) { config.features_enabled.push_back(kExpandedTabStrip); + config.features_disabled.push_back( + fullscreen::features::kSmoothScrollingDefault); } return config; }
diff --git a/ios/chrome/browser/ui/util/keyboard_observer_helper.mm b/ios/chrome/browser/ui/util/keyboard_observer_helper.mm index 5deb1b8..dd36ff15 100644 --- a/ios/chrome/browser/ui/util/keyboard_observer_helper.mm +++ b/ios/chrome/browser/ui/util/keyboard_observer_helper.mm
@@ -118,11 +118,13 @@ - (void)keyboardWillHide:(NSNotification*)notification { self.keyboardOnScreen = NO; +#if !defined(__IPHONE_13_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_13_0 dispatch_async(dispatch_get_main_queue(), ^{ if (self.keyboardOnScreen) { [self.consumer keyboardDidStayOnScreen]; } }); +#endif } #pragma mark - Private
diff --git a/ios/chrome/browser/web/error_page_egtest.mm b/ios/chrome/browser/web/error_page_egtest.mm index 5ff05c3a..4771c75 100644 --- a/ios/chrome/browser/web/error_page_egtest.mm +++ b/ios/chrome/browser/web/error_page_egtest.mm
@@ -101,6 +101,27 @@ [ChromeEarlGrey waitForWebStateContainingText:"bar"]; } +// Loads the URL which fails to load, then sucessfully navigates back/forward to +// the page. +- (void)testNavigateForwardToErrorPage { + self.serverRespondsWithContent = YES; + [ChromeEarlGrey loadURL:self.testServer->GetURL("/echo-query?bar")]; + [ChromeEarlGrey waitForWebStateContainingText:"bar"]; + + // No response leads to ERR_CONNECTION_CLOSED error. + self.serverRespondsWithContent = NO; + [ChromeEarlGrey loadURL:self.testServer->GetURL("/echo-query?foo")]; + [ChromeEarlGrey waitForWebStateContainingText:GetErrorMessage()]; + + self.serverRespondsWithContent = YES; + [ChromeEarlGrey goBack]; + [ChromeEarlGrey waitForWebStateContainingText:"bar"]; + + // Navigate forward to the error page, which should load without errors. + [ChromeEarlGrey goForward]; + [ChromeEarlGrey waitForWebStateContainingText:"foo"]; +} + // Loads the URL which fails to load, then sucessfully reloads the page. - (void)testReloadErrorPage { // No response leads to ERR_CONNECTION_CLOSED error.
diff --git a/ios/chrome/browser/web_state_list/BUILD.gn b/ios/chrome/browser/web_state_list/BUILD.gn index f78f880..a0cab940 100644 --- a/ios/chrome/browser/web_state_list/BUILD.gn +++ b/ios/chrome/browser/web_state_list/BUILD.gn
@@ -69,6 +69,7 @@ "//ios/chrome/browser/main:public", "//ios/chrome/browser/sessions:restoration_agent", "//ios/chrome/browser/sessions:restoration_observer", + "//ios/chrome/browser/ui/util", "//ios/web/public", ] frameworks = [ "Foundation.framework" ]
diff --git a/ios/chrome/browser/web_state_list/web_state_list_metrics_browser_agent.mm b/ios/chrome/browser/web_state_list/web_state_list_metrics_browser_agent.mm index c30f0db..bc61828 100644 --- a/ios/chrome/browser/web_state_list/web_state_list_metrics_browser_agent.mm +++ b/ios/chrome/browser/web_state_list/web_state_list_metrics_browser_agent.mm
@@ -14,6 +14,7 @@ #include "ios/chrome/browser/chrome_url_constants.h" #include "ios/chrome/browser/crash_report/crash_loop_detection_util.h" #import "ios/chrome/browser/sessions/session_restoration_browser_agent.h" +#include "ios/chrome/browser/ui/util/uikit_ui_util.h" #include "ios/chrome/browser/web_state_list/session_metrics.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" #include "ios/web/public/browser_state.h" @@ -157,7 +158,7 @@ void WebStateListMetricsBrowserAgent::PageLoaded( web::WebState* web_state, web::PageLoadCompletionStatus load_completion_status) { - switch ([[UIApplication sharedApplication] statusBarOrientation]) { + switch (GetInterfaceOrientation()) { case UIInterfaceOrientationPortrait: case UIInterfaceOrientationPortraitUpsideDown: UMA_HISTOGRAM_BOOLEAN("Tab.PageLoadInPortrait", YES);
diff --git a/ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h b/ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h index e95226e..c4026725 100644 --- a/ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h +++ b/ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h
@@ -13,6 +13,16 @@ // TODO (crbug.com/981889): Remove along with iOS 12. @interface UIColor (CRSemanticColors) +// System Background Color +@property(class, nonatomic, readonly) UIColor* cr_systemBackgroundColor; +@property(class, nonatomic, readonly) + UIColor* cr_secondarySystemBackgroundColor; + +// System Grouped Background Colors +@property(class, nonatomic, readonly) UIColor* cr_systemGroupedBackgroundColor; +@property(class, nonatomic, readonly) + UIColor* cr_secondarySystemGroupedBackgroundColor; + // Label Colors @property(class, nonatomic, readonly) UIColor* cr_labelColor; @property(class, nonatomic, readonly) UIColor* cr_secondaryLabelColor;
diff --git a/ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.mm b/ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.mm index 70f20f4..39ced8a 100644 --- a/ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.mm +++ b/ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.mm
@@ -10,6 +10,42 @@ @implementation UIColor (CRSemanticColors) +#pragma mark - System Background Colors + ++ (UIColor*)cr_systemBackgroundColor { + if (@available(iOS 13, *)) { + return UIColor.systemBackgroundColor; + } + return UIColor.whiteColor; +} + ++ (UIColor*)cr_secondarySystemBackgroundColor { + if (@available(iOS 13, *)) { + return UIColor.secondarySystemBackgroundColor; + } + // This is the value for secondarySystemBackgroundColor in light mode. + return [UIColor colorWithRed:244 / (CGFloat)0xFF + green:244 / (CGFloat)0xFF + blue:248 / (CGFloat)0xFF + alpha:1]; +} + +#pragma mark - System Grouped Background Colors + ++ (UIColor*)cr_systemGroupedBackgroundColor { + if (@available(iOS 13, *)) { + return UIColor.systemGroupedBackgroundColor; + } + return UIColor.groupTableViewBackgroundColor; +} + ++ (UIColor*)cr_secondarySystemGroupedBackgroundColor { + if (@available(iOS 13, *)) { + return UIColor.secondarySystemGroupedBackgroundColor; + } + return UIColor.whiteColor; +} + #pragma mark - Label Colors + (UIColor*)cr_labelColor {
diff --git a/ios/chrome/common/ui/colors/resources/BUILD.gn b/ios/chrome/common/ui/colors/resources/BUILD.gn index 59ca80c..c6935c0 100644 --- a/ios/chrome/common/ui/colors/resources/BUILD.gn +++ b/ios/chrome/common/ui/colors/resources/BUILD.gn
@@ -27,12 +27,9 @@ ":grey_700_color", ":grey_800_color", ":grey_900_color", - ":grouped_primary_background_color", - ":grouped_secondary_background_color", ":mdc_ink_color", ":mdc_secondary_ink_color", ":placeholder_image_tint_color", - ":primary_background_color", ":red_color", ":red_dark_color", ":scrim_background_color", @@ -226,15 +223,3 @@ colorset("secondary_background_color") { sources = [ "secondary_background_color.colorset/Contents.json" ] } - -colorset("primary_background_color") { - sources = [ "primary_background_color.colorset/Contents.json" ] -} - -colorset("grouped_secondary_background_color") { - sources = [ "grouped_secondary_background_color.colorset/Contents.json" ] -} - -colorset("grouped_primary_background_color") { - sources = [ "grouped_primary_background_color.colorset/Contents.json" ] -}
diff --git a/ios/chrome/common/ui/colors/resources/grouped_primary_background_color.colorset/Contents.json b/ios/chrome/common/ui/colors/resources/grouped_primary_background_color.colorset/Contents.json deleted file mode 100644 index f1f5bfa..0000000 --- a/ios/chrome/common/ui/colors/resources/grouped_primary_background_color.colorset/Contents.json +++ /dev/null
@@ -1,38 +0,0 @@ -{ - "info": { - "version": 1, - "author": "xcode" - }, - "colors": [ - { - "idiom": "universal", - "color": { - "color-space": "display-p3", - "components": { - "red": "0xF1", - "alpha": "1.000", - "blue": "0xF4", - "green": "0xF3" - } - } - }, - { - "idiom": "universal", - "appearances": [ - { - "appearance": "luminosity", - "value": "dark" - } - ], - "color": { - "color-space": "display-p3", - "components": { - "red": "0x20", - "alpha": "1.000", - "blue": "0x24", - "green": "0x21" - } - } - } - ] -} \ No newline at end of file
diff --git a/ios/chrome/common/ui/colors/resources/grouped_secondary_background_color.colorset/Contents.json b/ios/chrome/common/ui/colors/resources/grouped_secondary_background_color.colorset/Contents.json deleted file mode 100644 index 0d5ff736..0000000 --- a/ios/chrome/common/ui/colors/resources/grouped_secondary_background_color.colorset/Contents.json +++ /dev/null
@@ -1,38 +0,0 @@ -{ - "info": { - "version": 1, - "author": "xcode" - }, - "colors": [ - { - "idiom": "universal", - "color": { - "color-space": "display-p3", - "components": { - "red": "0xFF", - "alpha": "1.000", - "blue": "0xFF", - "green": "0xFF" - } - } - }, - { - "idiom": "universal", - "appearances": [ - { - "appearance": "luminosity", - "value": "dark" - } - ], - "color": { - "color-space": "display-p3", - "components": { - "red": "0x35", - "alpha": "1.000", - "blue": "0x39", - "green": "0x37" - } - } - } - ] -} \ No newline at end of file
diff --git a/ios/chrome/common/ui/colors/resources/primary_background_color.colorset/Contents.json b/ios/chrome/common/ui/colors/resources/primary_background_color.colorset/Contents.json deleted file mode 100644 index a66621c8..0000000 --- a/ios/chrome/common/ui/colors/resources/primary_background_color.colorset/Contents.json +++ /dev/null
@@ -1,38 +0,0 @@ -{ - "info": { - "version": 1, - "author": "xcode" - }, - "colors": [ - { - "idiom": "universal", - "color": { - "color-space": "display-p3", - "components": { - "red": "0xFF", - "alpha": "1.000", - "blue": "0xFF", - "green": "0xFF" - } - } - }, - { - "idiom": "universal", - "appearances": [ - { - "appearance": "luminosity", - "value": "dark" - } - ], - "color": { - "color-space": "display-p3", - "components": { - "red": "0x20", - "alpha": "1.000", - "blue": "0x24", - "green": "0x21" - } - } - } - ] -} \ No newline at end of file
diff --git a/ios/chrome/common/ui/colors/semantic_color_names.h b/ios/chrome/common/ui/colors/semantic_color_names.h index d66f212..ce13cb6 100644 --- a/ios/chrome/common/ui/colors/semantic_color_names.h +++ b/ios/chrome/common/ui/colors/semantic_color_names.h
@@ -14,10 +14,6 @@ extern NSString* const kDisabledTintColor; // Background color used in the rounded squares behind favicons. extern NSString* const kFaviconBackgroundColor; -// Primary grouped background color. -extern NSString* const kGroupedPrimaryBackgroundColor; -// Secondary grouped background color. -extern NSString* const kGroupedSecondaryBackgroundColor; // Ink color for an MDC button. extern NSString* const kMDCInkColor; // Ink color for a secondary style MDC button (button with transparent @@ -25,8 +21,6 @@ extern NSString* const kMDCSecondaryInkColor; // Color used to tint placeholder images and icons. extern NSString* const kPlaceholderImageTintColor; -// Primary background color. -extern NSString* const kPrimaryBackgroundColor; extern NSString* const kScrimBackgroundColor; // Secondary background color. extern NSString* const kSecondaryBackgroundColor;
diff --git a/ios/chrome/common/ui/colors/semantic_color_names.mm b/ios/chrome/common/ui/colors/semantic_color_names.mm index 22d8e42..74d8960 100644 --- a/ios/chrome/common/ui/colors/semantic_color_names.mm +++ b/ios/chrome/common/ui/colors/semantic_color_names.mm
@@ -13,14 +13,9 @@ NSString* const kCloseButtonColor = @"close_button_color"; NSString* const kDisabledTintColor = @"disabled_tint_color"; NSString* const kFaviconBackgroundColor = @"favicon_background_color"; -NSString* const kGroupedPrimaryBackgroundColor = - @"grouped_primary_background_color"; -NSString* const kGroupedSecondaryBackgroundColor = - @"grouped_secondary_background_color"; NSString* const kMDCInkColor = @"mdc_ink_color"; NSString* const kMDCSecondaryInkColor = @"mdc_secondary_ink_color"; NSString* const kPlaceholderImageTintColor = @"placeholder_image_tint_color"; -NSString* const kPrimaryBackgroundColor = @"primary_background_color"; NSString* const kScrimBackgroundColor = @"scrim_background_color"; NSString* const kSecondaryBackgroundColor = @"secondary_background_color"; NSString* const kSeparatorColor = @"separator_color";
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1 index f0f8507..fc2cbc7c 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -df0c5af3c01e211e892dfa7202abbd97923f42c8 \ No newline at end of file +d35eaa7488bab6b76b1e2cbcc9a79813ee380c2c \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1 index eb566b2..61f2d16 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -479a5cdbe222d03b81f46ad57802cbabe8d85142 \ No newline at end of file +2a03c2ba1c14490e70ec58326debef58891bec38 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1 index d96943a..96c2f6cca 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -6304c71654ccc27f78f770f348c50d9343ecc014 \ No newline at end of file +32575c02bd0089bc0c16100ab1851cc6006b7fa0 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1 index c550be42..b38e9cc 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -fd43d9d0bdf5b608a75bde850d771f551137244e \ No newline at end of file +1f1b56e21aa2be7a392e03cd1bd0cedadc11b6ef \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1 index 3e33356..4592cd67 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -2f23f78fcdc06953931ecefc1454539aa68c35cb \ No newline at end of file +123b2c131d978512700b9560bfef6a298ad14567 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1 index 601bf34..eb1a1e5e 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -2cc660c0e8df8ad03130b81e30dc6cd86ca71d59 \ No newline at end of file +671a339206310696c276bdb0be0cb912d87585eb \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1 index 69ab0b8..33896b8 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -d1a3948e1471f0d3eafef0d042257fce2406cbe1 \ No newline at end of file +8ecc877a8f1ea68933b0f3253f7060f5c3e8f123 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1 index 643fca35..8e73bca 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -cad27834b77d0b6819db2ecd2a9db07b1c386f06 \ No newline at end of file +49c07444d6372ee239e8a74f7573cbfc07f4cc8b \ No newline at end of file
diff --git a/ios/public/provider/chrome/browser/signin/chrome_identity.h b/ios/public/provider/chrome/browser/signin/chrome_identity.h index c755a07..3b7028a 100644 --- a/ios/public/provider/chrome/browser/signin/chrome_identity.h +++ b/ios/public/provider/chrome/browser/signin/chrome_identity.h
@@ -24,6 +24,10 @@ // Could be nil if no full name has been fetched for this account yet. @property(strong, nonatomic, readonly) NSString* userFullName; +// Returns the primary given name of the identity, usually the user's first +// name. Could be nil if no name has been fetched for this account yet. +@property(strong, nonatomic, readonly) NSString* userGivenName; + // Cached Hashed Gaia ID. This is used to pass the currently signed in account // between apps. @property(strong, nonatomic, readonly) NSString* hashedGaiaID;
diff --git a/ios/public/provider/chrome/browser/signin/chrome_identity.mm b/ios/public/provider/chrome/browser/signin/chrome_identity.mm index 6b6794f..fae2376 100644 --- a/ios/public/provider/chrome/browser/signin/chrome_identity.mm +++ b/ios/public/provider/chrome/browser/signin/chrome_identity.mm
@@ -27,6 +27,11 @@ return nil; } +- (NSString*)userGivenName { + NOTREACHED(); + return nil; +} + - (NSString*)hashedGaiaID { NOTREACHED(); return nil;
diff --git a/ios/public/provider/chrome/browser/signin/fake_chrome_identity.h b/ios/public/provider/chrome/browser/signin/fake_chrome_identity.h index 9085b568..bc0a810 100644 --- a/ios/public/provider/chrome/browser/signin/fake_chrome_identity.h +++ b/ios/public/provider/chrome/browser/signin/fake_chrome_identity.h
@@ -12,6 +12,8 @@ // Returns a ChromeIdentity based on |email|, |gaiaID| and |name|. // The |hashedGaiaID| property will be derived from |name|. +// For simplicity, both |userGivenName| and |userFullName| properties use +// |name|. + (FakeChromeIdentity*)identityWithEmail:(NSString*)email gaiaID:(NSString*)gaiaID name:(NSString*)name;
diff --git a/ios/public/provider/chrome/browser/signin/fake_chrome_identity.mm b/ios/public/provider/chrome/browser/signin/fake_chrome_identity.mm index a588fc70..724ba23 100644 --- a/ios/public/provider/chrome/browser/signin/fake_chrome_identity.mm +++ b/ios/public/provider/chrome/browser/signin/fake_chrome_identity.mm
@@ -14,6 +14,7 @@ NSString* const kCoderUserEmailKey = @"UserEmail"; NSString* const kCoderGaiaIDKey = @"GaiaID"; NSString* const kCoderUserFullNameKey = @"UserFullName"; +NSString* const kCoderUserGivenNameKey = @"UserGivenName"; NSString* const kCoderHashedGaiaIDKey = @"HashedGaiaID"; } // namespace @@ -21,6 +22,7 @@ NSString* _userEmail; NSString* _gaiaID; NSString* _userFullName; + NSString* _userGivenName; NSString* _hashedGaiaID; } @@ -40,6 +42,7 @@ _userEmail = [email copy]; _gaiaID = [gaiaID copy]; _userFullName = [name copy]; + _userGivenName = [name copy]; _hashedGaiaID = [NSString stringWithFormat:@"%@_hashID", name]; } return self; @@ -57,6 +60,10 @@ return _userFullName; } +- (NSString*)userGivenName { + return _userGivenName; +} + - (NSString*)hashedGaiaID { return _hashedGaiaID; } @@ -79,6 +86,7 @@ return [_userEmail isEqualToString:other.userEmail] && [_gaiaID isEqualToString:other.gaiaID] && [_userFullName isEqualToString:other.userFullName] && + [_userGivenName isEqualToString:other.userGivenName] && [_hashedGaiaID isEqualToString:other.hashedGaiaID]; } return NO; @@ -94,6 +102,7 @@ [coder encodeObject:_userEmail forKey:kCoderUserEmailKey]; [coder encodeObject:_gaiaID forKey:kCoderGaiaIDKey]; [coder encodeObject:_userFullName forKey:kCoderUserFullNameKey]; + [coder encodeObject:_userGivenName forKey:kCoderUserGivenNameKey]; [coder encodeObject:_hashedGaiaID forKey:kCoderHashedGaiaIDKey]; } @@ -105,6 +114,8 @@ forKey:kCoderGaiaIDKey]; _userFullName = [coder decodeObjectOfClass:[NSString class] forKey:kCoderUserFullNameKey]; + _userGivenName = [coder decodeObjectOfClass:[NSString class] + forKey:kCoderUserGivenNameKey]; _hashedGaiaID = [coder decodeObjectOfClass:[NSString class] forKey:kCoderHashedGaiaIDKey]; }
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn index a0258e2..c4b52c0 100644 --- a/ios/web/BUILD.gn +++ b/ios/web/BUILD.gn
@@ -478,11 +478,11 @@ ] sources = [ + "web_state/ui/crw_html_element_fetch_request_unittest.mm", "web_state/ui/crw_web_controller_unittest.mm", "web_state/ui/crw_web_view_content_view_unittest.mm", "web_state/ui/crw_web_view_proxy_impl_unittest.mm", "web_state/ui/crw_web_view_scroll_view_proxy_unittest.mm", - "web_state/ui/html_element_fetch_request_unittest.mm", "web_state/ui/web_view_js_utils_unittest.mm", "web_state/ui/wk_content_rule_list_util_unittest.mm", "web_state/ui/wk_web_view_configuration_provider_unittest.mm", @@ -527,6 +527,7 @@ ":web", "//base/test:test_support", "//ios/net", + "//ios/testing:block_swizzler", "//ios/testing:embedded_test_server_support", "//ios/testing:http_server_bundle_data", "//ios/web:resources_grit", @@ -554,6 +555,8 @@ "//ios/web/test:test_constants", "//ios/web/test:test_support", "//ios/web/web_state", + "//ios/web/web_state:context_menu", + "//ios/web/web_state/ui:crw_context_menu_controller", "//mojo/core/embedder", "//net:test_support", "//services/network/public/cpp", @@ -578,6 +581,7 @@ "web_state/error_page_inttest.mm", "web_state/http_auth_inttest.mm", "web_state/keep_render_process_alive_inttest.mm", + "web_state/ui/crw_context_menu_element_fetcher_inttest.mm", "web_state/web_state_observer_inttest.mm", "webui/web_ui_inttest.mm", "webui/web_ui_mojo_inttest.mm",
diff --git a/ios/web/common/uikit_ui_util.h b/ios/web/common/uikit_ui_util.h index 3ae8df7..9c3e40b 100644 --- a/ios/web/common/uikit_ui_util.h +++ b/ios/web/common/uikit_ui_util.h
@@ -11,4 +11,8 @@ // Use only if the context of which window doesn't matter. UIWindow* GetAnyKeyWindow(); +// Returns interface orientation for the current window, returned by +// GetAnyKeyWindow(). +UIInterfaceOrientation GetInterfaceOrientation(); + #endif // IOS_WEB_COMMON_UIKIT_UI_UTIL_H_
diff --git a/ios/web/common/uikit_ui_util.mm b/ios/web/common/uikit_ui_util.mm index 0ecd597..855669f 100644 --- a/ios/web/common/uikit_ui_util.mm +++ b/ios/web/common/uikit_ui_util.mm
@@ -22,3 +22,11 @@ return nil; #endif } + +UIInterfaceOrientation GetInterfaceOrientation() { +#if !defined(__IPHONE_13_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_13_0 + return [[UIApplication sharedApplication] statusBarOrientation]; +#else + return GetAnyKeyWindow().windowScene.interfaceOrientation; +#endif +}
diff --git a/ios/web/web_state/context_menu_params_utils.h b/ios/web/web_state/context_menu_params_utils.h index 44008f4..6a29c33 100644 --- a/ios/web/web_state/context_menu_params_utils.h +++ b/ios/web/web_state/context_menu_params_utils.h
@@ -11,10 +11,9 @@ namespace web { -// Returns true if the |element| dictionary contains enough information to -// present a context menu. (A valid url for either kContextMenuElementHyperlink -// or kContextMenuElementSource must exist in the dicitionary.) -BOOL CanShowContextMenuForElementDictionary(NSDictionary* element); +// Returns true if the |params| contain enough information to present a context +// menu. (A valid url for either link_url or src_url must exist in the params.) +BOOL CanShowContextMenuForParams(const ContextMenuParams& params); // creates a ContextMenuParams from a NSDictionary representing an HTML element. // The fields "href", "src", "title", "referrerPolicy" and "innerText" will
diff --git a/ios/web/web_state/context_menu_params_utils.mm b/ios/web/web_state/context_menu_params_utils.mm index 50dc3cb..67e2d9a1 100644 --- a/ios/web/web_state/context_menu_params_utils.mm +++ b/ios/web/web_state/context_menu_params_utils.mm
@@ -68,13 +68,11 @@ namespace web { -BOOL CanShowContextMenuForElementDictionary(NSDictionary* element) { - NSString* href = element[kContextMenuElementHyperlink]; - if (GURL(base::SysNSStringToUTF8(href)).is_valid()) { +BOOL CanShowContextMenuForParams(const ContextMenuParams& params) { + if (params.link_url.is_valid()) { return YES; } - NSString* src = element[kContextMenuElementSource]; - if (GURL(base::SysNSStringToUTF8(src)).is_valid()) { + if (params.src_url.is_valid()) { return YES; } return NO;
diff --git a/ios/web/web_state/context_menu_params_utils_unittest.mm b/ios/web/web_state/context_menu_params_utils_unittest.mm index e3622652..9df07ca0 100644 --- a/ios/web/web_state/context_menu_params_utils_unittest.mm +++ b/ios/web/web_state/context_menu_params_utils_unittest.mm
@@ -113,55 +113,49 @@ EXPECT_EQ(params.menu_title_origin, ContextMenuTitleOrigin::kURL); } -// Tests that a context menu will not be shown for an empty element dictionary. +// Tests that a context menu will not be shown for empty params. TEST_F(ContextMenuParamsUtilsTest, CanShowContextMenuTestEmptyDictionary) { - EXPECT_FALSE(CanShowContextMenuForElementDictionary(@{})); -} - -// Tests that a context menu will not be shown for an element dictionary with -// only a request id. -TEST_F(ContextMenuParamsUtilsTest, CanShowContextMenuTestRequestIdOnly) { - EXPECT_FALSE(CanShowContextMenuForElementDictionary( - @{kContextMenuElementRequestId : @"kContextMenuElementRequestId"})); + EXPECT_FALSE(CanShowContextMenuForParams(ContextMenuParams())); } // Tests that a context menu will be shown for a link. TEST_F(ContextMenuParamsUtilsTest, CanShowContextMenuTestHyperlink) { - EXPECT_TRUE(CanShowContextMenuForElementDictionary(@{ - kContextMenuElementHyperlink : @"http://example.com", - kContextMenuElementInnerText : @"Click me." - })); + ContextMenuParams params; + params.link_url = GURL("http://example.com"); + params.link_text = @"Click me."; + EXPECT_TRUE(CanShowContextMenuForParams(params)); } // Tests that a context menu will not be shown for an invalid link. TEST_F(ContextMenuParamsUtilsTest, CanShowContextMenuTestInvalidHyperlink) { - EXPECT_FALSE(CanShowContextMenuForElementDictionary( - @{kContextMenuElementHyperlink : @"invalid_url"})); + ContextMenuParams params; + params.link_url = GURL("invalid_url"); + EXPECT_FALSE(CanShowContextMenuForParams(params)); } // Tests that a context menu will be shown for an image. TEST_F(ContextMenuParamsUtilsTest, CanShowContextMenuTestImageWithTitle) { - EXPECT_TRUE(CanShowContextMenuForElementDictionary(@{ - kContextMenuElementSource : @"http://example.com/image.jpeg", - kContextMenuElementTitle : @"Image" - })); + ContextMenuParams params; + params.src_url = GURL("http://example.com/image.jpeg"); + params.menu_title = @"Image"; + EXPECT_TRUE(CanShowContextMenuForParams(params)); } // Tests that a context menu will not be shown for an image with an invalid // source url. TEST_F(ContextMenuParamsUtilsTest, CanShowContextMenuTestImageWithInvalidSource) { - EXPECT_FALSE(CanShowContextMenuForElementDictionary(@{ - kContextMenuElementSource : @"invalid_url", - })); + ContextMenuParams params; + params.src_url = GURL("invalid_url"); + EXPECT_FALSE(CanShowContextMenuForParams(params)); } // Tests that a context menu will be shown for a linked image. TEST_F(ContextMenuParamsUtilsTest, CanShowContextMenuTestLinkedImage) { - EXPECT_TRUE(CanShowContextMenuForElementDictionary(@{ - kContextMenuElementHyperlink : @"http://example.com", - kContextMenuElementSource : @"http://example.com/image.jpeg" - })); + ContextMenuParams params; + params.link_url = GURL("http://example.com"); + params.src_url = GURL("http://example.com/image.jpeg"); + EXPECT_TRUE(CanShowContextMenuForParams(params)); } // Tests that the menu title prepends the element's alt text if it is an image
diff --git a/ios/web/web_state/ui/BUILD.gn b/ios/web/web_state/ui/BUILD.gn index 0f0eca6..9f14e25 100644 --- a/ios/web/web_state/ui/BUILD.gn +++ b/ios/web/web_state/ui/BUILD.gn
@@ -104,10 +104,12 @@ ] sources = [ + "crw_context_menu_element_fetcher.h", + "crw_context_menu_element_fetcher.mm", + "crw_html_element_fetch_request.h", + "crw_html_element_fetch_request.mm", "crw_legacy_context_menu_controller.h", "crw_legacy_context_menu_controller.mm", - "html_element_fetch_request.h", - "html_element_fetch_request.mm", ] configs += [ "//build/config/compiler:enable_arc" ]
diff --git a/ios/web/web_state/ui/crw_context_menu_element_fetcher.h b/ios/web/web_state/ui/crw_context_menu_element_fetcher.h new file mode 100644 index 0000000..6896d0a --- /dev/null +++ b/ios/web/web_state/ui/crw_context_menu_element_fetcher.h
@@ -0,0 +1,33 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_WEB_WEB_STATE_UI_CRW_CONTEXT_MENU_ELEMENT_FETCHER_H_ +#define IOS_WEB_WEB_STATE_UI_CRW_CONTEXT_MENU_ELEMENT_FETCHER_H_ + +#import <Foundation/Foundation.h> +#import <WebKit/WebKit.h> + +namespace web { +struct ContextMenuParams; +class WebState; +} + +// Class handling the fetching information about DOM element in a specific +// position. +@interface CRWContextMenuElementFetcher : NSObject + +- (instancetype)initWithWebView:(WKWebView*)webView + webState:(web::WebState*)webState; + +// Asynchronously fetches information about DOM element for the given |point| +// (in the scroll view coordinates). |handler| can not be nil. +- (void)fetchDOMElementAtPoint:(CGPoint)point + completionHandler:(void (^)(const web::ContextMenuParams&))handler; + +// Cancels all the fetches current in progress. +- (void)cancelFetches; + +@end + +#endif // IOS_WEB_WEB_STATE_UI_CRW_CONTEXT_MENU_ELEMENT_FETCHER_H_
diff --git a/ios/web/web_state/ui/crw_context_menu_element_fetcher.mm b/ios/web/web_state/ui/crw_context_menu_element_fetcher.mm new file mode 100644 index 0000000..464ecf6 --- /dev/null +++ b/ios/web/web_state/ui/crw_context_menu_element_fetcher.mm
@@ -0,0 +1,157 @@ +// Copyright 2020 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. + +#import "ios/web/web_state/ui/crw_context_menu_element_fetcher.h" + +#include "base/strings/sys_string_conversions.h" +#include "base/unguessable_token.h" +#include "base/values.h" +#import "ios/web/js_messaging/crw_wk_script_message_router.h" +#import "ios/web/public/js_messaging/web_frame.h" +#import "ios/web/public/js_messaging/web_frame_util.h" +#import "ios/web/public/ui/context_menu_params.h" +#import "ios/web/public/web_state.h" +#import "ios/web/public/web_state_observer_bridge.h" +#import "ios/web/web_state/context_menu_constants.h" +#import "ios/web/web_state/context_menu_params_utils.h" +#import "ios/web/web_state/ui/crw_html_element_fetch_request.h" +#import "ios/web/web_state/ui/wk_web_view_configuration_provider.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { +// Javascript function name to obtain element details at a point. +const char kFindElementAtPointFunctionName[] = "findElementAtPoint"; + +// JavaScript message handler name installed in WKWebView for found element +// response. +NSString* const kFindElementResultHandlerName = @"FindElementResultHandler"; +} // namespace + +@interface CRWContextMenuElementFetcher () <CRWWebStateObserver> { + std::unique_ptr<web::WebStateObserverBridge> _observer; +} + +@property(nonatomic, readonly, weak) WKWebView* webView; + +@property(nonatomic, assign) web::WebState* webState; + +// Details for currently in progress element fetches. The objects are +// instances of CRWHTMLElementFetchRequest and are keyed by a unique requestId +// string. +@property(nonatomic, strong) NSMutableDictionary* pendingElementFetchRequests; + +@end + +@implementation CRWContextMenuElementFetcher + +- (instancetype)initWithWebView:(WKWebView*)webView + webState:(web::WebState*)webState { + self = [super init]; + if (self) { + _pendingElementFetchRequests = [[NSMutableDictionary alloc] init]; + + _webView = webView; + + _webState = webState; + _observer = std::make_unique<web::WebStateObserverBridge>(self); + webState->AddObserver(_observer.get()); + + // Listen for fetched element response. + web::WKWebViewConfigurationProvider& configurationProvider = + web::WKWebViewConfigurationProvider::FromBrowserState( + webState->GetBrowserState()); + CRWWKScriptMessageRouter* messageRouter = + configurationProvider.GetScriptMessageRouter(); + __weak __typeof(self) weakSelf = self; + [messageRouter + setScriptMessageHandler:^(WKScriptMessage* message) { + [weakSelf didReceiveScriptMessage:message]; + } + name:kFindElementResultHandlerName + webView:webView]; + } + return self; +} + +- (void)dealloc { + if (self.webState) + self.webState->RemoveObserver(_observer.get()); +} + +- (void)fetchDOMElementAtPoint:(CGPoint)point + completionHandler: + (void (^)(const web::ContextMenuParams&))handler { + if (!self.webState) { + return; + } + web::WebFrame* frame = GetMainFrame(self.webState); + if (!frame) { + // A WebFrame may not exist for certain types of content, like PDFs. + return; + } + DCHECK(handler); + + std::string requestID = base::UnguessableToken::Create().ToString(); + CRWHTMLElementFetchRequest* fetchRequest = + [[CRWHTMLElementFetchRequest alloc] initWithFoundElementHandler:handler]; + _pendingElementFetchRequests[base::SysUTF8ToNSString(requestID)] = + fetchRequest; + + CGSize webViewContentSize = self.webView.scrollView.contentSize; + + std::vector<base::Value> args; + args.push_back(base::Value(requestID)); + args.push_back(base::Value(point.x)); + args.push_back(base::Value(point.y)); + args.push_back(base::Value(webViewContentSize.width)); + args.push_back(base::Value(webViewContentSize.height)); + frame->CallJavaScriptFunction(std::string(kFindElementAtPointFunctionName), + args); +} + +- (void)cancelFetches { + for (CRWHTMLElementFetchRequest* fetchRequest in _pendingElementFetchRequests + .allValues) { + [fetchRequest invalidate]; + } +} + +#pragma mark - Private + +// Called when web controller receives a new message from the web page. +- (void)didReceiveScriptMessage:(WKScriptMessage*)message { + NSMutableDictionary* response = + [[NSMutableDictionary alloc] initWithDictionary:message.body]; + + NSString* requestID = response[web::kContextMenuElementRequestId]; + CRWHTMLElementFetchRequest* fetchRequest = + _pendingElementFetchRequests[requestID]; + if (!fetchRequest) { + // Do not process the message if a fetch request with a matching |requestID| + // was not found. This ensures that the response matches a request made by + // this instance. + return; + } + + web::ContextMenuParams params = + web::ContextMenuParamsFromElementDictionary(response); + params.is_main_frame = message.frameInfo.mainFrame; + params.view = self.webView; + + [_pendingElementFetchRequests removeObjectForKey:requestID]; + [fetchRequest runHandlerWithResponse:params]; +} + +#pragma mark - CRWWebStateObserver + +- (void)webStateDestroyed:(web::WebState*)webState { + if (self.webState) + self.webState->RemoveObserver(_observer.get()); + self.webState = nullptr; +} + +@end
diff --git a/ios/web/web_state/ui/crw_context_menu_element_fetcher_inttest.mm b/ios/web/web_state/ui/crw_context_menu_element_fetcher_inttest.mm new file mode 100644 index 0000000..2c41d62 --- /dev/null +++ b/ios/web/web_state/ui/crw_context_menu_element_fetcher_inttest.mm
@@ -0,0 +1,124 @@ +// Copyright 2020 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. + +#import "ios/web/web_state/ui/crw_context_menu_element_fetcher.h" + +#import <WebKit/WebKit.h> + +#include "base/macros.h" +#import "base/test/ios/wait_util.h" +#include "ios/testing/scoped_block_swizzler.h" +#import "ios/web/public/test/web_view_content_test_util.h" +#import "ios/web/test/web_test_with_web_controller.h" +#import "ios/web/web_state/context_menu_constants.h" +#import "ios/web/web_state/ui/crw_legacy_context_menu_controller.h" +#import "ios/web/web_state/ui/crw_web_controller.h" +#import "ios/web/web_state/web_state_impl.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/gtest_mac.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { +// This is the timeout used while waiting for the JavaScript to complete. The +// general kWaitForJSCompletionTimeout isn't used because one of the test is +// supposed to not complete and so will wait for the whole duration of the +// timeout. This constant is smaller to speed tests up. This constant is used in +// both the "successful" JavaScript calls and the "failing" JavaScript calls. It +// ensures that in the context of this test, the JavaScript completes in the +// given timespan (and so it ensures that if the "failing" JavaScript tests +// pass, it is because the JavaScript isn't called and not because it didn't +// have time to complete). +const CGFloat kFetcherJSTimeout = 1.0; +} // namespace + +namespace web { +class CRWContextMenuElementFetcherTest : public WebTestWithWebController { + public: + CRWContextMenuElementFetcherTest() { + // Disable the existing long press handling to avoid duplicating message + // handlers. + swizzler_ = std::make_unique<ScopedBlockSwizzler>( + [CRWLegacyContextMenuController class], + @selector(initWithWebView:webState:), ^id(id self) { + return nil; + }); + } + + void SetUp() override { + WebTestWithWebState::SetUp(); + WKWebView* web_view = [web_controller() ensureWebViewCreated]; + fetcher_ = + [[CRWContextMenuElementFetcher alloc] initWithWebView:web_view + webState:web_state()]; + } + + // Loads a page containing a link and waits until the link is present on the + // page, making sure that the HTML is correctly injected. + bool LoadHtmlPage() WARN_UNUSED_RESULT { + NSString* html = + @"<html><head>" + "<style>body { font-size:14em; }</style>" + "<meta name=\"viewport\" content=\"user-scalable=no, width=100\">" + "</head><body><p><a id=\"linkID\" " + "href=\"http://destination/\">link</a></p></body></html>"; + + LoadHtml(html); + + bool element_present = test::WaitForWebViewContainingElement( + web_state(), [ElementSelector selectorWithElementID:"linkID"]); + if (element_present) { + // If the element is present, we still need a small delay to let all the + // scripts be injected in the page. + base::test::ios::SpinRunLoopWithMinDelay( + base::TimeDelta::FromSecondsD(0.5)); + } + return element_present; + } + + CRWContextMenuElementFetcher* GetFetcher() { return fetcher_; } + + private: + std::unique_ptr<ScopedBlockSwizzler> swizzler_; + CRWContextMenuElementFetcher* fetcher_; +}; + +// Tests that the fetcher is triggering a callback for one element. +TEST_F(CRWContextMenuElementFetcherTest, FetchOneElement) { + EXPECT_TRUE(LoadHtmlPage()); + + CRWContextMenuElementFetcher* fetcher = GetFetcher(); + __block bool callback_called = false; + [fetcher fetchDOMElementAtPoint:CGPointMake(10, 10) + completionHandler:^(const web::ContextMenuParams&) { + callback_called = true; + }]; + + EXPECT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(kFetcherJSTimeout, ^{ + return callback_called; + })); +} + +// Tests that cancelled fetches don't trigger callback. +TEST_F(CRWContextMenuElementFetcherTest, CancelFetch) { + EXPECT_TRUE(LoadHtmlPage()); + + CRWContextMenuElementFetcher* fetcher = GetFetcher(); + __block bool callback_called = false; + [fetcher fetchDOMElementAtPoint:CGPointMake(10, 10) + completionHandler:^(const web::ContextMenuParams&) { + callback_called = true; + }]; + [fetcher cancelFetches]; + + // The callback should never be called. + EXPECT_FALSE( + base::test::ios::WaitUntilConditionOrTimeout(kFetcherJSTimeout, ^{ + return callback_called; + })); +} + +} // namespace web
diff --git a/ios/web/web_state/ui/html_element_fetch_request.h b/ios/web/web_state/ui/crw_html_element_fetch_request.h similarity index 68% rename from ios/web/web_state/ui/html_element_fetch_request.h rename to ios/web/web_state/ui/crw_html_element_fetch_request.h index 9aa02d3..6d89648 100644 --- a/ios/web/web_state/ui/html_element_fetch_request.h +++ b/ios/web/web_state/ui/crw_html_element_fetch_request.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_WEB_WEB_STATE_UI_HTML_ELEMENT_FETCH_REQUEST_H_ -#define IOS_WEB_WEB_STATE_UI_HTML_ELEMENT_FETCH_REQUEST_H_ +#ifndef IOS_WEB_WEB_STATE_UI_CRW_HTML_ELEMENT_FETCH_REQUEST_H_ +#define IOS_WEB_WEB_STATE_UI_CRW_HTML_ELEMENT_FETCH_REQUEST_H_ #import <Foundation/Foundation.h> @@ -11,8 +11,12 @@ class TimeTicks; } // namespace base +namespace web { +struct ContextMenuParams; +} + // Tracks request details for fetching attributes of an element. -@interface HTMLElementFetchRequest : NSObject +@interface CRWHTMLElementFetchRequest : NSObject // The time this object was created. @property(nonatomic, readonly) base::TimeTicks creationTime; @@ -21,16 +25,17 @@ // Designated initializer to create a new object with the given completion // handler |foundElementHandler|. - (instancetype)initWithFoundElementHandler: - (void (^)(NSDictionary*))foundElementHandler NS_DESIGNATED_INITIALIZER; + (void (^)(const web::ContextMenuParams&))foundElementHandler + NS_DESIGNATED_INITIALIZER; // Calls the |foundElementHandler| from the receiver's initializer with // |response| as the parameter. This method has no effect if |invalidate| has // been called. -- (void)runHandlerWithResponse:(NSDictionary*)response; +- (void)runHandlerWithResponse:(const web::ContextMenuParams&)response; // Removes the stored |foundElementHandler| from the receiver's initializer. // |runHandlerWithResponse:| will have no effect if called after |invalidate|. - (void)invalidate; @end -#endif // IOS_WEB_WEB_STATE_UI_HTML_ELEMENT_FETCH_REQUEST_H_ +#endif // IOS_WEB_WEB_STATE_UI_CRW_HTML_ELEMENT_FETCH_REQUEST_H_
diff --git a/ios/web/web_state/ui/html_element_fetch_request.mm b/ios/web/web_state/ui/crw_html_element_fetch_request.mm similarity index 65% rename from ios/web/web_state/ui/html_element_fetch_request.mm rename to ios/web/web_state/ui/crw_html_element_fetch_request.mm index 0835371..209779e 100644 --- a/ios/web/web_state/ui/html_element_fetch_request.mm +++ b/ios/web/web_state/ui/crw_html_element_fetch_request.mm
@@ -2,26 +2,28 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/web/web_state/ui/html_element_fetch_request.h" +#import "ios/web/web_state/ui/crw_html_element_fetch_request.h" #include "base/time/time.h" +#import "ios/web/public/ui/context_menu_params.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif -@interface HTMLElementFetchRequest () +@interface CRWHTMLElementFetchRequest () // Completion handler to call with found DOM element. -@property(nonatomic, copy) void (^foundElementHandler)(NSDictionary*); +@property(nonatomic, copy) void (^foundElementHandler) + (const web::ContextMenuParams&); @end -@implementation HTMLElementFetchRequest +@implementation CRWHTMLElementFetchRequest @synthesize creationTime = _creationTime; @synthesize foundElementHandler = _foundElementHandler; - (instancetype)initWithFoundElementHandler: - (void (^)(NSDictionary*))foundElementHandler { + (void (^)(const web::ContextMenuParams&))foundElementHandler { self = [super init]; if (self) { _creationTime = base::TimeTicks::Now(); @@ -30,7 +32,7 @@ return self; } -- (void)runHandlerWithResponse:(NSDictionary*)response { +- (void)runHandlerWithResponse:(const web::ContextMenuParams&)response { if (_foundElementHandler) { _foundElementHandler(response); }
diff --git a/ios/web/web_state/ui/crw_html_element_fetch_request_unittest.mm b/ios/web/web_state/ui/crw_html_element_fetch_request_unittest.mm new file mode 100644 index 0000000..370cf69 --- /dev/null +++ b/ios/web/web_state/ui/crw_html_element_fetch_request_unittest.mm
@@ -0,0 +1,67 @@ +// 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. + +#import "ios/web/web_state/ui/crw_html_element_fetch_request.h" + +#include "base/time/time.h" +#import "ios/web/public/ui/context_menu_params.h" +#import "ios/web/web_state/context_menu_constants.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/gtest_mac.h" +#include "testing/platform_test.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace web { + +using CRWHTMLElementFetchRequestTest = PlatformTest; + +// Tests that |creationTime| is set at CRWHTMLElementFetchRequest object +// creation. +TEST_F(CRWHTMLElementFetchRequestTest, CreationTime) { + CRWHTMLElementFetchRequest* request = + [[CRWHTMLElementFetchRequest alloc] initWithFoundElementHandler:nil]; + base::TimeDelta delta = base::TimeTicks::Now() - request.creationTime; + // Validate that |request.creationTime| is "now", but only use second + // precision to avoid performance induced test flake. + EXPECT_GT(1, delta.InSeconds()); +} + +// Tests that |runHandlerWithResponse:| runs the handler from the object's +// initializer with the expected |response|. +TEST_F(CRWHTMLElementFetchRequestTest, RunHandler) { + __block bool handler_called = false; + __block web::ContextMenuParams received_params; + void (^handler)(const web::ContextMenuParams&) = + ^(const web::ContextMenuParams& params) { + handler_called = true; + received_params = params; + }; + CRWHTMLElementFetchRequest* request = + [[CRWHTMLElementFetchRequest alloc] initWithFoundElementHandler:handler]; + web::ContextMenuParams params = web::ContextMenuParams(); + params.link_text = @"text"; + [request runHandlerWithResponse:params]; + EXPECT_TRUE(handler_called); + EXPECT_NSEQ(params.link_text, received_params.link_text); +} + +// Tests that |runHandlerWithResponse:| does not run the handler from the +// object's initializer if |invalidate| has been called. +TEST_F(CRWHTMLElementFetchRequestTest, Invalidate) { + __block bool handler_called = false; + void (^handler)(const web::ContextMenuParams&) = + ^(const web::ContextMenuParams& params) { + handler_called = true; + }; + CRWHTMLElementFetchRequest* request = + [[CRWHTMLElementFetchRequest alloc] initWithFoundElementHandler:handler]; + [request invalidate]; + [request runHandlerWithResponse:web::ContextMenuParams()]; + EXPECT_FALSE(handler_called); +} + +} // namespace web
diff --git a/ios/web/web_state/ui/crw_legacy_context_menu_controller.mm b/ios/web/web_state/ui/crw_legacy_context_menu_controller.mm index a5065ff..6970ccc 100644 --- a/ios/web/web_state/ui/crw_legacy_context_menu_controller.mm +++ b/ios/web/web_state/ui/crw_legacy_context_menu_controller.mm
@@ -11,21 +11,14 @@ #include "base/ios/ios_util.h" #include "base/mac/foundation_util.h" #include "base/metrics/histogram_macros.h" -#include "base/strings/sys_string_conversions.h" -#include "base/unguessable_token.h" #include "base/values.h" -#import "ios/web/js_messaging/crw_wk_script_message_router.h" -#import "ios/web/public/js_messaging/web_frame.h" -#import "ios/web/public/js_messaging/web_frame_util.h" #import "ios/web/public/navigation/navigation_context.h" #import "ios/web/public/ui/context_menu_params.h" #include "ios/web/public/web_client.h" #import "ios/web/public/web_state.h" #import "ios/web/public/web_state_observer_bridge.h" -#import "ios/web/web_state/context_menu_constants.h" #import "ios/web/web_state/context_menu_params_utils.h" -#import "ios/web/web_state/ui/html_element_fetch_request.h" -#import "ios/web/web_state/ui/wk_web_view_configuration_provider.h" +#import "ios/web/web_state/ui/crw_context_menu_element_fetcher.h" #import "ios/web/web_state/web_state_impl.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -54,13 +47,6 @@ } } -// Javascript function name to obtain element details at a point. -const char kFindElementAtPointFunctionName[] = "findElementAtPoint"; - -// JavaScript message handler name installed in WKWebView for found element -// response. -NSString* const kFindElementResultHandlerName = @"FindElementResultHandler"; - // Enum used to record element details fetched for the context menu. enum class ContextMenuElementFrame { // Recorded when the element was found in the main frame. @@ -89,17 +75,6 @@ kMaxValue = Cancel }; -// Struct to track the details of the element at |location| in |webView|. -struct ContextMenuInfo { - // The location of the long press. - CGPoint location; - // True if the element is in the page's main frame, false if in an iframe. - BOOL is_main_frame; - // DOM element information. May contain the keys defined in - // ios/web/web_state/context_menu_constants.h. All values are strings. - NSDictionary* dom_element; -}; - // Returns an array of gesture recognizers with |fragment| in it's description // and attached to a subview of |webView|. NSArray<UIGestureRecognizer*>* GestureRecognizersWithDescriptionFragment( @@ -182,6 +157,8 @@ // WebState associated with this controller. @property(nonatomic, assign) web::WebStateImpl* webState; +@property(nonatomic, strong) CRWContextMenuElementFetcher* elementFetcher; + // Called when the |_contextMenuRecognizer| finishes recognizing a long press. - (void)longPressDetectedByGestureRecognizer: (UIGestureRecognizer*)gestureRecognizer; @@ -190,21 +167,12 @@ // Called when the |_contextMenuRecognizer| changes. - (void)longPressGestureRecognizerChanged; // Show the context menu or allow the system default behavior based on the DOM -// element details in |_contextMenuInfoForLastTouch.dom_element|. +// element details in |contextMenuParams|. - (void)processReceivedDOMElement; // Called when the context menu must be shown. - (void)showContextMenu; // Cancels all touch events in the web view (long presses, tapping, scrolling). - (void)cancelAllTouches; -// Asynchronously fetches information about DOM element for the given point (in -// UIView coordinates). |handler| can not be nil. See -// |_contextMenuInfoForLastTouch.dom_element| for element format description. -- (void)fetchDOMElementAtPoint:(CGPoint)point - completionHandler:(void (^)(NSDictionary*))handler; -// Sets the value of |_contextMenuInfoForLastTouch.dom_element|. -- (void)setDOMElementForLastTouch:(NSDictionary*)element; -// Called to process a message received from JavaScript. -- (void)didReceiveScriptMessage:(WKScriptMessage*)message; // Cancels the display of the context menu and clears associated element fetch // request state. - (void)cancelContextMenuDisplay; @@ -214,10 +182,8 @@ std::unique_ptr<web::WebStateObserverBridge> _observer; // Long press recognizer that allows showing context menus. UILongPressGestureRecognizer* _contextMenuRecognizer; - // DOM element information for the point where the user made the last touch. - // Precalculation is necessary because retreiving DOM element relies on async - // API so element info can not be built on demand. - ContextMenuInfo _contextMenuInfoForLastTouch; + // Location of the last touch on the screen. + CGPoint _lastTouchLocation; // Whether or not the system cotext menu should be displayed. If not, custom // context menu should be displayed. BOOL _systemContextMenuEnabled; @@ -229,10 +195,8 @@ // |_contextMenuRecognizer| finished, but couldn't yet show the context menu // becuase the DOM element details were not yet available. BOOL _contextMenuNeedsDisplay; - // Details for currently in progress element fetches. The objects are - // instances of HTMLElementFetchRequest and are keyed by a unique requestId - // string. - NSMutableDictionary* _pendingElementFetchRequests; + // Parameters for the context menu, populated by the element fetcher. + base::Optional<web::ContextMenuParams> _contextMenuParams; } @synthesize webView = _webView; @@ -243,7 +207,10 @@ self = [super init]; if (self) { _webView = webView; - _pendingElementFetchRequests = [[NSMutableDictionary alloc] init]; + + _elementFetcher = + [[CRWContextMenuElementFetcher alloc] initWithWebView:webView + webState:webState]; _webState = webState; _observer = std::make_unique<web::WebStateObserverBridge>(self); @@ -273,20 +240,6 @@ [_webView addGestureRecognizer:_contextMenuRecognizer]; OverrideGestureRecognizers(_contextMenuRecognizer, _webView); - - // Listen for fetched element response. - web::WKWebViewConfigurationProvider& configurationProvider = - web::WKWebViewConfigurationProvider::FromBrowserState( - webState->GetBrowserState()); - CRWWKScriptMessageRouter* messageRouter = - configurationProvider.GetScriptMessageRouter(); - __weak CRWLegacyContextMenuController* weakSelf = self; - [messageRouter - setScriptMessageHandler:^(WKScriptMessage* message) { - [weakSelf didReceiveScriptMessage:message]; - } - name:kFindElementResultHandlerName - webView:webView]; } return self; } @@ -329,7 +282,7 @@ } - (void)longPressGestureRecognizerBegan { - if (_contextMenuInfoForLastTouch.dom_element) { + if (_contextMenuParams.has_value()) { [self processReceivedDOMElement]; } else { // Shows the context menu once the DOM element information is set. @@ -340,7 +293,7 @@ - (void)longPressGestureRecognizerChanged { if (!_contextMenuNeedsDisplay || - CGPointEqualToPoint(_contextMenuInfoForLastTouch.location, CGPointZero)) { + CGPointEqualToPoint(_lastTouchLocation, CGPointZero)) { return; } @@ -350,10 +303,8 @@ // |_contextMenuNeedsDisplay| has already been set to True. CGPoint currentTouchLocation = [_contextMenuRecognizer locationInView:_webView]; - float deltaX = std::abs(_contextMenuInfoForLastTouch.location.x - - currentTouchLocation.x); - float deltaY = std::abs(_contextMenuInfoForLastTouch.location.y - - currentTouchLocation.y); + float deltaX = std::abs(_lastTouchLocation.x - currentTouchLocation.x); + float deltaY = std::abs(_lastTouchLocation.y - currentTouchLocation.y); if (deltaX > kLongPressMoveDeltaPixels || deltaY > kLongPressMoveDeltaPixels) { [self cancelContextMenuDisplay]; @@ -361,8 +312,9 @@ } - (void)processReceivedDOMElement { - BOOL canShowContextMenu = web::CanShowContextMenuForElementDictionary( - _contextMenuInfoForLastTouch.dom_element); + BOOL canShowContextMenu = + _contextMenuParams.has_value() && + web::CanShowContextMenuForParams(_contextMenuParams.value()); if (!canShowContextMenu) { // There is no link or image under user's gesture. Do not cancel all touches // to allow system text selection UI. @@ -374,30 +326,25 @@ // intentionally suppress system context menu UI. [self cancelAllTouches]; - _contextMenuInfoForLastTouch.location = - [_contextMenuRecognizer locationInView:_webView]; + _lastTouchLocation = [_contextMenuRecognizer locationInView:_webView]; [self showContextMenu]; } - (void)showContextMenu { - if (!self.webState) { + if (!self.webState || !_contextMenuParams.has_value()) { return; } // Log if the element is in the main frame or a child frame. UMA_HISTOGRAM_ENUMERATION("ContextMenu.DOMElementFrame", - (_contextMenuInfoForLastTouch.is_main_frame + (_contextMenuParams.value().is_main_frame ? ContextMenuElementFrame::MainFrame : ContextMenuElementFrame::Iframe), ContextMenuElementFrame::Count); - web::ContextMenuParams params = web::ContextMenuParamsFromElementDictionary( - _contextMenuInfoForLastTouch.dom_element); - params.view = _webView; - params.location = _contextMenuInfoForLastTouch.location; - params.is_main_frame = _contextMenuInfoForLastTouch.is_main_frame; + _contextMenuParams.value().location = _lastTouchLocation; - self.webState->HandleContextMenu(params); + self.webState->HandleContextMenu(_contextMenuParams.value()); } - (void)cancelAllTouches { @@ -415,8 +362,9 @@ } } -- (void)setDOMElementForLastTouch:(NSDictionary*)element { - _contextMenuInfoForLastTouch.dom_element = [element copy]; +// Sets the value of |params|. +- (void)setParamsForLastTouch:(const web::ContextMenuParams&)params { + _contextMenuParams = params; if (_contextMenuNeedsDisplay) { _contextMenuNeedsDisplay = NO; UMA_HISTOGRAM_ENUMERATION(kContextMenuDelayedElementDetailsHistogram, @@ -425,33 +373,14 @@ } } -- (void)didReceiveScriptMessage:(WKScriptMessage*)message { - NSMutableDictionary* response = - [[NSMutableDictionary alloc] initWithDictionary:message.body]; - _contextMenuInfoForLastTouch.is_main_frame = message.frameInfo.mainFrame; - NSString* requestID = response[web::kContextMenuElementRequestId]; - HTMLElementFetchRequest* fetchRequest = - _pendingElementFetchRequests[requestID]; - // Do not process the message if a fetch request with a matching |requestID| - // was not found. This ensures that the response matches a request made by - // this CRWLegacyContextMenuController instance. - if (fetchRequest) { - [_pendingElementFetchRequests removeObjectForKey:requestID]; - [fetchRequest runHandlerWithResponse:response]; - } -} - - (void)cancelContextMenuDisplay { if (_contextMenuNeedsDisplay) { UMA_HISTOGRAM_ENUMERATION(kContextMenuDelayedElementDetailsHistogram, DelayedElementDetailsState::Cancel); } _contextMenuNeedsDisplay = NO; - _contextMenuInfoForLastTouch.location = CGPointZero; - for (HTMLElementFetchRequest* fetchRequest in _pendingElementFetchRequests - .allValues) { - [fetchRequest invalidate]; - } + _lastTouchLocation = CGPointZero; + [self.elementFetcher cancelFetches]; } #pragma mark - @@ -481,14 +410,15 @@ // touch. If there a link, the web controller will reject system's context // menu and show another one. If for some reason context menu info is not // fetched - system context menu will be shown. - [self setDOMElementForLastTouch:nil]; + _contextMenuParams.reset(); [self cancelContextMenuDisplay]; __weak CRWLegacyContextMenuController* weakSelf = self; - [self fetchDOMElementAtPoint:[touch locationInView:_webView] - completionHandler:^(NSDictionary* element) { - [weakSelf setDOMElementForLastTouch:element]; - }]; + [self.elementFetcher + fetchDOMElementAtPoint:[touch locationInView:_webView.scrollView] + completionHandler:^(const web::ContextMenuParams& params) { + [weakSelf setParamsForLastTouch:params]; + }]; return YES; } @@ -512,39 +442,6 @@ return YES; } -#pragma mark - -#pragma mark Web Page Features - -- (void)fetchDOMElementAtPoint:(CGPoint)point - completionHandler:(void (^)(NSDictionary*))handler { - if (!self.webState) { - return; - } - web::WebFrame* frame = GetMainFrame(self.webState); - if (!frame) { - // A WebFrame may not exist for certain types of content, like PDFs. - return; - } - DCHECK(handler); - - std::string requestID = base::UnguessableToken::Create().ToString(); - HTMLElementFetchRequest* fetchRequest = - [[HTMLElementFetchRequest alloc] initWithFoundElementHandler:handler]; - _pendingElementFetchRequests[base::SysUTF8ToNSString(requestID)] = - fetchRequest; - - CGSize webViewContentSize = self.webScrollView.contentSize; - - std::vector<base::Value> args; - args.push_back(base::Value(requestID)); - args.push_back(base::Value(point.x + self.scrollPosition.x)); - args.push_back(base::Value(point.y + self.scrollPosition.y)); - args.push_back(base::Value(webViewContentSize.width)); - args.push_back(base::Value(webViewContentSize.height)); - frame->CallJavaScriptFunction(std::string(kFindElementAtPointFunctionName), - args); -} - #pragma mark - CRWWebStateObserver - (void)webStateDestroyed:(web::WebState*)webState {
diff --git a/ios/web/web_state/ui/crw_wk_ui_handler.mm b/ios/web/web_state/ui/crw_wk_ui_handler.mm index 931c18c..adf24de 100644 --- a/ios/web/web_state/ui/crw_wk_ui_handler.mm +++ b/ios/web/web_state/ui/crw_wk_ui_handler.mm
@@ -168,6 +168,9 @@ }]; } +#if !defined(__IPHONE_13_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_13_0 + +// TODO(crbug.com/1131852): Preview depracted is iOS13+ - (BOOL)webView:(WKWebView*)webView shouldPreviewElement:(WKPreviewElementInfo*)elementInfo { return self.webStateImpl->ShouldPreviewLink( @@ -211,6 +214,8 @@ completionHandler); } +#endif // End of >iOS13 deprecated block. + - (void)webView:(WKWebView*)webView contextMenuDidEndForElement:(WKContextMenuElementInfo*)elementInfo API_AVAILABLE(ios(13.0)) {
diff --git a/ios/web/web_state/ui/html_element_fetch_request_unittest.mm b/ios/web/web_state/ui/html_element_fetch_request_unittest.mm deleted file mode 100644 index 58b4b563..0000000 --- a/ios/web/web_state/ui/html_element_fetch_request_unittest.mm +++ /dev/null
@@ -1,62 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/web/web_state/ui/html_element_fetch_request.h" - -#include "base/time/time.h" -#import "ios/web/web_state/context_menu_constants.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/gtest_mac.h" -#include "testing/platform_test.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace web { - -using HtmlElementFetchRequestTest = PlatformTest; - -// Tests that |creationTime| is set at HtmlElementFetchRequest object creation. -TEST_F(HtmlElementFetchRequestTest, CreationTime) { - HTMLElementFetchRequest* request = - [[HTMLElementFetchRequest alloc] initWithFoundElementHandler:nil]; - base::TimeDelta delta = base::TimeTicks::Now() - request.creationTime; - // Validate that |request.creationTime| is "now", but only use second - // precision to avoid performance induced test flake. - EXPECT_GT(1, delta.InSeconds()); -} - -// Tests that |runHandlerWithResponse:| runs the handler from the object's -// initializer with the expected |response|. -TEST_F(HtmlElementFetchRequestTest, RunHandler) { - __block bool handler_called = false; - __block NSDictionary* received_response = nil; - void (^handler)(NSDictionary*) = ^(NSDictionary* response) { - handler_called = true; - received_response = response; - }; - HTMLElementFetchRequest* request = - [[HTMLElementFetchRequest alloc] initWithFoundElementHandler:handler]; - NSDictionary* response = @{kContextMenuElementInnerText : @"text"}; - [request runHandlerWithResponse:response]; - EXPECT_TRUE(handler_called); - EXPECT_NSEQ(response, received_response); -} - -// Tests that |runHandlerWithResponse:| does not run the handler from the -// object's initializer if |invalidate| has been called. -TEST_F(HtmlElementFetchRequestTest, Invalidate) { - __block bool handler_called = false; - void (^handler)(NSDictionary*) = ^(NSDictionary* response) { - handler_called = true; - }; - HTMLElementFetchRequest* request = - [[HTMLElementFetchRequest alloc] initWithFoundElementHandler:handler]; - [request invalidate]; - [request runHandlerWithResponse:nil]; - EXPECT_FALSE(handler_called); -} - -} // namespace web
diff --git a/ios/web_view/internal/autofill/cwv_autofill_controller.mm b/ios/web_view/internal/autofill/cwv_autofill_controller.mm index c37d30d..f616c17 100644 --- a/ios/web_view/internal/autofill/cwv_autofill_controller.mm +++ b/ios/web_view/internal/autofill/cwv_autofill_controller.mm
@@ -70,9 +70,6 @@ // Javascript autofill manager associated with |webState|. JsAutofillManager* _JSAutofillManager; - // Javascript suggestion manager associated with |webState|. - JsSuggestionManager* _JSSuggestionManager; - // The |webState| which this autofill controller should observe. web::WebState* _webState; @@ -95,7 +92,7 @@ std::unique_ptr<autofill::FormActivityObserverBridge> _formActivityObserverBridge; - NSString* _lastFormActivityWebFrameID; + std::string _lastFormActivityWebFrameID; NSString* _lastFormActivityTypedValue; NSString* _lastFormActivityType; FormRendererId _lastFormActivityUniqueFormID; @@ -110,7 +107,6 @@ autofillClient autofillAgent:(AutofillAgent*)autofillAgent JSAutofillManager:(JsAutofillManager*)JSAutofillManager - JSSuggestionManager:(JsSuggestionManager*)JSSuggestionManager passwordManager:(std::unique_ptr<password_manager::PasswordManager>) passwordManager passwordManagerClient: @@ -144,8 +140,6 @@ _JSAutofillManager = JSAutofillManager; - _JSSuggestionManager = JSSuggestionManager; - _passwordManagerClient = std::move(passwordManagerClient); _passwordManagerClient->set_bridge(self); _passwordManager = std::move(passwordManager); @@ -301,21 +295,20 @@ } - (void)focusPreviousField { - [_JSSuggestionManager - selectPreviousElementInFrameWithID:_lastFormActivityWebFrameID]; + autofill::JsSuggestionManager::GetOrCreateForWebState(_webState) + ->SelectPreviousElementInFrameWithID(_lastFormActivityWebFrameID); } - (void)focusNextField { - [_JSSuggestionManager - selectNextElementInFrameWithID:_lastFormActivityWebFrameID]; + autofill::JsSuggestionManager::GetOrCreateForWebState(_webState) + ->SelectNextElementInFrameWithID(_lastFormActivityWebFrameID); } - (void)checkIfPreviousAndNextFieldsAreAvailableForFocusWithCompletionHandler: (void (^)(BOOL previous, BOOL next))completionHandler { - [_JSSuggestionManager - fetchPreviousAndNextElementsPresenceInFrameWithID: - _lastFormActivityWebFrameID - completionHandler:completionHandler]; + autofill::JsSuggestionManager::GetOrCreateForWebState(_webState) + ->FetchPreviousAndNextElementsPresenceInFrameWithID( + _lastFormActivityWebFrameID, base::BindOnce(completionHandler)); } #pragma mark - CWVAutofillClientIOSBridge @@ -493,7 +486,7 @@ NSString* nsType = base::SysUTF8ToNSString(params.type); BOOL userInitiated = params.has_user_gesture; - _lastFormActivityWebFrameID = nsFrameID; + _lastFormActivityWebFrameID = GetWebFrameId(frame); _lastFormActivityTypedValue = nsValue; _lastFormActivityType = nsType; if (params.type == "focus") {
diff --git a/ios/web_view/internal/autofill/cwv_autofill_controller_internal.h b/ios/web_view/internal/autofill/cwv_autofill_controller_internal.h index 8643f3a2..31f91166 100644 --- a/ios/web_view/internal/autofill/cwv_autofill_controller_internal.h +++ b/ios/web_view/internal/autofill/cwv_autofill_controller_internal.h
@@ -37,7 +37,6 @@ @class AutofillAgent; @class JsAutofillManager; -@class JsSuggestionManager; @class SharedPasswordController; @interface CWVAutofillController () <AutofillDriverIOSBridge, @@ -53,7 +52,6 @@ autofillClient autofillAgent:(AutofillAgent*)autofillAgent JSAutofillManager:(JsAutofillManager*)JSAutofillManager - JSSuggestionManager:(JsSuggestionManager*)JSSuggestionManager passwordManager:(std::unique_ptr<password_manager::PasswordManager>) passwordManager passwordManagerClient:
diff --git a/ios/web_view/internal/autofill/cwv_autofill_controller_unittest.mm b/ios/web_view/internal/autofill/cwv_autofill_controller_unittest.mm index 8358b69..0d5c013 100644 --- a/ios/web_view/internal/autofill/cwv_autofill_controller_unittest.mm +++ b/ios/web_view/internal/autofill/cwv_autofill_controller_unittest.mm
@@ -19,7 +19,6 @@ #import "components/autofill/ios/browser/fake_autofill_agent.h" #import "components/autofill/ios/browser/fake_js_autofill_manager.h" #import "components/autofill/ios/browser/form_suggestion.h" -#import "components/autofill/ios/browser/js_suggestion_manager.h" #include "components/autofill/ios/form_util/form_activity_params.h" #import "components/autofill/ios/form_util/form_activity_tab_helper.h" #import "components/autofill/ios/form_util/test_form_activity_tab_helper.h" @@ -88,7 +87,6 @@ web_state_.SetJSInjectionReceiver(injectionReceiver); js_autofill_manager_ = [[FakeJSAutofillManager alloc] init]; - js_suggestion_manager_ = OCMClassMock([JsSuggestionManager class]); UniqueIDDataTabHelper::CreateForWebState(&web_state_); @@ -125,7 +123,6 @@ autofillClient:std::move(autofill_client) autofillAgent:autofill_agent_ JSAutofillManager:js_autofill_manager_ - JSSuggestionManager:js_suggestion_manager_ passwordManager:std::move(password_manager) passwordManagerClient:std::move(password_manager_client) passwordManagerDriver:std::move(password_manager_driver) @@ -156,7 +153,6 @@ id password_controller_; std::unique_ptr<autofill::TestFormActivityTabHelper> form_activity_tab_helper_; - id js_suggestion_manager_; WebViewPasswordManagerClient* password_manager_client_; }; @@ -310,33 +306,6 @@ EXPECT_NSEQ(frame_id_, js_autofill_manager_.lastClearedFrameIdentifier); } -// Tests CWVAutofillController focus previous field. -TEST_F(CWVAutofillControllerTest, FocusPrevious) { - [[js_suggestion_manager_ expect] selectPreviousElementInFrameWithID:nil]; - [autofill_controller_ focusPreviousField]; - [js_suggestion_manager_ verify]; -} - -// Tests CWVAutofillController focus next field. -TEST_F(CWVAutofillControllerTest, FocusNext) { - [[js_suggestion_manager_ expect] selectNextElementInFrameWithID:nil]; - [autofill_controller_ focusNextField]; - [js_suggestion_manager_ verify]; -} - -// Tests CWVAutofillController checks previous and next focusable state. -TEST_F(CWVAutofillControllerTest, CheckFocus) { - id completionHandler = ^(BOOL previous, BOOL next) { - }; - [[js_suggestion_manager_ expect] - fetchPreviousAndNextElementsPresenceInFrameWithID:nil - completionHandler:completionHandler]; - [autofill_controller_ - checkIfPreviousAndNextFieldsAreAvailableForFocusWithCompletionHandler: - completionHandler]; - [js_suggestion_manager_ verify]; -} - // Tests CWVAutofillController delegate focus callback is invoked. TEST_F(CWVAutofillControllerTest, FocusCallback) { id delegate = OCMProtocolMock(@protocol(CWVAutofillControllerDelegate));
diff --git a/ios/web_view/internal/cwv_web_view.mm b/ios/web_view/internal/cwv_web_view.mm index f368ed5..5ca736ba 100644 --- a/ios/web_view/internal/cwv_web_view.mm +++ b/ios/web_view/internal/cwv_web_view.mm
@@ -652,11 +652,6 @@ initWithPrefService:_configuration.browserState->GetPrefs() webState:_webState.get()]; JsAutofillManager* JSAutofillManager = [[JsAutofillManager alloc] init]; - JsSuggestionManager* JSSuggestionManager = - base::mac::ObjCCastStrict<JsSuggestionManager>( - [_webState->GetJSInjectionReceiver() - instanceOfClass:[JsSuggestionManager class]]); - [JSSuggestionManager setWebFramesManager:_webState->GetWebFramesManager()]; auto passwordManagerClient = ios_web_view::WebViewPasswordManagerClient::Create( @@ -682,7 +677,6 @@ autofillClient:std::move(autofillClient) autofillAgent:autofillAgent JSAutofillManager:JSAutofillManager - JSSuggestionManager:JSSuggestionManager passwordManager:std::move(passwordManager) passwordManagerClient:std::move(passwordManagerClient) passwordManagerDriver:std::move(passwordManagerDriver)
diff --git a/media/capture/video/chromeos/camera_device_context.cc b/media/capture/video/chromeos/camera_device_context.cc index 2de1625..6f5f659 100644 --- a/media/capture/video/chromeos/camera_device_context.cc +++ b/media/capture/video/chromeos/camera_device_context.cc
@@ -153,4 +153,9 @@ return result == VideoCaptureDevice::Client::ReserveResult::kSucceeded; } +bool CameraDeviceContext::HasClient() { + base::AutoLock lock(client_lock_); + return !clients_.empty(); +} + } // namespace media
diff --git a/media/capture/video/chromeos/camera_device_delegate.cc b/media/capture/video/chromeos/camera_device_delegate.cc index b05c2db..b8260fc 100644 --- a/media/capture/video/chromeos/camera_device_delegate.cc +++ b/media/capture/video/chromeos/camera_device_delegate.cc
@@ -211,6 +211,8 @@ return StreamType::kYUVInput; case 3: return StreamType::kYUVOutput; + case 4: + return StreamType::kRecordingOutput; default: return StreamType::kUnknown; } @@ -226,6 +228,8 @@ return std::string("StreamType::kYUVInput"); case StreamType::kYUVOutput: return std::string("StreamType::kYUVOutput"); + case StreamType::kRecordingOutput: + return std::string("StreamType::kRecordingOutput"); default: return std::string("Unknown StreamType value: ") + base::NumberToString(static_cast<int32_t>(stream_type)); @@ -272,18 +276,16 @@ VideoCaptureDeviceDescriptor device_descriptor, scoped_refptr<CameraHalDelegate> camera_hal_delegate, scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner, - CameraAppDeviceImpl* camera_app_device, - ClientType client_type) + CameraAppDeviceImpl* camera_app_device) : device_descriptor_(device_descriptor), camera_hal_delegate_(std::move(camera_hal_delegate)), ipc_task_runner_(std::move(ipc_task_runner)), - camera_app_device_(camera_app_device), - client_type_(client_type) {} + camera_app_device_(camera_app_device) {} CameraDeviceDelegate::~CameraDeviceDelegate() = default; void CameraDeviceDelegate::AllocateAndStart( - const VideoCaptureParams& params, + const base::flat_map<ClientType, VideoCaptureParams>& params, CameraDeviceContext* device_context) { DCHECK(ipc_task_runner_->BelongsToCurrentThread()); @@ -593,6 +595,18 @@ result_metadata_frame_number_for_photo_state_ = current_request_frame_number_; } +void CameraDeviceDelegate::ReconfigureStreams( + const base::flat_map<ClientType, VideoCaptureParams>& params) { + DCHECK(ipc_task_runner_->BelongsToCurrentThread()); + chrome_capture_params_ = params; + if (request_manager_) { + // ReconfigureStreams is used for video recording. It does not require + // photo. + request_manager_->StopPreview(base::BindOnce( + &CameraDeviceDelegate::OnFlushed, GetWeakPtr(), false, base::nullopt)); + } +} + void CameraDeviceDelegate::SetRotation(int rotation) { DCHECK(ipc_task_runner_->BelongsToCurrentThread()); DCHECK(rotation >= 0 && rotation < 360 && rotation % 90 == 0); @@ -620,11 +634,11 @@ gfx::Size new_blob_resolution(static_cast<int32_t>(settings->width), static_cast<int32_t>(settings->height)); request_manager_->StopPreview( - base::BindOnce(&CameraDeviceDelegate::OnFlushed, GetWeakPtr(), + base::BindOnce(&CameraDeviceDelegate::OnFlushed, GetWeakPtr(), true, std::move(new_blob_resolution))); } else { request_manager_->StopPreview(base::BindOnce( - &CameraDeviceDelegate::OnFlushed, GetWeakPtr(), base::nullopt)); + &CameraDeviceDelegate::OnFlushed, GetWeakPtr(), true, base::nullopt)); } return true; } @@ -645,7 +659,7 @@ // Trigger the reconfigure process if it not yet triggered. if (on_reconfigured_callbacks_.empty()) { request_manager_->StopPreview(base::BindOnce( - &CameraDeviceDelegate::OnFlushed, GetWeakPtr(), base::nullopt)); + &CameraDeviceDelegate::OnFlushed, GetWeakPtr(), true, base::nullopt)); } auto on_reconfigured_callback = base::BindOnce( [](base::WeakPtr<Camera3AController> controller, @@ -681,6 +695,7 @@ } void CameraDeviceDelegate::OnFlushed( + bool require_photo, base::Optional<gfx::Size> new_blob_resolution, int32_t result) { DCHECK(ipc_task_runner_->BelongsToCurrentThread()); @@ -692,7 +707,7 @@ return; } device_context_->SetState(CameraDeviceContext::State::kInitialized); - ConfigureStreams(true, std::move(new_blob_resolution)); + ConfigureStreams(require_photo, std::move(new_blob_resolution)); } void CameraDeviceDelegate::OnClosed(int32_t result) { @@ -760,13 +775,15 @@ DCHECK_EQ(device_context_->GetState(), CameraDeviceContext::State::kStarting); mojo::PendingRemote<cros::mojom::Camera3CallbackOps> callback_ops; + // Assumes the buffer_type will be the same for all |chrome_capture_params|. request_manager_ = std::make_unique<RequestManager>( callback_ops.InitWithNewPipeAndPassReceiver(), std::make_unique<StreamCaptureInterfaceImpl>(GetWeakPtr()), - device_context_, chrome_capture_params_.buffer_type, + device_context_, + chrome_capture_params_[ClientType::kPreviewClient].buffer_type, std::make_unique<CameraBufferFactory>(), base::BindRepeating(&RotateAndBlobify), ipc_task_runner_, - camera_app_device_, client_type_); + camera_app_device_); camera_3a_controller_ = std::make_unique<Camera3AController>( static_metadata_, request_manager_.get(), ipc_task_runner_); device_ops_->Initialize( @@ -820,27 +837,33 @@ DCHECK_EQ(device_context_->GetState(), CameraDeviceContext::State::kInitialized); - // Set up context for preview stream. - cros::mojom::Camera3StreamPtr preview_stream = - cros::mojom::Camera3Stream::New(); - preview_stream->id = static_cast<uint64_t>(StreamType::kPreviewOutput); - preview_stream->stream_type = - cros::mojom::Camera3StreamType::CAMERA3_STREAM_OUTPUT; - preview_stream->width = - chrome_capture_params_.requested_format.frame_size.width(); - preview_stream->height = - chrome_capture_params_.requested_format.frame_size.height(); - preview_stream->format = - cros::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_YCbCr_420_888; - preview_stream->usage = cros::mojom::GRALLOC_USAGE_HW_COMPOSER | - cros::mojom::GRALLOC_USAGE_HW_VIDEO_ENCODER; - preview_stream->data_space = 0; - preview_stream->rotation = - cros::mojom::Camera3StreamRotation::CAMERA3_STREAM_ROTATION_0; - cros::mojom::Camera3StreamConfigurationPtr stream_config = cros::mojom::Camera3StreamConfiguration::New(); - stream_config->streams.push_back(std::move(preview_stream)); + for (const auto& param : chrome_capture_params_) { + // Set up context for preview stream and record stream. + cros::mojom::Camera3StreamPtr stream = cros::mojom::Camera3Stream::New(); + StreamType stream_type = (param.first == ClientType::kPreviewClient) + ? StreamType::kPreviewOutput + : StreamType::kRecordingOutput; + // TODO(henryhsu): PreviewClient should remove HW_VIDEO_ENCODER usage when + // multiple streams enabled. + auto usage = (param.first == ClientType::kPreviewClient) + ? (cros::mojom::GRALLOC_USAGE_HW_COMPOSER | + cros::mojom::GRALLOC_USAGE_HW_VIDEO_ENCODER) + : cros::mojom::GRALLOC_USAGE_HW_VIDEO_ENCODER; + stream->id = static_cast<uint64_t>(stream_type); + stream->stream_type = cros::mojom::Camera3StreamType::CAMERA3_STREAM_OUTPUT; + stream->width = param.second.requested_format.frame_size.width(); + stream->height = param.second.requested_format.frame_size.height(); + stream->format = + cros::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_YCbCr_420_888; + stream->usage = usage; + stream->data_space = 0; + stream->rotation = + cros::mojom::Camera3StreamRotation::CAMERA3_STREAM_ROTATION_0; + + stream_config->streams.push_back(std::move(stream)); + } // Set up context for still capture stream. We set still capture stream to the // JPEG stream configuration with maximum supported resolution. @@ -961,9 +984,9 @@ current_blob_resolution_.SetSize(blob_resolution.width(), blob_resolution.height()); - request_manager_->SetUpStreamsAndBuffers( - chrome_capture_params_.requested_format, static_metadata_, - std::move(updated_config->streams)); + request_manager_->SetUpStreamsAndBuffers(chrome_capture_params_, + static_metadata_, + std::move(updated_config->streams)); device_context_->SetState(CameraDeviceContext::State::kStreamConfigured); // Kick off the preview stream. @@ -1130,8 +1153,10 @@ SetFpsRangeInMetadata(&settings, specified_fps_range->GetMin(), specified_fps_range->GetMax()); } else { + // Assumes the frame_rate will be the same for all |chrome_capture_params|. int32_t requested_frame_rate = - std::round(chrome_capture_params_.requested_format.frame_rate); + std::round(chrome_capture_params_[ClientType::kPreviewClient] + .requested_format.frame_rate); bool prefer_constant_frame_rate = base::FeatureList::IsEnabled( chromeos::features::kPreferConstantFrameRate) ||
diff --git a/media/capture/video/chromeos/camera_device_delegate.h b/media/capture/video/chromeos/camera_device_delegate.h index f11df02..1e2e52f 100644 --- a/media/capture/video/chromeos/camera_device_delegate.h +++ b/media/capture/video/chromeos/camera_device_delegate.h
@@ -8,6 +8,7 @@ #include <memory> #include <queue> +#include "base/containers/flat_map.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" @@ -34,7 +35,19 @@ kJpegOutput = 1, kYUVInput = 2, kYUVOutput = 3, - kUnknown, + kRecordingOutput = 4, + kUnknown = 5, +}; + +// A map to know that each StreamType belongs to which ClientType. +// The index is StreamType value. +constexpr std::array<ClientType, static_cast<int>(StreamType::kUnknown)> + kStreamClientTypeMap = { + ClientType::kPreviewClient, // kPreviewOutput + ClientType::kPreviewClient, // kJpegOutput + ClientType::kPreviewClient, // kYUVInput + ClientType::kPreviewClient, // kYUVOutput + ClientType::kVideoClient, // kRecordingOutput }; // The metadata might be large so clone a whole metadata might be relatively @@ -96,6 +109,11 @@ // AllocateAndStart of VideoCaptureDeviceArcChromeOS runs on. All the methods // in CameraDeviceDelegate run on |ipc_task_runner_| and hence all the // access to member variables is sequenced. +// +// CameraDeviceDelegate supports multiple clients. +// It will use the first client for preview stream and photo stream and use +// second client for recording stream. +// The second client will be a virtual camera device which is only used in CCA. class CAPTURE_EXPORT CameraDeviceDelegate final : public CaptureMetadataDispatcher::ResultMetadataObserver { public: @@ -103,20 +121,23 @@ VideoCaptureDeviceDescriptor device_descriptor, scoped_refptr<CameraHalDelegate> camera_hal_delegate, scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner, - CameraAppDeviceImpl* camera_app_device, - ClientType client_type); + CameraAppDeviceImpl* camera_app_device); ~CameraDeviceDelegate() final; // Delegation methods for the VideoCaptureDevice interface. - void AllocateAndStart(const VideoCaptureParams& params, - CameraDeviceContext* device_context); + void AllocateAndStart( + const base::flat_map<ClientType, VideoCaptureParams>& params, + CameraDeviceContext* device_context); void StopAndDeAllocate(base::OnceClosure device_close_callback); void TakePhoto(VideoCaptureDevice::TakePhotoCallback callback); void GetPhotoState(VideoCaptureDevice::GetPhotoStateCallback callback); void SetPhotoOptions(mojom::PhotoSettingsPtr settings, VideoCaptureDevice::SetPhotoOptionsCallback callback); + void ReconfigureStreams( + const base::flat_map<ClientType, VideoCaptureParams>& params); + // Sets the frame rotation angle in |rotation_|. |rotation_| is clockwise // rotation in degrees, and is passed to |client_| along with the captured // frames. @@ -138,8 +159,10 @@ // Mojo connection error handler. void OnMojoConnectionError(); - // Reconfigure streams for picture taking. - void OnFlushed(base::Optional<gfx::Size> new_blob_resolution, int32_t result); + // Reconfigure streams for picture taking and recording. + void OnFlushed(bool require_photo, + base::Optional<gfx::Size> new_blob_resolution, + int32_t result); // Callback method for the Close Mojo IPC call. This method resets the Mojo // connection and closes the camera device. @@ -226,7 +249,8 @@ const scoped_refptr<CameraHalDelegate> camera_hal_delegate_; - VideoCaptureParams chrome_capture_params_; + // Map client type to video capture parameter. + base::flat_map<ClientType, VideoCaptureParams> chrome_capture_params_; CameraDeviceContext* device_context_; @@ -281,8 +305,6 @@ ResultMetadata result_metadata_; gfx::Rect active_array_size_; - ClientType client_type_; - base::WeakPtrFactory<CameraDeviceDelegate> weak_ptr_factory_{this}; 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 8ed8f8c..a9489f2 100644 --- a/media/capture/video/chromeos/camera_device_delegate_unittest.cc +++ b/media/capture/video/chromeos/camera_device_delegate_unittest.cc
@@ -111,11 +111,13 @@ constexpr size_t kDefaultWidth = 1280, kDefaultHeight = 720; constexpr int32_t kDefaultMinFrameRate = 1, kDefaultMaxFrameRate = 30; -VideoCaptureParams GetDefaultCaptureParams() { +base::flat_map<ClientType, VideoCaptureParams> GetDefaultCaptureParams() { VideoCaptureParams params; + base::flat_map<ClientType, VideoCaptureParams> capture_params; params.requested_format = {gfx::Size(kDefaultWidth, kDefaultHeight), float{kDefaultMaxFrameRate}, PIXEL_FORMAT_I420}; - return params; + capture_params[ClientType::kPreviewClient] = params; + return capture_params; } } // namespace @@ -162,7 +164,7 @@ camera_device_delegate_ = std::make_unique<CameraDeviceDelegate>( devices_info[0].descriptor, camera_hal_delegate_, - device_delegate_thread_.task_runner(), nullptr, client_type_); + device_delegate_thread_.task_runner(), nullptr); } void GetNumberOfFakeCameras(
diff --git a/media/capture/video/chromeos/camera_hal_delegate.cc b/media/capture/video/chromeos/camera_hal_delegate.cc index c1041dc..903c535 100644 --- a/media/capture/video/chromeos/camera_hal_delegate.cc +++ b/media/capture/video/chromeos/camera_hal_delegate.cc
@@ -194,39 +194,16 @@ return nullptr; } - if (camera_app_device_bridge) { - auto* camera_app_device = camera_app_device_bridge->GetCameraAppDevice( - device_descriptor.device_id); - // Since the cleanup callback will be triggered when VideoCaptureDevice died - // and |camera_app_device_bridge| is actually owned by - // VideoCaptureServiceImpl, it should be safe to assume - // |camera_app_device_bridge| is still valid here. - auto cleanup_callback = base::BindOnce( - [](const std::string& device_id, CameraAppDeviceBridgeImpl* bridge) { - bridge->OnDeviceClosed(device_id); - }, - device_descriptor.device_id, camera_app_device_bridge); - auto delegate = std::make_unique<VideoCaptureDeviceChromeOSDelegate>( - std::move(task_runner_for_screen_observer), device_descriptor, this, - camera_app_device, std::move(cleanup_callback)); - return std::make_unique<VideoCaptureDeviceChromeOSHalv3>( - std::move(delegate)); - } else { - auto delegate = std::make_unique<VideoCaptureDeviceChromeOSDelegate>( - std::move(task_runner_for_screen_observer), device_descriptor, this, - nullptr, base::DoNothing()); - return std::make_unique<VideoCaptureDeviceChromeOSHalv3>( - std::move(delegate)); - } + auto* delegate = GetVCDDelegate(task_runner_for_screen_observer, + device_descriptor, camera_app_device_bridge); + return std::make_unique<VideoCaptureDeviceChromeOSHalv3>(delegate); } void CameraHalDelegate::GetSupportedFormats( - int camera_id, + const cros::mojom::CameraInfoPtr& camera_info, VideoCaptureFormats* supported_formats) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - const cros::mojom::CameraInfoPtr& camera_info = camera_info_[camera_id]; - base::flat_set<int32_t> candidate_fps_set = GetAvailableFramerates(camera_info); @@ -371,7 +348,8 @@ desc.set_control_support(GetControlSupport(camera_info)); device_id_to_camera_id_[desc.device_id] = camera_id; devices_info.emplace_back(desc); - GetSupportedFormats(camera_id, &devices_info.back().supported_formats); + GetSupportedFormats(camera_info_[camera_id], + &devices_info.back().supported_formats); } } @@ -464,6 +442,47 @@ return it->second; } +VideoCaptureDeviceChromeOSDelegate* CameraHalDelegate::GetVCDDelegate( + scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_screen_observer, + const VideoCaptureDeviceDescriptor& device_descriptor, + CameraAppDeviceBridgeImpl* camera_app_device_bridge) { + auto camera_id = GetCameraIdFromDeviceId(device_descriptor.device_id); + auto it = vcd_delegate_map_.find(camera_id); + if (it == vcd_delegate_map_.end() || it->second->HasDeviceClient() == 0) { + std::unique_ptr<VideoCaptureDeviceChromeOSDelegate> delegate; + if (camera_app_device_bridge) { + auto* camera_app_device = camera_app_device_bridge->GetCameraAppDevice( + device_descriptor.device_id); + // Since the cleanup callback will be triggered when VideoCaptureDevice + // died and |camera_app_device_bridge| is actually owned by + // VideoCaptureServiceImpl, it should be safe to assume + // |camera_app_device_bridge| is still valid here. + auto cleanup_callback = base::BindOnce( + [](const std::string& device_id, int camera_id, + CameraAppDeviceBridgeImpl* bridge, + base::flat_map< + int, std::unique_ptr<VideoCaptureDeviceChromeOSDelegate>>* + vcd_delegate_map) { + bridge->OnDeviceClosed(device_id); + vcd_delegate_map->erase(camera_id); + }, + device_descriptor.device_id, camera_id, camera_app_device_bridge, + &vcd_delegate_map_); + + delegate = std::make_unique<VideoCaptureDeviceChromeOSDelegate>( + std::move(task_runner_for_screen_observer), device_descriptor, this, + camera_app_device, std::move(cleanup_callback)); + } else { + delegate = std::make_unique<VideoCaptureDeviceChromeOSDelegate>( + std::move(task_runner_for_screen_observer), device_descriptor, this, + nullptr, base::DoNothing()); + } + vcd_delegate_map_[camera_id] = std::move(delegate); + return vcd_delegate_map_[camera_id].get(); + } + return it->second.get(); +} + void CameraHalDelegate::SetCameraModuleOnIpcThread( mojo::PendingRemote<cros::mojom::CameraModule> camera_module) { DCHECK(ipc_task_runner_->BelongsToCurrentThread()); @@ -490,6 +509,7 @@ external_camera_info_updated_.Signal(); // Clear all cached camera info, especially external cameras. + base::AutoLock lock(camera_info_lock_); camera_info_.clear(); pending_external_camera_info_.clear(); } @@ -523,6 +543,8 @@ void CameraHalDelegate::OnGotNumberOfCamerasOnIpcThread(int32_t num_cameras) { DCHECK(ipc_task_runner_->BelongsToCurrentThread()); + + base::AutoLock lock(camera_info_lock_); if (num_cameras < 0) { builtin_camera_info_updated_.Signal(); LOG(ERROR) << "Failed to get number of cameras: " << num_cameras; @@ -544,6 +566,8 @@ void CameraHalDelegate::OnSetCallbacksOnIpcThread(int32_t result) { DCHECK(ipc_task_runner_->BelongsToCurrentThread()); + + base::AutoLock lock(camera_info_lock_); if (result) { num_builtin_cameras_ = 0; builtin_camera_info_updated_.Signal(); @@ -595,6 +619,7 @@ // |camera_info_| might contain some entries for external cameras as well, // we should check all built-in cameras explicitly. bool all_updated = [&]() { + camera_info_lock_.AssertAcquired(); for (size_t i = 0; i < num_builtin_cameras_; i++) { if (camera_info_.find(i) == camera_info_.end()) { return false;
diff --git a/media/capture/video/chromeos/camera_hal_delegate.h b/media/capture/video/chromeos/camera_hal_delegate.h index ccce7e1..34d4ddd 100644 --- a/media/capture/video/chromeos/camera_hal_delegate.h +++ b/media/capture/video/chromeos/camera_hal_delegate.h
@@ -9,6 +9,7 @@ #include <string> #include <unordered_map> +#include "base/containers/flat_map.h" #include "base/macros.h" #include "base/sequence_checker.h" #include "base/single_thread_task_runner.h" @@ -30,6 +31,7 @@ class CameraAppDeviceBridgeImpl; class CameraBufferFactory; +class VideoCaptureDeviceChromeOSDelegate; // CameraHalDelegate is the component which does Mojo IPCs to the camera HAL // process on Chrome OS to access the module-level camera functionalities such @@ -98,9 +100,15 @@ void OnRegisteredCameraHalClient(int32_t result); - void GetSupportedFormats(int camera_id, + void GetSupportedFormats(const cros::mojom::CameraInfoPtr& camera_info, VideoCaptureFormats* supported_formats); + VideoCaptureDeviceChromeOSDelegate* GetVCDDelegate( + scoped_refptr<base::SingleThreadTaskRunner> + task_runner_for_screen_observer, + const VideoCaptureDeviceDescriptor& device_descriptor, + CameraAppDeviceBridgeImpl* camera_app_device_bridge); + void SetCameraModuleOnIpcThread( mojo::PendingRemote<cros::mojom::CameraModule> camera_module); @@ -174,9 +182,10 @@ // conditions. For external cameras, the |camera_info_| would be read nad // updated in CameraDeviceStatusChange, which is also protected by // |camera_info_lock_|. - size_t num_builtin_cameras_; base::Lock camera_info_lock_; - std::unordered_map<int, cros::mojom::CameraInfoPtr> camera_info_; + size_t num_builtin_cameras_ GUARDED_BY(camera_info_lock_); + std::unordered_map<int, cros::mojom::CameraInfoPtr> camera_info_ + GUARDED_BY(camera_info_lock_); // A map from |VideoCaptureDeviceDescriptor.device_id| to camera id, which is // updated in GetDeviceDescriptors() and queried in @@ -204,6 +213,9 @@ // information of vendor tags. Bound to |ipc_task_runner_|. VendorTagOpsDelegate vendor_tag_ops_delegate_; + base::flat_map<int, std::unique_ptr<VideoCaptureDeviceChromeOSDelegate>> + vcd_delegate_map_; + DISALLOW_COPY_AND_ASSIGN(CameraHalDelegate); };
diff --git a/media/capture/video/chromeos/request_manager.cc b/media/capture/video/chromeos/request_manager.cc index 7dedadf0..7f7f5b4 100644 --- a/media/capture/video/chromeos/request_manager.cc +++ b/media/capture/video/chromeos/request_manager.cc
@@ -42,8 +42,7 @@ std::unique_ptr<CameraBufferFactory> camera_buffer_factory, BlobifyCallback blobify_callback, scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner, - CameraAppDeviceImpl* camera_app_device, - ClientType client_type) + CameraAppDeviceImpl* camera_app_device) : callback_ops_(this, std::move(callback_ops_receiver)), capture_interface_(std::move(capture_interface)), device_context_(device_context), @@ -52,15 +51,13 @@ stream_buffer_manager_( new StreamBufferManager(device_context_, video_capture_use_gmb_, - std::move(camera_buffer_factory), - client_type)), + std::move(camera_buffer_factory))), blobify_callback_(std::move(blobify_callback)), ipc_task_runner_(std::move(ipc_task_runner)), capturing_(false), partial_result_count_(1), first_frame_shutter_time_(base::TimeTicks()), - camera_app_device_(std::move(camera_app_device)), - client_type_(client_type) { + camera_app_device_(std::move(camera_app_device)) { DCHECK(ipc_task_runner_->BelongsToCurrentThread()); DCHECK(callback_ops_.is_bound()); DCHECK(device_context_); @@ -80,7 +77,7 @@ RequestManager::~RequestManager() = default; void RequestManager::SetUpStreamsAndBuffers( - VideoCaptureFormat capture_format, + base::flat_map<ClientType, VideoCaptureParams> capture_params, const cros::mojom::CameraMetadataPtr& static_metadata, std::vector<cros::mojom::Camera3StreamPtr> streams) { // The partial result count metadata is optional; defaults to 1 in case it @@ -107,7 +104,7 @@ } stream_buffer_manager_->SetUpStreamsAndBuffers( - capture_format, static_metadata, std::move(streams)); + capture_params, static_metadata, std::move(streams)); } cros::mojom::Camera3StreamPtr RequestManager::GetStreamConfiguration( @@ -269,11 +266,13 @@ // 2. Capture (YuvOutput) // 3. Preview + Capture (YuvOutput) // 4. Reprocess (YuvInput + BlobOutput) + // 5. Preview + Recording (YuvOutput) // // For device without reprocess capability: // 1. Preview // 2. Capture (BlobOutput) // 3. Preview + Capture (BlobOutput) + // 4. Preview + Recording (YuvOutput) std::set<StreamType> stream_types; cros::mojom::CameraMetadataPtr settings; TakePhotoCallback callback = base::NullCallback(); @@ -283,6 +282,7 @@ bool is_reprocess_request = false; bool is_preview_request = false; bool is_oneshot_request = false; + bool is_recording_request = false; // First, check if there are pending reprocess tasks. is_reprocess_request = TryPrepareReprocessRequest( @@ -300,7 +300,12 @@ TryPrepareOneShotRequest(&stream_types, &settings, &callback); } - if (!is_reprocess_request && !is_oneshot_request && !is_preview_request) { + if (is_preview_request) { + is_recording_request = TryPrepareRecordingRequest(&stream_types); + } + + if (!is_reprocess_request && !is_oneshot_request && !is_preview_request && + !is_recording_request) { // We have to keep the pipeline full. if (preview_buffers_queued_ < pipeline_depth_) { ipc_task_runner_->PostTask( @@ -450,6 +455,17 @@ return true; } +bool RequestManager::TryPrepareRecordingRequest( + std::set<StreamType>* stream_types) { + if (!stream_buffer_manager_->IsRecordingSupported() || + !stream_buffer_manager_->HasFreeBuffers({StreamType::kRecordingOutput})) { + return false; + } + + stream_types->insert({StreamType::kRecordingOutput}); + return true; +} + void RequestManager::OnProcessedCaptureRequest(int32_t result) { DCHECK(ipc_task_runner_->BelongsToCurrentThread()); @@ -790,8 +806,10 @@ // Deliver the captured data to client. if (stream_buffer->status == cros::mojom::Camera3BufferStatus::CAMERA3_BUFFER_STATUS_OK) { - if (stream_type == StreamType::kPreviewOutput) { - SubmitCapturedPreviewBuffer(frame_number, buffer_ipc_id); + if (stream_type == StreamType::kPreviewOutput || + stream_type == StreamType::kRecordingOutput) { + SubmitCapturedPreviewRecordingBuffer(frame_number, buffer_ipc_id, + stream_type); } else if (stream_type == StreamType::kJpegOutput) { SubmitCapturedJpegBuffer(frame_number, buffer_ipc_id); } else if (stream_type == StreamType::kYUVOutput) { @@ -827,14 +845,17 @@ PrepareCaptureRequest(); } -void RequestManager::SubmitCapturedPreviewBuffer(uint32_t frame_number, - uint64_t buffer_ipc_id) { +void RequestManager::SubmitCapturedPreviewRecordingBuffer( + uint32_t frame_number, + uint64_t buffer_ipc_id, + StreamType stream_type) { const CaptureResult& pending_result = pending_results_[frame_number]; + auto client_type = kStreamClientTypeMap[static_cast<int>(stream_type)]; if (video_capture_use_gmb_) { VideoCaptureFormat format; base::Optional<VideoCaptureDevice::Client::Buffer> buffer = stream_buffer_manager_->AcquireBufferForClientById( - StreamType::kPreviewOutput, buffer_ipc_id, &format); + stream_type, buffer_ipc_id, &format); CHECK(buffer); // TODO: Figure out the right color space for the camera frame. We may need @@ -866,22 +887,21 @@ metadata.rotation = VideoRotation::VIDEO_ROTATION_0; } device_context_->SubmitCapturedVideoCaptureBuffer( - client_type_, std::move(*buffer), format, pending_result.reference_time, + client_type, std::move(*buffer), format, pending_result.reference_time, pending_result.timestamp, metadata); // |buffer| ownership is transferred to client, so we need to reserve a // new video buffer. - stream_buffer_manager_->ReserveBuffer(StreamType::kPreviewOutput); + stream_buffer_manager_->ReserveBuffer(stream_type); } else { gfx::GpuMemoryBuffer* gmb = stream_buffer_manager_->GetGpuMemoryBufferById( - StreamType::kPreviewOutput, buffer_ipc_id); + stream_type, buffer_ipc_id); CHECK(gmb); device_context_->SubmitCapturedGpuMemoryBuffer( - client_type_, gmb, - stream_buffer_manager_->GetStreamCaptureFormat( - StreamType::kPreviewOutput), + client_type, gmb, + stream_buffer_manager_->GetStreamCaptureFormat(stream_type), pending_result.reference_time, pending_result.timestamp); - stream_buffer_manager_->ReleaseBufferFromCaptureResult( - StreamType::kPreviewOutput, buffer_ipc_id); + stream_buffer_manager_->ReleaseBufferFromCaptureResult(stream_type, + buffer_ipc_id); } }
diff --git a/media/capture/video/chromeos/request_manager.h b/media/capture/video/chromeos/request_manager.h index f5d4fdad..3d9a6d0 100644 --- a/media/capture/video/chromeos/request_manager.h +++ b/media/capture/video/chromeos/request_manager.h
@@ -12,6 +12,7 @@ #include <set> #include <vector> +#include "base/containers/flat_map.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" #include "media/capture/mojom/image_capture.mojom.h" @@ -107,14 +108,13 @@ std::unique_ptr<CameraBufferFactory> camera_buffer_factory, BlobifyCallback blobify_callback, scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner, - CameraAppDeviceImpl* camera_app_device, - ClientType client_type); + CameraAppDeviceImpl* camera_app_device); ~RequestManager() override; // Sets up the stream context and allocate buffers according to the // configuration specified in |streams|. void SetUpStreamsAndBuffers( - VideoCaptureFormat capture_format, + base::flat_map<ClientType, VideoCaptureParams> capture_params, const cros::mojom::CameraMetadataPtr& static_metadata, std::vector<cros::mojom::Camera3StreamPtr> streams); @@ -227,6 +227,8 @@ cros::mojom::CameraMetadataPtr* settings, TakePhotoCallback* callback); + bool TryPrepareRecordingRequest(std::set<StreamType>* stream_types); + // Callback for ProcessCaptureRequest(). void OnProcessedCaptureRequest(int32_t result); @@ -257,8 +259,9 @@ void SubmitCaptureResult(uint32_t frame_number, StreamType stream_type, cros::mojom::Camera3StreamBufferPtr stream_buffer); - void SubmitCapturedPreviewBuffer(uint32_t frame_number, - uint64_t buffer_ipc_id); + void SubmitCapturedPreviewRecordingBuffer(uint32_t frame_number, + uint64_t buffer_ipc_id, + StreamType stream_type); void SubmitCapturedJpegBuffer(uint32_t frame_number, uint64_t buffer_ipc_id); // If there are some metadata set by SetCaptureMetadata() or @@ -364,8 +367,6 @@ CameraAppDeviceImpl* camera_app_device_; // Weak. - ClientType client_type_; - base::WeakPtrFactory<RequestManager> weak_ptr_factory_{this}; DISALLOW_IMPLICIT_CONSTRUCTORS(RequestManager);
diff --git a/media/capture/video/chromeos/request_manager_unittest.cc b/media/capture/video/chromeos/request_manager_unittest.cc index 6227b6f3..429769a 100644 --- a/media/capture/video/chromeos/request_manager_unittest.cc +++ b/media/capture/video/chromeos/request_manager_unittest.cc
@@ -87,6 +87,9 @@ void SetUp() override { quit_ = false; client_type_ = ClientType::kPreviewClient; + VideoCaptureParams params; + params.requested_format = kDefaultCaptureFormat; + capture_params_[client_type_] = params; device_context_ = std::make_unique<CameraDeviceContext>(); if (device_context_->AddClient( client_type_, @@ -100,7 +103,7 @@ [](const uint8_t* buffer, const uint32_t bytesused, const VideoCaptureFormat& capture_format, const int rotation) { return mojom::Blob::New(); }), - base::ThreadTaskRunnerHandle::Get(), nullptr, client_type_); + base::ThreadTaskRunnerHandle::Get(), nullptr); } } @@ -284,6 +287,7 @@ mojo::Remote<cros::mojom::Camera3CallbackOps> mock_callback_ops_; std::unique_ptr<CameraDeviceContext> device_context_; ClientType client_type_; + base::flat_map<ClientType, VideoCaptureParams> capture_params_; private: std::unique_ptr<base::RunLoop> run_loop_; @@ -300,8 +304,7 @@ .WillRepeatedly(Invoke(this, &RequestManagerTest::ProcessCaptureRequest)); request_manager_->SetUpStreamsAndBuffers( - kDefaultCaptureFormat, - GetFakeStaticMetadata(/* partial_result_count */ 1), + capture_params_, GetFakeStaticMetadata(/* partial_result_count */ 1), PrepareCaptureStream(/* max_buffers */ 1)); request_manager_->StartPreview(cros::mojom::CameraMetadata::New()); @@ -343,8 +346,7 @@ })); request_manager_->SetUpStreamsAndBuffers( - kDefaultCaptureFormat, - GetFakeStaticMetadata(/* partial_result_count */ 3), + capture_params_, GetFakeStaticMetadata(/* partial_result_count */ 3), PrepareCaptureStream(/* max_buffers */ 1)); request_manager_->StartPreview(cros::mojom::CameraMetadata::New()); @@ -375,8 +377,7 @@ })); request_manager_->SetUpStreamsAndBuffers( - kDefaultCaptureFormat, - GetFakeStaticMetadata(/* partial_result_count */ 1), + capture_params_, GetFakeStaticMetadata(/* partial_result_count */ 1), PrepareCaptureStream(/* max_buffers */ 1)); request_manager_->StartPreview(cros::mojom::CameraMetadata::New()); @@ -415,8 +416,7 @@ .WillRepeatedly(Invoke(this, &RequestManagerTest::ProcessCaptureRequest)); request_manager_->SetUpStreamsAndBuffers( - kDefaultCaptureFormat, - GetFakeStaticMetadata(/* partial_result_count */ 1), + capture_params_, GetFakeStaticMetadata(/* partial_result_count */ 1), PrepareCaptureStream(/* max_buffers */ 1)); request_manager_->StartPreview(cros::mojom::CameraMetadata::New()); @@ -456,8 +456,7 @@ .WillRepeatedly(Invoke(this, &RequestManagerTest::ProcessCaptureRequest)); request_manager_->SetUpStreamsAndBuffers( - kDefaultCaptureFormat, - GetFakeStaticMetadata(/* partial_result_count */ 2), + capture_params_, GetFakeStaticMetadata(/* partial_result_count */ 2), PrepareCaptureStream(/* max_buffers */ 1)); request_manager_->StartPreview(cros::mojom::CameraMetadata::New()); @@ -499,8 +498,7 @@ .WillRepeatedly(Invoke(this, &RequestManagerTest::ProcessCaptureRequest)); request_manager_->SetUpStreamsAndBuffers( - kDefaultCaptureFormat, - GetFakeStaticMetadata(/* partial_result_count */ 1), + capture_params_, GetFakeStaticMetadata(/* partial_result_count */ 1), PrepareCaptureStream(/* max_buffers */ 1)); request_manager_->StartPreview(cros::mojom::CameraMetadata::New());
diff --git a/media/capture/video/chromeos/stream_buffer_manager.cc b/media/capture/video/chromeos/stream_buffer_manager.cc index 611d054..471b1bb 100644 --- a/media/capture/video/chromeos/stream_buffer_manager.cc +++ b/media/capture/video/chromeos/stream_buffer_manager.cc
@@ -27,12 +27,10 @@ StreamBufferManager::StreamBufferManager( CameraDeviceContext* device_context, bool video_capture_use_gmb, - std::unique_ptr<CameraBufferFactory> camera_buffer_factory, - ClientType client_type) + std::unique_ptr<CameraBufferFactory> camera_buffer_factory) : device_context_(device_context), video_capture_use_gmb_(video_capture_use_gmb), - camera_buffer_factory_(std::move(camera_buffer_factory)), - client_type_(client_type) { + camera_buffer_factory_(std::move(camera_buffer_factory)) { if (video_capture_use_gmb_) { gmb_support_ = std::make_unique<gpu::GpuMemoryBufferSupport>(); } @@ -155,8 +153,9 @@ } else { // We have to reserve a new buffer because the size is different. Buffer rotated_buffer; + auto client_type = kStreamClientTypeMap[static_cast<int>(stream_type)]; if (!device_context_->ReserveVideoCaptureBufferFromPool( - client_type_, format->frame_size, format->pixel_format, + client_type, format->frame_size, format->pixel_format, &rotated_buffer)) { DLOG(WARNING) << "Failed to reserve video capture buffer"; original_gmb->Unmap(); @@ -221,7 +220,7 @@ } void StreamBufferManager::SetUpStreamsAndBuffers( - VideoCaptureFormat capture_format, + base::flat_map<ClientType, VideoCaptureParams> capture_params, const cros::mojom::CameraMetadataPtr& static_metadata, std::vector<cros::mojom::Camera3StreamPtr> streams) { DestroyCurrentStreamsAndBuffers(); @@ -249,11 +248,14 @@ // flags of the stream. StreamType stream_type = StreamIdToStreamType(stream->id); auto stream_context = std::make_unique<StreamContext>(); - stream_context->capture_format = capture_format; + auto client_type = kStreamClientTypeMap[static_cast<int>(stream_type)]; + stream_context->capture_format = + capture_params[client_type].requested_format; stream_context->stream = std::move(stream); switch (stream_type) { case StreamType::kPreviewOutput: + case StreamType::kRecordingOutput: stream_context->buffer_dimension = gfx::Size( stream_context->stream->width, stream_context->stream->height); stream_context->buffer_usage = @@ -378,6 +380,11 @@ return stream_context_.find(StreamType::kYUVOutput) != stream_context_.end(); } +bool StreamBufferManager::IsRecordingSupported() { + return stream_context_.find(StreamType::kRecordingOutput) != + stream_context_.end(); +} + // static uint64_t StreamBufferManager::GetBufferIpcId(StreamType stream_type, int key) { uint64_t id = 0; @@ -441,8 +448,9 @@ return; } Buffer vcd_buffer; + auto client_type = kStreamClientTypeMap[static_cast<int>(stream_type)]; if (!device_context_->ReserveVideoCaptureBufferFromPool( - client_type_, stream_context->buffer_dimension, + client_type, stream_context->buffer_dimension, stream_context->capture_format.pixel_format, &vcd_buffer)) { DLOG(WARNING) << "Failed to reserve video capture buffer"; return;
diff --git a/media/capture/video/chromeos/stream_buffer_manager.h b/media/capture/video/chromeos/stream_buffer_manager.h index 50ed6a3..ba62fbe 100644 --- a/media/capture/video/chromeos/stream_buffer_manager.h +++ b/media/capture/video/chromeos/stream_buffer_manager.h
@@ -14,6 +14,7 @@ #include <unordered_map> #include <vector> +#include "base/containers/flat_map.h" #include "base/containers/queue.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" @@ -51,8 +52,7 @@ StreamBufferManager( CameraDeviceContext* device_context, bool video_capture_use_gmb, - std::unique_ptr<CameraBufferFactory> camera_buffer_factory, - ClientType client_type); + std::unique_ptr<CameraBufferFactory> camera_buffer_factory); ~StreamBufferManager(); void ReserveBuffer(StreamType stream_type); @@ -84,7 +84,7 @@ // Sets up the stream context and allocate buffers according to the // configuration specified in |stream|. void SetUpStreamsAndBuffers( - VideoCaptureFormat capture_format, + base::flat_map<ClientType, VideoCaptureParams> capture_params, const cros::mojom::CameraMetadataPtr& static_metadata, std::vector<cros::mojom::Camera3StreamPtr> streams); @@ -105,6 +105,8 @@ bool IsReprocessSupported(); + bool IsRecordingSupported(); + private: friend class RequestManagerTest; @@ -164,8 +166,6 @@ std::unique_ptr<CameraBufferFactory> camera_buffer_factory_; - ClientType client_type_; - base::WeakPtrFactory<StreamBufferManager> weak_ptr_factory_{this}; DISALLOW_IMPLICIT_CONSTRUCTORS(StreamBufferManager);
diff --git a/media/capture/video/chromeos/vendor_tag_ops_delegate.cc b/media/capture/video/chromeos/vendor_tag_ops_delegate.cc index 2ce163e..013b267 100644 --- a/media/capture/video/chromeos/vendor_tag_ops_delegate.cc +++ b/media/capture/video/chromeos/vendor_tag_ops_delegate.cc
@@ -13,7 +13,7 @@ VendorTagOpsDelegate::VendorTagOpsDelegate( scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner) - : ipc_task_runner_(ipc_task_runner) {} + : ipc_task_runner_(ipc_task_runner), is_initializing_(false) {} VendorTagOpsDelegate::~VendorTagOpsDelegate() = default; @@ -28,17 +28,29 @@ void VendorTagOpsDelegate::Initialize() { DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence()); + + base::AutoLock lock(lock_); + is_initializing_ = true; vendor_tag_ops_->GetTagCount(base::BindOnce( &VendorTagOpsDelegate::OnGotTagCount, base::Unretained(this))); } void VendorTagOpsDelegate::Reset() { DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence()); + + base::AutoLock lock(lock_); vendor_tag_ops_.reset(); pending_info_.clear(); name_map_.clear(); tag_map_.clear(); initialized_.Reset(); + is_initializing_ = false; +} + +void VendorTagOpsDelegate::StopInitialization() { + base::AutoLock lock(lock_); + initialized_.Signal(); + is_initializing_ = false; } void VendorTagOpsDelegate::RemovePending(uint32_t tag) { @@ -47,7 +59,7 @@ DCHECK_EQ(removed, 1u); if (pending_info_.empty()) { DVLOG(1) << "VendorTagOpsDelegate initialized"; - initialized_.Signal(); + StopInitialization(); } } @@ -55,13 +67,13 @@ DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence()); if (tag_count == -1) { LOG(ERROR) << "Failed to get tag count"; - initialized_.Signal(); + StopInitialization(); return; } if (tag_count == 0) { // There is no vendor tag, we are done here. - initialized_.Signal(); + StopInitialization(); return; } @@ -134,6 +146,13 @@ const VendorTagInfo* VendorTagOpsDelegate::GetInfoByName( const std::string& full_name) { + { + base::AutoLock lock(lock_); + if (!is_initializing_ && !initialized_.IsSignaled()) { + LOG(WARNING) << "VendorTagOps is accessed before calling Initialize()"; + return nullptr; + } + } initialized_.Wait(); auto it = name_map_.find(full_name); if (it == name_map_.end()) { @@ -144,6 +163,13 @@ const VendorTagInfo* VendorTagOpsDelegate::GetInfoByTag( cros::mojom::CameraMetadataTag tag) { + { + base::AutoLock lock(lock_); + if (!is_initializing_ && !initialized_.IsSignaled()) { + LOG(WARNING) << "VendorTagOps is accessed before calling Initialize()"; + return nullptr; + } + } initialized_.Wait(); auto it = tag_map_.find(tag); if (it == tag_map_.end()) {
diff --git a/media/capture/video/chromeos/vendor_tag_ops_delegate.h b/media/capture/video/chromeos/vendor_tag_ops_delegate.h index 206394f..cd963e0 100644 --- a/media/capture/video/chromeos/vendor_tag_ops_delegate.h +++ b/media/capture/video/chromeos/vendor_tag_ops_delegate.h
@@ -9,6 +9,7 @@ #include <string> #include <vector> +#include "base/synchronization/lock.h" #include "media/capture/video/chromeos/mojom/camera_common.mojom.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/remote.h" @@ -41,6 +42,7 @@ const VendorTagInfo* GetInfoByTag(cros::mojom::CameraMetadataTag tag); private: + void StopInitialization(); void RemovePending(uint32_t tag); void OnGotTagCount(int32_t tag_count); @@ -63,6 +65,9 @@ std::map<cros::mojom::CameraMetadataTag, VendorTagInfo> tag_map_; base::WaitableEvent initialized_; + + base::Lock lock_; + bool is_initializing_ GUARDED_BY(lock_); }; } // namespace media
diff --git a/media/capture/video/chromeos/video_capture_device_chromeos_delegate.cc b/media/capture/video/chromeos/video_capture_device_chromeos_delegate.cc index b8b8a3b..9d5ef8da 100644 --- a/media/capture/video/chromeos/video_capture_device_chromeos_delegate.cc +++ b/media/capture/video/chromeos/video_capture_device_chromeos_delegate.cc
@@ -123,60 +123,76 @@ camera_app_device_(camera_app_device), cleanup_callback_(std::move(cleanup_callback)), power_manager_client_proxy_( - base::MakeRefCounted<PowerManagerClientProxy>()), - client_type_(ClientType::kPreviewClient) { + base::MakeRefCounted<PowerManagerClientProxy>()) { power_manager_client_proxy_->Init(weak_ptr_factory_.GetWeakPtr(), capture_task_runner_, std::move(ui_task_runner)); } -VideoCaptureDeviceChromeOSDelegate::~VideoCaptureDeviceChromeOSDelegate() { +VideoCaptureDeviceChromeOSDelegate::~VideoCaptureDeviceChromeOSDelegate() {} + +void VideoCaptureDeviceChromeOSDelegate::Shutdown() { DCHECK(capture_task_runner_->BelongsToCurrentThread()); - DCHECK(!camera_device_ipc_thread_.IsRunning()); - screen_observer_delegate_->RemoveObserver(); - power_manager_client_proxy_->Shutdown(); - std::move(cleanup_callback_).Run(); + if (!HasDeviceClient()) { + DCHECK(!camera_device_ipc_thread_.IsRunning()); + screen_observer_delegate_->RemoveObserver(); + power_manager_client_proxy_->Shutdown(); + std::move(cleanup_callback_).Run(); + } } -// VideoCaptureDevice implementation. +bool VideoCaptureDeviceChromeOSDelegate::HasDeviceClient() { + return device_context_ && device_context_->HasClient(); +} + void VideoCaptureDeviceChromeOSDelegate::AllocateAndStart( const VideoCaptureParams& params, - std::unique_ptr<Client> client) { + std::unique_ptr<VideoCaptureDevice::Client> client, + ClientType client_type) { DCHECK(capture_task_runner_->BelongsToCurrentThread()); DCHECK(!camera_device_delegate_); - TRACE_EVENT0("camera", "Start Device"); - if (!camera_device_ipc_thread_.Start()) { - std::string error_msg = "Failed to start device thread"; - LOG(ERROR) << error_msg; - client->OnError( - media::VideoCaptureError::kCrosHalV3FailedToStartDeviceThread, - FROM_HERE, error_msg); - return; - } - capture_params_ = params; - device_context_ = std::make_unique<CameraDeviceContext>(); - if (device_context_->AddClient(client_type_, std::move(client))) { - camera_device_delegate_ = std::make_unique<CameraDeviceDelegate>( - device_descriptor_, camera_hal_delegate_, - camera_device_ipc_thread_.task_runner(), camera_app_device_, - client_type_); - OpenDevice(); + if (!HasDeviceClient()) { + TRACE_EVENT0("camera", "Start Device"); + if (!camera_device_ipc_thread_.Start()) { + std::string error_msg = "Failed to start device thread"; + LOG(ERROR) << error_msg; + client->OnError( + media::VideoCaptureError::kCrosHalV3FailedToStartDeviceThread, + FROM_HERE, error_msg); + return; + } + + device_context_ = std::make_unique<CameraDeviceContext>(); + if (device_context_->AddClient(client_type, std::move(client))) { + capture_params_[client_type] = params; + camera_device_delegate_ = std::make_unique<CameraDeviceDelegate>( + device_descriptor_, camera_hal_delegate_, + camera_device_ipc_thread_.task_runner(), camera_app_device_); + OpenDevice(); + } + } else { + if (device_context_->AddClient(client_type, std::move(client))) { + capture_params_[client_type] = params; + ReconfigureStreams(); + } } } -void VideoCaptureDeviceChromeOSDelegate::StopAndDeAllocate() { +void VideoCaptureDeviceChromeOSDelegate::StopAndDeAllocate( + ClientType client_type) { DCHECK(capture_task_runner_->BelongsToCurrentThread()); - if (!camera_device_delegate_) { - return; + DCHECK(!camera_device_delegate_); + device_context_->RemoveClient(client_type); + if (!HasDeviceClient()) { + CloseDevice(base::UnguessableToken()); + camera_device_ipc_thread_.Stop(); + camera_device_delegate_.reset(); + device_context_.reset(); } - CloseDevice(base::UnguessableToken()); - camera_device_ipc_thread_.Stop(); - camera_device_delegate_.reset(); - device_context_->RemoveClient(client_type_); - device_context_.reset(); } -void VideoCaptureDeviceChromeOSDelegate::TakePhoto(TakePhotoCallback callback) { +void VideoCaptureDeviceChromeOSDelegate::TakePhoto( + VideoCaptureDevice::TakePhotoCallback callback) { DCHECK(capture_task_runner_->BelongsToCurrentThread()); DCHECK(camera_device_delegate_); camera_device_ipc_thread_.task_runner()->PostTask( @@ -186,7 +202,7 @@ } void VideoCaptureDeviceChromeOSDelegate::GetPhotoState( - GetPhotoStateCallback callback) { + VideoCaptureDevice::GetPhotoStateCallback callback) { DCHECK(capture_task_runner_->BelongsToCurrentThread()); camera_device_ipc_thread_.task_runner()->PostTask( FROM_HERE, base::BindOnce(&CameraDeviceDelegate::GetPhotoState, @@ -196,7 +212,7 @@ void VideoCaptureDeviceChromeOSDelegate::SetPhotoOptions( mojom::PhotoSettingsPtr settings, - SetPhotoOptionsCallback callback) { + VideoCaptureDevice::SetPhotoOptionsCallback callback) { DCHECK(capture_task_runner_->BelongsToCurrentThread()); camera_device_ipc_thread_.task_runner()->PostTask( FROM_HERE, base::BindOnce(&CameraDeviceDelegate::SetPhotoOptions, @@ -224,6 +240,20 @@ camera_device_delegate_->GetWeakPtr(), rotation_)); } +void VideoCaptureDeviceChromeOSDelegate::ReconfigureStreams() { + DCHECK(capture_task_runner_->BelongsToCurrentThread()); + DCHECK(camera_device_delegate_); + + camera_device_ipc_thread_.task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&CameraDeviceDelegate::ReconfigureStreams, + camera_device_delegate_->GetWeakPtr(), capture_params_)); + camera_device_ipc_thread_.task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&CameraDeviceDelegate::SetRotation, + camera_device_delegate_->GetWeakPtr(), rotation_)); +} + void VideoCaptureDeviceChromeOSDelegate::CloseDevice( base::UnguessableToken unblock_suspend_token) { DCHECK(capture_task_runner_->BelongsToCurrentThread());
diff --git a/media/capture/video/chromeos/video_capture_device_chromeos_delegate.h b/media/capture/video/chromeos/video_capture_device_chromeos_delegate.h index 2b82e40..80aaac3d 100644 --- a/media/capture/video/chromeos/video_capture_device_chromeos_delegate.h +++ b/media/capture/video/chromeos/video_capture_device_chromeos_delegate.h
@@ -7,9 +7,11 @@ #include <memory> +#include "base/containers/flat_map.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" +#include "base/synchronization/lock.h" #include "base/threading/thread.h" #include "media/capture/video/chromeos/camera_device_context.h" #include "media/capture/video/chromeos/display_rotation_observer.h" @@ -29,10 +31,9 @@ class CameraHalDelegate; class CameraDeviceDelegate; -// Implementation of VideoCaptureDevice for ChromeOS with CrOS camera HALv3. +// Implementation of delegate for ChromeOS with CrOS camera HALv3. class CAPTURE_EXPORT VideoCaptureDeviceChromeOSDelegate final - : public VideoCaptureDevice, - public DisplayRotationObserver { + : public DisplayRotationObserver { public: VideoCaptureDeviceChromeOSDelegate( scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, @@ -41,22 +42,25 @@ CameraAppDeviceImpl* camera_app_device, base::OnceClosure cleanup_callback); - ~VideoCaptureDeviceChromeOSDelegate() final; + ~VideoCaptureDeviceChromeOSDelegate(); + void Shutdown(); + bool HasDeviceClient(); - // VideoCaptureDevice implementation. void AllocateAndStart(const VideoCaptureParams& params, - std::unique_ptr<Client> client) final; - void StopAndDeAllocate() final; - void TakePhoto(TakePhotoCallback callback) final; - void GetPhotoState(GetPhotoStateCallback callback) final; + std::unique_ptr<VideoCaptureDevice::Client> client, + ClientType client_type); + void StopAndDeAllocate(ClientType client_type); + void TakePhoto(VideoCaptureDevice::TakePhotoCallback callback); + void GetPhotoState(VideoCaptureDevice::GetPhotoStateCallback callback); void SetPhotoOptions(mojom::PhotoSettingsPtr settings, - SetPhotoOptionsCallback callback) final; + VideoCaptureDevice::SetPhotoOptionsCallback callback); private: // Helper to interact with PowerManagerClient on DBus original thread. class PowerManagerClientProxy; void OpenDevice(); + void ReconfigureStreams(); void CloseDevice(base::UnguessableToken unblock_suspend_token); // DisplayRotationDelegate implementation. @@ -79,7 +83,9 @@ // |capture_task_runner_|. base::Thread camera_device_ipc_thread_; - VideoCaptureParams capture_params_; + // Map client type to VideoCaptureParams. + base::flat_map<ClientType, VideoCaptureParams> capture_params_; + // |device_context_| is created and owned by // VideoCaptureDeviceChromeOSDelegate and is only accessed by // |camera_device_delegate_|. @@ -103,9 +109,6 @@ scoped_refptr<PowerManagerClientProxy> power_manager_client_proxy_; - // The client type in CameraDeviceContext. - ClientType client_type_; - base::WeakPtrFactory<VideoCaptureDeviceChromeOSDelegate> weak_ptr_factory_{ this};
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 34a6eaef..7e24d63a4 100644 --- a/media/capture/video/chromeos/video_capture_device_chromeos_halv3.cc +++ b/media/capture/video/chromeos/video_capture_device_chromeos_halv3.cc
@@ -9,21 +9,22 @@ namespace media { VideoCaptureDeviceChromeOSHalv3::VideoCaptureDeviceChromeOSHalv3( - std::unique_ptr<VideoCaptureDeviceChromeOSDelegate> delegate) - : vcd_delegate_(std::move(delegate)) {} + VideoCaptureDeviceChromeOSDelegate* delegate) + : vcd_delegate_(delegate), client_type_(ClientType::kPreviewClient) {} VideoCaptureDeviceChromeOSHalv3::~VideoCaptureDeviceChromeOSHalv3() { + vcd_delegate_->Shutdown(); } // VideoCaptureDevice implementation. void VideoCaptureDeviceChromeOSHalv3::AllocateAndStart( const VideoCaptureParams& params, std::unique_ptr<Client> client) { - vcd_delegate_->AllocateAndStart(params, std::move(client)); + vcd_delegate_->AllocateAndStart(params, std::move(client), client_type_); } void VideoCaptureDeviceChromeOSHalv3::StopAndDeAllocate() { - vcd_delegate_->StopAndDeAllocate(); + vcd_delegate_->StopAndDeAllocate(client_type_); } void VideoCaptureDeviceChromeOSHalv3::TakePhoto(TakePhotoCallback callback) {
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 b20f76f2..fde6525 100644 --- a/media/capture/video/chromeos/video_capture_device_chromeos_halv3.h +++ b/media/capture/video/chromeos/video_capture_device_chromeos_halv3.h
@@ -7,7 +7,9 @@ #include <memory> +#include "media/capture/video/chromeos/camera_device_context.h" #include "media/capture/video/video_capture_device.h" +#include "media/capture/video/video_capture_device_descriptor.h" namespace media { @@ -18,7 +20,7 @@ : public VideoCaptureDevice { public: explicit VideoCaptureDeviceChromeOSHalv3( - std::unique_ptr<VideoCaptureDeviceChromeOSDelegate> delegate); + VideoCaptureDeviceChromeOSDelegate* delegate); ~VideoCaptureDeviceChromeOSHalv3() final; @@ -32,7 +34,9 @@ SetPhotoOptionsCallback callback) final; private: - std::unique_ptr<VideoCaptureDeviceChromeOSDelegate> vcd_delegate_; + VideoCaptureDeviceChromeOSDelegate* vcd_delegate_; + + ClientType client_type_; DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureDeviceChromeOSHalv3); };
diff --git a/media/gpu/vaapi/vaapi_unittest.cc b/media/gpu/vaapi/vaapi_unittest.cc index 791cbdd0..f4870021 100644 --- a/media/gpu/vaapi/vaapi_unittest.cc +++ b/media/gpu/vaapi/vaapi_unittest.cc
@@ -22,9 +22,11 @@ #include "base/strings/pattern.h" #include "base/strings/string_split.h" #include "base/test/launcher/unit_test_launcher.h" +#include "base/test/scoped_feature_list.h" #include "base/test/test_suite.h" #include "build/chromeos_buildflags.h" #include "gpu/config/gpu_driver_bug_workarounds.h" +#include "media/base/media_switches.h" #include "media/gpu/vaapi/vaapi_wrapper.h" #include "media/media_buildflags.h" @@ -104,12 +106,23 @@ ? base::make_optional<VAEntrypoint>(it->second) : base::nullopt; } + +std::unique_ptr<base::test::ScopedFeatureList> CreateScopedFeatureList() { + auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>(); + scoped_feature_list->InitWithFeatures( + /*enabled_features=*/{media::kVaapiAV1Decoder}, + /*disabled_features=*/{}); + return scoped_feature_list; +} } // namespace class VaapiTest : public testing::Test { public: - VaapiTest() = default; + VaapiTest() : scoped_feature_list_(CreateScopedFeatureList()) {} ~VaapiTest() override = default; + + private: + std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_; }; std::map<VAProfile, std::vector<VAEntrypoint>> ParseVainfo( @@ -334,10 +347,16 @@ int main(int argc, char** argv) { base::TestSuite test_suite(argc, argv); - - // PreSandboxInitialization() loads and opens the driver, queries its - // capabilities and fills in the VASupportedProfiles. - media::VaapiWrapper::PreSandboxInitialization(); + { + // Enables/Disables features during PreSandboxInitialization(). We have to + // destruct ScopedFeatureList after it because base::TestSuite::Run() + // creates a ScopedFeatureList and multiple concurrent ScopedFeatureLists + // are not allowed. + auto scoped_feature_list = media::CreateScopedFeatureList(); + // PreSandboxInitialization() loads and opens the driver, queries its + // capabilities and fills in the VASupportedProfiles. + media::VaapiWrapper::PreSandboxInitialization(); + } return base::LaunchUnitTests( argc, argv,
diff --git a/net/quic/quic_transport_client.h b/net/quic/quic_transport_client.h index eaa79b6..9f873d1 100644 --- a/net/quic/quic_transport_client.h +++ b/net/quic/quic_transport_client.h
@@ -156,6 +156,11 @@ } void OnStopSendingReceived( const quic::QuicStopSendingFrame& /*frame*/) override {} + void OnNewConnectionIdSent( + const quic::QuicConnectionId& /*server_connection_id*/, + const quic::QuicConnectionId& /*new_connecition_id*/) override {} + void OnConnectionIdRetired( + const quic::QuicConnectionId& /*server_connection_id*/) override {} private: // State of the connection establishment process.
diff --git a/services/device/time_zone_monitor/time_zone_monitor_win.cc b/services/device/time_zone_monitor/time_zone_monitor_win.cc index 4bcdc5f5d..bbe92ad 100644 --- a/services/device/time_zone_monitor/time_zone_monitor_win.cc +++ b/services/device/time_zone_monitor/time_zone_monitor_win.cc
@@ -12,6 +12,7 @@ #include "base/callback_helpers.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "base/strings/utf_string_conversions.h" #include "base/trace_event/trace_event.h" #include "third_party/icu/source/i18n/unicode/timezone.h" #include "ui/gfx/win/singleton_hwnd_observer.h" @@ -24,7 +25,8 @@ : TimeZoneMonitor(), singleton_hwnd_observer_(new gfx::SingletonHwndObserver( base::BindRepeating(&TimeZoneMonitorWin::OnWndProc, - base::Unretained(this)))) {} + base::Unretained(this)))), + current_platform_timezone_(GetPlatformTimeZone()) {} TimeZoneMonitorWin(const TimeZoneMonitorWin&) = delete; TimeZoneMonitorWin& operator=(const TimeZoneMonitorWin&) = delete; @@ -52,14 +54,39 @@ } } + // Returns the platform specific string for the time zone. Do not rely on the + // ICU library since it's taking into account other sources for time zone like + // the TZ environment. This avoid loading the ICU library if not required. + std::string GetPlatformTimeZone() { + std::string timezone; + TIME_ZONE_INFORMATION time_zone_information; + if (::GetTimeZoneInformation(&time_zone_information)) { + // StandardName field may be empty. + timezone = base::WideToUTF8(time_zone_information.StandardName); + } + return timezone; + } + void OnWmTimechangeReceived() { TRACE_EVENT0("device", "TimeZoneMonitorWin::OnTimechangeReceived"); - UpdateIcuAndNotifyClients(DetectHostTimeZoneFromIcu()); + + // Only dispatch time zone notifications when the platform time zone has + // changed. Windows API is sending WM_TIMECHANGE messages each time a + // time property has changed which is common during a power suspend/resume + // transition even if the time zone stayed the same. As a good example, any + // NTP update may trigger a WM_TIMECHANGE message. + const std::string timezone = GetPlatformTimeZone(); + if (timezone.empty() || current_platform_timezone_ != timezone) { + UpdateIcuAndNotifyClients(DetectHostTimeZoneFromIcu()); + current_platform_timezone_ = timezone; + } + pending_update_notification_tasks_ = false; } std::unique_ptr<gfx::SingletonHwndObserver> singleton_hwnd_observer_; bool pending_update_notification_tasks_ = false; + std::string current_platform_timezone_; base::WeakPtrFactory<TimeZoneMonitorWin> weak_ptr_factory_{this}; };
diff --git a/services/network/url_loader_factory.cc b/services/network/url_loader_factory.cc index df541bd..9d75573 100644 --- a/services/network/url_loader_factory.cc +++ b/services/network/url_loader_factory.cc
@@ -278,7 +278,7 @@ DCHECK(url_request.web_bundle_token_params.has_value()); base::WeakPtr<WebBundleURLLoaderFactory> web_bundle_url_loader_factory = context_->GetWebBundleManager().CreateWebBundleURLLoaderFactory( - url_request.url, *url_request.web_bundle_token_params); + url_request.url, *url_request.web_bundle_token_params, params_); client = web_bundle_url_loader_factory->WrapURLLoaderClient(std::move(client)); }
diff --git a/services/network/web_bundle_manager.cc b/services/network/web_bundle_manager.cc index d980753..3538c889 100644 --- a/services/network/web_bundle_manager.cc +++ b/services/network/web_bundle_manager.cc
@@ -6,6 +6,7 @@ #include "base/bind.h" #include "mojo/public/cpp/bindings/remote.h" +#include "services/network/network_context.h" #include "services/network/public/mojom/web_bundle_handle.mojom.h" #include "services/network/web_bundle_url_loader_factory.h" @@ -18,7 +19,8 @@ base::WeakPtr<WebBundleURLLoaderFactory> WebBundleManager::CreateWebBundleURLLoaderFactory( const GURL& bundle_url, - const ResourceRequest::WebBundleTokenParams& web_bundle_token_params) { + const ResourceRequest::WebBundleTokenParams& web_bundle_token_params, + const mojom::URLLoaderFactoryParamsPtr& factory_params) { DCHECK(factories_.find(web_bundle_token_params.token) == factories_.end()); mojo::Remote<mojom::WebBundleHandle> remote( @@ -32,8 +34,9 @@ // |this| outlives |remote|. base::Unretained(this), web_bundle_token_params.token)); - auto factory = std::make_unique<WebBundleURLLoaderFactory>(bundle_url, - std::move(remote)); + auto factory = std::make_unique<WebBundleURLLoaderFactory>( + bundle_url, std::move(remote), + factory_params->request_initiator_origin_lock); auto weak_factory = factory->GetWeakPtr(); factories_.insert({web_bundle_token_params.token, std::move(factory)});
diff --git a/services/network/web_bundle_manager.h b/services/network/web_bundle_manager.h index 02b14a9..50e7320 100644 --- a/services/network/web_bundle_manager.h +++ b/services/network/web_bundle_manager.h
@@ -11,6 +11,7 @@ #include "base/memory/weak_ptr.h" #include "base/unguessable_token.h" #include "services/network/public/cpp/resource_request.h" +#include "services/network/public/mojom/network_context.mojom-forward.h" namespace network { @@ -28,7 +29,8 @@ base::WeakPtr<WebBundleURLLoaderFactory> CreateWebBundleURLLoaderFactory( const GURL& bundle_url, - const ResourceRequest::WebBundleTokenParams& params); + const ResourceRequest::WebBundleTokenParams& params, + const mojom::URLLoaderFactoryParamsPtr& factory_params); base::WeakPtr<WebBundleURLLoaderFactory> GetWebBundleURLLoaderFactory( const base::UnguessableToken& token);
diff --git a/services/network/web_bundle_manager_unittest.cc b/services/network/web_bundle_manager_unittest.cc index 0eb18bcb..af804aea 100644 --- a/services/network/web_bundle_manager_unittest.cc +++ b/services/network/web_bundle_manager_unittest.cc
@@ -7,6 +7,7 @@ #include "base/test/task_environment.h" #include "base/unguessable_token.h" #include "services/network/public/cpp/resource_request.h" +#include "services/network/public/mojom/network_context.mojom.h" #include "services/network/public/mojom/web_bundle_handle.mojom.h" #include "testing/gtest/include/gtest/gtest.h" @@ -37,8 +38,8 @@ auto token_params = ResourceRequest::WebBundleTokenParams(token, std::move(handle)); - auto factory = - manager.CreateWebBundleURLLoaderFactory(GURL(kBundleUrl), token_params); + auto factory = manager.CreateWebBundleURLLoaderFactory( + GURL(kBundleUrl), token_params, mojom::URLLoaderFactoryParams::New()); ASSERT_TRUE(factory); ASSERT_TRUE(manager.GetWebBundleURLLoaderFactory(token)); // Getting out of scope to delete |receiver|.
diff --git a/services/network/web_bundle_url_loader_factory.cc b/services/network/web_bundle_url_loader_factory.cc index 941d1eb..caf2cb4 100644 --- a/services/network/web_bundle_url_loader_factory.cc +++ b/services/network/web_bundle_url_loader_factory.cc
@@ -4,6 +4,7 @@ #include "services/network/web_bundle_url_loader_factory.h" +#include "base/optional.h" #include "components/web_package/web_bundle_parser.h" #include "components/web_package/web_bundle_utils.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" @@ -11,6 +12,7 @@ #include "mojo/public/cpp/system/data_pipe_drainer.h" #include "mojo/public/cpp/system/data_pipe_producer.h" #include "net/http/http_status_code.h" +#include "services/network/public/cpp/cross_origin_read_blocking.h" namespace network { @@ -128,8 +130,12 @@ public: URLLoader(mojo::PendingReceiver<mojom::URLLoader> loader, const ResourceRequest& request, - mojo::PendingRemote<mojom::URLLoaderClient> client) + mojo::PendingRemote<mojom::URLLoaderClient> client, + const base::Optional<url::Origin>& request_initiator_origin_lock) : url_(request.url), + request_mode_(request.mode), + request_initiator_(request.request_initiator), + request_initiator_origin_lock_(request_initiator_origin_lock), receiver_(this, std::move(loader)), client_(std::move(client)) { receiver_.set_disconnect_handler( @@ -139,6 +145,15 @@ URLLoader& operator=(const URLLoader&) = delete; const GURL& url() const { return url_; } + const mojom::RequestMode& request_mode() const { return request_mode_; } + + const base::Optional<url::Origin>& request_initiator() const { + return request_initiator_; + } + + const base::Optional<url::Origin>& request_initiator_origin_lock() const { + return request_initiator_origin_lock_; + } base::WeakPtr<URLLoader> GetWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); @@ -164,6 +179,39 @@ delete this; } + void BlockResponseForCorb(mojom::URLResponseHeadPtr response_head) { + // A minimum implementation to block CORB-protected resources. + // + // TODO(crbug.com/1082020): Re-use + // network::URLLoader::BlockResponseForCorb(), instead of copying + // essential parts from there, so that the two implementations won't + // diverge further. That requires non-trivial refactoring. + CrossOriginReadBlocking::SanitizeBlockedResponse(response_head.get()); + client_->OnReceiveResponse(std::move(response_head)); + + // Send empty body to the URLLoaderClient. + mojo::ScopedDataPipeProducerHandle producer; + mojo::ScopedDataPipeConsumerHandle consumer; + if (CreateDataPipe(nullptr, &producer, &consumer) != MOJO_RESULT_OK) { + OnFail(net::ERR_INSUFFICIENT_RESOURCES); + return; + } + producer.reset(); + client_->OnStartLoadingResponseBody(std::move(consumer)); + + URLLoaderCompletionStatus status; + status.error_code = net::OK; + status.completion_time = base::TimeTicks::Now(); + status.encoded_data_length = 0; + status.encoded_body_length = 0; + status.decoded_body_length = 0; + client_->OnComplete(status); + + // Reset the connection to the URLLoaderClient. This helps ensure that we + // won't accidentally leak any data to the renderer from this point on. + client_.reset(); + } + private: // mojom::URLLoader void FollowRedirect( @@ -185,6 +233,15 @@ void OnMojoDisconnect() { delete this; } const GURL url_; + mojom::RequestMode request_mode_; + base::Optional<url::Origin> request_initiator_; + // It is safe to hold |request_initiator_origin_lock_| in this factory because + // 1). |request_initiator_origin_lock| is a property of |URLLoaderFactory| + // (or, more accurately a property of |URLLoaderFactoryParams|), and + // 2) |WebURLLoader| is always associated with the same URLLoaderFactory + // (via URLLoaderFactory -> WebBundleManager -> WebBundleURLLoaderFactory + // -> WebBundleURLLoader). + const base::Optional<url::Origin> request_initiator_origin_lock_; mojo::Receiver<mojom::URLLoader> receiver_; mojo::Remote<mojom::URLLoaderClient> client_; base::WeakPtrFactory<URLLoader> weak_ptr_factory_{this}; @@ -317,9 +374,11 @@ WebBundleURLLoaderFactory::WebBundleURLLoaderFactory( const GURL& bundle_url, - mojo::Remote<mojom::WebBundleHandle> web_bundle_handle) + mojo::Remote<mojom::WebBundleHandle> web_bundle_handle, + const base::Optional<url::Origin>& request_initiator_origin_lock) : bundle_url_(bundle_url), - web_bundle_handle_(std::move(web_bundle_handle)) {} + web_bundle_handle_(std::move(web_bundle_handle)), + request_initiator_origin_lock_(request_initiator_origin_lock) {} WebBundleURLLoaderFactory::~WebBundleURLLoaderFactory() { for (auto loader : pending_loaders_) { @@ -368,7 +427,8 @@ const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) { TRACE_EVENT0("loading", "WebBundleURLLoaderFactory::CreateLoaderAndStart"); URLLoader* loader = - new URLLoader(std::move(receiver), url_request, std::move(client)); + new URLLoader(std::move(receiver), url_request, std::move(client), + request_initiator_origin_lock_); if (metadata_error_) { loader->OnFail(net::ERR_INVALID_WEB_BUNDLE); return; @@ -459,6 +519,21 @@ mojom::URLResponseHeadPtr response_head = web_package::CreateResourceResponse(response); response_head->web_bundle_url = bundle_url_; + // Add an artifical "X-Content-Type-Options: "nosniff" header, which is + // explained at + // https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#name-responses. + response_head->headers->SetHeader("X-Content-Type-Options", "nosniff"); + + auto corb_analyzer = + std::make_unique<CrossOriginReadBlocking::ResponseAnalyzer>( + loader->url(), loader->request_initiator(), *response_head, + loader->request_initiator_origin_lock(), loader->request_mode()); + + if (corb_analyzer->ShouldBlock()) { + loader->BlockResponseForCorb(std::move(response_head)); + return; + } + loader->OnResponse(std::move(response_head)); mojo::ScopedDataPipeProducerHandle producer;
diff --git a/services/network/web_bundle_url_loader_factory.h b/services/network/web_bundle_url_loader_factory.h index 8c22c08c..12de0a2d 100644 --- a/services/network/web_bundle_url_loader_factory.h +++ b/services/network/web_bundle_url_loader_factory.h
@@ -20,7 +20,8 @@ public: WebBundleURLLoaderFactory( const GURL& bundle_url, - mojo::Remote<mojom::WebBundleHandle> web_bundle_handle); + mojo::Remote<mojom::WebBundleHandle> web_bundle_handle, + const base::Optional<url::Origin>& request_initiator_origin_lock); ~WebBundleURLLoaderFactory() override; WebBundleURLLoaderFactory(const WebBundleURLLoaderFactory&) = delete; WebBundleURLLoaderFactory& operator=(const WebBundleURLLoaderFactory&) = @@ -57,6 +58,7 @@ GURL bundle_url_; mojo::Remote<mojom::WebBundleHandle> web_bundle_handle_; + const base::Optional<::url::Origin> request_initiator_origin_lock_; std::unique_ptr<BundleDataSource> source_; mojo::Remote<web_package::mojom::WebBundleParser> parser_; web_package::mojom::BundleMetadataPtr metadata_;
diff --git a/services/network/web_bundle_url_loader_factory_unittest.cc b/services/network/web_bundle_url_loader_factory_unittest.cc index 7a21b96..5da2855 100644 --- a/services/network/web_bundle_url_loader_factory_unittest.cc +++ b/services/network/web_bundle_url_loader_factory_unittest.cc
@@ -18,11 +18,16 @@ namespace { +const char kInitiatorUrl[] = "https://example.com/"; const char kBundleUrl[] = "https://example.com/bundle.wbn"; const char kResourceUrl[] = "https://example.com/"; const char kResourceUrl2[] = "https://example.com/another"; const char kResourceUrl3[] = "https://example.com/yetanother"; +// Cross origin resources +const char kCrossOriginJsonUrl[] = "https://other.com/resource.json"; +const char kCrossOriginJsUrl[] = "https://other.com/resource.js"; + std::vector<uint8_t> CreateSmallBundle() { web_package::test::WebBundleBuilder builder(kResourceUrl, "" /* manifest_url */); @@ -47,6 +52,19 @@ return builder.CreateBundle(); } +std::vector<uint8_t> CreateCrossOriginBundle() { + web_package::test::WebBundleBuilder builder(kCrossOriginJsonUrl, + "" /* manifest_url */); + builder.AddExchange( + kCrossOriginJsonUrl, + {{":status", "200"}, {"content-type", "application/json"}}, + "{ secret: 1 }"); + builder.AddExchange(kCrossOriginJsUrl, + {{":status", "200"}, {"content-type", "application/js"}}, + "const not_secret = 1;"); + return builder.CreateBundle(); +} + class TestWebBundleHandle : public mojom::WebBundleHandle { public: explicit TestWebBundleHandle( @@ -96,8 +114,8 @@ mojo::Remote<mojom::WebBundleHandle> handle; handle_ = std::make_unique<TestWebBundleHandle>( handle.BindNewPipeAndPassReceiver()); - factory_ = std::make_unique<WebBundleURLLoaderFactory>(GURL(kBundleUrl), - std::move(handle)); + factory_ = std::make_unique<WebBundleURLLoaderFactory>( + GURL(kBundleUrl), std::move(handle), base::nullopt); factory_->SetBundleStream(std::move(consumer)); } @@ -118,6 +136,8 @@ network::ResourceRequest request; request.url = url; request.method = "GET"; + request.request_initiator = url::Origin::Create(GURL(kInitiatorUrl)); + StartRequestResult result; result.client = std::make_unique<network::TestURLLoaderClient>(); factory_->CreateLoaderAndStart( @@ -340,4 +360,36 @@ EXPECT_EQ(last_bundle_error()->second, "Error reading response header."); } +TEST_F(WebBundleURLLoaderFactoryTest, CrossOiginJson) { + WriteBundle(CreateCrossOriginBundle()); + FinishWritingBundle(); + + auto request = StartRequest(GURL(kCrossOriginJsonUrl)); + request.client->RunUntilComplete(); + + EXPECT_EQ(net::OK, request.client->completion_status().error_code); + EXPECT_FALSE(last_bundle_error().has_value()); + std::string body; + ASSERT_TRUE(mojo::BlockingCopyToString( + request.client->response_body_release(), &body)); + EXPECT_TRUE(body.empty()) + << "body should be empty because JSON is a CORB-protected resource"; +} + +TEST_F(WebBundleURLLoaderFactoryTest, CrossOriginJs) { + WriteBundle(CreateCrossOriginBundle()); + FinishWritingBundle(); + + auto request = StartRequest(GURL(kCrossOriginJsUrl)); + request.client->RunUntilComplete(); + + EXPECT_EQ(net::OK, request.client->completion_status().error_code); + EXPECT_FALSE(last_bundle_error().has_value()); + std::string body; + ASSERT_TRUE(mojo::BlockingCopyToString( + request.client->response_body_release(), &body)); + EXPECT_EQ("const not_secret = 1;", body) + << "body should be valid one because JS is not a CORB protected resource"; +} + } // namespace network
diff --git a/testing/buildbot/chromium.goma.fyi.json b/testing/buildbot/chromium.goma.fyi.json index 81e3447..730d138 100644 --- a/testing/buildbot/chromium.goma.fyi.json +++ b/testing/buildbot/chromium.goma.fyi.json
@@ -229,69 +229,6 @@ } ] }, - "Win7 Builder (dbg) Goma Canary": { - "additional_compile_targets": [ - "all" - ], - "gtest_tests": [ - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "base_unittests", - "test_id_prefix": "ninja://base:base_unittests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "content_unittests", - "test_id_prefix": "ninja://content/test:content_unittests/" - } - ] - }, - "Win7 Builder Goma Canary": { - "additional_compile_targets": [ - "all", - "pdf_fuzzers" - ], - "gtest_tests": [ - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "base_unittests", - "test_id_prefix": "ninja://base:base_unittests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "content_unittests", - "test_id_prefix": "ninja://content/test:content_unittests/" - } - ] - }, "android-archive-dbg-goma-canary": { "additional_compile_targets": [ "all",
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index 311d4b6..78c590a 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -3452,23 +3452,6 @@ 'gtest_tests': 'goma_gtests', }, }, - 'Win7 Builder (dbg) Goma Canary': { - 'additional_compile_targets': [ - 'all', - ], - 'test_suites': { - 'gtest_tests': 'goma_gtests', - }, - }, - 'Win7 Builder Goma Canary': { - 'additional_compile_targets': [ - 'all', - 'pdf_fuzzers', - ], - 'test_suites': { - 'gtest_tests': 'goma_gtests', - }, - }, 'android-archive-dbg-goma-canary': { 'additional_compile_targets': [ 'all',
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 47ad760..50a0007 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1374,9 +1374,12 @@ ], "experiments": [ { - "name": "Enabled", + "name": "Enabled_Stage2", "enable_features": [ "AutofillEnableAccountWalletStorage" + ], + "disable_features": [ + "WalletRequiresFirstSyncSetupComplete" ] } ] @@ -3753,21 +3756,6 @@ ] } ], - "IOSPreloadDelayWebStateReset": [ - { - "platforms": [ - "ios" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "PreloadDelayWebStateReset" - ] - } - ] - } - ], "IOSRequestDesktopByDefault": [ { "platforms": [
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl index 8fdbafe..dbbad849 100644 --- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl +++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -1815,6 +1815,8 @@ backdrop selection target-text + spelling-error + grammar-error first-line-inherited scrollbar scrollbar-thumb
diff --git a/third_party/blink/public/mojom/frame/user_activation_notification_type.mojom b/third_party/blink/public/mojom/frame/user_activation_notification_type.mojom index 2d3878b2..4f576ff 100644 --- a/third_party/blink/public/mojom/frame/user_activation_notification_type.mojom +++ b/third_party/blink/public/mojom/frame/user_activation_notification_type.mojom
@@ -31,8 +31,8 @@ // A media API caused the notification call. kMedia, - // An NFS API caused the notification call. - kNativeFileSystem, + // A File System Access API caused the notification call. + kFileSystemAccess, // A plugin API caused the notification call. Deprecated, preserved only for // UMA consistency.
diff --git a/third_party/blink/public/mojom/web_feature/web_feature.mojom b/third_party/blink/public/mojom/web_feature/web_feature.mojom index 4bfd95b..ed8e453 100644 --- a/third_party/blink/public/mojom/web_feature/web_feature.mojom +++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -2670,7 +2670,7 @@ kV8Window_ShowDirectoryPicker_Method = 3342, kRTCConstraintEnableRtpDataChannelsTrue = 3344, kRTCConstraintEnableRtpDataChannelsFalse = 3345, - kNativeFileSystemDragAndDrop = 3346, + kFileSystemAccessDragAndDrop = 3346, kRTCAdaptivePtime = 3347, kHTMLMetaElementReferrerPolicyMultipleTokensAffectingRequest = 3348, kNavigationTimingL2 = 3349,
diff --git a/third_party/blink/public/platform/platform.h b/third_party/blink/public/platform/platform.h index cce6ef82..46bdf2e6 100644 --- a/third_party/blink/public/platform/platform.h +++ b/third_party/blink/public/platform/platform.h
@@ -387,6 +387,12 @@ // once CreateAndSetCompositorThread() is called. scoped_refptr<base::SingleThreadTaskRunner> CompositorThreadTaskRunner(); + // Returns the task runner of the media thread. + // This method should only be called on the main thread, or it crashes. + virtual scoped_refptr<base::SingleThreadTaskRunner> MediaThreadTaskRunner() { + return nullptr; + } + // This is called after the compositor thread is created, so the embedder // can initiate an IPC to change its thread priority (on Linux we can't // increase the nice value, so we need to ask the browser process). This
diff --git a/third_party/blink/public/platform/web_common.h b/third_party/blink/public/platform/web_common.h index c467fdb..3494c23 100644 --- a/third_party/blink/public/platform/web_common.h +++ b/third_party/blink/public/platform/web_common.h
@@ -89,7 +89,7 @@ #if defined(WIN32) typedef wchar_t WebUChar; #else -typedef uint16_t WebUChar; +typedef char16_t WebUChar; #endif // Latin-1 character type
diff --git a/third_party/blink/public/platform/web_drag_data.h b/third_party/blink/public/platform/web_drag_data.h index 940a4c53..b3f7f89 100644 --- a/third_party/blink/public/platform/web_drag_data.h +++ b/third_party/blink/public/platform/web_drag_data.h
@@ -45,7 +45,7 @@ template <typename T> class WebVector; -using NativeFileSystemDropData = +using FileSystemAccessDropData = base::RefCountedData<blink::CrossVariantMojoRemote< mojom::FileSystemAccessDragDropTokenInterfaceBase>>; @@ -84,7 +84,7 @@ // Only valid when storage_type == kStorageTypeFilename. WebString filename_data; WebString display_name_data; - scoped_refptr<NativeFileSystemDropData> native_file_system_entry; + scoped_refptr<FileSystemAccessDropData> file_system_access_entry; // Only valid when storage_type == kStorageTypeBinaryData. WebData binary_data;
diff --git a/third_party/blink/public/web/web_testing_support.h b/third_party/blink/public/web/web_testing_support.h index 324b8607..0281ba65 100644 --- a/third_party/blink/public/web/web_testing_support.h +++ b/third_party/blink/public/web/web_testing_support.h
@@ -42,9 +42,12 @@ // Injects the |internals| object into the frame for Javascript to use. static void InjectInternalsObject(WebLocalFrame*); static void InjectInternalsObject(v8::Local<v8::Context>); - // Resets the state of the |internals| object, and things that it modifies, - // back to their starting state at the end of a test. - static void ResetInternalsObject(WebLocalFrame*); + // Resets state on the main frame once a test is complete, including: + // - disposing any isolated worlds created by the test. + // - resetting the state of the |internals| object, and things that it + // modifies, + // back to their starting state + static void ResetMainFrame(WebLocalFrame*); // Use this to install a mock scrollbar theme for tests. To use, simply // inherit your test class from this or instantiate it manually. The
diff --git a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc index 46d24bd..be5cf445 100644 --- a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc +++ b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
@@ -169,8 +169,8 @@ scoped_refptr<const SecurityOrigin> origin; if (world_->IsMainWorld()) { - // ActivityLogger for main world is updated within updateDocumentInternal(). - UpdateDocumentInternal(); + // This also updates the ActivityLogger for the main world. + UpdateDocumentForMainWorld(); origin = GetFrame()->DomWindow()->GetSecurityOrigin(); } else { UpdateActivityLogger(); @@ -433,7 +433,6 @@ } void LocalWindowProxy::UpdateDocument() { - DCHECK(world_->IsMainWorld()); // For an uninitialized main window proxy, there's nothing we need // to update. The update is done when the window proxy gets initialized later. if (lifecycle_ == Lifecycle::kContextIsUninitialized) @@ -449,10 +448,14 @@ return; } - UpdateDocumentInternal(); + if (!world_->IsMainWorld()) + return; + + UpdateDocumentForMainWorld(); } -void LocalWindowProxy::UpdateDocumentInternal() { +void LocalWindowProxy::UpdateDocumentForMainWorld() { + DCHECK(world_->IsMainWorld()); UpdateActivityLogger(); UpdateDocumentProperty(); UpdateSecurityOrigin(GetFrame()->DomWindow()->GetSecurityOrigin());
diff --git a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.h b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.h index 5fa12678..f23c503 100644 --- a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.h +++ b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.h
@@ -92,9 +92,10 @@ // Triggers updates of objects that are associated with a Document: // - the activity logger - // - the document DOM wrapper + // - the document DOM wrapper (performance optimization for accessing + // window.document in the main world) // - the security origin - void UpdateDocumentInternal(); + void UpdateDocumentForMainWorld(); // The JavaScript wrapper for the document object is cached on the global // object for fast access. UpdateDocumentProperty sets the wrapper
diff --git a/third_party/blink/renderer/bindings/core/v8/script_controller.cc b/third_party/blink/renderer/bindings/core/v8/script_controller.cc index f33d32c2..105e583 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_controller.cc +++ b/third_party/blink/renderer/bindings/core/v8/script_controller.cc
@@ -177,7 +177,7 @@ } void ScriptController::UpdateDocument() { - window_proxy_manager_->MainWorldProxyMaybeUninitialized()->UpdateDocument(); + window_proxy_manager_->UpdateDocument(); } void ScriptController::ExecuteJavaScriptURL(
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/serialization_tag.h b/third_party/blink/renderer/bindings/core/v8/serialization/serialization_tag.h index d173618..1eb157a3 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/serialization_tag.h +++ b/third_party/blink/renderer/bindings/core/v8/serialization/serialization_tag.h
@@ -43,16 +43,15 @@ // transferred MojoHandle. kBlobTag = 'b', // uuid:WebCoreString, type:WebCoreString, size:uint64_t -> // Blob (ref) - kBlobIndexTag = 'i', // index:int32_t -> Blob (ref) - kFileTag = 'f', // file:RawFile -> File (ref) - kFileIndexTag = 'e', // index:int32_t -> File (ref) - kDOMFileSystemTag = 'd', // type:int32_t, name:WebCoreString, - // uuid:WebCoreString -> FileSystem (ref) - kNativeFileSystemFileHandleTag = 'n', // name:WebCoreString, index:uint32_t - // -> NativeFileSystemFileHandle (ref) - kNativeFileSystemDirectoryHandleTag = - 'N', // name:WebCoreString, index:uint32_t -> - // NativeFileSystemDirectoryHandle (ref) + kBlobIndexTag = 'i', // index:int32_t -> Blob (ref) + kFileTag = 'f', // file:RawFile -> File (ref) + kFileIndexTag = 'e', // index:int32_t -> File (ref) + kDOMFileSystemTag = 'd', // type:int32_t, name:WebCoreString, + // uuid:WebCoreString -> FileSystem (ref) + kFileSystemFileHandleTag = 'n', // name:WebCoreString, index:uint32_t + // -> FileSystemFileHandle (ref) + kFileSystemDirectoryHandleTag = 'N', // name:WebCoreString, index:uint32_t -> + // FileSystemDirectoryHandle (ref) kFileListTag = 'l', // length:uint32_t, files:RawFile[length] -> FileList (ref) kFileListIndexTag =
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc index ce93815..0d18b67 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc +++ b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc
@@ -793,7 +793,7 @@ "Update WebSerializedScriptValueVersion.h."); bool SerializedScriptValue::IsOriginCheckRequired() const { - return native_file_system_tokens_.size() > 0; + return file_system_access_tokens_.size() > 0; } } // namespace blink
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h index 08ef4b8..8c05985 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h +++ b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h
@@ -102,7 +102,7 @@ using TransferredWasmModulesArray = WTF::Vector<v8::CompiledWasmModule>; using MessagePortChannelArray = Vector<MessagePortChannel>; using StreamArray = Vector<Stream>; - using NativeFileSystemTokensArray = + using FileSystemAccessTokensArray = Vector<mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken>>; // Increment this for each incompatible change to the wire format. @@ -275,8 +275,8 @@ return shared_array_buffers_contents_; } BlobDataHandleMap& BlobDataHandles() { return blob_data_handles_; } - NativeFileSystemTokensArray& NativeFileSystemTokens() { - return native_file_system_tokens_; + FileSystemAccessTokensArray& FileSystemAccessTokens() { + return file_system_access_tokens_; } MojoScopedHandleArray& MojoHandles() { return mojo_handles_; } ArrayBufferContentsArray& GetArrayBufferContentsArray() { @@ -396,7 +396,7 @@ BlobDataHandleMap blob_data_handles_; MojoScopedHandleArray mojo_handles_; SharedArrayBufferContentsArray shared_array_buffers_contents_; - NativeFileSystemTokensArray native_file_system_tokens_; + FileSystemAccessTokensArray file_system_access_tokens_; HashMap<const void* const*, std::unique_ptr<Attachment>> attachments_; bool has_registered_external_allocation_;
diff --git a/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.cc b/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.cc index 66bc944..1032a80 100644 --- a/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.cc +++ b/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.cc
@@ -68,6 +68,13 @@ WindowProxyMaybeUninitialized(*entry.first)->InitializeIfNeeded(); } +void WindowProxyManager::ResetIsolatedWorldsForTesting() { + for (auto& world_info : isolated_worlds_) { + world_info.value->ClearForClose(); + } + isolated_worlds_.clear(); +} + WindowProxyManager::WindowProxyManager(Frame& frame, FrameType frame_type) : isolate_(V8PerIsolateData::MainThreadIsolate()), frame_(&frame), @@ -114,6 +121,16 @@ return window_proxy; } +void LocalWindowProxyManager::UpdateDocument() { + MainWorldProxyMaybeUninitialized()->UpdateDocument(); + + for (auto& entry : isolated_worlds_) { + auto* isolated_window_proxy = + static_cast<LocalWindowProxy*>(entry.value.Get()); + isolated_window_proxy->UpdateDocument(); + } +} + void LocalWindowProxyManager::UpdateSecurityOrigin( const SecurityOrigin* security_origin) { static_cast<LocalWindowProxy*>(window_proxy_.Get())
diff --git a/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.h b/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.h index ec27fcd..53e1fd7 100644 --- a/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.h +++ b/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.h
@@ -27,7 +27,7 @@ v8::Isolate* GetIsolate() const { return isolate_; } void ClearForClose(); - void CORE_EXPORT ClearForNavigation(); + CORE_EXPORT void ClearForNavigation(); void ClearForSwap(); void ClearForV8MemoryPurge(); @@ -45,6 +45,8 @@ return window_proxy; } + CORE_EXPORT void ResetIsolatedWorldsForTesting(); + protected: using IsolatedWorldMap = HeapHashMap<int, Member<WindowProxy>>; enum class FrameType { kLocal, kRemote }; @@ -93,6 +95,8 @@ return static_cast<LocalWindowProxy*>(window_proxy_.Get()); } + void UpdateDocument(); + // Sets the given security origin to the main world's context. Also updates // the security origin of the context for each isolated world. void UpdateSecurityOrigin(const SecurityOrigin*);
diff --git a/third_party/blink/renderer/bindings/core/v8/window_proxy_test.cc b/third_party/blink/renderer/bindings/core/v8/window_proxy_test.cc index 6faf1d5..ca16c31 100644 --- a/third_party/blink/renderer/bindings/core/v8/window_proxy_test.cc +++ b/third_party/blink/renderer/bindings/core/v8/window_proxy_test.cc
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "third_party/blink/public/web/web_script_source.h" #include "third_party/blink/renderer/core/testing/sim/sim_request.h" #include "third_party/blink/renderer/core/testing/sim/sim_test.h" #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" @@ -49,4 +50,46 @@ ASSERT_GT(ConsoleMessages().size(), 0U); EXPECT_EQ("PASSED", ConsoleMessages()[0]); } + +TEST_F(WindowProxyTest, IsolatedWorldReinitializedAfterNavigation) { + SimRequest main_resource("https://example.com/index.html", "text/html"); + LoadURL("https://example.com/index.html"); + main_resource.Complete(R"HTML( + <!DOCTYPE html> + <html><body><iframe></iframe></body></html> + )HTML"); + + ASSERT_TRUE(MainFrame().FirstChild()); + + v8::HandleScope scope(v8::Isolate::GetCurrent()); + + const int32_t kIsolatedWorldId = 42; + + // Save a reference to the top `window` in the isolated world. + v8::Local<v8::Value> window_top = + MainFrame().ExecuteScriptInIsolatedWorldAndReturnValue( + kIsolatedWorldId, WebScriptSource("window")); + ASSERT_TRUE(window_top->IsObject()); + + // Save a reference to the child frame's window proxy in the isolated world. + v8::Local<v8::Value> saved_child_window = + MainFrame().ExecuteScriptInIsolatedWorldAndReturnValue( + kIsolatedWorldId, WebScriptSource("saved = window[0]")); + ASSERT_TRUE(saved_child_window->IsObject()); + + frame_test_helpers::LoadFrame(MainFrame().FirstChild()->ToWebLocalFrame(), + "data:text/html,<body><p>Hello</p></body>"); + ASSERT_TRUE(MainFrame().FirstChild()); + + // Test if the window proxy of the navigated frame was reinitialized. The + // `top` attribute of the saved child frame's window proxy reference should + // refer to the same object as the top-level window proxy reference that was + // cached earlier. + v8::Local<v8::Value> top_via_saved = + MainFrame().ExecuteScriptInIsolatedWorldAndReturnValue( + kIsolatedWorldId, WebScriptSource("saved.top")); + EXPECT_TRUE(top_via_saved->IsObject()); + EXPECT_TRUE(window_top->StrictEquals(top_via_saved)); +} + } // namespace blink
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni index 7e3bb39d..9425e65 100644 --- a/third_party/blink/renderer/bindings/generated_in_modules.gni +++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -1745,8 +1745,8 @@ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_mime_type.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_mime_type_array.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_mime_type_array.h", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_native_file_system_directory_iterator.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_native_file_system_directory_iterator.h", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_file_system_directory_iterator.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_file_system_directory_iterator.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_native_io_file.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_native_io_file.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_native_io_file_manager.cc",
diff --git a/third_party/blink/renderer/bindings/idl_in_modules.gni b/third_party/blink/renderer/bindings/idl_in_modules.gni index 4c8f79e..9a37733 100644 --- a/third_party/blink/renderer/bindings/idl_in_modules.gni +++ b/third_party/blink/renderer/bindings/idl_in_modules.gni
@@ -206,7 +206,7 @@ "//third_party/blink/renderer/modules/encryptedmedia/navigator_request_media_key_system_access.idl", "//third_party/blink/renderer/modules/eventsource/event_source.idl", "//third_party/blink/renderer/modules/eventsource/event_source_init.idl", - "//third_party/blink/renderer/modules/file_system_access/data_transfer_item_native_file_system.idl", + "//third_party/blink/renderer/modules/file_system_access/data_transfer_item_file_system_access.idl", "//third_party/blink/renderer/modules/file_system_access/directory_picker_options.idl", "//third_party/blink/renderer/modules/file_system_access/file_picker_accept_type.idl", "//third_party/blink/renderer/modules/file_system_access/file_picker_options.idl", @@ -219,11 +219,11 @@ "//third_party/blink/renderer/modules/file_system_access/file_system_handle_permission_descriptor.idl", "//third_party/blink/renderer/modules/file_system_access/file_system_remove_options.idl", "//third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.idl", - "//third_party/blink/renderer/modules/file_system_access/native_file_system_directory_iterator.idl", + "//third_party/blink/renderer/modules/file_system_access/file_system_directory_iterator.idl", "//third_party/blink/renderer/modules/file_system_access/open_file_picker_options.idl", "//third_party/blink/renderer/modules/file_system_access/save_file_picker_options.idl", - "//third_party/blink/renderer/modules/file_system_access/storage_manager_native_file_system.idl", - "//third_party/blink/renderer/modules/file_system_access/window_native_file_system.idl", + "//third_party/blink/renderer/modules/file_system_access/storage_manager_file_system_access.idl", + "//third_party/blink/renderer/modules/file_system_access/window_file_system_access.idl", "//third_party/blink/renderer/modules/file_system_access/write_params.idl", "//third_party/blink/renderer/modules/filesystem/data_transfer_item_file_system.idl", "//third_party/blink/renderer/modules/filesystem/dedicated_worker_global_scope_file_system.idl",
diff --git a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc index ed3f252..327c0e8 100644 --- a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc +++ b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc
@@ -13,8 +13,8 @@ #include "third_party/blink/renderer/bindings/modules/v8/serialization/web_crypto_sub_tags.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/modules/crypto/crypto_key.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_directory_handle.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_file_handle.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_file_handle.h" #include "third_party/blink/renderer/modules/filesystem/dom_file_system.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_certificate.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_certificate_generator.h" @@ -52,9 +52,9 @@ ExecutionContext::From(GetScriptState()), name, static_cast<mojom::blink::FileSystemType>(raw_type), KURL(root_url)); } - case kNativeFileSystemFileHandleTag: - case kNativeFileSystemDirectoryHandleTag: - return ReadNativeFileSystemHandle(tag); + case kFileSystemFileHandleTag: + case kFileSystemDirectoryHandleTag: + return ReadFileSystemHandle(tag); case kRTCCertificateTag: { String pem_private_key; String pem_certificate; @@ -311,10 +311,9 @@ return MakeGarbageCollected<CryptoKey>(key); } -NativeFileSystemHandle* -V8ScriptValueDeserializerForModules::ReadNativeFileSystemHandle( +FileSystemHandle* V8ScriptValueDeserializerForModules::ReadFileSystemHandle( SerializationTag tag) { - if (!RuntimeEnabledFeatures::NativeFileSystemEnabled( + if (!RuntimeEnabledFeatures::FileSystemAccessEnabled( ExecutionContext::From(GetScriptState()))) { return nullptr; } @@ -326,8 +325,8 @@ } // Find the FileSystemHandle's token. - SerializedScriptValue::NativeFileSystemTokensArray& tokens_array = - GetSerializedScriptValue()->NativeFileSystemTokens(); + SerializedScriptValue::FileSystemAccessTokensArray& tokens_array = + GetSerializedScriptValue()->FileSystemAccessTokens(); if (token_index >= tokens_array.size()) { return nullptr; } @@ -344,34 +343,34 @@ token->Clone(token_clone.InitWithNewPipeAndPassReceiver()); tokens_array[token_index] = std::move(token_clone); - // Use the NativeFileSystemManager to redeem the token to clone the + // Use the FileSystemAccessManager to redeem the token to clone the // FileSystemHandle. ExecutionContext* execution_context = ExecutionContext::From(GetScriptState()); mojo::Remote<mojom::blink::FileSystemAccessManager> - native_file_system_manager; + file_system_access_manager; execution_context->GetBrowserInterfaceBroker().GetInterface( - native_file_system_manager.BindNewPipeAndPassReceiver()); + file_system_access_manager.BindNewPipeAndPassReceiver()); // Clone the FileSystemHandle object. switch (tag) { - case kNativeFileSystemFileHandleTag: { + case kFileSystemFileHandleTag: { mojo::PendingRemote<mojom::blink::FileSystemAccessFileHandle> file_handle; - native_file_system_manager->GetFileHandleFromToken( + file_system_access_manager->GetFileHandleFromToken( token.Unbind(), file_handle.InitWithNewPipeAndPassReceiver()); - return MakeGarbageCollected<NativeFileSystemFileHandle>( - execution_context, name, std::move(file_handle)); + return MakeGarbageCollected<FileSystemFileHandle>(execution_context, name, + std::move(file_handle)); } - case kNativeFileSystemDirectoryHandleTag: { + case kFileSystemDirectoryHandleTag: { mojo::PendingRemote<mojom::blink::FileSystemAccessDirectoryHandle> directory_handle; - native_file_system_manager->GetDirectoryHandleFromToken( + file_system_access_manager->GetDirectoryHandleFromToken( token.Unbind(), directory_handle.InitWithNewPipeAndPassReceiver()); - return MakeGarbageCollected<NativeFileSystemDirectoryHandle>( + return MakeGarbageCollected<FileSystemDirectoryHandle>( execution_context, name, std::move(directory_handle)); } default: {
diff --git a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.h b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.h index ccc7f4e..90408ee 100644 --- a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.h +++ b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.h
@@ -11,7 +11,7 @@ namespace blink { class CryptoKey; -class NativeFileSystemHandle; +class FileSystemHandle; class RTCEncodedAudioFrame; class RTCEncodedVideoFrame; class VideoFrame; @@ -46,7 +46,7 @@ return true; } CryptoKey* ReadCryptoKey(); - NativeFileSystemHandle* ReadNativeFileSystemHandle(SerializationTag tag); + FileSystemHandle* ReadFileSystemHandle(SerializationTag tag); RTCEncodedAudioFrame* ReadRTCEncodedAudioFrame(); RTCEncodedVideoFrame* ReadRTCEncodedVideoFrame(); VideoFrame* ReadVideoFrame();
diff --git a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc index 8cb08ef3..fe674e9 100644 --- a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc +++ b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc
@@ -62,18 +62,16 @@ return true; } if (wrapper_type_info == V8FileSystemFileHandle::GetWrapperTypeInfo() && - RuntimeEnabledFeatures::NativeFileSystemEnabled( + RuntimeEnabledFeatures::FileSystemAccessEnabled( ExecutionContext::From(GetScriptState()))) { - return WriteNativeFileSystemHandle( - kNativeFileSystemFileHandleTag, - wrappable->ToImpl<NativeFileSystemHandle>()); + return WriteFileSystemHandle(kFileSystemFileHandleTag, + wrappable->ToImpl<FileSystemHandle>()); } if (wrapper_type_info == V8FileSystemDirectoryHandle::GetWrapperTypeInfo() && - RuntimeEnabledFeatures::NativeFileSystemEnabled( + RuntimeEnabledFeatures::FileSystemAccessEnabled( ExecutionContext::From(GetScriptState()))) { - return WriteNativeFileSystemHandle( - kNativeFileSystemDirectoryHandleTag, - wrappable->ToImpl<NativeFileSystemHandle>()); + return WriteFileSystemHandle(kFileSystemDirectoryHandleTag, + wrappable->ToImpl<FileSystemHandle>()); } if (wrapper_type_info == V8RTCCertificate::GetWrapperTypeInfo()) { RTCCertificate* certificate = wrappable->ToImpl<RTCCertificate>(); @@ -301,20 +299,20 @@ return true; } -bool V8ScriptValueSerializerForModules::WriteNativeFileSystemHandle( +bool V8ScriptValueSerializerForModules::WriteFileSystemHandle( SerializationTag tag, - NativeFileSystemHandle* native_file_system_handle) { + FileSystemHandle* file_system_handle) { mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> token = - native_file_system_handle->Transfer(); + file_system_handle->Transfer(); - SerializedScriptValue::NativeFileSystemTokensArray& tokens_array = - GetSerializedScriptValue()->NativeFileSystemTokens(); + SerializedScriptValue::FileSystemAccessTokensArray& tokens_array = + GetSerializedScriptValue()->FileSystemAccessTokens(); tokens_array.push_back(std::move(token)); const uint32_t token_index = static_cast<uint32_t>(tokens_array.size() - 1); WriteTag(tag); - WriteUTF8String(native_file_system_handle->name()); + WriteUTF8String(file_system_handle->name()); WriteUint32(token_index); return true; }
diff --git a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.h b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.h index d15725e..2bee9de 100644 --- a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.h +++ b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.h
@@ -11,7 +11,7 @@ namespace blink { -class NativeFileSystemHandle; +class FileSystemHandle; class RTCEncodedAudioFrame; class RTCEncodedVideoFrame; class VideoFrame; @@ -32,9 +32,8 @@ private: void WriteOneByte(uint8_t byte) { WriteRawBytes(&byte, 1); } bool WriteCryptoKey(const WebCryptoKey&, ExceptionState&); - bool WriteNativeFileSystemHandle( - SerializationTag tag, - NativeFileSystemHandle* native_file_system_handle); + bool WriteFileSystemHandle(SerializationTag tag, + FileSystemHandle* file_system_handle); bool WriteRTCEncodedAudioFrame(RTCEncodedAudioFrame*); bool WriteRTCEncodedVideoFrame(RTCEncodedVideoFrame*); bool WriteVideoFrame(VideoFrame*);
diff --git a/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.cc b/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.cc index 94aebbec..1ec4526 100644 --- a/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.cc +++ b/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.cc
@@ -542,8 +542,8 @@ scoped_refptr<SerializedScriptValue> serialized_value = value->CreateSerializedValue(); - serialized_value->NativeFileSystemTokens() = - std::move(const_cast<IDBValue*>(value)->NativeFileSystemTokens()); + serialized_value->FileSystemAccessTokens() = + std::move(const_cast<IDBValue*>(value)->FileSystemAccessTokens()); SerializedScriptValue::DeserializeOptions options; options.blob_info = &value->BlobInfo();
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py index 0feb3e6..ca8faf0 100644 --- a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py +++ b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
@@ -5222,7 +5222,7 @@ } """)) - if class_like.identifier == "NativeFileSystemDirectoryIterator": + if class_like.identifier == "FileSystemDirectoryIterator": body.append( T("""\ // Temporary @@asyncIterator support for FileSystemDirectoryHandle
diff --git a/third_party/blink/renderer/bindings/templates/interface_base.cc.tmpl b/third_party/blink/renderer/bindings/templates/interface_base.cc.tmpl index 8473ac9..8f75aea 100644 --- a/third_party/blink/renderer/bindings/templates/interface_base.cc.tmpl +++ b/third_party/blink/renderer/bindings/templates/interface_base.cc.tmpl
@@ -586,7 +586,7 @@ interface_template->Inherit(intrinsic_iterator_prototype_interface_template); {% endif %} - {% if interface_name == 'NativeFileSystemDirectoryIterator' %} + {% if interface_name == 'FileSystemDirectoryIterator' %} // Temporary @@asyncIterator support for FileSystemDirectoryHandle // TODO(https://crbug.com/1087157): Replace with proper bindings support. v8::Local<v8::FunctionTemplate> intrinsic_iterator_prototype_interface_template =
diff --git a/third_party/blink/renderer/core/clipboard/data_object.cc b/third_party/blink/renderer/core/clipboard/data_object.cc index 763ca44..e21047f 100644 --- a/third_party/blink/renderer/core/clipboard/data_object.cc +++ b/third_party/blink/renderer/core/clipboard/data_object.cc
@@ -230,10 +230,10 @@ const String& filename, const String& display_name, const String& file_system_id, - scoped_refptr<NativeFileSystemDropData> native_file_system_entry) { + scoped_refptr<FileSystemAccessDropData> file_system_access_entry) { InternalAddFileItem(DataObjectItem::CreateFromFileWithFileSystemId( File::CreateForUserProvidedFile(filename, display_name), file_system_id, - std::move(native_file_system_entry))); + std::move(file_system_access_entry))); } void DataObject::AddSharedBuffer(scoped_refptr<SharedBuffer> buffer, @@ -308,7 +308,7 @@ has_file_system = true; data_object->AddFilename(item.filename_data, item.display_name_data, data.FilesystemId(), - item.native_file_system_entry); + item.file_system_access_entry); break; case WebDragData::Item::kStorageTypeBinaryData: // This should never happen when dragging in.
diff --git a/third_party/blink/renderer/core/clipboard/data_object.h b/third_party/blink/renderer/core/clipboard/data_object.h index b621b8e4..d7982fb 100644 --- a/third_party/blink/renderer/core/clipboard/data_object.h +++ b/third_party/blink/renderer/core/clipboard/data_object.h
@@ -99,8 +99,8 @@ void AddFilename(const String& filename, const String& display_name, const String& file_system_id, - scoped_refptr<NativeFileSystemDropData> - native_file_system_entry = nullptr); + scoped_refptr<FileSystemAccessDropData> + file_system_access_entry = nullptr); // Used for dragging in filesystem from the desktop. void SetFilesystemId(const String& file_system_id) {
diff --git a/third_party/blink/renderer/core/clipboard/data_object_item.cc b/third_party/blink/renderer/core/clipboard/data_object_item.cc index a4aa6c7..030a7c0 100644 --- a/third_party/blink/renderer/core/clipboard/data_object_item.cc +++ b/third_party/blink/renderer/core/clipboard/data_object_item.cc
@@ -63,12 +63,12 @@ DataObjectItem* DataObjectItem::CreateFromFileWithFileSystemId( File* file, const String& file_system_id, - scoped_refptr<NativeFileSystemDropData> native_file_entry) { + scoped_refptr<FileSystemAccessDropData> file_system_access_entry) { DataObjectItem* item = MakeGarbageCollected<DataObjectItem>(kFileKind, file->type()); item->file_ = file; item->file_system_id_ = file_system_id; - item->native_file_system_entry_ = native_file_entry; + item->file_system_access_entry_ = file_system_access_entry; return item; } @@ -226,17 +226,17 @@ } bool DataObjectItem::HasFileSystemAccessEntry() const { - return static_cast<bool>(native_file_system_entry_); + return static_cast<bool>(file_system_access_entry_); } mojo::PendingRemote<mojom::blink::FileSystemAccessDragDropToken> DataObjectItem::CloneFileSystemAccessEntryToken() const { DCHECK(HasFileSystemAccessEntry()); mojo::Remote<mojom::blink::FileSystemAccessDragDropToken> token_cloner( - std::move(native_file_system_entry_->data)); + std::move(file_system_access_entry_->data)); mojo::PendingRemote<mojom::blink::FileSystemAccessDragDropToken> token_clone; token_cloner->Clone(token_clone.InitWithNewPipeAndPassReceiver()); - native_file_system_entry_->data = token_cloner.Unbind(); + file_system_access_entry_->data = token_cloner.Unbind(); return token_clone; }
diff --git a/third_party/blink/renderer/core/clipboard/data_object_item.h b/third_party/blink/renderer/core/clipboard/data_object_item.h index 71706e5..4ac9450 100644 --- a/third_party/blink/renderer/core/clipboard/data_object_item.h +++ b/third_party/blink/renderer/core/clipboard/data_object_item.h
@@ -59,7 +59,8 @@ static DataObjectItem* CreateFromFileWithFileSystemId( File*, const String& file_system_id, - scoped_refptr<NativeFileSystemDropData> native_file_entry = nullptr); + scoped_refptr<FileSystemAccessDropData> file_system_access_entry = + nullptr); static DataObjectItem* CreateFromURL(const String& url, const String& title); static DataObjectItem* CreateFromHTML(const String& html, const KURL& base_url); @@ -106,7 +107,7 @@ kInternalSource, }; - scoped_refptr<NativeFileSystemDropData> native_file_system_entry_; + scoped_refptr<FileSystemAccessDropData> file_system_access_entry_; DataSource source_; ItemKind kind_; String type_;
diff --git a/third_party/blink/renderer/core/css/css_selector.cc b/third_party/blink/renderer/core/css/css_selector.cc index 74a7f48..a1068ac 100644 --- a/third_party/blink/renderer/core/css/css_selector.cc +++ b/third_party/blink/renderer/core/css/css_selector.cc
@@ -245,6 +245,10 @@ return kPseudoIdResizer; case kPseudoTargetText: return kPseudoIdTargetText; + case kPseudoSpellingError: + return kPseudoIdSpellingError; + case kPseudoGrammarError: + return kPseudoIdGrammarError; case kPseudoUnknown: case kPseudoEmpty: case kPseudoFirstChild: @@ -411,6 +415,7 @@ {"focus-within", CSSSelector::kPseudoFocusWithin}, {"fullscreen", CSSSelector::kPseudoFullscreen}, {"future", CSSSelector::kPseudoFutureCue}, + {"grammar-error", CSSSelector::kPseudoGrammarError}, {"horizontal", CSSSelector::kPseudoHorizontal}, {"host", CSSSelector::kPseudoHost}, {"hover", CSSSelector::kPseudoHover}, @@ -440,6 +445,7 @@ {"scope", CSSSelector::kPseudoScope}, {"selection", CSSSelector::kPseudoSelection}, {"single-button", CSSSelector::kPseudoSingleButton}, + {"spelling-error", CSSSelector::kPseudoSpellingError}, {"start", CSSSelector::kPseudoStart}, {"target", CSSSelector::kPseudoTarget}, {"target-text", CSSSelector::kPseudoTargetText}, @@ -521,6 +527,12 @@ return CSSSelector::kPseudoUnknown; } + if ((match->type == CSSSelector::kPseudoSpellingError || + match->type == CSSSelector::kPseudoGrammarError) && + !RuntimeEnabledFeatures::CSSSpellingGrammarErrorsEnabled()) { + return CSSSelector::kPseudoUnknown; + } + return static_cast<CSSSelector::PseudoType>(match->type); } @@ -630,6 +642,8 @@ case kPseudoWebKitCustomElement: case kPseudoSlotted: case kPseudoTargetText: + case kPseudoSpellingError: + case kPseudoGrammarError: if (match_ != kPseudoElement) pseudo_type_ = kPseudoUnknown; break; @@ -1121,6 +1135,8 @@ case kPseudoFirstLetter: case kPseudoSelection: case kPseudoTargetText: + case kPseudoSpellingError: + case kPseudoGrammarError: return true; default: return false;
diff --git a/third_party/blink/renderer/core/css/css_selector.h b/third_party/blink/renderer/core/css/css_selector.h index a60e66d4..9287a7c 100644 --- a/third_party/blink/renderer/core/css/css_selector.h +++ b/third_party/blink/renderer/core/css/css_selector.h
@@ -285,6 +285,8 @@ kPseudoVideoPersistentAncestor, kPseudoTargetText, kPseudoDir, + kPseudoSpellingError, + kPseudoGrammarError, }; enum class AttributeMatchType {
diff --git a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc index 55c709a2..b280d8e 100644 --- a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc +++ b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
@@ -734,10 +734,11 @@ AdjustOverflow(style); // overflow-clip-margin only applies if 'overflow: clip' is set along both - // axis. - if (style.OverflowX() != EOverflow::kClip || - style.OverflowY() != EOverflow::kClip) { - style.SetOverflowClipMargin(LayoutUnit()); + // axis or 'contain: paint'. + if (!style.ContainsPaint() && !(style.OverflowX() == EOverflow::kClip && + style.OverflowY() == EOverflow::kClip)) { + style.SetOverflowClipMargin( + ComputedStyleInitialValues::InitialOverflowClipMargin()); } if (StopPropagateTextDecorations(style, element))
diff --git a/third_party/blink/renderer/core/css/resolver/style_adjuster_test.cc b/third_party/blink/renderer/core/css/resolver/style_adjuster_test.cc index 5af052b..f7dbe27b9 100644 --- a/third_party/blink/renderer/core/css/resolver/style_adjuster_test.cc +++ b/third_party/blink/renderer/core/css/resolver/style_adjuster_test.cc
@@ -128,6 +128,7 @@ overflow-clip-margin: 1px;'> <div id='vishidden' style='overflow-x: visible; overflow-y: hidden; overflow-clip-margin: 1px;'> + <div id='containpaint' style='contain: paint; overflow-clip-margin: 1px;'> </div> )HTML"); UpdateAllLifecyclePhasesForTest(); @@ -173,6 +174,11 @@ EXPECT_EQ(EOverflow::kHidden, target->GetComputedStyle()->OverflowX()); EXPECT_EQ(EOverflow::kAuto, target->GetComputedStyle()->OverflowY()); EXPECT_EQ(LayoutUnit(), target->GetComputedStyle()->OverflowClipMargin()); + + target = GetDocument().getElementById("containpaint"); + ASSERT_TRUE(target); + EXPECT_TRUE(target->GetComputedStyle()->ContainsPaint()); + EXPECT_EQ(LayoutUnit(1), target->GetComputedStyle()->OverflowClipMargin()); } TEST_F(StyleAdjusterTest, TouchActionContentEditableArea) {
diff --git a/third_party/blink/renderer/core/css/rule_feature_set.cc b/third_party/blink/renderer/core/css/rule_feature_set.cc index d27e923..0c26747 100644 --- a/third_party/blink/renderer/core/css/rule_feature_set.cc +++ b/third_party/blink/renderer/core/css/rule_feature_set.cc
@@ -180,6 +180,8 @@ case CSSSelector::kPseudoIs: case CSSSelector::kPseudoWhere: case CSSSelector::kPseudoTargetText: + case CSSSelector::kPseudoSpellingError: + case CSSSelector::kPseudoGrammarError: return true; case CSSSelector::kPseudoUnknown: case CSSSelector::kPseudoLeftPage:
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc index 88d90dfa..6928b23 100644 --- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc +++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -723,7 +723,9 @@ if (print_context_) PrintEnd(); print_client_.reset(); +#if DCHECK_IS_ON() is_in_printing_ = false; +#endif } WebString WebLocalFrameImpl::AssignedName() const { @@ -1611,10 +1613,12 @@ void WebLocalFrameImpl::DispatchBeforePrintEvent( base::WeakPtr<WebPrintClient> print_client) { - CHECK(!is_in_printing_) << "DispatchAfterPrintEvent() should have been " - "called after the previous " - "DispatchBeforePrintEvent() call."; +#if DCHECK_IS_ON() + DCHECK(!is_in_printing_) << "DispatchAfterPrintEvent() should have been " + "called after the previous " + "DispatchBeforePrintEvent() call."; is_in_printing_ = true; +#endif print_client_ = print_client; @@ -1630,9 +1634,11 @@ } void WebLocalFrameImpl::DispatchAfterPrintEvent() { - CHECK(is_in_printing_) << "DispatchBeforePrintEvent() should be called " - "before DispatchAfterPrintEvent()."; +#if DCHECK_IS_ON() + DCHECK(is_in_printing_) << "DispatchBeforePrintEvent() should be called " + "before DispatchAfterPrintEvent()."; is_in_printing_ = false; +#endif print_client_.reset();
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/third_party/blink/renderer/core/frame/web_local_frame_impl.h index 4e62d1f..5cc6f7a5 100644 --- a/third_party/blink/renderer/core/frame/web_local_frame_impl.h +++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
@@ -584,11 +584,11 @@ // cleared upon close(). SelfKeepAlive<WebLocalFrameImpl> self_keep_alive_; +#if DCHECK_IS_ON() // True if DispatchBeforePrintEvent() was called, and // DispatchAfterPrintEvent() is not called yet. - // TODO(crbug.com/1121077) After fixing the bug, make this member variable - // only available when DCHECK_IS_ON(). bool is_in_printing_ = false; +#endif // Bookkeeping to suppress redundant scroll and focus requests for an already // scrolled and focused editable node.
diff --git a/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc b/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc index dabdd00..0a9daa58 100644 --- a/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc
@@ -180,6 +180,10 @@ return protocol::DOM::PseudoTypeEnum::Selection; case kPseudoIdTargetText: return protocol::DOM::PseudoTypeEnum::TargetText; + case kPseudoIdSpellingError: + return protocol::DOM::PseudoTypeEnum::SpellingError; + case kPseudoIdGrammarError: + return protocol::DOM::PseudoTypeEnum::GrammarError; case kPseudoIdFirstLineInherited: return protocol::DOM::PseudoTypeEnum::FirstLineInherited; case kPseudoIdScrollbar:
diff --git a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc index 6116c07..6cdd702 100644 --- a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc +++ b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc
@@ -369,6 +369,8 @@ DEFINE_STRING_MAPPING(PseudoXrOverlay) DEFINE_STRING_MAPPING(PseudoTargetText) DEFINE_STRING_MAPPING(PseudoModal) + DEFINE_STRING_MAPPING(PseudoSpellingError) + DEFINE_STRING_MAPPING(PseudoGrammarError) #undef DEFINE_STRING_MAPPING }
diff --git a/third_party/blink/renderer/core/layout/layout_block.cc b/third_party/blink/renderer/core/layout/layout_block.cc index f4c1983..5b75ed3 100644 --- a/third_party/blink/renderer/core/layout/layout_block.cc +++ b/third_party/blink/renderer/core/layout/layout_block.cc
@@ -251,8 +251,12 @@ NOT_DESTROYED(); LayoutBox::UpdateFromStyle(); - bool should_clip_overflow = !StyleRef().IsOverflowVisibleAlongBothAxes() && - AllowsNonVisibleOverflow(); + // OverflowClipMargin() is only set if overflow is 'clip' along both axis, or + // 'contain: paint'. The later implies clipping along both axis. + bool should_clip_overflow = + (!StyleRef().IsOverflowVisibleAlongBothAxes() || + StyleRef().OverflowClipMargin() != LayoutUnit()) && + AllowsNonVisibleOverflow(); if (should_clip_overflow != HasNonVisibleOverflow()) { if (GetScrollableArea()) GetScrollableArea()->InvalidateAllStickyConstraints();
diff --git a/third_party/blink/renderer/core/layout/layout_box_test.cc b/third_party/blink/renderer/core/layout/layout_box_test.cc index 201558a6..134cc6c 100644 --- a/third_party/blink/renderer/core/layout/layout_box_test.cc +++ b/third_party/blink/renderer/core/layout/layout_box_test.cc
@@ -524,6 +524,7 @@ SetBodyInnerHTML(R"HTML( <style> .parent { width: 100px; height: 50px; overflow: clip; } + .parent2 { width: 100px; height: 50px; contain: paint; } .child { width: 110px; height: 55px; } </style> <div id="clip1" style="overflow-clip-margin: 4px" class="parent"> @@ -532,6 +533,9 @@ <div id="clip2" style="overflow-clip-margin: 11px" class="parent"> <div class="child"></div> </div> + <div id="clip3" style="overflow-clip-margin: 11px" class="parent2"> + <div class="child"></div> + </div> )HTML"); LayoutBox* clip1 = GetLayoutBoxByElementId("clip1"); @@ -543,12 +547,18 @@ EXPECT_FALSE(clip2->IsScrollContainer()); EXPECT_TRUE(clip2->ShouldClipOverflowAlongBothAxis()); EXPECT_EQ(LayoutRect(0, 0, 110, 55), clip2->VisualOverflowRect()); + + LayoutBox* clip3 = GetLayoutBoxByElementId("clip3"); + EXPECT_FALSE(clip3->IsScrollContainer()); + EXPECT_TRUE(clip3->ShouldClipOverflowAlongBothAxis()); + EXPECT_EQ(LayoutRect(0, 0, 110, 55), clip3->VisualOverflowRect()); } TEST_P(LayoutBoxTest, LayoutOverflowRectWithOverflowClipMargin) { SetBodyInnerHTML(R"HTML( <style> .parent { width: 100px; height: 50px; overflow: clip; } + .parent2 { width: 100px; height: 50px; contain: paint; } .child { position: relative; top: -5px; left: -6px; width: 110px; height: 112px; } </style> @@ -558,6 +568,9 @@ <div id="clip2" style="overflow-clip-margin: 10px" class="parent"> <div class="child"></div> </div> + <div id="clip3" style="overflow-clip-margin: 10px" class="parent2"> + <div class="child"></div> + </div> )HTML"); LayoutBox* clip1 = GetLayoutBoxByElementId("clip1"); @@ -571,6 +584,12 @@ EXPECT_TRUE(clip2->ShouldClipOverflowAlongBothAxis()); EXPECT_EQ(LayoutRect(-6, -5, 110, 65), clip2->LayoutOverflowRectForPropagation(clip2->Parent())); + + LayoutBox* clip3 = GetLayoutBoxByElementId("clip3"); + EXPECT_FALSE(clip3->IsScrollContainer()); + EXPECT_TRUE(clip3->ShouldClipOverflowAlongBothAxis()); + EXPECT_EQ(LayoutRect(-6, -5, 110, 65), + clip3->LayoutOverflowRectForPropagation(clip3->Parent())); } TEST_P(LayoutBoxTest, ContentsVisualOverflowPropagation) {
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc index f68e51fe..2b5982e2 100644 --- a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc
@@ -117,6 +117,7 @@ /* containing_block_expects_minmax_without_percentages */ false, /* skip_collapsed_columns */ false); + // Standard: "used width of the table". LayoutUnit used_table_inline_size = ComputeUsedInlineSizeForTableFragment( space, table, table_border_padding, grid_min_max); @@ -397,18 +398,8 @@ scoped_refptr<const NGLayoutResult> NGTableLayoutAlgorithm::Layout() { DCHECK(!BreakToken()); + const bool is_fixed_layout = Style().IsFixedTableLayout(); - - // TODO(atotic) review autosizer usage in TablesNG. - // Legacy has: - // LayoutTable::UpdateLayout - // TextAutosizer::LayoutScope - // TableLayoutAlgorithmAuto::ComputeIntrinsicLogicalWidths - // TextAutosizer::TableLayoutScope - base::Optional<TextAutosizer::TableLayoutScope> text_autosizer; - if (!is_fixed_layout) - text_autosizer.emplace(To<LayoutNGTable>(Node().GetLayoutBox())); - const LogicalSize border_spacing = Style().TableBorderSpacing(); NGTableGroupedChildren grouped_children(Node()); const scoped_refptr<const NGTableBorders> table_borders = @@ -628,8 +619,6 @@ const PhysicalRect& table_grid_rect, const LogicalSize& border_spacing, const LayoutUnit table_grid_block_size) { - // TODO(atotic) SetHasNonCollapsedBorderDecoration should be a fragment - // property, not a flag on LayoutObject. container_builder_.SetTableGridRect(table_grid_rect); container_builder_.SetTableColumnCount(column_locations.size()); container_builder_.SetHasCollapsedBorders(table_borders.IsCollapsed());
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.cc index c3add42..f00325c 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.cc
@@ -305,11 +305,4 @@ } } -void LayoutSVGResourceClipper::WillBeDestroyed() { - NOT_DESTROYED(); - MarkAllClientsForInvalidation(SVGResourceClient::kClipCacheInvalidation | - SVGResourceClient::kPaintInvalidation); - LayoutSVGResourceContainer::WillBeDestroyed(); -} - } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.h b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.h index b290b60..1f4355e 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.h
@@ -57,11 +57,9 @@ base::Optional<Path> AsPath(); sk_sp<const PaintRecord> CreatePaintRecord(); - protected: - void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override; - void WillBeDestroyed() override; - private: + void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override; + void CalculateLocalClipBounds(); bool FindCycleFromSelf(SVGResourcesCycleSolver&) const override;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc index c3c6fd4..c7091e3 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc
@@ -55,6 +55,37 @@ ClearInvalidationMask(); } +void LayoutSVGResourceContainer::InvalidateClientsIfActiveResource() { + NOT_DESTROYED(); + // If this is the 'active' resource (the first element with the specified 'id' + // in tree order), notify any clients that they need to reevaluate the + // resource's contents. + const LocalSVGResource* resource = ResourceForContainer(*this); + if (!resource || resource->Target() != GetElement()) + return; + // Pass all available flags. This may be performing unnecessary invalidations + // in some cases. + MarkAllClientsForInvalidation(SVGResourceClient::kInvalidateAll); +} + +void LayoutSVGResourceContainer::WillBeDestroyed() { + NOT_DESTROYED(); + // The resource is being torn down. + InvalidateClientsIfActiveResource(); + LayoutSVGHiddenContainer::WillBeDestroyed(); +} + +void LayoutSVGResourceContainer::StyleDidChange( + StyleDifference diff, + const ComputedStyle* old_style) { + NOT_DESTROYED(); + LayoutSVGHiddenContainer::StyleDidChange(diff, old_style); + if (old_style) + return; + // The resource has been attached. + InvalidateClientsIfActiveResource(); +} + bool LayoutSVGResourceContainer::FindCycle( SVGResourcesCycleSolver& solver) const { NOT_DESTROYED();
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.h b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.h index c2020e7..5e18e64 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.h
@@ -97,7 +97,12 @@ static bool FindCycleInSubtree(SVGResourcesCycleSolver&, const LayoutObject& root); + void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override; + void WillBeDestroyed() override; + private: + void InvalidateClientsIfActiveResource(); + // Track global (markAllClientsForInvalidation) invalidations to avoid // redundant crawls. unsigned completed_invalidations_mask_ : 8;
diff --git a/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.cc b/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.cc index 313cc8c..83db543 100644 --- a/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.cc +++ b/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.cc
@@ -52,7 +52,7 @@ out->locked_agent_cluster_id = locked_agent_cluster_id; Vector<PendingRemote<blink::mojom::blink::FileSystemAccessTransferToken>>& - tokens = out->message->NativeFileSystemTokens(); + tokens = out->message->FileSystemAccessTokens(); if (!data.ReadFileSystemAccessTokens(&tokens)) { return false; }
diff --git a/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.h b/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.h index 6e6978a..43dab8a 100644 --- a/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.h +++ b/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.h
@@ -62,7 +62,7 @@ static Vector< mojo::PendingRemote<blink::mojom::blink::FileSystemAccessTransferToken>> file_system_access_tokens(blink::BlinkCloneableMessage& input) { - return std::move(input.message->NativeFileSystemTokens()); + return std::move(input.message->FileSystemAccessTokens()); } static bool Read(blink::mojom::CloneableMessageDataView,
diff --git a/third_party/blink/renderer/core/messaging/blink_transferable_message.cc b/third_party/blink/renderer/core/messaging/blink_transferable_message.cc index 12bd1f45..5408c7d 100644 --- a/third_party/blink/renderer/core/messaging/blink_transferable_message.cc +++ b/third_party/blink/renderer/core/messaging/blink_transferable_message.cc
@@ -108,9 +108,9 @@ std::move(image_bitmap_contents_array)); } - // Native file system transfer tokens. - for (auto& token : serialized_script_value->NativeFileSystemTokens()) { - result.message->NativeFileSystemTokens().push_back(std::move(token)); + // File System Access transfer tokens. + for (auto& token : serialized_script_value->FileSystemAccessTokens()) { + result.message->FileSystemAccessTokens().push_back(std::move(token)); } return result; @@ -192,7 +192,7 @@ // Convert the PendingRemote<FileSystemAccessTransferToken> from the // blink::mojom namespace to the blink::mojom::blink namespace. for (auto& token : message.file_system_access_tokens) { - result.message->NativeFileSystemTokens().push_back( + result.message->FileSystemAccessTokens().push_back( ToCrossVariantMojoType(std::move(token))); } return result;
diff --git a/third_party/blink/renderer/core/style/computed_style_constants.h b/third_party/blink/renderer/core/style/computed_style_constants.h index 2fda3cbc..1811443 100644 --- a/third_party/blink/renderer/core/style/computed_style_constants.h +++ b/third_party/blink/renderer/core/style/computed_style_constants.h
@@ -65,6 +65,8 @@ kPseudoIdSelection, kPseudoIdScrollbar, kPseudoIdTargetText, + kPseudoIdSpellingError, + kPseudoIdGrammarError, // Internal IDs follow: kPseudoIdFirstLineInherited, kPseudoIdScrollbarThumb,
diff --git a/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 b/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 index 1a740b1..48612ba6 100644 --- a/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 +++ b/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
@@ -228,7 +228,7 @@ { name: "PseudoBits", field_template: "primitive", - field_size: 9, + field_size: 11, default_value: "kPseudoIdNone", type_name: "unsigned", custom_copy: true,
diff --git a/third_party/blink/renderer/core/style/computed_style_test.cc b/third_party/blink/renderer/core/style/computed_style_test.cc index 219f8b1..bb184154 100644 --- a/third_party/blink/renderer/core/style/computed_style_test.cc +++ b/third_party/blink/renderer/core/style/computed_style_test.cc
@@ -155,12 +155,12 @@ } TEST(ComputedStyleTest, LastPublicPseudoElementStyle) { - static_assert(kFirstInternalPseudoId - 1 == kPseudoIdTargetText, + static_assert(kFirstInternalPseudoId - 1 == kPseudoIdGrammarError, "Make sure we are testing the last public pseudo id"); scoped_refptr<ComputedStyle> style = ComputedStyle::Create(); - style->SetHasPseudoElementStyle(kPseudoIdTargetText); - EXPECT_TRUE(style->HasPseudoElementStyle(kPseudoIdTargetText)); + style->SetHasPseudoElementStyle(kPseudoIdGrammarError); + EXPECT_TRUE(style->HasPseudoElementStyle(kPseudoIdGrammarError)); EXPECT_TRUE(style->HasAnyPseudoElementStyles()); }
diff --git a/third_party/blink/renderer/core/svg/svg_resource_client.h b/third_party/blink/renderer/core/svg/svg_resource_client.h index 19ab994..0de2357 100644 --- a/third_party/blink/renderer/core/svg/svg_resource_client.h +++ b/third_party/blink/renderer/core/svg/svg_resource_client.h
@@ -28,6 +28,9 @@ kPaintPropertiesInvalidation = 1 << 3, kClipCacheInvalidation = 1 << 4, kFilterCacheInvalidation = 1 << 5, + kInvalidateAll = kLayoutInvalidation | kBoundariesInvalidation | + kPaintInvalidation | kPaintPropertiesInvalidation | + kClipCacheInvalidation | kFilterCacheInvalidation, }; virtual void ResourceContentChanged(InvalidationModeMask) = 0; virtual void ResourceElementChanged() = 0;
diff --git a/third_party/blink/renderer/core/timing/measure_memory/measure_memory_controller.cc b/third_party/blink/renderer/core/timing/measure_memory/measure_memory_controller.cc index 3997607..6d8435f 100644 --- a/third_party/blink/renderer/core/timing/measure_memory/measure_memory_controller.cc +++ b/third_party/blink/renderer/core/timing/measure_memory/measure_memory_controller.cc
@@ -166,7 +166,8 @@ MemoryBreakdownEntry* ConvertBreakdown( const WebMemoryBreakdownEntryPtr& breakdown_entry) { auto* result = MemoryBreakdownEntry::Create(); - result->setBytes(breakdown_entry->bytes); + DCHECK(breakdown_entry->memory); + result->setBytes(breakdown_entry->memory->bytes); HeapVector<Member<MemoryAttribution>> attribution; for (const auto& entry : breakdown_entry->attribution) { attribution.push_back(ConvertAttribution(entry)); @@ -187,7 +188,9 @@ MemoryMeasurement* ConvertResult(const WebMemoryMeasurementPtr& measurement) { HeapVector<Member<MemoryBreakdownEntry>> breakdown; for (const auto& entry : measurement->breakdown) { - breakdown.push_back(ConvertBreakdown(entry)); + // Skip breakdowns that didn't get a measurement. + if (entry->memory) + breakdown.push_back(ConvertBreakdown(entry)); } // Add an empty breakdown entry as required by the spec. // See https://github.com/WICG/performance-measure-memory/issues/10.
diff --git a/third_party/blink/renderer/modules/cookie_store/cookie_change_event.idl b/third_party/blink/renderer/modules/cookie_store/cookie_change_event.idl index 049c5bd..0522d29 100644 --- a/third_party/blink/renderer/modules/cookie_store/cookie_change_event.idl +++ b/third_party/blink/renderer/modules/cookie_store/cookie_change_event.idl
@@ -3,14 +3,13 @@ // found in the LICENSE file. // Used to signal cookie changes to Document contexts. -// https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md +// https://wicg.github.io/cookie-store/explainer.html // // See extendable_cookie_change_event.idl for the equivalent event in // ServiceWorker contexts. [ Exposed=Window, - RuntimeEnabled=CookieStoreDocument, SecureContext ] interface CookieChangeEvent : Event { constructor(DOMString type, optional CookieChangeEventInit eventInitDict = {});
diff --git a/third_party/blink/renderer/modules/cookie_store/cookie_change_event_init.idl b/third_party/blink/renderer/modules/cookie_store/cookie_change_event_init.idl index ebce1f1..6b37d54 100644 --- a/third_party/blink/renderer/modules/cookie_store/cookie_change_event_init.idl +++ b/third_party/blink/renderer/modules/cookie_store/cookie_change_event_init.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md +// https://wicg.github.io/cookie-store/explainer.html dictionary CookieChangeEventInit : EventInit { CookieList changed;
diff --git a/third_party/blink/renderer/modules/cookie_store/cookie_store.idl b/third_party/blink/renderer/modules/cookie_store/cookie_store.idl index b1bb1b83..c617c11 100644 --- a/third_party/blink/renderer/modules/cookie_store/cookie_store.idl +++ b/third_party/blink/renderer/modules/cookie_store/cookie_store.idl
@@ -6,7 +6,6 @@ [ Exposed=(ServiceWorker,Window), - RuntimeEnabled=CookieStoreDocument, SecureContext ] interface CookieStore : EventTarget { // https://wicg.github.io/cookie-store/explainer.html#the-query-api
diff --git a/third_party/blink/renderer/modules/cookie_store/cookie_store_delete_options.idl b/third_party/blink/renderer/modules/cookie_store/cookie_store_delete_options.idl index d3b03cb..a519680 100644 --- a/third_party/blink/renderer/modules/cookie_store/cookie_store_delete_options.idl +++ b/third_party/blink/renderer/modules/cookie_store/cookie_store_delete_options.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md +// https://wicg.github.io/cookie-store/explainer.html dictionary CookieStoreDeleteOptions { required USVString name;
diff --git a/third_party/blink/renderer/modules/cookie_store/cookie_store_get_options.idl b/third_party/blink/renderer/modules/cookie_store/cookie_store_get_options.idl index 1202deb..c199461 100644 --- a/third_party/blink/renderer/modules/cookie_store/cookie_store_get_options.idl +++ b/third_party/blink/renderer/modules/cookie_store/cookie_store_get_options.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md +// https://wicg.github.io/cookie-store/explainer.html dictionary CookieStoreGetOptions { USVString name;
diff --git a/third_party/blink/renderer/modules/cookie_store/cookie_store_manager.idl b/third_party/blink/renderer/modules/cookie_store/cookie_store_manager.idl index 8876f55..e97ebc5 100644 --- a/third_party/blink/renderer/modules/cookie_store/cookie_store_manager.idl +++ b/third_party/blink/renderer/modules/cookie_store/cookie_store_manager.idl
@@ -5,7 +5,7 @@ // https://wicg.github.io/cookie-store/explainer.html#the-change-events-api [ - Exposed(ServiceWorker CookieStoreWorker, Window CookieStoreDocument), + Exposed=(ServiceWorker,Window), SecureContext ] interface CookieStoreManager { [CallWith=ScriptState, MeasureAs=CookieStoreAPI, RaisesException]
diff --git a/third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event.idl b/third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event.idl index 72f5588a..3d2124a 100644 --- a/third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event.idl +++ b/third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event.idl
@@ -3,13 +3,12 @@ // found in the LICENSE file. // Used to signal cookie changes to ServiceWorker contexts. -// https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md +// https://wicg.github.io/cookie-store/explainer.html // // See cookie_change_event.idl for the equivalent event in Document contexts. [ - Exposed=ServiceWorker, - RuntimeEnabled=CookieStoreWorker + Exposed=ServiceWorker ] interface ExtendableCookieChangeEvent : ExtendableEvent { constructor(DOMString type, optional ExtendableCookieChangeEventInit eventInitDict = {}); [
diff --git a/third_party/blink/renderer/modules/cookie_store/service_worker_global_scope_cookie_store.idl b/third_party/blink/renderer/modules/cookie_store/service_worker_global_scope_cookie_store.idl index 72c2d0cc..ccc8e5a 100644 --- a/third_party/blink/renderer/modules/cookie_store/service_worker_global_scope_cookie_store.idl +++ b/third_party/blink/renderer/modules/cookie_store/service_worker_global_scope_cookie_store.idl
@@ -2,10 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md +// https://wicg.github.io/cookie-store/explainer.html [ - RuntimeEnabled=CookieStoreWorker, ImplementedAs=GlobalCookieStore ] partial interface ServiceWorkerGlobalScope { [SameObject] readonly attribute CookieStore cookieStore;
diff --git a/third_party/blink/renderer/modules/cookie_store/service_worker_registration_cookies.idl b/third_party/blink/renderer/modules/cookie_store/service_worker_registration_cookies.idl index d602e4d..151f2c6 100644 --- a/third_party/blink/renderer/modules/cookie_store/service_worker_registration_cookies.idl +++ b/third_party/blink/renderer/modules/cookie_store/service_worker_registration_cookies.idl
@@ -4,7 +4,6 @@ [ Exposed=(ServiceWorker,Window), - RuntimeEnabled=CookieStoreWorker, ImplementedAs=CookieStoreManager ] partial interface ServiceWorkerRegistration { [SameObject] readonly attribute CookieStoreManager cookies;
diff --git a/third_party/blink/renderer/modules/cookie_store/window_cookie_store.idl b/third_party/blink/renderer/modules/cookie_store/window_cookie_store.idl index c86f9a4f..6882018 100644 --- a/third_party/blink/renderer/modules/cookie_store/window_cookie_store.idl +++ b/third_party/blink/renderer/modules/cookie_store/window_cookie_store.idl
@@ -2,10 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md +// https://wicg.github.io/cookie-store/explainer.html [ - RuntimeEnabled=CookieStoreDocument, ImplementedAs=GlobalCookieStore, SecureContext ] partial interface Window {
diff --git a/third_party/blink/renderer/modules/csspaint/background_color_paint_worklet.cc b/third_party/blink/renderer/modules/csspaint/background_color_paint_worklet.cc index e567f7e..4fbe937d 100644 --- a/third_party/blink/renderer/modules/csspaint/background_color_paint_worklet.cc +++ b/third_party/blink/renderer/modules/csspaint/background_color_paint_worklet.cc
@@ -5,6 +5,7 @@ #include "third_party/blink/renderer/modules/csspaint/background_color_paint_worklet.h" #include "third_party/blink/renderer/core/animation/animation_effect.h" +#include "third_party/blink/renderer/core/animation/css/compositor_keyframe_double.h" #include "third_party/blink/renderer/core/animation/css_color_interpolation_type.h" #include "third_party/blink/renderer/core/animation/element_animations.h" #include "third_party/blink/renderer/core/css/css_color_value.h" @@ -29,16 +30,20 @@ const FloatSize& container_size, int worklet_id, const Vector<Color>& animated_colors, + const Vector<double>& offsets, cc::PaintWorkletInput::PropertyKeys property_keys) : PaintWorkletInput(container_size, worklet_id, std::move(property_keys)), - animated_colors_(animated_colors) {} + animated_colors_(animated_colors), + offsets_(offsets) {} ~BackgroundColorPaintWorkletInput() override = default; const Vector<Color>& AnimatedColors() const { return animated_colors_; } + const Vector<double>& Offsets() const { return offsets_; } private: Vector<Color> animated_colors_; + Vector<double> offsets_; }; class BackgroundColorPaintWorkletProxyClient @@ -64,18 +69,39 @@ static_cast<const BackgroundColorPaintWorkletInput*>(compositor_input); FloatSize container_size = input->ContainerSize(); Vector<Color> animated_colors = input->AnimatedColors(); + Vector<double> offsets = input->Offsets(); DCHECK_GT(animated_colors.size(), 1u); + DCHECK_EQ(animated_colors.size(), offsets.size()); DCHECK_EQ(animated_property_values.size(), 1u); const auto& entry = animated_property_values.begin(); float progress = entry->second.float_value.value(); + + // Get the start and end color based on the progress and offsets. + DCHECK_EQ(offsets.front(), 0); + DCHECK_EQ(offsets.back(), 1); + unsigned result_index = -1; + for (unsigned i = 0; i < offsets.size() - 1; i++) { + if (progress <= offsets[i + 1]) { + result_index = i; + break; + } + } + DCHECK_GE(result_index, 0u); + // Because the progress is a global one, we need to adjust it with offsets. + float adjusted_progress = + (progress - offsets[result_index]) / + (offsets[result_index + 1] - offsets[result_index]); std::unique_ptr<InterpolableValue> from = - CSSColorInterpolationType::CreateInterpolableColor(animated_colors[0]); + CSSColorInterpolationType::CreateInterpolableColor( + animated_colors[result_index]); std::unique_ptr<InterpolableValue> to = - CSSColorInterpolationType::CreateInterpolableColor(animated_colors[1]); + CSSColorInterpolationType::CreateInterpolableColor( + animated_colors[result_index + 1]); std::unique_ptr<InterpolableValue> result = - CSSColorInterpolationType::CreateInterpolableColor(animated_colors[1]); - from->Interpolate(*to, progress, *result); + CSSColorInterpolationType::CreateInterpolableColor( + animated_colors[result_index + 1]); + from->Interpolate(*to, adjusted_progress, *result); Color rgba = CSSColorInterpolationType::GetRGBA(*(result.get())); SkColor current_color = static_cast<SkColor>(rgba); @@ -88,6 +114,7 @@ } }; +// TODO(crbug.com/1163949): Support animation keyframes without 0% or 100%. void GetColorsFromStringKeyframe(const PropertySpecificKeyframe* frame, Vector<Color>* animated_colors, const Element* element) { @@ -103,6 +130,13 @@ animated_colors->push_back(color_value->Value()); } +void GetCompositorKeyframeOffset(const PropertySpecificKeyframe* frame, + Vector<double>* offsets) { + const CompositorKeyframeDouble& value = + To<CompositorKeyframeDouble>(*(frame->GetCompositorKeyframeValue())); + offsets->push_back(value.ToDouble()); +} + void GetColorsFromTransitionKeyframe(const PropertySpecificKeyframe* frame, Vector<Color>* animated_colors, const Element* element) { @@ -140,6 +174,7 @@ const Node* node) { DCHECK(node->IsElementNode()); Vector<Color> animated_colors; + Vector<double> offsets; const Element* element = static_cast<const Element*>(node); ElementAnimations* element_animations = element->GetElementAnimations(); // TODO(crbug.com/1153672): implement main-thread fall back logic for @@ -154,16 +189,12 @@ model->GetPropertySpecificKeyframes( PropertyHandle(GetCSSPropertyBackgroundColor())); DCHECK_GE(frames->size(), 2u); - // TODO(crbug.com/1153671): right now we keep the first and last keyframe - // values only, we need to keep all keyframe values. - if (model->IsStringKeyframeEffectModel()) { - GetColorsFromStringKeyframe(frames->front(), &animated_colors, element); - GetColorsFromStringKeyframe(frames->back(), &animated_colors, element); - } else { - GetColorsFromTransitionKeyframe(frames->front(), &animated_colors, - element); - GetColorsFromTransitionKeyframe(frames->back(), &animated_colors, - element); + for (const auto& frame : *frames) { + if (model->IsStringKeyframeEffectModel()) + GetColorsFromStringKeyframe(frame, &animated_colors, element); + else + GetColorsFromTransitionKeyframe(frame, &animated_colors, element); + GetCompositorKeyframeOffset(frame, &offsets); } } @@ -178,7 +209,7 @@ element_id); scoped_refptr<BackgroundColorPaintWorkletInput> input = base::MakeRefCounted<BackgroundColorPaintWorkletInput>( - container_size, worklet_id_, animated_colors, + container_size, worklet_id_, animated_colors, offsets, std::move(input_property_keys)); return PaintWorkletDeferredImage::Create(std::move(input), container_size); }
diff --git a/third_party/blink/renderer/modules/exported/BUILD.gn b/third_party/blink/renderer/modules/exported/BUILD.gn index b9ffc21..e48fb21 100644 --- a/third_party/blink/renderer/modules/exported/BUILD.gn +++ b/third_party/blink/renderer/modules/exported/BUILD.gn
@@ -31,6 +31,7 @@ deps = [ "//skia", "//third_party/blink/renderer/bindings/modules/v8:testing", + "//third_party/blink/renderer/core", "//third_party/blink/renderer/core:testing", "//third_party/blink/renderer/modules:modules_testing", "//third_party/blink/renderer/platform",
diff --git a/third_party/blink/renderer/modules/exported/web_testing_support.cc b/third_party/blink/renderer/modules/exported/web_testing_support.cc index f31bd370..b553315 100644 --- a/third_party/blink/renderer/modules/exported/web_testing_support.cc +++ b/third_party/blink/renderer/modules/exported/web_testing_support.cc
@@ -25,7 +25,8 @@ #include "third_party/blink/public/web/web_testing_support.h" -#include "third_party/blink/public/web/web_local_frame.h" +#include "third_party/blink/renderer/bindings/core/v8/window_proxy_manager.h" +#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" #include "third_party/blink/renderer/core/testing/scoped_mock_overlay_scrollbars.h" #include "third_party/blink/renderer/core/testing/v8/web_core_test_support.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" @@ -108,9 +109,14 @@ web_core_test_support::InjectInternalsObject(context); } -void WebTestingSupport::ResetInternalsObject(WebLocalFrame* frame) { +void WebTestingSupport::ResetMainFrame(WebLocalFrame* main_frame) { + auto* main_frame_impl = To<WebLocalFrameImpl>(main_frame); v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); - web_core_test_support::ResetInternalsObject(frame->MainWorldScriptContext()); + web_core_test_support::ResetInternalsObject( + main_frame_impl->MainWorldScriptContext()); + main_frame_impl->GetFrame() + ->GetWindowProxyManager() + ->ResetIsolatedWorldsForTesting(); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/file_system_access/BUILD.gn b/third_party/blink/renderer/modules/file_system_access/BUILD.gn index 38f13af..6727d5d 100644 --- a/third_party/blink/renderer/modules/file_system_access/BUILD.gn +++ b/third_party/blink/renderer/modules/file_system_access/BUILD.gn
@@ -6,26 +6,26 @@ blink_modules_sources("file_system_access") { sources = [ - "data_transfer_item_native_file_system.cc", - "data_transfer_item_native_file_system.h", - "global_native_file_system.cc", - "global_native_file_system.h", - "native_file_system_directory_handle.cc", - "native_file_system_directory_handle.h", - "native_file_system_directory_iterator.cc", - "native_file_system_directory_iterator.h", - "native_file_system_error.cc", - "native_file_system_error.h", - "native_file_system_file_handle.cc", - "native_file_system_file_handle.h", - "native_file_system_handle.cc", - "native_file_system_handle.h", - "native_file_system_underlying_sink.cc", - "native_file_system_underlying_sink.h", - "native_file_system_writable_file_stream.cc", - "native_file_system_writable_file_stream.h", - "storage_manager_native_file_system.cc", - "storage_manager_native_file_system.h", + "data_transfer_item_file_system_access.cc", + "data_transfer_item_file_system_access.h", + "file_system_access_error.cc", + "file_system_access_error.h", + "file_system_directory_handle.cc", + "file_system_directory_handle.h", + "file_system_directory_iterator.cc", + "file_system_directory_iterator.h", + "file_system_file_handle.cc", + "file_system_file_handle.h", + "file_system_handle.cc", + "file_system_handle.h", + "file_system_underlying_sink.cc", + "file_system_underlying_sink.h", + "file_system_writable_file_stream.cc", + "file_system_writable_file_stream.h", + "global_file_system_access.cc", + "global_file_system_access.h", + "storage_manager_file_system_access.cc", + "storage_manager_file_system_access.h", ] deps = [ "//third_party/blink/renderer/platform" ] @@ -33,7 +33,7 @@ source_set("unit_tests") { testonly = true - sources = [ "global_native_file_system_test.cc" ] + sources = [ "global_file_system_access_test.cc" ] configs += [ "//third_party/blink/renderer:config",
diff --git a/third_party/blink/renderer/modules/file_system_access/data_transfer_item_native_file_system.cc b/third_party/blink/renderer/modules/file_system_access/data_transfer_item_file_system_access.cc similarity index 93% rename from third_party/blink/renderer/modules/file_system_access/data_transfer_item_native_file_system.cc rename to third_party/blink/renderer/modules/file_system_access/data_transfer_item_file_system_access.cc index b370f56..3e54366 100644 --- a/third_party/blink/renderer/modules/file_system_access/data_transfer_item_native_file_system.cc +++ b/third_party/blink/renderer/modules/file_system_access/data_transfer_item_file_system_access.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/blink/renderer/modules/file_system_access/data_transfer_item_native_file_system.h" +#include "third_party/blink/renderer/modules/file_system_access/data_transfer_item_file_system_access.h" #include "mojo/public/cpp/bindings/remote.h" #include "third_party/blink/public/common/browser_interface_broker_proxy.h" @@ -18,9 +18,9 @@ #include "third_party/blink/renderer/core/clipboard/data_transfer.h" #include "third_party/blink/renderer/core/clipboard/data_transfer_item.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_directory_handle.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_error.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_file_handle.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_access_error.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_file_handle.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/wtf/functional.h" @@ -29,7 +29,7 @@ namespace blink { // static -ScriptPromise DataTransferItemNativeFileSystem::getAsFileSystemHandle( +ScriptPromise DataTransferItemFileSystemAccess::getAsFileSystemHandle( ScriptState* script_state, DataTransferItem& data_transfer_item) { if (!data_transfer_item.GetDataTransfer()->CanReadData()) { @@ -72,7 +72,7 @@ ScriptState* script_state = resolver->GetScriptState(); if (!script_state) return; - resolver->Resolve(NativeFileSystemHandle::CreateFromMojoEntry( + resolver->Resolve(FileSystemHandle::CreateFromMojoEntry( std::move(entry), ExecutionContext::From(script_state))); }, std::move(nfs_manager), WrapPersistent(resolver)));
diff --git a/third_party/blink/renderer/modules/file_system_access/data_transfer_item_native_file_system.h b/third_party/blink/renderer/modules/file_system_access/data_transfer_item_file_system_access.h similarity index 76% rename from third_party/blink/renderer/modules/file_system_access/data_transfer_item_native_file_system.h rename to third_party/blink/renderer/modules/file_system_access/data_transfer_item_file_system_access.h index e917182..6db9014 100644 --- a/third_party/blink/renderer/modules/file_system_access/data_transfer_item_native_file_system.h +++ b/third_party/blink/renderer/modules/file_system_access/data_transfer_item_file_system_access.h
@@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_DATA_TRANSFER_ITEM_NATIVE_FILE_SYSTEM_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_DATA_TRANSFER_ITEM_NATIVE_FILE_SYSTEM_H_ +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_DATA_TRANSFER_ITEM_FILE_SYSTEM_ACCESS_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_DATA_TRANSFER_ITEM_FILE_SYSTEM_ACCESS_H_ #include "third_party/blink/renderer/core/clipboard/data_transfer_item.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_handle.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_handle.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" namespace blink { -class DataTransferItemNativeFileSystem { - STATIC_ONLY(DataTransferItemNativeFileSystem); +class DataTransferItemFileSystemAccess { + STATIC_ONLY(DataTransferItemFileSystemAccess); public: static ScriptPromise getAsFileSystemHandle(ScriptState*, DataTransferItem&); @@ -21,4 +21,4 @@ } // namespace blink -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_DATA_TRANSFER_ITEM_NATIVE_FILE_SYSTEM_H_ +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_DATA_TRANSFER_ITEM_FILE_SYSTEM_ACCESS_H_
diff --git a/third_party/blink/renderer/modules/file_system_access/data_transfer_item_file_system_access.idl b/third_party/blink/renderer/modules/file_system_access/data_transfer_item_file_system_access.idl new file mode 100644 index 0000000..a34eae0 --- /dev/null +++ b/third_party/blink/renderer/modules/file_system_access/data_transfer_item_file_system_access.idl
@@ -0,0 +1,11 @@ +// Copyright 2020 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. + +[ + ImplementedAs=DataTransferItemFileSystemAccess, + RuntimeEnabled=FileSystemAccess +] partial interface DataTransferItem { + [CallWith=ScriptState, MeasureAs=FileSystemAccessDragAndDrop] + Promise<FileSystemHandle?> getAsFileSystemHandle(); +};
diff --git a/third_party/blink/renderer/modules/file_system_access/data_transfer_item_native_file_system.idl b/third_party/blink/renderer/modules/file_system_access/data_transfer_item_native_file_system.idl deleted file mode 100644 index 48a9f1d..0000000 --- a/third_party/blink/renderer/modules/file_system_access/data_transfer_item_native_file_system.idl +++ /dev/null
@@ -1,10 +0,0 @@ -// Copyright 2020 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. - -[ - ImplementedAs=DataTransferItemNativeFileSystem, - RuntimeEnabled=NativeFileSystem -] partial interface DataTransferItem { - [CallWith=ScriptState, MeasureAs=NativeFileSystemDragAndDrop] Promise<FileSystemHandle?> getAsFileSystemHandle(); -};
diff --git a/third_party/blink/renderer/modules/file_system_access/directory_picker_options.idl b/third_party/blink/renderer/modules/file_system_access/directory_picker_options.idl index c6160d5e..1f6af0e 100644 --- a/third_party/blink/renderer/modules/file_system_access/directory_picker_options.idl +++ b/third_party/blink/renderer/modules/file_system_access/directory_picker_options.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://wicg.github.io/native-file-system/#dictdef-directorypickeroptions +// https://wicg.github.io/file-system-access/#dictdef-directorypickeroptions dictionary DirectoryPickerOptions { [RuntimeEnabled=FileSystemAccessAPIExperimental] CommonDirectory? startIn; };
diff --git a/third_party/blink/renderer/modules/file_system_access/file_picker_accept_type.idl b/third_party/blink/renderer/modules/file_system_access/file_picker_accept_type.idl index dc3f822..9dfee44 100644 --- a/third_party/blink/renderer/modules/file_system_access/file_picker_accept_type.idl +++ b/third_party/blink/renderer/modules/file_system_access/file_picker_accept_type.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://wicg.github.io/native-file-system/#dictdef-filepickeraccepttype +// https://wicg.github.io/file-system-access/#dictdef-filepickeraccepttype dictionary FilePickerAcceptType { USVString description; record<USVString, (USVString or sequence<USVString>)> accept;
diff --git a/third_party/blink/renderer/modules/file_system_access/file_picker_options.idl b/third_party/blink/renderer/modules/file_system_access/file_picker_options.idl index 3156525..3279e8a 100644 --- a/third_party/blink/renderer/modules/file_system_access/file_picker_options.idl +++ b/third_party/blink/renderer/modules/file_system_access/file_picker_options.idl
@@ -12,7 +12,7 @@ "videos", }; -// https://wicg.github.io/native-file-system/#dictdef-filepickeroptions +// https://wicg.github.io/file-system-access/#dictdef-filepickeroptions dictionary FilePickerOptions { sequence<FilePickerAcceptType> types; boolean excludeAcceptAllOption = false;
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_error.cc b/third_party/blink/renderer/modules/file_system_access/file_system_access_error.cc similarity index 96% rename from third_party/blink/renderer/modules/file_system_access/native_file_system_error.cc rename to third_party/blink/renderer/modules/file_system_access/file_system_access_error.cc index 128f63a..541a2355 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_error.cc +++ b/third_party/blink/renderer/modules/file_system_access/file_system_access_error.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_error.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_access_error.h" #include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" @@ -13,7 +13,7 @@ #include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { -namespace native_file_system_error { +namespace file_system_access_error { void Reject(ScriptPromiseResolver* resolver, const mojom::blink::FileSystemAccessError& error) { @@ -65,5 +65,5 @@ } } -} // namespace native_file_system_error +} // namespace file_system_access_error } // namespace blink
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_error.h b/third_party/blink/renderer/modules/file_system_access/file_system_access_error.h similarity index 76% rename from third_party/blink/renderer/modules/file_system_access/native_file_system_error.h rename to third_party/blink/renderer/modules/file_system_access/file_system_access_error.h index caa5d2e70f..5165fee2 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_error.h +++ b/third_party/blink/renderer/modules/file_system_access/file_system_access_error.h
@@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_ERROR_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_ERROR_H_ +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_ERROR_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_ERROR_H_ #include "base/files/file.h" #include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom-blink-forward.h" namespace blink { class ScriptPromiseResolver; -namespace native_file_system_error { +namespace file_system_access_error { // Rejects |resolver| with an appropriate exception if |status| represents an // error. Resolves |resolver| with undefined otherwise. @@ -22,7 +22,7 @@ void Reject(ScriptPromiseResolver* resolver, const mojom::blink::FileSystemAccessError& error); -} // namespace native_file_system_error +} // namespace file_system_access_error } // namespace blink -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_ERROR_H_ +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_ERROR_H_
diff --git a/third_party/blink/renderer/modules/file_system_access/file_system_create_writer_options.idl b/third_party/blink/renderer/modules/file_system_access/file_system_create_writer_options.idl index 4897040..5e9d8a4 100644 --- a/third_party/blink/renderer/modules/file_system_access/file_system_create_writer_options.idl +++ b/third_party/blink/renderer/modules/file_system_access/file_system_create_writer_options.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://wicg.github.io/native-file-system/#dictdef-filesystemcreatewriteroptions +// https://wicg.github.io/file-system-access/#dictdef-filesystemcreatewriteroptions dictionary FileSystemCreateWriterOptions { boolean keepExistingData = false; [RuntimeEnabled=FileSystemAccessAPIExperimental] boolean autoClose = false;
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_handle.cc b/third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.cc similarity index 78% rename from third_party/blink/renderer/modules/file_system_access/native_file_system_directory_handle.cc rename to third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.cc index ca377b0c..571df52 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_handle.cc +++ b/third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_directory_handle.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/remote.h" @@ -19,9 +19,9 @@ #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/execution_context/security_context.h" #include "third_party/blink/renderer/core/fileapi/file_error.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_directory_iterator.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_error.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_file_handle.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_access_error.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_directory_iterator.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_file_handle.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/weborigin/security_origin.h" #include "third_party/blink/renderer/platform/wtf/functional.h" @@ -30,35 +30,33 @@ using mojom::blink::FileSystemAccessErrorPtr; -NativeFileSystemDirectoryHandle::NativeFileSystemDirectoryHandle( +FileSystemDirectoryHandle::FileSystemDirectoryHandle( ExecutionContext* context, const String& name, mojo::PendingRemote<mojom::blink::FileSystemAccessDirectoryHandle> mojo_ptr) - : NativeFileSystemHandle(context, name), mojo_ptr_(context) { + : FileSystemHandle(context, name), mojo_ptr_(context) { mojo_ptr_.Bind(std::move(mojo_ptr), context->GetTaskRunner(TaskType::kMiscPlatformAPI)); DCHECK(mojo_ptr_.is_bound()); } -NativeFileSystemDirectoryIterator* NativeFileSystemDirectoryHandle::entries() { - return MakeGarbageCollected<NativeFileSystemDirectoryIterator>( - this, NativeFileSystemDirectoryIterator::Mode::kKeyValue, +FileSystemDirectoryIterator* FileSystemDirectoryHandle::entries() { + return MakeGarbageCollected<FileSystemDirectoryIterator>( + this, FileSystemDirectoryIterator::Mode::kKeyValue, GetExecutionContext()); } -NativeFileSystemDirectoryIterator* NativeFileSystemDirectoryHandle::keys() { - return MakeGarbageCollected<NativeFileSystemDirectoryIterator>( - this, NativeFileSystemDirectoryIterator::Mode::kKey, - GetExecutionContext()); +FileSystemDirectoryIterator* FileSystemDirectoryHandle::keys() { + return MakeGarbageCollected<FileSystemDirectoryIterator>( + this, FileSystemDirectoryIterator::Mode::kKey, GetExecutionContext()); } -NativeFileSystemDirectoryIterator* NativeFileSystemDirectoryHandle::values() { - return MakeGarbageCollected<NativeFileSystemDirectoryIterator>( - this, NativeFileSystemDirectoryIterator::Mode::kValue, - GetExecutionContext()); +FileSystemDirectoryIterator* FileSystemDirectoryHandle::values() { + return MakeGarbageCollected<FileSystemDirectoryIterator>( + this, FileSystemDirectoryIterator::Mode::kValue, GetExecutionContext()); } -ScriptPromise NativeFileSystemDirectoryHandle::getFileHandle( +ScriptPromise FileSystemDirectoryHandle::getFileHandle( ScriptState* script_state, const String& name, const FileSystemGetFileOptions* options) { @@ -76,10 +74,10 @@ if (!context) return; if (result->status != mojom::blink::FileSystemAccessStatus::kOk) { - native_file_system_error::Reject(resolver, *result); + file_system_access_error::Reject(resolver, *result); return; } - resolver->Resolve(MakeGarbageCollected<NativeFileSystemFileHandle>( + resolver->Resolve(MakeGarbageCollected<FileSystemFileHandle>( context, name, std::move(handle))); }, WrapPersistent(resolver), name)); @@ -87,7 +85,7 @@ return result; } -ScriptPromise NativeFileSystemDirectoryHandle::getDirectoryHandle( +ScriptPromise FileSystemDirectoryHandle::getDirectoryHandle( ScriptState* script_state, const String& name, const FileSystemGetDirectoryOptions* options) { @@ -111,12 +109,11 @@ if (!context) return; if (result->status != mojom::blink::FileSystemAccessStatus::kOk) { - native_file_system_error::Reject(resolver, *result); + file_system_access_error::Reject(resolver, *result); return; } - resolver->Resolve( - MakeGarbageCollected<NativeFileSystemDirectoryHandle>( - context, name, std::move(handle))); + resolver->Resolve(MakeGarbageCollected<FileSystemDirectoryHandle>( + context, name, std::move(handle))); }, WrapPersistent(resolver), name)); @@ -131,10 +128,9 @@ } // namespace -ScriptValue NativeFileSystemDirectoryHandle::getEntries( - ScriptState* script_state) { - auto* iterator = MakeGarbageCollected<NativeFileSystemDirectoryIterator>( - this, NativeFileSystemDirectoryIterator::Mode::kValue, +ScriptValue FileSystemDirectoryHandle::getEntries(ScriptState* script_state) { + auto* iterator = MakeGarbageCollected<FileSystemDirectoryIterator>( + this, FileSystemDirectoryIterator::Mode::kValue, ExecutionContext::From(script_state)); auto* isolate = script_state->GetIsolate(); auto context = script_state->GetContext(); @@ -150,7 +146,7 @@ return ScriptValue(script_state->GetIsolate(), result); } -ScriptPromise NativeFileSystemDirectoryHandle::removeEntry( +ScriptPromise FileSystemDirectoryHandle::removeEntry( ScriptState* script_state, const String& name, const FileSystemRemoveOptions* options) { @@ -167,16 +163,16 @@ name, options->recursive(), WTF::Bind( [](ScriptPromiseResolver* resolver, FileSystemAccessErrorPtr result) { - native_file_system_error::ResolveOrReject(resolver, *result); + file_system_access_error::ResolveOrReject(resolver, *result); }, WrapPersistent(resolver))); return result; } -ScriptPromise NativeFileSystemDirectoryHandle::resolve( +ScriptPromise FileSystemDirectoryHandle::resolve( ScriptState* script_state, - NativeFileSystemHandle* possible_child) { + FileSystemHandle* possible_child) { auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); ScriptPromise result = resolver->Promise(); @@ -192,7 +188,7 @@ [](ScriptPromiseResolver* resolver, FileSystemAccessErrorPtr result, const base::Optional<Vector<String>>& path) { if (result->status != mojom::blink::FileSystemAccessStatus::kOk) { - native_file_system_error::Reject(resolver, *result); + file_system_access_error::Reject(resolver, *result); return; } if (!path.has_value()) { @@ -207,19 +203,19 @@ } mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> -NativeFileSystemDirectoryHandle::Transfer() { +FileSystemDirectoryHandle::Transfer() { mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> result; if (mojo_ptr_.is_bound()) mojo_ptr_->Transfer(result.InitWithNewPipeAndPassReceiver()); return result; } -void NativeFileSystemDirectoryHandle::Trace(Visitor* visitor) const { +void FileSystemDirectoryHandle::Trace(Visitor* visitor) const { visitor->Trace(mojo_ptr_); - NativeFileSystemHandle::Trace(visitor); + FileSystemHandle::Trace(visitor); } -void NativeFileSystemDirectoryHandle::QueryPermissionImpl( +void FileSystemDirectoryHandle::QueryPermissionImpl( bool writable, base::OnceCallback<void(mojom::blink::PermissionStatus)> callback) { if (!mojo_ptr_.is_bound()) { @@ -229,7 +225,7 @@ mojo_ptr_->GetPermissionStatus(writable, std::move(callback)); } -void NativeFileSystemDirectoryHandle::RequestPermissionImpl( +void FileSystemDirectoryHandle::RequestPermissionImpl( bool writable, base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr, mojom::blink::PermissionStatus)> callback) { @@ -245,7 +241,7 @@ mojo_ptr_->RequestPermission(writable, std::move(callback)); } -void NativeFileSystemDirectoryHandle::IsSameEntryImpl( +void FileSystemDirectoryHandle::IsSameEntryImpl( mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> other, base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr, bool)> callback) {
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_handle.h b/third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.h similarity index 79% rename from third_party/blink/renderer/modules/file_system_access/native_file_system_directory_handle.h rename to third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.h index 6f0fd14..0ade0d7 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_handle.h +++ b/third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.h
@@ -2,33 +2,33 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_DIRECTORY_HANDLE_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_DIRECTORY_HANDLE_H_ +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_DIRECTORY_HANDLE_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_DIRECTORY_HANDLE_H_ #include "mojo/public/cpp/bindings/pending_remote.h" #include "third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom-blink.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_handle.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_handle.h" #include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" namespace blink { class FileSystemGetDirectoryOptions; class FileSystemGetFileOptions; class FileSystemRemoveOptions; -class NativeFileSystemDirectoryIterator; +class FileSystemDirectoryIterator; -class NativeFileSystemDirectoryHandle final : public NativeFileSystemHandle { +class FileSystemDirectoryHandle final : public FileSystemHandle { DEFINE_WRAPPERTYPEINFO(); public: - NativeFileSystemDirectoryHandle( + FileSystemDirectoryHandle( ExecutionContext* context, const String& name, mojo::PendingRemote<mojom::blink::FileSystemAccessDirectoryHandle>); // FileSystemDirectoryHandle IDL interface: - NativeFileSystemDirectoryIterator* entries(); - NativeFileSystemDirectoryIterator* keys(); - NativeFileSystemDirectoryIterator* values(); + FileSystemDirectoryIterator* entries(); + FileSystemDirectoryIterator* keys(); + FileSystemDirectoryIterator* values(); bool isDirectory() const override { return true; } @@ -43,7 +43,7 @@ const String& name, const FileSystemRemoveOptions*); - ScriptPromise resolve(ScriptState*, NativeFileSystemHandle* possible_child); + ScriptPromise resolve(ScriptState*, FileSystemHandle* possible_child); mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> Transfer() override; @@ -74,4 +74,4 @@ } // namespace blink -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_DIRECTORY_HANDLE_H_ +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_DIRECTORY_HANDLE_H_
diff --git a/third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.idl b/third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.idl index c63eac8..bf18156 100644 --- a/third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.idl +++ b/third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.idl
@@ -2,21 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://wicg.github.io/native-file-system/#filesystemdirectoryhandle +// https://wicg.github.io/file-system-access/#filesystemdirectoryhandle [ Exposed=(Window,Worker), SecureContext, Serializable, - RuntimeEnabled=NativeFileSystem, - ImplementedAs=NativeFileSystemDirectoryHandle + RuntimeEnabled=FileSystemAccess ] interface FileSystemDirectoryHandle : FileSystemHandle { // TODO(https://crbug.com/1087157): This interface defines an async // iterable, however that isn't supported yet by the bindings. So for now // just explicitly define what an async iterable definition implies. //async iterable<USVString, FileSystemHandle>; - NativeFileSystemDirectoryIterator entries(); - NativeFileSystemDirectoryIterator keys(); - NativeFileSystemDirectoryIterator values(); + FileSystemDirectoryIterator entries(); + FileSystemDirectoryIterator keys(); + FileSystemDirectoryIterator values(); [CallWith=ScriptState] Promise<FileSystemFileHandle> getFileHandle(USVString name, optional FileSystemGetFileOptions options = {}); [CallWith=ScriptState] Promise<FileSystemDirectoryHandle> getDirectoryHandle(USVString name, optional FileSystemGetDirectoryOptions options = {});
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_iterator.cc b/third_party/blink/renderer/modules/file_system_access/file_system_directory_iterator.cc similarity index 80% rename from third_party/blink/renderer/modules/file_system_access/native_file_system_directory_iterator.cc rename to third_party/blink/renderer/modules/file_system_access/file_system_directory_iterator.cc index 70e7e11..69d8970 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_iterator.cc +++ b/third_party/blink/renderer/modules/file_system_access/file_system_directory_iterator.cc
@@ -2,22 +2,22 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_directory_iterator.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_directory_iterator.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/fileapi/file_error.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_directory_handle.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_error.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_file_handle.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_access_error.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_file_handle.h" #include "third_party/blink/renderer/platform/wtf/functional.h" namespace blink { -NativeFileSystemDirectoryIterator::NativeFileSystemDirectoryIterator( - NativeFileSystemDirectoryHandle* directory, +FileSystemDirectoryIterator::FileSystemDirectoryIterator( + FileSystemDirectoryHandle* directory, Mode mode, ExecutionContext* execution_context) : ExecutionContextClient(execution_context), @@ -28,17 +28,16 @@ execution_context->GetTaskRunner(TaskType::kMiscPlatformAPI))); } -ScriptPromise NativeFileSystemDirectoryIterator::next( - ScriptState* script_state) { +ScriptPromise FileSystemDirectoryIterator::next(ScriptState* script_state) { if (error_) { auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); auto result = resolver->Promise(); - native_file_system_error::Reject(resolver, *error_); + file_system_access_error::Reject(resolver, *error_); return result; } if (!entries_.IsEmpty()) { - NativeFileSystemHandle* handle = entries_.TakeFirst(); + FileSystemHandle* handle = entries_.TakeFirst(); ScriptValue result; switch (mode_) { case Mode::kKey: @@ -68,11 +67,11 @@ return ScriptPromise::Cast(script_state, V8IteratorResultDone(script_state)); } -bool NativeFileSystemDirectoryIterator::HasPendingActivity() const { +bool FileSystemDirectoryIterator::HasPendingActivity() const { return pending_next_; } -void NativeFileSystemDirectoryIterator::Trace(Visitor* visitor) const { +void FileSystemDirectoryIterator::Trace(Visitor* visitor) const { ScriptWrappable::Trace(visitor); ExecutionContextClient::Trace(visitor); visitor->Trace(receiver_); @@ -81,7 +80,7 @@ visitor->Trace(directory_); } -void NativeFileSystemDirectoryIterator::DidReadDirectory( +void FileSystemDirectoryIterator::DidReadDirectory( mojom::blink::FileSystemAccessErrorPtr result, Vector<mojom::blink::FileSystemAccessEntryPtr> entries, bool has_more_entries) { @@ -90,13 +89,13 @@ if (result->status != mojom::blink::FileSystemAccessStatus::kOk) { error_ = std::move(result); if (pending_next_) { - native_file_system_error::Reject(pending_next_, *error_); + file_system_access_error::Reject(pending_next_, *error_); pending_next_ = nullptr; } return; } for (auto& e : entries) { - entries_.push_back(NativeFileSystemHandle::CreateFromMojoEntry( + entries_.push_back(FileSystemHandle::CreateFromMojoEntry( std::move(e), GetExecutionContext())); } waiting_for_more_entries_ = has_more_entries;
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_iterator.h b/third_party/blink/renderer/modules/file_system_access/file_system_directory_iterator.h similarity index 71% rename from third_party/blink/renderer/modules/file_system_access/native_file_system_directory_iterator.h rename to third_party/blink/renderer/modules/file_system_access/file_system_directory_iterator.h index 05b9003f..c1dca83 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_iterator.h +++ b/third_party/blink/renderer/modules/file_system_access/file_system_directory_iterator.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_DIRECTORY_ITERATOR_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_DIRECTORY_ITERATOR_H_ +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_DIRECTORY_ITERATOR_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_DIRECTORY_ITERATOR_H_ #include "base/files/file.h" #include "third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom-blink.h" @@ -15,15 +15,15 @@ #include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h" namespace blink { -class NativeFileSystemDirectoryHandle; -class NativeFileSystemHandle; +class FileSystemDirectoryHandle; +class FileSystemHandle; class ScriptPromise; class ScriptPromiseResolver; class ScriptState; -class NativeFileSystemDirectoryIterator final +class FileSystemDirectoryIterator final : public ScriptWrappable, - public ActiveScriptWrappable<NativeFileSystemDirectoryIterator>, + public ActiveScriptWrappable<FileSystemDirectoryIterator>, public ExecutionContextClient, public mojom::blink::FileSystemAccessDirectoryEntriesListener { DEFINE_WRAPPERTYPEINFO(); @@ -32,9 +32,9 @@ // Should this iterator returns keys, values or both? enum Mode { kKey, kValue, kKeyValue }; - NativeFileSystemDirectoryIterator(NativeFileSystemDirectoryHandle* directory, - Mode mode, - ExecutionContext* execution_context); + FileSystemDirectoryIterator(FileSystemDirectoryHandle* directory, + Mode mode, + ExecutionContext* execution_context); ScriptPromise next(ScriptState*); @@ -51,15 +51,15 @@ Mode mode_; mojom::blink::FileSystemAccessErrorPtr error_; bool waiting_for_more_entries_ = true; - HeapDeque<Member<NativeFileSystemHandle>> entries_; + HeapDeque<Member<FileSystemHandle>> entries_; Member<ScriptPromiseResolver> pending_next_; - Member<NativeFileSystemDirectoryHandle> directory_; + Member<FileSystemDirectoryHandle> directory_; HeapMojoReceiver<mojom::blink::FileSystemAccessDirectoryEntriesListener, - NativeFileSystemDirectoryIterator, + FileSystemDirectoryIterator, HeapMojoWrapperMode::kWithoutContextObserver> receiver_; }; } // namespace blink -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_DIRECTORY_ITERATOR_H_ +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_DIRECTORY_ITERATOR_H_
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_iterator.idl b/third_party/blink/renderer/modules/file_system_access/file_system_directory_iterator.idl similarity index 85% rename from third_party/blink/renderer/modules/file_system_access/native_file_system_directory_iterator.idl rename to third_party/blink/renderer/modules/file_system_access/file_system_directory_iterator.idl index 59a4c98..77bca06 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_iterator.idl +++ b/third_party/blink/renderer/modules/file_system_access/file_system_directory_iterator.idl
@@ -8,7 +8,7 @@ [ LegacyNoInterfaceObject, ActiveScriptWrappable, - RuntimeEnabled=NativeFileSystem -] interface NativeFileSystemDirectoryIterator { + RuntimeEnabled=FileSystemAccess +] interface FileSystemDirectoryIterator { [CallWith=ScriptState] Promise<any> next(); };
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_file_handle.cc b/third_party/blink/renderer/modules/file_system_access/file_system_file_handle.cc similarity index 84% rename from third_party/blink/renderer/modules/file_system_access/native_file_system_file_handle.cc rename to third_party/blink/renderer/modules/file_system_access/file_system_file_handle.cc index 921a1ee1..0f290539 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_file_handle.cc +++ b/third_party/blink/renderer/modules/file_system_access/file_system_file_handle.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_file_handle.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_file_handle.h" #include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom-blink.h" #include "third_party/blink/public/mojom/file_system_access/file_system_access_file_writer.mojom-blink.h" @@ -12,8 +12,8 @@ #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/fileapi/file.h" #include "third_party/blink/renderer/core/fileapi/file_error.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_error.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_writable_file_stream.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_access_error.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/file_metadata.h" #include "third_party/blink/renderer/platform/heap/heap.h" @@ -22,17 +22,17 @@ namespace blink { using mojom::blink::FileSystemAccessErrorPtr; -NativeFileSystemFileHandle::NativeFileSystemFileHandle( +FileSystemFileHandle::FileSystemFileHandle( ExecutionContext* context, const String& name, mojo::PendingRemote<mojom::blink::FileSystemAccessFileHandle> mojo_ptr) - : NativeFileSystemHandle(context, name), mojo_ptr_(context) { + : FileSystemHandle(context, name), mojo_ptr_(context) { mojo_ptr_.Bind(std::move(mojo_ptr), context->GetTaskRunner(TaskType::kMiscPlatformAPI)); DCHECK(mojo_ptr_.is_bound()); } -ScriptPromise NativeFileSystemFileHandle::createWritable( +ScriptPromise FileSystemFileHandle::createWritable( ScriptState* script_state, const FileSystemCreateWriterOptions* options, ExceptionState& exception_state) { @@ -55,11 +55,11 @@ if (!script_state) return; if (result->status != mojom::blink::FileSystemAccessStatus::kOk) { - native_file_system_error::Reject(resolver, *result); + file_system_access_error::Reject(resolver, *result); return; } - resolver->Resolve(NativeFileSystemWritableFileStream::Create( + resolver->Resolve(FileSystemWritableFileStream::Create( script_state, std::move(writer))); }, WrapPersistent(resolver))); @@ -67,9 +67,8 @@ return result; } -ScriptPromise NativeFileSystemFileHandle::getFile( - ScriptState* script_state, - ExceptionState& exception_state) { +ScriptPromise FileSystemFileHandle::getFile(ScriptState* script_state, + ExceptionState& exception_state) { if (!mojo_ptr_.is_bound()) { exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, ""); return ScriptPromise(); @@ -83,7 +82,7 @@ FileSystemAccessErrorPtr result, const base::File::Info& info, const scoped_refptr<BlobDataHandle>& blob) { if (result->status != mojom::blink::FileSystemAccessStatus::kOk) { - native_file_system_error::Reject(resolver, *result); + file_system_access_error::Reject(resolver, *result); return; } resolver->Resolve(MakeGarbageCollected<File>( @@ -95,19 +94,19 @@ } mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> -NativeFileSystemFileHandle::Transfer() { +FileSystemFileHandle::Transfer() { mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> result; if (mojo_ptr_.is_bound()) mojo_ptr_->Transfer(result.InitWithNewPipeAndPassReceiver()); return result; } -void NativeFileSystemFileHandle::Trace(Visitor* visitor) const { +void FileSystemFileHandle::Trace(Visitor* visitor) const { visitor->Trace(mojo_ptr_); - NativeFileSystemHandle::Trace(visitor); + FileSystemHandle::Trace(visitor); } -void NativeFileSystemFileHandle::QueryPermissionImpl( +void FileSystemFileHandle::QueryPermissionImpl( bool writable, base::OnceCallback<void(mojom::blink::PermissionStatus)> callback) { if (!mojo_ptr_.is_bound()) { @@ -117,7 +116,7 @@ mojo_ptr_->GetPermissionStatus(writable, std::move(callback)); } -void NativeFileSystemFileHandle::RequestPermissionImpl( +void FileSystemFileHandle::RequestPermissionImpl( bool writable, base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr, mojom::blink::PermissionStatus)> callback) { @@ -133,7 +132,7 @@ mojo_ptr_->RequestPermission(writable, std::move(callback)); } -void NativeFileSystemFileHandle::IsSameEntryImpl( +void FileSystemFileHandle::IsSameEntryImpl( mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> other, base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr, bool)> callback) {
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_file_handle.h b/third_party/blink/renderer/modules/file_system_access/file_system_file_handle.h similarity index 83% rename from third_party/blink/renderer/modules/file_system_access/native_file_system_file_handle.h rename to third_party/blink/renderer/modules/file_system_access/file_system_file_handle.h index 449f0536..02f5608 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_file_handle.h +++ b/third_party/blink/renderer/modules/file_system_access/file_system_file_handle.h
@@ -2,22 +2,22 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_FILE_HANDLE_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_FILE_HANDLE_H_ +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_FILE_HANDLE_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_FILE_HANDLE_H_ #include "mojo/public/cpp/bindings/pending_remote.h" #include "third_party/blink/public/mojom/file_system_access/file_system_access_file_handle.mojom-blink.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_handle.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_handle.h" #include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" namespace blink { class FileSystemCreateWriterOptions; -class NativeFileSystemFileHandle final : public NativeFileSystemHandle { +class FileSystemFileHandle final : public FileSystemHandle { DEFINE_WRAPPERTYPEINFO(); public: - NativeFileSystemFileHandle( + FileSystemFileHandle( ExecutionContext* context, const String& name, mojo::PendingRemote<mojom::blink::FileSystemAccessFileHandle>); @@ -56,4 +56,4 @@ } // namespace blink -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_FILE_HANDLE_H_ +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_FILE_HANDLE_H_
diff --git a/third_party/blink/renderer/modules/file_system_access/file_system_file_handle.idl b/third_party/blink/renderer/modules/file_system_access/file_system_file_handle.idl index b24362e..931ff2d 100644 --- a/third_party/blink/renderer/modules/file_system_access/file_system_file_handle.idl +++ b/third_party/blink/renderer/modules/file_system_access/file_system_file_handle.idl
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://wicg.github.io/native-file-system/#filesystemfilehandle +// https://wicg.github.io/file-system-access/#filesystemfilehandle [ Exposed=(Window,Worker), SecureContext, Serializable, - RuntimeEnabled=NativeFileSystem, - ImplementedAs=NativeFileSystemFileHandle + RuntimeEnabled=FileSystemAccess ] interface FileSystemFileHandle : FileSystemHandle { [CallWith=ScriptState, RaisesException] Promise<FileSystemWritableFileStream> createWritable(optional FileSystemCreateWriterOptions options = {}); + [CallWith=ScriptState, RaisesException] Promise<File> getFile(); };
diff --git a/third_party/blink/renderer/modules/file_system_access/file_system_get_directory_options.idl b/third_party/blink/renderer/modules/file_system_access/file_system_get_directory_options.idl index 529b8dd2..8c45a7f 100644 --- a/third_party/blink/renderer/modules/file_system_access/file_system_get_directory_options.idl +++ b/third_party/blink/renderer/modules/file_system_access/file_system_get_directory_options.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://wicg.github.io/native-file-system/#dictdef-filesystemgetdirectoryoptions +// https://wicg.github.io/file-system-access/#dictdef-filesystemgetdirectoryoptions dictionary FileSystemGetDirectoryOptions { boolean create = false; };
diff --git a/third_party/blink/renderer/modules/file_system_access/file_system_get_file_options.idl b/third_party/blink/renderer/modules/file_system_access/file_system_get_file_options.idl index 57c5a7d..ad7d5a5 100644 --- a/third_party/blink/renderer/modules/file_system_access/file_system_get_file_options.idl +++ b/third_party/blink/renderer/modules/file_system_access/file_system_get_file_options.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://wicg.github.io/native-file-system/#dictdef-filesystemgetfileoptions +// https://wicg.github.io/file-system-access/#dictdef-filesystemgetfileoptions dictionary FileSystemGetFileOptions { boolean create = false; };
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_handle.cc b/third_party/blink/renderer/modules/file_system_access/file_system_handle.cc similarity index 81% rename from third_party/blink/renderer/modules/file_system_access/native_file_system_handle.cc rename to third_party/blink/renderer/modules/file_system_access/file_system_handle.cc index 2809a9e..6ad3884 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_handle.cc +++ b/third_party/blink/renderer/modules/file_system_access/file_system_handle.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_handle.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_handle.h" #include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom-blink.h" #include "third_party/blink/public/platform/task_type.h" @@ -10,29 +10,28 @@ #include "third_party/blink/renderer/bindings/modules/v8/v8_file_system_handle_permission_descriptor.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/fileapi/file_error.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_directory_handle.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_error.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_file_handle.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_access_error.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_file_handle.h" #include "third_party/blink/renderer/platform/wtf/functional.h" namespace blink { using mojom::blink::FileSystemAccessEntryPtr; using mojom::blink::FileSystemAccessErrorPtr; -NativeFileSystemHandle::NativeFileSystemHandle( - ExecutionContext* execution_context, - const String& name) +FileSystemHandle::FileSystemHandle(ExecutionContext* execution_context, + const String& name) : ExecutionContextClient(execution_context), name_(name) {} // static -NativeFileSystemHandle* NativeFileSystemHandle::CreateFromMojoEntry( +FileSystemHandle* FileSystemHandle::CreateFromMojoEntry( mojom::blink::FileSystemAccessEntryPtr e, ExecutionContext* execution_context) { if (e->entry_handle->is_file()) { - return MakeGarbageCollected<NativeFileSystemFileHandle>( + return MakeGarbageCollected<FileSystemFileHandle>( execution_context, e->name, std::move(e->entry_handle->get_file())); } - return MakeGarbageCollected<NativeFileSystemDirectoryHandle>( + return MakeGarbageCollected<FileSystemDirectoryHandle>( execution_context, e->name, std::move(e->entry_handle->get_directory())); } @@ -52,7 +51,7 @@ } // namespace -ScriptPromise NativeFileSystemHandle::queryPermission( +ScriptPromise FileSystemHandle::queryPermission( ScriptState* script_state, const FileSystemHandlePermissionDescriptor* descriptor) { auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); @@ -70,7 +69,7 @@ return result; } -ScriptPromise NativeFileSystemHandle::requestPermission( +ScriptPromise FileSystemHandle::requestPermission( ScriptState* script_state, const FileSystemHandlePermissionDescriptor* descriptor) { auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); @@ -82,7 +81,7 @@ [](ScriptPromiseResolver* resolver, FileSystemAccessErrorPtr result, mojom::blink::PermissionStatus status) { if (result->status != mojom::blink::FileSystemAccessStatus::kOk) { - native_file_system_error::Reject(resolver, *result); + file_system_access_error::Reject(resolver, *result); return; } resolver->Resolve(MojoPermissionStatusToString(status)); @@ -92,9 +91,8 @@ return result; } -ScriptPromise NativeFileSystemHandle::isSameEntry( - ScriptState* script_state, - NativeFileSystemHandle* other) { +ScriptPromise FileSystemHandle::isSameEntry(ScriptState* script_state, + FileSystemHandle* other) { auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); ScriptPromise result = resolver->Promise(); @@ -104,7 +102,7 @@ [](ScriptPromiseResolver* resolver, FileSystemAccessErrorPtr result, bool same) { if (result->status != mojom::blink::FileSystemAccessStatus::kOk) { - native_file_system_error::Reject(resolver, *result); + file_system_access_error::Reject(resolver, *result); return; } resolver->Resolve(same); @@ -113,7 +111,7 @@ return result; } -void NativeFileSystemHandle::Trace(Visitor* visitor) const { +void FileSystemHandle::Trace(Visitor* visitor) const { ScriptWrappable::Trace(visitor); ExecutionContextClient::Trace(visitor); }
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_handle.h b/third_party/blink/renderer/modules/file_system_access/file_system_handle.h similarity index 82% rename from third_party/blink/renderer/modules/file_system_access/native_file_system_handle.h rename to third_party/blink/renderer/modules/file_system_access/file_system_handle.h index e3385d8..8ef5fe4 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_handle.h +++ b/third_party/blink/renderer/modules/file_system_access/file_system_handle.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_HANDLE_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_HANDLE_H_ +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_HANDLE_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_HANDLE_H_ #include "mojo/public/cpp/bindings/pending_remote.h" #include "third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom-blink-forward.h" @@ -21,14 +21,12 @@ class ExecutionContext; class FileSystemHandlePermissionDescriptor; -class NativeFileSystemHandle : public ScriptWrappable, - public ExecutionContextClient { +class FileSystemHandle : public ScriptWrappable, public ExecutionContextClient { DEFINE_WRAPPERTYPEINFO(); public: - NativeFileSystemHandle(ExecutionContext* execution_context, - const String& name); - static NativeFileSystemHandle* CreateFromMojoEntry( + FileSystemHandle(ExecutionContext* execution_context, const String& name); + static FileSystemHandle* CreateFromMojoEntry( mojom::blink::FileSystemAccessEntryPtr, ExecutionContext* execution_context); @@ -42,7 +40,7 @@ ScriptPromise requestPermission(ScriptState*, const FileSystemHandlePermissionDescriptor*); - ScriptPromise isSameEntry(ScriptState*, NativeFileSystemHandle* other); + ScriptPromise isSameEntry(ScriptState*, FileSystemHandle* other); // Grab a handle to a transfer token. This may return an invalid PendingRemote // if the context is already destroyed. @@ -69,4 +67,4 @@ } // namespace blink -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_HANDLE_H_ +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_HANDLE_H_
diff --git a/third_party/blink/renderer/modules/file_system_access/file_system_handle.idl b/third_party/blink/renderer/modules/file_system_access/file_system_handle.idl index 1cab690..bff43870 100644 --- a/third_party/blink/renderer/modules/file_system_access/file_system_handle.idl +++ b/third_party/blink/renderer/modules/file_system_access/file_system_handle.idl
@@ -2,19 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://wicg.github.io/native-file-system/#enumdef-filesystemhandlekind +// https://wicg.github.io/file-system-access/#enumdef-filesystemhandlekind enum FileSystemHandleKind { "file", "directory", }; -// https://wicg.github.io/native-file-system/#filesystemhandle +// https://wicg.github.io/file-system-access/#filesystemhandle [ Exposed=(Window,Worker), SecureContext, Serializable, - RuntimeEnabled=NativeFileSystem, - ImplementedAs=NativeFileSystemHandle + RuntimeEnabled=FileSystemAccess ] interface FileSystemHandle { // Brand checking APIs because javascript makes it otherwise really hard to // figure out what type an object is when you don't know in which global @@ -28,5 +27,6 @@ [CallWith=ScriptState] Promise<PermissionState> requestPermission( optional FileSystemHandlePermissionDescriptor descriptor = {}); - [CallWith=ScriptState, Measure] Promise<boolean> isSameEntry(FileSystemHandle other); + [CallWith=ScriptState, Measure] + Promise<boolean> isSameEntry(FileSystemHandle other); };
diff --git a/third_party/blink/renderer/modules/file_system_access/file_system_handle_permission_descriptor.idl b/third_party/blink/renderer/modules/file_system_access/file_system_handle_permission_descriptor.idl index c4762fc..4dd4048a 100644 --- a/third_party/blink/renderer/modules/file_system_access/file_system_handle_permission_descriptor.idl +++ b/third_party/blink/renderer/modules/file_system_access/file_system_handle_permission_descriptor.idl
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// http://wicg.github.io/native-file-system/#enumdef-filesystempermissionmode +// http://wicg.github.io/file-system-access/#enumdef-filesystempermissionmode enum FileSystemPermissionMode { "read", "readwrite" }; -// http://wicg.github.io/native-file-system/#dictdef-filesystemhandlepermissiondescriptor +// http://wicg.github.io/file-system-access/#dictdef-filesystemhandlepermissiondescriptor dictionary FileSystemHandlePermissionDescriptor { FileSystemPermissionMode mode = "read"; };
diff --git a/third_party/blink/renderer/modules/file_system_access/file_system_remove_options.idl b/third_party/blink/renderer/modules/file_system_access/file_system_remove_options.idl index f3f8566..786bc94 100644 --- a/third_party/blink/renderer/modules/file_system_access/file_system_remove_options.idl +++ b/third_party/blink/renderer/modules/file_system_access/file_system_remove_options.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://wicg.github.io/native-file-system/#dictdef-filesystemremoveoptions +// https://wicg.github.io/file-system-access/#dictdef-filesystemremoveoptions dictionary FileSystemRemoveOptions { boolean recursive = false; };
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_underlying_sink.cc b/third_party/blink/renderer/modules/file_system_access/file_system_underlying_sink.cc similarity index 82% rename from third_party/blink/renderer/modules/file_system_access/native_file_system_underlying_sink.cc rename to third_party/blink/renderer/modules/file_system_access/file_system_underlying_sink.cc index e59cc97..ff365fad 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_underlying_sink.cc +++ b/third_party/blink/renderer/modules/file_system_access/file_system_underlying_sink.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_underlying_sink.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_underlying_sink.h" #include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view_or_blob_or_usv_string.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" @@ -12,14 +12,14 @@ #include "third_party/blink/renderer/bindings/modules/v8/v8_write_params.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/fileapi/blob.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_error.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_writable_file_stream.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_access_error.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/blob/blob_data.h" namespace blink { -NativeFileSystemUnderlyingSink::NativeFileSystemUnderlyingSink( +FileSystemUnderlyingSink::FileSystemUnderlyingSink( ExecutionContext* context, mojo::PendingRemote<mojom::blink::FileSystemAccessFileWriter> writer_remote) : writer_remote_(context) { @@ -28,14 +28,14 @@ DCHECK(writer_remote_.is_bound()); } -ScriptPromise NativeFileSystemUnderlyingSink::start( +ScriptPromise FileSystemUnderlyingSink::start( ScriptState* script_state, WritableStreamDefaultController* controller, ExceptionState& exception_state) { return ScriptPromise::CastUndefined(script_state); } -ScriptPromise NativeFileSystemUnderlyingSink::write( +ScriptPromise FileSystemUnderlyingSink::write( ScriptState* script_state, ScriptValue chunk, WritableStreamDefaultController* controller, @@ -70,9 +70,8 @@ exception_state); } -ScriptPromise NativeFileSystemUnderlyingSink::close( - ScriptState* script_state, - ExceptionState& exception_state) { +ScriptPromise FileSystemUnderlyingSink::close(ScriptState* script_state, + ExceptionState& exception_state) { if (!writer_remote_.is_bound() || pending_operation_) { exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, "Object reached an invalid state"); @@ -81,16 +80,15 @@ pending_operation_ = MakeGarbageCollected<ScriptPromiseResolver>(script_state); ScriptPromise result = pending_operation_->Promise(); - writer_remote_->Close(WTF::Bind( - &NativeFileSystemUnderlyingSink::CloseComplete, WrapPersistent(this))); + writer_remote_->Close(WTF::Bind(&FileSystemUnderlyingSink::CloseComplete, + WrapPersistent(this))); return result; } -ScriptPromise NativeFileSystemUnderlyingSink::abort( - ScriptState* script_state, - ScriptValue reason, - ExceptionState& exception_state) { +ScriptPromise FileSystemUnderlyingSink::abort(ScriptState* script_state, + ScriptValue reason, + ExceptionState& exception_state) { // The specification guarantees that this will only be called after all // pending writes have been aborted. Terminating the remote connection // will ensure that the writes are not closed successfully. @@ -99,7 +97,7 @@ return ScriptPromise::CastUndefined(script_state); } -ScriptPromise NativeFileSystemUnderlyingSink::HandleParams( +ScriptPromise FileSystemUnderlyingSink::HandleParams( ScriptState* script_state, const WriteParams& params, ExceptionState& exception_state) { @@ -140,7 +138,7 @@ return ScriptPromise(); } -ScriptPromise NativeFileSystemUnderlyingSink::WriteData( +ScriptPromise FileSystemUnderlyingSink::WriteData( ScriptState* script_state, uint64_t position, const ArrayBufferOrArrayBufferViewOrBlobOrUSVString& data, @@ -173,7 +171,7 @@ return WriteBlob(script_state, position, blob, exception_state); } -ScriptPromise NativeFileSystemUnderlyingSink::WriteBlob( +ScriptPromise FileSystemUnderlyingSink::WriteBlob( ScriptState* script_state, uint64_t position, Blob* blob, @@ -186,14 +184,13 @@ pending_operation_ = MakeGarbageCollected<ScriptPromiseResolver>(script_state); ScriptPromise result = pending_operation_->Promise(); - writer_remote_->Write( - position, blob->AsMojoBlob(), - WTF::Bind(&NativeFileSystemUnderlyingSink::WriteComplete, - WrapPersistent(this))); + writer_remote_->Write(position, blob->AsMojoBlob(), + WTF::Bind(&FileSystemUnderlyingSink::WriteComplete, + WrapPersistent(this))); return result; } -ScriptPromise NativeFileSystemUnderlyingSink::Truncate( +ScriptPromise FileSystemUnderlyingSink::Truncate( ScriptState* script_state, uint64_t size, ExceptionState& exception_state) { @@ -206,15 +203,14 @@ MakeGarbageCollected<ScriptPromiseResolver>(script_state); ScriptPromise result = pending_operation_->Promise(); writer_remote_->Truncate( - size, WTF::Bind(&NativeFileSystemUnderlyingSink::TruncateComplete, + size, WTF::Bind(&FileSystemUnderlyingSink::TruncateComplete, WrapPersistent(this), size)); return result; } -ScriptPromise NativeFileSystemUnderlyingSink::Seek( - ScriptState* script_state, - uint64_t offset, - ExceptionState& exception_state) { +ScriptPromise FileSystemUnderlyingSink::Seek(ScriptState* script_state, + uint64_t offset, + ExceptionState& exception_state) { if (!writer_remote_.is_bound() || pending_operation_) { exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, "Object reached an invalid state"); @@ -224,11 +220,11 @@ return ScriptPromise::CastUndefined(script_state); } -void NativeFileSystemUnderlyingSink::WriteComplete( +void FileSystemUnderlyingSink::WriteComplete( mojom::blink::FileSystemAccessErrorPtr result, uint64_t bytes_written) { DCHECK(pending_operation_); - native_file_system_error::ResolveOrReject(pending_operation_, *result); + file_system_access_error::ResolveOrReject(pending_operation_, *result); pending_operation_ = nullptr; if (result->status == mojom::blink::FileSystemAccessStatus::kOk) { @@ -237,11 +233,11 @@ } } -void NativeFileSystemUnderlyingSink::TruncateComplete( +void FileSystemUnderlyingSink::TruncateComplete( uint64_t to_size, mojom::blink::FileSystemAccessErrorPtr result) { DCHECK(pending_operation_); - native_file_system_error::ResolveOrReject(pending_operation_, *result); + file_system_access_error::ResolveOrReject(pending_operation_, *result); pending_operation_ = nullptr; if (result->status == mojom::blink::FileSystemAccessStatus::kOk) { @@ -251,17 +247,17 @@ } } -void NativeFileSystemUnderlyingSink::CloseComplete( +void FileSystemUnderlyingSink::CloseComplete( mojom::blink::FileSystemAccessErrorPtr result) { DCHECK(pending_operation_); - native_file_system_error::ResolveOrReject(pending_operation_, *result); + file_system_access_error::ResolveOrReject(pending_operation_, *result); pending_operation_ = nullptr; // We close the mojo pipe because we intend this writable file stream to be // discarded after close. Subsequent operations will fail. writer_remote_.reset(); } -void NativeFileSystemUnderlyingSink::Trace(Visitor* visitor) const { +void FileSystemUnderlyingSink::Trace(Visitor* visitor) const { ScriptWrappable::Trace(visitor); UnderlyingSinkBase::Trace(visitor); visitor->Trace(writer_remote_);
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_underlying_sink.h b/third_party/blink/renderer/modules/file_system_access/file_system_underlying_sink.h similarity index 87% rename from third_party/blink/renderer/modules/file_system_access/native_file_system_underlying_sink.h rename to third_party/blink/renderer/modules/file_system_access/file_system_underlying_sink.h index 853a900..23cb4cd 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_underlying_sink.h +++ b/third_party/blink/renderer/modules/file_system_access/file_system_underlying_sink.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_UNDERLYING_SINK_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_UNDERLYING_SINK_H_ +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_UNDERLYING_SINK_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_UNDERLYING_SINK_H_ #include "third_party/blink/public/mojom/file_system_access/file_system_access_file_writer.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view_or_blob_or_usv_string.h" @@ -18,9 +18,9 @@ class ScriptPromiseResolver; class WriteParams; -class NativeFileSystemUnderlyingSink final : public UnderlyingSinkBase { +class FileSystemUnderlyingSink final : public UnderlyingSinkBase { public: - explicit NativeFileSystemUnderlyingSink( + explicit FileSystemUnderlyingSink( ExecutionContext*, mojo::PendingRemote<mojom::blink::FileSystemAccessFileWriter>); @@ -66,4 +66,4 @@ } // namespace blink -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_UNDERLYING_SINK_H_ +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_UNDERLYING_SINK_H_
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_writable_file_stream.cc b/third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.cc similarity index 86% rename from third_party/blink/renderer/modules/file_system_access/native_file_system_writable_file_stream.cc rename to third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.cc index 4e599eb..9d88ef3f 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_writable_file_stream.cc +++ b/third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_writable_file_stream.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.h" #include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view_or_blob_or_usv_string.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" @@ -12,13 +12,13 @@ #include "third_party/blink/renderer/core/streams/count_queuing_strategy.h" #include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h" #include "third_party/blink/renderer/core/streams/writable_stream_default_writer.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_underlying_sink.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_underlying_sink.h" #include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h" namespace blink { -NativeFileSystemWritableFileStream* NativeFileSystemWritableFileStream::Create( +FileSystemWritableFileStream* FileSystemWritableFileStream::Create( ScriptState* script_state, mojo::PendingRemote<mojom::blink::FileSystemAccessFileWriter> writer_pending_remote) { @@ -27,9 +27,9 @@ ExecutionContext* context = ExecutionContext::From(script_state); - auto* stream = MakeGarbageCollected<NativeFileSystemWritableFileStream>(); + auto* stream = MakeGarbageCollected<FileSystemWritableFileStream>(); - auto* underlying_sink = MakeGarbageCollected<NativeFileSystemUnderlyingSink>( + auto* underlying_sink = MakeGarbageCollected<FileSystemUnderlyingSink>( context, std::move(writer_pending_remote)); stream->underlying_sink_ = underlying_sink; auto underlying_sink_value = ScriptValue::From(script_state, underlying_sink); @@ -43,7 +43,7 @@ ExceptionState exception_state(script_state->GetIsolate(), ExceptionState::kConstructionContext, - "NativeFileSystemWritableFileStream"); + "FileSystemWritableFileStream"); stream->InitInternal(script_state, underlying_sink_value, strategy_value, exception_state); @@ -53,7 +53,7 @@ return stream; } -ScriptPromise NativeFileSystemWritableFileStream::write( +ScriptPromise FileSystemWritableFileStream::write( ScriptState* script_state, const ArrayBufferOrArrayBufferViewOrBlobOrUSVStringOrWriteParams& data, ExceptionState& exception_state) { @@ -69,7 +69,7 @@ return promise; } -ScriptPromise NativeFileSystemWritableFileStream::truncate( +ScriptPromise FileSystemWritableFileStream::truncate( ScriptState* script_state, uint64_t size, ExceptionState& exception_state) { @@ -89,7 +89,7 @@ return promise; } -ScriptPromise NativeFileSystemWritableFileStream::close( +ScriptPromise FileSystemWritableFileStream::close( ScriptState* script_state, ExceptionState& exception_state) { WritableStreamDefaultWriter* writer = @@ -103,7 +103,7 @@ return promise; } -ScriptPromise NativeFileSystemWritableFileStream::seek( +ScriptPromise FileSystemWritableFileStream::seek( ScriptState* script_state, uint64_t offset, ExceptionState& exception_state) { @@ -123,7 +123,7 @@ return promise; } -void NativeFileSystemWritableFileStream::Trace(Visitor* visitor) const { +void FileSystemWritableFileStream::Trace(Visitor* visitor) const { WritableStream::Trace(visitor); visitor->Trace(underlying_sink_); }
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_writable_file_stream.h b/third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.h similarity index 72% rename from third_party/blink/renderer/modules/file_system_access/native_file_system_writable_file_stream.h rename to third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.h index 55327a4..2f87469 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_writable_file_stream.h +++ b/third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_WRITABLE_FILE_STREAM_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_WRITABLE_FILE_STREAM_H_ +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_WRITABLE_FILE_STREAM_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_WRITABLE_FILE_STREAM_H_ #include "mojo/public/cpp/bindings/remote.h" #include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom-blink.h" @@ -17,19 +17,19 @@ class ScriptPromise; class ScriptState; -class NativeFileSystemUnderlyingSink; +class FileSystemUnderlyingSink; -class NativeFileSystemWritableFileStream final : public WritableStream { +class FileSystemWritableFileStream final : public WritableStream { DEFINE_WRAPPERTYPEINFO(); public: - static NativeFileSystemWritableFileStream* Create( + static FileSystemWritableFileStream* Create( ScriptState*, mojo::PendingRemote<mojom::blink::FileSystemAccessFileWriter>); void Trace(Visitor* visitor) const override; - // IDL defined functions specific to NativeFileSystemWritableFileStream. + // IDL defined functions specific to FileSystemWritableFileStream. ScriptPromise write( ScriptState*, const ArrayBufferOrArrayBufferViewOrBlobOrUSVStringOrWriteParams& data, @@ -39,8 +39,8 @@ ScriptPromise seek(ScriptState*, uint64_t offset, ExceptionState&); private: - Member<NativeFileSystemUnderlyingSink> underlying_sink_; + Member<FileSystemUnderlyingSink> underlying_sink_; }; } // namespace blink -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_WRITABLE_FILE_STREAM_H_ +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_WRITABLE_FILE_STREAM_H_
diff --git a/third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.idl b/third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.idl index e09e63d9..32a8914 100644 --- a/third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.idl +++ b/third_party/blink/renderer/modules/file_system_access/file_system_writable_file_stream.idl
@@ -2,12 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://wicg.github.io/native-file-system/#filesystemwritablefilestream +// https://wicg.github.io/file-system-access/#filesystemwritablefilestream [ Exposed=(Window,Worker), SecureContext, - ImplementedAs=NativeFileSystemWritableFileStream, - RuntimeEnabled=NativeFileSystem + RuntimeEnabled=FileSystemAccess ] interface FileSystemWritableFileStream : WritableStream { [CallWith=ScriptState, RaisesException] Promise<void> write((BufferSource or Blob or USVString or WriteParams) data); [CallWith=ScriptState, RaisesException] Promise<void> truncate(unsigned long long size);
diff --git a/third_party/blink/renderer/modules/file_system_access/global_native_file_system.cc b/third_party/blink/renderer/modules/file_system_access/global_file_system_access.cc similarity index 94% rename from third_party/blink/renderer/modules/file_system_access/global_native_file_system.cc rename to third_party/blink/renderer/modules/file_system_access/global_file_system_access.cc index e0dad660..ba70723 100644 --- a/third_party/blink/renderer/modules/file_system_access/global_native_file_system.cc +++ b/third_party/blink/renderer/modules/file_system_access/global_file_system_access.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/blink/renderer/modules/file_system_access/global_native_file_system.h" +#include "third_party/blink/renderer/modules/file_system_access/global_file_system_access.h" #include <utility> @@ -25,9 +25,9 @@ #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/workers/worker_global_scope.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_directory_handle.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_error.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_file_handle.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_access_error.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_file_handle.h" #include "third_party/blink/renderer/platform/bindings/enumeration_base.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/heap/heap.h" @@ -142,7 +142,7 @@ return; } - if (!window.GetSecurityOrigin()->CanAccessNativeFileSystem()) { + if (!window.GetSecurityOrigin()->CanAccessFileSystem()) { if (window.IsSandboxed(network::mojom::blink::WebSandboxFlags::kOrigin)) { exception_state.ThrowSecurityError( "Sandboxed documents aren't allowed to show a file picker."); @@ -229,7 +229,7 @@ return; if (file_operation_result->status != mojom::blink::FileSystemAccessStatus::kOk) { - native_file_system_error::Reject(resolver, + file_system_access_error::Reject(resolver, *file_operation_result); return; } @@ -237,25 +237,25 @@ // While it would be better to not trust the renderer process, // we're doing this here to avoid potential mojo message pipe // ordering problems, where the frame activation state - // reconciliation messages would compete with concurrent Native File - // System messages to the browser. + // reconciliation messages would compete with concurrent File + // System Access messages to the browser. // TODO(https://crbug.com/1017270): Remove this after spec change, // or when activation moves to browser. LocalFrame::NotifyUserActivation( local_frame, mojom::blink::UserActivationNotificationType:: - kNativeFileSystem); + kFileSystemAccess); if (return_as_sequence) { - HeapVector<Member<NativeFileSystemHandle>> results; + HeapVector<Member<FileSystemHandle>> results; results.ReserveInitialCapacity(entries.size()); for (auto& entry : entries) { - results.push_back(NativeFileSystemHandle::CreateFromMojoEntry( + results.push_back(FileSystemHandle::CreateFromMojoEntry( std::move(entry), context)); } resolver->Resolve(results); } else { DCHECK_EQ(1u, entries.size()); - resolver->Resolve(NativeFileSystemHandle::CreateFromMojoEntry( + resolver->Resolve(FileSystemHandle::CreateFromMojoEntry( std::move(entries[0]), context)); } }, @@ -267,7 +267,7 @@ } // namespace // static -ScriptPromise GlobalNativeFileSystem::showOpenFilePicker( +ScriptPromise GlobalFileSystemAccess::showOpenFilePicker( ScriptState* script_state, LocalDOMWindow& window, const OpenFilePickerOptions* options, @@ -308,7 +308,7 @@ } // static -ScriptPromise GlobalNativeFileSystem::showSaveFilePicker( +ScriptPromise GlobalFileSystemAccess::showSaveFilePicker( ScriptState* script_state, LocalDOMWindow& window, const SaveFilePickerOptions* options, @@ -346,7 +346,7 @@ } // static -ScriptPromise GlobalNativeFileSystem::showDirectoryPicker( +ScriptPromise GlobalFileSystemAccess::showDirectoryPicker( ScriptState* script_state, LocalDOMWindow& window, const DirectoryPickerOptions* options,
diff --git a/third_party/blink/renderer/modules/file_system_access/global_native_file_system.h b/third_party/blink/renderer/modules/file_system_access/global_file_system_access.h similarity index 90% rename from third_party/blink/renderer/modules/file_system_access/global_native_file_system.h rename to third_party/blink/renderer/modules/file_system_access/global_file_system_access.h index e0ee3bca..b6190eb 100644 --- a/third_party/blink/renderer/modules/file_system_access/global_native_file_system.h +++ b/third_party/blink/renderer/modules/file_system_access/global_file_system_access.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_GLOBAL_NATIVE_FILE_SYSTEM_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_GLOBAL_NATIVE_FILE_SYSTEM_H_ +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_GLOBAL_FILE_SYSTEM_ACCESS_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_GLOBAL_FILE_SYSTEM_ACCESS_H_ #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" @@ -18,8 +18,8 @@ class ScriptPromise; class ScriptState; -class GlobalNativeFileSystem { - STATIC_ONLY(GlobalNativeFileSystem); +class GlobalFileSystemAccess { + STATIC_ONLY(GlobalFileSystemAccess); public: static ScriptPromise showOpenFilePicker(ScriptState*, @@ -38,4 +38,4 @@ } // namespace blink -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_GLOBAL_NATIVE_FILE_SYSTEM_H_ +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_GLOBAL_FILE_SYSTEM_ACCESS_H_
diff --git a/third_party/blink/renderer/modules/file_system_access/global_native_file_system_test.cc b/third_party/blink/renderer/modules/file_system_access/global_file_system_access_test.cc similarity index 88% rename from third_party/blink/renderer/modules/file_system_access/global_native_file_system_test.cc rename to third_party/blink/renderer/modules/file_system_access/global_file_system_access_test.cc index 31f21e6..77bc8b04 100644 --- a/third_party/blink/renderer/modules/file_system_access/global_native_file_system_test.cc +++ b/third_party/blink/renderer/modules/file_system_access/global_file_system_access_test.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/blink/renderer/modules/file_system_access/global_native_file_system.h" +#include "third_party/blink/renderer/modules/file_system_access/global_file_system_access.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/receiver_set.h" @@ -21,27 +21,27 @@ namespace blink { -class MockNativeFileSystemManager +class MockFileSystemAccessManager : public mojom::blink::FileSystemAccessManager { public: - MockNativeFileSystemManager(BrowserInterfaceBrokerProxy& broker, + MockFileSystemAccessManager(BrowserInterfaceBrokerProxy& broker, base::OnceClosure reached_callback) : reached_callback_(std::move(reached_callback)), broker_(broker) { broker_.SetBinderForTesting( mojom::blink::FileSystemAccessManager::Name_, WTF::BindRepeating( - &MockNativeFileSystemManager::BindNativeFileSystemManager, + &MockFileSystemAccessManager::BindFileSystemAccessManager, WTF::Unretained(this))); } - MockNativeFileSystemManager(BrowserInterfaceBrokerProxy& broker) + MockFileSystemAccessManager(BrowserInterfaceBrokerProxy& broker) : broker_(broker) { broker_.SetBinderForTesting( mojom::blink::FileSystemAccessManager::Name_, WTF::BindRepeating( - &MockNativeFileSystemManager::BindNativeFileSystemManager, + &MockFileSystemAccessManager::BindFileSystemAccessManager, WTF::Unretained(this))); } - ~MockNativeFileSystemManager() override { + ~MockFileSystemAccessManager() override { broker_.SetBinderForTesting(mojom::blink::FileSystemAccessManager::Name_, {}); } @@ -91,7 +91,7 @@ GetEntryFromDragDropTokenCallback callback) override {} private: - void BindNativeFileSystemManager(mojo::ScopedMessagePipeHandle handle) { + void BindFileSystemAccessManager(mojo::ScopedMessagePipeHandle handle) { receivers_.Add(this, mojo::PendingReceiver<mojom::blink::FileSystemAccessManager>( std::move(handle))); @@ -103,7 +103,7 @@ BrowserInterfaceBrokerProxy& broker_; }; -class GlobalNativeFileSystemTest : public PageTestBase { +class GlobalFileSystemAccessTest : public PageTestBase { public: void SetUp() override { PageTestBase::SetUp(); @@ -122,13 +122,13 @@ } }; -TEST_F(GlobalNativeFileSystemTest, UserActivationRequiredOtherwiseDenied) { +TEST_F(GlobalFileSystemAccessTest, UserActivationRequiredOtherwiseDenied) { LocalFrame* frame = &GetFrame(); EXPECT_FALSE(frame->HasStickyUserActivation()); - MockNativeFileSystemManager manager(frame->GetBrowserInterfaceBroker()); + MockFileSystemAccessManager manager(frame->GetBrowserInterfaceBroker()); manager.SetChooseEntriesResponse(WTF::Bind( - [](MockNativeFileSystemManager::ChooseEntriesCallback callback) { + [](MockFileSystemAccessManager::ChooseEntriesCallback callback) { FAIL(); })); ClassicScript::CreateUnspecifiedScript( @@ -138,7 +138,7 @@ EXPECT_FALSE(frame->HasStickyUserActivation()); } -TEST_F(GlobalNativeFileSystemTest, UserActivationChooseEntriesSuccessful) { +TEST_F(GlobalFileSystemAccessTest, UserActivationChooseEntriesSuccessful) { LocalFrame* frame = &GetFrame(); EXPECT_FALSE(frame->HasStickyUserActivation()); @@ -147,10 +147,10 @@ EXPECT_TRUE(frame->HasStickyUserActivation()); base::RunLoop manager_run_loop; - MockNativeFileSystemManager manager(frame->GetBrowserInterfaceBroker(), + MockFileSystemAccessManager manager(frame->GetBrowserInterfaceBroker(), manager_run_loop.QuitClosure()); manager.SetChooseEntriesResponse(WTF::Bind( - [](MockNativeFileSystemManager::ChooseEntriesCallback callback) { + [](MockFileSystemAccessManager::ChooseEntriesCallback callback) { auto error = mojom::blink::FileSystemAccessError::New(); error->status = mojom::blink::FileSystemAccessStatus::kOk; error->message = ""; @@ -183,7 +183,7 @@ EXPECT_TRUE(frame->HasStickyUserActivation()); } -TEST_F(GlobalNativeFileSystemTest, UserActivationChooseEntriesErrors) { +TEST_F(GlobalFileSystemAccessTest, UserActivationChooseEntriesErrors) { LocalFrame* frame = &GetFrame(); EXPECT_FALSE(frame->HasStickyUserActivation()); @@ -197,7 +197,7 @@ // kOperationAborted is when the user cancels the file selection. FileSystemAccessStatus::kOperationAborted, }; - MockNativeFileSystemManager manager(frame->GetBrowserInterfaceBroker()); + MockFileSystemAccessManager manager(frame->GetBrowserInterfaceBroker()); for (const FileSystemAccessStatus& status : statuses) { LocalFrame::NotifyUserActivation( @@ -208,7 +208,7 @@ manager.SetQuitClosure(manager_run_loop.QuitClosure()); manager.SetChooseEntriesResponse(WTF::Bind( [](mojom::blink::FileSystemAccessStatus status, - MockNativeFileSystemManager::ChooseEntriesCallback callback) { + MockFileSystemAccessManager::ChooseEntriesCallback callback) { auto error = mojom::blink::FileSystemAccessError::New(); error->status = status; error->message = "";
diff --git a/third_party/blink/renderer/modules/file_system_access/idls.gni b/third_party/blink/renderer/modules/file_system_access/idls.gni index a3b719a..56587022 100644 --- a/third_party/blink/renderer/modules/file_system_access/idls.gni +++ b/third_party/blink/renderer/modules/file_system_access/idls.gni
@@ -3,7 +3,7 @@ # found in the LICENSE file. modules_idl_files = [ - "native_file_system_directory_iterator.idl", + "file_system_directory_iterator.idl", "file_system_directory_handle.idl", "file_system_file_handle.idl", "file_system_handle.idl", @@ -25,7 +25,7 @@ ] modules_dependency_idl_files = [ - "data_transfer_item_native_file_system.idl", - "storage_manager_native_file_system.idl", - "window_native_file_system.idl", + "data_transfer_item_file_system_access.idl", + "storage_manager_file_system_access.idl", + "window_file_system_access.idl", ]
diff --git a/third_party/blink/renderer/modules/file_system_access/open_file_picker_options.idl b/third_party/blink/renderer/modules/file_system_access/open_file_picker_options.idl index 96456f75..d74f2c1 100644 --- a/third_party/blink/renderer/modules/file_system_access/open_file_picker_options.idl +++ b/third_party/blink/renderer/modules/file_system_access/open_file_picker_options.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://wicg.github.io/native-file-system/#dictdef-openfilepickeroptions +// https://wicg.github.io/file-system-access/#dictdef-openfilepickeroptions dictionary OpenFilePickerOptions : FilePickerOptions { boolean multiple = false; };
diff --git a/third_party/blink/renderer/modules/file_system_access/save_file_picker_options.idl b/third_party/blink/renderer/modules/file_system_access/save_file_picker_options.idl index d18f9d01..c3f1237 100644 --- a/third_party/blink/renderer/modules/file_system_access/save_file_picker_options.idl +++ b/third_party/blink/renderer/modules/file_system_access/save_file_picker_options.idl
@@ -2,6 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://wicg.github.io/native-file-system/#dictdef-savefilepickeroptions +// https://wicg.github.io/file-system-access/#dictdef-savefilepickeroptions dictionary SaveFilePickerOptions : FilePickerOptions { };
diff --git a/third_party/blink/renderer/modules/file_system_access/storage_manager_native_file_system.cc b/third_party/blink/renderer/modules/file_system_access/storage_manager_file_system_access.cc similarity index 92% rename from third_party/blink/renderer/modules/file_system_access/storage_manager_native_file_system.cc rename to third_party/blink/renderer/modules/file_system_access/storage_manager_file_system_access.cc index b6fa20c..c21b28d 100644 --- a/third_party/blink/renderer/modules/file_system_access/storage_manager_native_file_system.cc +++ b/third_party/blink/renderer/modules/file_system_access/storage_manager_file_system_access.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/blink/renderer/modules/file_system_access/storage_manager_native_file_system.h" +#include "third_party/blink/renderer/modules/file_system_access/storage_manager_file_system_access.h" #include <utility> @@ -18,8 +18,8 @@ #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/workers/worker_global_scope.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_directory_handle.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_error.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_access_error.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/weborigin/security_origin.h" @@ -61,10 +61,10 @@ if (!context) return; if (result->status != mojom::blink::FileSystemAccessStatus::kOk) { - native_file_system_error::Reject(resolver, *result); + file_system_access_error::Reject(resolver, *result); return; } - resolver->Resolve(MakeGarbageCollected<NativeFileSystemDirectoryHandle>( + resolver->Resolve(MakeGarbageCollected<FileSystemDirectoryHandle>( context, kSandboxRootDirectoryName, std::move(handle))); }, WrapPersistent(resolver), std::move(manager))); @@ -73,13 +73,13 @@ } // namespace // static -ScriptPromise StorageManagerNativeFileSystem::getDirectory( +ScriptPromise StorageManagerFileSystemAccess::getDirectory( ScriptState* script_state, const StorageManager& storage, ExceptionState& exception_state) { ExecutionContext* context = ExecutionContext::From(script_state); - if (!context->GetSecurityOrigin()->CanAccessNativeFileSystem()) { + if (!context->GetSecurityOrigin()->CanAccessFileSystem()) { if (context->IsSandboxed(network::mojom::blink::WebSandboxFlags::kOrigin)) { exception_state.ThrowSecurityError( "Storage directory access is denied because the context is "
diff --git a/third_party/blink/renderer/modules/file_system_access/storage_manager_native_file_system.h b/third_party/blink/renderer/modules/file_system_access/storage_manager_file_system_access.h similarity index 79% rename from third_party/blink/renderer/modules/file_system_access/storage_manager_native_file_system.h rename to third_party/blink/renderer/modules/file_system_access/storage_manager_file_system_access.h index 300eef49..2ee916a 100644 --- a/third_party/blink/renderer/modules/file_system_access/storage_manager_native_file_system.h +++ b/third_party/blink/renderer/modules/file_system_access/storage_manager_file_system_access.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_STORAGE_MANAGER_NATIVE_FILE_SYSTEM_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_STORAGE_MANAGER_NATIVE_FILE_SYSTEM_H_ +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_STORAGE_MANAGER_FILE_SYSTEM_ACCESS_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_STORAGE_MANAGER_FILE_SYSTEM_ACCESS_H_ #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" @@ -15,8 +15,8 @@ class ScriptState; class StorageManager; -class StorageManagerNativeFileSystem { - STATIC_ONLY(StorageManagerNativeFileSystem); +class StorageManagerFileSystemAccess { + STATIC_ONLY(StorageManagerFileSystemAccess); public: static ScriptPromise getDirectory(ScriptState*, @@ -26,4 +26,4 @@ } // namespace blink -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_STORAGE_MANAGER_NATIVE_FILE_SYSTEM_H_ +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_STORAGE_MANAGER_FILE_SYSTEM_ACCESS_H_
diff --git a/third_party/blink/renderer/modules/file_system_access/storage_manager_native_file_system.idl b/third_party/blink/renderer/modules/file_system_access/storage_manager_file_system_access.idl similarity index 69% rename from third_party/blink/renderer/modules/file_system_access/storage_manager_native_file_system.idl rename to third_party/blink/renderer/modules/file_system_access/storage_manager_file_system_access.idl index f3a36d5..d73337e3 100644 --- a/third_party/blink/renderer/modules/file_system_access/storage_manager_native_file_system.idl +++ b/third_party/blink/renderer/modules/file_system_access/storage_manager_file_system_access.idl
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://wicg.github.io/native-file-system/#sandboxed-filesystem +// https://wicg.github.io/file-system-access/#sandboxed-filesystem [ SecureContext, - RuntimeEnabled=NativeFileSystem, - ImplementedAs=StorageManagerNativeFileSystem + RuntimeEnabled=FileSystemAccess, + ImplementedAs=StorageManagerFileSystemAccess ] partial interface StorageManager { [CallWith=ScriptState, RaisesException, Measure] Promise<FileSystemDirectoryHandle> getDirectory();
diff --git a/third_party/blink/renderer/modules/file_system_access/window_native_file_system.idl b/third_party/blink/renderer/modules/file_system_access/window_file_system_access.idl similarity index 91% rename from third_party/blink/renderer/modules/file_system_access/window_native_file_system.idl rename to third_party/blink/renderer/modules/file_system_access/window_file_system_access.idl index e2d65ef..f416f361 100644 --- a/third_party/blink/renderer/modules/file_system_access/window_native_file_system.idl +++ b/third_party/blink/renderer/modules/file_system_access/window_file_system_access.idl
@@ -6,8 +6,8 @@ // https://wicg.github.io/native-file-system/#api-getoriginprivatefilesystem [ SecureContext, - RuntimeEnabled=NativeFileSystem, - ImplementedAs=GlobalNativeFileSystem + RuntimeEnabled=FileSystemAccess, + ImplementedAs=GlobalFileSystemAccess ] partial interface Window { [CallWith=ScriptState, RaisesException, Measure] Promise<sequence<FileSystemFileHandle>> showOpenFilePicker(
diff --git a/third_party/blink/renderer/modules/file_system_access/write_params.idl b/third_party/blink/renderer/modules/file_system_access/write_params.idl index 9e6a39c..f62eff5 100644 --- a/third_party/blink/renderer/modules/file_system_access/write_params.idl +++ b/third_party/blink/renderer/modules/file_system_access/write_params.idl
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://wicg.github.io/native-file-system/#enumdef-writecommandtype +// https://wicg.github.io/file-system-access/#enumdef-writecommandtype enum WriteCommandType { "truncate", "seek", "write", }; -// https://wicg.github.io/native-file-system/#dictdef-writeparams +// https://wicg.github.io/file-system-access/#dictdef-writeparams dictionary WriteParams { required WriteCommandType type; unsigned long long? size;
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_value.cc b/third_party/blink/renderer/modules/indexeddb/idb_value.cc index 6257731..99e6a8c 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_value.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_value.cc
@@ -22,10 +22,10 @@ scoped_refptr<SharedBuffer> data, Vector<WebBlobInfo> blob_info, Vector<mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken>> - native_file_system_tokens) + file_system_access_tokens) : data_(std::move(data)), blob_info_(std::move(blob_info)), - native_file_system_tokens_(std::move(native_file_system_tokens)) {} + file_system_access_tokens_(std::move(file_system_access_tokens)) {} IDBValue::~IDBValue() { if (isolate_ && external_allocated_size_)
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_value.h b/third_party/blink/renderer/modules/indexeddb/idb_value.h index 344d71b..73cb14d 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_value.h +++ b/third_party/blink/renderer/modules/indexeddb/idb_value.h
@@ -55,8 +55,8 @@ const IDBKeyPath& KeyPath() const { return key_path_; } Vector<mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken>>& - NativeFileSystemTokens() { - return native_file_system_tokens_; + FileSystemAccessTokens() { + return file_system_access_tokens_; } // Injects a primary key into a value coming from the backend. @@ -104,7 +104,7 @@ Vector<WebBlobInfo> blob_info_; Vector<mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken>> - native_file_system_tokens_; + file_system_access_tokens_; std::unique_ptr<IDBKey> primary_key_; IDBKeyPath key_path_;
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.h b/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.h index c4980be..5d60000 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.h +++ b/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.h
@@ -161,7 +161,7 @@ DCHECK(owns_file_system_handles_) << __func__ << " called twice"; owns_file_system_handles_ = false; #endif // DCHECK_IS_ON() - return std::move(serialized_value_->NativeFileSystemTokens()); + return std::move(serialized_value_->FileSystemAccessTokens()); } size_t DataLengthBeforeWrapInBytes() { return original_data_length_; }
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc b/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc index 16dad28..3b82ac6 100644 --- a/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc +++ b/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc
@@ -174,7 +174,7 @@ external_objects(const std::unique_ptr<blink::IDBValue>& input) { Vector<blink::mojom::blink::IDBExternalObjectPtr> external_objects; external_objects.ReserveInitialCapacity( - input->BlobInfo().size() + input->NativeFileSystemTokens().size()); + input->BlobInfo().size() + input->FileSystemAccessTokens().size()); for (const blink::WebBlobInfo& info : input->BlobInfo()) { auto blob_info = blink::mojom::blink::IDBBlobInfo::New(); if (info.IsFile()) { @@ -198,7 +198,7 @@ blink::mojom::blink::IDBExternalObject::NewBlobOrFile( std::move(blob_info))); } - for (auto& token : input->NativeFileSystemTokens()) { + for (auto& token : input->FileSystemAccessTokens()) { external_objects.push_back( blink::mojom::blink::IDBExternalObject::NewFileSystemAccessToken( std::move(token)));
diff --git a/third_party/blink/renderer/modules/launch/dom_window_launch_queue.cc b/third_party/blink/renderer/modules/launch/dom_window_launch_queue.cc index 6687744..c28f7640 100644 --- a/third_party/blink/renderer/modules/launch/dom_window_launch_queue.cc +++ b/third_party/blink/renderer/modules/launch/dom_window_launch_queue.cc
@@ -5,7 +5,7 @@ #include "third_party/blink/renderer/modules/launch/dom_window_launch_queue.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_handle.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_handle.h" #include "third_party/blink/renderer/modules/launch/launch_params.h" #include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/heap/visitor.h" @@ -24,7 +24,7 @@ void DOMWindowLaunchQueue::UpdateLaunchFiles( LocalDOMWindow* window, - HeapVector<Member<NativeFileSystemHandle>> files) { + HeapVector<Member<FileSystemHandle>> files) { FromState(window)->launch_queue_->Enqueue( MakeGarbageCollected<LaunchParams>(std::move(files))); }
diff --git a/third_party/blink/renderer/modules/launch/dom_window_launch_queue.h b/third_party/blink/renderer/modules/launch/dom_window_launch_queue.h index d1337421..51ae652 100644 --- a/third_party/blink/renderer/modules/launch/dom_window_launch_queue.h +++ b/third_party/blink/renderer/modules/launch/dom_window_launch_queue.h
@@ -32,7 +32,7 @@ static Member<LaunchQueue> launchQueue(LocalDOMWindow&); static void UpdateLaunchFiles(LocalDOMWindow*, - HeapVector<Member<NativeFileSystemHandle>>); + HeapVector<Member<FileSystemHandle>>); void Trace(Visitor*) const override;
diff --git a/third_party/blink/renderer/modules/launch/launch_params.cc b/third_party/blink/renderer/modules/launch/launch_params.cc index 02d23256..733f82f 100644 --- a/third_party/blink/renderer/modules/launch/launch_params.cc +++ b/third_party/blink/renderer/modules/launch/launch_params.cc
@@ -4,13 +4,13 @@ #include "third_party/blink/renderer/modules/launch/launch_params.h" -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_handle.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_handle.h" #include "third_party/blink/renderer/platform/heap/visitor.h" namespace blink { -LaunchParams::LaunchParams(HeapVector<Member<NativeFileSystemHandle>> files) - : files_(files) {} +LaunchParams::LaunchParams(HeapVector<Member<FileSystemHandle>> files) + : files_(std::move(files)) {} LaunchParams::~LaunchParams() = default;
diff --git a/third_party/blink/renderer/modules/launch/launch_params.h b/third_party/blink/renderer/modules/launch/launch_params.h index 4e773c8..07b1805 100644 --- a/third_party/blink/renderer/modules/launch/launch_params.h +++ b/third_party/blink/renderer/modules/launch/launch_params.h
@@ -5,7 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_LAUNCH_LAUNCH_PARAMS_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_LAUNCH_LAUNCH_PARAMS_H_ -#include "third_party/blink/renderer/modules/file_system_access/native_file_system_handle.h" +#include "third_party/blink/renderer/modules/file_system_access/file_system_handle.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/heap/heap_allocator.h" @@ -18,16 +18,16 @@ DEFINE_WRAPPERTYPEINFO(); public: - explicit LaunchParams(HeapVector<Member<NativeFileSystemHandle>> files); + explicit LaunchParams(HeapVector<Member<FileSystemHandle>> files); ~LaunchParams() override; // LaunchParams IDL interface. - const HeapVector<Member<NativeFileSystemHandle>>& files() { return files_; } + const HeapVector<Member<FileSystemHandle>>& files() { return files_; } void Trace(Visitor*) const override; private: - HeapVector<Member<NativeFileSystemHandle>> files_; + HeapVector<Member<FileSystemHandle>> files_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/launch/web_launch_service_impl.cc b/third_party/blink/renderer/modules/launch/web_launch_service_impl.cc index 54a60780..8bd62ab 100644 --- a/third_party/blink/renderer/modules/launch/web_launch_service_impl.cc +++ b/third_party/blink/renderer/modules/launch/web_launch_service_impl.cc
@@ -37,9 +37,9 @@ if (!window_) return; - HeapVector<Member<NativeFileSystemHandle>> files; + HeapVector<Member<FileSystemHandle>> files; for (auto& entry : entries) { - files.push_back(NativeFileSystemHandle::CreateFromMojoEntry( + files.push_back(FileSystemHandle::CreateFromMojoEntry( std::move(entry), window_->GetExecutionContext())); }
diff --git a/third_party/blink/renderer/modules/webcodecs/color_space_primary_id.idl b/third_party/blink/renderer/modules/webcodecs/color_space_primary_id.idl index 60392d5..68ef2e9 100644 --- a/third_party/blink/renderer/modules/webcodecs/color_space_primary_id.idl +++ b/third_party/blink/renderer/modules/webcodecs/color_space_primary_id.idl
@@ -6,7 +6,7 @@ enum ColorSpacePrimaryID { "BT709", - "BT407M", + "BT470M", "BT470BG", "SMPTE170M", "SMPTE240M",
diff --git a/third_party/blink/renderer/modules/webcodecs/video_decoder.cc b/third_party/blink/renderer/modules/webcodecs/video_decoder.cc index eacd2075..14e0339 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_decoder.cc +++ b/third_party/blink/renderer/modules/webcodecs/video_decoder.cc
@@ -16,6 +16,8 @@ #include "media/media_buildflags.h" #include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h" #include "third_party/blink/public/platform/platform.h" +#include "third_party/blink/renderer/bindings/core/v8/script_promise.h" +#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_video_chunk.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_config.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" @@ -26,6 +28,7 @@ #include "third_party/blink/renderer/platform/bindings/exception_code.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" +#include "third_party/blink/renderer/platform/bindings/to_v8.h" #include "third_party/blink/renderer/platform/heap/persistent.h" #include "third_party/blink/renderer/platform/instrumentation/use_counter.h" #include "third_party/blink/renderer/platform/wtf/functional.h" @@ -39,6 +42,125 @@ namespace blink { +bool ParseCodecString(const String& codec_string, + media::VideoType& out_video_type, + String& out_console_message) { + bool is_codec_ambiguous = true; + media::VideoCodec codec = media::kUnknownVideoCodec; + media::VideoCodecProfile profile = media::VIDEO_CODEC_PROFILE_UNKNOWN; + media::VideoColorSpace color_space = media::VideoColorSpace::REC709(); + uint8_t level = 0; + bool parse_succeeded = + media::ParseVideoCodecString("", codec_string.Utf8(), &is_codec_ambiguous, + &codec, &profile, &level, &color_space); + + if (!parse_succeeded) { + out_console_message = "Failed to parse codec string."; + return false; + } + + if (is_codec_ambiguous) { + out_console_message = "Codec string is ambiguous."; + return false; + } + + out_video_type = {codec, profile, level, color_space}; + return true; +} + +bool IsValidConfig(const VideoDecoderConfig& config, + media::VideoType& out_video_type, + String& out_console_message) { + if (!ParseCodecString(config.codec(), out_video_type, out_console_message)) + return false; + + if (config.hasCodedWidth()) { + if (config.codedWidth() == 0) { + out_console_message = + "Invalid codedWidth. Value must be greater than zero."; + return false; + } + + uint32_t crop_left = config.hasCropLeft() ? config.cropLeft() : 0; + uint32_t crop_width = + config.hasCropWidth() ? config.cropWidth() : config.codedWidth(); + + if (crop_width == 0) { + out_console_message = + "Invalid cropWidth. Value must be greater than zero."; + return false; + } + + if (crop_left + crop_width > config.codedWidth()) { + out_console_message = + "Invalid cropLeft + cropWidth. Sum must not exceed codedWidth."; + return false; + } + } else { // !config.hasCodedWidth() + if (config.hasCropLeft()) { + out_console_message = + "Invalid config. cropLeft specified without codedWidth."; + return false; + } + + if (config.hasCropWidth()) { + out_console_message = + "Invalid config. cropWidth specified without codedWidth."; + return false; + } + } + + if (config.hasCodedHeight()) { + if (config.codedHeight() == 0) { + out_console_message = + "Invalid codedHeight. Value must be greater than zero."; + return false; + } + + uint32_t crop_top = config.hasCropTop() ? config.cropTop() : 0; + uint32_t crop_height = + config.hasCropHeight() ? config.cropHeight() : config.codedHeight(); + + if (crop_height == 0) { + out_console_message = + "Invalid cropHeight. Value must be greater than zero."; + return false; + } + + if (crop_top + crop_height > config.codedHeight()) { + out_console_message = + "Invalid cropTop + cropHeight. Sum must not exceed codedHeight."; + return false; + } + } else { // !config.hasCodedHeight() + if (config.hasCropTop()) { + out_console_message = + "Invalid config. cropTop specified without codedHeight."; + return false; + } + + if (config.hasCropHeight()) { + out_console_message = + "Invalid config. cropHeight specified without codedHeight."; + return false; + } + } + + if (config.hasDisplayWidth() && config.displayWidth() == 0) { + out_console_message = + "Invalid displayWidth. Value must be greater than zero."; + return false; + } + + if (config.hasDisplayHeight() && config.displayHeight() == 0) { + out_console_message = + "Invalid displayHeight. Value must be greater than zero."; + return false; + } + + return true; +} + // static std::unique_ptr<VideoDecoderTraits::MediaDecoderType> VideoDecoderTraits::CreateDecoder( @@ -96,6 +218,24 @@ } // static +ScriptPromise VideoDecoder::isConfigSupported(ScriptState* script_state, + const VideoDecoderConfig* config, + ExceptionState& exception_state) { + media::VideoType video_type; + String console_message; + + if (!IsValidConfig(*config, video_type, console_message)) { + exception_state.ThrowTypeError(console_message); + return ScriptPromise(); + } + + // TODO(https://crbug.com/1164013): Add async checks for hardware support upon + // adding "acceleration" options to the config. + bool is_supported = media::IsSupportedVideoType(video_type); + return ScriptPromise::Cast(script_state, ToV8(is_supported, script_state)); +} + +// static CodecConfigEval VideoDecoder::MakeMediaVideoDecoderConfig( const ConfigType& config, MediaConfigType& out_media_config, @@ -104,29 +244,10 @@ std::unique_ptr<media::mp4::AVCDecoderConfigurationRecord>& out_h264_avcc, #endif // BUILDFLAG(USE_PROPRIETARY_CODECS) String& out_console_message) { - bool is_codec_ambiguous = true; - media::VideoCodec codec = media::kUnknownVideoCodec; - media::VideoCodecProfile profile = media::VIDEO_CODEC_PROFILE_UNKNOWN; - media::VideoColorSpace color_space = media::VideoColorSpace::REC709(); - uint8_t level = 0; - bool parse_succeeded = media::ParseVideoCodecString( - "", config.codec().Utf8(), &is_codec_ambiguous, &codec, &profile, &level, - &color_space); + media::VideoType video_type; - if (!parse_succeeded) { - out_console_message = "Failed to parse codec string."; + if (!IsValidConfig(config, video_type, out_console_message)) return CodecConfigEval::kInvalid; - } - - if (is_codec_ambiguous) { - out_console_message = "Codec string is ambiguous."; - return CodecConfigEval::kInvalid; - } - - if (!media::IsSupportedVideoType({codec, profile, level, color_space})) { - out_console_message = "Configuration is not supported."; - return CodecConfigEval::kUnsupported; - } // TODO(sandersd): Can we allow shared ArrayBuffers? std::vector<uint8_t> extra_data; @@ -147,7 +268,7 @@ } #if BUILDFLAG(USE_PROPRIETARY_CODECS) - if (codec == media::kCodecH264) { + if (video_type.codec == media::kCodecH264) { if (extra_data.empty()) { out_console_message = "H.264 configuration must include an avcC description."; @@ -169,7 +290,7 @@ out_h264_converter.reset(); } #else - if (codec == media::kCodecH264) { + if (video_type.codec == media::kCodecH264) { out_console_message = "H.264 decoding is not supported."; return CodecConfigEval::kUnsupported; } @@ -180,11 +301,11 @@ // match. gfx::Size size = gfx::Size(1280, 720); - out_media_config.Initialize(codec, profile, - media::VideoDecoderConfig::AlphaMode::kIsOpaque, - color_space, media::kNoTransformation, size, - gfx::Rect(gfx::Point(), size), size, extra_data, - media::EncryptionScheme::kUnencrypted); + out_media_config.Initialize( + video_type.codec, video_type.profile, + media::VideoDecoderConfig::AlphaMode::kIsOpaque, video_type.color_space, + media::kNoTransformation, size, gfx::Rect(gfx::Point(), size), size, + extra_data, media::EncryptionScheme::kUnencrypted); return CodecConfigEval::kSupported; }
diff --git a/third_party/blink/renderer/modules/webcodecs/video_decoder.h b/third_party/blink/renderer/modules/webcodecs/video_decoder.h index c88e261..b3020dfb 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_decoder.h +++ b/third_party/blink/renderer/modules/webcodecs/video_decoder.h
@@ -48,6 +48,7 @@ class VideoDecoderInit; class VideoFrame; class V8VideoFrameOutputCallback; +class ScriptPromise; class MODULES_EXPORT VideoDecoderTraits { public: @@ -86,6 +87,10 @@ const VideoDecoderInit*, ExceptionState&); + static ScriptPromise isConfigSupported(ScriptState*, + const VideoDecoderConfig*, + ExceptionState&); + // For use by MediaSource and by ::MakeMediaConfig. static CodecConfigEval MakeMediaVideoDecoderConfig( const ConfigType& config,
diff --git a/third_party/blink/renderer/modules/webcodecs/video_decoder.idl b/third_party/blink/renderer/modules/webcodecs/video_decoder.idl index f805b5d44..3213222 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_decoder.idl +++ b/third_party/blink/renderer/modules/webcodecs/video_decoder.idl
@@ -35,6 +35,9 @@ // TODO(sandersd): Consider emitting an event when this number decreases. readonly attribute long decodeQueueSize; + // Which state the decoder is in, indicating which methods can be called. + readonly attribute CodecState state; + // Set the stream configuration for future decode() requests. // // The next decode request must be for a keyframe. @@ -73,6 +76,7 @@ // Not recoverable: make a new VideoDecoder if needed. [RaisesException] void close(); - // Which state the decoder is in, indicating which methods can be called. - readonly attribute CodecState state; + // Call prior to configure() to determine whether config will be supported. + [CallWith=ScriptState, RaisesException] + static Promise<boolean> isConfigSupported(VideoDecoderConfig config); };
diff --git a/third_party/blink/renderer/modules/webcodecs/video_frame.cc b/third_party/blink/renderer/modules/webcodecs/video_frame.cc index 314f845..60fcc365 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_frame.cc +++ b/third_party/blink/renderer/modules/webcodecs/video_frame.cc
@@ -213,6 +213,11 @@ // a VideoFrame instead of using writable_addr() here. reinterpret_cast<uint8_t*>(pm.writable_addr()), pm.computeByteSize(), timestamp); + if (!frame) { + exception_state.ThrowDOMException(DOMExceptionCode::kOperationError, + "Failed to create video frame"); + return nullptr; + } frame->set_color_space(gfx::ColorSpace(*sk_color_space)); frame->AddDestructionObserver(ConvertToBaseOnceCallback(CrossThreadBindOnce( base::DoNothing::Once<sk_sp<SkImage>>(), std::move(sk_image))));
diff --git a/third_party/blink/renderer/modules/webgl/DEPS b/third_party/blink/renderer/modules/webgl/DEPS index bb4a18d4..2e4eb39 100644 --- a/third_party/blink/renderer/modules/webgl/DEPS +++ b/third_party/blink/renderer/modules/webgl/DEPS
@@ -8,6 +8,7 @@ "+gpu/config/gpu_feature_info.h", "+media/base/video_frame.h", "+media/base/wait_and_replace_sync_token_client.h", + "+media/video/gpu_memory_buffer_video_frame_pool.h", "+skia/ext", "+third_party/blink/renderer/modules/webcodecs", "+ui/gl/gpu_preference.h",
diff --git a/third_party/blink/renderer/modules/webgl/webgl_webcodecs_video_frame.cc b/third_party/blink/renderer/modules/webgl/webgl_webcodecs_video_frame.cc index ed8db318..cf82e9b2 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_webcodecs_video_frame.cc +++ b/third_party/blink/renderer/modules/webgl/webgl_webcodecs_video_frame.cc
@@ -6,12 +6,16 @@ #include "build/build_config.h" #include "media/base/wait_and_replace_sync_token_client.h" +#include "media/video/gpu_memory_buffer_video_frame_pool.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_color_space.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_webgl_webcodecs_texture_info.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_webgl_webcodecs_video_frame_handle.h" #include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h" #include "third_party/blink/renderer/modules/webgl/webgl_unowned_texture.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" +#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" +#include "third_party/blink/renderer/platform/scheduler/public/worker_pool.h" +#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" #include "ui/gfx/color_transform.h" namespace blink { @@ -19,15 +23,168 @@ namespace { #if defined(OS_WIN) -const char* kRequiredExtension = "GL_NV_EGL_stream_consumer_external"; +const char kRequiredExtension[] = "GL_NV_EGL_stream_consumer_external"; #elif defined(OS_MAC) -const char* kRequiredExtension = "GL_ANGLE_texture_rectangle"; +const char kRequiredExtension[] = "GL_ANGLE_texture_rectangle"; #elif defined(OS_ANDROID) || defined(OS_CHROMEOS) -const char* kRequiredExtension = "GL_OES_EGL_image_external"; +const char kRequiredExtension[] = "GL_OES_EGL_image_external"; #else -const char* kRequiredExtension = ""; +const char kRequiredExtension[] = ""; #endif +void FillVideoColorSpace(VideoColorSpace* video_color_space, + gfx::ColorSpace& gfx_color_space) { + gfx::ColorSpace::PrimaryID primaries = gfx_color_space.GetPrimaryID(); + switch (primaries) { + case gfx::ColorSpace::PrimaryID::BT709: + video_color_space->setPrimaryID("BT709"); + break; + case gfx::ColorSpace::PrimaryID::BT470M: + video_color_space->setPrimaryID("BT470M"); + break; + case gfx::ColorSpace::PrimaryID::BT470BG: + video_color_space->setPrimaryID("BT470BG"); + break; + case gfx::ColorSpace::PrimaryID::SMPTE170M: + video_color_space->setPrimaryID("SMPTE170M"); + break; + case gfx::ColorSpace::PrimaryID::SMPTE240M: + video_color_space->setPrimaryID("SMPTE240M"); + break; + case gfx::ColorSpace::PrimaryID::FILM: + video_color_space->setPrimaryID("FILM"); + break; + case gfx::ColorSpace::PrimaryID::BT2020: + video_color_space->setPrimaryID("BT2020"); + break; + case gfx::ColorSpace::PrimaryID::SMPTEST428_1: + video_color_space->setPrimaryID("SMPTEST428_1"); + break; + case gfx::ColorSpace::PrimaryID::SMPTEST431_2: + video_color_space->setPrimaryID("SMPTEST431_2"); + break; + case gfx::ColorSpace::PrimaryID::SMPTEST432_1: + video_color_space->setPrimaryID("SMPTEST432_1"); + break; + // TODO(jie.a.chen@intel.com): Need to check EBU_3213_E. + default:; + } + + gfx::ColorSpace::TransferID transfer = gfx_color_space.GetTransferID(); + switch (transfer) { + case gfx::ColorSpace::TransferID::BT709: +#if defined(OS_MAC) + // TODO(jie.a.chen@intel.com): BT709_APPLE is not available in WebCodecs. + case gfx::ColorSpace::TransferID::BT709_APPLE: +#endif + video_color_space->setTransferID("BT709"); + break; + case gfx::ColorSpace::TransferID::GAMMA22: + video_color_space->setTransferID("GAMMA22"); + break; + case gfx::ColorSpace::TransferID::GAMMA28: + video_color_space->setTransferID("GAMMA28"); + break; + case gfx::ColorSpace::TransferID::SMPTE170M: + video_color_space->setTransferID("SMPTE170M"); + break; + case gfx::ColorSpace::TransferID::SMPTE240M: + video_color_space->setTransferID("SMPTE240M"); + break; + case gfx::ColorSpace::TransferID::LINEAR: + video_color_space->setTransferID("LINEAR"); + break; + case gfx::ColorSpace::TransferID::LOG: + video_color_space->setTransferID("LOG"); + break; + case gfx::ColorSpace::TransferID::LOG_SQRT: + video_color_space->setTransferID("LOG_SQRT"); + break; + case gfx::ColorSpace::TransferID::IEC61966_2_4: + video_color_space->setTransferID("IEC61966_2_4"); + break; + case gfx::ColorSpace::TransferID::BT1361_ECG: + video_color_space->setTransferID("BT1361_ECG"); + break; + case gfx::ColorSpace::TransferID::IEC61966_2_1: + video_color_space->setTransferID("IEC61966_2_1"); + break; + case gfx::ColorSpace::TransferID::BT2020_10: + video_color_space->setTransferID("BT2020_10"); + break; + + case gfx::ColorSpace::TransferID::BT2020_12: + video_color_space->setTransferID("BT2020_12"); + break; + case gfx::ColorSpace::TransferID::SMPTEST2084: + video_color_space->setTransferID("SMPTEST2084"); + break; + case gfx::ColorSpace::TransferID::SMPTEST428_1: + video_color_space->setTransferID("SMPTEST428_1"); + break; + default:; + } + + gfx::ColorSpace::MatrixID matrix = gfx_color_space.GetMatrixID(); + switch (matrix) { + case gfx::ColorSpace::MatrixID::RGB: + video_color_space->setMatrixID("RGB"); + break; + case gfx::ColorSpace::MatrixID::BT709: + video_color_space->setMatrixID("BT709"); + break; + case gfx::ColorSpace::MatrixID::FCC: + video_color_space->setMatrixID("FCC"); + break; + case gfx::ColorSpace::MatrixID::BT470BG: + video_color_space->setMatrixID("BT470BG"); + break; + case gfx::ColorSpace::MatrixID::SMPTE170M: + video_color_space->setMatrixID("SMPTE170M"); + break; + case gfx::ColorSpace::MatrixID::SMPTE240M: + video_color_space->setMatrixID("SMPTE240M"); + break; + case gfx::ColorSpace::MatrixID::YCOCG: + video_color_space->setMatrixID("YCOCG"); + break; + case gfx::ColorSpace::MatrixID::BT2020_NCL: + video_color_space->setMatrixID("BT2020_NCL"); + break; + case gfx::ColorSpace::MatrixID::BT2020_CL: + video_color_space->setMatrixID("BT2020_CL"); + break; + case gfx::ColorSpace::MatrixID::YDZDX: + video_color_space->setMatrixID("YDZDX"); + break; + default:; + } + + gfx::ColorSpace::RangeID range = gfx_color_space.GetRangeID(); + switch (range) { + case gfx::ColorSpace::RangeID::LIMITED: + video_color_space->setRangeID("LIMITED"); + break; + case gfx::ColorSpace::RangeID::FULL: + video_color_space->setRangeID("FULL"); + break; + case gfx::ColorSpace::RangeID::DERIVED: + video_color_space->setRangeID("DERIVED"); + break; + default:; + } +} + +void GetMediaTaskRunnerAndGpuFactoriesOnMainThread( + scoped_refptr<base::SingleThreadTaskRunner>* media_task_runner_out, + media::GpuVideoAcceleratorFactories** gpu_factories_out, + base::WaitableEvent* waitable_event) { + DCHECK(IsMainThread()); + *media_task_runner_out = Platform::Current()->MediaThreadTaskRunner(); + *gpu_factories_out = Platform::Current()->GetGpuFactories(); + waitable_event->Signal(); +} + } // namespace WebGLWebCodecsVideoFrame::WebGLWebCodecsVideoFrame( @@ -40,29 +197,39 @@ context->ContextGL()->Enable(GC3D_TEXTURE_RECTANGLE_ARB); #endif - // TODO(jie.a.chen@intel.com): More supports for HDR video. #if defined(OS_WIN) - sampler_type_ = "samplerExternalOES"; - sampler_func_ = "texture2D"; formats_supported[media::PIXEL_FORMAT_NV12] = true; - auto& components = format_to_components_map_[media::PIXEL_FORMAT_NV12]; - components[media::VideoFrame::kYPlane] = "r"; - components[media::VideoFrame::kUPlane] = "rg"; + auto& components_nv12 = format_to_components_map_[media::PIXEL_FORMAT_NV12]; + components_nv12[media::VideoFrame::kYPlane] = "r"; + components_nv12[media::VideoFrame::kUPlane] = "rg"; #elif defined(OS_MAC) - sampler_type_ = "sampler2DRect"; - sampler_func_ = "texture2DRect"; formats_supported[media::PIXEL_FORMAT_XRGB] = true; - auto& components = format_to_components_map_[media::PIXEL_FORMAT_XRGB]; - components[media::VideoFrame::kYPlane] = "rgba"; -#elif defined(OS_ANDROID) || defined(OS_CHROMEOS) - sampler_type_ = "samplerExternalOES"; - sampler_func_ = "texture2D"; + auto& components_xrgb = format_to_components_map_[media::PIXEL_FORMAT_XRGB]; + components_xrgb[media::VideoFrame::kYPlane] = "rgba"; +#elif defined(OS_ANDROID) formats_supported[media::PIXEL_FORMAT_ABGR] = true; - auto& components = format_to_components_map_[media::PIXEL_FORMAT_ABGR]; - components[media::VideoFrame::kYPlane] = "rgb"; + auto& components_abgr = format_to_components_map_[media::PIXEL_FORMAT_ABGR]; + components_abgr[media::VideoFrame::kYPlane] = "rgb"; + + // GpuMemoryBufferVideoFramePool + formats_supported[media::PIXEL_FORMAT_NV12] = true; + auto& components_nv12 = format_to_components_map_[media::PIXEL_FORMAT_NV12]; + components_nv12[media::VideoFrame::kYPlane] = "r"; + components_nv12[media::VideoFrame::kUPlane] = "rg"; +#elif defined(OS_CHROMEOS) + formats_supported[media::PIXEL_FORMAT_ABGR] = true; + auto& components_abgr = format_to_components_map_[media::PIXEL_FORMAT_ABGR]; + components_abgr[media::VideoFrame::kYPlane] = "rgb"; #endif } +WebGLWebCodecsVideoFrame::~WebGLWebCodecsVideoFrame() { + if (gpu_memory_buffer_pool_) { + media_task_runner_->DeleteSoon(FROM_HERE, + std::move(gpu_memory_buffer_pool_)); + } +} + WebGLExtensionName WebGLWebCodecsVideoFrame::GetName() const { return kWebGLWebCodecsVideoFrameName; } @@ -92,29 +259,68 @@ if (!video_frame || scoped.IsLost()) return nullptr; + const char* sampler_type = "sampler2D"; + const char* sampler_func = "texture2D"; + gfx::ColorSpace src_color_space = gfx::ColorSpace::CreateREC709(); + media::VideoPixelFormat pixel_format = media::PIXEL_FORMAT_UNKNOWN; +#if defined(OS_WIN) + sampler_type = "samplerExternalOES"; + pixel_format = media::PIXEL_FORMAT_NV12; +#elif defined(OS_MAC) + sampler_type = "sampler2DRect"; + sampler_func = "texture2DRect"; + pixel_format = media::PIXEL_FORMAT_XRGB; +#elif defined(OS_ANDROID) || defined(OS_CHROMEOS) + sampler_type = "samplerExternalOES"; + pixel_format = media::PIXEL_FORMAT_ABGR; + src_color_space = gfx::ColorSpace::CreateSRGB(); +#endif + scoped_refptr<media::VideoFrame> frame = video_frame->frame(); if (!frame->HasTextures()) { - exception_state.ThrowTypeError("Unable to import a software video frame."); + InitializeGpuMemoryBufferPool(); + base::WaitableEvent waitable_event; + media_task_runner_->PostTask( + FROM_HERE, + base::BindOnce( + &media::GpuMemoryBufferVideoFramePool::MaybeCreateHardwareFrame, + base::Unretained(gpu_memory_buffer_pool_.get()), + base::RetainedRef(frame), + base::BindOnce( + &WebGLWebCodecsVideoFrame::OnHardwareVideoFrameCreated, + base::Unretained(this), base::Unretained(&waitable_event)))); + waitable_event.Wait(); + + if (frame == hardware_video_frame_) { + exception_state.ThrowTypeError( + "Unable to import a software video frame."); + return nullptr; + } + frame = std::move(hardware_video_frame_); +#if defined(OS_WIN) + sampler_type = "sampler2D"; +#elif defined(OS_ANDROID) + sampler_type = "sampler2D"; + pixel_format = frame->format(); + src_color_space = frame->ColorSpace(); +#endif + } + + if (!formats_supported[pixel_format]) { + exception_state.ThrowTypeError( + String::Format("VideoPixelFormat:%s is not supported yet.", + media::VideoPixelFormatToString(pixel_format).c_str())); return nullptr; } - if (!formats_supported[frame->format()]) { - std::ostringstream ss; - ss << "VideoPixelFormat:" - << media::VideoPixelFormatToString(frame->format()) - << " is not supported yet."; - exception_state.ThrowTypeError(ss.str().c_str()); - return nullptr; - } - - const auto& components = format_to_components_map_[frame->format()]; + const auto& components = format_to_components_map_[pixel_format]; HeapVector<Member<WebGLWebCodecsTextureInfo>> info_array; for (size_t tex = 0; tex < frame->NumTextures(); ++tex) { WebGLWebCodecsTextureInfo* texture_info = MakeGarbageCollected<WebGLWebCodecsTextureInfo>(); info_array.push_back(texture_info); - texture_info->setSamplerType(sampler_type_.c_str()); - texture_info->setSamplerFunc(sampler_func_.c_str()); + texture_info->setSamplerType(sampler_type); + texture_info->setSamplerFunc(sampler_func); texture_info->setComponents(components[tex].c_str()); auto* gl = scoped.Context()->ContextGL(); @@ -144,45 +350,27 @@ if (std::string(kRequiredExtension) != "") { video_frame_handle->setRequiredExtension(kRequiredExtension); } + // Remove "PIXEL_FORMAT_" prefix + video_frame_handle->setPixelFormat( + &VideoPixelFormatToString(pixel_format)[13]); + // TODO(jie.a.chen@intel.com): Is the colorspace/flip-y/pre-alpha of video // frame specific to OS only? For the same OS, does it vary for different // video streams? video_frame_handle->setFlipY(true); video_frame_handle->setPremultipliedAlpha(false); - gfx::ColorSpace src_color_space = frame->ColorSpace(); #if defined(OS_WIN) - video_frame_handle->setPixelFormat("NV12"); + DCHECK(frame->format() == media::PIXEL_FORMAT_NV12); + src_color_space = frame->ColorSpace(); #elif defined(OS_MAC) video_frame_handle->setRequiredExtension("GL_ARB_texture_rectangle"); - video_frame_handle->setPixelFormat("XRGB"); video_frame_handle->setPremultipliedAlpha(true); + src_color_space = frame->ColorSpace(); src_color_space = src_color_space.GetAsFullRangeRGB(); -#elif defined(OS_ANDROID) || defined(OS_CHROMEOS) - if (!frame->ColorSpace().IsValid()) { - video_frame_handle->setPixelFormat("ABGR"); - src_color_space = gfx::ColorSpace::CreateSRGB(); - } #endif VideoColorSpace* video_frame_color_space = MakeGarbageCollected<VideoColorSpace>(); - // TODO(jie.a.chen@intel.com): Add ToString() for color space members. -#if defined(OS_WIN) - video_frame_color_space->setPrimaryID("BT709"); - video_frame_color_space->setTransferID("BT709"); - video_frame_color_space->setMatrixID("BT709"); - video_frame_color_space->setRangeID("LIMITED"); -#elif defined(OS_MAC) - video_frame_color_space->setPrimaryID("SMPTE240M"); - // TODO(jie.a.chen@intel.com): The actual BT709_APPLE is not available. - video_frame_color_space->setTransferID("BT709"); - video_frame_color_space->setMatrixID("RGB"); - video_frame_color_space->setRangeID("FULL"); -#elif defined(OS_ANDROID) || defined(OS_CHROMEOS) - video_frame_color_space->setPrimaryID("BT709"); - video_frame_color_space->setTransferID("IEC61966_2_1"); - video_frame_color_space->setMatrixID("RGB"); - video_frame_color_space->setRangeID("FULL"); -#endif + FillVideoColorSpace(video_frame_color_space, src_color_space); video_frame_handle->setColorSpace(video_frame_color_space); gfx::ColorSpace dst_color_space = gfx::ColorSpace::CreateSRGB(); @@ -225,4 +413,39 @@ return true; } +void WebGLWebCodecsVideoFrame::OnHardwareVideoFrameCreated( + base::WaitableEvent* waitable_event, + scoped_refptr<media::VideoFrame> video_frame) { + hardware_video_frame_ = std::move(video_frame); + waitable_event->Signal(); +} + +void WebGLWebCodecsVideoFrame::InitializeGpuMemoryBufferPool() { + if (!worker_task_runner_) { + worker_task_runner_ = worker_pool::CreateSequencedTaskRunner({}); + } + if (!gpu_memory_buffer_pool_) { + media::GpuVideoAcceleratorFactories* gpu_factories = nullptr; + if (IsMainThread()) { + media_task_runner_ = Platform::Current()->MediaThreadTaskRunner(); + gpu_factories = Platform::Current()->GetGpuFactories(); + } else { + base::WaitableEvent waitable_event; + // TODO(crbug.com/1164152): Lift the main thread restriction. + if (PostCrossThreadTask( + *Thread::MainThread()->GetTaskRunner(), FROM_HERE, + CrossThreadBindOnce( + &GetMediaTaskRunnerAndGpuFactoriesOnMainThread, + CrossThreadUnretained(&media_task_runner_), + CrossThreadUnretained(&gpu_factories), + CrossThreadUnretained(&waitable_event)))) { + waitable_event.Wait(); + } + } + gpu_memory_buffer_pool_ = + std::make_unique<media::GpuMemoryBufferVideoFramePool>( + media_task_runner_, worker_task_runner_, gpu_factories); + } +} + } // namespace blink
diff --git a/third_party/blink/renderer/modules/webgl/webgl_webcodecs_video_frame.h b/third_party/blink/renderer/modules/webgl/webgl_webcodecs_video_frame.h index c6fa3374..644d01c 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_webcodecs_video_frame.h +++ b/third_party/blink/renderer/modules/webgl/webgl_webcodecs_video_frame.h
@@ -10,6 +10,10 @@ #include "third_party/blink/renderer/modules/webcodecs/video_frame.h" #include "third_party/blink/renderer/modules/webgl/webgl_extension.h" +namespace media { +class GpuMemoryBufferVideoFramePool; +} // namespace media + namespace blink { class WebGLWebCodecsVideoFrameHandle; @@ -18,6 +22,8 @@ DEFINE_WRAPPERTYPEINFO(); public: + ~WebGLWebCodecsVideoFrame() override; + static bool Supported(WebGLRenderingContextBase*); static const char* ExtensionName(); @@ -36,9 +42,13 @@ ExceptionState&); private: + void OnHardwareVideoFrameCreated( + base::WaitableEvent* waitable_event, + scoped_refptr<media::VideoFrame> video_frame); + + void InitializeGpuMemoryBufferPool(); + std::bitset<media::PIXEL_FORMAT_MAX + 1> formats_supported; - std::string sampler_type_; - std::string sampler_func_; std::array<std::array<std::string, media::VideoFrame::kMaxPlanes>, media::PIXEL_FORMAT_MAX + 1> format_to_components_map_; @@ -47,6 +57,11 @@ // This holds the reference for all video frames being imported, but not // yet released. VideoFrameHandleMap tex0_to_video_frame_map_; + + std::unique_ptr<media::GpuMemoryBufferVideoFramePool> gpu_memory_buffer_pool_; + scoped_refptr<base::SequencedTaskRunner> worker_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_; + scoped_refptr<media::VideoFrame> hardware_video_frame_; }; } // namespace blink
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn index 1d87a9f..c37c11a 100644 --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1658,6 +1658,7 @@ "//third_party/blink/public/common", "//third_party/blink/public/strings", "//third_party/blink/renderer/platform/wtf", + "//third_party/blink/renderer/platform/wtf:buildflags", "//third_party/ced", "//third_party/emoji-segmenter", "//third_party/harfbuzz-ng:hb_scoped_util",
diff --git a/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h b/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h index 865c5c5..80a5914 100644 --- a/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h +++ b/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h
@@ -11,9 +11,17 @@ #include "base/macros.h" #include "third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" +#include "third_party/blink/renderer/platform/wtf/buildflags.h" #include "third_party/blink/renderer/platform/wtf/vector_traits.h" #include "v8/include/v8.h" +namespace cppgc { + +template <typename T> +struct TraceTrait; + +} // namespace cppgc + namespace blink { template <typename T> @@ -123,13 +131,37 @@ } v8::TracedReference<T> handle_; -}; + friend struct cppgc::TraceTrait<TraceWrapperV8Reference<T>>; +}; +} // namespace blink + +#if BUILDFLAG(USE_V8_OILPAN) + +namespace cppgc { template <typename T> struct TraceTrait<TraceWrapperV8Reference<T>> { STATIC_ONLY(TraceTrait); - public: + static cppgc::TraceDescriptor GetTraceDescriptor( + const TraceWrapperV8Reference<T>* ref) { + return {ref, Trace}; + } + + static void Trace(Visitor* visitor, const void* self) { + visitor->Trace( + static_cast<const TraceWrapperV8Reference<T>*>(self)->handle_); + } +}; +} // namespace cppgc + +#else // !USE_V8_OILPAN + +namespace blink { +template <typename T> +struct TraceTrait<TraceWrapperV8Reference<T>> { + STATIC_ONLY(TraceTrait); + static TraceDescriptor GetTraceDescriptor( const TraceWrapperV8Reference<T>* ref) { return {ref, TraceTrait<TraceWrapperV8Reference<T>>::Trace}; @@ -139,9 +171,10 @@ visitor->Trace(*static_cast<const TraceWrapperV8Reference<T>*>(ref)); } }; - } // namespace blink +#endif // !USE_V8_OILPAN + namespace WTF { template <typename T>
diff --git a/third_party/blink/renderer/platform/graphics/graphics_context.cc b/third_party/blink/renderer/platform/graphics/graphics_context.cc index 847557a..9f46f5ea 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_context.cc +++ b/third_party/blink/renderer/platform/graphics/graphics_context.cc
@@ -503,6 +503,30 @@ return UnionRect(bounds, offset_bounds); } +static void AdjustHoleForSideClipping(FloatRect& hole_rect, + const FloatSize& shadow_offset, + float shadow_blur, + GraphicsContext::Edges clipped_edges) { + if (clipped_edges & GraphicsContext::kLeftEdge) { + float extend_by = std::max(shadow_offset.Width(), 0.0f) + shadow_blur; + hole_rect.Move(-extend_by, 0); + hole_rect.SetWidth(hole_rect.Width() + extend_by); + } + if (clipped_edges & GraphicsContext::kTopEdge) { + float extend_by = std::max(shadow_offset.Height(), 0.0f) + shadow_blur; + hole_rect.Move(0, -extend_by); + hole_rect.SetHeight(hole_rect.Height() + extend_by); + } + if (clipped_edges & GraphicsContext::kRightEdge) { + float shrink_by = std::min(shadow_offset.Width(), 0.0f) - shadow_blur; + hole_rect.SetWidth(hole_rect.Width() - shrink_by); + } + if (clipped_edges & GraphicsContext::kBottomEdge) { + float shrink_by = std::min(shadow_offset.Height(), 0.0f) - shadow_blur; + hole_rect.SetHeight(hole_rect.Height() - shrink_by); + } +} + void GraphicsContext::DrawInnerShadow(const FloatRoundedRect& rect, const Color& orig_shadow_color, const FloatSize& shadow_offset, @@ -514,34 +538,13 @@ FloatRect hole_rect(rect.Rect()); hole_rect.Inflate(-shadow_spread); - if (hole_rect.IsEmpty()) { FillRoundedRect(rect, Color(shadow_color)); return; } + AdjustHoleForSideClipping(hole_rect, shadow_offset, shadow_blur, + clipped_edges); - if (clipped_edges & kLeftEdge) { - hole_rect.Move(-std::max(shadow_offset.Width(), 0.0f) - shadow_blur, 0); - hole_rect.SetWidth(hole_rect.Width() + - std::max(shadow_offset.Width(), 0.0f) + shadow_blur); - } - if (clipped_edges & kTopEdge) { - hole_rect.Move(0, -std::max(shadow_offset.Height(), 0.0f) - shadow_blur); - hole_rect.SetHeight(hole_rect.Height() + - std::max(shadow_offset.Height(), 0.0f) + shadow_blur); - } - if (clipped_edges & kRightEdge) - hole_rect.SetWidth(hole_rect.Width() - - std::min(shadow_offset.Width(), 0.0f) + shadow_blur); - if (clipped_edges & kBottomEdge) - hole_rect.SetHeight(hole_rect.Height() - - std::min(shadow_offset.Height(), 0.0f) + shadow_blur); - - Color fill_color(SkColorGetR(shadow_color), SkColorGetG(shadow_color), - SkColorGetB(shadow_color), 255); - - FloatRect outer_rect = AreaCastingShadowInHole(rect.Rect(), shadow_blur, - shadow_spread, shadow_offset); FloatRoundedRect rounded_hole(hole_rect, rect.GetRadii()); GraphicsContextStateSaver state_saver(*this); @@ -556,11 +559,15 @@ } DrawLooperBuilder draw_looper_builder; - draw_looper_builder.AddShadow(FloatSize(shadow_offset), shadow_blur, - shadow_color, + draw_looper_builder.AddShadow(shadow_offset, shadow_blur, shadow_color, DrawLooperBuilder::kShadowRespectsTransforms, DrawLooperBuilder::kShadowIgnoresAlpha); SetDrawLooper(draw_looper_builder.DetachDrawLooper()); + + Color fill_color(SkColorGetR(shadow_color), SkColorGetG(shadow_color), + SkColorGetB(shadow_color)); + FloatRect outer_rect = AreaCastingShadowInHole(rect.Rect(), shadow_blur, + shadow_spread, shadow_offset); FillRectWithRoundedHole(outer_rect, rounded_hole, fill_color); }
diff --git a/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.cc b/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.cc index 06cb2110..d230b83 100644 --- a/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.cc +++ b/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.cc
@@ -34,9 +34,9 @@ } ThreadState::ThreadState(v8::CppHeap& cpp_heap) - : cpp_heap_(cpp_heap), - allocation_handle_(cpp_heap.GetAllocationHandle()) - thread_id_(CurrentThread()) {} + : allocation_handle_(cpp_heap.GetAllocationHandle()), + cpp_heap_(cpp_heap), + thread_id_(CurrentThread()) {} ThreadState::~ThreadState() { DCHECK(!IsMainThread());
diff --git a/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.h b/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.h index c759d89..3b3cb82 100644 --- a/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.h +++ b/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.h
@@ -5,6 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_THREAD_STATE_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_THREAD_STATE_H_ +#include "base/compiler_specific.h" #include "base/lazy_instance.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" #include "third_party/blink/renderer/platform/wtf/thread_specific.h" @@ -68,6 +69,7 @@ ALWAYS_INLINE cppgc::AllocationHandle& allocation_handle() const { return allocation_handle_; } + ALWAYS_INLINE v8::CppHeap& cpp_heap() const { return cpp_heap_; } private: // Main-thread ThreadState avoids TLS completely by using a regular global.
diff --git a/third_party/blink/renderer/platform/mojo/drag_mojom_traits.cc b/third_party/blink/renderer/platform/mojo/drag_mojom_traits.cc index 8074424..3aa3c34 100644 --- a/third_party/blink/renderer/platform/mojo/drag_mojom_traits.cc +++ b/third_party/blink/renderer/platform/mojo/drag_mojom_traits.cc
@@ -103,12 +103,12 @@ item.filename_data = blink::FilePathToWebString(filename_data); item.display_name_data = blink::FilePathToWebString(display_name_data); mojo::PendingRemote<::blink::mojom::blink::FileSystemAccessDragDropToken> - native_file_system_token( + file_system_access_token( data.TakeFileSystemAccessToken<mojo::PendingRemote< ::blink::mojom::blink::FileSystemAccessDragDropToken>>()); - item.native_file_system_entry = - base::MakeRefCounted<::blink::NativeFileSystemDropData>( - std::move(native_file_system_token)); + item.file_system_access_entry = + base::MakeRefCounted<::blink::FileSystemAccessDropData>( + std::move(file_system_access_token)); *out = std::move(item); return true; @@ -187,7 +187,7 @@ file_system_access_token(const blink::WebDragData::Item& item) { // Should never have to send a transfer token information from the renderer // to the browser. - DCHECK(!item.native_file_system_entry); + DCHECK(!item.file_system_access_entry); return mojo::NullRemote(); }
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 9c35cb5..5b045a5 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -406,14 +406,6 @@ status: "experimental", }, { - name: "CookieStoreDocument", - status: "stable", - }, - { - name: "CookieStoreWorker", - status: "stable", - }, - { name: "CookiesWithoutSameSiteMustBeSecure", status: "test", }, @@ -622,6 +614,17 @@ name: "CSSSnapSize", status: "experimental", }, + { + // Support for CSS ::spelling-error, ::grammar-error, and the + // spelling-error and grammar-error values in text-decoration-line. + // + // https://drafts.csswg.org/css-pseudo-4/#selectordef-spelling-error + // https://drafts.csswg.org/css-pseudo-4/#selectordef-grammar-error + // https://drafts.csswg.org/css-text-decor-4/#valdef-text-decoration-line-spelling-error + // https://drafts.csswg.org/css-text-decor-4/#valdef-text-decoration-line-grammar-error + name: "CSSSpellingGrammarErrors", + status: "test", + }, // Make system color keywords compute to themselves. // https://github.com/w3c/csswg-drafts/issues/3847 { @@ -869,7 +872,7 @@ // Also enabled when blink::features::kFileHandlingAPI is overridden // on the command line (or via chrome://flags). name: "FileHandling", - depends_on: ["NativeFileSystem"], + depends_on: ["FileSystemAccess"], status: {"Android": "test", "default": "experimental"}, origin_trial_feature_name: "FileHandling", origin_trial_os: ["win", "mac", "linux", "chromeos"], @@ -879,6 +882,15 @@ status: "stable", }, { + // Also enabled when blink::features::kNativeFileSystemAPI is overridden + // on the command line (or via chrome://flags). + name: "FileSystemAccess", + status: {"Android": "test", "default": "stable"}, + // TODO(mek): Remove origin trial integration. + origin_trial_feature_name: "NativeFileSystem2", + origin_trial_os: ["win", "mac", "linux", "chromeos"], + }, + { // In-development features for the File System Access API. name: "FileSystemAccessAPIExperimental", status: "experimental", @@ -1303,15 +1315,6 @@ status: "stable", }, { - // Also enabled when blink::features::kNativeFileSystemAPI is overridden - // on the command line (or via chrome://flags). - name: "NativeFileSystem", - status: {"Android": "test", "default": "stable"}, - // TODO(mek): Remove origin trial integration. - origin_trial_feature_name: "NativeFileSystem2", - origin_trial_os: ["win", "mac", "linux", "chromeos"], - }, - { name: "NativeIO", status: "experimental", }, @@ -2180,7 +2183,8 @@ }, { name: "WebHID", - status: {"Android": "", "default": "stable"}, + origin_trial_feature_name: "WebHID", + status: {"Android": "", "default": "experimental"}, }, { name: "WebID",
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 2caf785..80502aa 100644 --- a/third_party/blink/renderer/platform/scheduler/worker/worker_thread.h +++ b/third_party/blink/renderer/platform/scheduler/worker/worker_thread.h
@@ -15,6 +15,7 @@ #include "third_party/blink/public/platform/web_private_ptr.h" #include "third_party/blink/renderer/platform/heap/gc_task_runner.h" #include "third_party/blink/renderer/platform/scheduler/public/thread.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" namespace blink { class BlinkGCMemoryDumpProvider;
diff --git a/third_party/blink/renderer/platform/supplementable.h b/third_party/blink/renderer/platform/supplementable.h index 7c309d3..1ff7c996 100644 --- a/third_party/blink/renderer/platform/supplementable.h +++ b/third_party/blink/renderer/platform/supplementable.h
@@ -77,7 +77,7 @@ // public: // static const char kSupplementName[]; // -// NavigatorFoo& From(Navigator&); +// static NavigatorFoo& From(Navigator&); // } // // // static
diff --git a/third_party/blink/renderer/platform/weborigin/security_origin.h b/third_party/blink/renderer/platform/weborigin/security_origin.h index c97a41b..9792167 100644 --- a/third_party/blink/renderer/platform/weborigin/security_origin.h +++ b/third_party/blink/renderer/platform/weborigin/security_origin.h
@@ -230,7 +230,6 @@ bool CanAccessCookies() const { return !IsOpaque(); } bool CanAccessPasswordManager() const { return !IsOpaque(); } bool CanAccessFileSystem() const { return !IsOpaque(); } - bool CanAccessNativeFileSystem() const { return !IsOpaque(); } bool CanAccessCacheStorage() const { return !IsOpaque(); } bool CanAccessLocks() const { return !IsOpaque(); } bool CanAccessSessionStorage() const { return !IsOpaque(); }
diff --git a/third_party/blink/renderer/platform/wtf/allocator/partitions.cc b/third_party/blink/renderer/platform/wtf/allocator/partitions.cc index b0eb5b71..e8b3b486 100644 --- a/third_party/blink/renderer/platform/wtf/allocator/partitions.cc +++ b/third_party/blink/renderer/platform/wtf/allocator/partitions.cc
@@ -34,6 +34,7 @@ #include "base/allocator/partition_allocator/memory_reclaimer.h" #include "base/allocator/partition_allocator/oom.h" #include "base/allocator/partition_allocator/page_allocator.h" +#include "base/allocator/partition_allocator/partition_alloc_constants.h" #include "base/allocator/partition_allocator/partition_alloc_features.h" #include "base/debug/alias.h" #include "base/no_destructor.h" @@ -48,9 +49,11 @@ const char* const Partitions::kAllocatedObjectPoolName = "partition_alloc/allocated_objects"; +#if defined(PA_HAS_64_BITS_POINTERS) && !ENABLE_REF_COUNT_FOR_BACKUP_REF_PTR // Runs PCScan on WTF partitions. const base::Feature kPCScanBlinkPartitions{"PCScanBlinkPartitions", base::FEATURE_DISABLED_BY_DEFAULT}; +#endif bool Partitions::initialized_ = false; @@ -103,7 +106,7 @@ buffer_root_ = buffer_allocator->root(); layout_root_ = layout_allocator->root(); -#if !ENABLE_REF_COUNT_FOR_BACKUP_REF_PTR +#if defined(PA_HAS_64_BITS_POINTERS) && !ENABLE_REF_COUNT_FOR_BACKUP_REF_PTR if (base::features::IsPartitionAllocPCScanEnabled() || base::FeatureList::IsEnabled(kPCScanBlinkPartitions)) { #if !BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py index 00d59cd4..31b83ef 100755 --- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py +++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -389,7 +389,7 @@ 'layout_invalidation_reason::.+', 'media_constraints_impl::.+', 'media_element_parser_helpers::.+', - 'native_file_system_error::.+', + 'file_system_access_error::.+', 'network_utils::.+', 'origin_trials::.+', 'paint_filter_builder::.+',
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/checkout.sh b/third_party/blink/tools/blinkpy/third_party/wpt/checkout.sh index 4f6fba2..1be9072 100755 --- a/third_party/blink/tools/blinkpy/third_party/wpt/checkout.sh +++ b/third_party/blink/tools/blinkpy/third_party/wpt/checkout.sh
@@ -27,7 +27,7 @@ # xargs on some platforms, so we remove those directories first. rm -fr html css # Remove all except white-listed. - comm -23 <(find . -type f | sort) <(cat ../WPTIncludeList | sort) | xargs -d '\n' -n 1 rm + comm -23 <(find . -type f -o -type l | sort) <(cat ../WPTIncludeList | sort) | xargs -d '\n' -n 1 rm find . -empty -type d -delete }
diff --git a/third_party/blink/web_tests/FlagExpectations/composite-after-paint b/third_party/blink/web_tests/FlagExpectations/composite-after-paint index 5e395d7..8dfab63 100644 --- a/third_party/blink/web_tests/FlagExpectations/composite-after-paint +++ b/third_party/blink/web_tests/FlagExpectations/composite-after-paint
@@ -64,6 +64,9 @@ crbug.com/1124979 compositing/video/video-controls-layer-creation.html [ Pass Failure ] crbug.com/1150468 virtual/composite-bgcolor-animation/external/wpt/css/css-backgrounds/animations/one-element-animation.html [ Crash ] +crbug.com/1150468 virtual/composite-bgcolor-animation/external/wpt/css/css-backgrounds/animations/one-element-three-keyframes-animation1.html [ Crash ] +crbug.com/1150468 virtual/composite-bgcolor-animation/external/wpt/css/css-backgrounds/animations/one-element-three-keyframes-animation2.html [ Crash ] +crbug.com/1150468 virtual/composite-bgcolor-animation/external/wpt/css/css-backgrounds/animations/one-element-three-keyframes-animation3.html [ Crash ] crbug.com/1150468 virtual/composite-bgcolor-animation/external/wpt/css/css-backgrounds/animations/one-element-transition.html [ Crash ] crbug.com/1157199 external/wpt/css/css-paint-api/column-count-crash.https.html [ Crash ]
diff --git a/third_party/blink/web_tests/LeakExpectations b/third_party/blink/web_tests/LeakExpectations index 0ef64b0..28cd6c2 100644 --- a/third_party/blink/web_tests/LeakExpectations +++ b/third_party/blink/web_tests/LeakExpectations
@@ -178,12 +178,6 @@ # Sheriff 2020-10-08 crbug.com/1136690 [ Linux ] http/tests/inspector-protocol/service-worker/service-worker-fetch-async-stacks.js [ Pass Timeout ] -# Sheriff 2021-01-06 -crbug.com/1163172 [ Linux ] external/wpt/css/selectors/focus-visible-003.html [ Pass Failure ] -crbug.com/1163172 [ Linux ] external/wpt/css/selectors/focus-visible-004.html [ Pass Failure ] -crbug.com/1163172 [ Linux ] external/wpt/css/selectors/focus-visible-015.html [ Pass Failure ] -crbug.com/1163172 [ Linux ] external/wpt/css/selectors/focus-visible-016.html [ Pass Failure ] - ########################################################################### # WARNING: Memory leaks must be fixed asap. Sheriff is expected to revert # # culprit CLs instead of suppressing the leaks. If you have any question, #
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 0865e97..0931a64 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -74,6 +74,7 @@ crbug.com/1132260 http/tests/devtools/components/linkifier.js [ Pass Failure ] crbug.com/1132260 http/tests/devtools/console/console-bad-stacktrace.js [ Pass Failure ] crbug.com/1132260 http/tests/devtools/console/console-uncaught-promise.js [ Pass Failure ] +crbug.com/1132260 http/tests/devtools/tracing/timeline-network/timeline-network-resource-details.js [ Pass Failure ] # With --enable-display-compositor-pixel-dump enabled by default, these three # tests fail. See crbug.com/887140 for more info. @@ -2473,6 +2474,7 @@ crbug.com/958381 [ Mac ] external/wpt/css/CSS2/tables/table-anonymous-objects-206.xht [ Failure ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 external/wpt/css/css-sizing/aspect-ratio/table-element-001.html [ Failure ] crbug.com/626703 external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-025.html [ Failure ] crbug.com/626703 external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-026.html [ Failure ] crbug.com/626703 external/wpt/html/interaction/focus/document-level-focus-apis/document-has-system-focus.html [ Timeout ] @@ -5935,3 +5937,9 @@ crbug.com/1161301 [ Mac10.15 ] external/wpt/webxr/xrSession_requestReferenceSpace_features.https.html [ Pass Timeout ] crbug.com/1161352 [ Mac10.14 ] virtual/controls-refresh-hc/fast/forms/color-scheme/search/search-appearance-basic.html [ Pass Timeout ] crbug.com/1161352 [ Mac10.14 ] external/wpt/webxr/xrSession_requestReferenceSpace_features.https.html [ Pass Failure Timeout ] + +# Failing on Webkit Linux Leak only: +crbug.com/1046784 http/tests/devtools/tracing/timeline-receive-response-event.js [ Pass Failure ] + +# Sheriff 2021-01-21 +crbug.com/1164166 [ Linux ] virtual/synchronous_html_parser/external/wpt/preload/avoid-prefetching-on-text-plain.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json index 0dd813e2..f43a58c 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -102639,6 +102639,19 @@ {} ] ], + "table-element-001.html": [ + "fd2dcd81dd90c6d82a3652750cea2370979aff7a", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], "zero-or-infinity-001.html": [ "760635c40e8fde8f3514761c77e83385592861b0", [ @@ -176808,270 +176821,6 @@ "b6c297cc77ddef6c4b0eae5c94a07d0827de89c7", [] ], - "name0001-expected": [ - "96527926e107477e66ab0386dea671d8973de695", - [] - ], - "name0001-test": [ - "3ce5f5f9824b95711aa93a82c45e39250aa225ed", - [] - ], - "name0002-expected": [ - "d4d3cda811bd744d741d883675d789e124c32449", - [] - ], - "name0002-test": [ - "d6eac8a757af54e177a04bf7d3b15e14080cdc5a", - [] - ], - "name0003-expected": [ - "0c00f45c4a479545f1272b6c7d3312f7b48d658a", - [] - ], - "name0003-test": [ - "7ea96155bd7752a8abffb7a85093fdd3fa19fc93", - [] - ], - "name0004-expected": [ - "b079529aa249748cdf1ada8ce4b99d12952745a7", - [] - ], - "name0004-test": [ - "99f0e61801a92ddc2034fec94fc61b02f1b2baf1", - [] - ], - "name0005-expected": [ - "a0f031bb34ed2284c99cab25c4864f7e55af6522", - [] - ], - "name0005-test": [ - "9e33e0c8e476c24b698b7c8061ea42a585b9ed73", - [] - ], - "name0006-expected": [ - "ee0e7d7c335d08c78793167fd581458b15e6a3ec", - [] - ], - "name0006-test": [ - "fbd03632c61b3df902d75dd8f11dcde5a7cf8634", - [] - ], - "name0007-expected": [ - "6d6e56ebe59b54fc030d7c88c72a142d1e5f7486", - [] - ], - "name0007-test": [ - "d41e64b87ec3d1e45cf0a9020c2a093063f8844f", - [] - ], - "name0008-expected": [ - "a4b8c2428258033c534e7ff05ac967dbe24ed9e9", - [] - ], - "name0008-test": [ - "7afcf700376b02f3a38c12752b0067cc66f3e190", - [] - ], - "name0009-expected": [ - "49506acc24893411e24dd9c63ed25f2b5945052d", - [] - ], - "name0009-test": [ - "f40d2c4d6b9e06be56505acb73594718724e5254", - [] - ], - "name0010-expected": [ - "1e72557892b01144f0cd3051a9a079fcc2253e46", - [] - ], - "name0010-test": [ - "fb4fd921be31471edd70aa0399c011aea48ee36d", - [] - ], - "name0011-expected": [ - "260d7028a0195e1c93da4cb10cac211016856e60", - [] - ], - "name0011-test": [ - "b36b72388f2b3dc6480dd798f57d8ed5624b5ae4", - [] - ], - "name0012-expected": [ - "0a2686a15257f03f02af93c39d410cc070e408fd", - [] - ], - "name0012-test": [ - "6927aac6fa061ad0e0be4f13f4d7c686602aef25", - [] - ], - "name0013-expected": [ - "87dec78b62265dd3dfd115e68ce526aef5213353", - [] - ], - "name0013-test": [ - "59ada98321c69945673b94c2504f81408224325b", - [] - ], - "name0014-expected": [ - "82bfe0e60acd0c9194bbbb5c33a0a4e95686d5fa", - [] - ], - "name0014-test": [ - "a113e99be5e27dd6186d247d5f1fe0f197f1349f", - [] - ], - "name0015-expected": [ - "390b77b30c40d33180bbe2026b052dadd44af527", - [] - ], - "name0015-test": [ - "60fc0746ba258f0b2ea7d20e32625d70f1ea481b", - [] - ], - "name0016-expected": [ - "7d4d9e330792bf536a304785940f865d9cd20aa3", - [] - ], - "name0016-test": [ - "371dbcde6cab2545f54b15d3f797936d39fae3d3", - [] - ], - "name0017-expected": [ - "96527926e107477e66ab0386dea671d8973de695", - [] - ], - "name0017-test": [ - "056143166bd1c31df501c74d13425656a744884c", - [] - ], - "name0018-expected": [ - "96527926e107477e66ab0386dea671d8973de695", - [] - ], - "name0018-test": [ - "e86a48360cf5735c3b0389d0f2d2507ec6c44b43", - [] - ], - "name0019-expected": [ - "8d0bc2d07d699558f0dc68690af76bd9b7f4e430", - [] - ], - "name0019-test": [ - "d48e3f6954a690c35628e3665fa329a67fb76452", - [] - ], - "name0020-expected": [ - "aa9cd6d435cfdb9bd2180bd163e1f1503e6deca0", - [] - ], - "name0020-test": [ - "b84f64d17981f59c5b1e557ba33362e38594e8b8", - [] - ], - "name0021-expected": [ - "206ff76e3e324b0c652024962dce34dd7e4dcf93", - [] - ], - "name0021-test": [ - "56b319e9d491dc99a1434b157803249fe7b4acbb", - [] - ], - "name0022-expected": [ - "b14d4f69b58c3d9cc7ed1f363d42d625e7bdcf8c", - [] - ], - "name0022-test": [ - "cc59ff17edabb8466b416dda9b4ed3c2f42a0b80", - [] - ], - "name0023-expected": [ - "5ab27668fdbdd021d29abbda3acd08e94aa92b0b", - [] - ], - "name0023-test": [ - "b7f9cc257d20fbc98b5c12125ee9dde8e4ae9436", - [] - ], - "name0024-expected": [ - "5ac4f2535c81810f380414f3e72ac8d35bfa76b7", - [] - ], - "name0024-test": [ - "da7b696da9129d5762468c0ba2b98d30974664ee", - [] - ], - "name0025-expected": [ - "68c38595db832182a19bf62086972fe2fd1a9295", - [] - ], - "name0025-test": [ - "708f006b9c0777592199ec0e8b333f44894e90fb", - [] - ], - "name0026-expected": [ - "b14d4f69b58c3d9cc7ed1f363d42d625e7bdcf8c", - [] - ], - "name0026-test": [ - "bbeb77a029c18442c90d81cd96a3b1eb1aa72170", - [] - ], - "name0027-expected": [ - "b14d4f69b58c3d9cc7ed1f363d42d625e7bdcf8c", - [] - ], - "name0027-test": [ - "d222227e6de7ded31c0be0e212f4611035c7ba79", - [] - ], - "name0028-expected": [ - "f14f9930f6b6b11391196c12ceeb6d98723ed2fb", - [] - ], - "name0028-test": [ - "1c197e3324c87aa5364224ecaf029dbf5ae0a7a4", - [] - ], - "name0029-expected": [ - "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", - [] - ], - "name0029-test": [ - "44212468d449cf18fac8987c1f0ba4127e1483ee", - [] - ], - "name0030-expected": [ - "a391380fb666180af1950103f50f584207c75138", - [] - ], - "name0030-test": [ - "cf3ff160f451ac4f53a847942df1b7a3f29861eb", - [] - ], - "name0031-expected": [ - "0cd5a50dd1b4eeda99b236c2716f656c7d1e83a7", - [] - ], - "name0031-test": [ - "9394184904027da428e718414c5ce19d0c17a6c1", - [] - ], - "name0032-expected": [ - "f4f7f3ff4cd4cf9e5c2528f0c082f4486b84c3b6", - [] - ], - "name0032-test": [ - "93fc9752333920c9b70236d7e53dd82199404811", - [] - ], - "name0033-expected": [ - "6e7762e35e375552eecb099f8b05ffa508825dc4", - [] - ], - "name0033-test": [ - "7bbdd89566a0a01d97df5d16b34a9822abeed6e9", - [] - ], "optional-domain0030-expected": [ "b14d4f69b58c3d9cc7ed1f363d42d625e7bdcf8c", [] @@ -177111,54 +176860,6 @@ "ordering0001-test": [ "ba6e85c44cdea2aa269ef170fe2d3a4c3a14e1ce", [] - ], - "value0001-expected": [ - "b14d4f69b58c3d9cc7ed1f363d42d625e7bdcf8c", - [] - ], - "value0001-test": [ - "38b7dd296e613e2d659a7516f56ea6e00e80a507", - [] - ], - "value0002-expected": [ - "9e96a81e3b4f787a158cd20a10e9defee7446948", - [] - ], - "value0002-test": [ - "bed691f1809cf37eb44c8a1083e9544bf333c03a", - [] - ], - "value0003-expected": [ - "5cc2d467ef724279da03a2af49535aa58382ee40", - [] - ], - "value0003-test": [ - "ce1d455201dbef9b08ff18315d2cceef569d0346", - [] - ], - "value0004-expected": [ - "400030f6f1d38f1833f1d8c960941f842b12a9e8", - [] - ], - "value0004-test": [ - "c569216520ca270f46741ec3ad0acd20bdd77887", - [] - ], - "value0005-expected": [ - "cad285f70867f41fdb4e4439d389b1f8171ee6ce", - [] - ], - "value0005-test": [ - "514c0f125f1f4d9d116d5ccfef3a44998b340869", - [] - ], - "value0006-expected": [ - "b14d4f69b58c3d9cc7ed1f363d42d625e7bdcf8c", - [] - ], - "value0006-test": [ - "a939a8229149c1d2311379d1632b47dd184affd8", - [] ] } } @@ -213464,7 +213165,7 @@ ] }, "requirements.txt": [ - "725ddd9e85ee202cf7fc9d3072a770a6351cdb71", + "28b20408eb011fbd2fad6665ed36b4bb8a4f5685", [] ], "selectors": { @@ -259816,7 +259517,7 @@ [] ], "RTCRtpTransceiver-stop-expected.txt": [ - "596e3c4a758c5b8e097b2636d39d59c64927781a", + "85ff9f1cffcadd652996a92e672c8e618349f2a6", [] ], "RTCRtpTransceiver.https-expected.txt": [ @@ -288711,28 +288412,12 @@ {} ] ], - "name-tests.html": [ - "e962539b0fbdcde83859496cc2b815194c7596a0", - [ - null, - { - "timeout": "long" - } - ] - ], "ordering-tests.html": [ "4dce985ac71a0d48538dc7376dff7102a0fcd78f", [ null, {} ] - ], - "value-tests.html": [ - "0d8daae165cbd2c33a4051048047ea459ad97b3c", - [ - null, - {} - ] ] }, "meta-blocked.html": [ @@ -288744,7 +288429,7 @@ ], "name": { "name.html": [ - "18fd87659442f95157d233a2e99b2704c8ea8f03", + "39fdc75d5992ad04c35f1f19c4613e2f35762fa2", [ null, { @@ -289159,7 +288844,7 @@ }, "value": { "value.html": [ - "c473a6bf7bd256586d74f2a6515cd096b93974e1", + "c1910839aa570d1de0a6eb2ee5b0d889d75224ff", [ null, { @@ -315434,7 +315119,7 @@ ] ], "focus-visible-003.html": [ - "aa73b4da44f0e831dbbd5516bd71daef245e7e65", + "3076823f703c5fe4a5822e9d2271034f94ebc829", [ null, { @@ -315443,7 +315128,7 @@ ] ], "focus-visible-004.html": [ - "b30b9e2938ab4ed4e3972340953649c21e0085d9", + "f1274b61ee9cec65a517a877b3fbcf967632ce04", [ null, { @@ -315527,7 +315212,7 @@ ] ], "focus-visible-015.html": [ - "685baeb7bad07ad45a8efda163dba5db94b9ffe8", + "98e44005c7604a764769472acac203e00c16023c", [ null, { @@ -315536,7 +315221,7 @@ ] ], "focus-visible-016.html": [ - "a65e5a5b3dd6aa2be7aa733d01725242e8b01cc4", + "080787fb1ee9f4ad96d8dacba051601421435932", [ null, { @@ -437597,7 +437282,7 @@ ] ], "video-decoder.any.js": [ - "2dd85ad955b7321167b9809007d1badea5780555", + "33ea2dbe375d5446e68e90405f9867ce8f7fb272", [ "webcodecs/video-decoder.any.html", { @@ -439457,7 +439142,7 @@ ] ], "RTCRtpTransceiver-stop.html": [ - "4f3a9ce85fa244bc673447fa389f44bdc381b230", + "60f6d0c13357b56a6e24ce4d5f29067e2683f492", [ null, {}
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/animations/one-element-three-keyframes-animation1.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/animations/one-element-three-keyframes-animation1.html new file mode 100644 index 0000000..380c5d3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/animations/one-element-three-keyframes-animation1.html
@@ -0,0 +1,47 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<link rel="help" href="https://drafts.csswg.org/css-backgrounds-3/#background-color"> +<link rel="match" href="one-element-animation-ref.html"> +<style> +.container { + width: 100px; + height: 100px; + background-color: green; + /* Use a long animation that start at 5% progress where the slope of the + selected timing function is zero. By setting up the animation in this way, + we accommodate lengthy delays in running the test without a potential drift + in the animated property value. This is important for avoiding flakes, + especially on debug builds. The screenshots are taken as soon as the + animation is ready, thus the long animation duration has no bearing on + the actual duration of the test. */ + animation: bgcolor 1000000s cubic-bezier(0,1,1,0) -50000s; +} +@keyframes bgcolor { + 0% { background-color: rgb(0, 200, 0); } + 10% { + background-color: rgb(200, 0, 0); + animation-timing-function: cubic-bezier(0,1,1,0); + } + 100% { + background-color: rgb(0, 0, 200); + animation-timing-function: cubic-bezier(0,1,1,0); + } +} +</style> +<script src="/common/reftest-wait.js"></script> +<body> +<div class="container"></div> + +<script> +// This test and the "one-element-three-keyframes-animation2.html" ensure that +// we select the correct start and end keyframes for interpolation. In this +// test, the start delay of the animation makes it jump to 5% right away, and in +// the "one-element-three-keyframes-animation2.html" the start delay makes it +// jump to 50%. So for this test, we would choose the keyframes at 0% and 10% +// for interpolation, where for the other test it would be 10% and 100%. +document.getAnimations()[0].ready.then(() => { + takeScreenshot(); +}); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/animations/one-element-three-keyframes-animation2-ref.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/animations/one-element-three-keyframes-animation2-ref.html new file mode 100644 index 0000000..823d8ac --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/animations/one-element-three-keyframes-animation2-ref.html
@@ -0,0 +1,10 @@ +<!DOCTYPE html> +<body> + <canvas id="canvas" width="100" height="100"></canvas> +</body> +<script> + var canvas = document.getElementById('canvas'); + var ctx = canvas.getContext('2d'); + ctx.fillStyle = 'rgb(100, 0, 100)'; + ctx.fillRect(0, 0, 100, 100); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/animations/one-element-three-keyframes-animation2.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/animations/one-element-three-keyframes-animation2.html new file mode 100644 index 0000000..e71b858 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/animations/one-element-three-keyframes-animation2.html
@@ -0,0 +1,45 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<link rel="help" href="https://drafts.csswg.org/css-backgrounds-3/#background-color"> +<link rel="match" href="one-element-three-keyframes-animation2-ref.html"> +<style> +.container { + width: 100px; + height: 100px; + background-color: green; + /* Use a long animation that start at 50% progress where the slope of the + selected timing function is zero. By setting up the animation in this way, + we accommodate lengthy delays in running the test without a potential drift + in the animated property value. This is important for avoiding flakes, + especially on debug builds. The screenshots are taken as soon as the + animation is ready, thus the long animation duration has no bearing on + the actual duration of the test. */ + animation: bgcolor 1000000s cubic-bezier(0,1,1,0) -500000s; +} +@keyframes bgcolor { + 0% { background-color: rgb(0, 200, 0); } + 10% { + background-color: rgb(200, 0, 0); + animation-timing-function: cubic-bezier(0,1,1,0); + } + 100% { + background-color: rgb(0, 0, 200); + animation-timing-function: cubic-bezier(0,1,1,0); + } +} +</style> +<script src="/common/reftest-wait.js"></script> +<body> +<div class="container"></div> + +<script> +// The start delay of the animation makes it jump 50% of the animation, which +// means we would select the keyframes at 10% and 100% for animation. The +// progress would be (0.5-0.1) / (1-0.1) = 0.44. So a timing function input of +// 0.44 results in an output of 0.5. +document.getAnimations()[0].ready.then(() => { + takeScreenshot(); +}); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/animations/one-element-three-keyframes-animation3.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/animations/one-element-three-keyframes-animation3.html new file mode 100644 index 0000000..080ed01 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/animations/one-element-three-keyframes-animation3.html
@@ -0,0 +1,41 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<link rel="help" href="https://drafts.csswg.org/css-backgrounds-3/#background-color"> +<link rel="match" href="one-element-animation-ref.html"> +<style> +.container { + width: 100px; + height: 100px; + background-color: green; + /* Use a long animation that start at 5% progress where the slope of the + selected timing function is zero. By setting up the animation in this way, + we accommodate lengthy delays in running the test without a potential drift + in the animated property value. This is important for avoiding flakes, + especially on debug builds. The screenshots are taken as soon as the + animation is ready, thus the long animation duration has no bearing on + the actual duration of the test. */ + animation: bgcolor 1000000s cubic-bezier(0,1,1,0) -50000s; +} +@keyframes bgcolor { + 10% { + background-color: rgb(200, 0, 0); + animation-timing-function: cubic-bezier(0,1,1,0); + } + 0% { background-color: rgb(0, 200, 0); } + 100% { + background-color: rgb(0, 0, 200); + animation-timing-function: cubic-bezier(0,1,1,0); + } +} +</style> +<script src="/common/reftest-wait.js"></script> +<body> +<div class="container"></div> + +<script> +document.getAnimations()[0].ready.then(() => { + takeScreenshot(); +}); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-clip-margin-004-ref.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-clip-margin-004-ref.html new file mode 100644 index 0000000..3cc79ed --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-clip-margin-004-ref.html
@@ -0,0 +1,32 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Verifies overflow-clip-margin extends outside bounds with contain: paint</title> +<link rel="help" href="https://www.w3.org/TR/css-overflow-3/#propdef-overflow-clip-margin"> +<link rel="author" title="Scott Violet" href="mailto:sky@chromium.org"> +<style> + .container { + display: flex; + } + .parent { + position: relative; + top: -10px; + left: -10px; + width: 120px; + height: 120px; + flex: none; + background-color: green; + } + .spacer { + flex: none; + height: 100px; + width: 100px; + } + +</style> +<p>You should see two green squares touching each other. The one on the + right should be slightly larger.</p> +<div class="spacer"></div> +<div class="container"> + <div class="spacer" style="background-color: green"></div> + <div class="parent"></div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-clip-margin-004.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-clip-margin-004.html new file mode 100644 index 0000000..aab356f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-clip-margin-004.html
@@ -0,0 +1,42 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Verifies overflow-clip-margin extends outside bounds with contain: paint</title> +<link rel="help" href="https://www.w3.org/TR/css-overflow-3/#propdef-overflow-clip-margin"> +<link rel="author" title="Scott Violet" href="mailto:sky@chromium.org"> +<link rel="match" href="overflow-clip-margin-004-ref.html"> +<style> + .container { + display: flex; + } + .parent { + width: 100px; + height: 100px; + flex: none; + contain: paint; + overflow-clip-margin: 10px; + } + .child { + width: 200px; + height: 200px; + position: relative; + top: -50px; + left: -50px; + background-color: green; + } + .spacer { + flex: none; + height: 100px; + width: 100px; + } + +</style> +<p>You should see two green squares touching each other. The one on the + right should be slightly larger.</p> +<div class="spacer"></div> +<div class="container"> + <div class="spacer" style="width: 90px; background-color: green"></div> + <div class="spacer" style="width: 10px"></div> + <div class="parent"> + <div class="child"></div> + </div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-clip-margin-005-ref.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-clip-margin-005-ref.html new file mode 100644 index 0000000..84110e57 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-clip-margin-005-ref.html
@@ -0,0 +1,31 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Verifies overflow-clip-margin impacts layout</title> +<link rel="help" href="https://www.w3.org/TR/css-overflow-3/#propdef-overflow-clip-margin"> +<link rel="author" title="Scott Violet" href="mailto:sky@chromium.org"> +<style> + .scroller { + overflow: auto; + width: 100px; + height: 100px; + } + .child { + position: relative; + width: 110px; + height: 110px; + background-color: green; + } +</style> +<p>You should see a green box with scrollbars.</p> +<div class="scroller"> + <div class="child"></div> +</div> + +<p>You should see a green box with scrollbars.</p> +<div class="scroller"> + <div class="child" style="width: 150px; height: 150px"></div> +</div> + +<p>You should see a green box with no scrollbars.</p> +<div class="scroller" style="background-color: green"> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-clip-margin-005.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-clip-margin-005.html new file mode 100644 index 0000000..2d03a96 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-clip-margin-005.html
@@ -0,0 +1,46 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Verifies overflow-clip-margin impacts layout</title> +<link rel="help" href="https://www.w3.org/TR/css-overflow-3/#propdef-overflow-clip-margin"> +<link rel="author" title="Scott Violet" href="mailto:sky@chromium.org"> +<link rel="match" href="overflow-clip-margin-005-ref.html"> +<style> + .scroller { + overflow: auto; + width: 100px; + height: 100px; + } + .parent { + width: 100px; + height: 100px; + contain: paint; + overflow-clip-margin: 10px; + } + .child { + width: 200px; + height: 200px; + position: relative; + top: -50px; + left: -50px; + background-color: green; + } +</style> +<p>You should see a green box with scrollbars.</p> +<div class="scroller"> + <div class="parent"> + <div class="child"></div> + </div> +</div> + +<p>You should see a green box with scrollbars.</p> +<div class="scroller"> + <div class="parent" style="overflow-clip-margin: 100px"> + <div class="child"></div> + </div> +</div> + +<p>You should see a green box with no scrollbars.</p> +<div class="scroller"> + <div class="parent" style="background-color: green"> + </div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-clip-margin-006-ref.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-clip-margin-006-ref.html new file mode 100644 index 0000000..cf6b55a2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-clip-margin-006-ref.html
@@ -0,0 +1,15 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Verifies overflow-clip-margin doesn't impact paint effects</title> +<link rel="help" href="https://www.w3.org/TR/css-overflow-3/#propdef-overflow-clip-margin"> +<link rel="author" title="Scott Violet" href="mailto:sky@chromium.org"> +<style> + .parent { + width: 100px; + height: 100px; + background-color: green; + box-shadow: 20px 20px 5px red; + } +</style> +<p>You should see a green box with a red box shadow. +<div class="parent"></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-clip-margin-006.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-clip-margin-006.html new file mode 100644 index 0000000..493bcee --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-clip-margin-006.html
@@ -0,0 +1,18 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Verifies overflow-clip-margin doesn't impact paint effects</title> +<link rel="help" href="https://www.w3.org/TR/css-overflow-3/#propdef-overflow-clip-margin"> +<link rel="author" title="Scott Violet" href="mailto:sky@chromium.org"> +<link rel="match" href="overflow-clip-margin-006-ref.html"> +<style> + .parent { + width: 100px; + height: 100px; + background-color: green; + contain: paint; + overflow-clip-margin: 1px; + box-shadow: 20px 20px 5px red; + } +</style> +<p>You should see a green box with a red box shadow. +<div class="parent"></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-pseudos-computed.html b/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-pseudos-computed.html new file mode 100644 index 0000000..ec3532db --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-pseudos-computed.html
@@ -0,0 +1,25 @@ +<!doctype html> +<meta charset="utf-8"> +<title>CSS Pseudo-Elements Test: highlight selectors getComputedStyle</title> +<link rel="help" href="https://drafts.csswg.org/css-pseudo/#highlight-selectors"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> + #target::selection, + #target::target-text, + #target::spelling-error, + #target::grammar-error { + background-color: green; + color: lime; + } +</style> +<div id="target"></div> +<script> + for (const pseudo of ["::selection", "::target-text", "::spelling-error", "::grammar-error"]) { + test(() => { + let style = getComputedStyle(target, pseudo); + assert_equals(style.backgroundColor, "rgb(0, 128, 0)", "Background color is green."); + assert_equals(style.color, "rgb(0, 255, 0)", "Color is lime."); + }, `getComputedStyle() for ${pseudo}`); + } +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-pseudo/parsing/highlight-pseudos.html b/third_party/blink/web_tests/external/wpt/css/css-pseudo/parsing/highlight-pseudos.html new file mode 100644 index 0000000..aa3c4e20 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-pseudo/parsing/highlight-pseudos.html
@@ -0,0 +1,22 @@ +<!doctype html> +<meta charset="utf-8"> +<title>CSS Pseudo-Elements Test: highlight selectors parsing</title> +<link rel="help" href="https://drafts.csswg.org/css-pseudo/#highlight-selectors"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/parsing-testcommon.js"></script> +<script> + for (const pseudo of ["::selection", "::target-text", "::spelling-error", "::grammar-error"]) { + test_valid_selector(`${pseudo}`); + test_valid_selector(`.a${pseudo}`); + test_valid_selector(`div ${pseudo}`); + test_valid_selector(`::part(my-part)${pseudo}`); + + test_invalid_selector(`::before${pseudo}`); + test_invalid_selector(`${pseudo}.a`); + test_invalid_selector(`${pseudo} div`); + test_invalid_selector(`${pseudo}::after`); + test_invalid_selector(`${pseudo}:hover`); + test_invalid_selector(`:not(${pseudo})`); + } +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-pseudo/parsing/target-text.html b/third_party/blink/web_tests/external/wpt/css/css-pseudo/parsing/target-text.html deleted file mode 100644 index 37cbdd4..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-pseudo/parsing/target-text.html +++ /dev/null
@@ -1,20 +0,0 @@ -<!doctype html> -<meta charset="utf-8"> -<title>CSS Pseudo-Elements Test: ::target-text parsing</title> -<link rel="help" href="https://drafts.csswg.org/css-pseudo/#selectordef-target-text"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/css/support/parsing-testcommon.js"></script> -<script> - test_valid_selector("::target-text"); - test_valid_selector(".a::target-text"); - test_valid_selector("div ::target-text"); - test_valid_selector("::part(my-part)::target-text"); - - test_invalid_selector("::before::target-text"); - test_invalid_selector("::target-text.a"); - test_invalid_selector("::target-text div"); - test_invalid_selector("::target-text::after"); - test_invalid_selector("::target-text:hover"); - test_invalid_selector(":not(::target-text)"); -</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-pseudo/target-text-computed.html b/third_party/blink/web_tests/external/wpt/css/css-pseudo/target-text-computed.html deleted file mode 100644 index 42990305..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-pseudo/target-text-computed.html +++ /dev/null
@@ -1,22 +0,0 @@ -<!doctype html> -<meta charset="utf-8"> -<title>CSS Pseudo-Elements Test: ::target-text getComputedStyle</title> -<link rel="help" href="https://drafts.csswg.org/css-pseudo/#selectordef-target-text"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<style> - #target::target-text { - background-color: green; - } - #target::target-text { - color: lime; - } -</style> -<div id="target"></div> -<script> - test(() => { - let style = getComputedStyle(target, "::target-text"); - assert_equals(style.backgroundColor, "rgb(0, 128, 0)", "Background color is green."); - assert_equals(style.color, "rgb(0, 255, 0)", "Color is lime."); - }, "getComputedStyle() for ::target-text"); -</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/aspect-ratio/table-element-001.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/aspect-ratio/table-element-001.html new file mode 100644 index 0000000..fd2dcd8 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/aspect-ratio/table-element-001.html
@@ -0,0 +1,25 @@ +<!DOCTYPE html> +<title>CSS aspect-ratio: aspect-ratio shouldn't apply to internal table boxes</title> +<link rel="author" title="mozilla" href="https://www.mozilla.org/"> +<link rel="help" href="https://drafts.csswg.org/css-sizing-4/#aspect-ratio"> +<link rel="match" href="../../reference/ref-filled-green-100px-square.xht" /> +<style> +table { + border-collapse: collapse; +} +th, td { + padding: 0px; +} +</style> + +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> + +<!-- aspect-ratio shouldn't apply to internal table boxes --> +<table> + <tr> + <th style='background: green; width: 100px; aspect-ratio: 1/1;'></th> + <td style='background: red; height: 50px; aspect-ratio: 4/1;'></td> + </tr> +</table> +<!-- aspect-ratio should apply to the table element --> +<table style='background: green; width: 100px; aspect-ratio: 2/1;'></table>
diff --git a/third_party/blink/web_tests/external/wpt/css/requirements.txt b/third_party/blink/web_tests/external/wpt/css/requirements.txt index 725ddd9..28b2040 100644 --- a/third_party/blink/web_tests/external/wpt/css/requirements.txt +++ b/third_party/blink/web_tests/external/wpt/css/requirements.txt
@@ -1,6 +1,6 @@ Template-Python==0.1.post1 html5lib==1.1 -lxml==4.5.2 +lxml==4.6.2 mercurial==4.5 six==1.15.0 webencodings==0.5.1
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-003.html b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-003.html index aa73b4d..3076823 100644 --- a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-003.html +++ b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-003.html
@@ -78,16 +78,18 @@ <label><input class="check" id="el-13" type="color"></input> Focus me.</label> </div> <script> - function mouseClickInTarget(selector) { - let target = document.querySelector(selector); - return test_driver.click(target); - } + setup({ explicit_done: true }); - for (const target of document.querySelectorAll(".check")) { + const elements = document.querySelectorAll(".check"); + for (let i = 0; i < elements.length; i++) { + const target = elements[i]; promise_test(() => { return new Promise(resolve => { target.addEventListener("focus", resolve); - test_driver.click(target); + test_driver.click(target).then(() => { + if (i == (elements.length - 1)) + done(); + }); }).then(() => { assert_equals(getComputedStyle(target).backgroundColor, "rgb(0, 255, 0)", `backgroundColor for ${target.tagName}#${target.id} should be lime`); assert_not_equals(getComputedStyle(target).outlineColor, "rgb(255, 0, 0)", `outlineColor for ${target.tagName}#${target.id} should NOT be red`);
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-004.html b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-004.html index b30b9e2..f1274b61 100644 --- a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-004.html +++ b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-004.html
@@ -77,16 +77,18 @@ <label><input class="check" id="el-11" type="color"></input> Focus me.</label> </div> <script> - function mouseClickInTarget(selector) { - let target = document.querySelector(selector); - return test_driver.click(target); - } + setup({ explicit_done: true }); - for (const target of document.querySelectorAll(".check")) { + const elements = document.querySelectorAll(".check"); + for (let i = 0; i < elements.length; i++) { + const target = elements[i]; promise_test(() => { return new Promise(resolve => { target.addEventListener("focus", resolve); - test_driver.click(target); + test_driver.click(target).then(() => { + if (i == (elements.length - 1)) + done(); + }); }).then(() => { assert_equals(getComputedStyle(target).backgroundColor, "rgb(0, 255, 0)", `backgroundColor for ${target.tagName}#${target.id} should be lime`); assert_not_equals(getComputedStyle(target).outlineColor, "rgb(255, 0, 0)", `outlineColor for ${target.tagName}#${target.id} should NOT be red`);
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-015.html b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-015.html index 685baeb..98e4400 100644 --- a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-015.html +++ b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-015.html
@@ -29,6 +29,8 @@ <div id="target" tabindex="0">Target</div> <script> + setup({ explicit_done: true }); + async_test(function(t) { initial.addEventListener("focus", t.step_func(function() { assert_equals(getComputedStyle(initial).backgroundColor, "rgb(0, 255, 0)", `backgroundColor for ${initial.tagName}#${initial.id} should be lime`); @@ -40,6 +42,6 @@ t.done(); })); - test_driver.click(initial); + test_driver.click(initial).then(() => done()); }, ":focus-visible does not match after script focus move"); </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-016.html b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-016.html index a65e5a5..080787f 100644 --- a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-016.html +++ b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-016.html
@@ -37,6 +37,8 @@ <input id="target" /> <script> + setup({ explicit_done: true }); + async_test(function(t) { initial.addEventListener("focus", t.step_func(function() { assert_equals(getComputedStyle(initial).backgroundColor, "rgb(0, 255, 0)", `backgroundColor for ${initial.tagName}#${initial.id} should be lime`); @@ -48,7 +50,7 @@ t.done(); })); - test_driver.click(initial); + test_driver.click(initial).then(() => done()); }, ":focus-visible always match on text inputs"); </script>
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_coordinates_when_locked.html.ini b/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_coordinates_when_locked.html.ini deleted file mode 100644 index 04c0f72..0000000 --- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_coordinates_when_locked.html.ini +++ /dev/null
@@ -1,5 +0,0 @@ -[pointerevent_coordinates_when_locked.html] - expected: TIMEOUT - - [mouse Test pointerevent coordinates when pointer is locked] - expected: NOTRUN
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_getCoalescedEvents_when_pointerlocked.html.ini b/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_getCoalescedEvents_when_pointerlocked.html.ini deleted file mode 100644 index 9e12583..0000000 --- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_getCoalescedEvents_when_pointerlocked.html.ini +++ /dev/null
@@ -1,3 +0,0 @@ -[pointerevent_getCoalescedEvents_when_pointerlocked.html] - [mouse pointermove getCoalescedEvents when lock test] - expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_movementxy_with_pointerlock.html.ini b/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_movementxy_with_pointerlock.html.ini deleted file mode 100644 index d22487b..0000000 --- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_movementxy_with_pointerlock.html.ini +++ /dev/null
@@ -1,6 +0,0 @@ -[pointerevent_movementxy_with_pointerlock.html] - expected: TIMEOUT - - [mouse pointerevent movementX/Y with pointerlock test] - expected: TIMEOUT - message: Test timed out
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_pointerlock_after_pointercapture.html.ini b/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_pointerlock_after_pointercapture.html.ini deleted file mode 100644 index dc1a38a9..0000000 --- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_pointerlock_after_pointercapture.html.ini +++ /dev/null
@@ -1,3 +0,0 @@ -[pointerevent_pointerlock_after_pointercapture.html] - [mouse no pointercapture while pointerlock] - expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_pointermove_in_pointerlock.html.ini b/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_pointermove_in_pointerlock.html.ini deleted file mode 100644 index 7c4043d..0000000 --- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_pointermove_in_pointerlock.html.ini +++ /dev/null
@@ -1,8 +0,0 @@ -[pointerevent_pointermove_in_pointerlock.html] - expected: TIMEOUT - - [pointermove event received] - expected: NOTRUN - - [pointermove event received inner frame] - expected: NOTRUN
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_pointermove_on_chorded_mouse_button_when_locked.html.ini b/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_pointermove_on_chorded_mouse_button_when_locked.html.ini deleted file mode 100644 index 9d0b178..0000000 --- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_pointermove_on_chorded_mouse_button_when_locked.html.ini +++ /dev/null
@@ -1,5 +0,0 @@ -[pointerevent_pointermove_on_chorded_mouse_button_when_locked.html] - expected: TIMEOUT - - [pointer locked pointermove events received for button state changes] - expected: NOTRUN
diff --git a/third_party/blink/web_tests/external/wpt/webcodecs/video-decoder.any.js b/third_party/blink/web_tests/external/wpt/webcodecs/video-decoder.any.js index 2dd85ad..33ea2db 100644 --- a/third_party/blink/web_tests/external/wpt/webcodecs/video-decoder.any.js +++ b/third_party/blink/web_tests/external/wpt/webcodecs/video-decoder.any.js
@@ -4,7 +4,7 @@ // TODO(sandersd): Move metadata into a helper library. // TODO(sandersd): Add H.264 decode test once there is an API to query for // supported codecs. -let h264 = { +const h264 = { async buffer() { return (await fetch('h264.mp4')).arrayBuffer(); }, codec: "avc1.64000c", description: {offset: 7229, size: 46}, @@ -20,7 +20,7 @@ {offset: 6429, size: 281}] }; -let vp9 = { +const vp9 = { async buffer() { return (await fetch('vp9.mp4')).arrayBuffer(); }, // TODO(sandersd): Verify that the file is actually level 1. codec: "vp09.00.10.08", @@ -36,6 +36,88 @@ {offset: 5193, size: 159}] }; +const badCodecsList = [ + '', // Empty codec + 'bogus', // Non exsitent codec + 'vorbis', // Audio codec + 'vp9', // Ambiguous codec + 'video/webm; codecs="vp9"' // Codec with mime type + ] + +const invalidConfigs = [ + { + comment: 'Emtpy codec', + config: {codec: ''}, + }, + { + comment: 'Unrecognized codec', + config: {codec: 'bogus'}, + }, + { + comment: 'Audio codec', + config: {codec: 'vorbis'}, + }, + { + comment: 'Ambiguous codec', + config: {codec: 'vp9'}, + }, + { + comment: 'Codec with MIME type', + config: {codec: 'video/webm; codecs="vp8"'}, + }, + { + comment: 'Zero coded size', + config: { + codec: h264.codec, + codedWidth: 0, + codedHeight: 0, + }, + }, + { + comment: 'Out of bounds crop size caused by left/top offset', + config: { + codec: h264.codec, + codedWidth: 1920, + codedHeight: 1088, + cropLeft: 10, + cropTop: 10, + // When unspecified, these default to coded dimensions + // cropWidth: 1920, + // cropHeight: 1088 + }, + }, + { + comment: 'Out of bounds crop size', + config: { + codec: h264.codec, + codedWidth: 1920, + codedHeight: 1088, + cropLeft: 10, + cropTop: 10, + cropWidth: 1920, + cropHeight: 1088, + }, + }, + { + comment: 'Way out of bounds crop size', + config: { + codec: h264.codec, + codedWidth: 1920, + codedHeight: 1088, + cropWidth: 4000, + cropHeight: 5000, + }, + }, + { + comment: 'Invalid display size', + config: { + codec: h264.codec, + displayWidth: 0, + displayHeight: 0, + }, + }, +] // invalidConfigs + function view(buffer, {offset, size}) { return new Uint8Array(buffer, offset, size); } @@ -48,6 +130,40 @@ }); } +invalidConfigs.forEach(entry => { + promise_test(t => { + return promise_rejects_js(t, TypeError, VideoDecoder.isConfigSupported(entry.config)); + }, 'Test that VideoDecoder.isConfigSupported() rejects invalid config:' + entry.comment); +}); + +invalidConfigs.forEach(entry => { + async_test(t => { + let codec = new VideoDecoder(getDefaultCodecInit(t)); + assert_throws_js(TypeError, () => { codec.configure(entry.config); }); + t.done(); + }, 'Test that VideoDecoder.configure() rejects invalid config:' + entry.comment); +}); + +promise_test(t => { + return VideoDecoder.isConfigSupported({codec: vp9.codec}); +}, 'Test VideoDecoder.isConfigSupported() with minimal valid config'); + +promise_test(t => { + // This config specifies a slight crop. H264 1080p content always crops + // because H264 coded dimensions are a multiple of 16 (e.g. 1088). + return VideoDecoder.isConfigSupported({ + codec: h264.codec, + codedWidth: 1920, + codedHeight: 1088, + cropLeft: 0, + cropTop: 0, + cropWidth: 1920, + cropHeight: 1080, + displayWidth: 1920, + displayHeight: 1080 + }); +}, 'Test VideoDecoder.isConfigSupported() with valid expanded config'); + promise_test(t => { // VideoDecoderInit lacks required fields. assert_throws_js(TypeError, () => { new VideoDecoder({}); }); @@ -65,18 +181,12 @@ promise_test(t => { let decoder = new VideoDecoder(getDefaultCodecInit(t)); - let badCodecsList = [ - '', // Empty codec - 'bogus', // Non exsitent codec - 'vorbis', // Audio codec - 'vp9', // Ambiguous codec - 'video/webm; codecs="vp9"' // Codec with mime type - ] - + // TODO(chcunningham): Remove badCodecsList testing. It's now covered more + // extensively by other tests. testConfigurations(decoder, { codec: vp9.codec }, badCodecsList); return endAfterEventLoopTurn(); -}, 'Test VideoDecoder.configure()'); +}, 'Test VideoDecoder.configure() with various codec strings'); promise_test(async t => { let buffer = await vp9.buffer();
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpTransceiver-stop-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpTransceiver-stop-expected.txt index 596e3c4..85ff9f1c 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpTransceiver-stop-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpTransceiver-stop-expected.txt
@@ -1,5 +1,6 @@ This is a testharness.js-based test. PASS A transceiver added and stopped before the initial offer generation should not trigger an offer m-section generation +PASS A transceiver added and stopped should not crash when getting receiver's transport PASS During renegotiation, adding and stopping a transceiver should not trigger a renegotiated offer m-section generation PASS A stopped sendonly transceiver should generate an inactive m-section in the offer PASS A stopped inactive transceiver should generate an inactive m-section in the offer
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpTransceiver-stop.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpTransceiver-stop.html index 4f3a9ce..60f6d0c1 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpTransceiver-stop.html +++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpTransceiver-stop.html
@@ -23,6 +23,18 @@ promise_test(async (t)=> { const pc1 = new RTCPeerConnection(); + t.add_cleanup(() => pc1.close()); + + pc1.addTransceiver("audio", { direction: "sendonly" }); + pc1.addTransceiver("video"); + assert_equals(null, pc1.getTransceivers()[1].receiver.transport); + + pc1.getTransceivers()[1].stop(); + assert_equals(pc1.getTransceivers()[1].receiver.transport, null); +}, "A transceiver added and stopped should not crash when getting receiver's transport"); + +promise_test(async (t)=> { + const pc1 = new RTCPeerConnection(); const pc2 = new RTCPeerConnection(); t.add_cleanup(() => pc1.close()); t.add_cleanup(() => pc2.close());
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/pseudo-elements-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/pseudo-elements-expected.txt index 7d8fad9..c8b42e8 100644 --- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/pseudo-elements-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/pseudo-elements-expected.txt
@@ -39,6 +39,11 @@ [$#inspected:after$] { (<style>) content: "AFTER"; +======== Pseudo ::grammar-error element ======== +[expanded] +#inspected::grammar-error { (<style>) + color: teal; + ======== Pseudo ::marker element ======== [expanded] [$#inspected::marker$] { (<style>) @@ -53,6 +58,11 @@ text-align: start !important; text-align-last: start !important; +======== Pseudo ::spelling-error element ======== +[expanded] +#inspected::spelling-error { (<style>) + color: orange; + ======== Pseudo ::target-text element ======== [expanded] #inspected::target-text { (<style>)
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/pseudo-elements.js b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/pseudo-elements.js index d1f44e8c..ddf302f 100644 --- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/pseudo-elements.js +++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/pseudo-elements.js
@@ -12,6 +12,14 @@ color: green; } + #inspected::spelling-error { + color: orange; + } + + #inspected::grammar-error { + color: teal; + } + #inspected { display: list-item; }
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/cookiestore-origin-trial-interfaces.html b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/cookiestore-origin-trial-interfaces.html deleted file mode 100644 index 79c4c203..0000000 --- a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/cookiestore-origin-trial-interfaces.html +++ /dev/null
@@ -1,29 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<!-- Generate token with the command: -generate_token.py http://127.0.0.1:8000 CookieStore --expire-timestamp=2000000000 --- --> -<meta http-equiv="origin-trial" content="A/tS990j7n9VjcZbX16/nUmZ8VdMMUzvcPOC6lSkRjLCqhbITiPki31a3TpeDuSZzcSKeZ7bik7JB0c+M/i6UQQAAABTeyJvcmlnaW4iOiAiaHR0cDovLzEyNy4wLjAuMTo4MDAwIiwgImZlYXR1cmUiOiAiQ29va2llU3RvcmUiLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0=" /> -<title>Cookie Store API - interfaces exposed by origin trial</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/resources/origin-trials-helper.js"></script> -<script src="/serviceworker/resources/test-helpers.js"></script> -<script> -test(t => { - OriginTrialsHelper.check_properties_exist(this, { - 'CookieStore': ['get', 'getAll', 'set', 'delete', 'onchange'], - 'CookieStoreManager': ['getSubscriptions', 'subscribe', 'unsubscribe'], - 'CookieChangeEvent': ['changed', 'deleted'], - 'ServiceWorkerRegistration': ['cookies'], - }); -}, 'Cookie Store API interfaces and properties in Origin-Trial enabled document.'); - -test(t => { - assert_true('cookieStore' in self, 'cookieStore property exists on global scope'); - assert_not_equals(window.cookieStore, undefined, 'cookieStore property can be accessed on window'); -}, 'Cookie Store API entry point in Origin-Trial enabled document.'); - -service_worker_test('resources/cookiestore-origin-trial-interfaces-serviceworker-enabled.php'); - -</script>
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/native-file-system-origin-trial-interfaces.html b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/file-system-access-origin-trial-interfaces.html similarity index 89% rename from third_party/blink/web_tests/http/tests/origin_trials/webexposed/native-file-system-origin-trial-interfaces.html rename to third_party/blink/web_tests/http/tests/origin_trials/webexposed/file-system-access-origin-trial-interfaces.html index 05cc05c2..b806171b 100644 --- a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/native-file-system-origin-trial-interfaces.html +++ b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/file-system-access-origin-trial-interfaces.html
@@ -4,7 +4,7 @@ generate_token.py http://127.0.0.1:8000 NativeFileSystem2 --expire-timestamp=2000000000 -- --> <meta http-equiv="origin-trial" content="AmmBxJTKsdbb26LLpdAVmIKBvVxU6fKf6UZDoMXiD+b9bULkOHzUTtZ4dNwHMhI7tZzO+tNgmWCzNK2MLoZsvAEAAABZeyJvcmlnaW4iOiAiaHR0cDovLzEyNy4wLjAuMTo4MDAwIiwgImZlYXR1cmUiOiAiTmF0aXZlRmlsZVN5c3RlbTIiLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0="> -<title>Native File System API - interfaces exposed by origin trial</title> +<title>File System Access API - interfaces exposed by origin trial</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/resources/origin-trials-helper.js"></script> @@ -17,5 +17,5 @@ 'FileSystemWritableFileStream': ['write', 'truncate', 'close', 'seek'], 'global': ['showOpenFilePicker', 'showSaveFilePicker', 'showDirectoryPicker'], }); -}, 'Native File System API interfaces and properties in Origin-Trial enabled document.'); +}, 'File System Access API interfaces and properties in Origin-Trial enabled document.'); </script>
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/resources/cookiestore-origin-trial-interfaces-serviceworker-enabled.php b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/resources/cookiestore-origin-trial-interfaces-serviceworker-enabled.php deleted file mode 100644 index ff2782f..0000000 --- a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/resources/cookiestore-origin-trial-interfaces-serviceworker-enabled.php +++ /dev/null
@@ -1,26 +0,0 @@ -<?php -// Generate token with the command: -// generate_token.py http://127.0.0.1:8000 CookieStore --expire-timestamp=2000000000 -header("Origin-Trial: AuCNc4F6ez8bdiKV6reoNKgzu2afmtUl5FgKkP6jdrbbCqVh8BfddejNqciWMz+V+oZXxJdW1LU5nQuC0Ij2GQkAAABTeyJvcmlnaW4iOiAiaHR0cDovLzEyNy4wLjAuMTo4MDAwIiwgImZlYXR1cmUiOiAiQ29va2llU3RvcmUiLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0="); -header('Content-Type: application/javascript'); -?> -importScripts('/resources/testharness.js', - '/resources/origin-trials-helper.js'); - -test(t => { - OriginTrialsHelper.check_properties_exist(this, { - 'CookieStore': ['get', 'getAll', 'set', 'delete'], - 'CookieStoreManager': ['getSubscriptions', 'subscribe', 'unsubscribe'], - 'ExtendableCookieChangeEvent': ['changed', 'deleted'], - 'ServiceWorkerRegistration': ['cookies'], - }); -}, 'Cookie Store API interfaces and properties in Origin-Trial enabled serviceworker.'); - -test(t => { - assert_true('cookieStore' in self, 'cookieStore property exists on global'); - assert_not_equals(self.cookieStore, undefined, 'cookieStore property can be accessed on self'); - assert_true('oncookiechange' in self, - 'oncookiechange property exists on global'); -}, 'Cookie Store API entry points in Origin-Trial enabled serviceworker.'); - -done();
diff --git a/third_party/blink/web_tests/http/tests/security/isolatedWorld/world-reuse.html b/third_party/blink/web_tests/http/tests/security/isolatedWorld/world-reuse.html index 03db5478..edf747a 100644 --- a/third_party/blink/web_tests/http/tests/security/isolatedWorld/world-reuse.html +++ b/third_party/blink/web_tests/http/tests/security/isolatedWorld/world-reuse.html
@@ -26,9 +26,13 @@ var iframeComplete = function(result) { // Isolated world executing in frame should be able to to access parent content. + let childFrameScriptElement = frames[0].document.createElement('script'); + childFrameScriptElement.innerText = ` testRunner.evaluateScriptInIsolatedWorld(1, "parent.document.body.appendChild(parent.document.createTextNode('Expecting true: ' + !!parent.frames[0].document.getElementById('output')));" + "parent.document.body.appendChild(parent.document.createElement('br'));"); + `; + frames[0].document.body.appendChild(childFrameScriptElement); document.body.appendChild(document.createTextNode('Expecting undefined,undefined: ' + result)); document.body.appendChild(document.createElement('br'));
diff --git a/third_party/blink/web_tests/inspector-protocol/page/add-script-to-evaluate-in-world.js b/third_party/blink/web_tests/inspector-protocol/page/add-script-to-evaluate-in-world.js index 436034f..9a58105 100644 --- a/third_party/blink/web_tests/inspector-protocol/page/add-script-to-evaluate-in-world.js +++ b/third_party/blink/web_tests/inspector-protocol/page/add-script-to-evaluate-in-world.js
@@ -6,10 +6,11 @@ const scriptIds = []; dp.Runtime.onConsoleAPICalled(msg => testRunner.log(msg.params.args[0].value)); - dp.Runtime.onExecutionContextCreated(msg => { + const logContextCreationCallback = msg => { if (msg.params.context.name.includes('world')) testRunner.log(msg.params.context.name); - }); + }; + dp.Runtime.onExecutionContextCreated(logContextCreationCallback); testRunner.log('Adding scripts'); for (let i = 0; i < 5; ++i) { @@ -27,6 +28,7 @@ testRunner.log('Failed script removal'); } + dp.Runtime.offExecutionContextCreated(logContextCreationCallback); await session.navigate('../resources/blank.html'); testRunner.completeTest();
diff --git a/third_party/blink/web_tests/platform/mac-mac-arm11.0/external/wpt/webrtc/RTCRtpTransceiver-stop-expected.txt b/third_party/blink/web_tests/platform/mac-mac-arm11.0/external/wpt/webrtc/RTCRtpTransceiver-stop-expected.txt new file mode 100644 index 0000000..596e3c4 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac-arm11.0/external/wpt/webrtc/RTCRtpTransceiver-stop-expected.txt
@@ -0,0 +1,11 @@ +This is a testharness.js-based test. +PASS A transceiver added and stopped before the initial offer generation should not trigger an offer m-section generation +PASS During renegotiation, adding and stopping a transceiver should not trigger a renegotiated offer m-section generation +PASS A stopped sendonly transceiver should generate an inactive m-section in the offer +PASS A stopped inactive transceiver should generate an inactive m-section in the offer +PASS If a transceiver is stopped locally, setting a locally generated answer should still work +PASS If a transceiver is stopped remotely, setting a locally generated answer should still work +PASS If a transceiver is stopped, transceivers, senders and receivers should disappear after offer/answer +FAIL If a transceiver is stopped, transceivers should end up in state stopped assert_equals: expected "recvonly" but got "stopped" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac-arm11.0/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCRtpTransceiver-stop-expected.txt b/third_party/blink/web_tests/platform/mac-mac-arm11.0/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCRtpTransceiver-stop-expected.txt new file mode 100644 index 0000000..7339289 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac-arm11.0/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCRtpTransceiver-stop-expected.txt
@@ -0,0 +1,11 @@ +This is a testharness.js-based test. +FAIL A transceiver added and stopped before the initial offer generation should not trigger an offer m-section generation promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'." +FAIL During renegotiation, adding and stopping a transceiver should not trigger a renegotiated offer m-section generation promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'." +FAIL A stopped sendonly transceiver should generate an inactive m-section in the offer promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'." +FAIL A stopped inactive transceiver should generate an inactive m-section in the offer promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'." +FAIL If a transceiver is stopped locally, setting a locally generated answer should still work promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'." +FAIL If a transceiver is stopped remotely, setting a locally generated answer should still work promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'." +FAIL If a transceiver is stopped, transceivers, senders and receivers should disappear after offer/answer promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'." +FAIL If a transceiver is stopped, transceivers should end up in state stopped promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt index d7c52ed..0b96c8de 100644 --- a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt
@@ -35,8 +35,6 @@ PASS window.cached_navigator.webdriver is false PASS window.cached_navigator_connection.onchange is null PASS window.cached_navigator_connection.saveData is false -PASS window.cached_navigator_hid.onconnect is null -PASS window.cached_navigator_hid.ondisconnect is null PASS window.cached_navigator_mediaDevices.ondevicechange is null PASS window.cached_navigator_mediaSession.metadata is null PASS window.cached_navigator_mediaSession.playbackState is 'none'
diff --git a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt index 463e454..b17bd1f5 100644 --- a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt
@@ -35,8 +35,6 @@ PASS window.cached_navigator.webdriver is false PASS window.cached_navigator_connection.onchange is null PASS window.cached_navigator_connection.saveData is false -PASS window.cached_navigator_hid.onconnect is null -PASS window.cached_navigator_hid.ondisconnect is null PASS window.cached_navigator_mediaDevices.ondevicechange is null PASS window.cached_navigator_mediaSession.metadata is null PASS window.cached_navigator_mediaSession.playbackState is 'none'
diff --git a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt index 350b91e..3530916 100644 --- a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt
@@ -35,8 +35,6 @@ PASS window.cached_navigator.webdriver is false PASS window.cached_navigator_connection.onchange is null PASS window.cached_navigator_connection.saveData is false -PASS window.cached_navigator_hid.onconnect is null -PASS window.cached_navigator_hid.ondisconnect is null PASS window.cached_navigator_mediaDevices.ondevicechange is null PASS window.cached_navigator_mediaSession.metadata is null PASS window.cached_navigator_mediaSession.playbackState is 'none'
diff --git a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt index e8c74642..d62632e5 100644 --- a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
@@ -35,8 +35,6 @@ PASS oldChildWindow.navigator.deviceMemory is newChildWindow.navigator.deviceMemory PASS oldChildWindow.navigator.doNotTrack is newChildWindow.navigator.doNotTrack PASS oldChildWindow.navigator.hardwareConcurrency is newChildWindow.navigator.hardwareConcurrency -PASS oldChildWindow.navigator.hid.onconnect is newChildWindow.navigator.hid.onconnect -PASS oldChildWindow.navigator.hid.ondisconnect is newChildWindow.navigator.hid.ondisconnect PASS oldChildWindow.navigator.language is newChildWindow.navigator.language PASS oldChildWindow.navigator.maxTouchPoints is newChildWindow.navigator.maxTouchPoints PASS oldChildWindow.navigator.mediaDevices.ondevicechange is newChildWindow.navigator.mediaDevices.ondevicechange
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/feature-policy-features-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/feature-policy-features-expected.txt index c0da977..4c4046d 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/feature-policy-features-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/feature-policy-features-expected.txt
@@ -27,7 +27,6 @@ fullscreen geolocation gyroscope -hid magnetometer microphone midi
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt index 31af8656..75d90f4 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -2183,40 +2183,6 @@ getter y getter z method constructor -interface HID : EventTarget - attribute @@toStringTag - getter onconnect - getter ondisconnect - method constructor - method getDevices - method requestDevice - setter onconnect - setter ondisconnect -interface HIDConnectionEvent : Event - attribute @@toStringTag - getter device - method constructor -interface HIDDevice : EventTarget - attribute @@toStringTag - getter collections - getter oninputreport - getter opened - getter productId - getter productName - getter vendorId - method close - method constructor - method open - method receiveFeatureReport - method sendFeatureReport - method sendReport - setter oninputreport -interface HIDInputReportEvent : Event - attribute @@toStringTag - getter data - getter device - getter reportId - method constructor interface HTMLAllCollection attribute @@toStringTag getter length @@ -4581,7 +4547,6 @@ getter doNotTrack getter geolocation getter hardwareConcurrency - getter hid getter keyboard getter language getter languages
diff --git a/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCRtpTransceiver-stop-expected.txt b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCRtpTransceiver-stop-expected.txt index 7339289..483bec2 100644 --- a/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCRtpTransceiver-stop-expected.txt +++ b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCRtpTransceiver-stop-expected.txt
@@ -1,5 +1,6 @@ This is a testharness.js-based test. FAIL A transceiver added and stopped before the initial offer generation should not trigger an offer m-section generation promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'." +FAIL A transceiver added and stopped should not crash when getting receiver's transport promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'." FAIL During renegotiation, adding and stopping a transceiver should not trigger a renegotiated offer m-section generation promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'." FAIL A stopped sendonly transceiver should generate an inactive m-section in the offer promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'." FAIL A stopped inactive transceiver should generate an inactive m-section in the offer promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'."
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt index 95b5641..88d9550 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -1725,6 +1725,7 @@ [Worker] getter isActive [Worker] method constructor [Worker] interface VideoDecoder +[Worker] static method isConfigSupported [Worker] attribute @@toStringTag [Worker] getter decodeQueueSize [Worker] getter state
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index 9f13f56b..f0c175c 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -8778,6 +8778,7 @@ getter valueMissing method constructor interface VideoDecoder + static method isConfigSupported attribute @@toStringTag getter decodeQueueSize getter state
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium index c90af48..d1a7856 100644 --- a/third_party/freetype/README.chromium +++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@ Name: FreeType URL: http://www.freetype.org/ -Version: VER-2-10-4-101-gcbc14b10e -Revision: cbc14b10e623a5d08c89a1323ae9c420c8492118 +Version: VER-2-10-4-104-g0901a6f74 +Revision: 0901a6f74c707f4e631d810b9f3ac7f0c0d2042e CPEPrefix: cpe:/a:freetype:freetype:2.10.4 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent JPEG Group) licenses"
diff --git a/third_party/usrsctp/BUILD.gn b/third_party/usrsctp/BUILD.gn index 0e5e0f6..b869852 100644 --- a/third_party/usrsctp/BUILD.gn +++ b/third_party/usrsctp/BUILD.gn
@@ -105,7 +105,6 @@ "SCTP_PROCESS_LEVEL_LOCKS", "SCTP_SIMPLE_ALLOCATOR", "SCTP_USE_OPENSSL_SHA1", - "SCTP_USE_OPENSSL_RAND", "__Userspace__", # "SCTP_DEBUG", # Uncomment for SCTP debugging. @@ -129,13 +128,26 @@ ] if (is_linux || is_chromeos || is_android) { - defines += [ "_GNU_SOURCE" ] + defines += [ + "__Userspace_os_Linux", + "_GNU_SOURCE", + ] } else if (is_apple) { defines += [ "HAVE_SA_LEN", "__APPLE_USE_RFC_2292", + "__Userspace_os_Darwin", ] } + if (is_win) { + defines += [ "__Userspace_os_Windows" ] + } else { + defines += [ "NON_WINDOWS_DEFINE" ] + } + + if (is_fuchsia) { + defines += [ "__Userspace_os_Fuchsia" ] + } deps = [ "//third_party/boringssl" ] }
diff --git a/third_party/usrsctp/README.chromium b/third_party/usrsctp/README.chromium index e30db20..bfc3852 100644 --- a/third_party/usrsctp/README.chromium +++ b/third_party/usrsctp/README.chromium
@@ -2,8 +2,8 @@ URL: http://github.com/sctplab/usrsctp Version: 0 CPEPrefix: cpe:/a:usrsctp_project:usrsctp:2019-12-20 -Date: Jan 5, 2021 -Revision: 4191ca1784d8774dbf62d48ab9426c7311a91bc5 +Date: Aug 28, 2020 +Revision: 995c0b84414466d77d52011e5b572cbe213b770a License: New BSD License File: LICENSE Security Critical: yes @@ -19,3 +19,9 @@ draft-stewart-prsctp-00.txt draft-stewart-tsvwg-sctpipv6-00.txt draft-iyengar-sctp-cacc-00.txt + +Local Modifications: +Cherry picked: +d844a690d30ace22de75e8b80d9bb08ae7283795 +355fb576b1a9dfef70fc0e158d66692662baaddc +7dab23aa0d8db86fedd222a308067439b03fad0f
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec index ea86ce6..b1fe70dd 100644 --- a/tools/gritsettings/resource_ids.spec +++ b/tools/gritsettings/resource_ids.spec
@@ -162,6 +162,10 @@ "chrome/browser/resources/preinstalled_web_apps/resources.grd": { "includes": [1710], }, + "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/pdf/resources.grd": { + "META": {"sizes": {"includes": [200]}}, + "includes": [1715], + }, "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/print_preview/print_preview_resources.grd": { "META": {"sizes": {"includes": [500],}}, "includes": [1720],
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 8fc5f5a..4d9234e 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -374,10 +374,6 @@ 'win32-archive-rel-goma-canary-localoutputcache': 'release_bot_x86_minimal_symbols_enable_archive_compression', 'win32-archive-rel-goma-latest-localoutputcache': 'release_bot_x86_minimal_symbols_enable_archive_compression', - 'Win7 Builder (dbg) Goma Canary': 'gpu_tests_debug_bot_x86_no_symbols', - 'Win7 Builder (dbg) Goma Latest Client': 'gpu_tests_debug_bot_x86_no_symbols', - 'Win7 Builder Goma Canary': 'gpu_tests_release_bot_x86_minimal_symbols', - 'Win7 Builder Goma Latest Client': 'gpu_tests_release_bot_x86_minimal_symbols', 'Mac Builder (dbg) Goma Canary': 'gpu_tests_debug_bot', 'Mac Builder (dbg) Goma Canary (clobber)': 'gpu_tests_debug_bot',
diff --git a/tools/mb/mb_config_expectations/chromium.goma.fyi.json b/tools/mb/mb_config_expectations/chromium.goma.fyi.json index cabdae5..cdfa93d 100644 --- a/tools/mb/mb_config_expectations/chromium.goma.fyi.json +++ b/tools/mb/mb_config_expectations/chromium.goma.fyi.json
@@ -181,50 +181,6 @@ "use_goma": true } }, - "Win7 Builder (dbg) Goma Canary": { - "gn_args": { - "ffmpeg_branding": "Chrome", - "is_component_build": true, - "is_debug": true, - "proprietary_codecs": true, - "symbol_level": 0, - "target_cpu": "x86", - "use_goma": true - } - }, - "Win7 Builder (dbg) Goma Latest Client": { - "gn_args": { - "ffmpeg_branding": "Chrome", - "is_component_build": true, - "is_debug": true, - "proprietary_codecs": true, - "symbol_level": 0, - "target_cpu": "x86", - "use_goma": true - } - }, - "Win7 Builder Goma Canary": { - "gn_args": { - "ffmpeg_branding": "Chrome", - "is_component_build": false, - "is_debug": false, - "proprietary_codecs": true, - "symbol_level": 1, - "target_cpu": "x86", - "use_goma": true - } - }, - "Win7 Builder Goma Latest Client": { - "gn_args": { - "ffmpeg_branding": "Chrome", - "is_component_build": false, - "is_debug": false, - "proprietary_codecs": true, - "symbol_level": 1, - "target_cpu": "x86", - "use_goma": true - } - }, "android-archive-dbg-goma-canary": { "gn_args": { "is_component_build": true,
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 27e293f..63d0e09 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -7169,6 +7169,14 @@ <int value="4" label="Unknown"/> </enum> +<enum name="BlueZResultOfAdvertisementMonitor"> + <int value="0" label="Success"/> + <int value="1" label="Unknown Error"/> + <int value="2" label="Invalid Parameters"/> + <int value="3" label="No Resource"/> + <int value="4" label="Busy"/> +</enum> + <enum name="BlueZResultOfAdvertisementRegistration"> <int value="1" label="Success"/> <int value="2" label="LE unsupported"/> @@ -30350,7 +30358,7 @@ <int value="3343" label="V8Window_GetOriginPrivateDirectory_Method"/> <int value="3344" label="RTCConstraintEnableRtpDataChannelsTrue"/> <int value="3345" label="RTCConstraintEnableRtpDataChannelsFalse"/> - <int value="3346" label="NativeFileSystemDragAndDrop"/> + <int value="3346" label="FileSystemAccessDragAndDrop"/> <int value="3347" label="RTCAdaptivePtime"/> <int value="3348" label="HTMLMetaElementReferrerPolicyMultipleTokensAffectingRequest"/> @@ -61423,6 +61431,13 @@ </int> </enum> +<enum name="ProfileKeepAliveOrigin"> + <int value="0" label="kWaitingForFirstBrowserWindow"/> + <int value="1" label="kBrowserWindow"/> + <int value="2" label="kBackgroundMode"/> + <int value="3" label="kOffTheRecordProfile"/> +</enum> + <enum name="ProfileMenuActionableItem"> <int value="0" label="Manage your Google Account button"/> <int value="1" label="Passwords button"/>
diff --git a/tools/metrics/histograms/histograms_xml/input/histograms.xml b/tools/metrics/histograms/histograms_xml/input/histograms.xml index 2a9a8ce..466ab52 100644 --- a/tools/metrics/histograms/histograms_xml/input/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/input/histograms.xml
@@ -480,6 +480,36 @@ </summary> </histogram> +<histogram name="InputMethod.MultilingualExperiment.Autocorrect.Actions" + enum="IMEAutocorrectActions" expires_after="2021-06-30"> + <owner>tranbaoduy@google.com</owner> + <owner>essential-inputs-team@google.com</owner> + <summary> + Same as InputMethod.Assistive.Autocorrect.Actions but only recorded for CrOS + 1P experimental multilingual input methods. + </summary> +</histogram> + +<histogram name="InputMethod.MultilingualExperiment.Autocorrect.Count" + enum="IMETextInputClient" expires_after="2021-06-30"> + <owner>tranbaoduy@google.com</owner> + <owner>essential-inputs-team@google.com</owner> + <summary> + Same as InputMethod.Assistive.Autocorrect.Count but only recorded for CrOS + 1P experimental multilingual input methods. + </summary> +</histogram> + +<histogram name="InputMethod.MultilingualExperiment.Autocorrect.Delay" + units="ms" expires_after="2021-06-30"> + <owner>tranbaoduy@google.com</owner> + <owner>essential-inputs-team@google.com</owner> + <summary> + Same as InputMethod.Assistive.Autocorrect.Delay but only recorded for CrOS + 1P experimental multilingual input methods. + </summary> +</histogram> + <histogram name="InputMethod.NextWordPrediction" enum="BooleanEnabled" expires_after="2021-06-13"> <owner>myy@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/others/histograms.xml b/tools/metrics/histograms/histograms_xml/others/histograms.xml index 29590f4..46df97a6 100644 --- a/tools/metrics/histograms/histograms_xml/others/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/others/histograms.xml
@@ -1251,6 +1251,53 @@ </summary> </histogram> +<histogram name="BlueZ.AdvertisementMonitor.NumOfMonitors" units="count" + expires_after="2021-12-28"> + <owner>apusaka@chromium.org</owner> + <owner>chromeos-bt-platform-sw-core@google.com</owner> + <summary> + This is specific to Chrome OS. Records the number of active advertisement + monitors every couple of minutes. This helps us to gauge the additional + power requirement for the advertisement monitor feature. + </summary> +</histogram> + +<histogram name="BlueZ.AdvertisementMonitor.{Filter}.FilterPatternsPerMinute" + units="count" expires_after="2021-12-28"> + <owner>apusaka@chromium.org</owner> + <owner>chromeos-bt-platform-sw-core@google.com</owner> + <summary> + This is specific to Chrome OS. Records the number of advertisement packet + received in the user space while the advertisement monitor is done using + {Filter} filtering. This helps us to gauge the additional power requirement + for the advertisement monitor feature. + </summary> + <token key="Filter"> + <variant name="MSFT"/> + <variant name="SW"/> + </token> +</histogram> + +<histogram name="BlueZ.AdvertisementMonitor.{Filter}.{Operation}.Result" + enum="BlueZResultOfAdvertisementMonitor" expires_after="2021-12-28"> + <owner>apusaka@chromium.org</owner> + <owner>chromeos-bt-platform-sw-core@google.com</owner> + <summary> + This is specific to Chrome OS. Records the outcome of {Operation} operation + of advertisement monitor when {Filter} filtering is used. This helps us to + verify the correctness of this feature as well as to point out possible + regression. + </summary> + <token key="Filter"> + <variant name="MSFT"/> + <variant name="SW"/> + </token> + <token key="Operation"> + <variant name="Add"/> + <variant name="Remove"/> + </token> +</histogram> + <histogram name="BlueZ.ChipLost2" units="seconds" expires_after="2021-05-16"> <owner>sonnysasaka@chromium.org</owner> <summary> @@ -4628,7 +4675,7 @@ </histogram> <histogram name="EasyUnlock.AuthEvent.DidUserManuallyUnlockPhone" - enum="EasyUnlockDidUserManuallyUnlockPhone" expires_after="2021-02-02"> + enum="EasyUnlockDidUserManuallyUnlockPhone" expires_after="2022-02-02"> <owner>hansberry@chromium.org</owner> <owner>better-together-dev@google.com</owner> <summary> @@ -4640,7 +4687,7 @@ </histogram> <histogram name="EasyUnlock.AuthEvent.SignIn" enum="EasyUnlockAuthEvent" - expires_after="2021-06-06"> + expires_after="2022-02-02"> <owner>hansberry@chromium.org</owner> <owner>better-together-dev@google.com</owner> <summary> @@ -4652,7 +4699,7 @@ </histogram> <histogram name="EasyUnlock.AuthEvent.SignIn.Duration" units="ms" - expires_after="2021-02-02"> + expires_after="2022-02-02"> <owner>hansberry@chromium.org</owner> <owner>better-together-dev@google.com</owner> <summary> @@ -4662,7 +4709,7 @@ </histogram> <histogram name="EasyUnlock.AuthEvent.Unlock" enum="EasyUnlockAuthEvent" - expires_after="2021-06-06"> + expires_after="2022-02-02"> <owner>hansberry@chromium.org</owner> <owner>better-together-dev@google.com</owner> <summary> @@ -4674,7 +4721,7 @@ </histogram> <histogram name="EasyUnlock.AuthEvent.Unlock.Duration" units="ms" - expires_after="2021-04-04"> + expires_after="2022-02-02"> <owner>hansberry@chromium.org</owner> <owner>better-together-dev@google.com</owner> <summary> @@ -4686,7 +4733,7 @@ </histogram> <histogram name="EasyUnlock.AuthProximity.RemoteDeviceModelHash" - enum="EasyUnlockDeviceModelHash" expires_after="2021-02-02"> + enum="EasyUnlockDeviceModelHash" expires_after="2022-02-02"> <owner>hansberry@chromium.org</owner> <owner>better-together-dev@google.com</owner> <summary> @@ -4700,7 +4747,7 @@ </histogram> <histogram name="EasyUnlock.AuthProximity.RollingRssi" units="dBm" - expires_after="2021-02-02"> + expires_after="2022-02-02"> <owner>hansberry@chromium.org</owner> <owner>better-together-dev@google.com</owner> <summary> @@ -4721,7 +4768,7 @@ </histogram> <histogram name="EasyUnlock.RemoteLockScreenState" - enum="EasyUnlockRemoteLockScreenState" expires_after="2021-02-02"> + enum="EasyUnlockRemoteLockScreenState" expires_after="2022-02-02"> <owner>hansberry@chromium.org</owner> <owner>better-together-dev@google.com</owner> <summary> @@ -4735,7 +4782,7 @@ </histogram> <histogram name="EasyUnlock.StartupTimeFromSuspend" units="ms" - expires_after="2021-02-02"> + expires_after="2022-02-02"> <owner>hansberry@chromium.org</owner> <owner>better-together-dev@google.com</owner> <summary> @@ -6746,7 +6793,10 @@ </histogram> <histogram name="ImportantFile.DeleteOnCloseError" enum="PlatformFileError" - expires_after="2021-01-19"> + expires_after="M89"> + <obsolete> + Removed in M89. + </obsolete> <owner>grt@chromium.org</owner> <owner>xaerox@yandex-team.ru</owner> <summary>
diff --git a/tools/metrics/histograms/histograms_xml/profile/histograms.xml b/tools/metrics/histograms/histograms_xml/profile/histograms.xml index fa0b66d4..a26f13ec 100644 --- a/tools/metrics/histograms/histograms_xml/profile/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/profile/histograms.xml
@@ -248,6 +248,17 @@ </summary> </histogram> +<histogram name="Profile.KeepAliveLeakAtShutdown" enum="ProfileKeepAliveOrigin" + expires_after="2021-06-01"> + <owner>nicolaso@chromium.org</owner> + <owner>cbe-eng@google.com</owner> + <summary> + Recorded during BrowserProcess teardown. Indicates that a Profile still has + ScopedProfileKeepAlive objects referencing it, of the given origin. This is + a sign of a bug, or incorrect usage of the ScopedProfileKeepAlive API. + </summary> +</histogram> + <histogram name="Profile.Menu.ClickedActionableItem" enum="ProfileMenuActionableItem" expires_after="2021-06-30"> <owner>droger@chromium.org</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index b371e75..609aea1 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -9,8 +9,8 @@ "remote_path": "perfetto_binaries/trace_processor_shell/mac/070ef598892aee3d5cfb628f577867217c863142/trace_processor_shell" }, "linux": { - "hash": "153bdd7d922d3d225b8c2855de063cf00ff59efa", - "remote_path": "perfetto_binaries/trace_processor_shell/linux/070ef598892aee3d5cfb628f577867217c863142/trace_processor_shell" + "hash": "5417da4ae1c19ada86faeaba0e3d694c4ff3661b", + "remote_path": "perfetto_binaries/trace_processor_shell/linux/3ce4e8ee1301d0102b3595187a93a3ba067b2a69/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn index 24ab739..dc5eedf 100644 --- a/ui/base/BUILD.gn +++ b/ui/base/BUILD.gn
@@ -1036,7 +1036,10 @@ "ime/chromeos/input_method_descriptor_unittest.cc", "ime/chromeos/input_method_util_unittest.cc", ] - deps += [ "//ui/base/ime/chromeos" ] + deps += [ + "//build:branding_buildflags", + "//ui/base/ime/chromeos", + ] } if ((is_linux || is_chromeos_lacros) && use_aura) { sources += [ "dragdrop/os_exchange_data_provider_non_backed_unittest.cc" ]
diff --git a/ui/base/ime/chromeos/extension_ime_util.cc b/ui/base/ime/chromeos/extension_ime_util.cc index 9588354..54ff2f2 100644 --- a/ui/base/ime/chromeos/extension_ime_util.cc +++ b/ui/base/ime/chromeos/extension_ime_util.cc
@@ -4,6 +4,7 @@ #include "ui/base/ime/chromeos/extension_ime_util.h" +#include "base/strings/strcat.h" #include "base/strings/string_util.h" #include "build/branding_buildflags.h" @@ -166,5 +167,16 @@ return false; } +bool IsExperimentalMultilingual(const std::string& input_method_id) { +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) + const std::string prefix = base::StrCat( + {kComponentExtensionIMEPrefix, kXkbExtensionId, "experimental_"}); + return base::StartsWith(input_method_id, prefix, + base::CompareCase::SENSITIVE); +#else + return false; +#endif +} + } // namespace extension_ime_util } // namespace chromeos
diff --git a/ui/base/ime/chromeos/extension_ime_util.h b/ui/base/ime/chromeos/extension_ime_util.h index a81c488..c975c14e 100644 --- a/ui/base/ime/chromeos/extension_ime_util.h +++ b/ui/base/ime/chromeos/extension_ime_util.h
@@ -99,6 +99,11 @@ std::string COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) GetComponentIDByInputMethodID(const std::string& input_method_id); +// Returns true if |input_method_id| refers to a CrOS 1P experimental +// multilingual input method. +bool COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) + IsExperimentalMultilingual(const std::string& input_method_id); + } // namespace extension_ime_util } // namespace chromeos
diff --git a/ui/base/ime/chromeos/extension_ime_util_unittest.cc b/ui/base/ime/chromeos/extension_ime_util_unittest.cc index 38ee414..d71a814b 100644 --- a/ui/base/ime/chromeos/extension_ime_util_unittest.cc +++ b/ui/base/ime/chromeos/extension_ime_util_unittest.cc
@@ -6,6 +6,8 @@ #include <string> +#include "base/strings/strcat.h" +#include "build/branding_buildflags.h" #include "testing/gtest/include/gtest/gtest.h" namespace chromeos { @@ -82,4 +84,30 @@ EXPECT_FALSE(extension_ime_util::IsArcIME("mozc")); } +TEST(ExtensionIMEUtilTest, IsExperimentalMultilingualTest) { + // TODO(crbug.com/1162211): Input method IDs are tuples of extension type, + // extension ID, and extension-local input method ID. However, currently + // they're just concats of the three constituent pieces of info, hence StrCat + // here. Replace StrCat once they're no longer unstructured string concats. + + EXPECT_FALSE(extension_ime_util::IsExperimentalMultilingual( + base::StrCat({"some_extension_type", "some_extension_id", + "experimental_hello_world"}))); + + EXPECT_FALSE(extension_ime_util::IsExperimentalMultilingual(base::StrCat( + {"_comp_ime_", "some_extension_id", "experimental_hello_world"}))); + + EXPECT_FALSE(extension_ime_util::IsExperimentalMultilingual(base::StrCat( + {"_comp_ime_", "jkghodnilhceideoidjikpgommlajknk", "hello_world"}))); + +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) + EXPECT_TRUE( +#else + EXPECT_FALSE( +#endif + extension_ime_util::IsExperimentalMultilingual( + base::StrCat({"_comp_ime_", "jkghodnilhceideoidjikpgommlajknk", + "experimental_hello_world"}))); +} + } // namespace chromeos
diff --git a/ui/file_manager/BUILD.gn b/ui/file_manager/BUILD.gn index 717f98cc..7f6dbd4c 100644 --- a/ui/file_manager/BUILD.gn +++ b/ui/file_manager/BUILD.gn
@@ -87,13 +87,17 @@ in_files = [ "audio_player/js/main.m.js", "audio_player/js/main_background.m.js", + "file_manager/background/js/main_background.m.js", "video_player/js/main.m.js", "video_player/js/main_background.m.js", ] deps = [ "//ui/file_manager/audio_player/js:main.m", + "//ui/file_manager/audio_player/js:main_background.m", + "//ui/file_manager/file_manager/background/js:main_background.m", "//ui/file_manager/video_player/js:main.m", + "//ui/file_manager/video_player/js:main_background.m", ] } @@ -117,39 +121,75 @@ # Base: "base/js/app_util.m.js", - "base/js/volume_manager_types.m.js", - "base/js/mediasession_types.m.js", + "base/js/error_counter.m.js", "base/js/filtered_volume_manager.m.js", + "base/js/mediasession_types.m.js", + "base/js/volume_manager_types.m.js", # Common: "file_manager/common/js/async_util.m.js", - "file_manager/common/js/util.m.js", + "file_manager/common/js/file_operation_common.m.js", "file_manager/common/js/file_type.m.js", "file_manager/common/js/files_app_entry_types.m.js", + "file_manager/common/js/importer_common.m.js", "file_manager/common/js/lru_cache.m.js", "file_manager/common/js/metrics.m.js", "file_manager/common/js/metrics_base.m.js", + "file_manager/common/js/progress_center_common.m.js", + "file_manager/common/js/trash.m.js", + "file_manager/common/js/util.m.js", # Externs: - "externs/entry_location.m.js", - "externs/files_app_entry_interfaces.m.js", "externs/background/background_base.m.js", + "externs/background/crostini.m.js", + "externs/background/drive_sync_handler.m.js", + "externs/background/duplicate_finder.m.js", + "externs/background/file_browser_background_full.m.js", + "externs/background/file_operation_manager.m.js", + "externs/background/import_history.m.js", + "externs/background/media_import_handler.m.js", + "externs/background/media_scanner.m.js", + "externs/background/progress_center.m.js", + "externs/background/task_queue.m.js", + "externs/entry_location.m.js", + "externs/exif_entry.m.js", + "externs/files_app_entry_interfaces.m.js", + "externs/metadata_worker_window.m.js", + "externs/progress_center_panel.m.js", "externs/volume_info.m.js", "externs/volume_info_list.m.js", "externs/volume_manager.m.js", - "externs/metadata_worker_window.m.js", - "externs/exif_entry.m.js", # Files app Background: - "file_manager/background/js/app_windows.m.js", "file_manager/background/js/app_window_wrapper.m.js", + "file_manager/background/js/app_windows.m.js", + "file_manager/background/js/background.m.js", "file_manager/background/js/background_base.m.js", + "file_manager/background/js/crostini.m.js", + "file_manager/background/js/device_handler.m.js", + "file_manager/background/js/drive_sync_handler.m.js", + "file_manager/background/js/duplicate_finder.m.js", "file_manager/background/js/entry_location_impl.m.js", - "file_manager/background/js/volume_manager_factory.m.js", - "file_manager/background/js/volume_manager_impl.m.js", + "file_manager/background/js/file_operation_handler.m.js", + "file_manager/background/js/file_operation_manager.m.js", + "file_manager/background/js/file_operation_util.m.js", + "file_manager/background/js/import_history.m.js", + "file_manager/background/js/launcher.m.js", + "file_manager/background/js/launcher_search.m.js", + "file_manager/background/js/media_import_handler.m.js", + "file_manager/background/js/media_scanner.m.js", + "file_manager/background/js/metadata_proxy.m.js", + "file_manager/background/js/metrics_start.m.js", + "file_manager/background/js/mount_metrics.m.js", + "file_manager/background/js/progress_center.m.js", + "file_manager/background/js/task_queue.m.js", + "file_manager/background/js/test_util.m.js", + "file_manager/background/js/test_util_base.m.js", + "file_manager/background/js/trash.m.js", "file_manager/background/js/volume_info_impl.m.js", "file_manager/background/js/volume_info_list_impl.m.js", - "file_manager/background/js/test_util_base.m.js", + "file_manager/background/js/volume_manager_factory.m.js", + "file_manager/background/js/volume_manager_impl.m.js", "file_manager/background/js/volume_manager_util.m.js", # Files app Foreground: @@ -222,6 +262,7 @@ "audio_player/js/main_background.m.rollup.js", "audio_player/js/metadata_worker.m.rollup.js", + "file_manager/background/js/main_background.m.rollup.js", "file_manager/foreground/elements/files_icon_button.m.js", "file_manager/foreground/elements/files_toggle_ripple.m.js", "file_manager/foreground/elements/files_ripple.m.js", @@ -234,6 +275,7 @@ "audio_player/js/main.m.rollup.js|audio_player/js/main.m.js", "audio_player/js/main_background.m.rollup.js|audio_player/js/main_background.m.js", "audio_player/js/metadata_worker.m.rollup.js|audio_player/js/metadata_worker.m.js", + "file_manager/background/js/main_background.m.rollup.js|file_manager/background/js/main_background.m.js", "video_player/js/main.m.rollup.js|video_player/js/main.m.js", "video_player/js/main_background.m.rollup.js|video_player/js/main_background.m.js", ] @@ -249,6 +291,7 @@ "//ui/file_manager/audio_player/js:build", "//ui/file_manager/audio_player/js:build_background", "//ui/file_manager/audio_player/js:build_worker", + "//ui/file_manager/file_manager/background/js:build", "//ui/file_manager/file_manager/foreground/elements:elements", "//ui/file_manager/video_player/js:build", "//ui/file_manager/video_player/js:build_background",
diff --git a/ui/file_manager/file_manager/background.html b/ui/file_manager/file_manager/background.html index 1086056..95b12478 100644 --- a/ui/file_manager/file_manager/background.html +++ b/ui/file_manager/file_manager/background.html
@@ -1,10 +1,4 @@ <!DOCTYPE html> <meta charset="utf-8"> -<script src="chrome://resources/js/cr.js"></script> -<script src="chrome://resources/js/cr/event_target.js"></script> -<script src="chrome://resources/js/assert.js"></script> -<script src="chrome://resources/js/cr/ui/array_data_model.js"></script> -<script src="chrome://resources/js/load_time_data.js"></script> -<script src="background/js/background_common_scripts.js"></script> -<script src="background/js/background_scripts.js"></script> +<script type="module" src="background/js/main_background.m.js"></script>
diff --git a/ui/file_manager/file_manager/background/js/BUILD.gn b/ui/file_manager/file_manager/background/js/BUILD.gn index 6fa08250..fb3480a 100644 --- a/ui/file_manager/file_manager/background/js/BUILD.gn +++ b/ui/file_manager/file_manager/background/js/BUILD.gn
@@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//chrome/browser/resources/tools/optimize_webui.gni") import("//third_party/closure_compiler/compile_js.gni") import("//third_party/closure_compiler/js_unit_tests.gni") import("//ui/file_manager/base/gn/js_test_gen_html.gni") @@ -267,6 +268,21 @@ extra_deps = [ ":modulize" ] } +js_library("main_background.m") { + visibility = [] + visibility = [ + ":*", + "//ui/file_manager:preprocess_static", + ] + + deps = [ + ":background.m", + ":metrics_start.m", + ":test_util.m", + "//ui/file_manager/base/js:error_counter.m", + ] +} + js_library("background_base") { visibility += related_apps deps = [ @@ -1315,3 +1331,24 @@ namespace_rewrites = cr_namespace_rewrites } + +preprocess_folder = + rebase_path( + "$target_gen_dir/../../../preprocessed/file_manager/background/js", + root_build_dir) + +optimize_webui("build") { + host = "file_manager" + + input = preprocess_folder + js_module_in_files = [ "main_background.m.js" ] + + js_out_files = [ "main_background.m.rollup.js" ] + + deps = [ + ":main_background.m", + "//ui/file_manager:preprocess_generated", + "//ui/file_manager:preprocess_static", + "//ui/webui/resources:preprocess", + ] +}
diff --git a/ui/file_manager/file_manager/background/js/main_background.m.js b/ui/file_manager/file_manager/background/js/main_background.m.js new file mode 100644 index 0000000..de846b6d --- /dev/null +++ b/ui/file_manager/file_manager/background/js/main_background.m.js
@@ -0,0 +1,13 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview Main entry point for background page, it replaces the + * background_scripts.js. + */ + +import './metrics_start.m.js'; +import '../../../base/js/error_counter.m.js'; +import './background.m.js'; +import './test_util.m.js';
diff --git a/ui/file_manager/file_manager/test/BUILD.gn b/ui/file_manager/file_manager/test/BUILD.gn index 6f0b620..f48e22d 100644 --- a/ui/file_manager/file_manager/test/BUILD.gn +++ b/ui/file_manager/file_manager/test/BUILD.gn
@@ -4,7 +4,7 @@ import("//third_party/closure_compiler/compile_js.gni") -python2_action("create_test_main") { +action("create_test_main") { script = "//ui/file_manager/file_manager/test/scripts/create_test_main.py" output = "$target_gen_dir/../test.html" sources = [
diff --git a/ui/file_manager/file_manager/test/scripts/create_test_main.py b/ui/file_manager/file_manager/test/scripts/create_test_main.py index cc953b1a..24b7057 100755 --- a/ui/file_manager/file_manager/test/scripts/create_test_main.py +++ b/ui/file_manager/file_manager/test/scripts/create_test_main.py
@@ -45,16 +45,16 @@ GENERATED_HTML = '<!-- %s -->\n\n' % GENERATED -def read(path): - with open(os.path.join(SRC, path)) as f: +def read(path, mode='r'): + with open(os.path.join(SRC, path), mode) as f: return f.read() -def write(path, content): +def write(path, content, mode='w'): fullpath = os.path.join(GEN, path) if not os.path.exists(os.path.dirname(fullpath)): os.makedirs(os.path.dirname(fullpath)) - with open(fullpath, 'w') as f: + with open(fullpath, mode) as f: f.write(content) @@ -130,7 +130,11 @@ srcf = os.path.join(root[len(SRC):], f) dstf = R_GEN + dst_dir + srcf[len(src_dir):] relpath = os.path.relpath(R_GEN, os.path.dirname(dstf)) + '/' - write(dstf, i18n(read(srcf).replace('chrome://resources/', relpath))) + try: + write(dstf, i18n(read(srcf).replace('chrome://resources/', relpath))) + except UnicodeDecodeError: + # Binary files get utf-8 codec errors in py3, copy them as binary. + write(dstf, read(srcf, 'rb'), 'wb') # Copy any files required in chrome://resources/... into test/gen/resources. copyresources('ui/webui/resources/', '') @@ -256,5 +260,5 @@ main_html = replaceline(main_html, filename, ['<script src="test/gen/%s"></script>' % filename]) -test_html = GENERATED_HTML + '\n'.join(main_html).encode('utf-8') -write('test.html', test_html) +test_html = (GENERATED_HTML + '\n'.join(main_html)).encode('utf-8') +write('test.html', test_html, 'wb')
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn index 6570153..03db25c7 100644 --- a/ui/views/BUILD.gn +++ b/ui/views/BUILD.gn
@@ -530,6 +530,10 @@ deps += [ "//ui/display/util" ] } + if (is_chromeos) { + deps += [ "//ui/base/ime/chromeos" ] + } + if (is_linux || is_chromeos) { public += [ "color_chooser/color_chooser_view.h" ] sources += [ "color_chooser/color_chooser_view.cc" ]
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc index 1c79aa2..590da79 100644 --- a/ui/views/controls/textfield/textfield.cc +++ b/ui/views/controls/textfield/textfield.cc
@@ -96,6 +96,11 @@ #include "ui/ozone/public/platform_gl_egl_utility.h" #endif +#if defined(OS_CHROMEOS) +#include "ui/base/ime/chromeos/extension_ime_util.h" +#include "ui/base/ime/chromeos/input_method_manager.h" +#endif + namespace views { namespace { @@ -1937,6 +1942,20 @@ if (!range.is_empty()) { base::UmaHistogramEnumeration("InputMethod.Assistive.Autocorrect.Count", TextInputClient::SubClass::kTextField); + +#if defined(OS_CHROMEOS) + auto* input_method_manager = + chromeos::input_method::InputMethodManager::Get(); + if (input_method_manager && + chromeos::extension_ime_util::IsExperimentalMultilingual( + input_method_manager->GetActiveIMEState() + ->GetCurrentInputMethod() + .id())) { + base::UmaHistogramEnumeration( + "InputMethod.MultilingualExperiment.Autocorrect.Count", + TextInputClient::SubClass::kTextField); + } +#endif } return model_->SetAutocorrectRange(range); }