diff --git a/.github/prompts/refactor_bedrock_test_part_1.prompt.md b/.github/prompts/refactor_bedrock_test_part_1.prompt.md index 87c670dd..333b298d 100644 --- a/.github/prompts/refactor_bedrock_test_part_1.prompt.md +++ b/.github/prompts/refactor_bedrock_test_part_1.prompt.md
@@ -12,13 +12,51 @@ ## Step by step instructions ```markdown -[ ] 0. Before you start -[ ] 1. Rename Test File -[ ] 2. Tell the user they must manually update `chrome/test/BUILD.gn` -[ ] 3. Tell the user they must format, stage and commit the changes -[ ] 4. Tell the user to proceed to refactoring part 2 +[ ] 1. Review user input +[ ] 2. Find the right `BUILD.gn` file +[ ] 3. Consider updating the `BUILD.gn` file +[ ] 4. Wait for the user to confirm they have updated the `BUILD.gn` file +[ ] 5. Rename Test File +[ ] 6. Tell the user to format, stage and commit the changes +[ ] 7. Tell the user to proceed to refactoring part 2 ``` +## Review user input +Review the following information before messaging the user so you can help them +effectively. + +You are responsible for determining the following variables: + - `${out_dir}`: The build directory (e.g., `out/debug_x64`). + +- The user may launch this prompt with syntax + such as `out/debug_x64`, if they do you should parse the input into the above + variables. +- The user may have specified `## Developer Prompt Variables`. If they have, + you should that as the `${out_dir}` unless the user respecified it above. + +### If the user did not provide satisfactory input +- If the user did not provide input, or provided some input, but did not provide +satisfactory input, to know `${out_dir}` . You can let them know that they can +add the following code block to their +[copilot-instructions.md](../copilot-instructions.md) file to set the default +`${out_dir}`. + ```markdown + ## Developer Prompt Variables + `${out_dir}` = `debug_x64` + ``` + +## Find the right `BUILD.gn` file +You will need to find the file that references the test file you are +refactoring. You can find this with the following command: +`gn refs out/{out_dir} ${file}` + +- If the output is `//chrome/browser/foo:bar`, the file will be + `chrome/browser/foo/BUILD.gn` and inside of the `${target}` `bar`. + You do not need to search for the `BUILD.gn` file, you can open it directly + since chrome is accessible relative to this file at + [`../../chrome/](../../chrome/). + + ## Rename Test File You **must** use `git mv` to rename the test file `${file}`. - The new filename should replace the `_unittest.cc` suffix with @@ -26,19 +64,36 @@ - *Example*: If `${file}` is `foo_unittest.cc`, the command would be `git mv foo_unittest.cc foo_browsertest.cc`. -## Instructions for Updating `chrome/test/BUILD.gn` -Tell the user they need to manually update the `chrome/test/BUILD.gn` file since -its too long for your context window. +## Consider updating the `BUILD.gn` file +Check the file length of the `BUILD.gn` file you found in the previous step. +- You must do this using `(Get-Content ${file}).Count` -When refactoring a unit test to a browser test in Chromium, they will need to -manually update the `chrome/test/BUILD.gn` file. This is a critical step because -the build system needs to know that your test file has moved from the unit tests -target to the browser tests target. +## If the file is under 4000 lines +You should attempt to follow the instructions below to update the +`BUILD.gn` file yourself. -Here's what they will need to do: +## If the file is over 4000 lines +If the file is over 4000 lines, tell the user the file is too long for your +context window. Tell the user they need to manually update the `BUILD.gn` file +since its too long for your context window. -1. **Find your original test file in the unit_tests section**: - - Look for your original file path in the `test("unit_tests")` section +### Updating the `BUILD.gn` file +When refactoring a unit test to a browser test in Chromium, you will need to +update the `BUILD.gn` file. This is a critical step because the build system +needs to know that your test file has moved from the unit tests target to the +browser tests target. + +You will need to explain your chain of thought and follow these step by step: +```markdown +[ ] 1. Find your original test file in the unit_tests section +[ ] 2. Remove the entry from unit_tests +[ ] 3. Add to browser_tests +[ ] 4. Review modified lines +``` + +#### Find your original test file in the `${target}` section + - Look for your original file path in the the `${target}`, this will likely + be a `test("unit_tests")` or `source_set("...unit_tests")` section - The file path will be formatted as a relative path, like: `"../browser/path/to/your_unittest.cc"` - For example, if your original file was at @@ -47,40 +102,80 @@ sources list - you can tell them the name of the file they are looking for -2. **Remove the entry from unit_tests**: - - Delete this line completely from the `sources = [ ... ]` list in the - `test("unit_tests")` section +#### Remove the file entry from unit_tests + - Delete the file entry only line from the `sources = [ ... ]` list in the + `${target}` section + - Do not delete the entire `sources = [ ... ]` block, just the line with your + original test file + - For example, if you are removing the line: + `../browser/ui/views/my_feature_unittest_2.cc`, + ```gn + # Before + # sources = [ + # ..., + # "../browser/ui/views/my_feature_unittest_1.cc", + # "../browser/ui/views/my_feature_unittest_2.cc", + # "../browser/ui/views/my_feature_unittest_3.cc", + # ..., + # ] + # After + sources = [ + ..., + "../browser/ui/views/my_feature_unittest_1.cc", + "../browser/ui/views/my_feature_unittest_3.cc", + ..., + ] + ``` -3. **Add to browser_tests**: - - Find the `test("browser_tests")` section in the file - - Add a new line with your renamed file path to its `sources = [ ... ]` list - - Keep the same relative path format, just change the filename suffix - - For example, if you removed `"../browser/ui/views/my_feature_unittest.cc"`, - you'd add `"../browser/ui/views/my_feature_browsertest.cc"` - - Let them know you will run a format tool to ensure the file is formatted - and sorted correctly - -4. **Respect any conditional blocks**: +#### Find the location to add the new browser test + - Look for the `browser_tests` section in the same `BUILD.gn` file + - This will likely be a `test("browser_tests")` or + `source_set("...browser_tests")` section + - If you don't see a `browser_tests` section, you may need to create one and + hook it up to `chrome/test/BUILD.gn`. - Pay attention to any `if` statement blocks that might be surrounding your test file - If your original file was inside a conditional block like `if (is_win)` or `if (enable_extensions)`, make sure to add your new browsertest file in the corresponding conditional block in the browser_tests section -Wait for the user to confirm that they have updated the `chrome/test/BUILD.gn` -file. +#### Add to browser_tests + - You must **add** a new line with your renamed file path to its + `sources = [ ... ]` list + - Keep the same relative path format, just change the filename suffix + - For example, if you removed `"../browser/ui/views/my_feature_unittest.cc"`, + you'd add `"../browser/ui/views/my_feature_browsertest.cc"` + +#### Review modified lines + - After making these changes, review the modified lines in the `BUILD.gn` + file to ensure they are correct + - Make sure you have removed the old unit test file and added the new + browser test file correctly + - No other lines should be modified + +Before moving on you must **wait** for the user to confirm that the `BUILD.gn` +file has been code reviewed by the user and updated correctly. ## Tell the user to format, stage and commit the changes -After the user has updated the `chrome/test/BUILD.gn` file, you **must** run the -following commands: +After `BUILD.gn` file has been updated you **must** run the following commands +in the following step by step order: +```markdown +[ ] 1. `git cl format ${file} [build.gn file]` +[ ] 2. `git add ${file} [build.gn file]` +[ ] 3. `git commit -m "[Bedrock]: Refactor ${file} _unittest to _browsertest"` +[ ] 4. `git cl upload` +``` -1. `gn add ${file} chrome/test/BUILD.gn` -2. `git cl format` -3. `gn add ${file} chrome/test/BUILD.gn` -4. `git commit -m "[Bedrock]: Refactor ${file} _unittest to _browsertest"` +Tell the user they must run `git cl upload` before continuing to part 2 +to upload the changes the code review system before continuing the refactor so +that code reviewers can clearly disambiguate the changes made in this part of +the refactor compared to the base test. There is a bug in gerrit that causes +large diffs of moved files to not show up correctly, so we want to +upload the changes in two parts to work around +[this known issue](https://g-issues.gerritcodereview.com/issues/40003516). ## Tell the user to proceed to refactoring part 2 After completing the above steps, provide the user with a clickable link to their new file and tell the user to start a new chat and run -[/refactor_unit_test_to_browser_test_part_2](refactor_unit_test_to_browser_test_part_2.prompt.md) +[/refactor_bedrock_part_2](refactor_bedrock_test_part_2.prompt.md) with the new file path.
diff --git a/.github/prompts/refactor_bedrock_test_part_2.prompt.md b/.github/prompts/refactor_bedrock_test_part_2.prompt.md index 3e878a5..1d4b5d37 100644 --- a/.github/prompts/refactor_bedrock_test_part_2.prompt.md +++ b/.github/prompts/refactor_bedrock_test_part_2.prompt.md
@@ -5,11 +5,48 @@ # Chromium Code Refactoring: Unit Test to Browser Test You are an AI assistant with 10 years of experience writing Chromium unit tests -and browser tests. The C++ test file `${file}` (which should now be named -`*_browsertest.cc`) has already been renamed and its entry in -`chrome/test/BUILD.gn` has been updated. Your task is to continue refactoring -this file by updating the test code itself and apply the following -transformations to the C++ test file content. +and browser tests. + +The C++ test file `${file}` (which should now be named `*_browsertest.cc`) has +already been renamed and its entry in `chrome/test/BUILD.gn` has been updated. + +Your primary goal is the elimination of the following classes and utilities by +conversion to browser tests. Significant test rework is not intended +(except for where absolutely necessary): +- `TestBrowserWindow` +- `BrowserWithTestWindowTest` +- `TestWithBrowserView` +- `CreateBrowserWithTestWindowForParams` + +Your task is to continue refactoring this file by updating the test code itself +and apply the following transformations to the C++ test file content. + +## Background +There are existing test fixtures and utilities that encourage use of Browser in +the unit_test target, namely those provided above. + +### Problem +- Encourages use of Browser instead of dependency injection + - Tests end up depending on the entirety of `//chrome/browser:browser` + and `//chrome/browser/ui::ui` + - Unit tests should be narrowly scoped to the feature under test +- Non representative tests + - Browser is partially / incorrectly constructed + - Incomplete construction of BrowserWindowFeatures + - Non representative environments (many services not instantiated) + - Construction / destruction / lifetimes do not match production + +### Solution +An initial step in addressing Browser dependency in unit tests is the +elimination of the test fixtures and utilities above. + +This can be done by converting such unit tests to browser tests. This ensures +that these unit tests (which are effectively browser tests) run in a more +representative environment. Once this conversion is complete the problematic +fixtures and utilities can also be removed. + +There may also be cases where unit tests use of the above fixtures and utilities +is unnecessary, and tests can simply be converted to a regular unit test. ## Step by step instructions @@ -23,6 +60,8 @@ [ ] 4. Adapt `TearDown` Method Signature [ ] 5. Update Test Case Definition Macro [ ] 6. Refactor Internal Test Logic +[ ] 7. Update all Common Browser Interaction Patterns (Examples) +[ ] 8. Tell the user to proceed to `/gtest` ``` ## Tell the user to proceed to `gtest` @@ -31,9 +70,22 @@ test. ## Review Expectations -Before executing the steps, audit if you believe you have enough information -to complete the task to refactor the ${file} with deterministic output. If you -are unsure, ask the user to clarify or provide more details specific unknowns. +You are responsible for the following: +- audit if you believe you have enough information to complete the task to + refactor the ${file} with deterministic output. +- If you are unsure of how to convert a code pattern, ask the user to clarify + or provide more details specific unknowns. +- You **must** minimize the diff required to refactor the test, you should + preserve as many lines of the original test as possible. +- Do **not** add additional comments or explanations to the code. +- Do **not** add additional asserts to the code that the original test did not + have. +- When a **mock** is used, ask the user if they would like it to be + replaced with a real browser interaction or if it should be kept as a mock. + Let them know that ideally, browser tests should not use mocks because they + are not testing the browser's behavior, however, if changing the mock + causes a very large diff, it may be better to keep the mock for now and remove + the mock in a future refactoring step. ## Modify Test Fixture Base Class - Identify the primary test class declaration (e.g., @@ -44,10 +96,12 @@ `class YourTestSuiteName : public BrowserWithTestWindowTest {` - Modify the base class to `InProcessBrowserTest`. - *Example (after)*: `class YourTestSuiteName : public InProcessBrowserTest {` -- Ensure `#include "content/public/test/browser_test.h"` is present for - `InProcessBrowserTest`. If `BrowserWithTestWindowTest` was used, its header +- Ensure `#include "chrome/test/base/in_process_browser_test.h"` and + `#include "content/public/test/browser_test.h"` are present + for `InProcessBrowserTest`. +- If `BrowserWithTestWindowTest` was used, its header (`#include "chrome/test/base/browser_with_test_window_test.h"`) should be - removed if it is no longer needed. + removed, it is no longer needed. ## Adapt `SetUp` Method Signature - Identify the `SetUp` method within your test fixture. @@ -87,10 +141,16 @@ `chrome/test/base/ui_test_utils.h`). ## Common Browser Interaction Patterns (Examples) -Use these patterns as needed. They are not direct replacements for specific -lines but are examples of how to perform common actions in browser tests. +Review the following common patterns and adapt your test code accordingly. +If the code is using an older pattern, replace it with the new one. + +### Required Headers +- if `browser()->` is used, ensure + `#include "chrome/browser/ui/browser.h"` is present. ### Adding a new tab to the active browser +- Replace uses of `AddTab(...)` with + `ui_test_utils::NavigateToURLWithDisposition(..)`. - Requires `#include "chrome/test/base/ui_test_utils.h"` for `AddTabAtIndex`. - using `ui_test_utils` for more robust tab addition: ```cpp @@ -109,20 +169,13 @@ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); ``` -### Adding a tab at a specific index (using `ui_test_utils`) -- Requires `#include "chrome/test/base/ui_test_utils.h"`. -```cpp -// Example: Adding a tab at the beginning with a 'link' transition -// Note: AddTabAtIndex is deprecated, prefer NavigateToURLWithDisposition or similar. -// If you must use it: -// ui_test_utils::AddTabAtIndex(0, GURL("about:blank"), ui::PAGE_TRANSITION_LINK); -// This assumes AddTabAtIndex is available and correctly scoped or called on browser()->tab_strip_model(). -// A more modern approach: -NavigateParams params(browser(), GURL("about:blank"), ui::PAGE_TRANSITION_LINK); -params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB; -params.tabstrip_index = 0; -ui_test_utils::Navigate(¶ms); -``` +### Getting the profiles +- For getting a `Profile*` the code must use + ```cpp + browser()->profile() + ``` + +### Navigation ### Accessing the active WebContents - Requires `#include "chrome/browser/ui/tabs/tab_strip_model.h"` and @@ -136,9 +189,13 @@ ### Navigating the current tab to a URL and waiting for completion Requires `#include "chrome/test/base/ui_test_utils.h"` and `#include "url/gurl.h"`. -```cpp -ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL("chrome://version"))); -``` +- Replace uses of `NavigateAndCommit()` and `NavigateAndCommitActiveTab()` +- using `ui_test_utils` for more robust tab addition: + ```cpp + ui_test_utils::NavigateToURLWithDisposition( + browser(), GURL("about:blank"), WindowOpenDisposition::CurrentTab, + ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); + ``` ### Executing JavaScript in a tab - Requires `#include "content/public/test/browser_test_utils.h"` and @@ -155,6 +212,9 @@ ### Waiting for conditions - Browser tests often require waiting for asynchronous operations. - Use appropriate waiting mechanisms, e.g., - `content::TestNavigationObserver`, `base::RunLoop`, or specific - `ui_test_utils` waiters. + Use appropriate waiting mechanisms, e.g.,`content::TestNavigationObserver` + or specific `ui_test_utils` waiters. +- Instead of `base::RunLoop` or other alternatives, use `base/test/run_until.h` + ```cpp + [[nodiscard]] bool RunUntil(base::FunctionRef<bool(void)> condition); + ```
diff --git a/.gn b/.gn index 60f8591a..ae58a0b0 100644 --- a/.gn +++ b/.gn
@@ -75,9 +75,6 @@ clang_unsafe_buffers_paths = "//build/config/unsafe_buffers_paths.txt" clang_warning_suppression_file = "//build/config/warning_suppression.txt" - - # Use Siso instead of Ninja. - use_siso = true } # These are the targets to skip header checking by default. The files in targets
diff --git a/BUILD.gn b/BUILD.gn index e32e315..9b416fb 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -1185,7 +1185,10 @@ # https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/run_web_platform_tests.md script_test("chrome_wpt_tests") { script = "//third_party/blink/tools/run_wpt_tests.py" - args = _common_web_test_options + [ "--product=chrome" ] + args = _common_web_test_options + [ + "--product=chrome", + "--verbose", + ] if (dcheck_always_on) { args += [ "--timeout-multiplier=2" ] } else { @@ -1209,7 +1212,10 @@ # https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/run_web_platform_tests.md script_test("headless_shell_wpt") { script = "//third_party/blink/tools/run_wpt_tests.py" - args = _common_web_test_options + [ "--product=headless_shell" ] + args = _common_web_test_options + [ + "--product=headless_shell", + "--verbose", + ] data_deps = [ ":blink_web_tests_expectations", ":blink_web_tests_support_data",
diff --git a/DEPS b/DEPS index 95cb4801..45bf48d 100644 --- a/DEPS +++ b/DEPS
@@ -295,19 +295,19 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'src_internal_revision': '6113fc67631d1ddb7a8918e5bb92e34d8492710b', + 'src_internal_revision': '0cd9d611e47ef77b8acd24fba00403d8709bd2da', # 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': 'e2dc10af85db2b3c8e95fe0b7f5817614fb31419', + 'skia_revision': '82d326fc2148181e8d9ca848b17237fa4db75331', # 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': 'e180c60cc3eb265924e992248b0fe2c68e122cab', + 'v8_revision': '61ddd471ece346840bbebbb308dceb4b4ce31b28', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '2f6f0514563d81e439e04ba09eee9e8a1d6ca8d1', + 'angle_revision': '90668ecf2978f085de9a9bdef4d8e5bad79df71e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -315,7 +315,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': 'cf433ae5520d061db56391155b59b34e67484f39', + 'pdfium_revision': '66b63bba62fc2587bf91d3a055a9079f5984b8c6', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -371,7 +371,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '61f9c08d6ae028f8440b1ddddb330cfdf028c159', + 'catapult_revision': '3af14c3b4e2496ad1b85e1f33823f006e30fe8e0', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling CrossBench # and whatever else without interference from each other. @@ -391,7 +391,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': 'a178b7d51c21c468b397db564aa21e34c7cc0aa2', + 'devtools_frontend_revision': 'c7d5f74c859abdd3219524ec9f77ce98d54a9a15', # 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. @@ -495,7 +495,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'libcxxabi_revision': '9810fb23f6ba666f017c2b67c67de2bcac2b44bd', + 'libcxxabi_revision': '241ef367ab2d135197377a82da5f7aee49a082f8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -822,10 +822,10 @@ 'condition': 'non_git_source', 'objects': [ { - 'object_name': '13eea9a3163f9e91f343e6a3197079986d7276b2', - 'sha256sum': 'd347ed7e5ef83e062d1044df222448e6857aa40d9ac6dace45591dc02f9c61b7', - 'size_bytes': 9650582, - 'generation': 1747160834666855, + 'object_name': '782009f3247d27e3c0a9663eb3a35c78bdca6745', + 'sha256sum': '656900010234995fda28593c8cfa32067117aa7028a8ba062febbc8c28636bb6', + 'size_bytes': 9659657, + 'generation': 1747350963881164, 'output_file': 'node_modules.tar.gz', }, ], @@ -1508,7 +1508,7 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '6a196fc5a4b07b4f6d8c64cb7ab20e43bdbeb43b', + 'cef11550a1facb7d8a76e3d9169d1e0a64adf73a', 'condition': 'checkout_android and checkout_src_internal', }, @@ -1667,7 +1667,7 @@ 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': 'mvb4FoiI7mx7wdZfh0eRwvgiV8OpsdFC_oluXPftl4gC', + 'version': '4iWSQnDJqcLNK274cq1Z7mu50FgwKfBxZhbjbtnga2sC', }, ], 'condition': 'checkout_android and non_git_source', @@ -2000,7 +2000,7 @@ 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '0772b51a975ba1ecf983b52665528d5b1db8a433', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '0b1d80ab9e9f1413234641d193639e5daa92dd5b', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -2475,7 +2475,7 @@ }, 'src/third_party/mutter/src': { - 'url': Var('chromium_git') + '/external/gitlab.gnome.org/GNOME/mutter.git' + '@' + 'e99ff5359c4134093efe3cb2aa208e4addf565c6', + 'url': Var('chromium_git') + '/external/gitlab.gnome.org/GNOME/mutter.git' + '@' + '881058e0a3c395b93986d734d2cff164376a1ec7', 'condition': 'checkout_linux and checkout_mutter', }, @@ -2739,7 +2739,7 @@ 'packages': [ { 'package': 'chromium/third_party/r8', - 'version': 'QhYGRVpYYKZmt3f_Zb2HoJ9LIBEnWaeeLXRNei47Z30C', + 'version': 'i5l_yPIc-ZuKle_ibElGMSf50XN8buMgspBkoObkkRAC', }, ], 'condition': 'checkout_android and non_git_source', @@ -2867,7 +2867,7 @@ 'dep_type': 'cipd', }, - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@9b8253ba5637b5ad10835a8e412f3b29b4cd9dae', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@7a77f5b6428118e42f8a35586578a4fabeba7135', 'src/third_party/glslang/src': '{chromium_git}/external/github.com/KhronosGroup/glslang@be4ee7d0e3bfd151bfda7b3a8e03f8c49c55ed7b', 'src/third_party/spirv-cross/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Cross@b8fcf307f1f347089e3c46eb4451d27f32ebc8d3', 'src/third_party/spirv-headers/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Headers@c9aad99f9276817f18f72a4696239237c83cb775', @@ -2876,7 +2876,7 @@ 'src/third_party/vulkan-loader/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@c913466fdc5004584890f89ff91121bdb2ffd4ba', 'src/third_party/vulkan-tools/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Tools@60b640cb931814fcc6dabe4fc61f4738c56579f6', 'src/third_party/vulkan-utility-libraries/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@49ac28931f28bffaa3cd73dc4ad997284d574962', - 'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@ee2b1e4837b496cacac158f13bac28ad543223f3', + 'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@30f98bc36f99860a6c2cd18c4af5f3f387e0b933', 'src/third_party/vulkan_memory_allocator': Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + '56300b29fbfcc693ee6609ddad3fdd5b7a449a21', @@ -2915,7 +2915,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'c01b768bce4a143e152c1870b6ba99ea6267d2b0', 'src/third_party/webgpu-cts/src': - Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '905c7cbfeaac1cf3feb4c6056dd6f3dbaa06b074', + Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '00bbf5422c1b7a71285c51b2dc1e1637e618b916', 'src/third_party/webpagereplay': Var('chromium_git') + '/webpagereplay.git' + '@' + Var('webpagereplay_revision'), @@ -2935,7 +2935,7 @@ Var('skia_git') + '/external/github.com/google/wuffs-mirror-release-c.git' + '@' + Var('wuffs_revision'), 'src/third_party/weston/src': { - 'url': Var('chromium_git') + '/external/anongit.freedesktop.org/git/wayland/weston.git' + '@' + 'bdba2f9adaca673fd58339d8140bc04727ee279d', + 'url': Var('chromium_git') + '/external/anongit.freedesktop.org/git/wayland/weston.git' + '@' + '4eb10b123b483327214d8da5da67e8bbeeaed8fe', 'condition': 'checkout_linux', }, @@ -4641,7 +4641,7 @@ 'src/components/optimization_guide/internal': { 'url': Var('chrome_git') + '/chrome/components/optimization_guide.git' + '@' + - '2cc55d5ca41fa04a1ac7a1c7971a9aba449d01b3', + 'abe28fc69cad880ec92b198727268aa7fbea55a0', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java index 3260b84..f8a8546 100644 --- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java +++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -1071,6 +1071,7 @@ Flag.baseFeature( "PrefetchServiceWorker", "Enables SpeculationRules prefetch to ServiceWorker-controlled URLs."), + Flag.baseFeature("TimedHTMLParserBudget"), // Add new commandline switches and features above. The final entry should have a // trailing comma for cleaner diffs. };
diff --git a/android_webview/test/BUILD.gn b/android_webview/test/BUILD.gn index 4cb3fd8d..939df9a 100644 --- a/android_webview/test/BUILD.gn +++ b/android_webview/test/BUILD.gn
@@ -96,11 +96,13 @@ } # Options shared by all script test targets that call `run_wpt_tests.py`. +# TODO(crbug.com/419890016): Consolidate the common options. _common_web_test_options = [ "--no-show-results", "--zero-tests-executed-ok", "--build-directory", "@WrappedPath(.)", + "--verbose", ] if (is_debug) { _common_web_test_options += [ "--debug" ]
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index 4990d6d8..802ad8a 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -5656,9 +5656,6 @@ <message name="IDS_ASH_MULTI_DEVICE_SETUP_NEW_USER_POTENTIAL_HOST_EXISTS_TITLE" desc="Title of the notification shown to a user that has not completed the MultiDevice setup when their Chrome device recognizes that they have a phone on their account that the Chrome device can connect to"> Your devices work even better together </message> - <message name="IDS_ASH_MULTI_DEVICE_SETUP_NOTIFIER_TEXT_WITH_PHONE_HUB" desc="The text mentions Phone Hub that shows in the notifier of multidevice setup."> - Quickly send or reply to your phone's messages using Phone Hub - </message> <message name="IDS_ASH_MULTI_DEVICE_SETUP_NOTIFIER_TEXT_WITHOUT_PHONE_HUB" desc="The text does not mention Phone Hub that shows in the notifier of multidevice setup."> Save time by quickly replying to your phone's texts from your Chromebook </message>
diff --git a/ash/ash_strings_grd/IDS_ASH_MULTI_DEVICE_SETUP_NOTIFIER_TEXT_WITH_PHONE_HUB.png.sha1 b/ash/ash_strings_grd/IDS_ASH_MULTI_DEVICE_SETUP_NOTIFIER_TEXT_WITH_PHONE_HUB.png.sha1 deleted file mode 100644 index 324c353..0000000 --- a/ash/ash_strings_grd/IDS_ASH_MULTI_DEVICE_SETUP_NOTIFIER_TEXT_WITH_PHONE_HUB.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -90e72fa71ad7ad060307ceba2445ae6632f9a1ac \ No newline at end of file
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index e8c6e6d..cb603d3 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -2406,42 +2406,6 @@ "PhoneHubMonochromeNotificationIcons", base::FEATURE_ENABLED_BY_DEFAULT); -// Determine whether we use revamped notifier to notify users to start -// onboarding to Phone Hub. -BASE_FEATURE(kPhoneHubOnboardingNotifierRevamp, - "PhoneHubOnboardingNotifierRevamp", - base::FEATURE_ENABLED_BY_DEFAULT); - -// Should we show nudge or notification to the user. -const base::FeatureParam<bool> kPhoneHubOnboardingNotifierUseNudge{ - &kPhoneHubOnboardingNotifierRevamp, "use_nudge", true}; - -const base::FeatureParam< - PhoneHubNotifierTextGroup>::Option phone_hub_notifier_text_groups[] = { - {PhoneHubNotifierTextGroup::kNotifierTextGroupA, "notifier_with_text_A"}, - {PhoneHubNotifierTextGroup::kNotifierTextGroupB, "notifier_with_text_B"}, -}; -// What text should we show to the user. -const base::FeatureParam<PhoneHubNotifierTextGroup> kPhoneHubNotifierTextGroup{ - &kPhoneHubOnboardingNotifierRevamp, "notifier_text_group", - PhoneHubNotifierTextGroup::kNotifierTextGroupB, - &phone_hub_notifier_text_groups}; - -// The length of time passing till we display nudge to users again -const base::FeatureParam<base::TimeDelta> kPhoneHubNudgeDelay{ - &kPhoneHubOnboardingNotifierRevamp, "nudge_delay", base::Hours(24)}; - -// Number of times nudge should be shown to user. -const base::FeatureParam<int> kPhoneHubNudgeTotalAppearancesAllowed{ - &kPhoneHubOnboardingNotifierRevamp, "nudge_total_appearances_allowed", 3}; - -// Determines up to how many minutes into user session multdevice setup -// notification can be shown. -const base::FeatureParam<base::TimeDelta> - kMultiDeviceSetupNotificationTimeLimit{ - &kPhoneHubOnboardingNotifierRevamp, - "MultiDeviceSetupNotificationTimitLimit", base::Minutes(5)}; - BASE_FEATURE(kPhoneHubPingOnBubbleOpen, "PhoneHubPingOnBubbleOpen", base::FEATURE_ENABLED_BY_DEFAULT); @@ -4390,10 +4354,6 @@ return base::FeatureList::IsEnabled(kPhoneHubMonochromeNotificationIcons); } -bool IsPhoneHubOnboardingNotifierRevampEnabled() { - return base::FeatureList::IsEnabled(kPhoneHubOnboardingNotifierRevamp); -} - bool IsPhoneHubPingOnBubbleOpenEnabled() { return base::FeatureList::IsEnabled(kPhoneHubPingOnBubbleOpen); }
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h index 2e10fb9..b0b9e54 100644 --- a/ash/constants/ash_features.h +++ b/ash/constants/ash_features.h
@@ -670,9 +670,6 @@ COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kMouseImposterCheck); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kMultiCalendarSupport); -COMPONENT_EXPORT(ASH_CONSTANTS) -extern const base::FeatureParam<base::TimeDelta> - kMultiDeviceSetupNotificationTimeLimit; COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kMultiZoneRgbKeyboard); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kNearbyPresence); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kNotificationLimit); @@ -796,22 +793,6 @@ COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kPhoneHubMonochromeNotificationIcons); COMPONENT_EXPORT(ASH_CONSTANTS) -BASE_DECLARE_FEATURE(kPhoneHubOnboardingNotifierRevamp); -COMPONENT_EXPORT(ASH_CONSTANTS) -extern const base::FeatureParam<bool> kPhoneHubOnboardingNotifierUseNudge; -enum class PhoneHubNotifierTextGroup { - // The int values should not be changed as they are referenced on the server. - kNotifierTextGroupA = 1, - kNotifierTextGroupB = 2 -}; -COMPONENT_EXPORT(ASH_CONSTANTS) -extern const base::FeatureParam<PhoneHubNotifierTextGroup> - kPhoneHubNotifierTextGroup; -COMPONENT_EXPORT(ASH_CONSTANTS) -extern const base::FeatureParam<base::TimeDelta> kPhoneHubNudgeDelay; -COMPONENT_EXPORT(ASH_CONSTANTS) -extern const base::FeatureParam<int> kPhoneHubNudgeTotalAppearancesAllowed; -COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kPhoneHubPingOnBubbleOpen); COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::FeatureParam<base::TimeDelta> kPhoneHubPingTimeout; @@ -1352,8 +1333,6 @@ COMPONENT_EXPORT(ASH_CONSTANTS) bool IsPhoneHubMonochromeNotificationIconsEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) -bool IsPhoneHubOnboardingNotifierRevampEnabled(); -COMPONENT_EXPORT(ASH_CONSTANTS) bool IsPhoneHubPingOnBubbleOpenEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsPhoneHubShortQuickActionPodsTitlesEnabled();
diff --git a/ash/multi_device_setup/multi_device_notification_presenter.cc b/ash/multi_device_setup/multi_device_notification_presenter.cc index dfa1256..55f080c 100644 --- a/ash/multi_device_setup/multi_device_notification_presenter.cc +++ b/ash/multi_device_setup/multi_device_notification_presenter.cc
@@ -7,7 +7,6 @@ #include <memory> #include <utility> -#include "ash/constants/ash_features.h" #include "ash/constants/notifier_catalogs.h" #include "ash/public/cpp/notification_utils.h" #include "ash/public/cpp/system_tray_client.h" @@ -100,14 +99,6 @@ void MultiDeviceNotificationPresenter::OnPotentialHostExistsForNewUser() { int title_message_id = IDS_ASH_MULTI_DEVICE_SETUP_NEW_USER_POTENTIAL_HOST_EXISTS_TITLE; - if (features::IsPhoneHubOnboardingNotifierRevampEnabled() && - !features::kPhoneHubOnboardingNotifierUseNudge.Get()) { - title_message_id = - features::kPhoneHubNotifierTextGroup.Get() == - features::PhoneHubNotifierTextGroup::kNotifierTextGroupA - ? IDS_ASH_MULTI_DEVICE_SETUP_NOTIFIER_TEXT_WITH_PHONE_HUB - : IDS_ASH_MULTI_DEVICE_SETUP_NOTIFIER_TEXT_WITHOUT_PHONE_HUB; - } std::u16string title = l10n_util::GetStringUTF16(title_message_id); std::u16string message = l10n_util::GetStringFUTF16( IDS_ASH_MULTI_DEVICE_SETUP_NEW_USER_POTENTIAL_HOST_EXISTS_MESSAGE,
diff --git a/ash/system/phonehub/onboarding_nudge_controller.cc b/ash/system/phonehub/onboarding_nudge_controller.cc index 8ad8acd5..c24e015 100644 --- a/ash/system/phonehub/onboarding_nudge_controller.cc +++ b/ash/system/phonehub/onboarding_nudge_controller.cc
@@ -7,7 +7,6 @@ #include <algorithm> #include <memory> -#include "ash/constants/ash_features.h" #include "ash/constants/notifier_catalogs.h" #include "ash/public/cpp/system/anchored_nudge_data.h" #include "ash/public/cpp/system/anchored_nudge_manager.h" @@ -56,25 +55,13 @@ OnboardingNudgeController::~OnboardingNudgeController() = default; void OnboardingNudgeController::ShowNudgeIfNeeded() { - if (!IsInPhoneHubNudgeExperimentGroup()) { - return; - } - if (!ShouldShowNudge()) { return; } - PA_LOG(INFO) - << "Phone Hub onboarding nudge is being shown for text experiment group " - << (features::kPhoneHubNotifierTextGroup.Get() == - features::PhoneHubNotifierTextGroup::kNotifierTextGroupA - ? "A." - : "B."); + PA_LOG(INFO) << "Phone Hub onboarding nudge is being shown."; std::u16string nudge_text = l10n_util::GetStringUTF16( - features::kPhoneHubNotifierTextGroup.Get() == - features::PhoneHubNotifierTextGroup::kNotifierTextGroupA - ? IDS_ASH_MULTI_DEVICE_SETUP_NOTIFIER_TEXT_WITH_PHONE_HUB - : IDS_ASH_MULTI_DEVICE_SETUP_NOTIFIER_TEXT_WITHOUT_PHONE_HUB); + IDS_ASH_MULTI_DEVICE_SETUP_NOTIFIER_TEXT_WITHOUT_PHONE_HUB); AnchoredNudgeData nudge_data = {kPhoneHubNudgeId, NudgeCatalogName::kPhoneHub, nudge_text, anchored_view_}; nudge_data.anchored_to_shelf = true; @@ -101,9 +88,6 @@ } void OnboardingNudgeController::HideNudge() { - if (!IsInPhoneHubNudgeExperimentGroup()) { - return; - } if (AnchoredNudgeManager::Get()->IsNudgeShown(kPhoneHubNudgeId)) { // `HideNudge()` is only invoked when Phone Hub icon is clicked. If the // nudge is visible, it should be counted as interaction. @@ -117,18 +101,11 @@ } void OnboardingNudgeController::MaybeRecordNudgeAction() { - if (!IsInPhoneHubNudgeExperimentGroup()) { - return; - } AnchoredNudgeManager::Get()->MaybeRecordNudgeAction( NudgeCatalogName::kPhoneHub); } void OnboardingNudgeController::OnNudgeHoverStateChanged(bool is_hovering) { - if (!IsInPhoneHubNudgeExperimentGroup()) { - return; - } - if (is_hovering) { PrefService* pref_service = GetPrefService(); pref_service->SetTime(kPhoneHubNudgeLastActionTime, clock_->Now()); @@ -136,10 +113,6 @@ } void OnboardingNudgeController::OnNudgeClicked() { - if (!IsInPhoneHubNudgeExperimentGroup()) { - return; - } - is_nudge_clicked_ = true; // Action can be click or hover so define `kPhoneHubNudgeLastActionTime` on @@ -151,10 +124,6 @@ } void OnboardingNudgeController::OnNudgeDismissed() { - if (!IsInPhoneHubNudgeExperimentGroup()) { - return; - } - if (is_nudge_clicked_ || is_phone_hub_icon_clicked_) { PrefService* pref_service = GetPrefService(); base::UmaHistogramTimes( @@ -225,11 +194,6 @@ return base::Contains(devices_in_pref, base::Value(device.instance_id())); } -bool OnboardingNudgeController::IsInPhoneHubNudgeExperimentGroup() { - return features::IsPhoneHubOnboardingNotifierRevampEnabled() && - features::kPhoneHubOnboardingNotifierUseNudge.Get(); -} - bool OnboardingNudgeController::ShouldShowNudge() { PrefService* pref_service = GetPrefService(); if (!pref_service->GetTime(kPhoneHubNudgeLastClickTime).is_null()) { @@ -238,9 +202,9 @@ } if (pref_service->GetInteger(kPhoneHubNudgeTotalAppearances) >= - features::kPhoneHubNudgeTotalAppearancesAllowed.Get()) { + kPhoneHubNudgeTotalAppearancesAllowed) { PA_LOG(INFO) << "Nudge has been shown " - << features::kPhoneHubNudgeTotalAppearancesAllowed.Get() + << kPhoneHubNudgeTotalAppearancesAllowed << " times. Do not show again."; return false; } @@ -250,11 +214,10 @@ } if ((clock_->Now() - pref_service->GetTime(kPhoneHubNudgeLastShownTime)) >= - features::kPhoneHubNudgeDelay.Get()) { + kPhoneHubNudgeDelay) { return true; } - PA_LOG(INFO) << "Nudge was shown less than " - << features::kPhoneHubNudgeDelay.Get() + PA_LOG(INFO) << "Nudge was shown less than " << kPhoneHubNudgeDelay << " hours ago. Not being shown this time."; return false; }
diff --git a/ash/system/phonehub/onboarding_nudge_controller.h b/ash/system/phonehub/onboarding_nudge_controller.h index e6c27ae..cbb4d7b 100644 --- a/ash/system/phonehub/onboarding_nudge_controller.h +++ b/ash/system/phonehub/onboarding_nudge_controller.h
@@ -9,6 +9,7 @@ #include "base/functional/callback.h" #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" +#include "base/time/time.h" #include "chromeos/ash/components/phonehub/feature_status_provider.h" class PrefRegistrySimple; @@ -84,6 +85,9 @@ FRIEND_TEST_ALL_PREFIXES(OnboardingNudgeControllerTest, DoNotAddToSyncedDeviceListIfAlreadyFound); + static constexpr int kPhoneHubNudgeTotalAppearancesAllowed = 3; + static constexpr base::TimeDelta kPhoneHubNudgeDelay = base::Hours(24); + bool IsDeviceStoredInPref(const multidevice::RemoteDeviceRef& device); void AddToEligibleDevicesPref(const multidevice::RemoteDeviceRef& device); @@ -95,8 +99,6 @@ void OnEligiblePhoneHubHostFound( const multidevice::RemoteDeviceRefList eligible_devices) override; - bool IsInPhoneHubNudgeExperimentGroup(); - bool ShouldShowNudge(); bool is_nudge_clicked_ = false;
diff --git a/ash/system/phonehub/phone_hub_tray.cc b/ash/system/phonehub/phone_hub_tray.cc index 873becd..07ab677 100644 --- a/ash/system/phonehub/phone_hub_tray.cc +++ b/ash/system/phonehub/phone_hub_tray.cc
@@ -147,18 +147,15 @@ UpdateTrayItemColor(is_active()); - onboarding_nudge_controller_ = - features::IsPhoneHubOnboardingNotifierRevampEnabled() - ? std::make_unique<OnboardingNudgeController>( - /*phone_hub_tray=*/this, - /*animation_stop_callback=*/ - base::BindRepeating(&PhoneHubTray::StopPulseAnimation, - weak_factory_.GetWeakPtr()), - /*start_animation_callback=*/ - base::BindRepeating(&PhoneHubTray::StartPulseAnimation, - weak_factory_.GetWeakPtr()), - base::DefaultClock::GetInstance()) - : nullptr; + onboarding_nudge_controller_ = std::make_unique<OnboardingNudgeController>( + /*phone_hub_tray=*/this, + /*animation_stop_callback=*/ + base::BindRepeating(&PhoneHubTray::StopPulseAnimation, + weak_factory_.GetWeakPtr()), + /*start_animation_callback=*/ + base::BindRepeating(&PhoneHubTray::StartPulseAnimation, + weak_factory_.GetWeakPtr()), + base::DefaultClock::GetInstance()); Shell::Get()->display_manager()->AddDisplayManagerObserver(this); @@ -172,8 +169,7 @@ if (phone_hub_manager_) { phone_hub_manager_->GetAppStreamManager()->RemoveObserver(this); } - if (phone_hub_manager_ && IsInPhoneHubNudgeExperimentGroup() && - onboarding_nudge_controller_) { + if (phone_hub_manager_ && onboarding_nudge_controller_) { phone_hub_manager_->GetFeatureStatusProvider()->RemoveObserver( onboarding_nudge_controller_.get()); } @@ -190,8 +186,7 @@ phone_hub_manager->GetAppStreamManager()->AddObserver(this); } phone_hub_manager_ = phone_hub_manager; - if (phone_hub_manager_ && IsInPhoneHubNudgeExperimentGroup() && - onboarding_nudge_controller_) { + if (phone_hub_manager_ && onboarding_nudge_controller_) { phone_hub_manager_->GetFeatureStatusProvider()->AddObserver( onboarding_nudge_controller_.get()); } @@ -287,9 +282,8 @@ bool aborted) { TrayBackgroundView::OnVisibilityAnimationFinished( should_log_visible_pod_count, aborted); - if (IsInPhoneHubNudgeExperimentGroup() && - ui_controller_->ui_state() == - PhoneHubUiController::UiState::kOnboardingWithoutPhone) { + if (ui_controller_->ui_state() == + PhoneHubUiController::UiState::kOnboardingWithoutPhone) { onboarding_nudge_controller_->ShowNudgeIfNeeded(); } } @@ -534,8 +528,7 @@ return; } - if (features::IsPhoneHubOnboardingNotifierRevampEnabled() && - AnchoredNudgeManager::Get()->IsNudgeShown( + if (AnchoredNudgeManager::Get()->IsNudgeShown( OnboardingNudgeController::kPhoneHubNudgeId)) { is_icon_clicked_when_nudge_visible_ = true; onboarding_nudge_controller_->HideNudge(); @@ -568,12 +561,7 @@ bool PhoneHubTray::IsInsideUnlockWindow() { return (base::Time::NowFromSystemTime() - last_unlocked_timestamp_) <= - features::kMultiDeviceSetupNotificationTimeLimit.Get(); -} - -bool PhoneHubTray::IsInPhoneHubNudgeExperimentGroup() { - return features::IsPhoneHubOnboardingNotifierRevampEnabled() && - features::kPhoneHubOnboardingNotifierUseNudge.Get(); + kMultiDeviceSetupNotificationTimeLimit; } BEGIN_METADATA(PhoneHubTray)
diff --git a/ash/system/phonehub/phone_hub_tray.h b/ash/system/phonehub/phone_hub_tray.h index c8fa21f7..f1603e4 100644 --- a/ash/system/phonehub/phone_hub_tray.h +++ b/ash/system/phonehub/phone_hub_tray.h
@@ -20,6 +20,7 @@ #include "base/gtest_prod_util.h" #include "base/memory/raw_ptr.h" #include "base/scoped_observation.h" +#include "base/time/time.h" #include "chromeos/ash/components/phonehub/app_stream_manager.h" #include "chromeos/ash/components/phonehub/icon_decoder.h" #include "chromeos/ash/components/phonehub/phone_hub_manager.h" @@ -133,6 +134,9 @@ FRIEND_TEST_ALL_PREFIXES(PhoneHubTrayTest, TrayPressedMetrics); FRIEND_TEST_ALL_PREFIXES(PhoneHubTrayTest, AccessibleNames); + static constexpr base::TimeDelta kMultiDeviceSetupNotificationTimeLimit = + base::Minutes(5); + // TrayBubbleView::Delegate: std::u16string GetAccessibleNameForBubble() override; bool ShouldEnableExtraKeyboardAccessibility() override; @@ -170,8 +174,6 @@ // Checks if nudge should be shown based on user login time. bool IsInsideUnlockWindow(); - bool IsInPhoneHubNudgeExperimentGroup(); - bool is_icon_clicked_when_setup_notification_visible_ = false; bool is_icon_clicked_when_nudge_visible_ = false;
diff --git a/base/BUILD.gn b/base/BUILD.gn index 5b41b3d..1bec6ae 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -1208,6 +1208,7 @@ "android/scoped_hardware_buffer_handle.h", "android/scoped_input_event.cc", "android/scoped_input_event.h", + "android/self_compaction_manager.h", "android/shared_preferences/shared_preferences_manager.cc", "android/shared_preferences/shared_preferences_manager.h", "android/statistics_recorder_android.cc",
diff --git a/base/allocator/partition_alloc_features.cc b/base/allocator/partition_alloc_features.cc index dac4af0..b2942fc 100644 --- a/base/allocator/partition_alloc_features.cc +++ b/base/allocator/partition_alloc_features.cc
@@ -487,7 +487,11 @@ #if PA_CONFIG(ENABLE_SHADOW_METADATA) BASE_FEATURE(kPartitionAllocShadowMetadata, "PartitionAllocShadowMetadata", +#if BUILDFLAG(IS_LINUX) + FEATURE_ENABLED_BY_DEFAULT); +#else FEATURE_DISABLED_BY_DEFAULT); +#endif constexpr FeatureParam<ShadowMetadataEnabledProcesses>::Option kShadowMetadataEnabledProcessesOptions[] = {
diff --git a/base/android/child_process_service.cc b/base/android/child_process_service.cc index 30663cd..2165bdd 100644 --- a/base/android/child_process_service.cc +++ b/base/android/child_process_service.cc
@@ -7,7 +7,7 @@ #include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/android/library_loader/library_loader_hooks.h" -#include "base/android/pre_freeze_background_memory_trimmer.h" +#include "base/android/self_compaction_manager.h" #include "base/debug/dump_without_crashing.h" #include "base/file_descriptor_store.h" #include "base/logging.h" @@ -84,7 +84,7 @@ } void JNI_ChildProcessService_OnSelfFreeze(JNIEnv* env) { - PreFreezeBackgroundMemoryTrimmer::OnSelfFreeze(); + SelfCompactionManager::OnSelfFreeze(); } } // namespace android
diff --git a/base/android/pre_freeze_background_memory_trimmer.cc b/base/android/pre_freeze_background_memory_trimmer.cc index 88b6a8ff..68646d3 100644 --- a/base/android/pre_freeze_background_memory_trimmer.cc +++ b/base/android/pre_freeze_background_memory_trimmer.cc
@@ -1112,4 +1112,23 @@ last_finished - last_cancelled); } +void SelfCompactionManager::OnSelfFreeze() { + PreFreezeBackgroundMemoryTrimmer::OnSelfFreeze(); +} + +void SelfCompactionManager::OnRunningCompact() { + PreFreezeBackgroundMemoryTrimmer::OnRunningCompact(); +} + +void SelfCompactionManager::MaybeCancelCompaction( + base::android::CompactCancellationReason cancellation_reason) { + PreFreezeBackgroundMemoryTrimmer::MaybeCancelCompaction(cancellation_reason); +} + +void SelfCompactionManager::SetOnStartSelfCompactionCallback( + base::RepeatingCallback<void()> callback) { + PreFreezeBackgroundMemoryTrimmer::SetOnStartSelfCompactionCallback( + std::move(callback)); +} + } // namespace base::android
diff --git a/base/android/pre_freeze_background_memory_trimmer.h b/base/android/pre_freeze_background_memory_trimmer.h index d44791b..38197480 100644 --- a/base/android/pre_freeze_background_memory_trimmer.h +++ b/base/android/pre_freeze_background_memory_trimmer.h
@@ -24,6 +24,15 @@ BASE_EXPORT BASE_DECLARE_FEATURE(kShouldFreezeSelf); BASE_EXPORT BASE_DECLARE_FEATURE(kUseRunningCompact); +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum class CompactCancellationReason { + kAppFreezer, + kPageResumed, + kTimeout, + kMaxValue = kTimeout +}; + // Starting from Android U, apps are frozen shortly after being backgrounded // (with some exceptions). This causes some background tasks for reclaiming // resources in Chrome to not be run until Chrome is foregrounded again (which @@ -36,15 +45,6 @@ // be frozen. class BASE_EXPORT PreFreezeBackgroundMemoryTrimmer { public: - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - enum class CompactCancellationReason { - kAppFreezer, - kPageResumed, - kTimeout, - kMaxValue = kTimeout - }; - static PreFreezeBackgroundMemoryTrimmer& Instance(); ~PreFreezeBackgroundMemoryTrimmer() = delete; @@ -425,6 +425,23 @@ bool supports_modern_trim_; }; +class BASE_EXPORT SelfCompactionManager { + public: + using CompactCancellationReason = CompactCancellationReason; + static void OnSelfFreeze(); + static void OnRunningCompact(); + + // If we are currently doing self compaction, cancel it. If it was running, + // record a metric with the reason for the cancellation. + static void MaybeCancelCompaction( + CompactCancellationReason cancellation_reason); + + // The callback runs in the thread pool. The caller cannot make any thread + // safety assumptions for the callback execution (e.g. it could run + // concurrently with the thread that registered it). + static void SetOnStartSelfCompactionCallback(base::RepeatingClosure callback); +}; + } // namespace base::android #endif // BASE_ANDROID_PRE_FREEZE_BACKGROUND_MEMORY_TRIMMER_H_
diff --git a/base/android/pre_freeze_background_memory_trimmer_unittest.cc b/base/android/pre_freeze_background_memory_trimmer_unittest.cc index 5bf5cdd..cc1e0c4 100644 --- a/base/android/pre_freeze_background_memory_trimmer_unittest.cc +++ b/base/android/pre_freeze_background_memory_trimmer_unittest.cc
@@ -882,8 +882,7 @@ EXPECT_TRUE(ShouldContinueCompaction(triggered_at)); PreFreezeBackgroundMemoryTrimmer::MaybeCancelCompaction( - PreFreezeBackgroundMemoryTrimmer::CompactCancellationReason:: - kPageResumed); + SelfCompactionManager::CompactCancellationReason::kPageResumed); EXPECT_FALSE(ShouldContinueCompaction(triggered_at)); } @@ -907,8 +906,7 @@ // We should not record the metric here, because we are not currently // running. PreFreezeBackgroundMemoryTrimmer::MaybeCancelCompaction( - PreFreezeBackgroundMemoryTrimmer::CompactCancellationReason:: - kPageResumed); + SelfCompactionManager::CompactCancellationReason::kPageResumed); // This metric is used for both self compaction and running compaction, with // the same prefix for both. @@ -940,8 +938,7 @@ EXPECT_EQ(task_environment_.GetPendingMainThreadTaskCount(), 1u); PreFreezeBackgroundMemoryTrimmer::MaybeCancelCompaction( - PreFreezeBackgroundMemoryTrimmer::CompactCancellationReason:: - kPageResumed); + SelfCompactionManager::CompactCancellationReason::kPageResumed); task_environment_.FastForwardBy( task_environment_.NextMainThreadPendingTaskDelay()); @@ -962,8 +959,7 @@ // Still only expect it to be recorded once, because we were not running the // second time we tried to cancel. PreFreezeBackgroundMemoryTrimmer::MaybeCancelCompaction( - PreFreezeBackgroundMemoryTrimmer::CompactCancellationReason:: - kPageResumed); + SelfCompactionManager::CompactCancellationReason::kPageResumed); histograms_.ExpectTotalCount( "Memory.RunningOrSelfCompact.Renderer.Cancellation.Reason", 1); @@ -1181,8 +1177,7 @@ task_environment_.FastForwardBy(base::Seconds(1)); PreFreezeBackgroundMemoryTrimmer::MaybeCancelCompaction( - PreFreezeBackgroundMemoryTrimmer::CompactCancellationReason:: - kPageResumed); + SelfCompactionManager::CompactCancellationReason::kPageResumed); EXPECT_EQ(task_environment_.GetPendingMainThreadTaskCount(), 1u); task_environment_.FastForwardBy(
diff --git a/base/android/self_compaction_manager.h b/base/android/self_compaction_manager.h new file mode 100644 index 0000000..4c289081 --- /dev/null +++ b/base/android/self_compaction_manager.h
@@ -0,0 +1,10 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_ANDROID_SELF_COMPACTION_MANAGER_H_ +#define BASE_ANDROID_SELF_COMPACTION_MANAGER_H_ + +#include "base/android/pre_freeze_background_memory_trimmer.h" + +#endif // BASE_ANDROID_SELF_COMPACTION_MANAGER_H_
diff --git a/base/third_party/xdg_user_dirs/README.chromium b/base/third_party/xdg_user_dirs/README.chromium index 6edfaa4..0d58a77 100644 --- a/base/third_party/xdg_user_dirs/README.chromium +++ b/base/third_party/xdg_user_dirs/README.chromium
@@ -1,9 +1,11 @@ Name: xdg-user-dirs URL: http://www.freedesktop.org/wiki/Software/xdg-user-dirs +Version: N/A Revision: 2f28f353ec3cf9288da70bab3ca963f2144808f0 Date: 2009-02-26 License: MIT License File: LICENSE +Security Critical: yes Shipped: yes This directory include xdg-user-dir-lookup.c renamed as xdg_user_dir_lookup.cc
diff --git a/build/config/mac/BUILD.gn b/build/config/mac/BUILD.gn index 66ca06b..0d5276c 100644 --- a/build/config/mac/BUILD.gn +++ b/build/config/mac/BUILD.gn
@@ -37,6 +37,14 @@ ldflags = common_mac_flags + # ld64 defaults to fixup chains on macOS 12+ when targeting arm64 and on + # macOS 13+ when targeting x86_64. ld.lld defaults to it on macOS 13+. + # It's probably safe to enable it on macOS even on intel, but for now + # only explicitly opt in on arm64. + if (current_cpu == "arm64") { + ldflags += [ "-Wl,-fixup_chains" ] + } + if (save_unstripped_output) { ldflags += [ "-Wcrl,unstripped," + rebase_path(root_out_dir) ] }
diff --git a/build/config/siso/android.star b/build/config/siso/android.star index 1eac27ac..45a906a 100644 --- a/build/config/siso/android.star +++ b/build/config/siso/android.star
@@ -159,7 +159,9 @@ "remote": remote_run_static_analysis, "platform_ref": "large", "canonicalize_dir": True, - "timeout": "2m", + # obj/chrome/android/chrome_java__errorprone.stamp step takes too + # long. + "timeout": "6m", }, { "name": "android/compile_kt", @@ -243,6 +245,16 @@ "timeout": "10m", }, { + "name": "android/proguard/local", + "command_prefix": "python3 ../../build/android/gyp/proguard.py", + "action_outs": [ + # http://crbug.com/396004680#comment15: It slows down CQ build. + # It's better to run it locally. + "./obj/chrome/test/android_browsertests__apk/android_browsertests__apk.r8dex.jar", + ], + "remote": False, + }, + { "name": "android/proguard", "command_prefix": "python3 ../../build/android/gyp/proguard.py", "handler": "android_proguard",
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc index dd79298..0794121 100644 --- a/cc/layers/picture_layer_impl.cc +++ b/cc/layers/picture_layer_impl.cc
@@ -1083,16 +1083,17 @@ // The transform node has the realized scroll offset and snap amount, // and should be used for rendering. const auto* scroll_node = scroll_tree.FindNodeFromElementId(element_id); - CHECK(scroll_node); - if (const auto* transform = - transform_tree.Node(scroll_node->transform_id)) { + const auto* transform = + scroll_node ? transform_tree.Node(scroll_node->transform_id) + : nullptr; + if (transform) { map[element_id] = gfx::PointAtOffsetFromOrigin( -transform->to_parent.To2dTranslation()); } else { - // Use the current scroll offset if the scroll node doesn't have a - // transform node. It doesn't matter because such a scroller is - // invisible. TODO(crbug.com/419921722): Investigate the case and - // add a test case. + // Use the current scroll offset if the scroll node doesn't exist or + // doesn't have a transform node. It doesn't matter because such a + // scroller is invisible. TODO(crbug.com/419921722): Investigate the + // case and add a test case. map[element_id] = scroll_tree.current_scroll_offset(element_id); } }
diff --git a/chrome/VERSION b/chrome/VERSION index 9d6e947..24ce670 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=139 MINOR=0 -BUILD=7205 +BUILD=7206 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 53e1d8a..9d2662b 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -2683,11 +2683,13 @@ } # Options shared by all script test targets that call `run_wpt_tests.py`. + # TODO(crbug.com/419890016): Consolidate the common options. _common_web_test_options = [ "--no-show-results", "--zero-tests-executed-ok", "--build-directory", "@WrappedPath(.)", + "--verbose", ] if (is_debug) { _common_web_test_options += [ "--debug" ]
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index f0bffc5a..c2f3b36 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -337,7 +337,6 @@ "java/src/org/chromium/chrome/browser/compositor/overlays/strip/TabGroupContextMenuCoordinator.java", "java/src/org/chromium/chrome/browser/compositor/overlays/strip/TabLoadTracker.java", "java/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripIphController.java", - "java/src/org/chromium/chrome/browser/compositor/overlays/strip/TooltipManager.java", "java/src/org/chromium/chrome/browser/compositor/overlays/strip/reorder/ExternalViewDragDropReorderStrategy.java", "java/src/org/chromium/chrome/browser/compositor/overlays/strip/reorder/GroupReorderStrategy.java", "java/src/org/chromium/chrome/browser/compositor/overlays/strip/reorder/ReorderDelegate.java",
diff --git a/chrome/android/features/tab_ui/BUILD.gn b/chrome/android/features/tab_ui/BUILD.gn index 245c04e..0237bb0 100644 --- a/chrome/android/features/tab_ui/BUILD.gn +++ b/chrome/android/features/tab_ui/BUILD.gn
@@ -67,7 +67,6 @@ "java/res/drawable/tab_strip_item_notification_bubble.xml", "java/res/drawable/tab_strip_selected_ring.xml", "java/res/drawable/tab_strip_selected_ring_incognito.xml", - "java/res/drawable/tab_strip_tooltip_background.xml", "java/res/drawable/tablet_tab_switcher_empty_state_illustration.xml", "java/res/drawable/ungroup_bar_background.xml", "java/res/layout/archived_tabs_auto_delete_promo.xml", @@ -108,7 +107,6 @@ "java/res/layout/tab_list_editor_toolbar.xml", "java/res/layout/tab_list_recycler_view_layout.xml", "java/res/layout/tab_strip_item.xml", - "java/res/layout/tab_strip_tooltip_holder.xml", "java/res/layout/toolbar_back_button.xml", "java/res/layout/toolbar_new_tab_and_menu_button.xml", "java/res/values-night/colors.xml",
diff --git a/chrome/android/features/tab_ui/java/res/drawable/tab_strip_tooltip_background.xml b/chrome/android/features/tab_ui/java/res/drawable/tab_strip_tooltip_background.xml deleted file mode 100644 index 4dfc64e..0000000 --- a/chrome/android/features/tab_ui/java/res/drawable/tab_strip_tooltip_background.xml +++ /dev/null
@@ -1,12 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -Copyright 2025 The Chromium Authors -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<shape - xmlns:android="http://schemas.android.com/apk/res/android"> - <corners android:radius="@dimen/tab_strip_tooltip_corner_radius"/> - <solid android:color="@macro/default_bg_color_inverse"/> -</shape>
diff --git a/chrome/android/features/tab_ui/java/res/layout/tab_strip_tooltip_holder.xml b/chrome/android/features/tab_ui/java/res/layout/tab_strip_tooltip_holder.xml deleted file mode 100644 index 850479bc..0000000 --- a/chrome/android/features/tab_ui/java/res/layout/tab_strip_tooltip_holder.xml +++ /dev/null
@@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -Copyright 2025 The Chromium Authors -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<FrameLayout - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" - android:id="@+id/tab_strip_tooltip_holder" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:visibility="gone" > - - <TextView - android:id="@+id/tooltip_label" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_margin="@dimen/tab_strip_tooltip_margin" - android:paddingHorizontal="@dimen/tab_strip_tooltip_label_horizontal_padding" - android:paddingVertical="@dimen/tab_strip_tooltip_label_vertical_padding" - android:textAppearance="@style/TextAppearance.TextSmall.Primary.OnAccent1" - android:background="@drawable/tab_strip_tooltip_background" /> -</FrameLayout>
diff --git a/chrome/android/features/tab_ui/java/res/values/dimens.xml b/chrome/android/features/tab_ui/java/res/values/dimens.xml index b9fd2588..9738c7c 100644 --- a/chrome/android/features/tab_ui/java/res/values/dimens.xml +++ b/chrome/android/features/tab_ui/java/res/values/dimens.xml
@@ -139,11 +139,6 @@ <dimen name="message_card_close_button_size">24dp</dimen> <dimen name="message_card_description_vertical_margin">14dp</dimen> - <!-- Dimens for tab strip tooltip. --> - <dimen name="tab_strip_tooltip_margin">10dp</dimen> - <dimen name="tab_strip_tooltip_label_horizontal_padding">8dp</dimen> - <dimen name="tab_strip_tooltip_label_vertical_padding">4dp</dimen> - <dimen name="tab_strip_tooltip_corner_radius">4dp</dimen> <dimen name="tab_strip_shared_image_tiles_size">26dp</dimen> <!-- Dimens for tab group list bottom sheet. -->
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoTabSwitcherPane.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoTabSwitcherPane.java index 1db0b7b..6f2c6c80 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoTabSwitcherPane.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoTabSwitcherPane.java
@@ -39,7 +39,6 @@ import org.chromium.chrome.browser.ui.edge_to_edge.EdgeToEdgeController; import org.chromium.chrome.browser.user_education.UserEducationHelper; import org.chromium.chrome.tab_ui.R; -import org.chromium.components.omnibox.OmniboxFeatures; import org.chromium.components.sensitive_content.SensitiveContentFeatures; import java.lang.annotation.Retention; @@ -101,9 +100,7 @@ setNewTabButtonEnabledState(/* enabled= */ true); - if (OmniboxFeatures.sAndroidHubSearch.isEnabled()) { - mHubSearchEnabledStateSupplier.set(true); - } + mHubSearchEnabledStateSupplier.set(true); } @Override @@ -288,7 +285,7 @@ coordinator.resetWithListOfTabs(null); cancelWaitForTabStateInitializedTimer(); - if (OmniboxFeatures.sAndroidHubSearch.isEnabled() && incognitoReauthShowing) { + if (incognitoReauthShowing) { mHubSearchEnabledStateSupplier.set(false); } } else {
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabArchiveSettingsFragment.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabArchiveSettingsFragment.java index 541fb05..e515f67 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabArchiveSettingsFragment.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabArchiveSettingsFragment.java
@@ -100,7 +100,8 @@ enableArchiveDuplicateTabsSwitch.setTitle( getString(R.string.archive_settings_archive_duplicate_tabs_title)); enableArchiveDuplicateTabsSwitch.setEnabled( - ChromeFeatureList.sAndroidTabDeclutterArchiveDuplicateTabs.isEnabled()); + ChromeFeatureList.sAndroidTabDeclutterArchiveDuplicateTabs.isEnabled() + && mArchiveSettings.getArchiveEnabled()); enableArchiveDuplicateTabsSwitch.setChecked( mArchiveSettings.isArchiveDuplicateTabsEnabled()); enableArchiveDuplicateTabsSwitch.setOnPreferenceChangeListener(
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabArchiveSettingsFragmentUnitTest.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabArchiveSettingsFragmentUnitTest.java index 78594f8..2f10ed3 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabArchiveSettingsFragmentUnitTest.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabArchiveSettingsFragmentUnitTest.java
@@ -22,6 +22,8 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; +import org.chromium.base.task.PostTask; +import org.chromium.base.task.TaskTraits; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.HistogramWatcher; import org.chromium.chrome.browser.preferences.ChromeSharedPreferences; @@ -147,8 +149,21 @@ HistogramWatcher.newSingleRecordWatcher( "Tabs.ArchiveSettings.ArchiveDuplicateTabsEnabled", true); enableArchiveDuplicateTabs.onClick(); + histogramWatcher.assertExpected(); assertTrue(enableArchiveDuplicateTabs.isEnabled()); assertTrue(mArchiveSettings.isArchiveDuplicateTabsEnabled()); + + // Click "Never" radio button to disable archive. The archive duplicate tabs + // preference should be disabled. + radioButton = archiveTimeDeltaPreference.getRadioButtonForTesting(0); + radioButton.onClick(radioButton); + // PostTask to ensure the UI is updated after the preference change. + PostTask.postTask( + TaskTraits.UI_DEFAULT, + () -> { + assertFalse(enableArchiveDuplicateTabs.isEnabled()); + assertFalse(enableArchiveDuplicateTabs.isChecked()); + }); } @Test
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneBase.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneBase.java index fa50fc8..9e2ef9b 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneBase.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneBase.java
@@ -64,7 +64,6 @@ import org.chromium.components.browser_ui.styles.ChromeColors; import org.chromium.components.browser_ui.widget.MenuOrKeyboardActionController.MenuOrKeyboardActionHandler; import org.chromium.components.feature_engagement.Tracker; -import org.chromium.components.omnibox.OmniboxFeatures; import org.chromium.ui.base.DeviceFormFactor; import java.util.List; @@ -142,16 +141,14 @@ @Override public void beforeStart() { mIsAnimatingSupplier.set(true); - if (OmniboxFeatures.sAndroidHubSearch.isEnabled() - && mPaneHubController != null) { + if (mPaneHubController != null) { mPaneHubController.setSearchBoxBackgroundProperties(/* shouldShow= */ true); } } @Override public void afterEnd() { - if (OmniboxFeatures.sAndroidHubSearch.isEnabled() - && mPaneHubController != null) { + if (mPaneHubController != null) { mPaneHubController.setSearchBoxBackgroundProperties( /* shouldShow= */ false); }
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilitiesUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilitiesUnitTest.java index fa55ac48..bdbf07a 100644 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilitiesUnitTest.java +++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilitiesUnitTest.java
@@ -23,7 +23,9 @@ import org.chromium.base.test.util.Features.EnableFeatures; import org.chromium.chrome.browser.device.DeviceClassManager; import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.util.ChromeAccessibilityUtil; +import org.chromium.ui.util.XrUtils; /** Unit Tests for {@link TabUiFeatureUtilities}. */ @RunWith(BaseRobolectricTestRunner.class) @@ -80,4 +82,19 @@ assertFalse(TabUiFeatureUtilities.shouldUseListMode()); } + + @Test + @CommandLineFlags.Add({ChromeSwitches.DISABLE_FULLSCREEN}) + public void testDisableFullScreen_XrDeviceWithFlag_isTrue() { + XrUtils.setXrDeviceForTesting(true); + + assertFalse(DeviceClassManager.enableFullscreen()); + } + + @Test + public void testDisableFullScreen_XrDeviceWithoutFlag_isTrue() { + XrUtils.setXrDeviceForTesting(true); + + assertFalse(DeviceClassManager.enableFullscreen()); + } }
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/HasContentListener.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/HasContentListener.java index d317622..cd6d682 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/HasContentListener.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/HasContentListener.java
@@ -4,7 +4,10 @@ package org.chromium.chrome.browser.feed; +import org.chromium.build.annotations.NullMarked; + /** Interface to listen to the hasContent events from FeedSurfaceMediator. */ +@NullMarked public interface HasContentListener { /** Called when the has content state changes. */ void hasContentChanged(@StreamKind int kind, boolean hasContent);
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/shared/ui/MaterialSpinnerView.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/shared/ui/MaterialSpinnerView.java index be9d1b2..596e28a 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/shared/ui/MaterialSpinnerView.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/shared/ui/MaterialSpinnerView.java
@@ -8,14 +8,16 @@ import android.util.AttributeSet; import android.view.View; -import androidx.annotation.Nullable; import androidx.appcompat.widget.AppCompatImageView; import androidx.swiperefreshlayout.widget.CircularProgressDrawable; import org.chromium.base.TraceEvent; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import org.chromium.components.browser_ui.styles.SemanticColorUtils; /** View that shows a Material themed spinner. */ +@NullMarked public class MaterialSpinnerView extends AppCompatImageView { private final CircularProgressDrawable mSpinner;
diff --git a/chrome/android/java/res_app/layout/main.xml b/chrome/android/java/res_app/layout/main.xml index 625f8b0..629c385 100644 --- a/chrome/android/java/res_app/layout/main.xml +++ b/chrome/android/java/res_app/layout/main.xml
@@ -159,13 +159,6 @@ android:inflatedId="@+id/tab_hover_card_holder" android:layout="@layout/tab_hover_card_holder" /> - <ViewStub - android:id="@+id/tab_strip_tooltip_holder_stub" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:inflatedId="@+id/tab_strip_tooltip_holder" - android:layout="@layout/tab_strip_tooltip_holder" /> - <org.chromium.components.messages.MessageContainer android:id="@+id/message_container" android:layout_width="match_parent"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index d8ac9f6b..9a7c23c5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -897,7 +897,6 @@ CompositorViewHolder compositorViewHolder = getCompositorViewHolderSupplier().get(); ViewStub tabHoverCardViewStub = findViewById(R.id.tab_hover_card_holder_stub); - ViewStub tabStripTooltipViewStub = findViewById(R.id.tab_strip_tooltip_holder_stub); View toolbarContainerView = findViewById(R.id.toolbar_container); mDragDropDelegate = new DragAndDropDelegateImpl(); mDragDropDelegate.setDragAndDropBrowserDelegate( @@ -927,7 +926,6 @@ mDragDropDelegate, toolbarContainerView, tabHoverCardViewStub, - tabStripTooltipViewStub, getWindowAndroid(), getToolbarManager(), mRootUiCoordinator.getDesktopWindowStateManager(),
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java index 78a8cbd0..41755a5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
@@ -49,6 +49,7 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.gsa.GSAUtils; import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteCoordinator; +import org.chromium.chrome.browser.pdf.PdfUtils; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.ProfileManager; import org.chromium.chrome.browser.renderer_host.ChromeNavigationUiData; @@ -1015,7 +1016,8 @@ String lowerCaseUrl = url.toLowerCase(Locale.US); if (ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL.equals(lowerCaseUrl) || ContentUrlConstants.ABOUT_BLANK_URL.equals(lowerCaseUrl) - || UrlConstants.CHROME_DINO_URL.equals(lowerCaseUrl)) { + || UrlConstants.CHROME_DINO_URL.equals(lowerCaseUrl) + || lowerCaseUrl.startsWith(UrlConstants.PDF_URL)) { return false; } @@ -1157,6 +1159,12 @@ if (isGoogleChromeScheme(url)) { url = ExternalNavigationHandler.getUrlFromSelfSchemeUrl(GOOGLECHROME_SCHEME, url); } + // To display a PDF in Chrome, the content URI must be encoded. + String encodedPdfUrl = + PdfUtils.getEncodedContentUri(url, ContextUtils.getApplicationContext()); + if (!TextUtils.isEmpty(encodedPdfUrl)) { + url = encodedPdfUrl; + } return url; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatService.java b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatService.java index a43a79e..ed81a78 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatService.java
@@ -71,7 +71,7 @@ } @Override - public IBinder onBind(Intent intent) { + public @Nullable IBinder onBind(Intent intent) { return mImpl.onBind(intent); } @@ -117,6 +117,6 @@ return mService.superOnUnbind(intent); } - public abstract IBinder onBind(Intent intent); + public abstract @Nullable IBinder onBind(Intent intent); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java index 621558f..7a43f69 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java
@@ -73,7 +73,6 @@ * tab drag and drop. * @param toolbarContainerView View passed to StripLayoutHelper to support tab drag and drop. * @param tabHoverCardViewStub The ViewStub representing the strip tab hover card. - * @param tabStripTooltipViewStub The ViewStub representing the tooltip for NTB or MSB. * @param toolbarManager The ToolbarManager instance. * @param desktopWindowStateManager The DesktopWindowStateManager for the app header. * @param actionConfirmationManager The {@link ActionConfirmationManager} for group actions. @@ -96,7 +95,6 @@ DragAndDropDelegate dragAndDropDelegate, View toolbarContainerView, @NonNull ViewStub tabHoverCardViewStub, - @NonNull ViewStub tabStripTooltipViewStub, @NonNull WindowAndroid windowAndroid, @NonNull ToolbarManager toolbarManager, @Nullable DesktopWindowStateManager desktopWindowStateManager, @@ -125,7 +123,6 @@ dragAndDropDelegate, toolbarContainerView, tabHoverCardViewStub, - tabStripTooltipViewStub, tabContentManagerSupplier, browserControlsStateProvider, windowAndroid,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/components/CompositorButton.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/components/CompositorButton.java index 4b4b41c..1938f0d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/components/CompositorButton.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/components/CompositorButton.java
@@ -12,7 +12,6 @@ import androidx.annotation.Nullable; import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutView; -import org.chromium.chrome.browser.compositor.overlays.strip.TooltipManager; import org.chromium.ui.util.MotionEventUtils; import java.lang.annotation.Retention; @@ -47,6 +46,10 @@ int TAB_CLOSE = 2; } + public interface TooltipHandler { + void setTooltipText(String text); + } + protected int mResource; protected int mBackgroundResource; @@ -60,7 +63,7 @@ private boolean mIsHovered; private String mAccessibilityDescriptionIncognito = ""; - @Nullable private TooltipManager mTooltipManager; + private final TooltipHandler mTooltipHandler; // @StripLayoutView the button was embedded in. Null if it's not a child view. @Nullable private final StripLayoutView mParentView; @@ -83,6 +86,7 @@ StripLayoutView parentView, float width, float height, + TooltipHandler tooltipHandler, StripLayoutViewOnClickHandler clickHandler, StripLayoutViewOnKeyboardFocusHandler keyboardFocusHandler, float clickSlopDp) { @@ -93,6 +97,7 @@ mOpacity = 1.f; mIsPressed = false; mParentView = parentView; + mTooltipHandler = tooltipHandler; setVisible(true); mClickSlop = clickSlopDp; @@ -282,13 +287,13 @@ } /** - * Set whether button is hovered on and notify the tooltip manager if the hover state changed. + * Set whether button is hovered on and notify the tooltip handler if the hover state changed. * * @param isHovered Whether the button is hovered on. */ public void setHovered(boolean isHovered) { - if (mTooltipManager != null && mIsHovered != isHovered) { - mTooltipManager.setHovered(this, isHovered); + if (mTooltipHandler != null && mIsHovered != isHovered) { + mTooltipHandler.setTooltipText(isHovered ? getAccessibilityDescription() : ""); } mIsHovered = isHovered; } @@ -330,13 +335,4 @@ public boolean getShouldApplyHoverBackground() { return isHovered() || isPressedFromMouse(); } - - /** - * @param tooltipManager The {@link - * org.chromium.chrome.browser.compositor.overlays.strip.TooltipManager} responsible for the - * tooltip associated with this button. - */ - public void setTooltipManager(TooltipManager tooltipManager) { - mTooltipManager = tooltipManager; - } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/components/TintedCompositorButton.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/components/TintedCompositorButton.java index 5b600d86..0cab01ef 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/components/TintedCompositorButton.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/components/TintedCompositorButton.java
@@ -38,6 +38,7 @@ StripLayoutView parentView, float width, float height, + TooltipHandler tooltipHandler, StripLayoutViewOnClickHandler clickHandler, StripLayoutViewOnKeyboardFocusHandler keyboardFocusHandler, @DrawableRes int resource, @@ -48,6 +49,7 @@ parentView, width, height, + tooltipHandler, clickHandler, keyboardFocusHandler, clickSlopDp);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/NewBackgroundTabAnimationHostView.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/NewBackgroundTabAnimationHostView.java index d3833dc..e033c64a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/NewBackgroundTabAnimationHostView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/NewBackgroundTabAnimationHostView.java
@@ -13,7 +13,6 @@ import android.graphics.Rect; import android.util.AttributeSet; import android.view.View; -import android.view.animation.Interpolator; import android.widget.FrameLayout; import android.widget.ImageView; @@ -21,8 +20,6 @@ import androidx.annotation.IntDef; import org.chromium.chrome.R; -import org.chromium.chrome.browser.flags.ChromeFeatureList; -import org.chromium.chrome.browser.hub.NewTabAnimationUtils.NewTabAnim; import org.chromium.chrome.browser.theme.ThemeUtils; import org.chromium.chrome.browser.toolbar.top.ToggleTabStackButton; import org.chromium.chrome.browser.ui.theme.BrandedColorScheme; @@ -92,31 +89,17 @@ target[0] -= Math.round(mLinkIcon.getWidth() / 2f); target[1] -= Math.round(mLinkIcon.getHeight() / 2f); - // TODO(crbug.com/419065710): Clean up versions. - @NewTabAnim int version = ChromeFeatureList.sShowNewTabAnimationsVersion.getValue(); - AnimatorSet transitionAnimator = getTransitionAnimator(); - ObjectAnimator pathAnimator = - getPathArcAnimator(originX, originY, target[0], target[1], version); + ObjectAnimator pathAnimator = getPathArcAnimator(originX, originY, target[0], target[1]); AnimatorSet backgroundAnimation = new AnimatorSet(); AnimatorSet fakeTabSwitcherAnimator; if (mAnimationType == AnimationType.DEFAULT) { fakeTabSwitcherAnimator = mFakeTabSwitcherButton.getShrinkAnimator(/* incrementCount= */ true); + fakeTabSwitcherAnimator.setStartDelay(SHRINK_DELAY_DURATION_MS); + transitionAnimator.setStartDelay(SHRINK_DELAY_DURATION_MS); - if (version == NewTabAnim.BOUNCE - || version == NewTabAnim.BOUNCE_DECELERATE_WITH_DELAY) { - fakeTabSwitcherAnimator.setInterpolator( - Interpolators.NEW_BACKGROUND_TAB_ANIMATION_BOUNCE_INTERPOLATOR); - fakeTabSwitcherAnimator.setStartDelay(SHRINK_DELAY_DURATION_MS); - transitionAnimator.setStartDelay(SHRINK_DELAY_DURATION_MS); - } else if (version == NewTabAnim.BOUNCE_DECELERATE) { - fakeTabSwitcherAnimator.setInterpolator( - Interpolators.NEW_BACKGROUND_TAB_ANIMATION_BOUNCE_INTERPOLATOR); - } else { - fakeTabSwitcherAnimator.setInterpolator(Interpolators.STANDARD_INTERPOLATOR); - } backgroundAnimation .play(transitionAnimator) .with(fakeTabSwitcherAnimator) @@ -208,26 +191,16 @@ * @param originY y-coordinate for the start point. * @param finalX x-coordinate for the end point. * @param finalY y-coordinate for the end point. - * @param version The {@link NewTabAnim} animation version. */ private ObjectAnimator getPathArcAnimator( - float originX, float originY, float finalX, float finalY, @NewTabAnim int version) { + float originX, float originY, float finalX, float finalY) { boolean isClockwise = mIsTopToolbar ? (originX >= finalX) : (originX <= finalX); ObjectAnimator animator = ViewCurvedMotionAnimatorFactory.build( mLinkIcon, originX, originY, finalX, finalY, isClockwise); animator.setDuration(PATH_ARC_DURATION_MS); - - Interpolator pathInterpolator = - switch (version) { - case NewTabAnim.M137 -> Interpolators - .NEW_BACKGROUND_TAB_ANIMATION_PATH_INTERPOLATOR; - case NewTabAnim.BOUNCE -> Interpolators - .NEW_BACKGROUND_TAB_ANIMATION_SECOND_PATH_INTERPOLATOR; - default -> Interpolators.EMPHASIZED_DECELERATE; - }; - animator.setInterpolator(pathInterpolator); + animator.setInterpolator(Interpolators.EMPHASIZED_DECELERATE); animator.addListener( new AnimatorListenerAdapter() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/NewBackgroundTabFakeTabSwitcherButton.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/NewBackgroundTabFakeTabSwitcherButton.java index 02b98f4..787be518 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/NewBackgroundTabFakeTabSwitcherButton.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/NewBackgroundTabFakeTabSwitcherButton.java
@@ -132,6 +132,7 @@ AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether(scaleXAnimator, scaleYAnimator); animatorSet.setDuration(SHRINK_DURATION_MS); + animatorSet.setInterpolator(Interpolators.NEW_BACKGROUND_TAB_ANIMATION_BOUNCE_INTERPOLATOR); animatorSet.addListener( new AnimatorListenerAdapter() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java index b01b1e0..42f1fd9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java
@@ -619,6 +619,9 @@ null, NEW_TAB_BUTTON_BACKGROUND_WIDTH_DP, NEW_TAB_BUTTON_BACKGROUND_HEIGHT_DP, + (text) -> { + mToolbarContainerView.setTooltipText(text); + }, /* clickHandler= */ this, /* keyboardFocusHandler= */ this, R.drawable.ic_new_tab_button,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java index 4ffedecb..3477b1c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java
@@ -21,7 +21,6 @@ import android.view.View.OnDragListener; import android.view.ViewStub; import android.view.animation.Interpolator; -import android.widget.FrameLayout; import androidx.annotation.ColorInt; import androidx.annotation.DrawableRes; @@ -226,8 +225,6 @@ private final TabSwitcherLayoutObserver mTabSwitcherLayoutObserver; private final View mToolbarControlContainer; private final ViewStub mTabHoverCardViewStub; - @Nullable private TooltipManager mTooltipManager; - private final ViewStub mTabStripTooltipViewStub; private float mModelSelectorWidth; private float mLastVisibleViewportOffsetY; @@ -340,11 +337,6 @@ mTabHoverCardViewStub.inflate(); } - // Inflate the tab strip tooltip ViewStub if not already inflated. - if (mTabStripTooltipViewStub.getParent() != null) { - mTabStripTooltipViewStub.inflate(); - } - getActiveStripLayoutHelper().onHoverEnter(x, y); } @@ -414,7 +406,6 @@ * drop. * @param toolbarContainerView View passed to TabDragSource for drag and drop. * @param tabHoverCardViewStub The ViewStub representing the strip tab hover card. - * @param tabStripTooltipViewStub The ViewStub representing the tooltip for tab strip buttons. * @param tabContentManagerSupplier Supplier of the TabContentManager instance. * @param browserControlsStateProvider BrowserControlsStateProvider for drag drop. * @param toolbarManager The ToolbarManager instance. @@ -436,7 +427,6 @@ DragAndDropDelegate dragDropDelegate, View toolbarContainerView, @NonNull ViewStub tabHoverCardViewStub, - @NonNull ViewStub tabStripTooltipViewStub, ObservableSupplier<TabContentManager> tabContentManagerSupplier, @NonNull BrowserControlsStateProvider browserControlsStateProvider, @NonNull WindowAndroid windowAndroid, @@ -497,7 +487,6 @@ mStripEndPadding = res.getDimension(R.dimen.button_end_padding) / mDensity; mTabHoverCardViewStub = tabHoverCardViewStub; - mTabStripTooltipViewStub = tabStripTooltipViewStub; if (MultiWindowUtils.isMultiInstanceApi31Enabled()) { mTabDragSource = @@ -563,16 +552,6 @@ mIncognitoHelper.setTabHoverCardView(hoverCardView); }); - tabStripTooltipViewStub.setOnInflateListener( - (viewStub, view) -> { - mTooltipManager = new TooltipManager((FrameLayout) view, () -> mTopPadding); - mNormalHelper.getNewTabButton().setTooltipManager(mTooltipManager); - mIncognitoHelper.getNewTabButton().setTooltipManager(mTooltipManager); - if (mModelSelectorButton != null) { - mModelSelectorButton.setTooltipManager(mTooltipManager); - } - }); - if (tabModelStartupInfoSupplier != null) { if (tabModelStartupInfoSupplier.hasValue()) { setTabModelStartupInfo(tabModelStartupInfoSupplier.get()); @@ -621,6 +600,9 @@ null, MODEL_SELECTOR_BUTTON_BACKGROUND_WIDTH_DP, MODEL_SELECTOR_BUTTON_BACKGROUND_HEIGHT_DP, + (tooltipText) -> { + mToolbarControlContainer.setTooltipText(tooltipText); + }, selectorClickHandler, keyboardFocusHandler, R.drawable.ic_incognito, @@ -692,9 +674,6 @@ mModelSelectorButton.setAccessibilityDescription( context.getString(R.string.accessibility_tabstrip_btn_incognito_toggle_standard), context.getString(R.string.accessibility_tabstrip_btn_incognito_toggle_incognito)); - if (mTooltipManager != null) { - mModelSelectorButton.setTooltipManager(mTooltipManager); - } } /** Cleans up internal state. An instance should not be used after this method is called. */ @@ -1623,14 +1602,6 @@ return mTabHoverCardViewStub; } - ViewStub getTooltipViewStubForTesting() { - return mTabStripTooltipViewStub; - } - - TooltipManager getTooltipManagerForTesting() { - return mTooltipManager; - } - public TabDragSource getTabDragSourceForTesting() { return mTabDragSource; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutTab.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutTab.java index 5e57c39..f820733 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutTab.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutTab.java
@@ -204,6 +204,7 @@ this, /* width= */ 0, /* height= */ 0, + /* tooltipHandler= */ null, clickHandler, keyboardFocusHandler, R.drawable.btn_tab_close_normal,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/TooltipManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/TooltipManager.java deleted file mode 100644 index 97ef56e..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/TooltipManager.java +++ /dev/null
@@ -1,111 +0,0 @@ -// Copyright 2025 The Chromium Authors -// 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.compositor.overlays.strip; - -import android.annotation.SuppressLint; -import android.os.Handler; -import android.os.Message; -import android.view.View; -import android.widget.FrameLayout; -import android.widget.TextView; - -import org.chromium.base.MathUtils; -import org.chromium.base.supplier.Supplier; -import org.chromium.chrome.R; -import org.chromium.chrome.browser.compositor.layouts.components.CompositorButton; - -/** Manages the tooltip that is shown when a CompositorButton is hovered. */ -public class TooltipManager { - private final TooltipEventHandler mHandler = new TooltipEventHandler(); - private CompositorButton mCurrentButton; - private final FrameLayout mTooltipView; - private final Supplier<Float> mTopPaddingSupplier; // in dp units - - private static final int MESSAGE_SHOW_TOOLTIP = 1; - private static final int TOOLTIP_DELAY_MS = 1000; - - public TooltipManager(FrameLayout tooltipView, Supplier<Float> topPaddingSupplierDp) { - mTooltipView = tooltipView; - mTopPaddingSupplier = topPaddingSupplierDp; - } - - public void setHovered(CompositorButton button, boolean isHovered) { - if (isHovered && mCurrentButton != button) { - hideImmediately(); - showWithDelayFor(button); - } else if (!isHovered && mCurrentButton == button) { - hideImmediately(); - } - } - - private void clearPendingMessages() { - mHandler.removeMessages(MESSAGE_SHOW_TOOLTIP); - } - - private void showWithDelayFor(CompositorButton targetButton) { - mCurrentButton = targetButton; - clearPendingMessages(); - - Message message = mHandler.obtainMessage(MESSAGE_SHOW_TOOLTIP, targetButton); - mHandler.sendMessageDelayed(message, TOOLTIP_DELAY_MS); - } - - void showImmediatelyFor(CompositorButton targetButton) { - mCurrentButton = targetButton; - - ((TextView) mTooltipView.findViewById(R.id.tooltip_label)) - .setText(targetButton.getAccessibilityDescription()); - - mTooltipView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); - float tooltipWidthPx = mTooltipView.getMeasuredWidth(); - mTooltipView.setX(calculateTooltipXPx(targetButton, tooltipWidthPx)); - mTooltipView.setY(calculateTooltipYPx(targetButton)); - - mTooltipView.setVisibility(View.VISIBLE); - } - - void hideImmediately() { - mCurrentButton = null; - clearPendingMessages(); - mTooltipView.setVisibility(View.GONE); - } - - private float calculateTooltipXPx(CompositorButton targetButton, float tooltipWidthPx) { - float idealXCenterDp = targetButton.getDrawX() + targetButton.getWidth() / 2f; - float idealXCenterPx = idealXCenterDp * getDisplayDensity(); - float idealXLeftPx = idealXCenterPx - tooltipWidthPx / 2f; - float safeXLeftPx = MathUtils.clamp(idealXLeftPx, 0, getWindowWidthPx() - tooltipWidthPx); - return safeXLeftPx; - } - - private float calculateTooltipYPx(CompositorButton targetButton) { - float yDp = mTopPaddingSupplier.get() + targetButton.getDrawY() + targetButton.getHeight(); - float yPx = yDp * getDisplayDensity(); - return yPx; - } - - private float getWindowWidthPx() { - return mTooltipView.getContext().getResources().getDisplayMetrics().widthPixels; - } - - private float getDisplayDensity() { - return mTooltipView.getContext().getResources().getDisplayMetrics().density; - } - - protected FrameLayout getTooltipViewForTesting() { - return mTooltipView; - } - - @SuppressLint("HandlerLeak") - private class TooltipEventHandler extends Handler { - @Override - public void handleMessage(Message m) { - if (m.what != MESSAGE_SHOW_TOOLTIP) { - assert false : "TooltipEventHandler got unknown message " + m.what; - } - showImmediatelyFor((CompositorButton) m.obj); - } - } -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java index c228bf1c..5ab6fdd1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java
@@ -26,6 +26,7 @@ import org.chromium.base.SysUtils; import org.chromium.base.UserData; import org.chromium.base.metrics.RecordHistogram; +import org.chromium.base.metrics.RecordUserAction; import org.chromium.base.supplier.Supplier; import org.chromium.chrome.R; import org.chromium.chrome.browser.IntentHandler; @@ -362,6 +363,7 @@ new UkmRecorder(mTab.getWebContents(), "DomDistiller.Android.ReaderModeShown") .addBooleanMetric("Shown") .record(); + RecordUserAction.record("DomDistiller.Android.OnStartedReaderMode"); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/FileAccessPermissionHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/download/FileAccessPermissionHelper.java index 9021e591..2131e84 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/FileAccessPermissionHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/FileAccessPermissionHelper.java
@@ -10,9 +10,9 @@ import android.os.Build; import android.util.Pair; -import androidx.annotation.NonNull; - import org.chromium.base.Callback; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import org.chromium.components.permissions.AndroidPermissionRequester; import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.modaldialog.DialogDismissalCause; @@ -24,9 +24,10 @@ import java.util.function.Consumer; /** - * Handles file access permission requests. - * TODO(shaktisahu): Move this to a generic location, preferably ui/android. + * Handles file access permission requests. TODO(shaktisahu): Move this to a generic location, + * preferably ui/android. */ +@NullMarked public class FileAccessPermissionHelper { /** * Requests the storage permission from Java. @@ -35,7 +36,7 @@ * @param callback Callback to notify if the permission is granted or not. */ public static void requestFileAccessPermission( - @NonNull WindowAndroid windowAndroid, final Callback<Boolean> callback) { + WindowAndroid windowAndroid, final Callback<Boolean> callback) { requestFileAccessPermissionHelper( windowAndroid, result -> { @@ -54,7 +55,7 @@ } static void requestFileAccessPermissionHelper( - @NonNull WindowAndroid windowAndroid, final Callback<Pair<Boolean, String>> callback) { + WindowAndroid windowAndroid, final Callback<Pair<Boolean, String>> callback) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU || windowAndroid.hasPermission(permission.WRITE_EXTERNAL_STORAGE)) { callback.onResult(Pair.create(true, null)); @@ -80,7 +81,7 @@ return; } - Consumer<PropertyModel> requestPermissions = + Consumer<@Nullable PropertyModel> requestPermissions = (model) -> { PermissionCallback permissionCallback = (permissions, grantResults) -> {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/OfflineContentAvailabilityStatusProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/download/OfflineContentAvailabilityStatusProvider.java index 429be05..626549e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/OfflineContentAvailabilityStatusProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/OfflineContentAvailabilityStatusProvider.java
@@ -6,6 +6,8 @@ import androidx.annotation.VisibleForTesting; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.download.items.OfflineContentAggregatorFactory; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.ChromeSharedPreferences; @@ -23,8 +25,9 @@ * used to decide whether or not users should see messages in the UI about offline content * availability in Chrome. */ +@NullMarked public class OfflineContentAvailabilityStatusProvider implements OfflineContentProvider.Observer { - private static OfflineContentAvailabilityStatusProvider sInstance; + private static @Nullable OfflineContentAvailabilityStatusProvider sInstance; // Keeps track of suggested content. private final Set<ContentId> mSuggestedItems = new HashSet<>();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/hub/HubLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/hub/HubLayout.java index ad63a1a..ef5b368 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/hub/HubLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/hub/HubLayout.java
@@ -61,7 +61,6 @@ import org.chromium.components.browser_ui.desktop_windowing.AppHeaderState; import org.chromium.components.browser_ui.desktop_windowing.DesktopWindowStateManager; import org.chromium.components.browser_ui.desktop_windowing.DesktopWindowStateManager.AppHeaderObserver; -import org.chromium.components.omnibox.OmniboxFeatures; import org.chromium.ui.base.DeviceFormFactor; import org.chromium.ui.base.LocalizationUtils; import org.chromium.ui.resources.ResourceManager; @@ -753,7 +752,7 @@ if (mTabModelSelector.isIncognitoBrandedModelSelected() != newIsIncognito) { // Start from above the toolbar when switching models. finalRect.top = containerViewRect.top; - } else if (OmniboxFeatures.sAndroidHubSearch.isEnabled()) { + } else { // Account for the hub's search box container height. int searchBoxHeight = HubUtils.getSearchBoxHeight(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/hub/HubLayoutUnitTest.java b/chrome/android/java/src/org/chromium/chrome/browser/hub/HubLayoutUnitTest.java index 68c03ec..f2c2955 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/hub/HubLayoutUnitTest.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/hub/HubLayoutUnitTest.java
@@ -68,8 +68,6 @@ import org.chromium.base.supplier.Supplier; import org.chromium.base.supplier.SyncOneshotSupplierImpl; import org.chromium.base.test.BaseRobolectricTestRule; -import org.chromium.base.test.util.Features.DisableFeatures; -import org.chromium.base.test.util.Features.EnableFeatures; import org.chromium.base.test.util.UserActionTester; import org.chromium.chrome.R; import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; @@ -93,7 +91,6 @@ import org.chromium.chrome.browser.tab_ui.TabContentManager; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.components.browser_ui.desktop_windowing.DesktopWindowStateManager; -import org.chromium.components.omnibox.OmniboxFeatureList; import org.chromium.ui.base.TestActivity; import org.chromium.ui.resources.ResourceManager; import org.chromium.ui.util.XrUtils; @@ -640,41 +637,6 @@ } @Test - @DisableFeatures(OmniboxFeatureList.ANDROID_HUB_SEARCH) - public void testFinalRect_SameModel() { - setupFinalRectMocks(/* modelIsIncognito= */ false); - Rect expectedRect = new Rect(0, 10, 90, 110); - Rect actualRect = new Rect(); - - mHubLayout.getFinalRectForNewTabAnimation( - mHubContainerViewMock, /* newIsIncognito= */ false, actualRect); - assertEquals(expectedRect, actualRect); - - when(mTabModelSelector.isIncognitoBrandedModelSelected()).thenReturn(true); - mHubLayout.getFinalRectForNewTabAnimation( - mHubContainerViewMock, /* newIsIncognito= */ true, actualRect); - assertEquals(expectedRect, actualRect); - } - - @Test - @DisableFeatures(OmniboxFeatureList.ANDROID_HUB_SEARCH) - public void testFinalRect_SwitchingModel() { - setupFinalRectMocks(/* modelIsIncognito= */ false); - Rect expectedRect = new Rect(0, 0, 90, 110); - Rect actualRect = new Rect(); - - mHubLayout.getFinalRectForNewTabAnimation( - mHubContainerViewMock, /* newIsIncognito= */ true, actualRect); - assertEquals(expectedRect, actualRect); - - when(mTabModelSelector.isIncognitoBrandedModelSelected()).thenReturn(true); - mHubLayout.getFinalRectForNewTabAnimation( - mHubContainerViewMock, /* newIsIncognito= */ false, actualRect); - assertEquals(expectedRect, actualRect); - } - - @Test - @EnableFeatures(OmniboxFeatureList.ANDROID_HUB_SEARCH) public void testFinalRectWithHubSearch_SwitchingModel() { setupFinalRectMocks(/* modelIsIncognito= */ false); Rect expectedRect = new Rect(0, 0, 90, 110); @@ -691,7 +653,6 @@ } @Test - @EnableFeatures(OmniboxFeatureList.ANDROID_HUB_SEARCH) public void testFinalRectWithHubSearch_SameModel() { setupFinalRectMocks(/* modelIsIncognito= */ false); Rect spyRect = spy(new Rect());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/hub/NewTabAnimationUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/hub/NewTabAnimationUtils.java index eae5cd3..6965e4c9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/hub/NewTabAnimationUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/hub/NewTabAnimationUtils.java
@@ -42,28 +42,6 @@ int CENTER = 4; } - /** - * Version for the new background tab animation. - * - * <p>These numbers match with the "version" feature param for ShowNewTabAnimations. - */ - @IntDef({ - NewTabAnim.M137, - NewTabAnim.BOUNCE, - NewTabAnim.DECELERATE, - NewTabAnim.BOUNCE_DECELERATE, - NewTabAnim.BOUNCE_DECELERATE_WITH_DELAY - }) - @Target(ElementType.TYPE_USE) - @Retention(RetentionPolicy.SOURCE) - public @interface NewTabAnim { - int M137 = 0; - int BOUNCE = 1; - int DECELERATE = 2; - int BOUNCE_DECELERATE = 3; - int BOUNCE_DECELERATE_WITH_DELAY = 4; - } - private static final float INITIAL_SCALE = 0.2f; private static final float FINAL_SCALE = 1.1f;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoProfileDestroyer.java b/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoProfileDestroyer.java index 665005b..cbb7590 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoProfileDestroyer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoProfileDestroyer.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.incognito; +import org.chromium.build.annotations.NullMarked; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.ProfileManager; import org.chromium.chrome.browser.tabmodel.IncognitoTabHostUtils; @@ -13,8 +14,9 @@ /** * Destroys incognito {@link Profile}s when the last incognito tab is destroyed. * - * Reacts to the presence or absence of incognito tabs. + * <p>Reacts to the presence or absence of incognito tabs. */ +@NullMarked public class IncognitoProfileDestroyer implements IncognitoTabModelObserver { private final TabModelSelector mTabModelSelector;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoSnapshotController.java b/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoSnapshotController.java index f3ef1c6..a2e88ab4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoSnapshotController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoSnapshotController.java
@@ -9,20 +9,20 @@ import android.view.Window; import android.view.WindowManager; -import androidx.annotation.NonNull; - import org.chromium.base.supplier.Supplier; +import org.chromium.build.annotations.NullMarked; import org.chromium.chrome.browser.flags.ChromeFeatureList; /** * An abstract base class to provide common functionalities related to allowing/blocking snapshot * for Incognito tabs across {@link ChromeTabbedActivity} and {@link CustomTabActivity}. */ +@NullMarked public abstract class IncognitoSnapshotController { - private final @NonNull Activity mActivity; - private final @NonNull Window mWindow; - private final @NonNull Supplier<Boolean> mIsShowingIncognitoSupplier; + private final Activity mActivity; + private final Window mWindow; + private final Supplier<Boolean> mIsShowingIncognitoSupplier; /** * @param activity The {@link Activity} on which the snapshot capability needs to be controlled. @@ -30,7 +30,7 @@ * showing Incognito or not currently. */ protected IncognitoSnapshotController( - @NonNull Activity activity, @NonNull Supplier<Boolean> isShowingIncognitoSupplier) { + Activity activity, Supplier<Boolean> isShowingIncognitoSupplier) { mActivity = activity; mWindow = activity.getWindow(); mIsShowingIncognitoSupplier = isShowingIncognitoSupplier;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AutofillSaveCardInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AutofillSaveCardInfoBar.java index d567a32..e638515 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AutofillSaveCardInfoBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AutofillSaveCardInfoBar.java
@@ -15,11 +15,11 @@ import android.widget.LinearLayout; import android.widget.TextView; -import androidx.annotation.Nullable; - import org.jni_zero.CalledByNative; import org.jni_zero.NativeMethods; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import org.chromium.chrome.R; import org.chromium.components.autofill.payments.CardDetail; import org.chromium.components.autofill.payments.LegalMessageLine; @@ -34,6 +34,7 @@ import java.util.List; /** An infobar for saving credit card information. */ +@NullMarked public class AutofillSaveCardInfoBar extends ConfirmInfoBar { private final @Nullable String mAccountFooterEmail; @@ -42,7 +43,7 @@ private final List<CardDetail> mCardDetails = new ArrayList<>(); private int mIconDrawableId = -1; private final String mTitleText; - private String mDescriptionText; + private @Nullable String mDescriptionText; private final boolean mIsGooglePayBrandingEnabled; private final LinkedList<LegalMessageLine> mLegalMessageLines = new LinkedList<LegalMessageLine>();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainerView.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainerView.java index 169e9e64..b929804 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainerView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainerView.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser.infobar; +import static org.chromium.build.NullUtil.assumeNonNull; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.content.Context; @@ -12,11 +14,11 @@ import android.view.ViewGroup; import android.widget.FrameLayout; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import org.chromium.base.supplier.ObservableSupplier; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; import org.chromium.chrome.browser.browser_controls.BrowserControlsUtils; import org.chromium.chrome.browser.ui.edge_to_edge.EdgeToEdgeController; @@ -32,6 +34,7 @@ import org.chromium.ui.display.DisplayUtil; /** The {@link View} for the {@link InfoBarContainer}. */ +@NullMarked public class InfoBarContainerView extends SwipableOverlayView implements BrowserControlsStateProvider.Observer, InsetObserver.WindowInsetObserver { /** Observes container view changes. */ @@ -55,15 +58,15 @@ /** Whether or not the InfoBarContainer is allowed to hide when the user scrolls. */ private static boolean sIsAllowedToAutoHide = true; - private final BrowserControlsStateProvider mBrowserControlsStateProvider; + private final @Nullable BrowserControlsStateProvider mBrowserControlsStateProvider; private final ContainerViewObserver mContainerViewObserver; private final InfoBarContainerLayout mLayout; /** Parent view that contains the InfoBarContainerLayout. */ - private ViewGroup mParentView; + private @Nullable ViewGroup mParentView; /** Animation used to snap the container to the nearest state if scroll direction changes. */ - private Animator mScrollDirectionChangeAnimation; + private @Nullable Animator mScrollDirectionChangeAnimation; /** Whether or not the current scroll is downward. */ private boolean mIsScrollingDownward; @@ -71,8 +74,8 @@ /** Tracks the previous event's scroll offset to determine if a scroll is up or down. */ private int mLastScrollOffsetY; - @Nullable private final ObservableSupplier<EdgeToEdgeController> mEdgeToEdgeSupplier; - @Nullable private EdgeToEdgePadAdjuster mEdgeToEdgePadAdjuster; + private final @Nullable ObservableSupplier<EdgeToEdgeController> mEdgeToEdgeSupplier; + private @Nullable EdgeToEdgePadAdjuster mEdgeToEdgePadAdjuster; /** * @param context The {@link Context} that this view is attached to. @@ -85,8 +88,8 @@ */ @Deprecated InfoBarContainerView( - @NonNull Context context, - @NonNull ContainerViewObserver containerViewObserver, + Context context, + ContainerViewObserver containerViewObserver, @Nullable BrowserControlsStateProvider browserControlsStateProvider, boolean isTablet) { this(context, containerViewObserver, browserControlsStateProvider, null, isTablet); @@ -103,8 +106,8 @@ * @param isTablet Whether this view is displayed on tablet or not. */ InfoBarContainerView( - @NonNull Context context, - @NonNull ContainerViewObserver containerViewObserver, + Context context, + ContainerViewObserver containerViewObserver, @Nullable BrowserControlsStateProvider browserControlsStateProvider, @Nullable ObservableSupplier<EdgeToEdgeController> edgeToEdgeSupplier, boolean isTablet) { @@ -134,7 +137,8 @@ } @Override - public void notifyAllAnimationsFinished(InfoBarUiItem frontInfoBar) { + public void notifyAllAnimationsFinished( + @Nullable InfoBarUiItem frontInfoBar) { mContainerViewObserver.notifyAllAnimationsFinished(frontInfoBar); } }); @@ -172,6 +176,7 @@ @Override protected boolean shouldConsumeScroll(int scrollOffsetY, int scrollExtentY) { + assumeNonNull(mBrowserControlsStateProvider); if (mBrowserControlsStateProvider.getBottomControlsHeight() <= 0) return true; boolean isScrollingDownward = scrollOffsetY > mLastScrollOffsetY; @@ -235,7 +240,7 @@ getTotalHeight() * 1.0f * Math.abs(topOffset) - / mBrowserControlsStateProvider.getTopControlsHeight()); + / assumeNonNull(mBrowserControlsStateProvider).getTopControlsHeight()); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/KnownInterceptionDisclosureInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/KnownInterceptionDisclosureInfoBar.java index 76372018..6ef94c8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/KnownInterceptionDisclosureInfoBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/KnownInterceptionDisclosureInfoBar.java
@@ -10,13 +10,15 @@ import org.jni_zero.CalledByNative; +import org.chromium.build.annotations.NullMarked; import org.chromium.components.infobars.ConfirmInfoBar; import org.chromium.components.infobars.InfoBarLayout; /** - * An infobar to disclose known monitoring to the user. This is a thin veneer over - * standard ConfirmInfoBar to provide a description as well as a title. + * An infobar to disclose known monitoring to the user. This is a thin veneer over standard + * ConfirmInfoBar to provide a description as well as a title. */ +@NullMarked public class KnownInterceptionDisclosureInfoBar extends ConfirmInfoBar { private final String mDescription;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/PasswordInfoBarUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/PasswordInfoBarUtils.java index 19560bb..e81f39df 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/PasswordInfoBarUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/PasswordInfoBarUtils.java
@@ -10,10 +10,12 @@ import android.widget.LinearLayout; import android.widget.TextView; +import org.chromium.build.annotations.NullMarked; import org.chromium.chrome.R; import org.chromium.components.browser_ui.widget.RoundedCornerImageView; /** Provides helper methods for Android Infobars. */ +@NullMarked class PasswordInfoBarUtils { private PasswordInfoBarUtils() {}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/PermissionInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/PermissionInfoBar.java index 43fb1a4..b77cd50 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/PermissionInfoBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/PermissionInfoBar.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser.infobar; +import static org.chromium.build.NullUtil.assertNonNull; + import android.os.Bundle; import android.text.SpannableString; import android.text.SpannableStringBuilder; @@ -11,6 +13,7 @@ import org.jni_zero.CalledByNative; +import org.chromium.build.annotations.NullMarked; import org.chromium.chrome.R; import org.chromium.chrome.browser.settings.SettingsNavigationFactory; import org.chromium.components.browser_ui.settings.SettingsNavigation; @@ -24,6 +27,7 @@ import org.chromium.ui.text.ChromeClickableSpan; /** An infobar used for prompting the user to grant a web API permission. */ +@NullMarked public class PermissionInfoBar extends ConfirmInfoBar implements AndroidPermissionRequester.RequestDelegate { /** The window which this infobar will be displayed upon. */ @@ -179,7 +183,7 @@ SettingsNavigation settingsNavigation = SettingsNavigationFactory.createSettingsNavigation(); settingsNavigation.startSettings( - getContext(), SingleCategorySettings.class, fragmentArguments); + assertNonNull(getContext()), SingleCategorySettings.class, fragmentArguments); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/SubPanelListener.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/SubPanelListener.java index d792fcb..7a65b946 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/SubPanelListener.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/SubPanelListener.java
@@ -3,7 +3,10 @@ // found in the LICENSE file. package org.chromium.chrome.browser.infobar; +import org.chromium.build.annotations.NullMarked; + /** A listener to interact with the different subpanels of the translate infobar. */ +@NullMarked public interface SubPanelListener { /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ActivityLifecycleDispatcherImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/init/ActivityLifecycleDispatcherImpl.java index 492a9aa9..6852e01 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/init/ActivityLifecycleDispatcherImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/init/ActivityLifecycleDispatcherImpl.java
@@ -9,9 +9,9 @@ import android.content.res.Configuration; import android.os.Bundle; -import androidx.annotation.Nullable; - import org.chromium.base.ObserverList; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; import org.chromium.chrome.browser.lifecycle.ActivityResultWithNativeObserver; import org.chromium.chrome.browser.lifecycle.ConfigurationChangedObserver; @@ -31,8 +31,9 @@ * Dispatches lifecycle events of activities extending {@link AsyncInitializationActivity} to * registered observers. * - * All observers will be automatically cleared when the backing activity is destroyed. + * <p>All observers will be automatically cleared when the backing activity is destroyed. */ +@NullMarked public class ActivityLifecycleDispatcherImpl implements ActivityLifecycleDispatcher { private final ObserverList<InflationObserver> mInflationObservers = new ObserverList<>(); private final ObserverList<NativeInitObserver> mNativeInitObservers = new ObserverList<>(); @@ -61,7 +62,7 @@ private boolean mIsNativeInitialized; private boolean mDestroyed; - public ActivityLifecycleDispatcherImpl(Activity activity) { + public ActivityLifecycleDispatcherImpl(@Nullable Activity activity) { mActivity = activity; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ActivityProfileProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/init/ActivityProfileProvider.java index 8220c9ba..67304d1c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/init/ActivityProfileProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/init/ActivityProfileProvider.java
@@ -4,10 +4,9 @@ package org.chromium.chrome.browser.init; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - import org.chromium.base.supplier.OneshotSupplierImpl; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; import org.chromium.chrome.browser.lifecycle.DestroyObserver; import org.chromium.chrome.browser.profiles.OtrProfileId; @@ -16,9 +15,10 @@ import org.chromium.chrome.browser.profiles.ProfileProvider; /** Handles initializing an Activity appropriate ProfileProvider. */ +@NullMarked public class ActivityProfileProvider extends OneshotSupplierImpl<ProfileProvider> implements ProfileManager.Observer, DestroyObserver { - private OtrProfileId mOtrProfileId; + private @Nullable OtrProfileId mOtrProfileId; private boolean mHasCreatedOtrProfileId; /** @@ -26,7 +26,7 @@ * * @param lifecycleDispatcher Provides lifecycle events for the host activity. */ - public ActivityProfileProvider(@NonNull ActivityLifecycleDispatcher lifecycleDispatcher) { + public ActivityProfileProvider(ActivityLifecycleDispatcher lifecycleDispatcher) { lifecycleDispatcher.register(this); if (ProfileManager.isInitialized()) { @@ -49,15 +49,14 @@ private void onProfileManagerReady() { set( new ProfileProvider() { - @NonNull + @Override public Profile getOriginalProfile() { return ProfileManager.getLastUsedRegularProfile(); } - @Nullable @Override - public Profile getOffTheRecordProfile(boolean createIfNeeded) { + public @Nullable Profile getOffTheRecordProfile(boolean createIfNeeded) { Profile originalProfile = getOriginalProfile(); OtrProfileId otrProfileId = getOrCreateOtrProfileId(); return otrProfileId == null @@ -77,8 +76,7 @@ }); } - @Nullable - private OtrProfileId getOrCreateOtrProfileId() { + private @Nullable OtrProfileId getOrCreateOtrProfileId() { if (!mHasCreatedOtrProfileId) { mOtrProfileId = createOffTheRecordProfileId(); mHasCreatedOtrProfileId = true; @@ -90,8 +88,7 @@ * Create the OtrProfileId that should be used for the incognito profile of this provider. If * null, the default OffTheRecord profile will be used. */ - @Nullable - protected OtrProfileId createOffTheRecordProfileId() { + protected @Nullable OtrProfileId createOffTheRecordProfileId() { return null; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/BrowserParts.java b/chrome/android/java/src/org/chromium/chrome/browser/init/BrowserParts.java index b1d4f647..e351342 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/init/BrowserParts.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/init/BrowserParts.java
@@ -4,14 +4,16 @@ package org.chromium.chrome.browser.init; -import androidx.annotation.Nullable; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; /** * Interface that any {@link AsyncInitializationActivity} can use to interact with this delegate - * during start up. Functions called by - * {@link ChromeBrowserInitializer#handlePreNativeStartupAndLoadLibraries(BrowserParts)} are called - * in the order they are listed. + * during start up. Functions called by {@link + * ChromeBrowserInitializer#handlePreNativeStartupAndLoadLibraries(BrowserParts)} are called in the + * order they are listed. */ +@NullMarked public interface BrowserParts { /** * Called during {@link
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeActivityNativeDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeActivityNativeDelegate.java index 5f8e780..964e29d8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeActivityNativeDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeActivityNativeDelegate.java
@@ -6,7 +6,8 @@ import android.content.Intent; -import androidx.annotation.Nullable; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; /** * An activity level delegate to handle native initialization and activity lifecycle related tasks @@ -15,6 +16,7 @@ * have not been loaded yet, the calls in ChromeActivityNativeDelegate will be in the right order * among themselves, but can be deferred and out of sync wrt to Activity calls. */ +@NullMarked public interface ChromeActivityNativeDelegate { /** * Carry out native initialization related tasks and any other java tasks that can be done async
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/MinimalBrowserStartupUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/init/MinimalBrowserStartupUtils.java index aff3054e..a81d1dba 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/init/MinimalBrowserStartupUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/init/MinimalBrowserStartupUtils.java
@@ -4,7 +4,10 @@ package org.chromium.chrome.browser.init; +import org.chromium.build.annotations.NullMarked; + /** Helper class for features that can be run in the minimal browser mode. */ +@NullMarked public class MinimalBrowserStartupUtils { public static final String TASK_TAG = "Servicification Startup Task"; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/MediaCaptureDevicesDispatcherAndroid.java b/chrome/android/java/src/org/chromium/chrome/browser/media/MediaCaptureDevicesDispatcherAndroid.java index 52373c9e..f8331bf 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/MediaCaptureDevicesDispatcherAndroid.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/MediaCaptureDevicesDispatcherAndroid.java
@@ -6,12 +6,14 @@ import org.jni_zero.NativeMethods; +import org.chromium.build.annotations.NullMarked; import org.chromium.content_public.browser.WebContents; /** * Java access point for MediaCaptureDevicesDispatcher, allowing for querying and manipulation of * media capture state. */ +@NullMarked public class MediaCaptureDevicesDispatcherAndroid { public static boolean isCapturingAudio(WebContents webContents) { if (webContents == null) return false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPicture.java b/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPicture.java index 9e96fe1..9ee5a659 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPicture.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPicture.java
@@ -10,11 +10,13 @@ import android.os.Build; import org.chromium.base.TraceEvent; +import org.chromium.build.annotations.NullMarked; /** * Utility for determining if Picture-in-Picture is available and whether the user has disabled * Picture-in-Picture for Chrome using the system's per-application settings. */ +@NullMarked public abstract class PictureInPicture { private PictureInPicture() {}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/ChromeMediaNotificationControllerDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/ChromeMediaNotificationControllerDelegate.java index 9ae8f7a0..1781ad2d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/ChromeMediaNotificationControllerDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/ChromeMediaNotificationControllerDelegate.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser.media.ui; +import static org.chromium.build.NullUtil.assumeNonNull; + import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; @@ -14,12 +16,13 @@ import android.support.v4.media.session.MediaSessionCompat; import android.util.SparseArray; -import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.mediarouter.media.MediaRouter; import org.chromium.base.ContextUtils; import org.chromium.base.metrics.RecordHistogram; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import org.chromium.chrome.R; import org.chromium.chrome.browser.base.SplitCompatService; import org.chromium.chrome.browser.notifications.NotificationConstants; @@ -34,6 +37,7 @@ import org.chromium.components.browser_ui.notifications.NotificationWrapperBuilder; /** A class that provides Chrome-specific behavior to {@link MediaNotificationController}. */ +@NullMarked class ChromeMediaNotificationControllerDelegate implements MediaNotificationController.Delegate { private final int mNotificationId; @@ -86,7 +90,7 @@ } @Override - public IBinder onBind(Intent intent) { + public @Nullable IBinder onBind(Intent intent) { return null; } @@ -99,7 +103,7 @@ } @Override - public int onStartCommand(Intent intent, int flags, int startId) { + public int onStartCommand(@Nullable Intent intent, int flags, int startId) { if (!processIntent(intent)) { // The service has been started with startForegroundService() but the // notification hasn't been shown. On O it will lead to the app crash. @@ -122,7 +126,7 @@ } @VisibleForTesting - boolean processIntent(Intent intent) { + boolean processIntent(@Nullable Intent intent) { MediaNotificationController controller = getController(); if (controller == null) return false; @@ -224,8 +228,9 @@ } @Override - public Intent createServiceIntent() { - Class<?> serviceClass = sMapNotificationIdToOptions.get(mNotificationId).serviceClass; + public @Nullable Intent createServiceIntent() { + Class<?> serviceClass = + assumeNonNull(sMapNotificationIdToOptions.get(mNotificationId)).serviceClass; return (serviceClass != null) ? new Intent(getContext(), serviceClass) : null; } @@ -236,7 +241,8 @@ @Override public String getNotificationGroupName() { - String groupName = sMapNotificationIdToOptions.get(mNotificationId).groupName; + String groupName = + assumeNonNull(sMapNotificationIdToOptions.get(mNotificationId)).groupName; assert groupName != null; return groupName;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java index 33ab778..e436073 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java
@@ -79,7 +79,6 @@ import org.chromium.components.browser_ui.edge_to_edge.EdgeToEdgeSystemBarColorHelper; import org.chromium.components.browser_ui.modaldialog.AppModalPresenter; import org.chromium.components.metrics.OmniboxEventProtos.OmniboxEventProto.PageClassification; -import org.chromium.components.omnibox.OmniboxFeatures; import org.chromium.ui.base.ActivityKeyboardVisibilityDelegate; import org.chromium.ui.base.ActivityWindowAndroid; import org.chromium.ui.modaldialog.ModalDialogManager; @@ -410,9 +409,7 @@ mSearchBoxDataProvider.setCurrentUrl(SearchActivityUtils.getIntentUrl(intent)); - if (OmniboxFeatures.sAndroidHubSearch.isEnabled()) { - setColorScheme(mSearchBoxDataProvider.isIncognitoBranded()); - } + setColorScheme(mSearchBoxDataProvider.isIncognitoBranded()); switch (mIntentOrigin) { case IntentOrigin.CUSTOM_TAB: @@ -518,7 +515,7 @@ private void finishNativeInitializationWithProfile(Profile profile) { refinePageClassWithProfile(profile); - if (OmniboxFeatures.sAndroidHubSearch.isEnabled() && mIntentOrigin == IntentOrigin.HUB) { + if (mIntentOrigin == IntentOrigin.HUB) { setHubSearchBoxUrlBarElements(); } @@ -668,8 +665,7 @@ intent.putExtra(SearchWidgetProvider.EXTRA_FROM_SEARCH_WIDGET, true); } - if (OmniboxFeatures.sAndroidHubSearch.isEnabled() - && mSearchBoxDataProvider.isIncognitoBranded()) { + if (mSearchBoxDataProvider.isIncognitoBranded()) { intent.putExtra(Browser.EXTRA_APPLICATION_ID, getApplicationContext().getPackageName()); intent.putExtra(IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, true); IntentUtils.addTrustedIntentExtras(intent);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/BottomAttachedUiObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/BottomAttachedUiObserver.java index 3c92308..7cd67d8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/BottomAttachedUiObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/BottomAttachedUiObserver.java
@@ -552,7 +552,7 @@ @Override public void onSheetContentChanged(BottomSheetContent newContent) { if (newContent != null) { - mBottomSheetColor = newContent.getBackgroundColor(); + mBottomSheetColor = mBottomSheetController.getSheetBackgroundColor(); } updateBottomAttachedColor(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index 6060443..224f7da 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -1718,7 +1718,8 @@ mWindowAndroid.getInsetObserver(), controlContainerTranslationSupplier, controlContainerHeightSupplier, - keyboardAccessoryStateSupplier.getIsSheetShowingSupplier()); + keyboardAccessoryStateSupplier.getIsSheetShowingSupplier(), + this::isUrlBarFocused); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java index e08fa4d..d99ebb8 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java
@@ -7,7 +7,6 @@ import android.content.pm.ActivityInfo; import android.view.MotionEvent; import android.view.View; -import android.widget.FrameLayout; import androidx.test.filters.LargeTest; import androidx.test.platform.app.InstrumentationRegistry; @@ -1227,115 +1226,6 @@ }); } - /** Tests hover enter/move/exit events associated with the tab strip buttons. */ - @Test - @LargeTest - @Feature({"TabStrip"}) - @Restriction(DeviceFormFactor.TABLET) - public void testHoverOnTabStripButtons() throws Exception { - StripLayoutHelperManager stripLayoutHelperManager = - TabStripUtils.getStripLayoutHelperManager(mActivityTestRule.getActivity()); - - // Select NTB. - CompositorButton newTabButton = stripLayoutHelperManager.getNewTabButton(); - Assert.assertNotNull( - "Tooltip ViewStub should not be inflated before first hover event.", - stripLayoutHelperManager.getTooltipViewStubForTesting().getParent()); - - // Simulate a hover into NTB. - float xEnter = newTabButton.getDrawX() + newTabButton.getWidth() / 2; - float yEnter = newTabButton.getDrawY() + newTabButton.getHeight() / 2; - ThreadUtils.runOnUiThreadBlocking( - () -> - stripLayoutHelperManager.simulateHoverEventForTesting( - MotionEvent.ACTION_HOVER_ENTER, xEnter, yEnter)); - - // Verify that the tooltip is visible as expected. - FrameLayout tooltipView = - stripLayoutHelperManager.getTooltipManagerForTesting().getTooltipViewForTesting(); - Assert.assertNotNull("Tooltip view should be set.", tooltipView); - CriteriaHelper.pollInstrumentationThread( - () -> { - Criteria.checkThat( - "Tooltip should be visible.", - tooltipView.getVisibility(), - Matchers.is(View.VISIBLE)); - }); - - // Enter incognito mode. - mActivityTestRule.newIncognitoTabFromMenu(); - InstrumentationRegistry.getInstrumentation().waitForIdleSync(); - - // Select MSB. - CompositorButton modelSelectorButton = stripLayoutHelperManager.getModelSelectorButton(); - Assert.assertNotNull( - "The modelSelectorButton should be set in StripLayoutHelperManager instance", - modelSelectorButton); - - // Simulate a subsequent hover into the MSB. - float xMove = modelSelectorButton.getDrawX() + modelSelectorButton.getWidth() / 3; - float yMove = modelSelectorButton.getDrawY() + modelSelectorButton.getHeight() / 3; - ThreadUtils.runOnUiThreadBlocking( - () -> - stripLayoutHelperManager.simulateHoverEventForTesting( - MotionEvent.ACTION_HOVER_MOVE, xMove, yMove)); - Assert.assertNotNull("Tooltip view should be set.", tooltipView); - CriteriaHelper.pollInstrumentationThread( - () -> { - Criteria.checkThat( - "Tooltip should be visible.", - tooltipView.getVisibility(), - Matchers.is(View.VISIBLE)); - }); - - // Simulate a subsequent hover outside the MSB. - float xExit = xMove + modelSelectorButton.getWidth(); - float yExit = yMove + modelSelectorButton.getHeight(); - ThreadUtils.runOnUiThreadBlocking( - () -> - stripLayoutHelperManager.simulateHoverEventForTesting( - MotionEvent.ACTION_HOVER_EXIT, xExit, yExit)); - Assert.assertNotNull("Tooltip view should be set.", tooltipView); - CriteriaHelper.pollInstrumentationThread( - () -> { - Criteria.checkThat( - "Tooltip should be gone.", - tooltipView.getVisibility(), - Matchers.is(View.GONE)); - }); - - // Exit incognito mode. - clickIncognitoToggleButton(); - - // Simulate a subsequent hover into the MSB outside of incognito mode. - ThreadUtils.runOnUiThreadBlocking( - () -> - stripLayoutHelperManager.simulateHoverEventForTesting( - MotionEvent.ACTION_HOVER_MOVE, xMove, yMove)); - Assert.assertNotNull("Tooltip view should be set.", tooltipView); - CriteriaHelper.pollInstrumentationThread( - () -> { - Criteria.checkThat( - "Tooltip should be visible.", - tooltipView.getVisibility(), - Matchers.is(View.VISIBLE)); - }); - - // Simulate the final hover outside the MSB. - ThreadUtils.runOnUiThreadBlocking( - () -> - stripLayoutHelperManager.simulateHoverEventForTesting( - MotionEvent.ACTION_HOVER_EXIT, xExit, yExit)); - Assert.assertNotNull("Tooltip view should be set.", tooltipView); - CriteriaHelper.pollInstrumentationThread( - () -> { - Criteria.checkThat( - "Tooltip should be gone.", - tooltipView.getVisibility(), - Matchers.is(View.GONE)); - }); - } - /** Simulates a click to the incognito toggle button. */ protected void clickIncognitoToggleButton() { final CallbackHelper tabModelSelectedCallback = new CallbackHelper();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/MostVisitedTilesPTTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/MostVisitedTilesPTTest.java index 576cb1d..605d61e5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/MostVisitedTilesPTTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/MostVisitedTilesPTTest.java
@@ -18,7 +18,10 @@ import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.Features.DisableFeatures; +import org.chromium.base.test.util.Features.EnableFeatures; import org.chromium.base.test.util.HistogramWatcher; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.suggestions.SiteSuggestion; import org.chromium.chrome.browser.util.BrowserUiUtils.ModuleTypeOnStartAndNtp; @@ -33,7 +36,9 @@ import org.chromium.chrome.test.util.browser.suggestions.mostvisited.FakeMostVisitedSites; import org.chromium.net.test.EmbeddedTestServerRule; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** Tests the Most Visited Tiles in the NTP. */ @RunWith(ChromeJUnit4ClassRunner.class) @@ -63,19 +68,43 @@ @Test @MediumTest - public void test010_ClickFirstMVT() { + @DisableFeatures({ChromeFeatureList.MOST_VISITED_TILES_CUSTOMIZATION}) + public void test010_ClickFirstMVT_DisableMvtCustomization() { doClickMVTTest(0); } @Test @MediumTest - public void test020_ClickLastMVT() { + @EnableFeatures({ChromeFeatureList.MOST_VISITED_TILES_CUSTOMIZATION}) + public void test010_ClickFirstMVT_EnableMvtCustomization() { + doClickMVTTest(0); + } + + @Test + @MediumTest + @DisableFeatures({ChromeFeatureList.MOST_VISITED_TILES_CUSTOMIZATION}) + public void test020_ClickLastMVT_DisableMvtCustomization() { + doClickMVTTest(7); + } + + @Test + @MediumTest + @EnableFeatures({ChromeFeatureList.MOST_VISITED_TILES_CUSTOMIZATION}) + public void test020_ClickLastMVT_EnableMvtCustomization() { doClickMVTTest(7); } private void doClickMVTTest(int index) { RegularNewTabPageStation page = mCtaTestRule.start(); - MvtsFacility mvts = page.focusOnMvts(sSiteSuggestions); + + Set<Integer> nonTileIndices; + // Populate with the "Add new" button at the end. + nonTileIndices = new HashSet<Integer>(); + if (ChromeFeatureList.isEnabled(ChromeFeatureList.MOST_VISITED_TILES_CUSTOMIZATION)) { + nonTileIndices.add(sSiteSuggestions.size()); + } + + MvtsFacility mvts = page.focusOnMvts(sSiteSuggestions, nonTileIndices); WebPageStation mostVisitedPage; try (var histogram = HistogramWatcher.newSingleRecordWatcher(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/ShowNtpAtStartupTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/ShowNtpAtStartupTest.java index 34b89bf..ad74e21 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/ShowNtpAtStartupTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/ShowNtpAtStartupTest.java
@@ -43,7 +43,6 @@ import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.DoNotBatch; import org.chromium.base.test.util.Feature; -import org.chromium.base.test.util.Features.DisableFeatures; import org.chromium.base.test.util.Features.EnableFeatures; import org.chromium.base.test.util.HistogramWatcher; import org.chromium.base.test.util.Restriction; @@ -171,7 +170,6 @@ @MediumTest @Feature({"StartSurface"}) @EnableFeatures({START_SURFACE_RETURN_TIME_IMMEDIATE, ChromeFeatureList.MAGIC_STACK_ANDROID}) - @DisableFeatures(ChromeFeatureList.TAB_RESUMPTION_MODULE_ANDROID) public void testSingleTabCardGoneAfterTabClosed_MagicStack() throws IOException { HomeSurfaceTestUtils.prepareTabStateMetadataFile( new int[] {0, 1}, new String[] {TAB_URL, TAB_URL_1}, 0); @@ -231,7 +229,6 @@ @MediumTest @Feature({"StartSurface"}) @EnableFeatures(START_SURFACE_RETURN_TIME_IMMEDIATE) - @DisableFeatures(ChromeFeatureList.TAB_RESUMPTION_MODULE_ANDROID) public void testSingleTabModule() throws IOException { HomeSurfaceTestUtils.prepareTabStateMetadataFile( new int[] {0, 1}, new String[] {TAB_URL, TAB_URL_1}, 0); @@ -256,7 +253,6 @@ @MediumTest @Feature({"StartSurface"}) @EnableFeatures({START_SURFACE_RETURN_TIME_IMMEDIATE, ChromeFeatureList.MAGIC_STACK_ANDROID}) - @DisableFeatures(ChromeFeatureList.TAB_RESUMPTION_MODULE_ANDROID) public void testSingleTabModule_MagicStack() throws IOException { HomeSurfaceTestUtils.prepareTabStateMetadataFile( new int[] {0, 1}, new String[] {TAB_URL, TAB_URL_1}, 0); @@ -340,7 +336,6 @@ @MediumTest @Feature({"StartSurface"}) @EnableFeatures({START_SURFACE_RETURN_TIME_IMMEDIATE, ChromeFeatureList.MAGIC_STACK_ANDROID}) - @DisableFeatures(ChromeFeatureList.TAB_RESUMPTION_MODULE_ANDROID) public void testClickSingleTabCardCloseNtpHomeSurface() throws IOException { HomeSurfaceTestUtils.prepareTabStateMetadataFile(new int[] {0}, new String[] {TAB_URL}, 0); mActivityTestRule.startFromLauncher();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesLayoutTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesLayoutTest.java index c023d5d..de15b557 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesLayoutTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesLayoutTest.java
@@ -45,7 +45,10 @@ import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; +import org.chromium.base.test.util.Features.DisableFeatures; +import org.chromium.base.test.util.Features.EnableFeatures; import org.chromium.chrome.browser.app.ChromeActivity; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; import org.chromium.chrome.browser.night_mode.ChromeNightModeTestUtils; @@ -144,19 +147,56 @@ @MediumTest @Feature({"NewTabPage", "RenderTest"}) @ParameterAnnotations.UseMethodParameter(NightModeTestUtils.NightModeParams.class) - public void testTilesLayoutAppearance(boolean nightModeEnabled) throws Exception { - NewTabPage ntp = setUpFakeDataToShowOnNtp(FAKE_MOST_VISITED_URLS.length); - mRenderTestRule.render(getTilesLayout(ntp), "ntp_tile_layout"); + @DisableFeatures({ChromeFeatureList.MOST_VISITED_TILES_CUSTOMIZATION}) + public void testTilesLayoutAppearance_DisableMvtCustomization(boolean nightModeEnabled) + throws Exception { + doTilesLayoutAppearanceTest(nightModeEnabled, ""); } @Test @MediumTest @Feature({"NewTabPage", "RenderTest"}) + @ParameterAnnotations.UseMethodParameter(NightModeTestUtils.NightModeParams.class) + @EnableFeatures({ChromeFeatureList.MOST_VISITED_TILES_CUSTOMIZATION}) + public void testTilesLayoutAppearance_EnableMvtCustomization(boolean nightModeEnabled) + throws Exception { + doTilesLayoutAppearanceTest(nightModeEnabled, "_with_add_new_button"); + } + + private void doTilesLayoutAppearanceTest(boolean nightModeEnabled, String suffix) + throws Exception { + NewTabPage ntp = setUpFakeDataToShowOnNtp(FAKE_MOST_VISITED_URLS.length); + mRenderTestRule.render(getTilesLayout(ntp), "ntp_tile_layout" + suffix); + } + + @Test + @MediumTest + @Feature({"NewTabPage", "RenderTest"}) + @DisableFeatures({ChromeFeatureList.MOST_VISITED_TILES_CUSTOMIZATION}) @DisableIf.Build( message = "Both variants are flaky on Nougat emulator, see crbug.com/1450693", supported_abis_includes = "x86", sdk_is_less_than = VERSION_CODES.O) - public void testModernTilesLayoutAppearance_Full() throws IOException, InterruptedException { + public void testModernTilesLayoutAppearance_Full_DisableMvtCustomization() + throws IOException, InterruptedException { + doModernTilesLayoutAppearanceTest_Full(""); + } + + @Test + @MediumTest + @Feature({"NewTabPage", "RenderTest"}) + @EnableFeatures({ChromeFeatureList.MOST_VISITED_TILES_CUSTOMIZATION}) + @DisableIf.Build( + message = "Both variants are flaky on Nougat emulator, see crbug.com/1450693", + supported_abis_includes = "x86", + sdk_is_less_than = VERSION_CODES.O) + public void testModernTilesLayoutAppearance_Full_EnableMvtCustomization() + throws IOException, InterruptedException { + doModernTilesLayoutAppearanceTest_Full("_with_add_new_button"); + } + + private void doModernTilesLayoutAppearanceTest_Full(String suffix) + throws IOException, InterruptedException { View tilesLayout = renderTiles(makeSuggestions(FAKE_MOST_VISITED_URLS.length)); Activity activity = mActivityTestRule.getActivity(); @@ -167,7 +207,7 @@ activity.getResources().getConfiguration().orientation, is(ORIENTATION_PORTRAIT)); }); - mRenderTestRule.render(tilesLayout, "modern_tiles_layout_full_portrait"); + mRenderTestRule.render(tilesLayout, "modern_tiles_layout_full_portrait" + suffix); activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); CriteriaHelper.pollUiThread( @@ -176,7 +216,7 @@ activity.getResources().getConfiguration().orientation, is(ORIENTATION_LANDSCAPE)); }); - mRenderTestRule.render(tilesLayout, "modern_tiles_layout_full_landscape"); + mRenderTestRule.render(tilesLayout, "modern_tiles_layout_full_landscape" + suffix); // Reset device orientation. ActivityTestUtils.clearActivityOrientation(activity);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGroupUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGroupUnitTest.java index e2024a54..35036ff 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGroupUnitTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGroupUnitTest.java
@@ -28,6 +28,8 @@ import android.graphics.Bitmap.Config; import android.graphics.Color; import android.view.ContextThemeWrapper; +import android.view.View; +import android.widget.TextView; import androidx.test.annotation.UiThreadTest; import androidx.test.filters.SmallTest; @@ -46,6 +48,8 @@ import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.DisabledTest; +import org.chromium.base.test.util.Features.DisableFeatures; +import org.chromium.base.test.util.Features.EnableFeatures; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.native_page.ContextMenuManager; import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; @@ -326,8 +330,22 @@ @Test @UiThreadTest @SmallTest + @DisableFeatures({ChromeFeatureList.MOST_VISITED_TILES_CUSTOMIZATION}) // If this flakes again, refer to https://crbug.com/1330627, https://crbug.com/1293208. - public void testRenderTileView() { + public void testRenderTileView_DisableMvtCustomization() { + doRenderTileViewTest(); + } + + @Test + @UiThreadTest + @SmallTest + @EnableFeatures({ChromeFeatureList.MOST_VISITED_TILES_CUSTOMIZATION}) + // If this flakes again, refer to https://crbug.com/1330627, https://crbug.com/1293208. + public void testRenderTileView_EnableMvtCustomization() { + doRenderTileViewTest(); + } + + private void doRenderTileViewTest() { SuggestionsUiDelegate uiDelegate = mSuggestionsUiDelegate; when(uiDelegate.getImageFetcher()).thenReturn(mImageFetcher); TileGroup tileGroup = @@ -348,9 +366,20 @@ // Render them to the layout. refreshData(tileGroup, layout); - assertThat(layout.getChildCount(), is(2)); - assertThat(((SuggestionsTileView) layout.getChildAt(0)).getUrl().getSpec(), is(URLS[0])); - assertThat(((SuggestionsTileView) layout.getChildAt(1)).getUrl().getSpec(), is(URLS[1])); + if (ChromeFeatureList.isEnabled(ChromeFeatureList.MOST_VISITED_TILES_CUSTOMIZATION)) { + assertThat(layout.getChildCount(), is(3)); + assertThat( + ((SuggestionsTileView) layout.getChildAt(0)).getUrl().getSpec(), is(URLS[0])); + assertThat( + ((SuggestionsTileView) layout.getChildAt(1)).getUrl().getSpec(), is(URLS[1])); + assertTrue(isAddNewButton(layout.getChildAt(2))); + } else { + assertThat(layout.getChildCount(), is(2)); + assertThat( + ((SuggestionsTileView) layout.getChildAt(0)).getUrl().getSpec(), is(URLS[0])); + assertThat( + ((SuggestionsTileView) layout.getChildAt(1)).getUrl().getSpec(), is(URLS[1])); + } // Rerun to test SuggestionsTileView caching. refreshData(tileGroup, layout); } @@ -386,8 +415,22 @@ @Test @UiThreadTest @SmallTest + @DisableFeatures({ChromeFeatureList.MOST_VISITED_TILES_CUSTOMIZATION}) // If this flakes again, refer to https://crbug.com/1286755. - public void testRenderTileViewReplacing() { + public void testRenderTileViewReplacing_DisableMvtCustomization() { + doRenderTileViewReplacingTest(); + } + + @Test + @UiThreadTest + @SmallTest + @EnableFeatures({ChromeFeatureList.MOST_VISITED_TILES_CUSTOMIZATION}) + // If this flakes again, refer to https://crbug.com/1286755. + public void testRenderTileViewReplacing_EnableMvtCustomization() { + doRenderTileViewReplacingTest(); + } + + private void doRenderTileViewReplacingTest() { SuggestionsUiDelegate uiDelegate = mSuggestionsUiDelegate; when(uiDelegate.getImageFetcher()).thenReturn(mMockImageFetcher); TileGroup tileGroup = @@ -412,9 +455,16 @@ // The tiles should be updated, the old ones removed. refreshData(tileGroup, layout); - assertThat(layout.getChildCount(), is(2)); - assertThat(layout.indexOfChild(view1), is(-1)); - assertThat(layout.indexOfChild(view2), is(-1)); + if (ChromeFeatureList.isEnabled(ChromeFeatureList.MOST_VISITED_TILES_CUSTOMIZATION)) { + assertThat(layout.getChildCount(), is(3)); + assertThat(layout.indexOfChild(view1), is(-1)); + assertThat(layout.indexOfChild(view2), is(-1)); + assertTrue(isAddNewButton(layout.getChildAt(2))); + } else { + assertThat(layout.getChildCount(), is(2)); + assertThat(layout.indexOfChild(view1), is(-1)); + assertThat(layout.indexOfChild(view2), is(-1)); + } // Rerun to test SuggestionsTileView caching. refreshData(tileGroup, layout); } @@ -605,6 +655,13 @@ return tileGroup; } + private boolean isAddNewButton(View view) { + View tileView = view.findViewById(R.id.tile_view_title); + return tileView != null + && (tileView instanceof TextView) + && ((TextView) tileView).getText().toString().equals("Add new"); + } + private static class FakeImageFetcher extends ImageFetcher { private final List<LargeIconCallback> mCallbackList = new ArrayList<>();
diff --git a/chrome/android/junit/BUILD.gn b/chrome/android/junit/BUILD.gn index 4b71e97..5e8bd97 100644 --- a/chrome/android/junit/BUILD.gn +++ b/chrome/android/junit/BUILD.gn
@@ -551,7 +551,6 @@ "src/org/chromium/chrome/browser/compositor/overlays/strip/TabGroupContextMenuCoordinatorUnitTest.java", "src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripIphControllerUnitTest.java", "src/org/chromium/chrome/browser/compositor/overlays/strip/TabUsageTrackerTest.java", - "src/org/chromium/chrome/browser/compositor/overlays/strip/TooltipManagerUnitTest.java", "src/org/chromium/chrome/browser/compositor/overlays/strip/reorder/ExternalViewDragDropReorderStrategyTest.java", "src/org/chromium/chrome/browser/compositor/overlays/strip/reorder/GroupReorderStrategyTest.java", "src/org/chromium/chrome/browser/compositor/overlays/strip/reorder/ReorderStrategyTestBase.java",
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManagerTest.java index f04c3ad..7b1633b 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManagerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManagerTest.java
@@ -146,7 +146,6 @@ @Mock private Tab mSelectedTab; @Mock private StripLayoutTab mHoveredStripTab; @Mock private ViewStub mTabHoverCardViewStub; - @Mock private ViewStub mTooltipViewStub; @Mock private ObservableSupplierImpl<TabContentManager> mTabContentManagerSupplier; @Mock private BrowserControlsStateProvider mBrowserControlStateProvider; @Mock private WindowAndroid mWindowAndroid; @@ -237,7 +236,6 @@ mDragDropDelegate, mToolbarContainerView, mTabHoverCardViewStub, - mTooltipViewStub, mTabContentManagerSupplier, mBrowserControlStateProvider, mWindowAndroid,
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java index dbeb528..77f9d75 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java
@@ -93,6 +93,7 @@ import org.chromium.chrome.browser.compositor.layouts.LayoutUpdateHost; import org.chromium.chrome.browser.compositor.layouts.components.CompositorButton; import org.chromium.chrome.browser.compositor.layouts.components.CompositorButton.ButtonType; +import org.chromium.chrome.browser.compositor.layouts.components.CompositorButton.TooltipHandler; import org.chromium.chrome.browser.compositor.layouts.components.TintedCompositorButton; import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutView.StripLayoutViewOnClickHandler; import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutView.StripLayoutViewOnKeyboardFocusHandler; @@ -185,6 +186,7 @@ @Mock private StripTabHoverCardView mTabHoverCardView; @Mock private Profile mProfile; @Mock private StripLayoutViewOnClickHandler mClickHandler; + @Mock private TooltipHandler mTooltipHandler; @Mock private StripLayoutViewOnKeyboardFocusHandler mKeyboardFocusHandler; @Mock private TabDragSource mTabDragSource; @Mock private WindowAndroid mWindowAndroid; @@ -1443,6 +1445,7 @@ tab, 24.f, 24.f, + mTooltipHandler, mClickHandler, mKeyboardFocusHandler, R.drawable.btn_tab_close_normal, @@ -1480,6 +1483,7 @@ tabs[0], 24.f, 24.f, + mTooltipHandler, mClickHandler, mKeyboardFocusHandler, R.drawable.btn_tab_close_normal,
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/TooltipManagerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/TooltipManagerUnitTest.java deleted file mode 100644 index cc6238e57..0000000 --- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/TooltipManagerUnitTest.java +++ /dev/null
@@ -1,134 +0,0 @@ -// Copyright 2025 The Chromium Authors -// 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.compositor.overlays.strip; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.when; -import static org.robolectric.Robolectric.buildActivity; - -import android.app.Activity; -import android.content.Context; -import android.view.View; -import android.widget.FrameLayout; -import android.widget.TextView; - -import org.junit.Before; -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.robolectric.annotation.Config; - -import org.chromium.base.test.BaseRobolectricTestRunner; -import org.chromium.chrome.R; -import org.chromium.chrome.browser.compositor.layouts.components.CompositorButton; - -/** Unit tests for {@link TooltipManager}. */ -@RunWith(BaseRobolectricTestRunner.class) -@Config(manifest = Config.NONE, qualifiers = "w640dp-h360dp") -public class TooltipManagerUnitTest { - - @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); - - @Mock private CompositorButton mButton; - - private TooltipManager mTooltipManager; - private FrameLayout mTooltipView; - private Context mContext; - - @Before - public void setUp() { - Activity activity = buildActivity(Activity.class).setup().get(); - activity.setTheme(R.style.Theme_BrowserUI_DayNight); - mTooltipView = - (FrameLayout) - activity.getLayoutInflater() - .inflate(R.layout.tab_strip_tooltip_holder, null); - mTooltipManager = new TooltipManager(mTooltipView, () -> 0f); - - mContext = mTooltipView.getContext(); - mContext.getResources().getDisplayMetrics().density = 1f; - } - - @Test - public void showAndHide() { - when(mButton.getAccessibilityDescription()).thenReturn("The button description"); - when(mButton.getDrawX()).thenReturn(100f); - when(mButton.getDrawY()).thenReturn(100f); - when(mButton.getWidth()).thenReturn(100f); - when(mButton.getHeight()).thenReturn(100f); - - mTooltipManager.showImmediatelyFor(mButton); - assertEquals( - "|mTooltipView| should be visible.", View.VISIBLE, mTooltipView.getVisibility()); - - mTooltipManager.hideImmediately(); - assertEquals("|mTooltipView| should be gone.", View.GONE, mTooltipView.getVisibility()); - } - - @Test - public void correctText() { - when(mButton.getAccessibilityDescription()).thenReturn("The button description"); - when(mButton.getDrawX()).thenReturn(100f); - when(mButton.getDrawY()).thenReturn(100f); - when(mButton.getWidth()).thenReturn(100f); - when(mButton.getHeight()).thenReturn(100f); - - mTooltipManager.showImmediatelyFor(mButton); - - assertEquals( - "|mTooltipView| should be visible.", View.VISIBLE, mTooltipView.getVisibility()); - assertEquals( - "Tooltip text is incorrect.", - mButton.getAccessibilityDescription(), - ((TextView) mTooltipView.findViewById(R.id.tooltip_label)).getText()); - } - - private void testCorrectPosition() { - assertEquals( - "|mTooltipView| should be visible.", View.VISIBLE, mTooltipView.getVisibility()); - assertTrue( - "|mTooltipView| should not cross the left window border.", - mTooltipView.getX() >= 0f); - assertTrue( - "|mTooltipView| should not cross the right window border.", - mTooltipView.getX() + mTooltipView.getWidth() <= 640f); - assertTrue( - "|mTooltipView| should not cross the top window border.", - mTooltipView.getY() >= 0f); - assertTrue( - "|mTooltipView| should not cross the bottom window border.", - mTooltipView.getY() + mTooltipView.getHeight() <= 360f); - } - - @Test - public void tooltipStaysInTheWindowLeftBound() { - when(mButton.getAccessibilityDescription()).thenReturn("A very long button description"); - when(mButton.getDrawX()).thenReturn(0f); - when(mButton.getDrawY()).thenReturn(0f); - when(mButton.getWidth()).thenReturn(10f); - when(mButton.getHeight()).thenReturn(10f); - - mTooltipManager.showImmediatelyFor(mButton); - - testCorrectPosition(); - } - - @Test - public void tooltipStaysInTheWindowRightBound() { - when(mButton.getAccessibilityDescription()).thenReturn("A very long button description"); - when(mButton.getDrawX()).thenReturn(630f); - when(mButton.getDrawY()).thenReturn(0f); - when(mButton.getWidth()).thenReturn(10f); - when(mButton.getHeight()).thenReturn(10f); - - mTooltipManager.showImmediatelyFor(mButton); - - testCorrectPosition(); - } -}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayerTest.java index 958e4f0..7bb57dc6 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayerTest.java
@@ -42,6 +42,7 @@ import org.chromium.chrome.browser.compositor.layouts.LayoutUpdateHost; import org.chromium.chrome.browser.compositor.layouts.components.CompositorButton; import org.chromium.chrome.browser.compositor.layouts.components.CompositorButton.ButtonType; +import org.chromium.chrome.browser.compositor.layouts.components.CompositorButton.TooltipHandler; import org.chromium.chrome.browser.compositor.layouts.components.TintedCompositorButton; import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutGroupTitle; import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutHelperManager; @@ -63,6 +64,7 @@ @Mock private ResourceManager mResourceManager; @Mock private LayerTitleCache mLayerTitleCache; @Mock private SceneLayer mSceneLayer; + @Mock private TooltipHandler mTooltipHandler; @Mock private StripLayoutViewOnClickHandler mOnClickHandler; @Mock private StripLayoutViewOnKeyboardFocusHandler mKeyboardFocusHandler; @Mock private TabLoadTrackerCallback mTabLoadTrackerCallback; @@ -109,6 +111,7 @@ null, 32.f, 32.f, + mTooltipHandler, mOnClickHandler, mKeyboardFocusHandler, R.drawable.ic_incognito, @@ -120,6 +123,7 @@ null, 32.f, 32.f, + mTooltipHandler, mOnClickHandler, mKeyboardFocusHandler, R.drawable.ic_new_tab_button,
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedMediatorUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedMediatorUnitTest.java index e2768139..dc96589 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedMediatorUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedMediatorUnitTest.java
@@ -37,7 +37,10 @@ import org.robolectric.annotation.Config; import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.base.test.util.Features.DisableFeatures; +import org.chromium.base.test.util.Features.EnableFeatures; import org.chromium.chrome.R; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.native_page.ContextMenuManager; import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; import org.chromium.chrome.browser.profiles.Profile; @@ -163,7 +166,18 @@ } @Test - public void testMvtContainerOnTileCountChanged() { + @DisableFeatures({ChromeFeatureList.MOST_VISITED_TILES_CUSTOMIZATION}) + public void testMvtContainerOnTileCountChanged_DisableMvtCustomization() { + doTestMvtContainerOnTileCountChanged(); + } + + @Test + @EnableFeatures({ChromeFeatureList.MOST_VISITED_TILES_CUSTOMIZATION}) + public void testMvtContainerOnTileCountChanged_EndableMvtCustomization() { + doTestMvtContainerOnTileCountChanged(); + } + + private void doTestMvtContainerOnTileCountChanged() { ArrayList<SiteSuggestion> array = new ArrayList<>(); array.add(mData); mMostVisitedSites.setTileSuggestions(array); @@ -171,10 +185,16 @@ Assert.assertTrue(mModel.get(IS_CONTAINER_VISIBLE)); - // When there's no mv tile, the mv tiles container should be hidden. mMostVisitedSites.setTileSuggestions(new ArrayList<>()); mMediator.onTileCountChanged(); - Assert.assertFalse(mModel.get(IS_CONTAINER_VISIBLE)); + if (ChromeFeatureList.isEnabled(ChromeFeatureList.MOST_VISITED_TILES_CUSTOMIZATION)) { + // When there's no mv tile, the mv tiles container should show (with the "Add new" + // button). + Assert.assertTrue(mModel.get(IS_CONTAINER_VISIBLE)); + } else { + // When there's no mv tile, the mv tiles container should be hidden. + Assert.assertFalse(mModel.get(IS_CONTAINER_VISIBLE)); + } // When there is mv tile, the mv tiles container should be shown. mMostVisitedSites.setTileSuggestions(JUnitTestGURLs.HTTP_URL.getSpec());
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/BottomAttachedUiObserverTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/BottomAttachedUiObserverTest.java index 56195f1..8fbcc3d 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/BottomAttachedUiObserverTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/BottomAttachedUiObserverTest.java
@@ -98,9 +98,7 @@ @Mock private OverlayPanelStateProvider mOverlayPanelStateProvider; @Mock private BottomSheetController mBottomSheetController; - @Mock private BottomSheetContent mBottomSheetContentNullBackground; - @Mock private BottomSheetContent mBottomSheetContentYellowBackground; - @Mock private BottomSheetContent mBottomSheetContentCyanBackground; + @Mock private BottomSheetContent mSheetContent; @Mock private OmniboxSuggestionsVisualState mOmniboxSuggestionsVisualState; @@ -123,11 +121,7 @@ when(mContextualSearchManager.getOverlayPanelStateProviderSupplier()) .thenReturn(mOverlayPanelStateProviderSupplier); - when(mBottomSheetContentNullBackground.getBackgroundColor()).thenReturn(null); - when(mBottomSheetContentYellowBackground.getBackgroundColor()) - .thenReturn(BOTTOM_SHEET_YELLOW); - when(mBottomSheetContentCyanBackground.getBackgroundColor()).thenReturn(BOTTOM_SHEET_CYAN); - + doReturn(null).when(mBottomSheetController).getSheetBackgroundColor(); when(mBottomSheetController.isFullWidth()).thenReturn(true); when(mSnackbarManager.isFullWidth()).thenReturn(true); @@ -454,7 +448,8 @@ public void testAdaptsColorToBottomSheet() { doReturn(false).when(mBottomSheetController).isAnchoredToBottomControls(); - mBottomAttachedUiObserver.onSheetContentChanged(mBottomSheetContentNullBackground); + doReturn(null).when(mBottomSheetController).getSheetBackgroundColor(); + mBottomAttachedUiObserver.onSheetContentChanged(mSheetContent); mColorChangeObserver.assertState(null, false, false); mBottomAttachedUiObserver.onSheetOpened(0); @@ -462,18 +457,21 @@ mBottomAttachedUiObserver.onSheetClosed(0); mColorChangeObserver.assertState(null, false, false); - mBottomAttachedUiObserver.onSheetContentChanged(mBottomSheetContentCyanBackground); + doReturn(BOTTOM_SHEET_CYAN).when(mBottomSheetController).getSheetBackgroundColor(); + mBottomAttachedUiObserver.onSheetContentChanged(mSheetContent); mBottomAttachedUiObserver.onSheetOpened(0); mColorChangeObserver.assertState(BOTTOM_SHEET_CYAN, false, false); mBottomAttachedUiObserver.onSheetClosed(0); mColorChangeObserver.assertState(null, false, false); - mBottomAttachedUiObserver.onSheetContentChanged(mBottomSheetContentYellowBackground); + doReturn(BOTTOM_SHEET_YELLOW).when(mBottomSheetController).getSheetBackgroundColor(); + mBottomAttachedUiObserver.onSheetContentChanged(mSheetContent); mColorChangeObserver.assertState(null, false, false); mBottomAttachedUiObserver.onSheetOpened(0); mColorChangeObserver.assertState(BOTTOM_SHEET_YELLOW, false, false); - mBottomAttachedUiObserver.onSheetContentChanged(mBottomSheetContentCyanBackground); + doReturn(BOTTOM_SHEET_CYAN).when(mBottomSheetController).getSheetBackgroundColor(); + mBottomAttachedUiObserver.onSheetContentChanged(mSheetContent); mColorChangeObserver.assertState(BOTTOM_SHEET_CYAN, false, false); mBottomAttachedUiObserver.onSheetClosed(0); mColorChangeObserver.assertState(null, false, false); @@ -485,7 +483,8 @@ when(mBottomSheetController.isFullWidth()).thenReturn(false, false); when(mBottomControlsStacker.isLayerVisible(eq(LayerType.BOTTOM_CHIN))).thenReturn(false); - mBottomAttachedUiObserver.onSheetContentChanged(mBottomSheetContentYellowBackground); + doReturn(BOTTOM_SHEET_YELLOW).when(mBottomSheetController).getSheetBackgroundColor(); + mBottomAttachedUiObserver.onSheetContentChanged(mSheetContent); mColorChangeObserver.assertState(null, false, false); mBottomAttachedUiObserver.onSheetOpened(0); @@ -500,7 +499,8 @@ when(mBottomSheetController.isFullWidth()).thenReturn(false, false); when(mBottomControlsStacker.isLayerVisible(eq(LayerType.BOTTOM_CHIN))).thenReturn(true); - mBottomAttachedUiObserver.onSheetContentChanged(mBottomSheetContentYellowBackground); + doReturn(BOTTOM_SHEET_YELLOW).when(mBottomSheetController).getSheetBackgroundColor(); + mBottomAttachedUiObserver.onSheetContentChanged(mSheetContent); mColorChangeObserver.assertState(null, false, false); mBottomAttachedUiObserver.onSheetOpened(0); @@ -515,7 +515,8 @@ when(mBottomSheetController.isFullWidth()).thenReturn(false); when(mBottomControlsStacker.isLayerVisible(eq(LayerType.BOTTOM_CHIN))).thenReturn(false); - mBottomAttachedUiObserver.onSheetContentChanged(mBottomSheetContentYellowBackground); + doReturn(BOTTOM_SHEET_YELLOW).when(mBottomSheetController).getSheetBackgroundColor(); + mBottomAttachedUiObserver.onSheetContentChanged(mSheetContent); mColorChangeObserver.assertState(null, false, false); mBottomAttachedUiObserver.onSheetOpened(0); @@ -532,7 +533,8 @@ when(mBottomControlsStacker.hasVisibleLayersOtherThan(eq(LayerType.BOTTOM_CHIN))) .thenReturn(false); - mBottomAttachedUiObserver.onSheetContentChanged(mBottomSheetContentYellowBackground); + doReturn(BOTTOM_SHEET_YELLOW).when(mBottomSheetController).getSheetBackgroundColor(); + mBottomAttachedUiObserver.onSheetContentChanged(mSheetContent); mColorChangeObserver.assertColor(null).assertForceShowDivider(false); mBottomAttachedUiObserver.onSheetOpened(0); @@ -549,7 +551,8 @@ when(mBottomControlsStacker.hasVisibleLayersOtherThan(eq(LayerType.BOTTOM_CHIN))) .thenReturn(false); - mBottomAttachedUiObserver.onSheetContentChanged(mBottomSheetContentYellowBackground); + doReturn(BOTTOM_SHEET_YELLOW).when(mBottomSheetController).getSheetBackgroundColor(); + mBottomAttachedUiObserver.onSheetContentChanged(mSheetContent); mColorChangeObserver.assertColor(null).assertForceShowDivider(false); mBottomAttachedUiObserver.onSheetOpened(0); @@ -566,7 +569,8 @@ when(mBottomControlsStacker.hasVisibleLayersOtherThan(eq(LayerType.BOTTOM_CHIN))) .thenReturn(true); - mBottomAttachedUiObserver.onSheetContentChanged(mBottomSheetContentYellowBackground); + doReturn(BOTTOM_SHEET_YELLOW).when(mBottomSheetController).getSheetBackgroundColor(); + mBottomAttachedUiObserver.onSheetContentChanged(mSheetContent); mColorChangeObserver.assertColor(null).assertForceShowDivider(false); mBottomAttachedUiObserver.onSheetOpened(0); @@ -583,7 +587,8 @@ when(mBottomControlsStacker.hasVisibleLayersOtherThan(eq(LayerType.BOTTOM_CHIN))) .thenReturn(false); - mBottomAttachedUiObserver.onSheetContentChanged(mBottomSheetContentYellowBackground); + doReturn(BOTTOM_SHEET_YELLOW).when(mBottomSheetController).getSheetBackgroundColor(); + mBottomAttachedUiObserver.onSheetContentChanged(mSheetContent); mColorChangeObserver.assertColor(null).assertForceShowDivider(false); mBottomAttachedUiObserver.onSheetOpened(0); @@ -600,7 +605,8 @@ when(mBottomControlsStacker.hasVisibleLayersOtherThan(eq(LayerType.BOTTOM_CHIN))) .thenReturn(false); - mBottomAttachedUiObserver.onSheetContentChanged(mBottomSheetContentYellowBackground); + doReturn(BOTTOM_SHEET_YELLOW).when(mBottomSheetController).getSheetBackgroundColor(); + mBottomAttachedUiObserver.onSheetContentChanged(mSheetContent); mColorChangeObserver.assertColor(null).assertForceShowDivider(false); mBottomAttachedUiObserver.onSheetOpened(0); @@ -617,7 +623,8 @@ when(mBottomControlsStacker.hasVisibleLayersOtherThan(eq(LayerType.BOTTOM_CHIN))) .thenReturn(true); - mBottomAttachedUiObserver.onSheetContentChanged(mBottomSheetContentYellowBackground); + doReturn(BOTTOM_SHEET_YELLOW).when(mBottomSheetController).getSheetBackgroundColor(); + mBottomAttachedUiObserver.onSheetContentChanged(mSheetContent); mColorChangeObserver.assertColor(null).assertForceShowDivider(false); mBottomAttachedUiObserver.onSheetOpened(0); @@ -742,7 +749,8 @@ mColorChangeObserver.assertState(OVERLAY_PANEL_COLOR, false, false); // Show bottom sheet. - mBottomAttachedUiObserver.onSheetContentChanged(mBottomSheetContentYellowBackground); + doReturn(BOTTOM_SHEET_YELLOW).when(mBottomSheetController).getSheetBackgroundColor(); + mBottomAttachedUiObserver.onSheetContentChanged(mSheetContent); mBottomAttachedUiObserver.onSheetOpened(0); mColorChangeObserver.assertState(BOTTOM_SHEET_YELLOW, false, false); @@ -806,13 +814,15 @@ mBottomAttachedUiObserver.onOverlayPanelStateChanged( OverlayPanel.PanelState.PEEKED, OVERLAY_PANEL_COLOR); - mBottomAttachedUiObserver.onSheetContentChanged(mBottomSheetContentYellowBackground); + doReturn(BOTTOM_SHEET_YELLOW).when(mBottomSheetController).getSheetBackgroundColor(); + mBottomAttachedUiObserver.onSheetContentChanged(mSheetContent); mBottomAttachedUiObserver.onSheetOpened(0); mColorChangeObserver.assertState(BROWSER_CONTROLS_COLOR, false, false); doReturn(1.0f).when(mBrowserControlsStateProvider).getBrowserControlHiddenRatio(); - mBottomAttachedUiObserver.onSheetContentChanged(mBottomSheetContentYellowBackground); + doReturn(BOTTOM_SHEET_YELLOW).when(mBottomSheetController).getSheetBackgroundColor(); + mBottomAttachedUiObserver.onSheetContentChanged(mSheetContent); mBottomAttachedUiObserver.onSheetOpened(0); mColorChangeObserver.assertState(BOTTOM_SHEET_YELLOW, false, false); @@ -868,7 +878,7 @@ }) @DisableFeatures({ChromeFeatureList.EDGE_TO_EDGE_BOTTOM_CHIN}) public void testNavBarColorAnimationsBottomSheet() { - mBottomAttachedUiObserver.onSheetContentChanged(mBottomSheetContentNullBackground); + mBottomAttachedUiObserver.onSheetContentChanged(mSheetContent); mColorChangeObserver.assertState(null, false, false); mBottomAttachedUiObserver.onSheetOpened(0); @@ -876,7 +886,8 @@ mBottomAttachedUiObserver.onSheetClosed(0); mColorChangeObserver.assertState(null, false, false); - mBottomAttachedUiObserver.onSheetContentChanged(mBottomSheetContentCyanBackground); + doReturn(BOTTOM_SHEET_CYAN).when(mBottomSheetController).getSheetBackgroundColor(); + mBottomAttachedUiObserver.onSheetContentChanged(mSheetContent); mBottomAttachedUiObserver.onSheetOpened(0); // Nav bar color animations disabled on appearance. mColorChangeObserver.assertState(BOTTOM_SHEET_CYAN, false, true);
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 10ff525..af31e4e 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -3769,26 +3769,6 @@ {" - all windowing modes", kAuxiliaryNavigationStaysInBrowserOn, std::size(kAuxiliaryNavigationStaysInBrowserOn), nullptr}}; -const FeatureEntry::FeatureParam kShowNewTabAnimationsBounce[] = { - {"version", "1"}}; -const FeatureEntry::FeatureParam kShowNewTabAnimationsDecelerate[] = { - {"version", "2"}}; -const FeatureEntry::FeatureParam kShowNewTabAnimationsBounceDecelerate[] = { - {"version", "3"}}; -const FeatureEntry::FeatureParam kShowNewTabAnimationsM137[] = { - {"version", "0"}}; -const FeatureEntry::FeatureVariation kShowNewTabAnimationsVariations[] = { - {"- Bouncy GTS icon with delay", kShowNewTabAnimationsBounce, - std::size(kShowNewTabAnimationsBounce), nullptr}, - {"- Bouncy GTS icon with decelerate arc", - kShowNewTabAnimationsBounceDecelerate, - std::size(kShowNewTabAnimationsBounceDecelerate), nullptr}, - {"- Decelerate arc", kShowNewTabAnimationsDecelerate, - std::size(kShowNewTabAnimationsDecelerate), nullptr}, - {"- M137 with new duration", kShowNewTabAnimationsM137, - std::size(kShowNewTabAnimationsM137), nullptr}, -}; - #endif // BUILDFLAG(IS_ANDROID) #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || \ @@ -4245,25 +4225,6 @@ {"with password manager heuristics", kSensitiveContentUsePwmHeuristics, std::size(kSensitiveContentUsePwmHeuristics), nullptr}, }; - -const FeatureEntry::FeatureParam kAndroidHubEnableBookmarks[] = { - {"enable_bookmark_provider", "true"}}; -const FeatureEntry::FeatureParam kAndroidHubEnableHistory[] = { - {"enable_history_provider", "true"}}; -const FeatureEntry::FeatureParam kAndroidHubEnableAllExtraProviders[] = { - {"enable_bookmark_provider", "true"}, - {"enable_history_provider", "true"}}; -const FeatureEntry::FeatureParam kAndroidHubEnableEnterToSearch[] = { - {"enable_press_enter_to_search", "true"}}; -const FeatureEntry::FeatureVariation kAndroidHubSearchVariations[] = { - {"with bookmarks", kAndroidHubEnableBookmarks, - std::size(kAndroidHubEnableBookmarks), nullptr}, - {"with history", kAndroidHubEnableHistory, - std::size(kAndroidHubEnableHistory), nullptr}, - {"with all extra providers", kAndroidHubEnableAllExtraProviders, - std::size(kAndroidHubEnableAllExtraProviders), nullptr}, - {"with pressing enter to search", kAndroidHubEnableEnterToSearch, - std::size(kAndroidHubEnableEnterToSearch), nullptr}}; #endif // BUILDFLAG(IS_ANDROID) // Feature variations for kSubframeProcessReuseThresholds. @@ -6762,8 +6723,7 @@ {"omnibox-show-popup-on-mouse-released", flag_descriptions::kOmniboxShowPopupOnMouseReleasedName, - flag_descriptions::kOmniboxShowPopupOnMouseReleasedDescription, - kOsDesktop, + flag_descriptions::kOmniboxShowPopupOnMouseReleasedDescription, kOsDesktop, FEATURE_VALUE_TYPE(omnibox::kShowPopupOnMouseReleased)}, {"omnibox-hide-suggestion-group-headers", @@ -7685,9 +7645,7 @@ {"show-new-tab-animations", flag_descriptions::kShowNewTabAnimationsName, flag_descriptions::kShowNewTabAnimationsDescription, kOsAndroid, - FEATURE_WITH_PARAMS_VALUE_TYPE(chrome::android::kShowNewTabAnimations, - kShowNewTabAnimationsVariations, - "ShowNewTabAnimations")}, + FEATURE_VALUE_TYPE(chrome::android::kShowNewTabAnimations)}, {"tab-switcher-color-blend-animate", flag_descriptions::kTabSwitcherColorBlendAnimateName, @@ -10577,11 +10535,6 @@ FEATURE_VALUE_TYPE(blink::features::kObservableAPI)}, #if BUILDFLAG(IS_ANDROID) - {"android-hub-search", flag_descriptions::kAndroidHubSearchName, - flag_descriptions::kAndroidHubSearchDescription, kOsAndroid, - FEATURE_WITH_PARAMS_VALUE_TYPE(omnibox::kAndroidHubSearch, - kAndroidHubSearchVariations, - "AndroidHubSearch")}, {"android-hub-search-tab-groups", flag_descriptions::kAndroidHubSearchTabGroupsName, flag_descriptions::kAndroidHubSearchTabGroupsDescription, kOsAndroid,
diff --git a/chrome/browser/ash/arc/screen_capture/arc_screen_capture_bridge.cc b/chrome/browser/ash/arc/screen_capture/arc_screen_capture_bridge.cc index 25358420..ad6e500a 100644 --- a/chrome/browser/ash/arc/screen_capture/arc_screen_capture_bridge.cc +++ b/chrome/browser/ash/arc/screen_capture/arc_screen_capture_bridge.cc
@@ -13,11 +13,13 @@ #include "base/memory/singleton.h" #include "base/strings/utf_string_conversions.h" #include "base/system/sys_info.h" +#include "base/types/expected.h" #include "chrome/browser/ash/arc/screen_capture/arc_screen_capture_session.h" #include "chrome/browser/media/webrtc/desktop_media_list_ash.h" #include "chromeos/ash/experiences/arc/arc_browser_context_keyed_service_factory_base.h" #include "chromeos/ash/experiences/arc/session/arc_bridge_service.h" #include "content/public/browser/browser_thread.h" +#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h" #include "ui/base/mojom/ui_base_types.mojom-shared.h" namespace { @@ -124,18 +126,24 @@ void ArcScreenCaptureBridge::PermissionPromptCallback( const std::string& package_name, - content::DesktopMediaID desktop_id) { + base::expected<content::DesktopMediaID, + blink::mojom::MediaStreamRequestResult> result) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + auto found = pending_permissions_map_.find(package_name); if (found == pending_permissions_map_.end()) { // This is normal if the dialog was accepted from testing. return; } - if (desktop_id.is_null()) { + + if (!result.has_value() || result.value().is_null()) { std::move(found->second.callback).Run(false); pending_permissions_map_.erase(found); return; } + + const content::DesktopMediaID desktop_id = result.value(); + // Remove any existing entry since emplace will not overwrite it. // This is OK since these persist forever and this may be requested again with // a different desktop.
diff --git a/chrome/browser/ash/arc/screen_capture/arc_screen_capture_bridge.h b/chrome/browser/ash/arc/screen_capture/arc_screen_capture_bridge.h index 739259ff..7104bdc 100644 --- a/chrome/browser/ash/arc/screen_capture/arc_screen_capture_bridge.h +++ b/chrome/browser/ash/arc/screen_capture/arc_screen_capture_bridge.h
@@ -10,10 +10,12 @@ #include <unordered_map> #include "base/memory/raw_ptr.h" +#include "base/types/expected.h" #include "chrome/browser/media/webrtc/desktop_media_picker.h" #include "chromeos/ash/experiences/arc/mojom/screen_capture.mojom.h" #include "components/keyed_service/core/keyed_service.h" #include "content/public/browser/desktop_media_id.h" +#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h" namespace content { class BrowserContext; @@ -75,8 +77,10 @@ const bool enable_notification; }; - void PermissionPromptCallback(const std::string& package_name, - content::DesktopMediaID desktop_id); + void PermissionPromptCallback( + const std::string& package_name, + base::expected<content::DesktopMediaID, + blink::mojom::MediaStreamRequestResult> result); const raw_ptr<ArcBridgeService> arc_bridge_service_; // Owned by ArcServiceManager.
diff --git a/chrome/browser/ash/browser_delegate/browser_controller_impl.cc b/chrome/browser/ash/browser_delegate/browser_controller_impl.cc index 78aad1f..1dd05f2 100644 --- a/chrome/browser/ash/browser_delegate/browser_controller_impl.cc +++ b/chrome/browser/ash/browser_delegate/browser_controller_impl.cc
@@ -70,7 +70,7 @@ BrowserDelegate* BrowserControllerImpl::GetLastUsedVisibleBrowser() { for (Browser* browser : BrowserList::GetInstance()->OrderedByActivation()) { - if (browser->window()->GetNativeWindow()->IsVisible()) { + if (browser->window()->IsVisible()) { return GetDelegate(browser); } }
diff --git a/chrome/browser/chromeos/app_mode/BUILD.gn b/chrome/browser/chromeos/app_mode/BUILD.gn index 31c5af8..6aae5e0 100644 --- a/chrome/browser/chromeos/app_mode/BUILD.gn +++ b/chrome/browser/chromeos/app_mode/BUILD.gn
@@ -54,6 +54,7 @@ "//base", "//build:buildflag_header_h", "//chrome/browser:browser_public_dependencies", + "//chrome/browser/apps/app_service/publishers/proto", "//chrome/browser/profiles:profile", "//chrome/browser/ui:browser_list", "//chrome/browser/web_applications",
diff --git a/chrome/browser/component_updater/iwa_key_distribution_component_installer.cc b/chrome/browser/component_updater/iwa_key_distribution_component_installer.cc index 5b75c09..05a77f9 100644 --- a/chrome/browser/component_updater/iwa_key_distribution_component_installer.cc +++ b/chrome/browser/component_updater/iwa_key_distribution_component_installer.cc
@@ -163,10 +163,6 @@ << " in " << install_dir; web_app::IwaKeyDistributionInfoProvider& info_provider = CHECK_DEREF(web_app::IwaKeyDistributionInfoProvider::GetInstance()); - if (IsOnDemandUpdateSupported()) { - info_provider.SetUp(base::BindRepeating( - &IwaKeyDistributionComponentInstallerPolicy::QueueOnDemandUpdate)); - } info_provider.LoadKeyDistributionData( version, install_dir.Append(kDataFileName), /*is_preloaded=*/manifest.FindBool(kPreloadedKey).value_or(false)); @@ -205,6 +201,14 @@ return; } + // `RegisterIwaKeyDistributionComponent` is effectively called before the user + // profile is created. Hence we can avoid eventual initialization race + // conditions for user sessions. + web_app::IwaKeyDistributionInfoProvider::GetInstance()->SetUp( + IsOnDemandUpdateSupported(), + base::BindRepeating( + &IwaKeyDistributionComponentInstallerPolicy::QueueOnDemandUpdate)); + base::MakeRefCounted<ComponentInstaller>( std::make_unique<IwaKeyDistributionComponentInstallerPolicy>()) ->Register(cus, base::DoNothing());
diff --git a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorTabSheetContent.java b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorTabSheetContent.java index 5f907175..cfde892 100644 --- a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorTabSheetContent.java +++ b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorTabSheetContent.java
@@ -278,8 +278,8 @@ } @Override - public @Nullable Integer getBackgroundColor() { - return null; + public boolean hasSolidBackgroundColor() { + return false; } @Override
diff --git a/chrome/browser/device/android/java/src/org/chromium/chrome/browser/device/DeviceClassManager.java b/chrome/browser/device/android/java/src/org/chromium/chrome/browser/device/DeviceClassManager.java index aca3e756..e87e09d 100644 --- a/chrome/browser/device/android/java/src/org/chromium/chrome/browser/device/DeviceClassManager.java +++ b/chrome/browser/device/android/java/src/org/chromium/chrome/browser/device/DeviceClassManager.java
@@ -9,6 +9,7 @@ import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.flags.ChromeSwitches; +import org.chromium.ui.util.XrUtils; /** * This class is used to turn on and off certain features for different types of @@ -53,7 +54,10 @@ // Flag based configurations. CommandLine commandLine = CommandLine.getInstance(); - mEnableFullscreen = !commandLine.hasSwitch(ChromeSwitches.DISABLE_FULLSCREEN); + // To provide a desktop like behavior on an immersive XR device the full screen mode is + // disabled on the browser. It is also not controlled by the command line argument. + mEnableFullscreen = + !XrUtils.isXrDevice() && !commandLine.hasSwitch(ChromeSwitches.DISABLE_FULLSCREEN); } /**
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn index 4310de0..86dd994 100644 --- a/chrome/browser/extensions/BUILD.gn +++ b/chrome/browser/extensions/BUILD.gn
@@ -529,6 +529,8 @@ "api/identity/identity_unimplemented_functions_android.cc", "api/identity/identity_unimplemented_functions_android.h", "api/management/chrome_management_api_delegate_android.cc", + "api/tabs/tabs_api_stub.cc", + "api/tabs/tabs_api_stub.h", "extension_disabled_ui_android.cc", "extension_error_ui_android.cc", "extension_error_ui_android.h",
diff --git a/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc b/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc index e49015b..25b2cd9 100644 --- a/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc +++ b/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc
@@ -9,6 +9,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" +#include "base/types/expected.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/extensions/api/desktop_capture/desktop_capture_api.h" @@ -25,6 +26,7 @@ #include "extensions/test/test_extension_dir.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" +#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h" #include "third_party/webrtc/modules/desktop_capture/desktop_capture_types.h" #include "ui/base/ozone_buildflags.h" @@ -32,10 +34,11 @@ namespace { -using content::DesktopMediaID; -using content::WebContentsMediaCaptureId; -using testing::Combine; -using testing::Values; +using ::blink::mojom::MediaStreamRequestResult; +using ::content::DesktopMediaID; +using ::content::WebContentsMediaCaptureId; +using ::testing::Combine; +using ::testing::Values; class DesktopCaptureApiTest : public ExtensionApiTest { public: @@ -86,78 +89,86 @@ // Each element in the following array corresponds to one test in // chrome/test/data/extensions/api_test/desktop_capture/test.js . FakeDesktopMediaPickerFactory::TestFlags test_flags[] = { - // pickerUiCanceled() - {.expect_screens = true, .expect_windows = true}, - // chooseMedia() - {.expect_screens = true, - .expect_windows = true, - .selected_source = - DesktopMediaID(DesktopMediaID::TYPE_SCREEN, DesktopMediaID::kNullId)}, - // screensOnly() - {.expect_screens = true}, - // WindowsOnly() - {.expect_windows = true}, - // tabOnly() - {.expect_tabs = true}, - // audioShareNoApproval() - {.expect_screens = true, - .expect_windows = true, - .expect_tabs = true, - .expect_audio = true, - .selected_source = - DesktopMediaID(DesktopMediaID::TYPE_WEB_CONTENTS, 123, false)}, - // audioShareApproval() - {.expect_screens = true, - .expect_windows = true, - .expect_tabs = true, - .expect_audio = true, - .selected_source = - DesktopMediaID(DesktopMediaID::TYPE_WEB_CONTENTS, 123, true)}, - // chooseMediaAndGetStream() - {.expect_screens = true, - .expect_windows = true, - .selected_source = DesktopMediaID(DesktopMediaID::TYPE_SCREEN, + // pickerUiCanceled() + {.expect_screens = true, + .expect_windows = true, + .picker_result = base::unexpected( + MediaStreamRequestResult::PERMISSION_DENIED_BY_USER)}, + // chooseMedia() + {.expect_screens = true, + .expect_windows = true, + .picker_result = DesktopMediaID(DesktopMediaID::TYPE_SCREEN, + DesktopMediaID::kNullId)}, + // screensOnly() + {.expect_screens = true, + .picker_result = DesktopMediaID(DesktopMediaID::TYPE_SCREEN, + DesktopMediaID::kNullId)}, + // WindowsOnly() + {.expect_windows = true, + .picker_result = DesktopMediaID(DesktopMediaID::TYPE_WINDOW, + DesktopMediaID::kFakeId)}, + // tabOnly() + {.expect_tabs = true, + .picker_result = DesktopMediaID(DesktopMediaID::TYPE_WEB_CONTENTS, 123)}, + // audioShareNoApproval() + {.expect_screens = true, + .expect_windows = true, + .expect_tabs = true, + .expect_audio = true, + .picker_result = + DesktopMediaID(DesktopMediaID::TYPE_WEB_CONTENTS, 123, false)}, + // audioShareApproval() + {.expect_screens = true, + .expect_windows = true, + .expect_tabs = true, + .expect_audio = true, + .picker_result = + DesktopMediaID(DesktopMediaID::TYPE_WEB_CONTENTS, 123, true)}, + // chooseMediaAndGetStream() + {.expect_screens = true, + .expect_windows = true, + .picker_result = DesktopMediaID(DesktopMediaID::TYPE_SCREEN, webrtc::kFullDesktopScreenId)}, - // chooseMediaAndTryGetStreamWithInvalidId() - {.expect_screens = true, - .expect_windows = true, - .selected_source = DesktopMediaID(DesktopMediaID::TYPE_SCREEN, + // chooseMediaAndTryGetStreamWithInvalidId() + {.expect_screens = true, + .expect_windows = true, + .picker_result = DesktopMediaID(DesktopMediaID::TYPE_SCREEN, webrtc::kFullDesktopScreenId)}, - // cancelDialog() - {.expect_screens = true, .expect_windows = true, .cancelled = true}, + // cancelDialog() + {.expect_screens = true, .expect_windows = true, .cancelled = true}, // TODO(crbug.com/41366624): Test fails; invalid device IDs being generated. #if 0 // tabShareWithAudioPermissionGetStream() {.expect_tabs = true, .expect_audio = true, - .selected_source = MakeFakeWebContentsMediaId(true)}, + .picker_result = MakeFakeWebContentsMediaId(true)}, #endif - // windowShareWithAudioGetStream() - {.expect_windows = true, - .expect_audio = true, - .selected_source = DesktopMediaID(DesktopMediaID::TYPE_WINDOW, + // windowShareWithAudioGetStream() + {.expect_windows = true, + .expect_audio = true, + .picker_result = DesktopMediaID(DesktopMediaID::TYPE_WINDOW, DesktopMediaID::kFakeId, true)}, - // screenShareWithAudioGetStream() - {.expect_screens = true, - .expect_audio = true, - .selected_source = DesktopMediaID(DesktopMediaID::TYPE_SCREEN, + // screenShareWithAudioGetStream() + {.expect_screens = true, + .expect_audio = true, + .picker_result = DesktopMediaID(DesktopMediaID::TYPE_SCREEN, webrtc::kFullDesktopScreenId, true)}, // TODO(crbug.com/41366624): Test fails; invalid device IDs being generated. #if 0 // tabShareWithoutAudioPermissionGetStream() {.expect_tabs = true, .expect_audio = true, - .selected_source = MakeFakeWebContentsMediaId(false)}, + .picker_result = MakeFakeWebContentsMediaId(false)}, #endif - // windowShareWithoutAudioGetStream() - {.expect_windows = true, - .expect_audio = true, - .selected_source = - DesktopMediaID(DesktopMediaID::TYPE_WINDOW, DesktopMediaID::kFakeId)}, - // screenShareWithoutAudioGetStream() - {.expect_screens = true, - .expect_audio = true, - .selected_source = DesktopMediaID(DesktopMediaID::TYPE_SCREEN, + // windowShareWithoutAudioGetStream() + {.expect_windows = true, + .expect_audio = true, + .picker_result = DesktopMediaID(DesktopMediaID::TYPE_WINDOW, + DesktopMediaID::kFakeId)}, + // screenShareWithoutAudioGetStream() + {.expect_screens = true, + .expect_audio = true, + .picker_result = DesktopMediaID(DesktopMediaID::TYPE_SCREEN, webrtc::kFullDesktopScreenId)}, }; picker_factory_.SetTestFlags(test_flags, std::size(test_flags)); @@ -191,15 +202,15 @@ FakeDesktopMediaPickerFactory::TestFlags test_flags[] = { {.expect_screens = true, .expect_windows = true, - .selected_source = DesktopMediaID(DesktopMediaID::TYPE_SCREEN, - webrtc::kFullDesktopScreenId)}, + .picker_result = DesktopMediaID(DesktopMediaID::TYPE_SCREEN, + webrtc::kFullDesktopScreenId)}, {.expect_screens = true, .expect_windows = true, - .selected_source = DesktopMediaID(DesktopMediaID::TYPE_SCREEN, - DesktopMediaID::kNullId)}, + .picker_result = DesktopMediaID(DesktopMediaID::TYPE_SCREEN, + DesktopMediaID::kNullId)}, {.expect_screens = true, .expect_windows = true, - .selected_source = + .picker_result = DesktopMediaID(DesktopMediaID::TYPE_SCREEN, DesktopMediaID::kNullId), .cancelled = true}, }; @@ -308,8 +319,7 @@ browser(), GetURLForPath("localhost", "/test_file.html"))); FakeDesktopMediaPickerFactory::TestFlags test_flags[] = { - {.expect_tabs = true, - .selected_source = MakeFakeWebContentsMediaId(true)}, + {.expect_tabs = true, .picker_result = MakeFakeWebContentsMediaId(true)}, }; picker_factory_.SetTestFlags(test_flags, std::size(test_flags));
diff --git a/chrome/browser/extensions/api/tabs/tabs_api_stub.cc b/chrome/browser/extensions/api/tabs/tabs_api_stub.cc new file mode 100644 index 0000000..933be8c --- /dev/null +++ b/chrome/browser/extensions/api/tabs/tabs_api_stub.cc
@@ -0,0 +1,306 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/api/tabs/tabs_api_stub.h" + +#include "base/notimplemented.h" +#include "base/values.h" +#include "chrome/browser/extensions/extension_tab_util.h" +#include "chrome/browser/ui/android/tab_model/tab_model.h" +#include "chrome/browser/ui/android/tab_model/tab_model_list.h" +#include "url/gurl.h" + +namespace extensions { + +namespace windows = api::windows; +namespace tabs = api::tabs; + +namespace { + +constexpr char kNotImplemented[] = "Not implemented"; + +} // namespace + +// Windows --------------------------------------------------------------------- + +ExtensionFunction::ResponseAction WindowsGetFunction::Run() { + std::optional<windows::Get::Params> params = + windows::Get::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +ExtensionFunction::ResponseAction WindowsGetCurrentFunction::Run() { + std::optional<windows::GetCurrent::Params> params = + windows::GetCurrent::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +ExtensionFunction::ResponseAction WindowsGetLastFocusedFunction::Run() { + std::optional<windows::GetLastFocused::Params> params = + windows::GetLastFocused::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +ExtensionFunction::ResponseAction WindowsGetAllFunction::Run() { + std::optional<windows::GetAll::Params> params = + windows::GetAll::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +ExtensionFunction::ResponseAction WindowsCreateFunction::Run() { + std::optional<windows::Create::Params> params = + windows::Create::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +ExtensionFunction::ResponseAction WindowsUpdateFunction::Run() { + std::optional<windows::Update::Params> params = + windows::Update::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +ExtensionFunction::ResponseAction WindowsRemoveFunction::Run() { + std::optional<windows::Remove::Params> params = + windows::Remove::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +// Tabs ------------------------------------------------------------------------ + +ExtensionFunction::ResponseAction TabsGetSelectedFunction::Run() { + std::optional<tabs::GetSelected::Params> params = + tabs::GetSelected::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +ExtensionFunction::ResponseAction TabsGetAllInWindowFunction::Run() { + std::optional<tabs::GetAllInWindow::Params> params = + tabs::GetAllInWindow::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +ExtensionFunction::ResponseAction TabsQueryFunction::Run() { + std::optional<tabs::Query::Params> params = + tabs::Query::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + NOTIMPLEMENTED() << "Using stub implementation and returning active tab"; + base::Value::List result; + api::tabs::Tab tab_object; + // Always return the active tab in the current window. + for (TabModel* tab_model : TabModelList::models()) { + if (!tab_model->IsActiveModel()) { + continue; + } + auto* web_contents = tab_model->GetActiveWebContents(); + if (!web_contents) { + continue; + } + tab_object.id = ExtensionTabUtil::GetTabId(web_contents); + result.Append(tab_object.ToValue()); + return RespondNow(WithArguments(std::move(result))); + } + return RespondNow(Error("No active tab")); +} + +ExtensionFunction::ResponseAction TabsCreateFunction::Run() { + std::optional<tabs::Create::Params> params = + tabs::Create::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +ExtensionFunction::ResponseAction TabsDuplicateFunction::Run() { + std::optional<tabs::Duplicate::Params> params = + tabs::Duplicate::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +ExtensionFunction::ResponseAction TabsGetFunction::Run() { + std::optional<tabs::Get::Params> params = tabs::Get::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +ExtensionFunction::ResponseAction TabsGetCurrentFunction::Run() { + return RespondNow(Error(kNotImplemented)); +} + +ExtensionFunction::ResponseAction TabsHighlightFunction::Run() { + std::optional<tabs::Highlight::Params> params = + tabs::Highlight::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +TabsUpdateFunction::TabsUpdateFunction() = default; + +ExtensionFunction::ResponseAction TabsUpdateFunction::Run() { + std::optional<tabs::Update::Params> params = + tabs::Update::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +ExtensionFunction::ResponseAction TabsMoveFunction::Run() { + std::optional<tabs::Move::Params> params = tabs::Move::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +ExtensionFunction::ResponseAction TabsReloadFunction::Run() { + std::optional<tabs::Reload::Params> params = + tabs::Reload::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +TabsRemoveFunction::TabsRemoveFunction() = default; + +ExtensionFunction::ResponseAction TabsRemoveFunction::Run() { + std::optional<tabs::Remove::Params> params = + tabs::Remove::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +ExtensionFunction::ResponseAction TabsGroupFunction::Run() { + std::optional<tabs::Group::Params> params = + tabs::Group::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +ExtensionFunction::ResponseAction TabsUngroupFunction::Run() { + std::optional<tabs::Ungroup::Params> params = + tabs::Ungroup::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +TabsCaptureVisibleTabFunction::TabsCaptureVisibleTabFunction() = default; + +ExtensionFunction::ResponseAction TabsCaptureVisibleTabFunction::Run() { + EXTENSION_FUNCTION_VALIDATE(has_args()); + return RespondNow(Error(kNotImplemented)); +} + +ExtensionFunction::ResponseAction TabsDetectLanguageFunction::Run() { + std::optional<tabs::DetectLanguage::Params> params = + tabs::DetectLanguage::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +ExecuteCodeInTabFunction::ExecuteCodeInTabFunction() = default; + +ExecuteCodeInTabFunction::~ExecuteCodeInTabFunction() = default; + +ExecuteCodeFunction::InitResult ExecuteCodeInTabFunction::Init() { + NOTIMPLEMENTED(); + return set_init_result(VALIDATION_FAILURE); +} + +bool ExecuteCodeInTabFunction::ShouldInsertCSS() const { + return false; +} + +bool ExecuteCodeInTabFunction::ShouldRemoveCSS() const { + return false; +} + +bool ExecuteCodeInTabFunction::CanExecuteScriptOnPage(std::string* error) { + NOTIMPLEMENTED(); + return false; +} + +ScriptExecutor* ExecuteCodeInTabFunction::GetScriptExecutor( + std::string* error) { + NOTIMPLEMENTED(); + return nullptr; +} + +bool ExecuteCodeInTabFunction::IsWebView() const { + return false; +} + +int ExecuteCodeInTabFunction::GetRootFrameId() const { + NOTIMPLEMENTED(); + return ExtensionApiFrameIdMap::kTopFrameId; +} + +const GURL& ExecuteCodeInTabFunction::GetWebViewSrc() const { + NOTIMPLEMENTED(); + return GURL::EmptyGURL(); +} + +bool TabsInsertCSSFunction::ShouldInsertCSS() const { + return true; +} + +bool TabsRemoveCSSFunction::ShouldRemoveCSS() const { + return true; +} + +ExtensionFunction::ResponseAction TabsSetZoomFunction::Run() { + std::optional<tabs::SetZoom::Params> params = + tabs::SetZoom::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +ExtensionFunction::ResponseAction TabsGetZoomFunction::Run() { + std::optional<tabs::GetZoom::Params> params = + tabs::GetZoom::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +ExtensionFunction::ResponseAction TabsSetZoomSettingsFunction::Run() { + std::optional<tabs::SetZoomSettings::Params> params = + tabs::SetZoomSettings::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +ExtensionFunction::ResponseAction TabsGetZoomSettingsFunction::Run() { + std::optional<tabs::GetZoomSettings::Params> params = + tabs::GetZoomSettings::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +TabsDiscardFunction::TabsDiscardFunction() = default; + +ExtensionFunction::ResponseAction TabsDiscardFunction::Run() { + std::optional<tabs::Discard::Params> params = + tabs::Discard::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +ExtensionFunction::ResponseAction TabsGoForwardFunction::Run() { + std::optional<tabs::GoForward::Params> params = + tabs::GoForward::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +ExtensionFunction::ResponseAction TabsGoBackFunction::Run() { + std::optional<tabs::GoBack::Params> params = + tabs::GoBack::Params::Create(args()); + EXTENSION_FUNCTION_VALIDATE(params); + return RespondNow(Error(kNotImplemented)); +} + +} // namespace extensions
diff --git a/chrome/browser/extensions/api/tabs/tabs_api_stub.h b/chrome/browser/extensions/api/tabs/tabs_api_stub.h new file mode 100644 index 0000000..a42987f --- /dev/null +++ b/chrome/browser/extensions/api/tabs/tabs_api_stub.h
@@ -0,0 +1,253 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_EXTENSIONS_API_TABS_TABS_API_STUB_H_ +#define CHROME_BROWSER_EXTENSIONS_API_TABS_TABS_API_STUB_H_ + +#include "chrome/common/extensions/api/tabs.h" +#include "extensions/browser/api/execute_code_function.h" +#include "extensions/browser/extension_function.h" + +namespace extensions { + +// This file provides a stub implementation of the chrome.tabs and +// chrome.windows APIs. They are intended for desktop android bringup, as there +// are other APIs (e.g. cookies) that rely types from tabs and windows. + +// Windows +class WindowsGetFunction : public ExtensionFunction { + ~WindowsGetFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("windows.get", WINDOWS_GET) +}; +class WindowsGetCurrentFunction : public ExtensionFunction { + ~WindowsGetCurrentFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("windows.getCurrent", WINDOWS_GETCURRENT) +}; +class WindowsGetLastFocusedFunction : public ExtensionFunction { + ~WindowsGetLastFocusedFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("windows.getLastFocused", WINDOWS_GETLASTFOCUSED) +}; +class WindowsGetAllFunction : public ExtensionFunction { + ~WindowsGetAllFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("windows.getAll", WINDOWS_GETALL) +}; +class WindowsCreateFunction : public ExtensionFunction { + ~WindowsCreateFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("windows.create", WINDOWS_CREATE) +}; +class WindowsUpdateFunction : public ExtensionFunction { + ~WindowsUpdateFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("windows.update", WINDOWS_UPDATE) +}; +class WindowsRemoveFunction : public ExtensionFunction { + ~WindowsRemoveFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("windows.remove", WINDOWS_REMOVE) +}; + +// Tabs +class TabsGetFunction : public ExtensionFunction { + ~TabsGetFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("tabs.get", TABS_GET) +}; +class TabsGetCurrentFunction : public ExtensionFunction { + ~TabsGetCurrentFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("tabs.getCurrent", TABS_GETCURRENT) +}; +class TabsGetSelectedFunction : public ExtensionFunction { + ~TabsGetSelectedFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("tabs.getSelected", TABS_GETSELECTED) +}; +class TabsGetAllInWindowFunction : public ExtensionFunction { + ~TabsGetAllInWindowFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("tabs.getAllInWindow", TABS_GETALLINWINDOW) +}; +class TabsQueryFunction : public ExtensionFunction { + ~TabsQueryFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("tabs.query", TABS_QUERY) +}; +class TabsCreateFunction : public ExtensionFunction { + ~TabsCreateFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("tabs.create", TABS_CREATE) +}; +class TabsDuplicateFunction : public ExtensionFunction { + ~TabsDuplicateFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("tabs.duplicate", TABS_DUPLICATE) +}; +class TabsHighlightFunction : public ExtensionFunction { + ~TabsHighlightFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("tabs.highlight", TABS_HIGHLIGHT) +}; +class TabsUpdateFunction : public ExtensionFunction { + public: + TabsUpdateFunction(); + + private: + ~TabsUpdateFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("tabs.update", TABS_UPDATE) +}; +class TabsMoveFunction : public ExtensionFunction { + ~TabsMoveFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("tabs.move", TABS_MOVE) +}; +class TabsReloadFunction : public ExtensionFunction { + ~TabsReloadFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("tabs.reload", TABS_RELOAD) +}; +class TabsRemoveFunction : public ExtensionFunction { + public: + TabsRemoveFunction(); + + private: + ~TabsRemoveFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("tabs.remove", TABS_REMOVE) +}; +class TabsGroupFunction : public ExtensionFunction { + ~TabsGroupFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("tabs.group", TABS_GROUP) +}; +class TabsUngroupFunction : public ExtensionFunction { + ~TabsUngroupFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("tabs.ungroup", TABS_UNGROUP) +}; +class TabsDetectLanguageFunction : public ExtensionFunction { + private: + ~TabsDetectLanguageFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("tabs.detectLanguage", TABS_DETECTLANGUAGE) +}; +class TabsCaptureVisibleTabFunction : public ExtensionFunction { + public: + TabsCaptureVisibleTabFunction(); + + private: + ~TabsCaptureVisibleTabFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("tabs.captureVisibleTab", TABS_CAPTUREVISIBLETAB) +}; + +// Implement API calls tabs.executeScript, tabs.insertCSS, and tabs.removeCSS. +class ExecuteCodeInTabFunction : public ExecuteCodeFunction { + public: + ExecuteCodeInTabFunction(); + + protected: + ~ExecuteCodeInTabFunction() override; + + InitResult Init() override; + bool ShouldInsertCSS() const override; + bool ShouldRemoveCSS() const override; + bool CanExecuteScriptOnPage(std::string* error) override; + ScriptExecutor* GetScriptExecutor(std::string* error) override; + bool IsWebView() const override; + int GetRootFrameId() const override; + const GURL& GetWebViewSrc() const override; +}; + +class TabsExecuteScriptFunction : public ExecuteCodeInTabFunction { + private: + ~TabsExecuteScriptFunction() override = default; + + DECLARE_EXTENSION_FUNCTION("tabs.executeScript", TABS_EXECUTESCRIPT) +}; + +class TabsInsertCSSFunction : public ExecuteCodeInTabFunction { + private: + ~TabsInsertCSSFunction() override = default; + + bool ShouldInsertCSS() const override; + + DECLARE_EXTENSION_FUNCTION("tabs.insertCSS", TABS_INSERTCSS) +}; + +class TabsRemoveCSSFunction : public ExecuteCodeInTabFunction { + private: + ~TabsRemoveCSSFunction() override = default; + + bool ShouldRemoveCSS() const override; + + DECLARE_EXTENSION_FUNCTION("tabs.removeCSS", TABS_REMOVECSS) +}; + +class TabsSetZoomFunction : public ExtensionFunction { + private: + ~TabsSetZoomFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("tabs.setZoom", TABS_SETZOOM) +}; + +class TabsGetZoomFunction : public ExtensionFunction { + private: + ~TabsGetZoomFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("tabs.getZoom", TABS_GETZOOM) +}; + +class TabsSetZoomSettingsFunction : public ExtensionFunction { + private: + ~TabsSetZoomSettingsFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("tabs.setZoomSettings", TABS_SETZOOMSETTINGS) +}; + +class TabsGetZoomSettingsFunction : public ExtensionFunction { + private: + ~TabsGetZoomSettingsFunction() override = default; + ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("tabs.getZoomSettings", TABS_GETZOOMSETTINGS) +}; + +class TabsDiscardFunction : public ExtensionFunction { + public: + TabsDiscardFunction(); + + private: + ~TabsDiscardFunction() override = default; + ExtensionFunction::ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("tabs.discard", TABS_DISCARD) +}; + +class TabsGoForwardFunction : public ExtensionFunction { + public: + TabsGoForwardFunction() {} + + private: + ~TabsGoForwardFunction() override = default; + ExtensionFunction::ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("tabs.goForward", TABS_GOFORWARD) +}; + +class TabsGoBackFunction : public ExtensionFunction { + public: + TabsGoBackFunction() {} + + private: + ~TabsGoBackFunction() override = default; + ExtensionFunction::ResponseAction Run() override; + DECLARE_EXTENSION_FUNCTION("tabs.goBack", TABS_GOBACK) +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_API_TABS_TABS_API_STUB_H_
diff --git a/chrome/browser/extensions/extension_action_dispatcher.cc b/chrome/browser/extensions/extension_action_dispatcher.cc index 6cabb75..13bf726 100644 --- a/chrome/browser/extensions/extension_action_dispatcher.cc +++ b/chrome/browser/extensions/extension_action_dispatcher.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/extensions/extension_action_dispatcher.h" #include "base/lazy_instance.h" +#include "chrome/browser/extensions/extension_tab_util.h" #include "components/sessions/content/session_tab_helper.h" #include "components/sessions/core/session_id.h" #include "content/public/browser/web_contents.h" @@ -15,10 +16,6 @@ #include "extensions/browser/extension_prefs.h" #include "extensions/common/mojom/context_type.mojom.h" -#if BUILDFLAG(ENABLE_EXTENSIONS) -#include "chrome/browser/extensions/extension_tab_util.h" -#endif // BUILDFLAG(ENABLE_EXTENSIONS) - namespace extensions { static base::LazyInstance< @@ -63,7 +60,6 @@ const ExtensionAction& extension_action, content::WebContents* web_contents, const Extension* extension) { -#if BUILDFLAG(ENABLE_EXTENSIONS) events::HistogramValue histogram_value = events::UNKNOWN; const char* event_name = nullptr; switch (extension_action.action_type()) { @@ -99,11 +95,6 @@ extension_action.extension_id(), histogram_value, event_name, std::move(args)); } -#else - // TODO(crbug.com/393179880): Once we can create JS tab objects via - // ExtensionTabUtil::CreateTabObject() enable this method. - NOTIMPLEMENTED() << "Dispatching actions not yet supported on Android."; -#endif // BUILDFLAG(ENABLE_EXTENSIONS) } void ExtensionActionDispatcher::ClearAllValuesForTab(
diff --git a/chrome/browser/extensions/extension_tab_util.cc b/chrome/browser/extensions/extension_tab_util.cc index 959e848a..094aaacf 100644 --- a/chrome/browser/extensions/extension_tab_util.cc +++ b/chrome/browser/extensions/extension_tab_util.cc
@@ -21,7 +21,11 @@ #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" +#include "extensions/common/extension.h" #include "extensions/common/mojom/api_permission_id.mojom-shared.h" +#include "extensions/common/mojom/context_type.mojom.h" +#include "extensions/common/permissions/api_permission.h" +#include "extensions/common/permissions/permissions_data.h" #include "third_party/blink/public/common/chrome_debug_urls.h" #include "third_party/blink/public/common/features.h" @@ -76,14 +80,10 @@ #include "extensions/browser/extension_util.h" #include "extensions/common/constants.h" #include "extensions/common/error_utils.h" -#include "extensions/common/extension.h" #include "extensions/common/feature_switch.h" #include "extensions/common/manifest_constants.h" #include "extensions/common/manifest_handlers/incognito_info.h" #include "extensions/common/manifest_handlers/options_page_info.h" -#include "extensions/common/mojom/context_type.mojom.h" -#include "extensions/common/permissions/api_permission.h" -#include "extensions/common/permissions/permissions_data.h" #include "url/gurl.h" #include "url/url_constants.h" #endif @@ -94,10 +94,10 @@ namespace extensions { -#if !BUILDFLAG(IS_ANDROID) - namespace { +#if !BUILDFLAG(IS_ANDROID) + constexpr char kGroupNotFoundError[] = "No group with id: *."; constexpr char kInvalidUrlError[] = "Invalid url: \"*\"."; @@ -164,6 +164,7 @@ return url.SchemeIsFile() || (url.SchemeIs(content::kViewSourceScheme) && GURL(url.GetContent()).SchemeIsFile()); } +#endif // !BUILDFLAG(IS_ANDROID) ExtensionTabUtil::ScrubTabBehaviorType GetScrubTabBehaviorImpl( const Extension* extension, @@ -203,6 +204,7 @@ return ExtensionTabUtil::kDontScrubTab; } +#if !BUILDFLAG(IS_ANDROID) bool HasValidMainFrameProcess(content::WebContents* contents) { content::RenderFrameHost* main_frame_host = contents->GetPrimaryMainFrame(); content::RenderProcessHost* process_host = main_frame_host->GetProcess(); @@ -226,9 +228,11 @@ base::UmaHistogramEnumeration("Extensions.Navigation.Scheme", scheme); } +#endif // !BUILDFLAG(IS_ANDROID) } // namespace +#if !BUILDFLAG(IS_ANDROID) ExtensionTabUtil::OpenTabParams::OpenTabParams() = default; ExtensionTabUtil::OpenTabParams::~OpenTabParams() = default; @@ -469,6 +473,7 @@ std::string ExtensionTabUtil::GetBrowserWindowTypeText(const Browser& browser) { return WindowControllerFromBrowser(&browser)->GetWindowTypeText(); } +#endif // !BUILDFLAG(IS_ANDROID) // static api::tabs::Tab ExtensionTabUtil::CreateTabObject( @@ -477,6 +482,13 @@ const Extension* extension, TabStripModel* tab_strip, int tab_index) { +#if BUILDFLAG(IS_ANDROID) + NOTIMPLEMENTED() << "Using stub implementation of CreateTabObject"; + api::tabs::Tab tab_object; + tab_object.id = GetTabId(contents); + tab_object.index = tab_index; + return tab_object; +#else if (!tab_strip) ExtensionTabUtil::GetTabStripModel(contents, &tab_strip, &tab_index); api::tabs::Tab tab_object; @@ -558,8 +570,11 @@ ScrubTabForExtension(extension, contents, &tab_object, scrub_tab_behavior); return tab_object; +#endif } +#if !BUILDFLAG(IS_ANDROID) +// static base::Value::List ExtensionTabUtil::CreateTabList(const Browser* browser, const Extension* extension, mojom::ContextType context) { @@ -600,6 +615,7 @@ } return info; } +#endif // static ExtensionTabUtil::ScrubTabBehavior ExtensionTabUtil::GetScrubTabBehavior( @@ -666,6 +682,7 @@ } } +#if !BUILDFLAG(IS_ANDROID) // static bool ExtensionTabUtil::GetTabStripModel(const WebContents* web_contents, TabStripModel** tab_strip_model,
diff --git a/chrome/browser/extensions/extension_tab_util.h b/chrome/browser/extensions/extension_tab_util.h index 425b57d..af7411b 100644 --- a/chrome/browser/extensions/extension_tab_util.h +++ b/chrome/browser/extensions/extension_tab_util.h
@@ -86,6 +86,7 @@ "Cannot navigate to a file URL without local file access."; static constexpr char kTabsKey[] = "tabs"; +#endif // !BUILDFLAG(IS_ANDROID) enum ScrubTabBehaviorType { kScrubTabFully, @@ -98,6 +99,7 @@ ScrubTabBehaviorType pending_info; }; +#if !BUILDFLAG(IS_ANDROID) struct OpenTabParams { OpenTabParams(); ~OpenTabParams(); @@ -151,6 +153,7 @@ // Returns the tabs:: API constant for the window type of the `browser`. static std::string GetBrowserWindowTypeText(const Browser& browser); +#endif // !BUILDFLAG(IS_ANDROID) // Creates a Tab object (see chrome/common/extensions/api/tabs.json) with // information about the state of a browser tab for the given `web_contents`. @@ -170,7 +173,7 @@ const Extension* extension, TabStripModel* tab_strip, int tab_index); - +#if !BUILDFLAG(IS_ANDROID) // Creates a base::Value::Dict representing the window for the given // `browser`, and scrubs any privacy-sensitive data that `extension` does not // have access to. `populate_tab_behavior` determines whether tabs will be @@ -186,6 +189,7 @@ // Creates a tab MutedInfo object (see chrome/common/extensions/api/tabs.json) // with information about the mute state of a browser tab. static api::tabs::MutedInfo CreateMutedInfo(content::WebContents* contents); +#endif // !BUILDFLAG(IS_ANDROID) // Gets the level of scrubbing of tab data that needs to happen for a given // extension and web contents. This is the preferred way to get @@ -207,6 +211,7 @@ api::tabs::Tab* tab, ScrubTabBehavior scrub_tab_behavior); +#if !BUILDFLAG(IS_ANDROID) // Gets the `tab_strip_model` and `tab_index` for the given `web_contents`. static bool GetTabStripModel(const content::WebContents* web_contents, TabStripModel** tab_strip_model,
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 87bf79c..5db754a 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -243,11 +243,6 @@ "expiry_milestone": 137 }, { - "name": "android-hub-search", - "owners": [ "wylieb@google.com", "clank-tab-dev@google.com" ], - "expiry_milestone": 140 - }, - { "name": "android-hub-search-tab-groups", "owners": [ "wylieb@google.com", "clank-tab-dev@google.com" ], "expiry_milestone": 140
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 5513d38..b8f5065a 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -4637,10 +4637,6 @@ const char kAndroidElegantTextHeightDescription[] = "Enables elegant text height in core BrowserUI theme."; -const char kAndroidHubSearchName[] = "Android Hub Search"; -const char kAndroidHubSearchDescription[] = - "Enables searching through the hub."; - const char kAndroidHubSearchTabGroupsName[] = "Android Hub Tab Group Search"; const char kAndroidHubSearchTabGroupsDescription[] = "Enables searching through tab groups in the hub.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 14b920b..f643f08 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -2718,9 +2718,6 @@ extern const char kAndroidElegantTextHeightName[]; extern const char kAndroidElegantTextHeightDescription[]; -extern const char kAndroidHubSearchName[]; -extern const char kAndroidHubSearchDescription[]; - extern const char kAndroidHubSearchTabGroupsName[]; extern const char kAndroidHubSearchTabGroupsDescription[];
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java index ddf94b9c..fac64a2 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -576,7 +576,6 @@ public static final String TAB_GROUP_SYNC_AUTO_OPEN_KILL_SWITCH = "TabGroupSyncAutoOpenKillSwitch"; public static final String TABLET_TAB_STRIP_ANIMATION = "TabletTabStripAnimation"; - public static final String TAB_RESUMPTION_MODULE_ANDROID = "TabResumptionModuleAndroid"; public static final String TAB_STATE_FLAT_BUFFER = "TabStateFlatBuffer"; public static final String TAB_STRIP_CONTEXT_MENU = "TabStripContextMenuAndroid"; public static final String TAB_STRIP_DENSITY_CHANGE_ANDROID = "TabStripDensityChangeAndroid"; @@ -808,7 +807,10 @@ public static final CachedFlag sMagicStackAndroid = newCachedFlag(MAGIC_STACK_ANDROID, true); public static final CachedFlag sMiniOriginBar = newCachedFlag(MINI_ORIGIN_BAR, false, true); public static final CachedFlag sMostVisitedTilesCustomization = - newCachedFlag(MOST_VISITED_TILES_CUSTOMIZATION, false); + newCachedFlag( + MOST_VISITED_TILES_CUSTOMIZATION, + /* defaultValue= */ false, + /* defaultValueInTests= */ true); public static final CachedFlag sMostVisitedTilesReselect = newCachedFlag(MOST_VISITED_TILES_RESELECT, false); public static final CachedFlag sMultiInstanceApplicationStatusCleanup = @@ -1590,8 +1592,6 @@ sDisableBottomControlsStackerYOffsetDispatching = sBottomBrowserControlsRefactor.newBooleanParam( "disable_bottom_controls_stacker_y_offset", false); - public static final MutableIntParamWithSafeDefault sShowNewTabAnimationsVersion = - sShowNewTabAnimations.newIntParam("version", 4); public static final MutableIntParamWithSafeDefault sTabSwitcherColorBlendAnimateDurationMs = sTabSwitcherColorBlendAnimate.newIntParam("animation_duration_ms", 240); public static final MutableIntParamWithSafeDefault sTabSwitcherColorBlendAnimateInterpolator =
diff --git a/chrome/browser/glic/glic_user_status_browsertest.cc b/chrome/browser/glic/glic_user_status_browsertest.cc index 32829c6..69b239f 100644 --- a/chrome/browser/glic/glic_user_status_browsertest.cc +++ b/chrome/browser/glic/glic_user_status_browsertest.cc
@@ -49,11 +49,6 @@ namespace { const char kGlicUserStatusRelativeTestUrl[] = "/userstatus"; -// Define constants that are used in prefs checks -static constexpr char kUserStatus[] = "user_status"; -static constexpr char kUpdatedAt[] = "updated_at"; -static constexpr char kAccountId[] = "account_id"; - // Simple wrapper to serves as a POD for the test accounts. struct TestAccount { const std::string email; @@ -216,7 +211,7 @@ network::TestURLLoaderFactory test_url_loader_factory_; }; -IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest, Enterprise_SignIn_Enabled) { +IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest, EnterpriseSignInEnabled) { policy::ScopedManagementServiceOverrideForTesting platform_management( policy::ManagementServiceFactory::GetForProfile(profile()), policy::EnterpriseManagementAuthority::CLOUD); @@ -247,7 +242,7 @@ } IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest, - Enterprise_GeminiSettingsChange_SignedOut) { + EnterpriseSignInEnabledGeminiSettings) { policy::ScopedManagementServiceOverrideForTesting platform_management( policy::ManagementServiceFactory::GetForProfile(profile()), policy::EnterpriseManagementAuthority::CLOUD); @@ -332,7 +327,7 @@ } IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest, - Enterprise_GeminiSettingsChange_NoSignedOut) { + EnterpriseGeminiSettingsChangeNoSignedOut) { policy::ScopedManagementServiceOverrideForTesting platform_management( policy::ManagementServiceFactory::GetForProfile(profile()), policy::EnterpriseManagementAuthority::CLOUD); @@ -398,7 +393,7 @@ } IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest, - Enterprise_SignIn_DisabledByAdmin) { + EnterpriseSignInDisabledByAdmin) { policy::ScopedManagementServiceOverrideForTesting platform_management( policy::ManagementServiceFactory::GetForProfile(profile()), policy::EnterpriseManagementAuthority::CLOUD); @@ -428,7 +423,7 @@ } IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest, - Enterprise_SignIn_DisabledOther) { + EnterpriseSignInDisabledOther) { policy::ScopedManagementServiceOverrideForTesting platform_management( policy::ManagementServiceFactory::GetForProfile(profile()), policy::EnterpriseManagementAuthority::CLOUD); @@ -458,7 +453,7 @@ } IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest, - Enterprise_SignIn_ServerUnavailable_NoStoredResult) { + EnterpriseSignInServerUnavailableNoStoredResult) { policy::ScopedManagementServiceOverrideForTesting platform_management( policy::ManagementServiceFactory::GetForProfile(profile()), policy::EnterpriseManagementAuthority::CLOUD); @@ -483,7 +478,7 @@ } IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest, - Enterprise_SignIn_ServerUnavailable_HasStoredResult) { + EnterpriseSignInServerUnavailableHasStoredResult) { policy::ScopedManagementServiceOverrideForTesting platform_management( policy::ManagementServiceFactory::GetForProfile(profile()), policy::EnterpriseManagementAuthority::CLOUD); @@ -513,7 +508,7 @@ EXPECT_FALSE(IsGlicEnabled()); } -IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest, Enterprise_SignOut) { +IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest, EnterpriseSignOut) { policy::ScopedManagementServiceOverrideForTesting platform_management( policy::ManagementServiceFactory::GetForProfile(profile()), policy::EnterpriseManagementAuthority::CLOUD); @@ -547,7 +542,7 @@ EXPECT_FALSE(IsGlicEnabled()); } -IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest, NonEnterprise_SignIn) { +IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest, NonEnterpriseSignIn) { bool request_received = false; embedded_test_server()->RegisterRequestHandler(base::BindLambdaForTesting( [=, &request_received](const net::test_server::HttpRequest& request) @@ -586,5 +581,61 @@ ASSERT_TRUE(IsGlicEnabled()); } +IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest, EnterpriseDataProtection) { + policy::ScopedManagementServiceOverrideForTesting platform_management( + policy::ManagementServiceFactory::GetForProfile(profile()), + policy::EnterpriseManagementAuthority::CLOUD); + + RegisterUserStatusHandler( + net::HTTP_OK, + R"({"isGlicEnabled": true, "isAccessDeniedByAdmin": false, + "isEnterpriseAccountDataProtected": true })"); + net::test_server::EmbeddedTestServerHandle test_server_handle; + ASSERT_TRUE(test_server_handle = + embedded_test_server()->StartAndReturnHandle()); + + SetGlicUserStatusUrlForTest(); + + SimulatePrimaryAccountChangedSignIn(&enterpriseAccount); + + ASSERT_TRUE(base::test::RunUntil( + [&]() { return GetCachedStatusDict().has_value(); })); + + // Verify the isEnterpriseAccountDataProtected field. + EXPECT_EQ(profile() + ->GetPrefs() + ->GetDict(prefs::kGlicUserStatus) + .FindBool(kIsEnterpriseAccountDataProtected), + true); +} + +IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest, + EnterpriseDataProtectionMissingInServerResponse) { + policy::ScopedManagementServiceOverrideForTesting platform_management( + policy::ManagementServiceFactory::GetForProfile(profile()), + policy::EnterpriseManagementAuthority::CLOUD); + + RegisterUserStatusHandler( + net::HTTP_OK, + R"({"isGlicEnabled": true, "isAccessDeniedByAdmin": false})"); + net::test_server::EmbeddedTestServerHandle test_server_handle; + ASSERT_TRUE(test_server_handle = + embedded_test_server()->StartAndReturnHandle()); + + SetGlicUserStatusUrlForTest(); + + SimulatePrimaryAccountChangedSignIn(&enterpriseAccount); + + ASSERT_TRUE(base::test::RunUntil( + [&]() { return GetCachedStatusDict().has_value(); })); + + // Verify the isEnterpriseAccountDataProtected field. + EXPECT_EQ(profile() + ->GetPrefs() + ->GetDict(prefs::kGlicUserStatus) + .FindBool(kIsEnterpriseAccountDataProtected), + false); +} + } // namespace } // namespace glic
diff --git a/chrome/browser/glic/glic_user_status_code.h b/chrome/browser/glic/glic_user_status_code.h index 70accb9e..8ae3862 100644 --- a/chrome/browser/glic/glic_user_status_code.h +++ b/chrome/browser/glic/glic_user_status_code.h
@@ -5,10 +5,22 @@ #ifndef CHROME_BROWSER_GLIC_GLIC_USER_STATUS_CODE_H_ #define CHROME_BROWSER_GLIC_GLIC_USER_STATUS_CODE_H_ +#include "base/json/json_value_converter.h" #include "base/time/time.h" namespace glic { +// Keys of the pref dict. +inline constexpr char kUserStatus[] = "user_status"; +inline constexpr char kUpdatedAt[] = "updated_at"; +inline constexpr char kAccountId[] = "account_id"; + +// Keys of the JSON response of the glic user status RPC. +inline constexpr char kIsGlicEnabled[] = "isGlicEnabled"; +inline constexpr char kIsAccessDeniedByAdmin[] = "isAccessDeniedByAdmin"; +inline constexpr char kIsEnterpriseAccountDataProtected[] = + "isEnterpriseAccountDataProtected"; + // These enums are persisted in the disk as integers. They should not be // renumbered or removed. enum UserStatusCode { @@ -20,6 +32,9 @@ struct CachedUserStatus { UserStatusCode user_status_code; + // If true, this is an enterprise account for whom different disclosures + // should be shown. See b/413482904 for details. + bool is_enterprise_account_data_protected; base::Time last_updated; };
diff --git a/chrome/browser/glic/glic_user_status_fetcher.cc b/chrome/browser/glic/glic_user_status_fetcher.cc index 4bd0508..2090f895 100644 --- a/chrome/browser/glic/glic_user_status_fetcher.cc +++ b/chrome/browser/glic/glic_user_status_fetcher.cc
@@ -73,10 +73,6 @@ } } )"); - -constexpr char kUserStatus[] = "user_status"; -constexpr char kUpdatedAt[] = "updated_at"; -constexpr char kAccountId[] = "account_id"; } // namespace namespace glic { @@ -146,6 +142,7 @@ return CachedUserStatus{ UserStatusCode(pref_dict.FindInt(kUserStatus).value_or(0)), + pref_dict.FindBool(kIsEnterpriseAccountDataProtected).value_or(false), last_updated_default_value}; } @@ -303,14 +300,17 @@ } void GlicUserStatusFetcher::ProcessResponse(const std::string& account_id_hash, - UserStatusCode result_code) { + CachedUserStatus user_status) { // We don't overwrite the previous GlicUserStatus when UserStatusCode is // SERVER_UNAVAILABLE. - if (result_code != UserStatusCode::SERVER_UNAVAILABLE) { + if (user_status.user_status_code != UserStatusCode::SERVER_UNAVAILABLE) { base::Value::Dict data; data.Set(kAccountId, account_id_hash); - data.Set(kUserStatus, result_code); - data.Set(kUpdatedAt, base::Time::Now().InSecondsFSinceUnixEpoch()); + data.Set(kUserStatus, user_status.user_status_code); + data.Set(kUpdatedAt, user_status.last_updated.InSecondsFSinceUnixEpoch()); + data.Set(kIsEnterpriseAccountDataProtected, + user_status.is_enterprise_account_data_protected); + profile_->GetPrefs()->SetDict(glic::prefs::kGlicUserStatus, std::move(data)); }
diff --git a/chrome/browser/glic/glic_user_status_fetcher.h b/chrome/browser/glic/glic_user_status_fetcher.h index ead3b2e..010d7ae 100644 --- a/chrome/browser/glic/glic_user_status_fetcher.h +++ b/chrome/browser/glic/glic_user_status_fetcher.h
@@ -83,7 +83,7 @@ void FetchNow(); void ProcessResponse(const std::string& account_id_hash, - UserStatusCode result_code); + CachedUserStatus user_status); bool is_user_status_waiting_for_refresh_token_ = false; raw_ptr<Profile> profile_;
diff --git a/chrome/browser/glic/glic_user_status_request.cc b/chrome/browser/glic/glic_user_status_request.cc index 203d7a5..83bd6c08 100644 --- a/chrome/browser/glic/glic_user_status_request.cc +++ b/chrome/browser/glic/glic_user_status_request.cc
@@ -7,19 +7,35 @@ #include "base/json/json_reader.h" #include "base/logging.h" #include "base/strings/string_util.h" +#include "chrome/browser/glic/glic_user_status_code.h" #include "google_apis/common/api_error_codes.h" namespace { -constexpr char kIsGlicEnabled[] = "isGlicEnabled"; -constexpr char kIsAccessDeniedByAdmin[] = "isAccessDeniedByAdmin"; +// The server response would be first converted to JSON. The JSON object would +// be converted to this struct. +struct GlicUserStatusResponse { + bool is_glic_enabled = true; + bool is_access_denied_by_admin = false; + bool is_enterprise_account_data_protected = false; + static void RegisterJSONConverter( + base::JSONValueConverter<GlicUserStatusResponse>* converter) { + converter->RegisterBoolField(glic::kIsGlicEnabled, + &GlicUserStatusResponse::is_glic_enabled); + converter->RegisterBoolField( + glic::kIsAccessDeniedByAdmin, + &GlicUserStatusResponse::is_access_denied_by_admin); + converter->RegisterBoolField( + glic::kIsEnterpriseAccountDataProtected, + &GlicUserStatusResponse::is_enterprise_account_data_protected); + } +}; } // namespace namespace glic { GlicUserStatusRequest::GlicUserStatusRequest( google_apis::RequestSender* sender, GURL url, - base::OnceCallback<void(UserStatusCode result_code)> - process_response_callback) + base::OnceCallback<void(CachedUserStatus)> process_response_callback) : UrlFetchRequestBase(sender, google_apis::ProgressCallback(), google_apis::ProgressCallback()), @@ -36,7 +52,8 @@ google_apis::ApiErrorCode code, const std::string& reason) { // This method is to map error reason parsed from response body to - // ApiErrorCode. we assume for now that result is to be sent as ApiErrorCode. + // ApiErrorCode. we assume for now that result is to be sent as + // ApiErrorCode. return code; } @@ -49,9 +66,10 @@ const network::mojom::URLResponseHead* response_head, base::FilePath response_file, std::string response_body) { - std::move(process_response_callback_) - .Run(MapApiErrorCodeAndResponseBodyToUserStatus(GetErrorCode(), - response_body)); + auto cached_user_status = + MapApiErrorCodeAndResponseBodyToUserStatus(GetErrorCode(), response_body); + + std::move(process_response_callback_).Run(cached_user_status); OnProcessURLFetchResultsComplete(); } @@ -59,40 +77,68 @@ // called when request is canceled or auth is failed. void GlicUserStatusRequest::RunCallbackOnPrematureFailure( google_apis::ApiErrorCode error) { - std::move(process_response_callback_) - .Run(MapApiErrorCodeAndResponseBodyToUserStatus(error, "")); + auto cached_user_status = + MapApiErrorCodeAndResponseBodyToUserStatus(error, ""); + std::move(process_response_callback_).Run(cached_user_status); } -UserStatusCode +CachedUserStatus GlicUserStatusRequest::MapApiErrorCodeAndResponseBodyToUserStatus( google_apis::ApiErrorCode api_error_code, - std::string_view response_body) { + std::string_view response_body_as_string) { + // Currently, the is_enterprise_account_data_protected is not used for any + // Chrome behavir. Its sole use is to tell the user if their data is logged. + // It is worse to tell the user that their data when in fact it is, than to + // tell the user that their data is logged when in fact it is not. (And that + // messaging is the only thing this boolean controls). Therefore, we default + // the field to false. If the field is to be used in other ways later, the + // default value may need to change too. + CachedUserStatus user_status = { + .user_status_code = UserStatusCode::SERVER_UNAVAILABLE, + .is_enterprise_account_data_protected = false, + .last_updated = base::Time::Now()}; + if (api_error_code != google_apis::HTTP_SUCCESS) { - return UserStatusCode::SERVER_UNAVAILABLE; + return user_status; } // Parse response body to JSON in the form of // { // is_glic_enabled: true/false // is_access_denied_by_admin: true/false + // is_enterprise_account_data_protected: true/false // } - std::optional<base::Value::Dict> parsed = - base::JSONReader::ReadDict(response_body); + std::optional<base::Value::Dict> parsed_json = + base::JSONReader::ReadDict(response_body_as_string); - if (!parsed.has_value()) { - DVLOG(1) << "Failed reading response body: " << response_body; - return UserStatusCode::SERVER_UNAVAILABLE; + if (!parsed_json.has_value()) { + DVLOG(1) << "Failed reading response body: " << response_body_as_string; + return user_status; } - // The feature is enabled (if the response fails to mention it, we assume it - // is). - if (parsed->FindBool(kIsGlicEnabled).value_or(true)) { - return UserStatusCode::ENABLED; + // Convert response body in JSON format to the GlicUserStatusResponse + // struct. + GlicUserStatusResponse response; + base::JSONValueConverter<GlicUserStatusResponse> converter; + + if (!converter.Convert(parsed_json.value(), &response)) { + return user_status; } - // The feature is disabled (find the reason, if given). - return parsed->FindBool(kIsAccessDeniedByAdmin).value_or(false) - ? UserStatusCode::DISABLED_BY_ADMIN - : UserStatusCode::DISABLED_OTHER; + user_status.is_enterprise_account_data_protected = + response.is_enterprise_account_data_protected; + + if (response.is_glic_enabled) { + // The feature is enabled (if the response fails to mention it, we assume it + // is). + user_status.user_status_code = UserStatusCode::ENABLED; + } else { + // The feature is disabled (find the reason, if given). + user_status.user_status_code = response.is_access_denied_by_admin + ? UserStatusCode::DISABLED_BY_ADMIN + : UserStatusCode::DISABLED_OTHER; + } + + return user_status; } } // namespace glic
diff --git a/chrome/browser/glic/glic_user_status_request.h b/chrome/browser/glic/glic_user_status_request.h index b5f7e3c6..a7cc3e333 100644 --- a/chrome/browser/glic/glic_user_status_request.h +++ b/chrome/browser/glic/glic_user_status_request.h
@@ -19,8 +19,7 @@ google_apis::RequestSender* sender, GURL url, - base::OnceCallback<void(UserStatusCode result_code)> - process_response_callback); + base::OnceCallback<void(CachedUserStatus)> process_response_callback); GlicUserStatusRequest(const GlicUserStatusRequest&) = delete; GlicUserStatusRequest& operator=(const GlicUserStatusRequest&) = delete; ~GlicUserStatusRequest() override; @@ -42,13 +41,12 @@ void RunCallbackOnPrematureFailure(google_apis::ApiErrorCode code) override; private: - static UserStatusCode MapApiErrorCodeAndResponseBodyToUserStatus( + static CachedUserStatus MapApiErrorCodeAndResponseBodyToUserStatus( google_apis::ApiErrorCode result_code, std::string_view response_body); GURL url_; - base::OnceCallback<void(UserStatusCode result_code)> - process_response_callback_; + base::OnceCallback<void(CachedUserStatus)> process_response_callback_; }; } // namespace glic
diff --git a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarMediator.java b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarMediator.java index 350d3d7..d5615aeb 100644 --- a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarMediator.java +++ b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarMediator.java
@@ -37,7 +37,6 @@ import org.chromium.chrome.browser.ui.searchactivityutils.SearchActivityExtras.ResolutionType; import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.components.feature_engagement.Tracker; -import org.chromium.components.omnibox.OmniboxFeatures; import org.chromium.ui.base.DeviceFormFactor; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.url.GURL; @@ -154,9 +153,7 @@ mRemoveReferenceButtonObservers.add(() -> supplier.removeObserver(observer)); - if (OmniboxFeatures.sAndroidHubSearch.isEnabled()) { - pane.getHubSearchEnabledStateSupplier().addObserver(mOnHubSearchEnabledStateChange); - } + pane.getHubSearchEnabledStateSupplier().addObserver(mOnHubSearchEnabledStateChange); } ObservableSupplier<Pane> focusedPaneSupplier = paneManager.getFocusedPaneSupplier(); focusedPaneSupplier.addObserver(mOnFocusedPaneChange); @@ -169,12 +166,10 @@ mPropertyModel.set(PANE_BUTTON_LOOKUP_CALLBACK, this::consumeButtonLookup); - if (OmniboxFeatures.sAndroidHubSearch.isEnabled()) { - mPropertyModel.set(SEARCH_LISTENER, this::onSearchClicked); - // Fire an event for the original setup. - mComponentCallbacks.onConfigurationChanged(mContext.getResources().getConfiguration()); - mContext.registerComponentCallbacks(mComponentCallbacks); - } + mPropertyModel.set(SEARCH_LISTENER, this::onSearchClicked); + // Fire an event for the original setup. + mComponentCallbacks.onConfigurationChanged(mContext.getResources().getConfiguration()); + mContext.registerComponentCallbacks(mComponentCallbacks); } /** Cleans up observers. */ @@ -186,15 +181,12 @@ mRemoveReferenceButtonObservers.forEach(Runnable::run); mRemoveReferenceButtonObservers.clear(); mPaneManager.getFocusedPaneSupplier().removeObserver(mOnFocusedPaneChange); - if (OmniboxFeatures.sAndroidHubSearch.isEnabled()) { - mContext.unregisterComponentCallbacks(mComponentCallbacks); + mContext.unregisterComponentCallbacks(mComponentCallbacks); - for (@PaneId int paneId : mPaneManager.getPaneOrderController().getPaneOrder()) { - @Nullable Pane pane = mPaneManager.getPaneForId(paneId); - if (pane == null) continue; - pane.getHubSearchEnabledStateSupplier() - .removeObserver(mOnHubSearchEnabledStateChange); - } + for (@PaneId int paneId : mPaneManager.getPaneOrderController().getPaneOrder()) { + @Nullable Pane pane = mPaneManager.getPaneForId(paneId); + if (pane == null) continue; + pane.getHubSearchEnabledStateSupplier().removeObserver(mOnHubSearchEnabledStateChange); } } @@ -291,16 +283,14 @@ // This must be called before IS_INCOGNITO is set for all valid focused panes. This is // because hub search box elements (hint text) that will be updated via incognito state // changing will depend on a delay property key set in the configuration changed callback. - if (OmniboxFeatures.sAndroidHubSearch.isEnabled()) { - // Fire an event to determine what is shown. - mComponentCallbacks.onConfigurationChanged(mContext.getResources().getConfiguration()); + // Fire an event to determine what is shown. + mComponentCallbacks.onConfigurationChanged(mContext.getResources().getConfiguration()); - // Reset the enabled state of hub search to the supplier value or true if uninitialized - // when toggling panes to account for a potential disabled state from incognito reauth. - Boolean hubSearchEnabledState = focusedPane.getHubSearchEnabledStateSupplier().get(); - boolean enabled = hubSearchEnabledState == null ? true : hubSearchEnabledState; - mPropertyModel.set(HUB_SEARCH_ENABLED_STATE, enabled); - } + // Reset the enabled state of hub search to the supplier value or true if uninitialized + // when toggling panes to account for a potential disabled state from incognito reauth. + Boolean hubSearchEnabledState = focusedPane.getHubSearchEnabledStateSupplier().get(); + boolean enabled = hubSearchEnabledState == null ? true : hubSearchEnabledState; + mPropertyModel.set(HUB_SEARCH_ENABLED_STATE, enabled); mPropertyModel.set(MENU_BUTTON_VISIBLE, focusedPane.getMenuButtonVisible());
diff --git a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarView.java b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarView.java index f6b92be..5bef2f3 100644 --- a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarView.java +++ b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarView.java
@@ -52,7 +52,6 @@ import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.hub.HubToolbarProperties.PaneButtonLookup; -import org.chromium.components.omnibox.OmniboxFeatures; import org.chromium.ui.animation.AnimationHandler; import java.util.List; @@ -231,9 +230,7 @@ void setColorMixer(HubColorMixer mixer) { registerColorBlends(mixer); - if (OmniboxFeatures.sAndroidHubSearch.isEnabled()) { - registerSearchBoxColorBlends(mixer); - } + registerSearchBoxColorBlends(mixer); } private void registerColorBlends(HubColorMixer mixer) { @@ -456,9 +453,7 @@ } void updateIncognitoElements(boolean isIncognito) { - if (OmniboxFeatures.sAndroidHubSearch.isEnabled()) { - updateSearchBoxElements(isIncognito); - } + updateSearchBoxElements(isIncognito); } private @Nullable View getButtonView(int index) {
diff --git a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarViewUnitTest.java b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarViewUnitTest.java index 53351f61..509bad6f 100644 --- a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarViewUnitTest.java +++ b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarViewUnitTest.java
@@ -62,12 +62,9 @@ import org.chromium.base.test.BaseRobolectricTestRule; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.Features; -import org.chromium.base.test.util.Features.DisableFeatures; -import org.chromium.base.test.util.Features.EnableFeatures; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.hub.HubToolbarProperties.PaneButtonLookup; import org.chromium.components.browser_ui.styles.SemanticColorUtils; -import org.chromium.components.omnibox.OmniboxFeatureList; import org.chromium.ui.base.TestActivity; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; @@ -307,7 +304,6 @@ } @Test - @EnableFeatures(OmniboxFeatureList.ANDROID_HUB_SEARCH) public void testUpdateIncognitoElements() { mPropertyModel.set(IS_INCOGNITO, true); assertEquals( @@ -319,7 +315,6 @@ } @Test - @EnableFeatures(OmniboxFeatureList.ANDROID_HUB_SEARCH) public void testUpdateSearchBoxColorScheme() { forceSetColorScheme(HubColorScheme.INCOGNITO); assertEquals( @@ -343,7 +338,6 @@ } @Test - @EnableFeatures(OmniboxFeatureList.ANDROID_HUB_SEARCH) public void testHubSearchEnabledState() { mPropertyModel.set(HUB_SEARCH_ENABLED_STATE, false); assertFalse(mSearchBox.isEnabled()); @@ -357,17 +351,10 @@ } @Test - @EnableFeatures(OmniboxFeatureList.ANDROID_HUB_SEARCH) public void testHubColorMixer_searchBoxEnabled() { verify(mColorMixer, times(8)).registerBlend(any()); } - @Test - @DisableFeatures(OmniboxFeatureList.ANDROID_HUB_SEARCH) - public void testHubColorMixer_searchBoxDisabled() { - verify(mColorMixer, times(5)).registerBlend(any()); - } - /** * Setting the color twice forces {@link HubColorMixerImpl} to make a color scheme change * without an animation.
diff --git a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/ShrinkExpandHubLayoutAnimatorProvider.java b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/ShrinkExpandHubLayoutAnimatorProvider.java index 6765c78..f1f7f26 100644 --- a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/ShrinkExpandHubLayoutAnimatorProvider.java +++ b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/ShrinkExpandHubLayoutAnimatorProvider.java
@@ -27,7 +27,6 @@ import org.chromium.base.supplier.SyncOneshotSupplierImpl; import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; -import org.chromium.components.omnibox.OmniboxFeatures; import org.chromium.ui.animation.AnimationPerformanceTracker; import org.chromium.ui.animation.AnimationPerformanceTracker.AnimationMetrics; import org.chromium.ui.interpolators.Interpolators; @@ -300,10 +299,8 @@ } int searchBoxHeight = - OmniboxFeatures.sAndroidHubSearch.isEnabled() - ? HubUtils.getSearchBoxHeight( - mHubContainerView, R.id.hub_toolbar, R.id.toolbar_action_container) - : 0; + HubUtils.getSearchBoxHeight( + mHubContainerView, R.id.hub_toolbar, R.id.toolbar_action_container); Rect initialRect = animationData.getInitialRect(); Rect finalRect = animationData.getFinalRect(); assert mShrinkExpandImageView != null;
diff --git a/chrome/browser/magic_stack/android/junit/src/org/chromium/chrome/browser/magic_stack/HomeModulesCoordinatorUnitTest.java b/chrome/browser/magic_stack/android/junit/src/org/chromium/chrome/browser/magic_stack/HomeModulesCoordinatorUnitTest.java index d715759..64bd3f00 100644 --- a/chrome/browser/magic_stack/android/junit/src/org/chromium/chrome/browser/magic_stack/HomeModulesCoordinatorUnitTest.java +++ b/chrome/browser/magic_stack/android/junit/src/org/chromium/chrome/browser/magic_stack/HomeModulesCoordinatorUnitTest.java
@@ -55,7 +55,6 @@ import org.chromium.base.FeatureOverrides; import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.base.test.BaseRobolectricTestRunner; -import org.chromium.base.test.util.Features.DisableFeatures; import org.chromium.base.test.util.Features.EnableFeatures; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.magic_stack.ModuleDelegate.ModuleType; @@ -338,9 +337,6 @@ @Test @SmallTest - @DisableFeatures({ - ChromeFeatureList.TAB_RESUMPTION_MODULE_ANDROID, - }) public void testRecordMagicStackScroll_Scrolled() { mCoordinator = createCoordinator(/* skipInitProfile= */ true); mCoordinator.setMediatorForTesting(mMediator); @@ -358,9 +354,6 @@ @Test @SmallTest - @DisableFeatures({ - ChromeFeatureList.TAB_RESUMPTION_MODULE_ANDROID, - }) public void testRecordMagicStackScroll_NotScrolled() { when(mModuleDelegateHost.isHomeSurface()).thenReturn(true); mCoordinator = createCoordinator(/* skipInitProfile= */ true); @@ -376,9 +369,6 @@ @Test @SmallTest - @DisableFeatures({ - ChromeFeatureList.TAB_RESUMPTION_MODULE_ANDROID, - }) public void testOnModuleChangedCallback() { when(mModuleDelegateHost.isHomeSurface()).thenReturn(true); mCoordinator = createCoordinator(/* skipInitProfile= */ true);
diff --git a/chrome/browser/media/webrtc/desktop_capture_access_handler.cc b/chrome/browser/media/webrtc/desktop_capture_access_handler.cc index c1f3b78..d145ef1 100644 --- a/chrome/browser/media/webrtc/desktop_capture_access_handler.cc +++ b/chrome/browser/media/webrtc/desktop_capture_access_handler.cc
@@ -15,6 +15,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "base/types/expected.h" #include "build/build_config.h" #include "chrome/browser/media/webrtc/capture_policy_utils.h" #include "chrome/browser/media/webrtc/desktop_capture_devices_util.h" @@ -67,8 +68,9 @@ #include "chrome/browser/media/webrtc/system_media_capture_permissions_mac.h" #endif // BUILDFLAG(IS_MAC) -using content::BrowserThread; -using extensions::mojom::ManifestLocation; +using ::blink::mojom::MediaStreamRequestResult; +using ::content::BrowserThread; +using ::extensions::mojom::ManifestLocation; namespace { @@ -163,25 +165,26 @@ return audio_permitted && audio_requested && audio_supported; } -// Returns whether the request is approved or not. Some extensions do not -// require user approval, because they provide their own user approval UI. For -// others, shows a message box and asks for user approval. -bool IsRequestApproved(content::WebContents* web_contents, - const content::MediaStreamRequest& request, - const extensions::Extension* extension, - bool is_allowlisted_extension) { +// Checks whether the request is approved. +// If it is approved, returns MediaStreamRequestResult::OK. +// If not approved, returns the relevant MediaStreamRequestResult error code. +MediaStreamRequestResult CheckIfRequestApproved( + content::WebContents* web_contents, + const content::MediaStreamRequest& request, + const extensions::Extension* extension, + bool is_allowlisted_extension) { // Component extensions and some external extensions are approved by default. if (extension && (extension->location() == ManifestLocation::kComponent || extension->location() == ManifestLocation::kExternalComponent || is_allowlisted_extension)) { - return true; + return MediaStreamRequestResult::OK; } // chrome://feedback/ is allowed by default. // The user can still decide whether the screenshot taken is shared or not. if (request.security_origin.spec() == chrome::kChromeUIFeedbackURL) { - return true; + return MediaStreamRequestResult::OK; } #if !BUILDFLAG(IS_ANDROID) @@ -202,7 +205,15 @@ l10n_util::GetStringFUTF16(IDS_MEDIA_SCREEN_CAPTURE_CONFIRMATION_TITLE, application_name), confirmation_text); - return mb_result == chrome::MESSAGE_BOX_RESULT_YES; + switch (mb_result) { + case chrome::MESSAGE_BOX_RESULT_NO: + return MediaStreamRequestResult::PERMISSION_DENIED_BY_USER; + case chrome::MESSAGE_BOX_RESULT_YES: + return MediaStreamRequestResult::OK; + case chrome::MESSAGE_BOX_RESULT_DEFERRED: + break; + } + NOTREACHED(); } } // namespace @@ -245,16 +256,17 @@ if (!screen_capture_enabled || !origin_is_secure) { std::move(pending_request->callback) .Run(blink::mojom::StreamDevicesSet(), - blink::mojom::MediaStreamRequestResult::INVALID_STATE, + MediaStreamRequestResult::INVALID_STATE, /*ui=*/nullptr); return; } - if (!IsRequestApproved(web_contents, pending_request->request, extension, - pending_request->is_allowlisted_extension)) { + const MediaStreamRequestResult request_result = + CheckIfRequestApproved(web_contents, pending_request->request, extension, + pending_request->is_allowlisted_extension); + if (request_result != MediaStreamRequestResult::OK) { std::move(pending_request->callback) - .Run(blink::mojom::StreamDevicesSet(), - blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, + .Run(blink::mojom::StreamDevicesSet(), request_result, /*ui=*/nullptr); return; } @@ -265,7 +277,7 @@ pending_request->request.render_frame_id))) { std::move(pending_request->callback) .Run(blink::mojom::StreamDevicesSet(), - blink::mojom::MediaStreamRequestResult::INVALID_STATE, + MediaStreamRequestResult::INVALID_STATE, /*ui=*/nullptr); return; } @@ -339,7 +351,7 @@ blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE) { std::move(pending_request->callback) .Run(blink::mojom::StreamDevicesSet(), - blink::mojom::MediaStreamRequestResult::INVALID_STATE, + MediaStreamRequestResult::INVALID_STATE, /*ui=*/nullptr); return; } @@ -351,7 +363,7 @@ if (allowed_capture_level == AllowedScreenCaptureLevel::kDisallowed) { std::move(pending_request->callback) .Run(blink::mojom::StreamDevicesSet(), - blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, + MediaStreamRequestResult::PERMISSION_DENIED, /*ui=*/nullptr); return; } @@ -368,7 +380,7 @@ if (allowed_capture_level < AllowedScreenCaptureLevel::kDesktop) { std::move(pending_request->callback) .Run(blink::mojom::StreamDevicesSet(), - blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, + MediaStreamRequestResult::PERMISSION_DENIED, /*ui=*/nullptr); return; } @@ -378,8 +390,7 @@ system_permission_settings::SystemPermission::kAllowed) { std::move(pending_request->callback) .Run(blink::mojom::StreamDevicesSet(), - blink::mojom::MediaStreamRequestResult:: - PERMISSION_DENIED_BY_SYSTEM, + MediaStreamRequestResult::PERMISSION_DENIED_BY_SYSTEM, /*ui=*/nullptr); return; } @@ -417,7 +428,7 @@ if (media_id.type == content::DesktopMediaID::TYPE_NONE) { std::move(pending_request->callback) .Run(blink::mojom::StreamDevicesSet(), - blink::mojom::MediaStreamRequestResult::INVALID_STATE, + MediaStreamRequestResult::INVALID_STATE, /*ui=*/nullptr); return; } @@ -425,7 +436,7 @@ if (!IsMediaTypeAllowed(allowed_capture_level, media_id.type)) { std::move(pending_request->callback) .Run(blink::mojom::StreamDevicesSet(), - blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, + MediaStreamRequestResult::PERMISSION_DENIED, /*ui=*/nullptr); return; } @@ -434,10 +445,9 @@ system_media_permissions::CheckSystemScreenCapturePermission() != system_permission_settings::SystemPermission::kAllowed) { std::move(pending_request->callback) - .Run( - blink::mojom::StreamDevicesSet(), - blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED_BY_SYSTEM, - /*ui=*/nullptr); + .Run(blink::mojom::StreamDevicesSet(), + MediaStreamRequestResult::PERMISSION_DENIED_BY_SYSTEM, + /*ui=*/nullptr); return; } #endif @@ -449,7 +459,7 @@ media_id.web_contents_id.main_render_frame_id))) { std::move(pending_request->callback) .Run(blink::mojom::StreamDevicesSet(), - blink::mojom::MediaStreamRequestResult::TAB_CAPTURE_FAILURE, + MediaStreamRequestResult::TAB_CAPTURE_FAILURE, /*ui=*/nullptr); return; } @@ -486,7 +496,7 @@ if (!pending_request->picker) { std::move(pending_request->callback) .Run(blink::mojom::StreamDevicesSet(), - blink::mojom::MediaStreamRequestResult::INVALID_STATE, + MediaStreamRequestResult::INVALID_STATE, /*ui=*/nullptr); return; } @@ -594,7 +604,8 @@ void DesktopCaptureAccessHandler::OnPickerDialogResults( base::WeakPtr<content::WebContents> web_contents, const std::u16string& application_title, - content::DesktopMediaID media_id) { + base::expected<content::DesktopMediaID, + blink::mojom::MediaStreamRequestResult> result) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!web_contents) { @@ -618,12 +629,13 @@ std::move(queue.front()); queue.pop_front(); - if (media_id.is_null()) { + if (!result.has_value()) { std::move(pending_request->callback) - .Run(blink::mojom::StreamDevicesSet(), - blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, + .Run(blink::mojom::StreamDevicesSet(), result.error(), /*ui=*/nullptr); } else { + const content::DesktopMediaID media_id = result.value(); + CHECK(!media_id.is_null()); #if BUILDFLAG(IS_CHROMEOS) // base::Unretained(this) is safe because DesktopCaptureAccessHandler is // owned by MediaCaptureDevicesDispatcher, which is a lazy singleton which @@ -639,8 +651,10 @@ media_id.audio_share); #endif // !BUILDFLAG(IS_CHROMEOS) } - if (!queue.empty()) + + if (!queue.empty()) { ProcessQueuedAccessRequest(queue, web_contents.get()); + } } void DesktopCaptureAccessHandler::WebContentsDestroyed( @@ -696,8 +710,7 @@ pending_request->is_allowlisted_extension); std::move(pending_request->callback) - .Run(stream_devices_set, blink::mojom::MediaStreamRequestResult::OK, - std::move(ui)); + .Run(stream_devices_set, MediaStreamRequestResult::OK, std::move(ui)); } #if BUILDFLAG(IS_CHROMEOS) @@ -718,7 +731,7 @@ if (!is_dlp_allowed) { std::move(pending_request->callback) .Run(blink::mojom::StreamDevicesSet(), - blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, + MediaStreamRequestResult::PERMISSION_DENIED, /*ui=*/nullptr); return; }
diff --git a/chrome/browser/media/webrtc/desktop_capture_access_handler.h b/chrome/browser/media/webrtc/desktop_capture_access_handler.h index cb2ca13..e684bf9a 100644 --- a/chrome/browser/media/webrtc/desktop_capture_access_handler.h +++ b/chrome/browser/media/webrtc/desktop_capture_access_handler.h
@@ -10,6 +10,7 @@ #include <utility> #include "base/memory/raw_ptr.h" +#include "base/types/expected.h" #include "chrome/browser/media/capture_access_handler_base.h" #include "chrome/browser/media/media_access_handler.h" #include "chrome/browser/media/webrtc/desktop_media_list.h" @@ -18,6 +19,7 @@ #include "chrome/browser/tab_contents/web_contents_collection.h" #include "content/public/browser/desktop_media_id.h" #include "content/public/browser/media_stream_request.h" +#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h" #if BUILDFLAG(IS_CHROMEOS) namespace aura { @@ -86,9 +88,11 @@ std::unique_ptr<PendingAccessRequest> pending_request); void ProcessQueuedAccessRequest(const RequestsQueue& queue, content::WebContents* web_contents); - void OnPickerDialogResults(base::WeakPtr<content::WebContents> web_contents, - const std::u16string& application_title, - content::DesktopMediaID source); + void OnPickerDialogResults( + base::WeakPtr<content::WebContents> web_contents, + const std::u16string& application_title, + base::expected<content::DesktopMediaID, + blink::mojom::MediaStreamRequestResult> result); void DeletePendingAccessRequest(int render_process_id, int render_frame_id, int page_request_id);
diff --git a/chrome/browser/media/webrtc/desktop_capture_access_handler_unittest.cc b/chrome/browser/media/webrtc/desktop_capture_access_handler_unittest.cc index 5ed7feb..8611af6 100644 --- a/chrome/browser/media/webrtc/desktop_capture_access_handler_unittest.cc +++ b/chrome/browser/media/webrtc/desktop_capture_access_handler_unittest.cc
@@ -12,6 +12,7 @@ #include "base/functional/bind.h" #include "base/memory/raw_ptr.h" #include "base/run_loop.h" +#include "base/types/expected.h" #include "build/build_config.h" #include "chrome/browser/media/webrtc/fake_desktop_media_picker_factory.h" #include "chrome/common/chrome_switches.h" @@ -108,16 +109,19 @@ } void ProcessDeviceUpdateRequest( - const content::DesktopMediaID& fake_desktop_media_id_response, + const base::expected<content::DesktopMediaID, + blink::mojom::MediaStreamRequestResult>& response, blink::mojom::MediaStreamRequestResult* request_result, blink::mojom::StreamDevices* stream_devices_result, blink::MediaStreamRequestType request_type, bool request_audio) { FakeDesktopMediaPickerFactory::TestFlags test_flags[] = { - {false /* expect_screens */, false /* expect_windows*/, - true /* expect_tabs */, false /* expect_current_tab */, - request_audio /* expect_audio */, - fake_desktop_media_id_response /* selected_source */}}; + {.expect_screens = false, + .expect_windows = false, + .expect_tabs = true, + .expect_current_tab = false, + .expect_audio = request_audio, + .picker_result = response}}; picker_factory_->SetTestFlags(test_flags, std::size(test_flags)); blink::mojom::MediaStreamType audio_type = request_audio ? blink::mojom::MediaStreamType::GUM_DESKTOP_AUDIO_CAPTURE @@ -212,9 +216,11 @@ TEST_F(DesktopCaptureAccessHandlerTest, ChangeSourcePermissionDenied) { blink::mojom::MediaStreamRequestResult result; blink::mojom::StreamDevices stream_devices; - ProcessDeviceUpdateRequest(content::DesktopMediaID(), &result, - &stream_devices, blink::MEDIA_DEVICE_UPDATE, - false /*request audio*/); + ProcessDeviceUpdateRequest( + base::unexpected( + blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED), + &result, &stream_devices, blink::MEDIA_DEVICE_UPDATE, + false /*request audio*/); EXPECT_EQ(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, result); EXPECT_EQ(0u, blink::CountDevices(stream_devices)); }
diff --git a/chrome/browser/media/webrtc/desktop_media_picker.h b/chrome/browser/media/webrtc/desktop_media_picker.h index 509e618..a09ac0e 100644 --- a/chrome/browser/media/webrtc/desktop_media_picker.h +++ b/chrome/browser/media/webrtc/desktop_media_picker.h
@@ -12,11 +12,13 @@ #include "base/feature_list.h" #include "base/functional/callback_forward.h" #include "base/memory/raw_ptr.h" +#include "base/types/expected.h" #include "build/android_buildflags.h" #include "build/buildflag.h" #include "content/public/browser/desktop_media_id.h" #include "content/public/browser/media_stream_request.h" #include "content/public/browser/web_contents_observer.h" +#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h" #include "ui/base/mojom/ui_base_types.mojom-shared.h" #include "ui/base/ui_base_types.h" #include "ui/gfx/native_widget_types.h" @@ -37,7 +39,10 @@ // TODO(crbug.com/40637301): Rename this class. class DesktopMediaPicker { public: - using DoneCallback = base::OnceCallback<void(content::DesktopMediaID id)>; + using DoneCallbackArgumentType = + base::expected<content::DesktopMediaID, + blink::mojom::MediaStreamRequestResult>; + using DoneCallback = base::OnceCallback<void(DoneCallbackArgumentType)>; struct Params { // Possible sources of the request.
diff --git a/chrome/browser/media/webrtc/desktop_media_picker_controller.cc b/chrome/browser/media/webrtc/desktop_media_picker_controller.cc index e4fc467b..151d1d0 100644 --- a/chrome/browser/media/webrtc/desktop_media_picker_controller.cc +++ b/chrome/browser/media/webrtc/desktop_media_picker_controller.cc
@@ -12,6 +12,7 @@ #include "base/containers/contains.h" #include "base/functional/bind.h" #include "base/strings/utf_string_conversions.h" +#include "base/types/expected.h" #include "build/build_config.h" #include "chrome/browser/media/webrtc/capture_policy_utils.h" #include "chrome/browser/media/webrtc/desktop_media_picker.h" @@ -32,8 +33,11 @@ #include "extensions/common/switches.h" #include "media/audio/audio_features.h" #include "media/base/media_switches.h" +#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h" #include "ui/base/l10n/l10n_util.h" +using ::content::DesktopMediaID; + DesktopMediaPickerController::DesktopMediaPickerController( DesktopMediaPickerFactory* picker_factory) : picker_factory_(picker_factory @@ -77,7 +81,7 @@ } void DesktopMediaPickerController::WebContentsDestroyed() { - OnPickerDialogResults(std::string(), content::DesktopMediaID()); + OnPickerDialogResults(std::string(), DesktopMediaID()); } // static @@ -108,8 +112,8 @@ if (source_list->GetSourceCount() == 1) { // With only one possible source, the picker dialog is being bypassed. Apply // the default value of the "audio checkbox" here for desktop screen share. - content::DesktopMediaID media_id = source_list->GetSource(0).id; - DCHECK_EQ(media_id.type, content::DesktopMediaID::TYPE_SCREEN); + DesktopMediaID media_id = source_list->GetSource(0).id; + DCHECK_EQ(media_id.type, DesktopMediaID::TYPE_SCREEN); media_id.audio_share = params_.request_audio && IsSystemAudioCaptureSupported(params_.request_source); @@ -141,7 +145,11 @@ void DesktopMediaPickerController::OnPickerDialogResults( const std::string& err, - content::DesktopMediaID source) { - if (done_callback_) + base::expected<content::DesktopMediaID, + blink::mojom::MediaStreamRequestResult> result) { + if (done_callback_) { + const content::DesktopMediaID source = + result.value_or(content::DesktopMediaID()); std::move(done_callback_).Run(err, source); + } }
diff --git a/chrome/browser/media/webrtc/desktop_media_picker_controller.h b/chrome/browser/media/webrtc/desktop_media_picker_controller.h index 6276a06b..1d64ca1 100644 --- a/chrome/browser/media/webrtc/desktop_media_picker_controller.h +++ b/chrome/browser/media/webrtc/desktop_media_picker_controller.h
@@ -11,10 +11,12 @@ #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" +#include "base/types/expected.h" #include "chrome/browser/media/webrtc/desktop_media_list.h" #include "chrome/browser/media/webrtc/desktop_media_picker.h" #include "content/public/browser/desktop_media_id.h" #include "content/public/browser/web_contents_observer.h" +#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h" #include "ui/base/ui_base_types.h" class DesktopMediaList; @@ -89,8 +91,10 @@ // This function is responsible to call |done_callback_| and after running the // callback |this| might be destroyed. Do **not** access fields after calling // this function. - void OnPickerDialogResults(const std::string& err, - content::DesktopMediaID source); + void OnPickerDialogResults( + const std::string& err, + base::expected<content::DesktopMediaID, + blink::mojom::MediaStreamRequestResult> result); Params params_; DoneCallback done_callback_;
diff --git a/chrome/browser/media/webrtc/display_media_access_handler.cc b/chrome/browser/media/webrtc/display_media_access_handler.cc index 89da8b3..656cb16c 100644 --- a/chrome/browser/media/webrtc/display_media_access_handler.cc +++ b/chrome/browser/media/webrtc/display_media_access_handler.cc
@@ -13,6 +13,7 @@ #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/strings/utf_string_conversions.h" +#include "base/types/expected.h" #include "build/build_config.h" #include "chrome/browser/bad_message.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" @@ -274,6 +275,10 @@ // before sending IPC, but just to be sure double check here as well. This // is not treated as a BadMessage because it is possible for the transient // user activation to expire between the renderer side check and this check. + // + // TODO(crbug.com/416448339): Introduce and use a new result value, + // MediaStreamRequestResult::NO_TRANSIENT_ACTIVATION. In JS, it should map + // to `InvalidStateError`, not to `NotAllowedError`. if (!rfh->HasTransientUserActivation() && capture_policy::IsTransientActivationRequiredForGetDisplayMedia( web_contents)) { @@ -621,7 +626,7 @@ void DisplayMediaAccessHandler::OnDisplaySurfaceSelected( base::WeakPtr<WebContents> web_contents, - DesktopMediaID media_id) { + base::expected<DesktopMediaID, MediaStreamRequestResult> result) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!web_contents) { @@ -630,12 +635,14 @@ return; } - if (media_id.is_null()) { - RejectRequest(web_contents.get(), - MediaStreamRequestResult::PERMISSION_DENIED); + if (!result.has_value()) { + RejectRequest(web_contents.get(), result.error()); return; } + const DesktopMediaID media_id = result.value(); + CHECK(!media_id.is_null()); + // If the media id is tied to a tab, check that it hasn't been destroyed. if (media_id.type == DesktopMediaID::TYPE_WEB_CONTENTS && !WebContents::FromRenderFrameHost(content::RenderFrameHost::FromID(
diff --git a/chrome/browser/media/webrtc/display_media_access_handler.h b/chrome/browser/media/webrtc/display_media_access_handler.h index a74500c4..088b69c4 100644 --- a/chrome/browser/media/webrtc/display_media_access_handler.h +++ b/chrome/browser/media/webrtc/display_media_access_handler.h
@@ -8,6 +8,7 @@ #include <memory> #include "base/memory/weak_ptr.h" +#include "base/types/expected.h" #include "build/build_config.h" #include "chrome/browser/media/capture_access_handler_base.h" #include "chrome/browser/media/media_access_handler.h" @@ -18,6 +19,7 @@ #include "chrome/browser/tab_contents/web_contents_collection.h" #include "content/public/browser/desktop_media_id.h" #include "content/public/browser/web_contents.h" +#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h" namespace extensions { class Extension; @@ -97,12 +99,16 @@ void AcceptRequest(content::WebContents* web_contents, const content::DesktopMediaID& media_id); - // Called back after the user chooses one of the possible desktop media - // sources for the request that's currently being processed. If no |media_id| - // is given, the request was rejected, either by the browser or by the user. + // Called after the user interacts with the media-picker. + // - If the user chooses to share a tab/window/screen, `result.value()` holds + // the media-ID of the chosen surface. + // - If the user rejects the prompt, or if any error occurs, or if the system + // automatically rejects the request, `result.error()` holds the relevant + // error code. void OnDisplaySurfaceSelected( base::WeakPtr<content::WebContents> web_contents, - content::DesktopMediaID media_id); + base::expected<content::DesktopMediaID, + blink::mojom::MediaStreamRequestResult> result); #if BUILDFLAG(IS_CHROMEOS) // Called back after checking Data Leak Prevention (DLP) restrictions.
diff --git a/chrome/browser/media/webrtc/display_media_access_handler_unittest.cc b/chrome/browser/media/webrtc/display_media_access_handler_unittest.cc index 0edb61e..82f93e82 100644 --- a/chrome/browser/media/webrtc/display_media_access_handler_unittest.cc +++ b/chrome/browser/media/webrtc/display_media_access_handler_unittest.cc
@@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - #include "chrome/browser/media/webrtc/display_media_access_handler.h" #include <array> @@ -15,6 +14,7 @@ #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "base/test/mock_callback.h" +#include "base/types/expected.h" #include "build/build_config.h" #include "chrome/browser/media/webrtc/fake_desktop_media_picker_factory.h" #include "chrome/common/pref_names.h" @@ -71,7 +71,7 @@ .expect_tabs = true, .expect_current_tab = false, .expect_audio = request_audio, - .selected_source = + .picker_result = content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, content::DesktopMediaID::kFakeId)}); } @@ -155,15 +155,18 @@ } void ProcessRequest( - const content::DesktopMediaID& fake_desktop_media_id_response, + base::expected<content::DesktopMediaID, + blink::mojom::MediaStreamRequestResult> response, blink::mojom::MediaStreamRequestResult* request_result, blink::mojom::StreamDevices& devices_result, bool request_audio, bool expect_result = true) { - SetTestFlags({{true /* expect_screens */, true /* expect_windows*/, - true /* expect_tabs */, /* expect_current_tab, */ false, - request_audio, - fake_desktop_media_id_response /* selected_source */}}); + SetTestFlags({{.expect_screens = true, + .expect_windows = true, + .expect_tabs = true, + .expect_current_tab = false, + .expect_audio = request_audio, + .picker_result = response}}); content::MediaStreamRequest request = MakeRequest(request_audio); @@ -315,8 +318,9 @@ TEST_F(DisplayMediaAccessHandlerTest, PermissionDenied) { blink::mojom::MediaStreamRequestResult result; blink::mojom::StreamDevices devices; - ProcessRequest(content::DesktopMediaID(), &result, devices, - true /* request_audio */); + ProcessRequest(base::unexpected( + blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED), + &result, devices, true /* request_audio */); EXPECT_EQ(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, result); EXPECT_EQ(0u, blink::CountDevices(devices)); } @@ -887,7 +891,9 @@ SetTestFlags({{/*expect_screens=*/!exclude_monitor_type_surfaces_, /*expect_windows=*/true, /*expect_tabs=*/true, /*expect_current_tab=*/false, - /*expect_audio=*/false, content::DesktopMediaID(), + /*expect_audio=*/false, + base::unexpected( + blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED), /*cancelled=*/false}}); blink::mojom::MediaStreamRequestResult result; blink::mojom::StreamDevices devices;
diff --git a/chrome/browser/media/webrtc/fake_desktop_media_picker_factory.cc b/chrome/browser/media/webrtc/fake_desktop_media_picker_factory.cc index 7659cf1..79186ab9 100644 --- a/chrome/browser/media/webrtc/fake_desktop_media_picker_factory.cc +++ b/chrome/browser/media/webrtc/fake_desktop_media_picker_factory.cc
@@ -77,7 +77,8 @@ } void FakeDesktopMediaPicker::CallCallback(DoneCallback done_callback) { - std::move(done_callback).Run(expectation_->selected_source); + CHECK(expectation_->picker_result.has_value()); + std::move(done_callback).Run(expectation_->picker_result.value()); } FakeDesktopMediaPickerFactory::FakeDesktopMediaPickerFactory() = default;
diff --git a/chrome/browser/media/webrtc/fake_desktop_media_picker_factory.h b/chrome/browser/media/webrtc/fake_desktop_media_picker_factory.h index 6047596..ef253ad 100644 --- a/chrome/browser/media/webrtc/fake_desktop_media_picker_factory.h +++ b/chrome/browser/media/webrtc/fake_desktop_media_picker_factory.h
@@ -9,10 +9,12 @@ #include <vector> #include "base/memory/raw_ptr.h" +#include "base/types/expected.h" #include "chrome/browser/media/webrtc/desktop_media_list.h" #include "chrome/browser/media/webrtc/desktop_media_picker.h" #include "chrome/browser/media/webrtc/desktop_media_picker_factory.h" #include "content/public/browser/desktop_media_id.h" +#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h" class FakeDesktopMediaPicker; @@ -26,7 +28,9 @@ bool expect_tabs = false; bool expect_current_tab = false; bool expect_audio = false; - content::DesktopMediaID selected_source; + std::optional<base::expected<content::DesktopMediaID, + blink::mojom::MediaStreamRequestResult>> + picker_result; bool cancelled = false; // Following flags are set by FakeDesktopMediaPicker when it's created and
diff --git a/chrome/browser/media/webrtc/webrtc_desktop_capture_browsertest.cc b/chrome/browser/media/webrtc/webrtc_desktop_capture_browsertest.cc index 589481d..6ab38a0 100644 --- a/chrome/browser/media/webrtc/webrtc_desktop_capture_browsertest.cc +++ b/chrome/browser/media/webrtc/webrtc_desktop_capture_browsertest.cc
@@ -256,7 +256,7 @@ .expect_screens = true, .expect_windows = true, .expect_tabs = true, - .selected_source = std::move(media_id_callback).Run(), + .picker_result = std::move(media_id_callback).Run(), }; picker_factory_.SetTestFlags(&test_flags, /*tests_count=*/1);
diff --git a/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc b/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc index 77dad4c..ebafcf5 100644 --- a/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc +++ b/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc
@@ -2512,3 +2512,42 @@ EXPECT_FALSE(HasCscIndicator(capture_session.initially_captured_tab())); EXPECT_FALSE(HasCscIndicator(capture_session.other_tab())); } + +class WebRtcScreenCaptureBrowserTestUserRejection + : public WebRtcScreenCaptureBrowserTest, + public testing::WithParamInterface<bool> { + public: + WebRtcScreenCaptureBrowserTestUserRejection() + : prefer_current_tab_(GetParam()) {} + ~WebRtcScreenCaptureBrowserTestUserRejection() override = default; + + void SetUpCommandLine(base::CommandLine* command_line) override { + WebRtcScreenCaptureBrowserTest::SetUpCommandLine(command_line); + command_line->AppendSwitch(prefer_current_tab_ + ? switches::kThisTabCaptureAutoReject + : switches::kCaptureAutoReject); + } + + bool PreferCurrentTab() const override { return prefer_current_tab_; } + + private: + const bool prefer_current_tab_; +}; + +INSTANTIATE_TEST_SUITE_P(, WebRtcScreenCaptureBrowserTestUserRejection, Bool()); + +IN_PROC_BROWSER_TEST_P(WebRtcScreenCaptureBrowserTestUserRejection, + CorrectErrorReported) { + ASSERT_TRUE(embedded_test_server()->Start()); + OpenTestPageInNewTab(kCapturedPageMain); + content::WebContents* capturing_tab = OpenTestPageInNewTab(kMainHtmlPage); + + RunGetDisplayMedia( + capturing_tab, + GetConstraints( + /*video=*/true, /*audio=*/false), + /*is_fake_ui=*/false, + /*expect_success=*/false, + /*is_tab_capture=*/true, + /*expected_error=*/"NotAllowedError: Permission denied by user"); +}
diff --git a/chrome/browser/net/system_network_context_manager.cc b/chrome/browser/net/system_network_context_manager.cc index 4a5d0d68..ed7bd987 100644 --- a/chrome/browser/net/system_network_context_manager.cc +++ b/chrome/browser/net/system_network_context_manager.cc
@@ -44,6 +44,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/google_url_loader_throttle.h" #include "chrome/common/pref_names.h" +#include "chrome/common/request_header_integrity/buildflags.h" #include "components/certificate_transparency/ct_known_logs.h" #include "components/embedder_support/user_agent_utils.h" #include "components/net_log/net_export_file_writer.h" @@ -105,6 +106,10 @@ #include "chrome/browser/net/chrome_mojo_proxy_resolver_win.h" #endif // BUILDFLAG(IS_WIN) +#if BUILDFLAG(ENABLE_REQUEST_HEADER_INTEGRITY) +#include "chrome/common/request_header_integrity/request_header_integrity_url_loader_throttle.h" // nogncheck crbug.com/1125897 +#endif + namespace { // Enumeration of possible sandbox states. These values are persisted to logs, // so entries should not be renumbered and numeric values should never be @@ -859,6 +864,10 @@ network::mojom::NetworkContextParams* network_context_params) { variations::UpdateCorsExemptHeaderForVariations(network_context_params); GoogleURLLoaderThrottle::UpdateCorsExemptHeader(network_context_params); +#if BUILDFLAG(ENABLE_REQUEST_HEADER_INTEGRITY) + request_header_integrity::RequestHeaderIntegrityURLLoaderThrottle:: + UpdateCorsExemptHeaders(network_context_params); +#endif // BUILDFLAG(ENABLE_REQUEST_HEADER_INTEGRITY) network_context_params->enable_brotli = true;
diff --git a/chrome/browser/ntp_customization/java/res/layout/ntp_customization_bottom_sheet.xml b/chrome/browser/ntp_customization/java/res/layout/ntp_customization_bottom_sheet.xml index 2947d21..7769bf3f 100644 --- a/chrome/browser/ntp_customization/java/res/layout/ntp_customization_bottom_sheet.xml +++ b/chrome/browser/ntp_customization/java/res/layout/ntp_customization_bottom_sheet.xml
@@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- -Copyright 2025 The Chromium Authors. +Copyright 2025 The Chromium Authors Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> @@ -8,6 +8,7 @@ <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/bottom_sheet_container" android:layout_width="match_parent" android:layout_height="match_parent" tools:ignore="UnusedResources">
diff --git a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationBottomSheetContent.java b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationBottomSheetContent.java index 14aa8bb..fbb81e4 100644 --- a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationBottomSheetContent.java +++ b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationBottomSheetContent.java
@@ -49,7 +49,7 @@ @Override public int getVerticalScrollOffset() { - return 0; + return mContentView.findViewById(R.id.bottom_sheet_container).getScrollY(); } @Override
diff --git a/chrome/browser/pdf/pdf_searchify_browsertest.cc b/chrome/browser/pdf/pdf_searchify_browsertest.cc index 4ca6207d..30435c6 100644 --- a/chrome/browser/pdf/pdf_searchify_browsertest.cc +++ b/chrome/browser/pdf/pdf_searchify_browsertest.cc
@@ -13,7 +13,6 @@ #include "components/pdf/browser/pdf_document_helper.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" -#include "pdf/pdf_features.h" #include "services/screen_ai/public/cpp/utilities.h" #include "ui/accessibility/accessibility_features.h" #include "ui/accessibility/accessibility_switches.h" @@ -77,7 +76,6 @@ if (IsSearchifyActive()) { enabled.push_back({::features::kScreenAITestMode, {}}); enabled.push_back({ax::mojom::features::kScreenAIOCREnabled, {}}); - enabled.push_back({chrome_pdf::features::kPdfSearchify, {}}); } return enabled; } @@ -190,5 +188,8 @@ IsScreenReaderEnabled(), IsSearchifyActive() ? 1 : 0); } +// TODO(crbug.com/382610226): Add text selection test for PDFs with rotated page +// or image. + // TODO(crbug.com/382610226): Consider adding save tests like // pdf_extension_download_test.cc
diff --git a/chrome/browser/privacy_sandbox/notice/BUILD.gn b/chrome/browser/privacy_sandbox/notice/BUILD.gn index a4bf546..4f23352 100644 --- a/chrome/browser/privacy_sandbox/notice/BUILD.gn +++ b/chrome/browser/privacy_sandbox/notice/BUILD.gn
@@ -101,6 +101,7 @@ ":notice_mojom", "//base", "//chrome/browser/profiles:profile", + "//chrome/browser/sync", "//chrome/browser/ui:ui", "//chrome/browser/ui/browser_window:browser_window", "//chrome/browser/ui/privacy_sandbox:privacy_sandbox", @@ -215,6 +216,7 @@ sources += [ "desktop_entrypoint_handlers_browsertest.cc" ] deps += [ ":desktop_view_manager", + "//chrome/browser/sync", "//chrome/test:test_support_ui", ] }
diff --git a/chrome/browser/privacy_sandbox/notice/desktop_entrypoint_handlers.cc b/chrome/browser/privacy_sandbox/notice/desktop_entrypoint_handlers.cc index b5e75776..5eafe61 100644 --- a/chrome/browser/privacy_sandbox/notice/desktop_entrypoint_handlers.cc +++ b/chrome/browser/privacy_sandbox/notice/desktop_entrypoint_handlers.cc
@@ -7,10 +7,12 @@ #include "chrome/browser/privacy_sandbox/notice/desktop_entrypoint_handlers_helper.h" #include "chrome/browser/privacy_sandbox/notice/desktop_view_manager.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/sync/sync_service_factory.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window/public/browser_window_interface.h" #include "chrome/browser/ui/profiles/profile_customization_bubble_sync_controller.h" #include "chrome/common/webui_url_constants.h" +#include "components/sync/service/sync_service.h" #include "components/tabs/public/tab_interface.h" #include "components/web_modal/web_contents_modal_dialog_host.h" #include "content/public/browser/navigation_handle.h" @@ -95,6 +97,13 @@ return; } + // If a Sync setup is in progress, the prompt should not be shown. + if (auto* sync_service = SyncServiceFactory::GetForProfile(profile)) { + if (sync_service->IsSetupInProgress()) { + return; + } + } + // TODO(crbug.com/408016824): Add error-event histograms. HandleEntryPoint(browser_window_interface);
diff --git a/chrome/browser/privacy_sandbox/notice/desktop_entrypoint_handlers_browsertest.cc b/chrome/browser/privacy_sandbox/notice/desktop_entrypoint_handlers_browsertest.cc index cc097a1..228d9b0 100644 --- a/chrome/browser/privacy_sandbox/notice/desktop_entrypoint_handlers_browsertest.cc +++ b/chrome/browser/privacy_sandbox/notice/desktop_entrypoint_handlers_browsertest.cc
@@ -9,12 +9,14 @@ #include "chrome/browser/privacy_sandbox/notice/mocks/mock_notice_service.h" #include "chrome/browser/privacy_sandbox/notice/notice_service_factory.h" #include "chrome/browser/privacy_sandbox/notice/notice_service_interface.h" +#include "chrome/browser/sync/sync_service_factory.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/common/webui_url_constants.h" #include "chrome/test/base/platform_browser_test.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/ui_test_utils.h" +#include "components/sync/test/test_sync_service.h" #include "content/public/test/browser_test.h" #include "net/test/embedded_test_server/embedded_test_server.h" @@ -28,6 +30,24 @@ PrivacySandboxNoticeEntryPointHandlersTest() : https_test_server_(net::EmbeddedTestServer::TYPE_HTTPS) {} + void RegisterTestingSyncServiceFactory(content::BrowserContext* context) { + SyncServiceFactory::GetInstance()->SetTestingFactory( + context, + base::BindRepeating( + [](content::BrowserContext*) -> std::unique_ptr<KeyedService> { + return std::make_unique<syncer::TestSyncService>(); + })); + } + + void SetUpInProcessBrowserTestFixture() override { + services_subscription_ = + BrowserContextDependencyManager::GetInstance() + ->RegisterCreateServicesCallbackForTesting(base::BindRepeating( + &PrivacySandboxNoticeEntryPointHandlersTest:: + RegisterTestingSyncServiceFactory, + base::Unretained(this))); + } + void SetUpOnMainThread() override { https_test_server()->AddDefaultHandlers( base::FilePath(FILE_PATH_LITERAL("content/test/data"))); @@ -51,9 +71,15 @@ mock_notice_service_->GetDesktopViewManager()); } + syncer::TestSyncService* test_sync_service() { + return static_cast<syncer::TestSyncService*>( + SyncServiceFactory::GetForProfile(browser()->profile())); + } + protected: raw_ptr<MockPrivacySandboxNoticeService> mock_notice_service_; net::EmbeddedTestServer https_test_server_; + base::CallbackListSubscription services_subscription_; }; // Test that navigation to unsuitable URLS do not alert view manager. @@ -105,6 +131,37 @@ Mock::VerifyAndClearExpectations(mock_view_manager()); } +IN_PROC_BROWSER_TEST_F(PrivacySandboxNoticeEntryPointHandlersTest, + NoPromptSync) { + // Check when sync setup is in progress, that no prompt is shown. + EXPECT_CALL(*mock_view_manager(), HandleChromeOwnedPageNavigation).Times(0); + + test_sync_service()->SetSetupInProgress(); + + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), + GURL(chrome::kChromeUISettingsURL))); + + Mock::VerifyAndClearExpectations(mock_view_manager()); +} + +#if BUILDFLAG(ENABLE_DICE_SUPPORT) +// Check when profile setup is in progress, that no prompt is shown. +IN_PROC_BROWSER_TEST_F(PrivacySandboxNoticeEntryPointHandlersTest, + NoPromptProfileSetup) { + EXPECT_CALL(*mock_view_manager(), HandleChromeOwnedPageNavigation).Times(0); + // Show the profile customization dialog. + browser()->signin_view_controller()->ShowModalProfileCustomizationDialog( + /*is_local_profile_creation=*/true); + ASSERT_TRUE(ui_test_utils::NavigateToURLWithDisposition( + browser(), GURL(chrome::kChromeUINewTabPageURL), + WindowOpenDisposition::NEW_FOREGROUND_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP)); + + Mock::VerifyAndClearExpectations(mock_view_manager()); +} +#endif // BUILDFLAG(ENABLE_DICE_SUPPORT) + +// URLS check class PrivacySandboxNoticeEntryPointHandlersTest_SuitableUrls : public PrivacySandboxNoticeEntryPointHandlersTest, public testing::WithParamInterface<GURL> {}; @@ -130,23 +187,5 @@ GURL(url::kAboutBlankURL), GURL(chrome::kChromeUISettingsURL), GURL(chrome::kChromeUIHistoryURL))); - -#if BUILDFLAG(ENABLE_DICE_SUPPORT) -// Check when profile setup is in progress, that no prompt is shown. -IN_PROC_BROWSER_TEST_F(PrivacySandboxNoticeEntryPointHandlersTest, - NoPromptProfileSetup) { - EXPECT_CALL(*mock_view_manager(), HandleChromeOwnedPageNavigation).Times(0); - // Show the profile customization dialog. - browser()->signin_view_controller()->ShowModalProfileCustomizationDialog( - /*is_local_profile_creation=*/true); - ASSERT_TRUE(ui_test_utils::NavigateToURLWithDisposition( - browser(), GURL(chrome::kChromeUINewTabPageURL), - WindowOpenDisposition::NEW_FOREGROUND_TAB, - ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP)); - - Mock::VerifyAndClearExpectations(mock_view_manager()); -} -#endif // BUILDFLAG(ENABLE_DICE_SUPPORT) - } // namespace } // namespace privacy_sandbox
diff --git a/chrome/browser/resources/commerce/product_specifications/app.ts b/chrome/browser/resources/commerce/product_specifications/app.ts index 8779f61c..8ab7ff67 100644 --- a/chrome/browser/resources/commerce/product_specifications/app.ts +++ b/chrome/browser/resources/commerce/product_specifications/app.ts
@@ -464,10 +464,6 @@ } private computeShowComparisonTableList_() { - if (!loadTimeData.getBoolean('comparisonTableListEnabled')) { - return false; - } - return this.showEmptyState_ && this.id_ === null && this.sets_.length > 0 && this.appState_ === AppState.TABLE_EMPTY; } @@ -695,13 +691,7 @@ } protected seeAllSets_() { - if (loadTimeData.getBoolean('comparisonTableListEnabled')) { - this.productSpecificationsProxy_.showComparePage(true); - return; - } - - OpenWindowProxyImpl.getInstance().openUrl( - loadTimeData.getString('productSpecificationsManagementUrl')); + this.productSpecificationsProxy_.showComparePage(true); } protected async onUrlAdd_( @@ -1034,8 +1024,7 @@ // If we show the empty state and there are no comparison tables, try to // fetch them. - if (loadTimeData.getBoolean('comparisonTableListEnabled') && - this.showEmptyState_ && this.sets_.length === 0) { + if (this.showEmptyState_ && this.sets_.length === 0) { const {sets} = await this.shoppingApi_.getAllProductSpecificationsSets(); this.sets_ = sets; }
diff --git a/chrome/browser/resources/lens/overlay/side_panel/feedback_toast.ts b/chrome/browser/resources/lens/overlay/side_panel/feedback_toast.ts index 0346fd3..65089b3b 100644 --- a/chrome/browser/resources/lens/overlay/side_panel/feedback_toast.ts +++ b/chrome/browser/resources/lens/overlay/side_panel/feedback_toast.ts
@@ -76,6 +76,7 @@ protected onHideFeedbackToastClick() { this.hide(); + this.dispatchEvent(new CustomEvent('feedback-toast-dismissed')); } }
diff --git a/chrome/browser/resources/lens/overlay/side_panel/side_panel_app.html b/chrome/browser/resources/lens/overlay/side_panel/side_panel_app.html index b0802395..1163e0dd 100644 --- a/chrome/browser/resources/lens/overlay/side_panel/side_panel_app.html +++ b/chrome/browser/resources/lens/overlay/side_panel/side_panel_app.html
@@ -222,7 +222,7 @@ <cr-toast id="messageToast" duration="4000"> <div>[[toastMessage]]</div> - <cr-button on-click="onHideMessageToastClick"> + <cr-button id="messageToastDismissButton" on-click="onHideMessageToastClick"> $i18n{dismiss} </cr-button> </cr-toast>
diff --git a/chrome/browser/resources/lens/overlay/side_panel/side_panel_app.ts b/chrome/browser/resources/lens/overlay/side_panel/side_panel_app.ts index 69ad781..739fe67 100644 --- a/chrome/browser/resources/lens/overlay/side_panel/side_panel_app.ts +++ b/chrome/browser/resources/lens/overlay/side_panel/side_panel_app.ts
@@ -14,6 +14,7 @@ import {ColorChangeUpdater} from '//resources/cr_components/color_change_listener/colors_css_updater.js'; import {HelpBubbleMixin} from '//resources/cr_components/help_bubble/help_bubble_mixin.js'; import type {SearchboxElement} from '//resources/cr_components/searchbox/searchbox.js'; +import type {CrButtonElement} from '//resources/cr_elements/cr_button/cr_button.js'; import type {CrToastElement} from '//resources/cr_elements/cr_toast/cr_toast.js'; import {I18nMixin} from '//resources/cr_elements/i18n_mixin.js'; import {assert} from '//resources/js/assert.js'; @@ -29,7 +30,6 @@ import {handleEscapeSearchbox} from '../searchbox_utils.js'; import type {FeedbackToastElement} from './feedback_toast.js'; - import {PostMessageReceiver} from './post_message_communication.js'; import {getTemplate} from './side_panel_app.html.js'; import {SidePanelBrowserProxyImpl} from './side_panel_browser_proxy.js'; @@ -41,11 +41,17 @@ const VIEWPORT_HEIGHT_KEY = 'bih'; const VIEWPORT_WIDTH_KEY = 'biw'; +// The delay in milliseconds to reshow the feedback toast after it was hidden by +// another toast. This is only used if the feedback toast was not already +// dismissed. +const RESHOW_FEEDBACK_TOAST_DELAY_MS = 4100; + export interface LensSidePanelAppElement { $: { feedbackToast: FeedbackToastElement, ghostLoader: SidePanelGhostLoaderElement, messageToast: CrToastElement, + messageToastDismissButton: CrButtonElement, errorPage: SidePanelErrorPageElement, results: HTMLIFrameElement, searchbox: SearchboxElement, @@ -202,6 +208,10 @@ // window. private postMessageReceiver: PostMessageReceiver = new PostMessageReceiver(SidePanelBrowserProxyImpl.getInstance()); + // Whether the feedback toast has been explicitly dismissed by the user. + private feedbackToastDismissed = false; + // The timeout ID for reshowing the feedback toast. + private feedbackToastReshowTimeoutId = -1; private browserProxy: SidePanelBrowserProxy = SidePanelBrowserProxyImpl.getInstance(); @@ -260,6 +270,9 @@ this.eventTracker_.add( document, 'query-autocomplete', this.handleQueryAutocomplete.bind(this)); + this.eventTracker_.add( + this.$.feedbackToast, 'feedback-toast-dismissed', + () => this.feedbackToastDismissed = true); // Start listening to postMessages on the window. this.postMessageReceiver.listen(); @@ -290,7 +303,9 @@ // focused. this.blurSearchbox(); + clearTimeout(this.feedbackToastReshowTimeoutId); this.$.feedbackToast.hide(); + this.$.messageToast.hide(); } else { // Animate away the progress bar once the results are loaded. this.progressBarHideAnimation = this.$.uploadProgressBarContainer.animate( @@ -307,6 +322,7 @@ // Show the feedback on every result load by showing it as soon as the // result load animation is complete. + this.feedbackToastDismissed = false; this.showFeedbackToast(); } } @@ -474,6 +490,12 @@ private async showMessageToast(message: string) { this.$.feedbackToast.hide(); await this.showToast(this.$.messageToast, message); + if (!this.feedbackToastDismissed) { + clearTimeout(this.feedbackToastReshowTimeoutId); + this.feedbackToastReshowTimeoutId = setTimeout(() => { + this.showFeedbackToast(); + }, RESHOW_FEEDBACK_TOAST_DELAY_MS); + } } private async showToast(toast: CrToastElement, message?: string) { @@ -494,6 +516,10 @@ private onHideMessageToastClick() { this.$.messageToast.hide(); + if (!this.feedbackToastDismissed) { + clearTimeout(this.feedbackToastReshowTimeoutId); + this.showFeedbackToast(); + } } makeGhostLoaderVisibleForTesting() {
diff --git a/chrome/browser/resources/pdf/elements/viewer_text_bottom_toolbar.css b/chrome/browser/resources/pdf/elements/viewer_text_bottom_toolbar.css index 85f8c98..3822bdd9 100644 --- a/chrome/browser/resources/pdf/elements/viewer_text_bottom_toolbar.css +++ b/chrome/browser/resources/pdf/elements/viewer_text_bottom_toolbar.css
@@ -14,6 +14,7 @@ :host { --cr-focus-outline-color: var(--viewer-icon-focus-outline-color); border-radius: 16px 16px 0 0; + z-index: 2; /* The text box itself uses 1. Use 2 to layer above the box. */ } .md-select {
diff --git a/chrome/browser/safe_browsing/chrome_client_side_detection_host_delegate_unittest.cc b/chrome/browser/safe_browsing/chrome_client_side_detection_host_delegate_browsertest.cc similarity index 79% rename from chrome/browser/safe_browsing/chrome_client_side_detection_host_delegate_unittest.cc rename to chrome/browser/safe_browsing/chrome_client_side_detection_host_delegate_browsertest.cc index 5eb17ae3..1bc582253 100644 --- a/chrome/browser/safe_browsing/chrome_client_side_detection_host_delegate_unittest.cc +++ b/chrome/browser/safe_browsing/chrome_client_side_detection_host_delegate_browsertest.cc
@@ -11,20 +11,23 @@ #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager_factory.h" +#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/test/base/browser_with_test_window_test.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" #include "components/safe_browsing/content/browser/safe_browsing_navigation_observer.h" #include "components/safe_browsing/content/browser/safe_browsing_navigation_observer_manager.h" #include "components/safe_browsing/core/common/features.h" #include "content/public/browser/global_routing_id.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/browser_test.h" #include "content/public/test/navigation_simulator.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" namespace safe_browsing { -class ChromeClientSideDetectionHostDelegateTest - : public BrowserWithTestWindowTest { +class ChromeClientSideDetectionHostDelegateTest : public InProcessBrowserTest { public: ChromeClientSideDetectionHostDelegateTest() = default; @@ -33,23 +36,26 @@ ChromeClientSideDetectionHostDelegateTest& operator=( const ChromeClientSideDetectionHostDelegateTest&) = delete; - void SetUp() override { - BrowserWithTestWindowTest::SetUp(); - AddTab(browser(), GURL("http://foo/0")); - Profile* profile = Profile::FromBrowserContext( - browser()->tab_strip_model()->GetWebContentsAt(0)->GetBrowserContext()); + void SetUpOnMainThread() override { + InProcessBrowserTest::SetUpOnMainThread(); + ASSERT_TRUE(ui_test_utils::NavigateToURLWithDisposition( + browser(), GURL("http://foo/0"), + WindowOpenDisposition::NEW_FOREGROUND_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP)); + Profile* profile = browser()->profile(); navigation_observer_manager_ = SafeBrowsingNavigationObserverManagerFactory::GetForBrowserContext( profile); + ASSERT_TRUE(browser()->tab_strip_model()->GetActiveWebContents()); navigation_observer_ = std::make_unique<SafeBrowsingNavigationObserver>( - browser()->tab_strip_model()->GetWebContentsAt(0), + browser()->tab_strip_model()->GetActiveWebContents(), HostContentSettingsMapFactory::GetForProfile(profile), navigation_observer_manager_); } - void TearDown() override { + void TearDownOnMainThread() override { navigation_observer_.reset(); - BrowserWithTestWindowTest::TearDown(); + InProcessBrowserTest::TearDownOnMainThread(); } NavigationEventList* navigation_event_list() { @@ -62,7 +68,8 @@ std::unique_ptr<SafeBrowsingNavigationObserver> navigation_observer_; }; -TEST_F(ChromeClientSideDetectionHostDelegateTest, GetReferrerChain) { +IN_PROC_BROWSER_TEST_F(ChromeClientSideDetectionHostDelegateTest, + GetReferrerChain) { base::Time now = base::Time::Now(); base::Time one_second_ago = base::Time::FromSecondsSinceUnixEpoch( now.InSecondsFSinceUnixEpoch() - 1.0); @@ -86,7 +93,7 @@ std::unique_ptr<ChromeClientSideDetectionHostDelegate> csd_host_delegate = std::make_unique<ChromeClientSideDetectionHostDelegate>( - browser()->tab_strip_model()->GetWebContentsAt(0)); + browser()->tab_strip_model()->GetActiveWebContents()); csd_host_delegate->SetNavigationObserverManagerForTesting( navigation_observer_manager_); std::unique_ptr<ClientPhishingRequest> verdict(new ClientPhishingRequest); @@ -100,7 +107,8 @@ EXPECT_EQ("http://a.com/", referrer_chain[0].referrer_url()); } -TEST_F(ChromeClientSideDetectionHostDelegateTest, NoNavigationObserverManager) { +IN_PROC_BROWSER_TEST_F(ChromeClientSideDetectionHostDelegateTest, + NoNavigationObserverManager) { base::Time now = base::Time::Now(); base::Time one_second_ago = base::Time::FromSecondsSinceUnixEpoch( now.InSecondsFSinceUnixEpoch() - 1.0); @@ -115,7 +123,7 @@ std::unique_ptr<ChromeClientSideDetectionHostDelegate> csd_host_delegate = std::make_unique<ChromeClientSideDetectionHostDelegate>( - browser()->tab_strip_model()->GetWebContentsAt(0)); + browser()->tab_strip_model()->GetActiveWebContents()); std::unique_ptr<ClientPhishingRequest> verdict(new ClientPhishingRequest); csd_host_delegate->AddReferrerChain(verdict.get(), GURL("http://b.com/"), content::GlobalRenderFrameHostId());
diff --git a/chrome/browser/support_tool/screenshot_data_collector_browsertest.cc b/chrome/browser/support_tool/screenshot_data_collector_browsertest.cc index 6df3d20..3662041 100644 --- a/chrome/browser/support_tool/screenshot_data_collector_browsertest.cc +++ b/chrome/browser/support_tool/screenshot_data_collector_browsertest.cc
@@ -71,7 +71,7 @@ OpenNewTab(GURL(chrome::kChromeUINewTabPageURL)); // Select `new_page_id` in FakeDesktopMediaPickerFactory. - test_flags_.selected_source = new_page_id; + test_flags_.picker_result = new_page_id; picker_factory.SetTestFlags(&test_flags_, 1); data_collector.SetPickerFactoryForTesting(&picker_factory);
diff --git a/chrome/browser/ui/android/ephemeraltab/java/src/org/chromium/chrome/browser/ephemeraltab/EphemeralTabSheetContent.java b/chrome/browser/ui/android/ephemeraltab/java/src/org/chromium/chrome/browser/ephemeraltab/EphemeralTabSheetContent.java index c65d328..d5833b3 100644 --- a/chrome/browser/ui/android/ephemeraltab/java/src/org/chromium/chrome/browser/ephemeraltab/EphemeralTabSheetContent.java +++ b/chrome/browser/ui/android/ephemeraltab/java/src/org/chromium/chrome/browser/ephemeraltab/EphemeralTabSheetContent.java
@@ -287,8 +287,8 @@ } @Override - public @Nullable Integer getBackgroundColor() { - return null; + public boolean hasSolidBackgroundColor() { + return false; } @Nullable
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java index 8600099..e54aec7f 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
@@ -934,11 +934,7 @@ if (mAutocompleteInput.getPageClassification() == PageClassification.ANDROID_HUB_VALUE) { RecordUserAction.record("HubSearch.KeyboardEnterPressed"); - - if (!OmniboxFeatures.sAndroidHubSearchEnterPerformsSearch.getValue()) { - // For Hub Search, searching by keyboard typed query is not allowed so do nothing. - return; - } + // For Hub Search, default behavior kicks off search by pressing enter, do not return. } if (mAutocomplete.isPresent()) {
diff --git a/chrome/browser/ui/android/pdf/java/src/org/chromium/chrome/browser/pdf/PdfUtils.java b/chrome/browser/ui/android/pdf/java/src/org/chromium/chrome/browser/pdf/PdfUtils.java index 80ea64a..0506a50 100644 --- a/chrome/browser/ui/android/pdf/java/src/org/chromium/chrome/browser/pdf/PdfUtils.java +++ b/chrome/browser/ui/android/pdf/java/src/org/chromium/chrome/browser/pdf/PdfUtils.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser.pdf; +import android.content.ContentResolver; +import android.content.Context; import android.net.Uri; import android.os.Build; import android.os.ext.SdkExtensions; @@ -25,6 +27,7 @@ import org.chromium.content_public.browser.ContentFeatureList; import org.chromium.content_public.browser.ContentFeatureMap; import org.chromium.content_public.browser.LoadUrlParams; +import org.chromium.ui.base.MimeTypeUtils; import org.chromium.url.GURL; import java.io.File; @@ -333,6 +336,26 @@ } } + /** + * Encode content uri if it is PDF MIME type. + * + * @param uri The uri to be encoded. + * @param context The {@link Context} to retrieve {@link ContentResolver}. + * @return the encoded content uri if it is PDF MIME type; or null otherwise. + */ + public static @Nullable String getEncodedContentUri(@Nullable String uri, Context context) { + if (TextUtils.isEmpty(uri) + || !UrlConstants.CONTENT_SCHEME.equals(Uri.parse(uri).getScheme())) { + return null; + } + ContentResolver contentResolver = context.getContentResolver(); + String mimeType = contentResolver.getType(Uri.parse(uri)); + if (MimeTypeUtils.PDF_MIME_TYPE.equals(mimeType)) { + return PdfUtils.encodePdfPageUrl(uri); + } + return null; + } + static void recordPdfLoad() { RecordHistogram.recordBooleanHistogram("Android.Pdf.DocumentLoad", true); }
diff --git a/chrome/browser/ui/android/pdf/java/src/org/chromium/chrome/browser/pdf/PdfUtilsUnitTest.java b/chrome/browser/ui/android/pdf/java/src/org/chromium/chrome/browser/pdf/PdfUtilsUnitTest.java index 27706e3..c578d71b 100644 --- a/chrome/browser/ui/android/pdf/java/src/org/chromium/chrome/browser/pdf/PdfUtilsUnitTest.java +++ b/chrome/browser/ui/android/pdf/java/src/org/chromium/chrome/browser/pdf/PdfUtilsUnitTest.java
@@ -4,9 +4,14 @@ package org.chromium.chrome.browser.pdf; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.when; +import android.content.ContentResolver; +import android.content.Context; import android.net.Uri; +import android.text.TextUtils; import org.junit.After; import org.junit.Assert; @@ -22,11 +27,14 @@ import org.chromium.chrome.browser.util.ChromeFileProvider; import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.content_public.browser.LoadUrlParams; +import org.chromium.ui.base.MimeTypeUtils; @RunWith(BaseRobolectricTestRunner.class) public class PdfUtilsUnitTest { @Mock private LoadUrlParams mLoadUrlParams; @Mock private NativePage mNativePage; + @Mock private Context mContext; + @Mock private ContentResolver mContentResolver; private AutoCloseable mCloseableMocks; private String mPdfPageUrl; private String mPdfPageBlobUrl; @@ -51,6 +59,7 @@ ChromeFileProvider.setGeneratedUriForTesting(Uri.parse(CONTENT_URL)); mPdfPageUrl = PdfUtils.encodePdfPageUrl(PDF_LINK); mPdfPageBlobUrl = PdfUtils.encodePdfPageUrl(PDF_BLOB_URL); + when(mContext.getContentResolver()).thenReturn(mContentResolver); } @After @@ -233,4 +242,24 @@ Assert.assertEquals( "The decoded url should match", CONTENT_URL_SPECIAL_CHARACTER, decodedUrl); } + + @Test + public void testGetEncodedContentUri_PDF() { + when(mContentResolver.getType(any())).thenReturn(MimeTypeUtils.PDF_MIME_TYPE); + String encodedUrl = PdfUtils.getEncodedContentUri(CONTENT_URL, mContext); + Assert.assertFalse("The encoded url should exist", TextUtils.isEmpty(encodedUrl)); + } + + @Test + public void testGetEncodedContentUri_Image() { + when(mContentResolver.getType(any())).thenReturn("image/jpeg"); + String encodedUrl = PdfUtils.getEncodedContentUri(CONTENT_URL, mContext); + Assert.assertTrue("The encoded url should not exist", TextUtils.isEmpty(encodedUrl)); + } + + @Test + public void testGetEncodedContentUri_Https() { + String encodedUrl = PdfUtils.getEncodedContentUri(PDF_LINK, mContext); + Assert.assertTrue("The encoded url should not exist", TextUtils.isEmpty(encodedUrl)); + } }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/MiniOriginBarController.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/MiniOriginBarController.java index bce4f97..8524c1d 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/MiniOriginBarController.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/MiniOriginBarController.java
@@ -125,6 +125,7 @@ private FrameLayout.LayoutParams mDefaultLocationBarLayoutParams; private final TouchEventObserver mTouchEventObserver; private final InsetObserver mInsetObserver; + private final BooleanSupplier mIsOmniboxFocusedSupplier; private final int mDefaultLocationBarRightPadding; // The starting horizontal position of the location bar when the mini origin bar is in its // least-minimized state. @@ -154,7 +155,8 @@ InsetObserver insetObserver, ObservableSupplierImpl<Integer> controlContainerTranslationSupplier, ObservableSupplierImpl<Integer> controlContainerHeightSupplier, - ObservableSupplier<Boolean> isKeyboardAccessorySheetShowing) { + ObservableSupplier<Boolean> isKeyboardAccessorySheetShowing, + BooleanSupplier isOmniboxFocusedSupplier) { mLocationBar = locationBar; mIsFormFieldFocusedSupplier = isFormFieldFocusedSupplier; mKeyboardVisibilityDelegate = keyboardVisibilityDelegate; @@ -165,6 +167,7 @@ mControlContainerHeightSupplier = controlContainerHeightSupplier; mIsKeyboardAccessorySheetShowing = isKeyboardAccessorySheetShowing; mInsetObserver = insetObserver; + mIsOmniboxFocusedSupplier = isOmniboxFocusedSupplier; mDefaultLocationBarRightPadding = mLocationBar.getContainerView().getPaddingRight(); mDefaultLocationBarLayoutParams = (FrameLayout.LayoutParams) mLocationBar.getContainerView().getLayoutParams(); @@ -193,11 +196,13 @@ : MiniOriginEvent.FORM_FIELD_LOST_FOCUS); }; mKeyboardVisibilityObserver = - (showing) -> - updateMiniOriginBarState( - showing - ? MiniOriginEvent.KEYBOARD_APPEARED - : MiniOriginEvent.KEYBOARD_DISAPPEARED); + (showing) -> { + if (mIsOmniboxFocusedSupplier.getAsBoolean()) return; + updateMiniOriginBarState( + showing + ? MiniOriginEvent.KEYBOARD_APPEARED + : MiniOriginEvent.KEYBOARD_DISAPPEARED); + }; mIsFormFieldFocusedSupplier.addObserver(mIsFormFieldFocusedObserver); mKeyboardVisibilityDelegate.addKeyboardVisibilityListener(mKeyboardVisibilityObserver); @@ -341,9 +346,10 @@ } private boolean waitingForImeAnimationToStart() { - return mMiniOriginBarState == MiniOriginState.READY - || mMiniOriginBarState == MiniOriginState.SHOWING - || mMiniOriginBarState == MiniOriginState.SUPPRESSED_BY_CLICK; + return !mIsOmniboxFocusedSupplier.getAsBoolean() + && (mMiniOriginBarState == MiniOriginState.READY + || mMiniOriginBarState == MiniOriginState.SHOWING + || mMiniOriginBarState == MiniOriginState.SUPPRESSED_BY_CLICK); } /**
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/MiniOriginBarControllerTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/MiniOriginBarControllerTest.java index ee3deebe..45cf4e31 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/MiniOriginBarControllerTest.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/MiniOriginBarControllerTest.java
@@ -50,6 +50,7 @@ import org.chromium.ui.InsetObserver; import java.util.Collections; +import java.util.function.BooleanSupplier; @RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE) @@ -91,6 +92,8 @@ new WindowInsetsAnimationCompat(WindowInsetsCompat.Type.ime(), null, 160); private final WindowInsetsAnimationCompat mNonImeAnimation = new WindowInsetsAnimationCompat(WindowInsetsCompat.Type.systemBars(), null, 160); + private boolean mOmniboxFocused; + private final BooleanSupplier mIsOmniboxFocusedSupplier = () -> mOmniboxFocused; @Before public void setUp() { @@ -114,7 +117,8 @@ mInsetObserver, mControlContainerTranslationSupplier, mControlContainerHeightSupplier, - mIsKeyboardAccessorySheetShowing); + mIsKeyboardAccessorySheetShowing, + mIsOmniboxFocusedSupplier); } @Test @@ -472,5 +476,21 @@ MiniOriginState.SHOWING, mMiniOriginBarController.getCurrentStateForTesting()); } + @Test + public void testOmniboxFocused() { + doReturn(ControlsPosition.BOTTOM).when(mBrowserControlsSizer).getControlsPosition(); + mMiniOriginBarController.onControlsPositionChanged(ControlsPosition.BOTTOM); + + mIsFormFieldFocused.onNodeAttributeUpdated(true, false); + mOmniboxFocused = true; + + final MiniOriginWindowInsetsAnimationListener animationListener = + mMiniOriginBarController.getAnimationListenerForTesting(); + + animationListener.onPrepare(mImeAnimation); + mKeyboardVisibilityDelegate.setVisibilityForTests(true); + verify(mLocationBar, never()).setShowOriginOnly(anyBoolean()); + } + // show again, start, finish showing (predictive back) }
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_list_controller.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_list_controller.cc index 0057efc..823e1f3 100644 --- a/chrome/browser/ui/views/desktop_capture/desktop_media_list_controller.cc +++ b/chrome/browser/ui/views/desktop_capture/desktop_media_list_controller.cc
@@ -51,7 +51,9 @@ auto_accept_this_tab_capture_(ShouldAutoAcceptThisTabCapture()), auto_reject_this_tab_capture_( base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kThisTabCaptureAutoReject)) { + switches::kThisTabCaptureAutoReject)), + auto_reject_capture_(base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kCaptureAutoReject)) { DCHECK(dialog_); DCHECK(media_list_); } @@ -328,5 +330,5 @@ if (media_list_->GetMediaListType() == DesktopMediaList::Type::kCurrentTab) { return auto_reject_this_tab_capture_; } - return false; + return auto_reject_capture_; }
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_list_controller.h b/chrome/browser/ui/views/desktop_capture/desktop_media_list_controller.h index eb57d1b..a8375eb 100644 --- a/chrome/browser/ui/views/desktop_capture/desktop_media_list_controller.h +++ b/chrome/browser/ui/views/desktop_capture/desktop_media_list_controller.h
@@ -174,6 +174,7 @@ const std::string auto_select_source_; // Any source by its title. const bool auto_accept_this_tab_capture_; // Only for current-tab capture. const bool auto_reject_this_tab_capture_; // Only for current-tab capture. + const bool auto_reject_capture_; // Applies to any capture. base::WeakPtrFactory<DesktopMediaListController> weak_factory_{this}; };
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc index 94eb50e..de6235a4 100644 --- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc +++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
@@ -14,6 +14,7 @@ #include "base/functional/callback.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/user_metrics.h" +#include "base/types/expected.h" #include "build/build_config.h" #include "chrome/browser/media/webrtc/desktop_media_list.h" #include "chrome/browser/media/webrtc/desktop_media_picker_controller.h" @@ -46,6 +47,7 @@ #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_delegate.h" +#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/base/mojom/dialog_button.mojom.h" @@ -73,11 +75,12 @@ #include "chrome/browser/glic/resources/grit/glic_browser_resources.h" #endif -using content::DesktopMediaID; -using content::RenderFrameHost; -using content::WebContents; -using content::WebContentsMediaCaptureId; -using RequestSource = DesktopMediaPicker::Params::RequestSource; +using ::blink::mojom::MediaStreamRequestResult; +using ::content::DesktopMediaID; +using ::content::RenderFrameHost; +using ::content::WebContents; +using ::content::WebContentsMediaCaptureId; +using RequestSource = ::DesktopMediaPicker::Params::RequestSource; const DesktopMediaSourceViewStyle& GetGenericScreenStyle() { static const DesktopMediaSourceViewStyle style( @@ -406,8 +409,11 @@ base::BindOnce( [](DesktopMediaPickerDialogView* dialog) { // If the dialog is being closed then notify the parent about it. + // That the parent has not yet been detached indicates that there + // has been no result yet. We can infer that the user rejected. if (dialog->parent_) { - dialog->parent_->NotifyDialogResult(DesktopMediaID()); + dialog->parent_->NotifyDialogResult(base::unexpected( + MediaStreamRequestResult::PERMISSION_DENIED_BY_USER)); } }, this)); @@ -1156,7 +1162,10 @@ new DesktopMediaPickerDialogView(params, this, std::move(source_lists)); } -void DesktopMediaPickerImpl::NotifyDialogResult(const DesktopMediaID& source) { +void DesktopMediaPickerImpl::NotifyDialogResult( + base::expected<DesktopMediaID, MediaStreamRequestResult> result) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + // Once this method is called the |dialog_| will close and destroy itself. dialog_->DetachParent(); dialog_ = nullptr; @@ -1170,7 +1179,7 @@ // Notify the |callback_| asynchronously because it may need to destroy // DesktopMediaPicker. content::GetUIThreadTaskRunner({})->PostTask( - FROM_HERE, base::BindOnce(std::move(callback_), source)); + FROM_HERE, base::BindOnce(std::move(callback_), result)); } // static
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h index 84ff860..774bd5d 100644 --- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h +++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h
@@ -8,11 +8,13 @@ #include <string> #include "base/memory/raw_ptr.h" +#include "base/types/expected.h" #include "build/build_config.h" #include "chrome/browser/media/webrtc/desktop_media_picker.h" #include "chrome/browser/ui/views/desktop_capture/desktop_media_list_controller.h" #include "chrome/browser/ui/views/desktop_capture/desktop_media_pane_view.h" #include "chrome/browser/ui/views/desktop_capture/screen_capture_permission_checker.h" +#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h" #include "ui/base/interaction/element_identifier.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/base/mojom/dialog_button.mojom.h" @@ -220,7 +222,9 @@ DesktopMediaPickerImpl& operator=(const DesktopMediaPickerImpl&) = delete; ~DesktopMediaPickerImpl() override; - void NotifyDialogResult(const content::DesktopMediaID& source); + void NotifyDialogResult( + base::expected<content::DesktopMediaID, + blink::mojom::MediaStreamRequestResult> result); // DesktopMediaPicker: void Show(const DesktopMediaPicker::Params& params,
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc index 7b16b93..28cce78 100644 --- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc +++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc
@@ -16,6 +16,7 @@ #include "base/strings/strcat.h" #include "base/strings/utf_string_conversions.h" #include "base/task/single_thread_task_runner.h" +#include "base/types/expected.h" #include "build/build_config.h" #include "chrome/browser/media/webrtc/desktop_media_picker_controller.h" #include "chrome/browser/media/webrtc/desktop_media_picker_manager.h" @@ -32,6 +33,7 @@ #include "content/public/test/browser_task_environment.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/mojom/dialog_button.mojom.h" #include "ui/base/ui_base_switches.h" @@ -52,7 +54,12 @@ #include "base/mac/mac_util.h" #endif -using content::DesktopMediaID; +using ::blink::mojom::MediaStreamRequestResult; +using ::content::DesktopMediaID; + +using PickedIdOrErrorCode = + base::expected<content::DesktopMediaID, + blink::mojom::MediaStreamRequestResult>; namespace views { @@ -181,19 +188,19 @@ return picker_views_->GetDialogViewForTesting(); } - void OnPickerDone(content::DesktopMediaID picked_id) { - picked_id_ = picked_id; + void OnPickerDone(PickedIdOrErrorCode result) { + picker_result_ = result; run_loop_.Quit(); } - std::optional<content::DesktopMediaID> WaitForPickerDone() { + PickedIdOrErrorCode WaitForPickerResult() { run_loop_.Run(); - return picked_id_; + CHECK(picker_result_.has_value()); + return picker_result_.value(); } - std::optional<content::DesktopMediaID> picked_id() const { - return picked_id_; - } + // Checks whether `picker_result_` was ever set. + bool has_picker_result() const { return picker_result_.has_value(); } const std::vector<DesktopMediaList::Type>& source_types() { return source_types_; @@ -213,7 +220,7 @@ std::vector<DesktopMediaList::Type> delegated_source_types_; base::RunLoop run_loop_; - std::optional<content::DesktopMediaID> picked_id_; + std::optional<PickedIdOrErrorCode> picker_result_; std::unique_ptr<views::test::WidgetDestroyedWaiter> widget_destroyed_waiter_; base::WeakPtrFactory<DesktopMediaPickerViewsTestBase> weak_factory_{this}; @@ -235,7 +242,9 @@ TEST_P(DesktopMediaPickerViewsTest, DoneCallbackCalledWhenWindowClosed) { GetPickerDialogView()->GetWidget()->Close(); - EXPECT_EQ(content::DesktopMediaID(), WaitForPickerDone()); + EXPECT_EQ( + WaitForPickerResult(), + base::unexpected(MediaStreamRequestResult::PERMISSION_DENIED_BY_USER)); } TEST_P(DesktopMediaPickerViewsTest, DoneCallbackCalledOnOkButtonPressed) { @@ -254,7 +263,7 @@ ui::mojom::DialogButton::kOk)); GetPickerDialogView()->AcceptDialog(); - EXPECT_EQ(kFakeId, WaitForPickerDone()); + EXPECT_EQ(kFakeId, WaitForPickerResult()); } // Regression test for https://crbug.com/1102153 @@ -269,7 +278,7 @@ media_lists_[DesktopMediaList::Type::kScreen]->AddSourceByFullMediaID( kFakeId); test_api_.DoubleTapSourceAtIndex(0); - EXPECT_FALSE(picked_id().has_value()); + EXPECT_FALSE(has_picker_result()); } TEST_P(DesktopMediaPickerViewsTest, CancelButtonAlwaysEnabled) { @@ -365,7 +374,7 @@ test_api_.FocusSourceAtIndex(0); GetPickerDialogView()->AcceptDialog(); - EXPECT_EQ(result_id, WaitForPickerDone()); + EXPECT_EQ(result_id, WaitForPickerResult()); } TEST_P(DesktopMediaPickerViewsTest, OkButtonEnabledDuringAcceptSpecific) { @@ -386,7 +395,7 @@ ui::mojom::DialogButton::kOk)); GetPickerDialogView()->AcceptSpecificSource(fake_id); - EXPECT_EQ(fake_id, WaitForPickerDone()); + EXPECT_EQ(fake_id, WaitForPickerResult()); } #if BUILDFLAG(IS_MAC) @@ -617,7 +626,7 @@ media_lists_[Type()]->AddSourceByFullMediaID(fake_id); GetPickerDialogView()->AcceptSpecificSource(fake_id); - EXPECT_EQ(fake_id, WaitForPickerDone()); + EXPECT_EQ(fake_id, WaitForPickerResult()); } class DesktopMediaPickerViewsSystemAudioTest @@ -904,7 +913,7 @@ FROM_HERE, run_loop_.QuitClosure()); run_loop_.Run(); - EXPECT_FALSE(picked_id().has_value()); + EXPECT_FALSE(has_picker_result()); } // This class expects tests to directly call first SetSourceTypes() and then @@ -1011,7 +1020,9 @@ media_lists_[DesktopMediaList::Type::kScreen] ->OnDelegatedSourceListDismissed(); - EXPECT_EQ(DesktopMediaID(), WaitForPickerDone()); + EXPECT_EQ( + WaitForPickerResult(), + base::unexpected(MediaStreamRequestResult::PERMISSION_DENIED_BY_USER)); } // Creates a picker without the default fallback pane and verifies that when it @@ -1026,8 +1037,9 @@ media_lists_[DesktopMediaList::Type::kScreen] ->OnDelegatedSourceListDismissed(); - - EXPECT_EQ(DesktopMediaID(), WaitForPickerDone()); + EXPECT_EQ( + WaitForPickerResult(), + base::unexpected(MediaStreamRequestResult::PERMISSION_DENIED_BY_USER)); } #if BUILDFLAG(IS_MAC) @@ -1049,7 +1061,9 @@ // Dismissing the delegated source list should close the picker // without a selection. - EXPECT_EQ(content::DesktopMediaID(), WaitForPickerDone()); + EXPECT_EQ( + WaitForPickerResult(), + base::unexpected(MediaStreamRequestResult::PERMISSION_DENIED_BY_USER)); } // The delegated picker experience on MacOS (using SCContentSharingPicker)
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_tab_list_unittest.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_tab_list_unittest.cc index d9368ecd..60436b2 100644 --- a/chrome/browser/ui/views/desktop_capture/desktop_media_tab_list_unittest.cc +++ b/chrome/browser/ui/views/desktop_capture/desktop_media_tab_list_unittest.cc
@@ -59,7 +59,7 @@ "DesktopMediaPickerDialogView"); picker_views_->Show(picker_params, std::move(source_lists), - base::BindOnce([](content::DesktopMediaID id) {})); + base::DoNothing()); test_api_.set_picker(picker_views_.get()); tab_list_ =
diff --git a/chrome/browser/ui/views/desktop_capture/share_this_tab_dialog_views.cc b/chrome/browser/ui/views/desktop_capture/share_this_tab_dialog_views.cc index c47491f5..ae400d3 100644 --- a/chrome/browser/ui/views/desktop_capture/share_this_tab_dialog_views.cc +++ b/chrome/browser/ui/views/desktop_capture/share_this_tab_dialog_views.cc
@@ -7,6 +7,7 @@ #include "base/command_line.h" #include "base/metrics/histogram_functions.h" #include "base/time/time.h" +#include "base/types/expected.h" #include "build/build_config.h" #include "build/config/chromebox_for_meetings/buildflags.h" // PLATFORM_CFM #include "chrome/browser/media/webrtc/desktop_media_list.h" @@ -30,6 +31,7 @@ #include "content/public/browser/desktop_media_id.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents_delegate.h" +#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/base/mojom/dialog_button.mojom.h" @@ -53,6 +55,9 @@ namespace { +using ::blink::mojom::MediaStreamRequestResult; +using ::content::DesktopMediaID; + constexpr int kTitleTopMargin = 16; constexpr gfx::Insets kAudioToggleInsets = gfx::Insets::VH(8, 16); constexpr int kAudioToggleChildSpacing = 8; @@ -129,8 +134,11 @@ base::BindOnce( [](ShareThisTabDialogView* dialog) { // If the dialog is being closed then notify the parent about it. + // That the parent has not yet been detached indicates that there + // has been no result yet. We can infer that the user rejected. if (dialog->parent_) { - dialog->parent_->NotifyDialogResult(content::DesktopMediaID()); + dialog->parent_->NotifyDialogResult(base::unexpected( + MediaStreamRequestResult::PERMISSION_DENIED_BY_USER)); } }, this)); @@ -241,9 +249,8 @@ source_view_->StopRefreshing(); if (parent_ && web_contents_) { - content::DesktopMediaID desktop_media_id( - content::DesktopMediaID::TYPE_WEB_CONTENTS, - content::DesktopMediaID::kNullId, + DesktopMediaID desktop_media_id( + DesktopMediaID::TYPE_WEB_CONTENTS, DesktopMediaID::kNullId, content::WebContentsMediaCaptureId( web_contents_->GetPrimaryMainFrame() ->GetProcess() @@ -398,7 +405,8 @@ } void ShareThisTabMediaPicker::NotifyDialogResult( - const content::DesktopMediaID& source) { + base::expected<content::DesktopMediaID, + blink::mojom::MediaStreamRequestResult> result) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // Once this method is called the |dialog_| will close and destroy itself. @@ -414,5 +422,5 @@ // Notify the |callback_| asynchronously because it may need to destroy // DesktopMediaPicker. content::GetUIThreadTaskRunner({})->PostTask( - FROM_HERE, base::BindOnce(std::move(callback_), source)); + FROM_HERE, base::BindOnce(std::move(callback_), result)); }
diff --git a/chrome/browser/ui/views/desktop_capture/share_this_tab_dialog_views.h b/chrome/browser/ui/views/desktop_capture/share_this_tab_dialog_views.h index 4f46c1b..7c89f43 100644 --- a/chrome/browser/ui/views/desktop_capture/share_this_tab_dialog_views.h +++ b/chrome/browser/ui/views/desktop_capture/share_this_tab_dialog_views.h
@@ -8,9 +8,11 @@ #include <string> #include "base/memory/raw_ptr.h" +#include "base/types/expected.h" #include "build/build_config.h" #include "chrome/browser/media/webrtc/desktop_media_picker.h" #include "chrome/browser/ui/views/desktop_capture/share_this_tab_source_view.h" +#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h" #include "ui/base/interaction/element_identifier.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/views/controls/button/toggle_button.h" @@ -86,7 +88,9 @@ ShareThisTabMediaPicker& operator=(const ShareThisTabMediaPicker&) = delete; ~ShareThisTabMediaPicker() override; - void NotifyDialogResult(const content::DesktopMediaID& source); + void NotifyDialogResult( + base::expected<content::DesktopMediaID, + blink::mojom::MediaStreamRequestResult> result); // DesktopMediaPicker: void Show(const DesktopMediaPicker::Params& params,
diff --git a/chrome/browser/ui/views/location_bar/lens_overlay_homework_page_action_icon_view.cc b/chrome/browser/ui/views/location_bar/lens_overlay_homework_page_action_icon_view.cc index c93890f..21f1e6c 100644 --- a/chrome/browser/ui/views/location_bar/lens_overlay_homework_page_action_icon_view.cc +++ b/chrome/browser/ui/views/location_bar/lens_overlay_homework_page_action_icon_view.cc
@@ -29,6 +29,10 @@ #include "ui/views/interaction/element_tracker_views.h" #include "ui/views/view_class_properties.h" +#if BUILDFLAG(ENABLE_GLIC) +#include "chrome/browser/glic/glic_enabling.h" +#endif // BUILDFLAG(ENABLE_GLIC) + LensOverlayHomeworkPageActionIconView::LensOverlayHomeworkPageActionIconView( IconLabelBubbleView::Delegate* parent_delegate, Delegate* delegate, @@ -80,6 +84,14 @@ return false; } +#if BUILDFLAG(ENABLE_GLIC) + if (lens::features::IsLensOverlayEduActionChipDisabledByGlic() && + glic::GlicEnabling::IsEligibleForGlicTieredRollout( + browser_->GetProfile())) { + return false; + } +#endif // BUILDFLAG(ENABLE_GLIC) + if (!browser_->GetProfile()->GetPrefs()->GetBoolean( omnibox::kShowGoogleLensShortcut)) { return false;
diff --git a/chrome/browser/ui/views/toolbar/app_menu.cc b/chrome/browser/ui/views/toolbar/app_menu.cc index bc911ad..59526cd 100644 --- a/chrome/browser/ui/views/toolbar/app_menu.cc +++ b/chrome/browser/ui/views/toolbar/app_menu.cc
@@ -1356,8 +1356,12 @@ } } - auto* browser_view = BrowserView::GetBrowserViewForBrowser(browser_); - browser_view->toolbar_button_provider()->GetAppMenuButton()->OnMenuClosed(); + // This can be called if the app menu was open during browser destruction, at + // which point BrowserView may be in the process of being torn down. + // Null-check BrowserView to guard against such cases. + if (auto* browser_view = BrowserView::GetBrowserViewForBrowser(browser_)) { + browser_view->toolbar_button_provider()->GetAppMenuButton()->OnMenuClosed(); + } if (bookmark_menu_delegate_.get()) { BookmarkMergedSurfaceService* service =
diff --git a/chrome/browser/ui/views/toolbar/app_menu_interactive_uitest.cc b/chrome/browser/ui/views/toolbar/app_menu_interactive_uitest.cc index e3f814d9..47b8b58 100644 --- a/chrome/browser/ui/views/toolbar/app_menu_interactive_uitest.cc +++ b/chrome/browser/ui/views/toolbar/app_menu_interactive_uitest.cc
@@ -7,11 +7,13 @@ #include "base/test/bind.h" #include "build/buildflag.h" #include "chrome/browser/bookmarks/bookmark_model_factory.h" +#include "chrome/browser/lifetime/application_lifetime_desktop.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_element_identifiers.h" #include "chrome/browser/ui/toolbar/bookmark_sub_menu_model.h" #include "chrome/browser/ui/views/toolbar/browser_app_menu_button.h" +#include "chrome/test/base/ui_test_utils.h" #include "chrome/test/interaction/interactive_browser_test.h" #include "components/bookmarks/browser/bookmark_model.h" #include "components/bookmarks/browser/bookmark_model_observer.h" @@ -303,3 +305,16 @@ NameSubmenuChild(AppMenuModel::kBookmarksMenuItem, kBNodeMenuId, 9u), CheckViewProperty(kBNodeMenuId, &views::MenuItemView::title, u"a")); } + +using AppMenuInteractiveTest = InteractiveBrowserTest; + +IN_PROC_BROWSER_TEST_F(AppMenuInteractiveTest, DoNotCrashOnBrowserClose) { + RunTestSequence( + // Open the App menu. + PressButton(kToolbarAppMenuButtonElementId), + // Close all browsers, ensure the browser process does not crash. + Do([]() { + chrome::CloseAllBrowsers(); + ui_test_utils::WaitForBrowserToClose(); + })); +}
diff --git a/chrome/browser/ui/webui/commerce/product_specifications_ui.cc b/chrome/browser/ui/webui/commerce/product_specifications_ui.cc index a114d726..af7063af 100644 --- a/chrome/browser/ui/webui/commerce/product_specifications_ui.cc +++ b/chrome/browser/ui/webui/commerce/product_specifications_ui.cc
@@ -134,14 +134,10 @@ }; source->AddLocalizedStrings(kLocalizedStrings); - source->AddString("productSpecificationsManagementUrl", - kChromeUICompareListsUrl); source->AddString("compareLearnMoreUrl", kChromeUICompareLearnMoreUrl); source->AddInteger("maxNameLength", kMaxNameLength); source->AddInteger("maxTableSize", kMaxTableSize); - source->AddBoolean("comparisonTableListEnabled", true); - std::string email; signin::IdentityManager* identity_manager = IdentityManagerFactory::GetForProfile(profile);
diff --git a/chrome/browser/web_applications/isolated_web_apps/key_distribution/iwa_key_distribution_info_provider_unittest.cc b/chrome/browser/web_applications/isolated_web_apps/key_distribution/iwa_key_distribution_info_provider_unittest.cc index 4d80a05..a4c5628 100644 --- a/chrome/browser/web_applications/isolated_web_apps/key_distribution/iwa_key_distribution_info_provider_unittest.cc +++ b/chrome/browser/web_applications/isolated_web_apps/key_distribution/iwa_key_distribution_info_provider_unittest.cc
@@ -313,10 +313,6 @@ using ComponentRegistration = component_updater::ComponentRegistration; void SetUp() override { - web_app::IwaKeyDistributionInfoProvider::GetInstance()->SetUp( - base::BindRepeating( - &component_updater::IwaKeyDistributionComponentInstallerPolicy:: - QueueOnDemandUpdate)); auto cus = std::make_unique< testing::NiceMock<component_updater::MockComponentUpdateService>>(); cus_ = cus.get(); @@ -332,8 +328,7 @@ auto matcher, IwaKeyDistributionInfoProvider* key_provider, base::OnceClosure task) { - bool register_first = GetParam(); - if (register_first) { + if (register_first()) { ASSERT_THAT(test::RegisterIwaKeyDistributionComponentAndWaitForLoad(), matcher); key_provider->OnMaybeDownloadedComponentDataReady().Post(FROM_HERE, @@ -346,6 +341,8 @@ } } + bool register_first() const { return GetParam(); } + base::test::TaskEnvironment& task_environment() { return env_; } void WillRegisterAndLoadComponent(bool is_preloaded) { @@ -471,6 +468,11 @@ TEST_P(IwaIwaKeyDistributionInfoProviderReadinessTest, PreloadedComponentAndOnMaybeReadyCalledUpdateSuccess) { + if (!register_first()) { + GTEST_SKIP() << "Disabled until IWA become available outside of " + "non-initial profiles"; + } + WillRegisterAndLoadComponent(/*is_preloaded=*/true); WillRequestOnDemandUpdateWithSuccess(); @@ -501,6 +503,11 @@ TEST_P(IwaIwaKeyDistributionInfoProviderReadinessTest, PreloadedComponentAndOnMaybeReadyCalledUpdateFails) { + if (!register_first()) { + GTEST_SKIP() << "Disabled until IWA become available outside of " + "non-initial profiles"; + } + WillRegisterAndLoadComponent(/*is_preloaded=*/true); WillRequestOnDemandUpdateWithoutSuccess(); @@ -523,6 +530,11 @@ TEST_P(IwaIwaKeyDistributionInfoProviderReadinessTest, PreloadedComponentAndOnMaybeReadyCalledUpdateDelayedSuccess) { + if (!register_first()) { + GTEST_SKIP() << "Disabled until IWA become available outside of " + "non-initial profiles"; + } + WillRegisterAndLoadComponent(/*is_preloaded=*/true); WillRequestOnDemandUpdateWithSuccess(/*load_delay=*/base::Seconds(30));
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt index 9458fa4..a7533f02 100644 --- a/chrome/build/android-arm64.pgo.txt +++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@ -chrome-android64-main-1748368508-88655140671c5cad6b34eb5aad5a3f8dfb9c7abf-d08182b0ab799d89612b6f63d505bef7709e69c4.profdata +chrome-android64-main-1748390213-ccaf8520e13b590d876e94c75464a170cae0cfdd-09299ca336bc81469bbf1d7ce9044c8aaf755bc0.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index 683ad0d..8591ebd 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1748375992-89938c148ebb10d16f24dad1bbc2f3bdd729d010-4368a976ba269a508df94a10c67a6bdbdfae4830.profdata +chrome-mac-arm-main-1748390213-c4347f945a671f33fdbc22138aad8415939adea9-09299ca336bc81469bbf1d7ce9044c8aaf755bc0.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 18eee7e..eb5aba6 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1748368546-c18cfc3887ba2e44120dac714d516a6fdb3fb778-efe97c857f5fec7190a6eb042071b615d70daef1.profdata +chrome-mac-main-1748390213-6c43742e64b5fd50267e6e45a75da7edaf876004-09299ca336bc81469bbf1d7ce9044c8aaf755bc0.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt index 6fe52bf..05049420 100644 --- a/chrome/build/win-arm64.pgo.txt +++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@ -chrome-win-arm64-main-1748368546-b8505c64d06f03abc8bf45d491c6faf003ba2171-efe97c857f5fec7190a6eb042071b615d70daef1.profdata +chrome-win-arm64-main-1748390213-d2c32cf6045f34f32801c22d74d0baddd3649ea5-09299ca336bc81469bbf1d7ce9044c8aaf755bc0.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 6e5a05a..e632121 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1748336186-ccf2b8b07747c45f782c3149550d8b4f4ebd0701-21a6f9e1f5692d40d1ac97af5f6bd16d12239f36.profdata +chrome-win32-main-1748368546-8f299642069b3b5b693e632a1da9820609d73839-efe97c857f5fec7190a6eb042071b615d70daef1.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 596296a..d980913 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1748347148-6a52345518edc855e697cbd4d88213dc9a889ea7-f2633b5bd0e5d7b297519c24db7146f02911eaa1.profdata +chrome-win64-main-1748379548-c617c4f58f09b684b575c498c1114b30e1ae19b2-21369d0a37bf6f7db620dc940a43188af8d820f5.profdata
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 6efda4b..ceb1947 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc
@@ -629,11 +629,14 @@ // testing purposes. const char kSystemLogUploadFrequency[] = "system-log-upload-frequency"; -// This flag makes Chrome auto-accept/reject requests to capture the current +// These flags make Chrome auto-accept/reject requests to capture the current // tab. It should only be used for tests. const char kThisTabCaptureAutoAccept[] = "auto-accept-this-tab-capture"; const char kThisTabCaptureAutoReject[] = "auto-reject-this-tab-capture"; +// This flag makes Chrome auto-reject requests capture a tab/window/screen. +const char kCaptureAutoReject[] = "auto-reject-capture"; + // Custom delay for memory log. This should be used only for testing purpose. const char kTestMemoryLogDelayInMinutes[] = "test-memory-log-delay-in-minutes";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index 1323398..1afb66b 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h
@@ -56,6 +56,7 @@ extern const char kAutoSelectWindowCaptureSourceByTitle[]; extern const char kBrowserSigninAutoAccept[]; extern const char kBypassAccountAlreadyUsedByAnotherProfileCheck[]; +extern const char kCaptureAutoReject[]; extern const char kCheckForUpdateIntervalSec[]; extern const char kCipherSuiteBlacklist[]; extern const char kCrashOnHangThreads[];
diff --git a/chrome/common/extensions/api/api_sources.gni b/chrome/common/extensions/api/api_sources.gni index d79675ef..d8a7924 100644 --- a/chrome/common/extensions/api/api_sources.gni +++ b/chrome/common/extensions/api/api_sources.gni
@@ -20,7 +20,9 @@ "identity.idl", "notifications.idl", "scripting.idl", + "tabs.json", "webstore_private.json", + "windows.json", ] # Schemas that should be used only to auto-generate the C++ types. @@ -35,13 +37,6 @@ # Some APIs (e.g. cookies) rely on types and headers from other APIs. types_only_schema_sources_ = [] -if (enable_desktop_android_extensions) { - types_only_schema_sources_ += [ - "tabs.json", - "windows.json", - ] -} - if (enable_extensions) { schema_sources_ += [ "accessibility_features.json", @@ -81,7 +76,6 @@ "system_private.json", "tab_capture.idl", "tab_groups.json", - "tabs.json", "web_authentication_proxy.idl", "web_navigation.json", @@ -90,8 +84,6 @@ "webrtc_audio_private.idl", "webrtc_desktop_capture_private.idl", "webrtc_logging_private.idl", - - "windows.json", ] if (!is_android) {
diff --git a/chrome/common/request_header_integrity/BUILD.gn b/chrome/common/request_header_integrity/BUILD.gn index 6ae583d..dc06a76 100644 --- a/chrome/common/request_header_integrity/BUILD.gn +++ b/chrome/common/request_header_integrity/BUILD.gn
@@ -49,6 +49,7 @@ "//components/google/core/common", "//google_apis", "//services/network/public/cpp", + "//services/network/public/mojom", "//third_party/blink/public/common:headers", ] }
diff --git a/chrome/common/request_header_integrity/request_header_integrity_url_loader_throttle.cc b/chrome/common/request_header_integrity/request_header_integrity_url_loader_throttle.cc index 495d17c..37536f3 100644 --- a/chrome/common/request_header_integrity/request_header_integrity_url_loader_throttle.cc +++ b/chrome/common/request_header_integrity/request_header_integrity_url_loader_throttle.cc
@@ -18,6 +18,7 @@ #include "components/google/core/common/google_util.h" #include "google_apis/google_api_keys.h" #include "services/network/public/cpp/resource_request.h" +#include "services/network/public/mojom/network_context.mojom.h" #if BUILDFLAG(GOOGLE_CHROME_BRANDING) #include "chrome/common/request_header_integrity/internal/google_header_names.h" @@ -87,11 +88,14 @@ google_apis::GetAPIKey() + embedder_support::GetUserAgent()))); const std::string channel_name = GetChannelName(); if (!channel_name.empty()) { - request->headers.SetHeader(CHANNEL_NAME_HEADER_NAME, channel_name); + request->cors_exempt_headers.SetHeader(CHANNEL_NAME_HEADER_NAME, + channel_name); } - request->headers.SetHeader(LASTCHANGE_YEAR_HEADER_NAME, LASTCHANGE_YEAR); - request->headers.SetHeader(VALIDATE_HEADER_NAME, digest); - request->headers.SetHeader(COPYRIGHT_HEADER_NAME, CHROME_COPYRIGHT); + request->cors_exempt_headers.SetHeader(LASTCHANGE_YEAR_HEADER_NAME, + LASTCHANGE_YEAR); + request->cors_exempt_headers.SetHeader(VALIDATE_HEADER_NAME, digest); + request->cors_exempt_headers.SetHeader(COPYRIGHT_HEADER_NAME, + CHROME_COPYRIGHT); } // static @@ -99,4 +103,13 @@ return base::FeatureList::IsEnabled(kRequestHeaderIntegrity); } +// static +void RequestHeaderIntegrityURLLoaderThrottle::UpdateCorsExemptHeaders( + network::mojom::NetworkContextParams* params) { + params->cors_exempt_header_list.push_back(CHANNEL_NAME_HEADER_NAME); + params->cors_exempt_header_list.push_back(LASTCHANGE_YEAR_HEADER_NAME); + params->cors_exempt_header_list.push_back(VALIDATE_HEADER_NAME); + params->cors_exempt_header_list.push_back(COPYRIGHT_HEADER_NAME); +} + } // namespace request_header_integrity
diff --git a/chrome/common/request_header_integrity/request_header_integrity_url_loader_throttle.h b/chrome/common/request_header_integrity/request_header_integrity_url_loader_throttle.h index 71068da..90c92c1 100644 --- a/chrome/common/request_header_integrity/request_header_integrity_url_loader_throttle.h +++ b/chrome/common/request_header_integrity/request_header_integrity_url_loader_throttle.h
@@ -7,6 +7,10 @@ #include "third_party/blink/public/common/loader/url_loader_throttle.h" +namespace network::mojom { +class NetworkContextParams; +} + namespace request_header_integrity { class RequestHeaderIntegrityURLLoaderThrottle @@ -25,6 +29,8 @@ bool* defer) override; static bool IsFeatureEnabled(); + static void UpdateCorsExemptHeaders( + network::mojom::NetworkContextParams* params); }; } // namespace request_header_integrity
diff --git a/chrome/common/request_header_integrity/request_header_integrity_url_loader_throttle_unittest.cc b/chrome/common/request_header_integrity/request_header_integrity_url_loader_throttle_unittest.cc index 57aa49d..a7f8261 100644 --- a/chrome/common/request_header_integrity/request_header_integrity_url_loader_throttle_unittest.cc +++ b/chrome/common/request_header_integrity/request_header_integrity_url_loader_throttle_unittest.cc
@@ -48,10 +48,10 @@ network::ResourceRequest request; request.url = GURL("https://www.somesite.com/"); - ASSERT_TRUE(request.headers.IsEmpty()); + ASSERT_TRUE(request.cors_exempt_headers.IsEmpty()); bool ignored; throttle().WillStartRequest(&request, &ignored); - EXPECT_TRUE(request.headers.IsEmpty()); + EXPECT_TRUE(request.cors_exempt_headers.IsEmpty()); } #if !BUILDFLAG(GOOGLE_CHROME_BRANDING) @@ -59,10 +59,10 @@ network::ResourceRequest request; request.url = GURL("https://www.google.com/"); - ASSERT_TRUE(request.headers.IsEmpty()); + ASSERT_TRUE(request.cors_exempt_headers.IsEmpty()); bool ignored; throttle().WillStartRequest(&request, &ignored); - EXPECT_EQ(3u, request.headers.GetHeaderVector().size()); + EXPECT_EQ(3u, request.cors_exempt_headers.GetHeaderVector().size()); } #endif // !BUILDFLAG(GOOGLE_CHROME_BRANDING) @@ -79,15 +79,16 @@ network::ResourceRequest request; request.url = GURL("https://www.google.com/"); - ASSERT_TRUE(request.headers.IsEmpty()); + ASSERT_TRUE(request.cors_exempt_headers.IsEmpty()); bool ignored; throttle().WillStartRequest(&request, &ignored); - EXPECT_EQ(4u, request.headers.GetHeaderVector().size()); - EXPECT_TRUE(request.headers.HasHeader(CHANNEL_NAME_HEADER_NAME)); - EXPECT_TRUE(request.headers.HasHeader(LASTCHANGE_YEAR_HEADER_NAME)); - EXPECT_TRUE(request.headers.HasHeader(VALIDATE_HEADER_NAME)); + EXPECT_EQ(4u, request.cors_exempt_headers.GetHeaderVector().size()); + EXPECT_TRUE(request.cors_exempt_headers.HasHeader(CHANNEL_NAME_HEADER_NAME)); + EXPECT_TRUE( + request.cors_exempt_headers.HasHeader(LASTCHANGE_YEAR_HEADER_NAME)); + EXPECT_TRUE(request.cors_exempt_headers.HasHeader(VALIDATE_HEADER_NAME)); const std::optional<std::string> copyright = - request.headers.GetHeader(COPYRIGHT_HEADER_NAME); + request.cors_exempt_headers.GetHeader(COPYRIGHT_HEADER_NAME); ASSERT_TRUE(copyright.has_value()); EXPECT_NE(copyright->find("Copyright"), std::string::npos); }
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn index 14717902..e4537f6 100644 --- a/chrome/renderer/BUILD.gn +++ b/chrome/renderer/BUILD.gn
@@ -5,6 +5,7 @@ import("//build/config/buildflags_paint_preview.gni") import("//build/config/features.gni") import("//chrome/common/features.gni") +import("//chrome/common/request_header_integrity/buildflags.gni") import("//components/nacl/features.gni") import("//components/offline_pages/buildflags/features.gni") import("//components/optimization_guide/features.gni") @@ -138,6 +139,7 @@ "//chrome/common", "//chrome/common:mojo_bindings", "//chrome/common/net", + "//chrome/common/request_header_integrity:buildflags", "//chrome/common/search:mojo_bindings", "//chrome/services/speech/buildflags", "//components/autofill/content/renderer", @@ -296,6 +298,10 @@ ] } + if (enable_request_header_integrity) { + deps += [ "//chrome/common/request_header_integrity" ] + } + if (enable_widevine_cdm_component) { deps += [ "//third_party/widevine/cdm:headers" ] }
diff --git a/chrome/renderer/url_loader_throttle_provider_impl.cc b/chrome/renderer/url_loader_throttle_provider_impl.cc index 0ed2c94..8a15ac9b1 100644 --- a/chrome/renderer/url_loader_throttle_provider_impl.cc +++ b/chrome/renderer/url_loader_throttle_provider_impl.cc
@@ -14,6 +14,7 @@ #include "base/task/sequenced_task_runner.h" #include "build/build_config.h" #include "chrome/common/google_url_loader_throttle.h" +#include "chrome/common/request_header_integrity/buildflags.h" #include "chrome/renderer/chrome_content_renderer_client.h" #include "chrome/renderer/chrome_render_frame_observer.h" #include "chrome/renderer/chrome_render_thread_observer.h" @@ -44,6 +45,10 @@ #include "extensions/renderer/extension_throttle_manager.h" #endif +#if BUILDFLAG(ENABLE_REQUEST_HEADER_INTEGRITY) +#include "chrome/common/request_header_integrity/request_header_integrity_url_loader_throttle.h" // nogncheck crbug.com/1125897 +#endif + #if BUILDFLAG(IS_CHROMEOS) #include "chrome/renderer/ash_merge_session_loader_throttle.h" #endif // BUILDFLAG(IS_CHROMEOS) @@ -286,6 +291,15 @@ ->chromeos_listener())); #endif // BUILDFLAG(IS_CHROMEOS) +#if BUILDFLAG(ENABLE_REQUEST_HEADER_INTEGRITY) + if (request_header_integrity::RequestHeaderIntegrityURLLoaderThrottle:: + IsFeatureEnabled()) { + throttles.push_back( + std::make_unique<request_header_integrity:: + RequestHeaderIntegrityURLLoaderThrottle>()); + } +#endif + if (local_frame_token.has_value()) { auto throttle = content::MaybeCreateIdentityUrlLoaderThrottle(base::BindRepeating(
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 31762ce..2681b04 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -5452,6 +5452,7 @@ } if (safe_browsing_mode == 1) { sources += [ + "../browser/safe_browsing/chrome_client_side_detection_host_delegate_browsertest.cc", "../browser/safe_browsing/chrome_password_protection_service_browsertest.cc", "../browser/safe_browsing/chrome_password_protection_service_sync_browsertest.cc", "../browser/safe_browsing/client_side_detection_host_browsertest.cc", @@ -9601,7 +9602,6 @@ # TODO(sgurun): enable tests for safe_browsing==2. sources += [ "../browser/safe_browsing/advanced_protection_status_manager_desktop_unittest.cc", - "../browser/safe_browsing/chrome_client_side_detection_host_delegate_unittest.cc", "../browser/safe_browsing/chrome_password_reuse_detection_manager_client_unittest.cc", "../browser/safe_browsing/chrome_ping_manager_factory_unittest.cc", "../browser/safe_browsing/client_side_detection_host_unittest.cc",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherStation.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherStation.java index d50d478..85eb872 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherStation.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/TabSwitcherStation.java
@@ -36,7 +36,6 @@ import org.chromium.chrome.test.transit.page.PageStation; import org.chromium.chrome.test.transit.tabmodel.TabCountChangedCondition; import org.chromium.chrome.test.util.TabBinningUtil; -import org.chromium.components.omnibox.OmniboxFeatures; import java.util.List; @@ -72,22 +71,20 @@ newTabButtonElement = declareView(toolbarElement.descendant(withId(R.id.toolbar_action_button))); - if (OmniboxFeatures.sAndroidHubSearch.isEnabled()) { - declareElementFactory( - mActivityElement, - delayedElements -> { - Matcher<View> searchBox = withId(R.id.search_box); - ViewSpec<View> searchLoupe = - toolbarElement.descendant(withId(R.id.search_loupe)); - if (shouldHubSearchBoxBeVisible()) { - searchElement = delayedElements.declareView(searchLoupe); - delayedElements.declareNoView(searchBox); - } else { - searchElement = delayedElements.declareView(searchBox); - delayedElements.declareNoView(searchLoupe); - } - }); - } + declareElementFactory( + mActivityElement, + delayedElements -> { + Matcher<View> searchBox = withId(R.id.search_box); + ViewSpec<View> searchLoupe = + toolbarElement.descendant(withId(R.id.search_loupe)); + if (shouldHubSearchBoxBeVisible()) { + searchElement = delayedElements.declareView(searchLoupe); + delayedElements.declareNoView(searchBox); + } else { + searchElement = delayedElements.declareView(searchBox); + delayedElements.declareNoView(searchLoupe); + } + }); recyclerViewElement = declareView( paneHostElement.descendant(
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/MvtsFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/MvtsFacility.java index 2e1c58f..0a7b072 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/MvtsFacility.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/MvtsFacility.java
@@ -55,7 +55,8 @@ tilesLayoutElement = declareView(withId(R.id.mv_tiles_layout), ViewElement.displayingAtLeastOption(1)); declareEnterCondition( - new ViewHasChildrenCountCondition(tilesLayoutElement, mSiteSuggestions.size())); + new ViewHasChildrenCountCondition( + tilesLayoutElement, mSiteSuggestions.size() + mNonTileIndices.size())); // Will call declareItems() super.declareExtraElements();
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/RegularNewTabPageStation.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/RegularNewTabPageStation.java index b3507d8..21d22a1 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/RegularNewTabPageStation.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/RegularNewTabPageStation.java
@@ -27,6 +27,7 @@ import org.chromium.components.omnibox.OmniboxFeatures; import java.util.List; +import java.util.Set; /** * The New Tab Page screen, with an omnibox, most visited tiles, and the Feed instead of the @@ -82,9 +83,11 @@ * @param siteSuggestions the expected SiteSuggestions to be displayed. Use fakes ones for * testing. */ - public MvtsFacility focusOnMvts(List<SiteSuggestion> siteSuggestions) { + public MvtsFacility focusOnMvts( + List<SiteSuggestion> siteSuggestions, Set<Integer> nonTileIndices) { // Assume MVTs are on the screen; if this assumption changes, make sure to scroll to them. - return enterFacilitySync(new MvtsFacility(siteSuggestions), /* trigger= */ null); + return enterFacilitySync( + new MvtsFacility(siteSuggestions, nonTileIndices), /* trigger= */ null); } /** Click the URL bar to enter the Omnibox. */
diff --git a/chrome/test/data/pdf/ink2_manager_test.ts b/chrome/test/data/pdf/ink2_manager_test.ts index 01bd728..880d095 100644 --- a/chrome/test/data/pdf/ink2_manager_test.ts +++ b/chrome/test/data/pdf/ink2_manager_test.ts
@@ -9,7 +9,7 @@ import {assertAnnotationBrush, assertDeepEquals, MockDocumentDimensions, setGetAnnotationBrushReply, setUpInkTestContext} from './test_util.js'; -const {viewport, mockPlugin, mockWindow} = setUpInkTestContext(); +const {viewport, mockPlugin} = setUpInkTestContext(); const manager = Ink2Manager.getInstance(); function getTestAnnotation(id: number): TextAnnotation { @@ -29,7 +29,7 @@ pageNumber: 0, textBoxRect: { height: 35, - locationX: 20, + locationX: 60, locationY: 25, width: 50, }, @@ -51,16 +51,16 @@ } // Simulates the way the viewport is rotated from the plugin by setting updated -// DocumentDimensions. Assumes a non-rotated pageWidth of 80 and pageHeight of -// 100. +// DocumentDimensions. Assumes a non-rotated pageWidth of 400 and pageHeight of +// 500. function rotateViewport(orientation: number) { const rotatedDocumentDimensions = new MockDocumentDimensions(0, 0); // When the plugin notifies the viewport of new dimensions for a rotation, // it swaps the width and height if the page is oriented sideways. if (orientation === 0 || orientation === 2) { - rotatedDocumentDimensions.addPage(80, 100); + rotatedDocumentDimensions.addPage(400, 500); } else { - rotatedDocumentDimensions.addPage(100, 80); + rotatedDocumentDimensions.addPage(500, 400); } rotatedDocumentDimensions.layoutOptions = { defaultPageOrientation: orientation, // 90 degree CCW rotation @@ -185,7 +185,7 @@ testAnnotation2.text = 'Goodbye Moon'; testAnnotation2.textBoxRect = { height: 25, - locationX: 10, + locationX: 60, locationY: 65, width: 50, }; @@ -208,7 +208,7 @@ // Check that initializing a new annotation in a different location sets // a different id. let whenInitEvent = eventToPromise('initialize-text-box', testManager); - testManager.initializeTextAnnotation({x: 75, y: 20}); + testManager.initializeTextAnnotation({x: 200, y: 200}); let initEvent = await whenInitEvent; chrome.test.assertEq(2, initEvent.detail.annotation.id); chrome.test.assertEq('', initEvent.detail.annotation.text); @@ -217,13 +217,13 @@ // Check that the two existing annotations can be activated. mockPlugin.clearMessages(); whenInitEvent = eventToPromise('initialize-text-box', testManager); - testManager.initializeTextAnnotation({x: 30, y: 30}); + testManager.initializeTextAnnotation({x: 120, y: 30}); initEvent = await whenInitEvent; const testAnnotation1ScreenCoords = structuredClone(testAnnotation1); // Add page offsets. These are the defaults for the test viewport setup - // of a 90x90 page in a 100x100 window. + // of a 400x500 page in a 500x500 window. testAnnotation1ScreenCoords.textBoxRect.locationX = - testAnnotation1.textBoxRect.locationX + 10; + testAnnotation1.textBoxRect.locationX + 55; testAnnotation1ScreenCoords.textBoxRect.locationY = testAnnotation1.textBoxRect.locationY + 3; assertDeepEquals(testAnnotation1ScreenCoords, initEvent.detail.annotation); @@ -231,11 +231,11 @@ mockPlugin.clearMessages(); whenInitEvent = eventToPromise('initialize-text-box', testManager); - testManager.initializeTextAnnotation({x: 30, y: 70}); + testManager.initializeTextAnnotation({x: 120, y: 70}); initEvent = await whenInitEvent; const testAnnotation2ScreenCoords = structuredClone(testAnnotation2); testAnnotation2ScreenCoords.textBoxRect.locationX = - testAnnotation2.textBoxRect.locationX + 10; + testAnnotation2.textBoxRect.locationX + 55; testAnnotation2ScreenCoords.textBoxRect.locationY = testAnnotation2.textBoxRect.locationY + 3; assertDeepEquals(testAnnotation2ScreenCoords, initEvent.detail.annotation); @@ -321,11 +321,11 @@ // Confirm both scrollbars and mock viewport dimensions. chrome.test.assertTrue(viewport.documentHasScrollbars().vertical); chrome.test.assertTrue(viewport.documentHasScrollbars().horizontal); - chrome.test.assertEq(100, viewport.size.width); - chrome.test.assertEq(100, viewport.size.height); + chrome.test.assertEq(500, viewport.size.width); + chrome.test.assertEq(500, viewport.size.height); chrome.test.assertFalse(viewport.scrollbarWidth === 0); - const edge = 100 - viewport.scrollbarWidth; + const edge = 500 - viewport.scrollbarWidth; Ink2Manager.getInstance().initializeTextAnnotation({x: edge, y: 20}); chrome.test.assertEq(1, blurEvents); Ink2Manager.getInstance().initializeTextAnnotation({x: 20, y: edge}); @@ -341,15 +341,6 @@ }, async function testInitializeTextboxNoLocation() { - // Update the viewport to be sufficiently large to accommodate a default - // size textbox for testing. - const documentDimensions = new MockDocumentDimensions(0, 0); - documentDimensions.addPage(400, 500); - viewport.setDocumentDimensions(documentDimensions); - - // Make the viewport window larger. - mockWindow.setSize(500, 500); - let whenInitEvent = eventToPromise('initialize-text-box', manager); // Initialize without a location. This is what happens when the user creates // a textbox by using "Enter" on the plugin, instead of with the mouse. @@ -417,10 +408,11 @@ Ink2Manager.getInstance().initializeTextAnnotation(); initEvent = await whenInitEvent; - // The default width goes down from 222 to the width of the page, which is - // 195 at 0.5 zoom: (pageWidth - 2 * shadow) * zoom = (400 - 2 * 5) * .5. chrome.test.assertEq( MIN_TEXTBOX_SIZE_PX, initEvent.detail.annotation.textBoxRect.height); + + // The default width goes down from 222 to the width of the page, which is + // 195 at 0.5 zoom ( 400 * 0.5 - 2 * shadow ). // The page is centered on the viewport in the x direction, so it runs from // 152.5 to 347.5. The center is at (152.5 + 347.5) / 2 = 250. Subtract half // the default width to get the left edge. @@ -441,18 +433,11 @@ // Reset zoom, window size and annotation id for next test. viewport.setZoom(1.0); manager.resetAnnotationIdForTest(); - mockWindow.setSize(100, 100); chrome.test.succeed(); }, async function testInitializeTextBox() { - // Create a new mock document dimensions that has different width from - // height. This is relevant for testing different rotations. - const documentDimensions = new MockDocumentDimensions(0, 0); - documentDimensions.addPage(80, 100); - viewport.setDocumentDimensions(documentDimensions); - // Add listeners for the expected events that fire in response to an // initializeTextAnnotation call. let eventsDispatched: Array<{name: string, detail: any}> = []; @@ -478,21 +463,20 @@ MIN_TEXTBOX_SIZE_PX, initData.annotation.textBoxRect.height); chrome.test.assertEq(x, initData.annotation.textBoxRect.locationX); chrome.test.assertEq(y, initData.annotation.textBoxRect.locationY); - // Textbox width gets clamped because the page is small. chrome.test.assertEq( - rotation % 2 === 0 ? 70 : 90, initData.annotation.textBoxRect.width); + DEFAULT_TEXTBOX_WIDTH, initData.annotation.textBoxRect.width); chrome.test.assertEq(0, initData.annotation.pageNumber); chrome.test.assertEq(id, initData.annotation.id); chrome.test.assertEq(rotation, initData.annotation.textOrientation); - // Placeholder viewport has a 80x100 page and 100x100 window. + // Placeholder viewport has a 400x500 page and 500x500 window. // The y offset is always 3px, because the page is always positioned // 3px from the top. When the page is oriented vertically, it is centered // in the viewport with an additional 5px margin in x, creating pageX = - // (100 - 80)/2 + 5 = 15px offset. When the page is oriented horizontally, - // it is as wide as the viewport, so it uses the minimum 5px margin for - // pageX. + // (500 - 400)/2 + 5 = 55px offset. When the page is oriented + // horizontally, it is as wide as the viewport, so it uses the minimum + // 5px margin for pageX. chrome.test.assertEq( - rotation % 2 === 0 ? 15 : 5, initData.pageCoordinates.x); + rotation % 2 === 0 ? 55 : 5, initData.pageCoordinates.x); chrome.test.assertEq(3, initData.pageCoordinates.y); chrome.test.assertEq('attributes-changed', eventsDispatched[1]!.name); assertDeepEquals(attributes, eventsDispatched[1]!.detail); @@ -509,13 +493,13 @@ await verifyTextboxInit(/* x= */ 15, /* y= */ 10, /* rotations= */ 1, /* id= */ 0); rotateViewport(/* clockwiseRotations= */ 2); - await verifyTextboxInit(/* x= */ 50, /* y= */ 60, /* rotations= */ 2, + await verifyTextboxInit(/* x= */ 60, /* y= */ 60, /* rotations= */ 2, /* id= */ 1); rotateViewport(/* clockwiseRotations= */ 1); await verifyTextboxInit(/* x= */ 80, /* y = */ 20, /* rotations= */ 3, /* id= */ 2); rotateViewport(/* clockwiseRotations= */ 0); - await verifyTextboxInit(/* x= */ 20, /* y= */ 23, /* rotations= */ 0, + await verifyTextboxInit(/* x= */ 200, /* y= */ 23, /* rotations= */ 0, /* id= */ 3); chrome.test.succeed(); @@ -569,7 +553,7 @@ // Test committing annotations at different rotations to ensure the // conversion back to page coordinates works correctly. Note that the - // page screen rectangle will be 70x90 since there are 10px of page + // page screen rectangle will be 390x490 since there are 10px of page // shadow. // 90 degrees CCW @@ -579,8 +563,8 @@ annotationPageCoords.textBoxRect = { height: 50, width: 35, - locationX: 13, - locationY: 15, + locationX: 333, + locationY: 55, }; testCommitAnnotation(annotationScreenCoords, annotationPageCoords); // Delete to clear state. @@ -596,8 +580,8 @@ annotationPageCoords.textBoxRect = { height: 35, width: 50, - locationX: 15, - locationY: 33, + locationX: 335, + locationY: 433, }; testCommitAnnotation(annotationScreenCoords, annotationPageCoords); // Delete to clear state. @@ -614,7 +598,7 @@ height: 50, width: 35, locationX: 22, - locationY: 25, + locationY: 385, }; testCommitAnnotation(annotationScreenCoords, annotationPageCoords); // Delete to clear state. @@ -652,15 +636,15 @@ const whenUpdateEvent = eventToPromise('initialize-text-box', manager); // Click inside the existing text box area. - Ink2Manager.getInstance().initializeTextAnnotation({x: 40, y: 40}); + Ink2Manager.getInstance().initializeTextAnnotation({x: 80, y: 40}); await whenUpdateEvent; chrome.test.assertEq(2, eventsDispatched.length); chrome.test.assertEq('initialize-text-box', eventsDispatched[0]!.name); const initData = eventsDispatched[0]!.detail as TextBoxInit; const testAnnotation = getTestAnnotation(0); assertDeepEquals(testAnnotation, initData.annotation); - // Still using the 80x100 page from the previous test. - chrome.test.assertEq(15, initData.pageCoordinates.x); + // Still using the 400x500 page from the previous test. + chrome.test.assertEq(55, initData.pageCoordinates.x); chrome.test.assertEq(3, initData.pageCoordinates.y); chrome.test.assertEq('attributes-changed', eventsDispatched[1]!.name); assertDeepEquals( @@ -678,23 +662,23 @@ // pageMarginY * zoom = 3 * 1 chrome.test.assertEq(3, initialParams.pageDimensions.y); // (windowWidth - docWidth * zoom)/2 + pageMarginX * zoom = - // (100 - 80 * 1)/2 + 5 * 1 - chrome.test.assertEq(15, initialParams.pageDimensions.x); + // (500 - 400 * 1)/2 + 5 * 1 + chrome.test.assertEq(55, initialParams.pageDimensions.x); // 10px of width are taken up by PAGE_SHADOW. - chrome.test.assertEq(70, initialParams.pageDimensions.width); + chrome.test.assertEq(390, initialParams.pageDimensions.width); // 20px of height are also taken up by PAGE_SHADOW. - chrome.test.assertEq(90, initialParams.pageDimensions.height); + chrome.test.assertEq(490, initialParams.pageDimensions.height); chrome.test.assertEq(0, initialParams.clockwiseRotations); // In this new layout, the existing 50x35 annotation at page coordinate - // 5, 22 has its top left corner at 20, 25 in screen coordinates. Make + // 5, 22 has its top left corner at 60, 25 in screen coordinates. Make // sure clicking there creates the box, and clicking just outside of this // does not. mockPlugin.clearMessages(); - Ink2Manager.getInstance().initializeTextAnnotation({x: 20, y: 25}); + Ink2Manager.getInstance().initializeTextAnnotation({x: 60, y: 25}); verifyStartTextAnnotationMessage(true); mockPlugin.clearMessages(); - Ink2Manager.getInstance().initializeTextAnnotation({x: 19, y: 24}); + Ink2Manager.getInstance().initializeTextAnnotation({x: 59, y: 24}); verifyStartTextAnnotationMessage(false); // Zoom out should fire an event. @@ -705,19 +689,19 @@ // pageMarginY * zoom = 3 * .5 chrome.test.assertEq(1.5, changedEvent.detail.pageDimensions.y); // (windowWidth - docWidth * zoom)/2 + pageMarginX * zoom = - // (100 - 80 * .5)/2 + 5 * .5 - chrome.test.assertEq(32.5, changedEvent.detail.pageDimensions.x); - chrome.test.assertEq(35, changedEvent.detail.pageDimensions.width); - chrome.test.assertEq(45, changedEvent.detail.pageDimensions.height); + // (500 - 400 * .5)/2 + 5 * .5 + chrome.test.assertEq(152.5, changedEvent.detail.pageDimensions.x); + chrome.test.assertEq(195, changedEvent.detail.pageDimensions.width); + chrome.test.assertEq(245, changedEvent.detail.pageDimensions.height); chrome.test.assertEq(0, changedEvent.detail.clockwiseRotations); // In this new layout, the existing 50x35 annotation at page coordinate - // 5, 22 has its top left corner at 35, 12.5 in screen coordinates. + // 5, 22 has its top left corner at 155, 12.5 in screen coordinates. mockPlugin.clearMessages(); - Ink2Manager.getInstance().initializeTextAnnotation({x: 35, y: 13}); + Ink2Manager.getInstance().initializeTextAnnotation({x: 155, y: 13}); verifyStartTextAnnotationMessage(true); mockPlugin.clearMessages(); - Ink2Manager.getInstance().initializeTextAnnotation({x: 34, y: 12}); + Ink2Manager.getInstance().initializeTextAnnotation({x: 154, y: 12}); verifyStartTextAnnotationMessage(false); // Zoom in should fire an event. @@ -729,8 +713,8 @@ chrome.test.assertEq(6, changedEvent.detail.pageDimensions.y); // docWidth * zoom > windowWidth, so this is now pageMarginX * zoom = 5 * 2 chrome.test.assertEq(10, changedEvent.detail.pageDimensions.x); - chrome.test.assertEq(140, changedEvent.detail.pageDimensions.width); - chrome.test.assertEq(180, changedEvent.detail.pageDimensions.height); + chrome.test.assertEq(780, changedEvent.detail.pageDimensions.width); + chrome.test.assertEq(980, changedEvent.detail.pageDimensions.height); chrome.test.assertEq(0, changedEvent.detail.clockwiseRotations); // In this new layout, the existing 50x35 annotation at page coordinate @@ -751,8 +735,8 @@ chrome.test.assertEq(-34, changedEvent.detail.pageDimensions.y); // Shifts by -20 * zoom = -40 from previous position. chrome.test.assertEq(-30, changedEvent.detail.pageDimensions.x); - chrome.test.assertEq(140, changedEvent.detail.pageDimensions.width); - chrome.test.assertEq(180, changedEvent.detail.pageDimensions.height); + chrome.test.assertEq(780, changedEvent.detail.pageDimensions.width); + chrome.test.assertEq(980, changedEvent.detail.pageDimensions.height); chrome.test.assertEq(0, changedEvent.detail.clockwiseRotations); // In this new layout, the existing 50x35 annotation at page coordinate @@ -774,20 +758,22 @@ chrome.test.assertEq(-34, changedEvent.detail.pageDimensions.y); chrome.test.assertEq(-30, changedEvent.detail.pageDimensions.x); // Width and height are switched. - chrome.test.assertEq(180, changedEvent.detail.pageDimensions.width); - chrome.test.assertEq(140, changedEvent.detail.pageDimensions.height); + chrome.test.assertEq(980, changedEvent.detail.pageDimensions.width); + chrome.test.assertEq(780, changedEvent.detail.pageDimensions.height); // Rotations now non-zero. chrome.test.assertEq(3, changedEvent.detail.clockwiseRotations); // In this new layout, the existing 50x35 annotation at page coordinate - // 5, 22 has its top left corner at 14, -4 in screen coordinates. - // It has width 70 and height 100 so (85, 0) should be just outside the box - // and (84, 0) just inside. + // 5, 22 has its top left corner at 14, 636 in screen coordinates. This + // is outside the viewport, which is only 500px tall. Scroll down by 200, or + // 100 more in page coordinates, to put the box at 14, 436 so it can be + // activated. + viewport.goToPageAndXy(0, 20, 120); mockPlugin.clearMessages(); - Ink2Manager.getInstance().initializeTextAnnotation({x: 84, y: 0}); + Ink2Manager.getInstance().initializeTextAnnotation({x: 84, y: 436}); verifyStartTextAnnotationMessage(true); mockPlugin.clearMessages(); - Ink2Manager.getInstance().initializeTextAnnotation({x: 85, y: 0}); + Ink2Manager.getInstance().initializeTextAnnotation({x: 85, y: 436}); verifyStartTextAnnotationMessage(false); chrome.test.succeed(); @@ -799,11 +785,11 @@ rotateViewport(/* clockwiseRotations= */ 0); // 0 rotation. viewport.goToPageAndXy(0, 0, 0); - // Simulate creating a textbox at (55, 50) (near center of the viewport). - manager.initializeTextAnnotation({x: 55, y: 50}); + // Simulate creating a textbox at (255, 250) (near center of the viewport). + manager.initializeTextAnnotation({x: 255, y: 250}); // Zoom by 2x. This would cause the textbox to be out of the view, at - // location 110, 100. + // location 510, 500. viewport.setZoom(2.0); mockPlugin.clearMessages(); @@ -812,8 +798,8 @@ // there). Make sure the manager sends a message to the plugin to scroll // the viewport to the textbox. manager.textBoxFocused({ - locationX: 110, - locationY: 100, + locationX: 510, + locationY: 500, height: 50, width: 50, }); @@ -821,17 +807,17 @@ let syncScrollMessage = mockPlugin.findMessage('syncScrollToRemote'); chrome.test.assertTrue(syncScrollMessage !== undefined); chrome.test.assertEq('syncScrollToRemote', syncScrollMessage.type); - // The content is 160x200 (2x page size), and the viewport is 100x100. The + // The content is 800x1000 (2x page size), and the viewport is 500x500. The // scrollbar is 5px wide. // Max scroll is contentSize - viewportSize + scrollbarWidth. - // The max scroll is therefore 160 - 100 + 5 = 65 horizontally, so in the x - // direction scroll is clamped at 65, which is less than the desired scroll - // of 110 - .1 * viewportWidth = 100. - // Vertically, the desired y position is 100 - .1 * viewportHeight = 90, + // The max scroll is therefore 800 - 500 + 5 = 305 horizontally, so in the x + // direction scroll is clamped at 305, which is less than the desired scroll + // of 510 - .1 * viewportWidth = 460. + // Vertically, the desired y position is 500 - .1 * viewportHeight = 450, // which is within the max scroll of - // contentWidth - viewportWidth + scrollbarWidth = 105. - chrome.test.assertEq(65, syncScrollMessage.x); - chrome.test.assertEq(90, syncScrollMessage.y); + // contentHeight - viewportHeight + scrollbarWidth = 505. + chrome.test.assertEq(305, syncScrollMessage.x); + chrome.test.assertEq(450, syncScrollMessage.y); // Focusing a textbox that is already in the view shouldn't scroll the // viewport. @@ -855,11 +841,12 @@ syncScrollMessage = mockPlugin.findMessage('syncScrollToRemote'); chrome.test.assertTrue(syncScrollMessage !== undefined); chrome.test.assertEq('syncScrollToRemote', syncScrollMessage.type); - // Scroll x to maxScrollWidth - 20 - .1 * viewportWidth = 65 - 20 - 10 = 35. - // Scroll y to maxScrollHeight - 10 - .1 * viewportHeight = - // 90 - 10 - 10 = 70. - chrome.test.assertEq(35, syncScrollMessage.x); - chrome.test.assertEq(70, syncScrollMessage.y); + // Scroll x to maxScrollWidth - 20 - .1 * viewportWidth = 305 - 20 - 50 = + // 235. + // Scroll y to currentScrollY - 10 - .1 * viewportHeight = + // 450 - 10 - 50 = 390. + chrome.test.assertEq(235, syncScrollMessage.x); + chrome.test.assertEq(390, syncScrollMessage.y); chrome.test.succeed(); },
diff --git a/chrome/test/data/pdf/ink2_text_box_test.ts b/chrome/test/data/pdf/ink2_text_box_test.ts index 4f48c26..a1daa3c 100644 --- a/chrome/test/data/pdf/ink2_text_box_test.ts +++ b/chrome/test/data/pdf/ink2_text_box_test.ts
@@ -819,9 +819,9 @@ async function testEscapeAndDelete() { viewport.setZoom(1.0); - // Initialize to a 100x100 box at 10, 10. Place the box in the top corner + // Initialize to a 100x100 box at 55, 10. Place the box in the top corner // of the page, so that the viewport won't scroll when it is focused. - initializeBox(100, 100, 10, 10); + initializeBox(100, 100, 55, 10); // Wait for focus to happen so that we can correctly test focus changes // later. await eventToPromise('textbox-focused-for-test', textbox); @@ -862,7 +862,7 @@ // If the user is dragging, escape commits the annotation at the start // location and hides the box. - initializeBox(100, 100, 10, 10); + initializeBox(100, 100, 55, 10); await microtasksFinished(); chrome.test.assertTrue(isVisible(textbox)); mockPlugin.clearMessages(); @@ -884,7 +884,7 @@ verifyFinishTextAnnotationMessage(testAnnotation); // Escape without any modification hides the box but doesn't send a message. - initializeBox(100, 100, 10, 10); + initializeBox(100, 100, 55, 10); await microtasksFinished(); chrome.test.assertTrue(isVisible(textbox)); mockPlugin.clearMessages(); @@ -895,10 +895,10 @@ chrome.test.assertEq( undefined, mockPlugin.findMessage('setTextAnnotation')); - // Initialize to a 100x100 box at 10, 10 with some text content. Use + // Initialize to a 100x100 box at 55, 10 with some text content. Use // "Delete" to clear all the content, which will trigger a message since // this is for an existing annotation. - initializeBox(100, 100, 10, 10, true); + initializeBox(100, 100, 55, 10, true); await microtasksFinished(); chrome.test.assertFalse(textbox.hidden); chrome.test.assertTrue(isVisible(textbox)); @@ -999,12 +999,12 @@ // Using manager initialization to get correct coordinates for the zoom // level. - manager.initializeTextAnnotation({x: 20, y: 20}); + manager.initializeTextAnnotation({x: 60, y: 60}); await eventToPromise('textbox-focused-for-test', textbox); await microtasksFinished(); const styles = getComputedStyle(textbox); - chrome.test.assertEq('3px', styles.getPropertyValue('left')); - chrome.test.assertEq('5px', styles.getPropertyValue('top')); + chrome.test.assertEq('43px', styles.getPropertyValue('left')); + chrome.test.assertEq('45px', styles.getPropertyValue('top')); // Scroll away from the textbox. Note this method accepts page coordinates. // Scrolling by 35 in page coordinates scrolls by 70 in screen coordinates @@ -1016,8 +1016,8 @@ manager.dispatchEvent(new CustomEvent('blur-text-box')); viewport.goToPageAndXy(0, 35, 35); await microtasksFinished(); - chrome.test.assertEq('-67px', styles.getPropertyValue('left')); - chrome.test.assertEq('-65px', styles.getPropertyValue('top')); + chrome.test.assertEq('-27px', styles.getPropertyValue('left')); + chrome.test.assertEq('-25px', styles.getPropertyValue('top')); // Focus the textbox, which should cause the manager to scroll the viewport. // This won't actually scroll the viewport in the test, since the plugin @@ -1027,9 +1027,9 @@ const syncScrollMessage = mockPlugin.findMessage('syncScrollToRemote'); chrome.test.assertTrue(syncScrollMessage !== undefined); chrome.test.assertEq('syncScrollToRemote', syncScrollMessage.type); - // The box is at 20, 20 in viewport coordinates, and the viewport is 100px + // The box is at 60, 60 in viewport coordinates, and the viewport is 500px // wide. The manager specifies a margin of 10% of the viewport when - // scrolling. + // scrolling, so both of these end up at 10. chrome.test.assertEq(10, syncScrollMessage.x); chrome.test.assertEq(10, syncScrollMessage.y);
diff --git a/chrome/test/data/pdf/test_util.ts b/chrome/test/data/pdf/test_util.ts index 7db6411..434ee55 100644 --- a/chrome/test/data/pdf/test_util.ts +++ b/chrome/test/data/pdf/test_util.ts
@@ -560,26 +560,23 @@ // Sets up zoomable viewport and a dummy plugin for Ink. This combines the // functionality of getZoomableViewport() and setupTestMockPluginForInk(), which // are mutually exclusive since they both attempt to call setContent() on the -// viewport. Returns a reference to the new viewport, plugin and mock window. -export function setUpInkTestContext(): { - viewport: Viewport, - mockPlugin: MockPdfPluginElement, - mockWindow: MockElement, -} { +// viewport. Returns a reference to the new viewport and mock plugin. +export function setUpInkTestContext(): + {viewport: Viewport, mockPlugin: MockPdfPluginElement} { // Clear the DOM and create dummy content. document.body.innerHTML = ''; const dummyContent = document.createElement('div'); document.body.appendChild(dummyContent); // Create the viewport. - const mockWindow = new MockElement(100, 100, null); + const mockWindow = new MockElement(500, 500, null); const mockSizer = new MockSizer(); const viewport = new Viewport( mockWindow as unknown as HTMLElement, mockSizer as unknown as HTMLElement, dummyContent, /*scrollbarWidth=*/ 5, /*defaultZoom=*/ 1); viewport.setZoomFactorRange([0.25, 0.4, 0.5, 1, 2]); const documentDimensions = new MockDocumentDimensions(0, 0); - documentDimensions.addPage(90, 90); + documentDimensions.addPage(400, 500); viewport.setDocumentDimensions(documentDimensions); // Create mock plugin. @@ -611,7 +608,7 @@ // changes. In prod these are piped through the top level pdf-viewer element. viewport.setViewportChangedCallback(() => manager.viewportChanged()); - return {viewport, mockPlugin, mockWindow}; + return {viewport, mockPlugin}; } /**
diff --git a/chrome/test/data/webrtc/webrtc_getdisplaymedia_test.html b/chrome/test/data/webrtc/webrtc_getdisplaymedia_test.html index eec217d..c5f000a 100644 --- a/chrome/test/data/webrtc/webrtc_getdisplaymedia_test.html +++ b/chrome/test/data/webrtc/webrtc_getdisplaymedia_test.html
@@ -28,7 +28,7 @@ function compareErrors(expectedError) { return function(error) { - console.log('getUserMedia error: ' + error.name, error); + console.log('getDisplayMedia error: ' + error.name, error); return logAndReturn(error.toString() == expectedError ? "expected-error" : "unexpected-error"); @@ -36,7 +36,7 @@ } function handleError(error) { - console.log('getUserMedia error: ' + error.name, error); + console.log('getDisplayMedia error: ' + error.name, error); return logAndReturn("capture-failure"); }
diff --git a/chrome/test/data/webui/commerce/product_specifications/app_test.ts b/chrome/test/data/webui/commerce/product_specifications/app_test.ts index d57ad49c..6461abd 100644 --- a/chrome/test/data/webui/commerce/product_specifications/app_test.ts +++ b/chrome/test/data/webui/commerce/product_specifications/app_test.ts
@@ -2542,10 +2542,6 @@ const pluralStringProxy = new TestPluralStringProxy(); PluralStringProxyImpl.setInstance(pluralStringProxy); - loadTimeData.overrideValues({ - 'comparisonTableListEnabled': true, - }); - shoppingServiceApi.setResultFor( 'getAllProductSpecificationsSets', Promise.resolve({ sets: SPECS_SETS, @@ -2565,18 +2561,6 @@ }); }); - test('list does not appear when the feature is off', async () => { - loadTimeData.overrideValues({ - 'comparisonTableListEnabled': false, - }); - - const appElement = await createAppElement(); - await microtasksFinished(); - - const listElement = appElement.$.comparisonTableList; - assertFalse(isVisible(listElement)); - }); - test('list is hidden if there are no comparison tables', async () => { shoppingServiceApi.setResultFor( 'getAllProductSpecificationsSets', Promise.resolve({sets: []}));
diff --git a/chrome/test/data/webui/lens/side_panel/feedback_toast_test.ts b/chrome/test/data/webui/lens/side_panel/feedback_toast_test.ts index c0bbc1d..04e05ef 100644 --- a/chrome/test/data/webui/lens/side_panel/feedback_toast_test.ts +++ b/chrome/test/data/webui/lens/side_panel/feedback_toast_test.ts
@@ -16,10 +16,16 @@ import {TestLensSidePanelBrowserProxy} from './test_side_panel_browser_proxy.js'; +// The delay in milliseconds to reshow the feedback toast after it was hidden by +// another toast. This is only used if the feedback toast was not already +// dismissed. +const RESHOW_FEEDBACK_TOAST_DELAY_MS = 4100; + suite('FeedbackToast', () => { let testBrowserProxy: TestLensSidePanelBrowserProxy; let lensSidePanelElement: LensSidePanelAppElement; let callbackRouterRemote: LensSidePanelPageRemote; + let reshowFeedbackToastCallback: Function; function isRendered(el: HTMLElement) { // isVisible only checks if the bounding client rect is not empty and @@ -32,6 +38,10 @@ 'cr-toast')!; } + function getMessageToast(): CrToastElement { + return lensSidePanelElement.$.messageToast; + } + setup(() => { testBrowserProxy = new TestLensSidePanelBrowserProxy(); SidePanelBrowserProxyImpl.setInstance(testBrowserProxy); @@ -39,6 +49,21 @@ // Enable the new feedback feature. loadTimeData.overrideValues({'newFeedbackEnabled': true}); + + // Override setTimeout, and only alter behavior for the text received + // timeout. Using MockTimer did not work here, as it interfered with many + // other, unrelated timers causing tests to crash. + const origSetTimeout = window.setTimeout; + window.setTimeout = function( + handler: TimerHandler, timeout: number|undefined): number { + if (timeout === RESHOW_FEEDBACK_TOAST_DELAY_MS) { + const callback = handler as Function; + reshowFeedbackToastCallback = callback; + return 0; + } + return origSetTimeout(handler, timeout); + }; + callbackRouterRemote = testBrowserProxy.callbackRouter.$.bindNewPipeAndPassRemote(); document.body.innerHTML = window.trustedTypes!.emptyHTML; @@ -110,4 +135,119 @@ await testBrowserProxy.handler.whenCalled('requestSendFeedback'); assertFalse(isRendered(getFeedbackToast())); }); + + test('MessageToastHidesFeedbackToast', async () => { + // Show the feedback toast first. + callbackRouterRemote.setIsLoadingResults(false); + await waitAfterNextRender(lensSidePanelElement); + assertTrue(isRendered(getFeedbackToast())); + + // Show a message toast. + callbackRouterRemote.showToast('Test message'); + await waitAfterNextRender(lensSidePanelElement); + + // Feedback toast should be hidden. + assertFalse(isRendered(getFeedbackToast())); + assertTrue(isRendered(getMessageToast())); + }); + + test('FeedbackToastReshowsAfterMessageToastHidesAutomatically', async () => { + // Show the feedback toast first. + callbackRouterRemote.setIsLoadingResults(false); + await waitAfterNextRender(lensSidePanelElement); + assertTrue(isRendered(getFeedbackToast())); + + // Show a message toast. + callbackRouterRemote.showToast('Test message'); + await waitAfterNextRender(lensSidePanelElement); + assertFalse(isRendered(getFeedbackToast())); + assertTrue(isRendered(getMessageToast())); + + // Call the timeout. + reshowFeedbackToastCallback(); + await waitAfterNextRender(lensSidePanelElement); + + // Feedback toast should reappear. + assertTrue(isRendered(getFeedbackToast())); + assertFalse(isRendered(getMessageToast())); + }); + + test( + 'FeedbackToastReshowsImmediatelyAfterMessageToastDismissed', async () => { + // Show the feedback toast first. + callbackRouterRemote.setIsLoadingResults(false); + await waitAfterNextRender(lensSidePanelElement); + assertTrue(isRendered(getFeedbackToast())); + + // Show a message toast. + callbackRouterRemote.showToast('Test message'); + await waitAfterNextRender(lensSidePanelElement); + assertFalse(isRendered(getFeedbackToast())); + assertTrue(isRendered(getMessageToast())); + + // Dismiss the message toast. + lensSidePanelElement.$.messageToastDismissButton.click(); + await waitAfterNextRender(lensSidePanelElement); + + // Feedback toast should reappear immediately. + assertTrue(isRendered(getFeedbackToast())); + assertFalse(isRendered(getMessageToast())); + }); + + test('FeedbackToastDoesNotReshowIfDismissedByUser', async () => { + // Show the feedback toast first. + callbackRouterRemote.setIsLoadingResults(false); + await waitAfterNextRender(lensSidePanelElement); + assertTrue(isRendered(getFeedbackToast())); + + // Click the close button, which should hide the feedback toast. + const closeButton = + lensSidePanelElement.$.feedbackToast.shadowRoot.querySelector( + 'cr-icon-button'); + assertTrue(closeButton !== null); + closeButton.click(); + await waitAfterNextRender(lensSidePanelElement); + assertFalse(isRendered(getFeedbackToast())); + + // Show a message toast. + callbackRouterRemote.showToast('Test message'); + await waitAfterNextRender(lensSidePanelElement); + assertFalse(isRendered(getFeedbackToast())); + assertTrue(isRendered(getMessageToast())); + + // Call the timeout. + reshowFeedbackToastCallback(); + await waitAfterNextRender(lensSidePanelElement); + + // Feedback toast should not reappear. + assertFalse(isRendered(getFeedbackToast())); + }); + + test('FinishingLoadResetsDismissedStateAndShowsFeedbackToast', async () => { + // Show the feedback toast first. + callbackRouterRemote.setIsLoadingResults(false); + await waitAfterNextRender(lensSidePanelElement); + assertTrue(isRendered(getFeedbackToast())); + + // Click the close button, which should hide the feedback toast. + const closeButton = + lensSidePanelElement.$.feedbackToast.shadowRoot.querySelector( + 'cr-icon-button'); + assertTrue(closeButton !== null); + closeButton.click(); + await waitAfterNextRender(lensSidePanelElement); + assertFalse(isRendered(getFeedbackToast())); + + // Start and finish a new load. + callbackRouterRemote.setIsLoadingResults(true); + await waitAfterNextRender(lensSidePanelElement); + assertFalse(isRendered(getFeedbackToast())); + + callbackRouterRemote.setIsLoadingResults(false); + await waitAfterNextRender(lensSidePanelElement); + + // Feedback toast should reappear because the dismissed state was reset on + // load finish. + assertTrue(isRendered(getFeedbackToast())); + }); });
diff --git a/chrome/updater/enterprise/win/google/generate_group_policy_template_admx.py b/chrome/updater/enterprise/win/google/generate_group_policy_template_admx.py index 8550b17..b0ae7c7 100755 --- a/chrome/updater/enterprise/win/google/generate_group_policy_template_admx.py +++ b/chrome/updater/enterprise/win/google/generate_group_policy_template_admx.py
@@ -370,7 +370,64 @@ <supportedOn ref="Sup_GoogleUpdate1_3_34_3" /> <enabledValue><decimal value="1" /></enabledValue> <disabledValue><decimal value="0" /></disabledValue> - </policy>''' + </policy> + <policy name="Pol_MajorVersionRollout%(AppLegalId)s" class="Machine" + displayName="$(string.Pol_MajorVersionRollout)" + explainText="$(string.Explain_MajorVersionRollout%(AppLegalId)s)" + presentation="$(presentation.Pol_MajorVersionRollout)" + key="%(RootPolicyKey)s"> + <parentCategory ref="Cat_%(AppLegalId)s" /> + <supportedOn ref="Sup_GoogleUpdate138_0_7200_0" /> + <elements> + <enum id="Part_MajorVersion" + valueName="MajorVerionRollout%(AppGuid)s" required="true"> + <item displayName="$(string.Name_RolloutDefault)"> + <value> + <decimal value="0" /> + </value> + </item> + <item displayName="$(string.Name_RolloutSlow)"> + <value> + <decimal value="1" /> + </value> + </item> + <item displayName="$(string.Name_RolloutFast)"> + <value> + <decimal value="2" /> + </value> + </item> + </enum> + </elements> + </policy> + <policy name="Pol_MinorVersionRollout%(AppLegalId)s" class="Machine" + displayName="$(string.Pol_MinorVersionRollout)" + explainText="$(string.Explain_MinorVersionRollout%(AppLegalId)s)" + presentation="$(presentation.Pol_MinorVersionRollout)" + key="%(RootPolicyKey)s"> + <parentCategory ref="Cat_%(AppLegalId)s" /> + <supportedOn ref="Sup_GoogleUpdate138_0_7200_0" /> + <elements> + <enum id="Part_MinorVersion" + valueName="MinorVerionRollout%(AppGuid)s" required="true"> + <item displayName="$(string.Name_RolloutDefault)"> + <value> + <decimal value="0" /> + </value> + </item> + <item displayName="$(string.Name_RolloutSlow)"> + <value> + <decimal value="1" /> + </value> + </item> + <item displayName="$(string.Name_RolloutFast)"> + <value> + <decimal value="2" /> + </value> + </item> + </enum> + </elements> + </policy> + ''' ADMX_FOOTER = '</policyDefinitions>' @@ -520,6 +577,7 @@ ('Sup_GoogleUpdate1_3_34_3', 'At least Google Update 1.3.34.3'), ('Sup_GoogleUpdate1_3_35_441', 'At least Google Update 1.3.35.441'), ('Sup_GoogleUpdate1_3_35_453', 'At least Google Update 1.3.35.453'), + ('Sup_GoogleUpdate138_0_7200_0', 'At least GoogleUpdater 138.0.7200.0'), ('Cat_GoogleUpdate', 'Google Update'), ('Cat_Preferences', 'Preferences'), ('Cat_ProxyServer', 'Proxy Server'), @@ -541,6 +599,8 @@ ('Pol_TargetChannel', 'Target Channel override'), ('Pol_TargetVersionPrefix', 'Target version prefix override'), ('Pol_RollbackToTargetVersion', 'Rollback to Target version'), + ('Pol_MajorVersionRollout', 'Major version rollout'), + ('Pol_MinorVersionRollout', 'Major version rollout'), ('Part_AutoUpdateCheckPeriod', 'Minutes between update checks'), ('Part_UpdateCheckSuppressedStartHour', 'Hour in a day that start to suppress update check'), @@ -561,10 +621,15 @@ ('Part_UpdatePolicy', 'Policy'), ('Part_TargetChannel', 'Target Channel'), ('Part_TargetVersionPrefix', 'Target version prefix'), + ('Part_MajorVersion', 'Rollout Policy'), + ('Part_MinorVersion', 'Rollout Policy'), ('Name_UpdatesEnabled', 'Always allow updates (recommended)'), ('Name_ManualUpdatesOnly', 'Manual updates only'), ('Name_AutomaticUpdatesOnly', 'Automatic silent updates only'), ('Name_UpdatesDisabled', 'Updates disabled'), + ('Name_RolloutDefault', 'Participate in gradual rollout (recommended)'), + ('Name_RolloutSlow', 'Update only after gradual rollout completes'), + ('Name_RolloutFast', 'Update immediately when gradual rollout starts'), ('ProxyDisabled_DropDown', 'Never use a proxy'), ('ProxyAutoDetect_DropDown', 'Auto detect proxy settings'), ('ProxyPacScript_DropDown', 'Use a .pac proxy script'), @@ -728,6 +793,14 @@ </textBox> </presentation> <presentation id="Pol_RollbackToTargetVersion" /> + <presentation id="Pol_MajorVersionRollout"> + <dropdownList refId="Part_MajorVersion" + defaultItem="0">Policy</dropdownList> + </presentation> + <presentation id="Pol_MinorVersionRollout"> + <dropdownList refId="Part_MinorVersion" + defaultItem="0">Policy</dropdownList> + </presentation> ''' ADML_RESOURCE_TABLE_TEMPLATE = ''' @@ -869,6 +942,20 @@ string_definition_list.append( app_rollback_to_target_version_explanation) + string_definition_list.append( + ('Explain_MajorVersionRollout' + app_legal_id, + 'Specifies when to apply major %s updates that are gradually ' + 'rolling out. Major updates often have fixes, security patches, ' + 'and new features.\n\n' + '%s' % (app_name, ADML_DOMAIN_REQUIREMENT_EN))) + + string_definition_list.append( + ('Explain_MinorVersionRollout' + app_legal_id, + 'Specifies when to apply minor %s updates that are gradually ' + 'rolling out. Minor version updates often have fixes and ' + 'security patches, but rarely contain new features.\n\n' + '%s' % (app_name, ADML_DOMAIN_REQUIREMENT_EN))) + app_resource_strings = [] for entry in string_definition_list: app_resource_strings.append(' <string id="%s">%s</string>' %
diff --git a/chrome/updater/installer.cc b/chrome/updater/installer.cc index 15073890..6cf32d63 100644 --- a/chrome/updater/installer.cc +++ b/chrome/updater/installer.cc
@@ -15,6 +15,7 @@ #include "base/functional/callback.h" #include "base/logging.h" #include "base/notreached.h" +#include "base/strings/string_number_conversions.h" #include "base/task/thread_pool.h" #include "base/threading/scoped_blocking_call.h" #include "base/time/time.h" @@ -86,6 +87,8 @@ const std::string& target_channel, const std::string& target_version_prefix, bool rollback_allowed, + std::optional<int> major_version_rollout_policy, + std::optional<int> minor_version_rollout_policy, bool update_disabled, UpdateService::PolicySameVersionUpdate policy_same_version_update, scoped_refptr<PersistedData> persisted_data, @@ -96,6 +99,8 @@ install_data_index_(install_data_index), install_source_(install_source), rollback_allowed_(rollback_allowed), + major_version_rollout_policy_(major_version_rollout_policy), + minor_version_rollout_policy_(minor_version_rollout_policy), target_channel_(target_channel), target_version_prefix_(target_version_prefix), update_disabled_(update_disabled), @@ -161,6 +166,16 @@ component.target_version_prefix = target_version_prefix_; component.updates_enabled = !update_disabled_; component.install_source = install_source_; + if (major_version_rollout_policy_) { + component.installer_attributes.emplace( + "major_version_rollout_policy", + base::NumberToString(*major_version_rollout_policy_)); + } + if (minor_version_rollout_policy_) { + component.installer_attributes.emplace( + "minor_version_rollout_policy", + base::NumberToString(*minor_version_rollout_policy_)); + } std::move(callback).Run(component); }
diff --git a/chrome/updater/installer.h b/chrome/updater/installer.h index 1a029c09..bcd4873 100644 --- a/chrome/updater/installer.h +++ b/chrome/updater/installer.h
@@ -104,6 +104,8 @@ const std::string& target_channel, const std::string& target_version_prefix, bool rollback_allowed, + std::optional<int> major_version_rollout_policy, + std::optional<int> minor_version_rollout_policy, bool update_disabled, UpdateService::PolicySameVersionUpdate policy_same_version_update, scoped_refptr<PersistedData> persisted_data, @@ -162,6 +164,8 @@ const std::string install_data_index_; const std::string install_source_; const bool rollback_allowed_; + const std::optional<int> major_version_rollout_policy_; + const std::optional<int> minor_version_rollout_policy_; const std::string target_channel_; const std::string target_version_prefix_; const bool update_disabled_;
diff --git a/chrome/updater/installer_unittest.cc b/chrome/updater/installer_unittest.cc index 7e00422..d72c07b 100644 --- a/chrome/updater/installer_unittest.cc +++ b/chrome/updater/installer_unittest.cc
@@ -44,6 +44,8 @@ base::MakeRefCounted<Installer>( "id", "client_install_data", "install_data_index", "install_source", "target_channel", "target_version_prefix", /*rollback_allowed=*/true, + /*major_version_rollout_policy=*/1, + /*minor_version_rollout_policy=*/2, /*update_disabled=*/false, UpdateService::PolicySameVersionUpdate::kNotAllowed, metadata, crx_file::VerifierFormat::CRX3_WITH_PUBLISHER_PROOF) @@ -67,6 +69,16 @@ // install_data_index is unset because client_install_data was sent. EXPECT_EQ(crx.install_data_index, ""); + ASSERT_NE(crx.installer_attributes.find("major_version_rollout_policy"), + crx.installer_attributes.end()); + ASSERT_NE(crx.installer_attributes.find("minor_version_rollout_policy"), + crx.installer_attributes.end()); + EXPECT_EQ( + crx.installer_attributes.find("major_version_rollout_policy")->second, + "1"); + EXPECT_EQ( + crx.installer_attributes.find("minor_version_rollout_policy")->second, + "2"); } #if BUILDFLAG(IS_MAC) @@ -102,6 +114,8 @@ base::MakeRefCounted<Installer>( "id", "client_install_data", "install_data_index", "install_source", "target_channel", "target_version_prefix", /*rollback_allowed=*/true, + /*major_version_rollout_policy=*/1, + /*minor_version_rollout_policy=*/2, /*update_disabled=*/false, UpdateService::PolicySameVersionUpdate::kNotAllowed, metadata, crx_file::VerifierFormat::CRX3_WITH_PUBLISHER_PROOF) @@ -145,6 +159,8 @@ base::MakeRefCounted<Installer>( "id", "client_install_data", "install_data_index", "install_source", "target_channel", "target_version_prefix", /*rollback_allowed=*/true, + /*major_version_rollout_policy=*/1, + /*minor_version_rollout_policy=*/2, /*update_disabled=*/false, UpdateService::PolicySameVersionUpdate::kNotAllowed, metadata, crx_file::VerifierFormat::CRX3_WITH_PUBLISHER_PROOF) @@ -190,6 +206,8 @@ base::MakeRefCounted<Installer>( "id", "client_install_data", "install_data_index", "install_source", "target_channel", "target_version_prefix", /*rollback_allowed=*/true, + /*major_version_rollout_policy=*/1, + /*minor_version_rollout_policy=*/2, /*update_disabled=*/false, UpdateService::PolicySameVersionUpdate::kNotAllowed, metadata, crx_file::VerifierFormat::CRX3_WITH_PUBLISHER_PROOF) @@ -220,6 +238,8 @@ "id", "client_install_data", "install_data_index", "install_source", "target_channel", "target_version_prefix", /*rollback_allowed=*/true, + /*major_version_rollout_policy=*/1, + /*minor_version_rollout_policy=*/2, /*update_disabled=*/false, UpdateService::PolicySameVersionUpdate::kNotAllowed, metadata, crx_file::VerifierFormat::CRX3_WITH_PUBLISHER_PROOF))
diff --git a/chrome/updater/policy/dm_policy_manager.cc b/chrome/updater/policy/dm_policy_manager.cc index d5eb20c..f264d783 100644 --- a/chrome/updater/policy/dm_policy_manager.cc +++ b/chrome/updater/policy/dm_policy_manager.cc
@@ -261,6 +261,26 @@ ROLLBACK_TO_TARGET_VERSION_ENABLED); } +std::optional<int> DMPolicyManager::GetMajorVersionRolloutPolicy( + const std::string& app_id) const { + const auto* app_settings = GetAppSettings(app_id); + if (!app_settings || !app_settings->has_major_version_rollout_policy()) { + return std::nullopt; + } + + return app_settings->major_version_rollout_policy(); +} + +std::optional<int> DMPolicyManager::GetMinorVersionRolloutPolicy( + const std::string& app_id) const { + const auto* app_settings = GetAppSettings(app_id); + if (!app_settings || !app_settings->has_minor_version_rollout_policy()) { + return std::nullopt; + } + + return app_settings->minor_version_rollout_policy(); +} + std::optional<std::vector<std::string>> DMPolicyManager::GetForceInstallApps() const { std::vector<std::string> force_install_apps;
diff --git a/chrome/updater/policy/dm_policy_manager.h b/chrome/updater/policy/dm_policy_manager.h index b0a6a64..7cf792d 100644 --- a/chrome/updater/policy/dm_policy_manager.h +++ b/chrome/updater/policy/dm_policy_manager.h
@@ -46,6 +46,10 @@ const std::string& app_id) const override; std::optional<bool> IsRollbackToTargetVersionAllowed( const std::string& app_id) const override; + std::optional<int> GetMajorVersionRolloutPolicy( + const std::string& app_id) const override; + std::optional<int> GetMinorVersionRolloutPolicy( + const std::string& app_id) const override; std::optional<std::string> GetProxyMode() const override; std::optional<std::string> GetProxyPacUrl() const override; std::optional<std::string> GetProxyServer() const override;
diff --git a/chrome/updater/policy/mac/managed_preference_policy_manager.mm b/chrome/updater/policy/mac/managed_preference_policy_manager.mm index 4f96d11a..9888d99e 100644 --- a/chrome/updater/policy/mac/managed_preference_policy_manager.mm +++ b/chrome/updater/policy/mac/managed_preference_policy_manager.mm
@@ -56,6 +56,10 @@ const std::string& app_id) const override; std::optional<bool> IsRollbackToTargetVersionAllowed( const std::string& app_id) const override; + std::optional<int> GetMajorVersionRolloutPolicy( + const std::string& app_id) const override; + std::optional<int> GetMinorVersionRolloutPolicy( + const std::string& app_id) const override; std::optional<std::string> GetProxyMode() const override; std::optional<std::string> GetProxyPacUrl() const override; std::optional<std::string> GetProxyServer() const override; @@ -194,6 +198,22 @@ : std::nullopt; } +std::optional<int> ManagedPreferencePolicyManager::GetMajorVersionRolloutPolicy( + const std::string& app_id) const { + int update_policy = + [impl_ majorVersionRolloutPolicy:base::SysUTF8ToNSString(app_id)]; + return update_policy == kPolicyNotSet ? std::nullopt + : std::optional<int>(update_policy); +} + +std::optional<int> ManagedPreferencePolicyManager::GetMinorVersionRolloutPolicy( + const std::string& app_id) const { + int update_policy = + [impl_ minorVersionRolloutPolicy:base::SysUTF8ToNSString(app_id)]; + return update_policy == kPolicyNotSet ? std::nullopt + : std::optional<int>(update_policy); +} + std::optional<std::vector<std::string>> ManagedPreferencePolicyManager::GetForceInstallApps() const { return std::nullopt;
diff --git a/chrome/updater/policy/mac/managed_preference_policy_manager_impl.h b/chrome/updater/policy/mac/managed_preference_policy_manager_impl.h index 3de6983..184247e 100644 --- a/chrome/updater/policy/mac/managed_preference_policy_manager_impl.h +++ b/chrome/updater/policy/mac/managed_preference_policy_manager_impl.h
@@ -61,6 +61,8 @@ - (nullable NSString*)targetChannel:(nonnull NSString*)appid; - (nullable NSString*)targetVersionPrefix:(nonnull NSString*)appid; - (int)rollbackToTargetVersion:(nonnull NSString*)appid; +- (int)majorVersionRolloutPolicy:(nonnull NSString*)appid; +- (int)minorVersionRolloutPolicy:(nonnull NSString*)appid; - (nullable NSArray<NSString*>*)appsWithPolicy;
diff --git a/chrome/updater/policy/mac/managed_preference_policy_manager_impl.mm b/chrome/updater/policy/mac/managed_preference_policy_manager_impl.mm index f64537f..14959df 100644 --- a/chrome/updater/policy/mac/managed_preference_policy_manager_impl.mm +++ b/chrome/updater/policy/mac/managed_preference_policy_manager_impl.mm
@@ -22,6 +22,8 @@ NSString* kTargetChannelKey = @"TargetChannel"; NSString* kTargetVersionPrefixKey = @"TargetVersionPrefix"; NSString* kRollbackToTargetVersionKey = @"RollbackToTargetVersion"; +NSString* kMajorVersionRolloutKey = @"MajorVersionRolloutPolicy"; +NSString* kMinorVersionRolloutKey = @"MinorVersionRolloutPolicy"; } // namespace namespace updater { @@ -155,6 +157,8 @@ @property(nonatomic, readonly) int rollbackToTargetVersion; @property(nonatomic, readonly, nullable) NSString* targetChannel; @property(nonatomic, readonly, nullable) NSString* targetVersionPrefix; +@property(nonatomic, readonly) int majorVersionRolloutPolicy; +@property(nonatomic, readonly) int minorVersionRolloutPolicy; @end @@ -162,6 +166,8 @@ @synthesize updatePolicy = _updatePolicy; @synthesize rollbackToTargetVersion = _rollbackToTargetVersion; +@synthesize majorVersionRolloutPolicy = _majorVersionRolloutPolicy; +@synthesize minorVersionRolloutPolicy = _minorVersionRolloutPolicy; - (instancetype)initWithDictionary:(CRUAppPolicyDictionary*)policyDict { if (([super init])) { @@ -173,6 +179,10 @@ base::apple::ObjCCast<NSString>(policyDict[kTargetVersionPrefixKey]); _rollbackToTargetVersion = updater::ReadPolicyInteger(policyDict[kRollbackToTargetVersionKey]); + _majorVersionRolloutPolicy = + updater::ReadPolicyInteger(policyDict[kMajorVersionRolloutKey]); + _minorVersionRolloutPolicy = + updater::ReadPolicyInteger(policyDict[kMinorVersionRolloutKey]); } return self; @@ -292,6 +302,22 @@ return [_appPolicies objectForKey:appid].rollbackToTargetVersion; } +- (int)majorVersionRolloutPolicy:(NSString*)appid { + appid = appid.lowercaseString; + if (![_appPolicies objectForKey:appid]) { + return updater::kPolicyNotSet; + } + return [_appPolicies objectForKey:appid].majorVersionRolloutPolicy; +} + +- (int)minorVersionRolloutPolicy:(NSString*)appid { + appid = appid.lowercaseString; + if (![_appPolicies objectForKey:appid]) { + return updater::kPolicyNotSet; + } + return [_appPolicies objectForKey:appid].minorVersionRolloutPolicy; +} + - (NSArray<NSString*>*)appsWithPolicy { return [_appPolicies allKeys]; }
diff --git a/chrome/updater/policy/manager.cc b/chrome/updater/policy/manager.cc index 4475327..e583417 100644 --- a/chrome/updater/policy/manager.cc +++ b/chrome/updater/policy/manager.cc
@@ -63,6 +63,10 @@ const std::string& app_id) const override; std::optional<bool> IsRollbackToTargetVersionAllowed( const std::string& app_id) const override; + std::optional<int> GetMajorVersionRolloutPolicy( + const std::string& app_id) const override; + std::optional<int> GetMinorVersionRolloutPolicy( + const std::string& app_id) const override; std::optional<std::string> GetProxyMode() const override; std::optional<std::string> GetProxyPacUrl() const override; std::optional<std::string> GetProxyServer() const override; @@ -138,6 +142,16 @@ return false; } +std::optional<int> DefaultValuesPolicyManager::GetMajorVersionRolloutPolicy( + const std::string& app_id) const { + return std::nullopt; +} + +std::optional<int> DefaultValuesPolicyManager::GetMinorVersionRolloutPolicy( + const std::string& app_id) const { + return std::nullopt; +} + std::optional<std::string> DefaultValuesPolicyManager::GetProxyMode() const { return std::nullopt; }
diff --git a/chrome/updater/policy/manager.h b/chrome/updater/policy/manager.h index 97e4102..1f1c6c1 100644 --- a/chrome/updater/policy/manager.h +++ b/chrome/updater/policy/manager.h
@@ -81,11 +81,13 @@ // Otherwise, returns kPolicyDisabled. virtual std::optional<int> GetEffectivePolicyForAppInstalls( const std::string& app_id) const = 0; + // Returns kPolicyEnabled if updates of the specified app is allowed. // Otherwise, returns one of kPolicyDisabled, kPolicyManualUpdatesOnly, or // kPolicyAutomaticUpdatesOnly. virtual std::optional<int> GetEffectivePolicyForAppUpdates( const std::string& app_id) const = 0; + // Returns the target version prefix for the app. // Examples: // * "" (or not configured): update to latest version available. @@ -94,11 +96,27 @@ // * "55.24.34": update to this specific version only. virtual std::optional<std::string> GetTargetVersionPrefix( const std::string& app_id) const = 0; + // Returns whether the RollbackToTargetVersion policy has been set for the // app. If RollbackToTargetVersion is set, the TargetVersionPrefix policy // governs the version to rollback clients with higher versions to. virtual std::optional<bool> IsRollbackToTargetVersionAllowed( const std::string& app_id) const = 0; + + // Returns one of kPolicyRolloutDefault, kPolicyRolloutFast, or + // kPolicyRolloutSlow, indicating the preference for participating in app + // gradual rollouts, skipping gradual rollouts, or holding back from gradual + // rollouts, respectively. Applies to major revisions of apps only. + virtual std::optional<int> GetMajorVersionRolloutPolicy( + const std::string& app_id) const = 0; + + // Returns one of kPolicyRolloutDefault, kPolicyRolloutFast, or + // kPolicyRolloutSlow, indicating the preference for participating in app + // gradual rollouts, skipping gradual rollouts, or holding back from gradual + // rollouts, respectively. Applies to minor revisions of apps only. + virtual std::optional<int> GetMinorVersionRolloutPolicy( + const std::string& app_id) const = 0; + // Returns a proxy mode such as |auto_detect|. virtual std::optional<std::string> GetProxyMode() const = 0;
diff --git a/chrome/updater/policy/policy_manager.cc b/chrome/updater/policy/policy_manager.cc index ed3f2be..1b2c1bb 100644 --- a/chrome/updater/policy/policy_manager.cc +++ b/chrome/updater/policy/policy_manager.cc
@@ -13,6 +13,7 @@ #include "base/containers/flat_set.h" #include "base/logging.h" #include "base/memory/scoped_refptr.h" +#include "base/strings/strcat.h" #include "base/strings/string_util.h" #include "base/values.h" #include "chrome/updater/policy/manager.h" @@ -60,6 +61,8 @@ constexpr char kTargetVersionPrefix[] = "targetversionprefix"; constexpr char kTargetChannel[] = "targetchannel"; constexpr char kRollbackToTargetVersion[] = "RollbackToTargetVersion"; +constexpr char kMajorVersionRolloutPrefix[] = "MajorVersionRollout"; +constexpr char kMinorVersionRolloutPrefix[] = "MinorVersionRollout"; } // namespace @@ -148,42 +151,45 @@ std::optional<int> PolicyManager::GetEffectivePolicyForAppInstalls( const std::string& app_id) const { - std::string app_value_name(kInstallAppPrefix); - app_value_name.append(app_id); - std::optional<int> policy = GetIntegerPolicy(app_value_name); + std::optional<int> policy = + GetIntegerPolicy(base::StrCat({kInstallAppPrefix, app_id})); return policy ? policy : GetIntegerPolicy(kInstallAppsDefault); } std::optional<int> PolicyManager::GetEffectivePolicyForAppUpdates( const std::string& app_id) const { - std::string app_value_name(kUpdateAppPrefix); - app_value_name.append(app_id); - std::optional<int> policy = GetIntegerPolicy(app_value_name); + std::optional<int> policy = + GetIntegerPolicy(base::StrCat({kUpdateAppPrefix, app_id})); return policy ? policy : GetIntegerPolicy(kUpdateAppsDefault); } std::optional<std::string> PolicyManager::GetTargetChannel( const std::string& app_id) const { - std::string app_value_name(kTargetChannel); - app_value_name.append(app_id); - return GetStringPolicy(app_value_name.c_str()); + return GetStringPolicy(base::StrCat({kTargetChannel, app_id})); } std::optional<std::string> PolicyManager::GetTargetVersionPrefix( const std::string& app_id) const { - std::string app_value_name(kTargetVersionPrefix); - app_value_name.append(app_id); - return GetStringPolicy(app_value_name.c_str()); + return GetStringPolicy(base::StrCat({kTargetVersionPrefix, app_id})); } std::optional<bool> PolicyManager::IsRollbackToTargetVersionAllowed( const std::string& app_id) const { - std::string app_value_name(kRollbackToTargetVersion); - app_value_name.append(app_id); - std::optional<int> policy = GetIntegerPolicy(app_value_name); + std::optional<int> policy = + GetIntegerPolicy(base::StrCat({kRollbackToTargetVersion, app_id})); return policy ? std::optional<bool>(policy.value()) : std::nullopt; } +std::optional<int> PolicyManager::GetMajorVersionRolloutPolicy( + const std::string& app_id) const { + return GetIntegerPolicy(base::StrCat({kMajorVersionRolloutPrefix, app_id})); +} + +std::optional<int> PolicyManager::GetMinorVersionRolloutPolicy( + const std::string& app_id) const { + return GetIntegerPolicy(base::StrCat({kMinorVersionRolloutPrefix, app_id})); +} + std::optional<std::string> PolicyManager::GetProxyMode() const { return GetStringPolicy(kProxyMode); } @@ -211,9 +217,11 @@ base::ToLowerASCII(kUpdatesSuppressedDurationMin), }; static constexpr const char* kAppPolicyPrefixes[] = { - kInstallAppsDefault, kInstallAppPrefix, kUpdateAppsDefault, - kUpdateAppPrefix, kTargetVersionPrefix, kTargetChannel, - kRollbackToTargetVersion}; + kInstallAppsDefault, kInstallAppPrefix, + kUpdateAppsDefault, kUpdateAppPrefix, + kTargetVersionPrefix, kTargetChannel, + kRollbackToTargetVersion, kMajorVersionRolloutPrefix, + kMinorVersionRolloutPrefix}; std::vector<std::string> apps_with_policy; std::ranges::for_each(policies_, [&](const auto& policy) { const std::string policy_name = policy.first;
diff --git a/chrome/updater/policy/policy_manager.h b/chrome/updater/policy/policy_manager.h index 00576b5..ff687890 100644 --- a/chrome/updater/policy/policy_manager.h +++ b/chrome/updater/policy/policy_manager.h
@@ -49,6 +49,10 @@ const std::string& app_id) const override; std::optional<bool> IsRollbackToTargetVersionAllowed( const std::string& app_id) const override; + std::optional<int> GetMajorVersionRolloutPolicy( + const std::string& app_id) const override; + std::optional<int> GetMinorVersionRolloutPolicy( + const std::string& app_id) const override; std::optional<std::string> GetProxyMode() const override; std::optional<std::string> GetProxyPacUrl() const override; std::optional<std::string> GetProxyServer() const override;
diff --git a/chrome/updater/policy/policy_manager_unittest.cc b/chrome/updater/policy/policy_manager_unittest.cc index 87ccd69..0e56a227 100644 --- a/chrome/updater/policy/policy_manager_unittest.cc +++ b/chrome/updater/policy/policy_manager_unittest.cc
@@ -93,6 +93,8 @@ policies.Set(base::StrCat({"rollbacktotargetversion", kTestAppID}), 1); policies.Set(base::StrCat({"install", kTestAppIDForceInstall}), kPolicyForceInstallUser); + policies.Set(base::StrCat({"majorversionrollout", kTestAppID}), 1); + policies.Set(base::StrCat({"minorversionrollout", kTestAppID}), 2); scoped_refptr<PolicyManagerInterface> policy_manager = CreateDictPolicyManager(std::move(policies)); @@ -139,6 +141,11 @@ EXPECT_FALSE( policy_manager->IsRollbackToTargetVersionAllowed("non-exist-app")); + EXPECT_EQ(policy_manager->GetMajorVersionRolloutPolicy(kTestAppID), 1); + EXPECT_EQ(policy_manager->GetMinorVersionRolloutPolicy(kTestAppID), 2); + EXPECT_FALSE(policy_manager->GetMajorVersionRolloutPolicy("non-exist-app")); + EXPECT_FALSE(policy_manager->GetMajorVersionRolloutPolicy("non-exist-app")); + std::optional<std::vector<std::string>> force_install_apps = policy_manager->GetForceInstallApps(); ASSERT_EQ(force_install_apps.has_value(), !IsSystemInstall());
diff --git a/chrome/updater/policy/service.cc b/chrome/updater/policy/service.cc index 1d4239f76..e75eb91 100644 --- a/chrome/updater/policy/service.cc +++ b/chrome/updater/policy/service.cc
@@ -309,6 +309,20 @@ &PolicyManagerInterface::IsRollbackToTargetVersionAllowed, app_id); } +PolicyStatus<int> PolicyService::GetMajorVersionRolloutPolicy( + const std::string& app_id) const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return QueryAppPolicy(&PolicyManagerInterface::GetMajorVersionRolloutPolicy, + app_id); +} + +PolicyStatus<int> PolicyService::GetMinorVersionRolloutPolicy( + const std::string& app_id) const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return QueryAppPolicy(&PolicyManagerInterface::GetMajorVersionRolloutPolicy, + app_id); +} + PolicyStatus<std::string> PolicyService::GetProxyMode() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return QueryPolicy(
diff --git a/chrome/updater/policy/service.h b/chrome/updater/policy/service.h index a7bfbf1d..2432bea 100644 --- a/chrome/updater/policy/service.h +++ b/chrome/updater/policy/service.h
@@ -68,6 +68,11 @@ return conflict_policy_; } + std::optional<T> effective_policy_value() const { + return effective_policy_ ? std::optional<T>(effective_policy_->policy) + : std::nullopt; + } + explicit operator bool() const { return effective_policy_.has_value(); } // Convenience method to extract the effective policy's value. const T& policy() const { @@ -149,6 +154,10 @@ const std::string& app_id) const; PolicyStatus<bool> IsRollbackToTargetVersionAllowed( const std::string& app_id) const; + PolicyStatus<int> GetMajorVersionRolloutPolicy( + const std::string& app_id) const; + PolicyStatus<int> GetMinorVersionRolloutPolicy( + const std::string& app_id) const; PolicyStatus<std::string> GetProxyMode() const; PolicyStatus<std::string> GetProxyPacUrl() const; PolicyStatus<std::string> GetProxyServer() const;
diff --git a/chrome/updater/policy/service_unittest.cc b/chrome/updater/policy/service_unittest.cc index bf1b3ba..9a4e665 100644 --- a/chrome/updater/policy/service_unittest.cc +++ b/chrome/updater/policy/service_unittest.cc
@@ -205,6 +205,30 @@ target_version_prefixes_[app_id] = std::move(target_version_prefix); } + std::optional<int> GetMajorVersionRolloutPolicy( + const std::string& app_id) const override { + auto value = major_version_rollout_policies_.find(app_id); + return value == major_version_rollout_policies_.end() + ? std::nullopt + : std::make_optional(value->second); + } + + void SetMajorVersionRolloutPolicy(const std::string& app_id, int policy) { + major_version_rollout_policies_[app_id] = policy; + } + + std::optional<int> GetMinorVersionRolloutPolicy( + const std::string& app_id) const override { + auto value = minor_version_rollout_policies_.find(app_id); + return value == minor_version_rollout_policies_.end() + ? std::nullopt + : std::make_optional(value->second); + } + + void SetMinorVersionRolloutPolicy(const std::string& app_id, int policy) { + minor_version_rollout_policies_[app_id] = policy; + } + std::optional<std::vector<std::string>> GetForceInstallApps() const override { return std::nullopt; } @@ -243,6 +267,8 @@ std::map<std::string, int> update_policies_; std::map<std::string, std::string> channels_; std::map<std::string, std::string> target_version_prefixes_; + std::map<std::string, int> major_version_rollout_policies_; + std::map<std::string, int> minor_version_rollout_policies_; }; class PolicyServiceTest : public ::testing::Test { @@ -288,6 +314,14 @@ policy_service->IsRollbackToTargetVersionAllowed("test1"); ASSERT_TRUE(rollback_allowed); EXPECT_EQ(rollback_allowed.policy(), false); + + PolicyStatus<int> major_version_rollout_policy = + policy_service->GetMajorVersionRolloutPolicy("test1"); + EXPECT_FALSE(major_version_rollout_policy); + + PolicyStatus<int> minor_version_rollout_policy = + policy_service->GetMinorVersionRolloutPolicy("test1"); + EXPECT_FALSE(minor_version_rollout_policy); } TEST_F(PolicyServiceTest, ValidatePolicyValues) {
diff --git a/chrome/updater/protos/omaha_settings.proto b/chrome/updater/protos/omaha_settings.proto index 34717240..8e1f7f2 100644 --- a/chrome/updater/protos/omaha_settings.proto +++ b/chrome/updater/protos/omaha_settings.proto
@@ -60,6 +60,17 @@ ROLLBACK_TO_TARGET_VERSION_ENABLED = 1; } +enum RolloutValue { + // Participate in gradual rollout. + ROLLOUT_DEFAULT = 0; + + // Update after gradual rollout completes. + ROLLOUT_SLOW = 1; + + // Update when gradual rollout begins. + ROLLOUT_FAST = 2; +} + message UpdatesSuppressed { optional int64 start_hour = 1; optional int64 start_minute = 2; @@ -149,6 +160,18 @@ // binaries for the specified channel. If this policy is not set, the default // channel will be used. optional string target_channel = 8; + + // Major Version Rollout + // + // If a major update for the application is gradually rollout out, this policy + // controls when in the gradual rollout this device will update. + optional RolloutValue major_version_rollout_policy = 9; + + // Minor Version Rollout + // + // If a minor update for the application is gradually rollout out, this policy + // controls when in the gradual rollout this device will update. + optional RolloutValue minor_version_rollout_policy = 10; } message GcpwSpecificApplicationSettings {
diff --git a/chrome/updater/update_service_impl_impl.cc b/chrome/updater/update_service_impl_impl.cc index ec6a875..6cd479c85 100644 --- a/chrome/updater/update_service_impl_impl.cc +++ b/chrome/updater/update_service_impl_impl.cc
@@ -164,6 +164,10 @@ policy_service->GetTargetChannel(id).policy_or(std::string()), policy_service->GetTargetVersionPrefix(id).policy_or(std::string()), policy_service->IsRollbackToTargetVersionAllowed(id).policy_or(false), + policy_service->GetMajorVersionRolloutPolicy(id) + .effective_policy_value(), + policy_service->GetMinorVersionRolloutPolicy(id) + .effective_policy_value(), [&policy_service, &id, &is_foreground, update_blocked] { if (update_blocked) { return true;
diff --git a/chromeos/ash/components/heatmap/OWNERS b/chromeos/ash/components/heatmap/OWNERS index f616ccc..2e46272 100644 --- a/chromeos/ash/components/heatmap/OWNERS +++ b/chromeos/ash/components/heatmap/OWNERS
@@ -1,2 +1 @@ -robsc@google.com jiwan@chromium.org
diff --git a/chromeos/ash/components/phonehub/feature_status_provider_impl.cc b/chromeos/ash/components/phonehub/feature_status_provider_impl.cc index dbf045a..c719779 100644 --- a/chromeos/ash/components/phonehub/feature_status_provider_impl.cc +++ b/chromeos/ash/components/phonehub/feature_status_provider_impl.cc
@@ -6,7 +6,6 @@ #include <utility> -#include "ash/constants/ash_features.h" #include "base/functional/bind.h" #include "base/metrics/histogram_macros.h" #include "base/task/task_traits.h" @@ -189,8 +188,7 @@ } void FeatureStatusProviderImpl::OnNewDevicesSynced() { - if (features::IsPhoneHubOnboardingNotifierRevampEnabled() && - ComputeStatus() == FeatureStatus::kEligiblePhoneButNotSetUp) { + if (ComputeStatus() == FeatureStatus::kEligiblePhoneButNotSetUp) { CheckEligibleDevicesForNudge(); } UpdateStatus();
diff --git a/chromeos/ash/services/multidevice_setup/account_status_change_delegate_notifier_impl.cc b/chromeos/ash/services/multidevice_setup/account_status_change_delegate_notifier_impl.cc index 419787320..c0e80d8 100644 --- a/chromeos/ash/services/multidevice_setup/account_status_change_delegate_notifier_impl.cc +++ b/chromeos/ash/services/multidevice_setup/account_status_change_delegate_notifier_impl.cc
@@ -7,7 +7,6 @@ #include <set> #include <utility> -#include "ash/constants/ash_features.h" #include "base/memory/ptr_util.h" #include "base/time/clock.h" #include "base/time/time.h" @@ -16,7 +15,6 @@ #include "chromeos/ash/services/multidevice_setup/host_status_provider_impl.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" -#include "components/session_manager/core/session_manager.h" namespace ash { @@ -85,7 +83,6 @@ ~AccountStatusChangeDelegateNotifierImpl() { host_status_provider_->RemoveObserver(this); oobe_completion_tracker_->RemoveObserver(this); - session_manager::SessionManager::Get()->RemoveObserver(this); } void AccountStatusChangeDelegateNotifierImpl::OnDelegateSet() { @@ -144,12 +141,6 @@ LoadHostDeviceIdFromEndOfPreviousSession(); host_status_provider_->AddObserver(this); oobe_completion_tracker_->AddObserver(this); - session_manager::SessionManager::Get()->AddObserver(this); - if (IsInPhoneHubNotificationExperimentGroup()) { - // In the object is created after OnSessionStateChanged() is already called, - // manually update the timestamp. - UpdateSessionStartTimeIfEligible(); - } } void AccountStatusChangeDelegateNotifierImpl::OnHostStatusChange( @@ -164,29 +155,6 @@ delegate()->OnNoLongerNewUser(); } -void AccountStatusChangeDelegateNotifierImpl::OnSessionStateChanged() { - UpdateSessionStartTimeIfEligible(); -} - -void AccountStatusChangeDelegateNotifierImpl:: - UpdateSessionStartTimeIfEligible() { - if (session_manager::SessionManager::Get()->IsUserSessionBlocked()) { - return; - } - if (IsInPhoneHubNotificationExperimentGroup()) { - pref_service_->SetInt64(kMultiDeviceLastSessionStartTime, - clock_->Now().InMillisecondsSinceUnixEpoch()); - CheckForNewUserPotentialHostExistsEvent( - host_status_provider_->GetHostWithStatus()); - } -} - -bool AccountStatusChangeDelegateNotifierImpl:: - IsInPhoneHubNotificationExperimentGroup() { - return features::IsPhoneHubOnboardingNotifierRevampEnabled() && - !features::kPhoneHubOnboardingNotifierUseNudge.Get(); -} - void AccountStatusChangeDelegateNotifierImpl::CheckForMultiDeviceEvents( const HostStatusProvider::HostStatusWithDevice& host_status_with_device) { if (!delegate()) { @@ -221,7 +189,6 @@ kVerifiedHostDeviceIdFromMostRecentHostStatusUpdatePrefName, kNoHost); } - CheckForNewUserPotentialHostExistsEvent(host_status_with_device); CheckForNoLongerNewUserEvent(host_status_with_device, host_status_before_update); CheckForExistingUserHostSwitchedEvent(host_status_with_device, @@ -230,62 +197,6 @@ host_status_with_device, verified_host_device_id_before_update); } -void AccountStatusChangeDelegateNotifierImpl:: - CheckForNewUserPotentialHostExistsEvent( - const HostStatusProvider::HostStatusWithDevice& - host_status_with_device) { - if (!features::IsPhoneHubOnboardingNotifierRevampEnabled()) { - // We do not notify the user if they already had a chance to go through - // setup flow in OOBE. - if (pref_service_->GetInt64(kOobeSetupFlowTimestampPrefName) != - kTimestampNotSet) { - return; - } - } else { - if (!IsInPhoneHubNotificationExperimentGroup()) { - // The user is in group for nudge. Do not show notification. - return; - } - } - - // We only check for new user events if there is no enabled host. - if (verified_host_device_id_from_most_recent_update_) - return; - - // If the observer has been notified of a potential verified host in the past, - // they are not considered a new user. - if (pref_service_->GetInt64(kNewUserPotentialHostExistsPrefName) != - kTimestampNotSet || - pref_service_->GetInt64(kExistingUserChromebookAddedPrefName) != - kTimestampNotSet) { - return; - } - - // kEligibleHostExistsButNoHostSet is the only HostStatus that can describe - // a new user. - if (host_status_with_device.host_status() != - mojom::HostStatus::kEligibleHostExistsButNoHostSet) { - return; - } - - if (IsInPhoneHubNotificationExperimentGroup()) { - if (pref_service_->GetInt64(kMultiDeviceLastSessionStartTime) != - kTimestampNotSet && - clock_->Now() - - base::Time::FromMillisecondsSinceUnixEpoch( - pref_service_->GetInt64(kMultiDeviceLastSessionStartTime)) > - features::kMultiDeviceSetupNotificationTimeLimit.Get()) { - return; - } - } - - if (delegate()) { - delegate()->OnPotentialHostExistsForNewUser(); - pref_service_->SetInt64(kNewUserPotentialHostExistsPrefName, - clock_->Now().InMillisecondsSinceUnixEpoch()); - } -} - void AccountStatusChangeDelegateNotifierImpl::CheckForNoLongerNewUserEvent( const HostStatusProvider::HostStatusWithDevice& host_status_with_device, const std::optional<mojom::HostStatus> host_status_before_update) {
diff --git a/chromeos/ash/services/multidevice_setup/account_status_change_delegate_notifier_impl.h b/chromeos/ash/services/multidevice_setup/account_status_change_delegate_notifier_impl.h index 4103439..42673d0 100644 --- a/chromeos/ash/services/multidevice_setup/account_status_change_delegate_notifier_impl.h +++ b/chromeos/ash/services/multidevice_setup/account_status_change_delegate_notifier_impl.h
@@ -13,7 +13,6 @@ #include "chromeos/ash/services/multidevice_setup/host_status_provider.h" #include "chromeos/ash/services/multidevice_setup/public/cpp/oobe_completion_tracker.h" #include "chromeos/ash/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h" -#include "components/session_manager/core/session_manager_observer.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/remote.h" @@ -36,8 +35,7 @@ class AccountStatusChangeDelegateNotifierImpl : public AccountStatusChangeDelegateNotifier, public HostStatusProvider::Observer, - public OobeCompletionTracker::Observer, - public session_manager::SessionManagerObserver { + public OobeCompletionTracker::Observer { public: class Factory { public: @@ -105,18 +103,9 @@ // OobeCompletionTracker::Observer: void OnOobeCompleted() override; - // SessionManagerObserver:: - void OnSessionStateChanged() override; - - void UpdateSessionStartTimeIfEligible(); - - bool IsInPhoneHubNotificationExperimentGroup(); - void CheckForMultiDeviceEvents( const HostStatusProvider::HostStatusWithDevice& host_status_with_device); - void CheckForNewUserPotentialHostExistsEvent( - const HostStatusProvider::HostStatusWithDevice& host_status_with_device); void CheckForNoLongerNewUserEvent( const HostStatusProvider::HostStatusWithDevice& host_status_with_device, const std::optional<mojom::HostStatus> host_status_before_update);
diff --git a/clank b/clank index 6a196fc5..cef1155 160000 --- a/clank +++ b/clank
@@ -1 +1 @@ -Subproject commit 6a196fc5a4b07b4f6d8c64cb7ab20e43bdbeb43b +Subproject commit cef11550a1facb7d8a76e3d9169d1e0a64adf73a
diff --git a/components/browser_ui/banners/android/java/src/org/chromium/components/browser_ui/banners/SwipableOverlayView.java b/components/browser_ui/banners/android/java/src/org/chromium/components/browser_ui/banners/SwipableOverlayView.java index 1b742723..567344d 100644 --- a/components/browser_ui/banners/android/java/src/org/chromium/components/browser_ui/banners/SwipableOverlayView.java +++ b/components/browser_ui/banners/android/java/src/org/chromium/components/browser_ui/banners/SwipableOverlayView.java
@@ -104,12 +104,14 @@ /** * Creates a SwipableOverlayView. + * * @param context Context for acquiring resources. * @param attrs Attributes from the XML layout inflation. * @param hideOnScroll Whether this view should observe user's gesture and then auto-hide when - * page is scrolled down. + * page is scrolled down. */ - public SwipableOverlayView(Context context, AttributeSet attrs, boolean hideOnScroll) { + public SwipableOverlayView( + Context context, @Nullable AttributeSet attrs, boolean hideOnScroll) { super(context, attrs); mGestureStateListener = hideOnScroll ? createGestureStateListener() : null; mGestureState = Gesture.NONE; @@ -144,7 +146,7 @@ return mTotalHeight; } - protected void addToParentView(ViewGroup parentView) { + protected void addToParentView(@Nullable ViewGroup parentView) { if (parentView == null) return; if (getParent() == null) { parentView.addView(this, createLayoutParams());
diff --git a/components/browser_ui/bottomsheet/android/internal/BUILD.gn b/components/browser_ui/bottomsheet/android/internal/BUILD.gn index 5ba2f8a..c579f6a5 100644 --- a/components/browser_ui/bottomsheet/android/internal/BUILD.gn +++ b/components/browser_ui/bottomsheet/android/internal/BUILD.gn
@@ -26,6 +26,7 @@ "..:manager_java", "//base:base_java", "//components/browser_ui/desktop_windowing/android:java", + "//components/browser_ui/styles/android:java", "//components/browser_ui/styles/android:java_resources", "//components/browser_ui/widget/android:java", "//third_party/androidx:androidx_annotation_annotation_java", @@ -36,6 +37,7 @@ } robolectric_library("junit_tests") { + resources_package = "org.chromium.components.browser_ui.bottomsheet" sources = [ "java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetControllerImplUnitTest.java", "java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetSwipeDetectorTest.java", @@ -44,9 +46,11 @@ deps = [ ":java", "../:java", + "../:java_resources", "//base:base_java", "//base:base_junit_test_support", "//components/browser_ui/desktop_windowing/android:java", + "//components/browser_ui/theme/android:java_resources", "//components/browser_ui/widget/android:java", "//third_party/junit", "//third_party/mockito:mockito_java",
diff --git a/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java b/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java index 04e5513..b9d67400 100644 --- a/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java +++ b/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java
@@ -18,6 +18,7 @@ import android.view.Window; import android.widget.FrameLayout; +import androidx.annotation.ColorInt; import androidx.annotation.StringRes; import androidx.annotation.VisibleForTesting; @@ -35,6 +36,7 @@ import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent.HeightMode; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.SheetState; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.StateChangeReason; +import org.chromium.components.browser_ui.styles.SemanticColorUtils; import org.chromium.components.browser_ui.widget.animation.CancelAwareAnimatorListener; import org.chromium.ui.KeyboardVisibilityDelegate; import org.chromium.ui.accessibility.AccessibilityState; @@ -168,6 +170,7 @@ private int mAppHeaderHeight; private int mBottomMargin; + private final @ColorInt int mSheetBgColor; /** * A view used to render a shadow behind the sheet and extends outside the bounds of its parent @@ -230,7 +233,7 @@ mMinHalfFullDistance = getResources().getDimensionPixelSize(R.dimen.bottom_sheet_min_full_half_distance); - + mSheetBgColor = SemanticColorUtils.getSheetBgColor(context); mGestureDetector = new BottomSheetSwipeDetector(context, this); mIsTouchEnabled = true; } @@ -911,6 +914,12 @@ return mContainerWidth; } + /** Return the background color of the sheet. */ + @ColorInt + int getSheetBackgroundColor() { + return mSheetBgColor; + } + /** * Sends notifications if the sheet is transitioning from the peeking to half expanded state and * from the peeking to fully expanded state. The peek to half events are only sent when the
diff --git a/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetControllerImpl.java b/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetControllerImpl.java index eba2c6a..ccb07e3 100644 --- a/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetControllerImpl.java +++ b/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetControllerImpl.java
@@ -693,6 +693,16 @@ return mIsAnchoredToBottomControls; } + @Override + public @Nullable Integer getSheetBackgroundColor() { + if (mBottomSheet == null + || getCurrentSheetContent() == null + || !getCurrentSheetContent().hasSolidBackgroundColor()) { + return null; + } + return mBottomSheet.getSheetBackgroundColor(); + } + // ScrimCoordinator.Observer @Override public void scrimVisibilityChanged(boolean scrimVisible) {
diff --git a/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetControllerImplUnitTest.java b/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetControllerImplUnitTest.java index 8bf137b..f66727b 100644 --- a/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetControllerImplUnitTest.java +++ b/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetControllerImplUnitTest.java
@@ -62,6 +62,7 @@ public void setUp() { MockitoAnnotations.openMocks(this); Activity activity = buildActivity(Activity.class).setup().get(); + activity.setTheme(R.style.Theme_BrowserUI_DayNight); mWindow = activity.getWindow(); when(mRoot.getContext()).thenReturn(activity); when(mRoot.findViewById(R.id.bottom_sheet)).thenReturn(mBottomSheet);
diff --git a/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetUnitTest.java b/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetUnitTest.java index d3d2a07..7dd7ebda 100644 --- a/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetUnitTest.java +++ b/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetUnitTest.java
@@ -44,6 +44,7 @@ public void setUp() { MockitoAnnotations.openMocks(this); Activity activity = buildActivity(Activity.class).setup().get(); + activity.setTheme(R.style.Theme_BrowserUI_DayNight); mBottomSheet = (BottomSheet) LayoutInflater.from(activity).inflate(R.layout.bottom_sheet, null); mBottomSheet.setSheetContainerForTesting(mSheetContainer);
diff --git a/components/browser_ui/bottomsheet/android/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetContent.java b/components/browser_ui/bottomsheet/android/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetContent.java index 95f87a4..cafa11e 100644 --- a/components/browser_ui/bottomsheet/android/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetContent.java +++ b/components/browser_ui/bottomsheet/android/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetContent.java
@@ -7,14 +7,12 @@ import android.content.Context; import android.view.View; -import androidx.annotation.ColorInt; import androidx.annotation.IntDef; import androidx.annotation.StringRes; import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; -import org.chromium.components.browser_ui.styles.SemanticColorUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -65,25 +63,16 @@ View getContentView(); /** - * Gets the background color for the bottom sheet content, defaulting to the semantic default - * background color if no background color is specified by the content. This should return null - * if the sheet content is showing tab content / a page preview. - */ - @ColorInt - default @Nullable Integer getBackgroundColor() { - return SemanticColorUtils.getDefaultBgColor(getContentView().getContext()); - } - - /** * Get the {@link View} that contains the toolbar specific to the content being displayed. If * null is returned, the omnibox is used. * * @return The toolbar view. */ - @Nullable - View getToolbarView(); + @Nullable View getToolbarView(); - /** @return The vertical scroll offset of the content view. */ + /** + * @return The vertical scroll offset of the content view. + */ int getVerticalScrollOffset(); /** @@ -140,6 +129,14 @@ } /** + * Returns whether this sheet content has a solid background color. Return false when the sheet + * is showing complex content like tab content / a page preview. + */ + default boolean hasSolidBackgroundColor() { + return true; + } + + /** * The height of bottom sheet in PEEK mode. The sheet content that wants to show content as PEEK * can override this method and provide a non-negative height. This interface by default * supplies {@link HeightMode#DISABLED}.
diff --git a/components/browser_ui/bottomsheet/android/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetController.java b/components/browser_ui/bottomsheet/android/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetController.java index de92866..b9e2b7a5 100644 --- a/components/browser_ui/bottomsheet/android/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetController.java +++ b/components/browser_ui/bottomsheet/android/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetController.java
@@ -4,6 +4,7 @@ package org.chromium.components.browser_ui.bottomsheet; +import androidx.annotation.ColorInt; import androidx.annotation.IntDef; import org.chromium.build.annotations.NullMarked; @@ -215,4 +216,11 @@ * controls UI. */ boolean isAnchoredToBottomControls(); + + /** + * Get the current background color for the bottom sheet. If the sheet does not have a solid + * background color, this will return null. + */ + @ColorInt + @Nullable Integer getSheetBackgroundColor(); }
diff --git a/components/browser_ui/media/android/java/src/org/chromium/components/browser_ui/media/MediaNotificationController.java b/components/browser_ui/media/android/java/src/org/chromium/components/browser_ui/media/MediaNotificationController.java index 51eefa85..c2fb02f8 100644 --- a/components/browser_ui/media/android/java/src/org/chromium/components/browser_ui/media/MediaNotificationController.java +++ b/components/browser_ui/media/android/java/src/org/chromium/components/browser_ui/media/MediaNotificationController.java
@@ -4,6 +4,7 @@ package org.chromium.components.browser_ui.media; +import static org.chromium.build.NullUtil.assertNonNull; import static org.chromium.build.NullUtil.assumeNonNull; import android.app.PendingIntent; @@ -396,7 +397,7 @@ @VisibleForTesting public PendingIntentProvider createPendingIntent(String action) { - Intent intent = mDelegate.createServiceIntent().setAction(action); + Intent intent = assumeNonNull(mDelegate.createServiceIntent()).setAction(action); return PendingIntentProvider.getService( getContext(), 0, @@ -434,7 +435,7 @@ /** An interface for separating embedder-specific logic. */ public interface Delegate { /** Returns an intent that will start a Service which listens to notification actions. */ - Intent createServiceIntent(); + @Nullable Intent createServiceIntent(); /** Returns the name of the embedding app. */ String getAppName(); @@ -531,7 +532,7 @@ mService = null; } - public boolean processIntent(Service service, Intent intent) { + public boolean processIntent(Service service, @Nullable Intent intent) { if (intent == null || mMediaNotificationInfo == null) return false; if (intent.getAction() == null) { @@ -639,7 +640,7 @@ // catch the exception, and `mService` will remain null for us to try again later. try { ForegroundServiceUtils.getInstance() - .startForegroundService(mDelegate.createServiceIntent()); + .startForegroundService(assertNonNull(mDelegate.createServiceIntent())); } catch (RuntimeException e) { } } else {
diff --git a/components/browser_ui/styles/android/java/res/values/semantic_colors_dynamic.xml b/components/browser_ui/styles/android/java/res/values/semantic_colors_dynamic.xml index 8e1bff0..21038e0 100644 --- a/components/browser_ui/styles/android/java/res/values/semantic_colors_dynamic.xml +++ b/components/browser_ui/styles/android/java/res/values/semantic_colors_dynamic.xml
@@ -8,7 +8,6 @@ <!-- LINT.IfChange --> <macro name="default_bg_color">?attr/colorSurface</macro> <macro name="default_bg_color_elev_0">?attr/colorSurface</macro> - <macro name="default_bg_color_inverse">?attr/colorSurfaceInverse</macro> <macro name="default_control_color_active">?attr/colorPrimary</macro> <macro name="default_control_color_normal">?attr/colorOnSurfaceVariant</macro>
diff --git a/components/commerce/core/commerce_constants.h b/components/commerce/core/commerce_constants.h index 261de088..03357692 100644 --- a/components/commerce/core/commerce_constants.h +++ b/components/commerce/core/commerce_constants.h
@@ -13,10 +13,6 @@ // The host for compare. inline constexpr char kChromeUICompareHost[] = "compare"; -// The URL for managing compare entities. -inline constexpr char kChromeUICompareListsUrl[] = - "chrome://history/comparisonTables"; - // The URL for compare. inline constexpr char kChromeUICompareUrl[] = "chrome://compare";
diff --git a/components/exo/wayland/BUILD.gn b/components/exo/wayland/BUILD.gn index 0948ac1..e7a7bdc 100644 --- a/components/exo/wayland/BUILD.gn +++ b/components/exo/wayland/BUILD.gn
@@ -419,7 +419,7 @@ "//third_party/wayland-protocols:text_input_extension_protocol", "//third_party/wayland-protocols:text_input_protocol", "//third_party/wayland-protocols:touchpad_haptics_protocol", - "//third_party/wayland-protocols:ui_controls_v1_protocol", + "//third_party/wayland-protocols:ui_controls_protocol", "//third_party/wayland-protocols:viewporter_protocol", "//third_party/wayland-protocols:vsync_feedback_protocol", "//third_party/wayland-protocols:vsync_feedback_protocol",
diff --git a/components/input/render_input_router.mojom b/components/input/render_input_router.mojom index 78d66c5..d4563b9 100644 --- a/components/input/render_input_router.mojom +++ b/components/input/render_input_router.mojom
@@ -62,12 +62,11 @@ // Viz needs this to do input handling on it's side. StateOnTouchTransfer(TouchTransferState state); - // Notifies RenderInputRouters corresponding to |frame_sink_ids| on the + // Notifies RenderInputRouter corresponding to |frame_sink_id| on the // VizCompositor thread of changes to |force_enable_zoom| state for // Accessibility. - ForceEnableZoomStateChanged( - bool force_enable_zoom, - array<viz.mojom.FrameSinkId> frame_sink_ids); + ForceEnableZoomStateChanged(bool force_enable_zoom, + viz.mojom.FrameSinkId frame_sink_id); // Stops any ongoing flings for |frame_sink_id| on VizCompositorThread. StopFlingingOnViz(viz.mojom.FrameSinkId frame_sink_id); @@ -94,32 +93,28 @@ interface RenderInputRouterDelegateClient { // Notifies InputEventObservers in the browser of input events being handled // on Viz (with InputVizard). - NotifyObserversOfInputEvent(viz.mojom.FrameSinkId id, - blink.mojom.Event event, + NotifyObserversOfInputEvent(blink.mojom.Event event, bool dispatched_to_renderer); // Notifies InputEventObservers in the browser of input event acks being // handled on Viz (with InputVizard). - NotifyObserversOfInputEventAcks( - viz.mojom.FrameSinkId id, blink.mojom.InputEventResultSource ack_source, + NotifyObserversOfInputEventAcks(blink.mojom.InputEventResultSource ack_source, blink.mojom.InputEventResultState ack_result, blink.mojom.Event event); // Notifies the browser of an invalid input event source being seen on // the VizCompositor thread when handling input. - OnInvalidInputEventSource(viz.mojom.FrameSinkId id); + OnInvalidInputEventSource(); // Sends |DidOverscrollParams| to the browser to allow overscroll effect to // request input back if it ends up consuming the input sequence. StateOnOverscrollTransfer( - viz.mojom.FrameSinkId frame_sink_id, blink.mojom.DidOverscrollParams? overscroll); - // Notifies browser that the renderer (corresponding to |frame_sink_id|) is - // responsive after being unresponsive or has turned unresonsive to input - // events. For the latter, it also passes over the timestamp when an input - // event timed out without getting an ack from the renderer. + // Notifies browser that the renderer is responsive after being unresponsive + // or has turned unresonsive to input events. For the latter, it also passes + // over the timestamp when an input event timed out without getting an ack + // from the renderer. RendererInputResponsivenessChanged( - viz.mojom.FrameSinkId frame_sink_id, bool is_responsive, mojo_base.mojom.TimeTicks? ack_timeout_ts); };
diff --git a/components/lens/lens_features.cc b/components/lens/lens_features.cc index d251dd4..e6c0f61 100644 --- a/components/lens/lens_features.cc +++ b/components/lens/lens_features.cc
@@ -556,6 +556,9 @@ &kLensOverlayEduActionChip, "url-path-forced-allowed-match-patterns", "[]"}; +const base::FeatureParam<bool> kLensOverlayEduActionChipDisabledByGlic{ + &kLensOverlayEduActionChip, "disabled-by-glic", true}; + std::string GetHomepageURLForLens() { return kHomepageURLForLens.Get(); } @@ -1187,4 +1190,8 @@ return kLensOverlayEduHashedDomainBlockFilters.Get(); } +bool IsLensOverlayEduActionChipDisabledByGlic() { + return kLensOverlayEduActionChipDisabledByGlic.Get(); +} + } // namespace lens::features
diff --git a/components/lens/lens_features.h b/components/lens/lens_features.h index 175a9b7d..9e3a7ac 100644 --- a/components/lens/lens_features.h +++ b/components/lens/lens_features.h
@@ -147,6 +147,10 @@ COMPONENT_EXPORT(LENS_FEATURES) extern const base::FeatureParam<bool> kLensOverlayEnableOpenInNewTab; +// Whether the EDU action chip should be disabled by glic. +COMPONENT_EXPORT(LENS_FEATURES) +extern const base::FeatureParam<bool> kLensOverlayEduActionChipDisabledByGlic; + // The URL for the Lens home page. COMPONENT_EXPORT(LENS_FEATURES) extern std::string GetHomepageURLForLens(); @@ -902,5 +906,9 @@ COMPONENT_EXPORT(LENS_FEATURES) extern std::string GetLensOverlayEduHashedDomainBlockFilters(); +// Whether EDU action chip should be disabled by glic. +COMPONENT_EXPORT(LENS_FEATURES) +bool IsLensOverlayEduActionChipDisabledByGlic(); + } // namespace lens::features #endif // COMPONENTS_LENS_LENS_FEATURES_H_
diff --git a/components/omnibox/browser/autocomplete_controller.cc b/components/omnibox/browser/autocomplete_controller.cc index ec5c289..1093528 100644 --- a/components/omnibox/browser/autocomplete_controller.cc +++ b/components/omnibox/browser/autocomplete_controller.cc
@@ -1105,10 +1105,8 @@ if (omnibox::IsAndroidHub(input_.current_page_classification())) { return provider->type() == AutocompleteProvider::TYPE_SEARCH || provider->type() == AutocompleteProvider::TYPE_OPEN_TAB || - (OmniboxFieldTrial::kAndroidHubSearchEnableBookmarkProvider.Get() && - provider->type() == AutocompleteProvider::TYPE_BOOKMARK) || - (OmniboxFieldTrial::kAndroidHubSearchEnableHistoryProvider.Get() && - provider->type() == AutocompleteProvider::TYPE_HISTORY_QUICK); + provider->type() == AutocompleteProvider::TYPE_BOOKMARK || + provider->type() == AutocompleteProvider::TYPE_HISTORY_QUICK; } #endif
diff --git a/components/omnibox/browser/omnibox_field_trial.h b/components/omnibox/browser/omnibox_field_trial.h index 8057d54..8e98fbc 100644 --- a/components/omnibox/browser/omnibox_field_trial.h +++ b/components/omnibox/browser/omnibox_field_trial.h
@@ -741,20 +741,6 @@ // <- Site Search Starter Pack // --------------------------------------------------------- -// Android Hub Search --> -// -// Controls different variations of android hub search including what -// primitives are included. -#if BUILDFLAG(IS_ANDROID) -constexpr base::FeatureParam<bool> kAndroidHubSearchEnableBookmarkProvider{ - &omnibox::kAndroidHubSearch, "enable_bookmark_provider", true}; - -constexpr base::FeatureParam<bool> kAndroidHubSearchEnableHistoryProvider{ - &omnibox::kAndroidHubSearch, "enable_history_provider", true}; -#endif - -// <- Android Hub Search -// --------------------------------------------------------- // Power Tools --> constexpr base::FeatureParam<size_t> kOmniboxNumNtpZpsRecentSearches{ &omnibox::kNumNtpZpsRecentSearches, "omnibox_num_ntp_zps_recent_searches",
diff --git a/components/omnibox/common/android/java/src/org/chromium/components/omnibox/OmniboxFeatures.java b/components/omnibox/common/android/java/src/org/chromium/components/omnibox/OmniboxFeatures.java index 30e42f3..53f589d 100644 --- a/components/omnibox/common/android/java/src/org/chromium/components/omnibox/OmniboxFeatures.java +++ b/components/omnibox/common/android/java/src/org/chromium/components/omnibox/OmniboxFeatures.java
@@ -110,9 +110,6 @@ public static final CachedFlag sRetainOmniboxOnFocus = newFlag(OmniboxFeatureList.RETAIN_OMNIBOX_ON_FOCUS, FeatureState.ENABLED_IN_TEST); - public static final CachedFlag sAndroidHubSearch = - newFlag(OmniboxFeatureList.ANDROID_HUB_SEARCH, FeatureState.ENABLED_IN_PROD); - public static final CachedFlag sPostDelayedTaskFocusTab = newFlag(OmniboxFeatureList.POST_DELAYED_TASK_FOCUS_TAB, FeatureState.ENABLED_IN_PROD); @@ -178,11 +175,6 @@ public static final BooleanCachedFeatureParam sJumpStartOmniboxCoverRecentlyVisitedPage = newBooleanParam(sJumpStartOmnibox, "jump_start_cover_recently_visited_page", false); - // This parameter allows the user to click enter when on hub search to perform a search on the - // listed suggestions or perform a google search on the query if no suggestions are found. - public static final BooleanCachedFeatureParam sAndroidHubSearchEnterPerformsSearch = - newBooleanParam(sAndroidHubSearch, "enable_press_enter_to_search", true); - // Omnibox Diagnostics private static final CachedFlag sDiagnostics = newFlag(OmniboxFeatureList.DIAGNOSTICS, FeatureState.DISABLED);
diff --git a/components/omnibox/common/omnibox_feature_configs.cc b/components/omnibox/common/omnibox_feature_configs.cc index b5e52bb3..4d280b6 100644 --- a/components/omnibox/common/omnibox_feature_configs.cc +++ b/components/omnibox/common/omnibox_feature_configs.cc
@@ -290,7 +290,7 @@ realbox_unscoped_suggestions = base::FeatureParam<bool>(&kSearchAggregatorProvider, - "realbox_unscoped_suggestions", false) + "realbox_unscoped_suggestions", true) .Get(); scoring_max_matches_created_per_type =
diff --git a/components/omnibox/common/omnibox_features.cc b/components/omnibox/common/omnibox_features.cc index fe73bfc2..95a2f434 100644 --- a/components/omnibox/common/omnibox_features.cc +++ b/components/omnibox/common/omnibox_features.cc
@@ -398,9 +398,6 @@ "SuppressIntermediateACUpdatesOnLowEndDevices", DISABLED); -// (Android only) Show the search feature in the hub. -BASE_FEATURE(kAndroidHubSearch, "AndroidHubSearch", ENABLED); - // (Android only) Show tab groups via the search feature in the hub. BASE_FEATURE(kAndroidHubSearchTabGroups, "AndroidHubSearchTabGroups", DISABLED); @@ -424,7 +421,6 @@ &kOmniboxElegantTextHeight, &kRetainOmniboxOnFocus, &kJumpStartOmnibox, - &kAndroidHubSearch, &kAndroidHubSearchTabGroups, &kPostDelayedTaskFocusTab, &kOmniboxMobileParityUpdate};
diff --git a/components/omnibox/common/omnibox_features.h b/components/omnibox/common/omnibox_features.h index bdc1b35..017b992 100644 --- a/components/omnibox/common/omnibox_features.h +++ b/components/omnibox/common/omnibox_features.h
@@ -138,7 +138,6 @@ BASE_DECLARE_FEATURE(kRetainOmniboxOnFocus); BASE_DECLARE_FEATURE(kJumpStartOmnibox); BASE_DECLARE_FEATURE(kSuppressIntermediateACUpdatesOnLowEndDevices); -BASE_DECLARE_FEATURE(kAndroidHubSearch); // Delay focusTab to prioritize navigation (https://crbug.com/374852568). BASE_DECLARE_FEATURE(kPostDelayedTaskFocusTab); BASE_DECLARE_FEATURE(kAndroidHubSearchTabGroups);
diff --git a/components/optimization_guide/internal b/components/optimization_guide/internal index 2cc55d5..abe28fc 160000 --- a/components/optimization_guide/internal +++ b/components/optimization_guide/internal
@@ -1 +1 @@ -Subproject commit 2cc55d5ca41fa04a1ac7a1c7971a9aba449d01b3 +Subproject commit abe28fc69cad880ec92b198727268aa7fbea55a0
diff --git a/components/payments/content/secure_payment_confirmation_app_factory.cc b/components/payments/content/secure_payment_confirmation_app_factory.cc index 7c56bec..687ae18 100644 --- a/components/payments/content/secure_payment_confirmation_app_factory.cc +++ b/components/payments/content/secure_payment_confirmation_app_factory.cc
@@ -150,6 +150,30 @@ } } + if (!request->payment_entities_logos.empty()) { + for (const mojom::PaymentEntityLogoPtr& logo : + request->payment_entities_logos) { + if (logo.is_null()) { + *error_message = errors::kNonNullPaymentEntityLogoRequired; + return false; + } + + if (!logo->url.is_valid()) { + *error_message = errors::kValidLogoUrlRequired; + return false; + } + if (!logo->url.SchemeIsHTTPOrHTTPS() && + !logo->url.SchemeIs(url::kDataScheme)) { + *error_message = errors::kValidLogoUrlSchemeRequired; + return false; + } + if (logo->label.empty()) { + *error_message = errors::kLogoLabelRequired; + return false; + } + } + } + return true; } @@ -318,11 +342,47 @@ return; } + // We currently support two ways to specify logos to be shown on the UX: + // the old (experimental) network_info/issuer_info fields, and the new + // payment_entities_logos field. Both are flag-guarded, and only one flow + // is supported at a time, so to simplify the rest of the logic we + // consolidate payment_entities_logos (if set) into + // issuer_info/network_info. + // + // If both flags are turned on (and payment_entities_logos is provided), + // then payment_entities_logos will 'win' and overwrite network_info and + // issuer_info. + // + // TODO(crbug.com/417683819): Switch to using an array of logos in + // SecurePaymentConfirmationAppFactory, and invert the logic here. + mojom::SecurePaymentConfirmationRequestPtr spc_request = + method_data->secure_payment_confirmation.Clone(); + if (base::FeatureList::IsEnabled( + blink::features::kSecurePaymentConfirmationUxRefresh) && + !spc_request->payment_entities_logos.empty()) { + const mojom::PaymentEntityLogoPtr& first_logo = + spc_request->payment_entities_logos[0]; + spc_request->network_info = mojom::NetworkOrIssuerInformation::New( + /*name=*/first_logo->label, + /*icon=*/first_logo->url); + + if (spc_request->payment_entities_logos.size() > 1) { + const mojom::PaymentEntityLogoPtr& second_logo = + spc_request->payment_entities_logos[1]; + spc_request->issuer_info = mojom::NetworkOrIssuerInformation::New( + /*name=*/second_logo->label, + /*icon=*/second_logo->url); + + } else { + spc_request->issuer_info = nullptr; + } + } + // Record if the user will be offered an opt-out experience. Technically // SPC has not been 'selected' yet in the conceptual PaymentRequest flow, // however we know that for SPC it must be the only payment method offered // so we are safe to record this now. - if (method_data->secure_payment_confirmation->show_opt_out) { + if (spc_request->show_opt_out) { delegate->SetOptOutOffered(); } @@ -343,10 +403,9 @@ base::BindOnce(&SecurePaymentConfirmationAppFactory:: OnIsUserVerifyingPlatformAuthenticatorAvailable, weak_ptr_factory_.GetWeakPtr(), - std::make_unique<Request>( - delegate, web_data_service, - method_data->secure_payment_confirmation.Clone(), - std::move(authenticator)))); + std::make_unique<Request>(delegate, web_data_service, + std::move(spc_request), + std::move(authenticator)))); return; } }
diff --git a/components/payments/content/secure_payment_confirmation_app_factory_unittest.cc b/components/payments/content/secure_payment_confirmation_app_factory_unittest.cc index 4013c487..3bb0a6b 100644 --- a/components/payments/content/secure_payment_confirmation_app_factory_unittest.cc +++ b/components/payments/content/secure_payment_confirmation_app_factory_unittest.cc
@@ -17,6 +17,7 @@ #include "components/payments/content/mock_payment_app_factory_delegate.h" #include "components/payments/content/mock_payment_manifest_web_data_service.h" #include "components/payments/core/features.h" +#include "components/payments/core/native_error_strings.h" #include "components/webauthn/core/browser/mock_internal_authenticator.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/test_browser_context.h" @@ -121,7 +122,8 @@ auto mock_delegate = std::make_unique<MockPaymentAppFactoryDelegate>( web_contents_, std::move(method_data)); - EXPECT_CALL(*mock_delegate, OnPaymentAppCreationError(_, _)); + EXPECT_CALL(*mock_delegate, + OnPaymentAppCreationError(errors::kCredentialIdsRequired, _)); secure_payment_confirmation_app_factory_->Create(mock_delegate->GetWeakPtr()); } @@ -137,7 +139,8 @@ auto mock_delegate = std::make_unique<MockPaymentAppFactoryDelegate>( web_contents_, std::move(method_data)); - EXPECT_CALL(*mock_delegate, OnPaymentAppCreationError(_, _)); + EXPECT_CALL(*mock_delegate, + OnPaymentAppCreationError(errors::kCredentialIdsRequired, _)); secure_payment_confirmation_app_factory_->Create(mock_delegate->GetWeakPtr()); } @@ -153,7 +156,8 @@ auto mock_delegate = std::make_unique<MockPaymentAppFactoryDelegate>( web_contents_, std::move(method_data)); - EXPECT_CALL(*mock_delegate, OnPaymentAppCreationError(_, _)); + EXPECT_CALL(*mock_delegate, + OnPaymentAppCreationError(errors::kChallengeRequired, _)); secure_payment_confirmation_app_factory_->Create(mock_delegate->GetWeakPtr()); } @@ -169,7 +173,8 @@ auto mock_delegate = std::make_unique<MockPaymentAppFactoryDelegate>( web_contents_, std::move(method_data)); - EXPECT_CALL(*mock_delegate, OnPaymentAppCreationError(_, _)); + EXPECT_CALL(*mock_delegate, OnPaymentAppCreationError( + errors::kInstrumentDisplayNameRequired, _)); secure_payment_confirmation_app_factory_->Create(mock_delegate->GetWeakPtr()); } @@ -185,7 +190,8 @@ auto mock_delegate = std::make_unique<MockPaymentAppFactoryDelegate>( web_contents_, std::move(method_data)); - EXPECT_CALL(*mock_delegate, OnPaymentAppCreationError(_, _)); + EXPECT_CALL(*mock_delegate, OnPaymentAppCreationError( + errors::kValidInstrumentIconRequired, _)); secure_payment_confirmation_app_factory_->Create(mock_delegate->GetWeakPtr()); } @@ -202,7 +208,8 @@ auto mock_delegate = std::make_unique<MockPaymentAppFactoryDelegate>( web_contents_, std::move(method_data)); - EXPECT_CALL(*mock_delegate, OnPaymentAppCreationError(_, _)); + EXPECT_CALL(*mock_delegate, OnPaymentAppCreationError( + errors::kValidInstrumentIconRequired, _)); secure_payment_confirmation_app_factory_->Create(mock_delegate->GetWeakPtr()); } @@ -231,7 +238,8 @@ // EXPECT_CALL doesn't support <<, so to make it clear which rp_id was being // tested in a failure case we use SCOPED_TRACE. SCOPED_TRACE(rp_id); - EXPECT_CALL(*mock_delegate, OnPaymentAppCreationError(_, _)); + EXPECT_CALL(*mock_delegate, + OnPaymentAppCreationError(errors::kRpIdRequired, _)); secure_payment_confirmation_app_factory_->Create( mock_delegate->GetWeakPtr()); } @@ -250,7 +258,8 @@ auto mock_delegate = std::make_unique<MockPaymentAppFactoryDelegate>( web_contents_, std::move(method_data)); - EXPECT_CALL(*mock_delegate, OnPaymentAppCreationError(_, _)); + EXPECT_CALL(*mock_delegate, OnPaymentAppCreationError( + errors::kPayeeOriginOrPayeeNameRequired, _)); secure_payment_confirmation_app_factory_->Create(mock_delegate->GetWeakPtr()); } @@ -266,7 +275,8 @@ auto mock_delegate = std::make_unique<MockPaymentAppFactoryDelegate>( web_contents_, std::move(method_data)); - EXPECT_CALL(*mock_delegate, OnPaymentAppCreationError(_, _)); + EXPECT_CALL(*mock_delegate, OnPaymentAppCreationError( + errors::kPayeeOriginOrPayeeNameRequired, _)); secure_payment_confirmation_app_factory_->Create(mock_delegate->GetWeakPtr()); } @@ -283,7 +293,8 @@ auto mock_delegate = std::make_unique<MockPaymentAppFactoryDelegate>( web_contents_, std::move(method_data)); - EXPECT_CALL(*mock_delegate, OnPaymentAppCreationError(_, _)); + EXPECT_CALL(*mock_delegate, + OnPaymentAppCreationError(errors::kPayeeOriginMustBeHttps, _)); secure_payment_confirmation_app_factory_->Create(mock_delegate->GetWeakPtr()); } @@ -303,7 +314,8 @@ auto mock_delegate = std::make_unique<MockPaymentAppFactoryDelegate>( web_contents_, std::move(method_data)); - EXPECT_CALL(*mock_delegate, OnPaymentAppCreationError(_, _)); + EXPECT_CALL(*mock_delegate, + OnPaymentAppCreationError(errors::kNetworkNameRequired, _)); secure_payment_confirmation_app_factory_->Create(mock_delegate->GetWeakPtr()); } @@ -322,7 +334,8 @@ auto mock_delegate = std::make_unique<MockPaymentAppFactoryDelegate>( web_contents_, std::move(method_data)); - EXPECT_CALL(*mock_delegate, OnPaymentAppCreationError(_, _)); + EXPECT_CALL(*mock_delegate, + OnPaymentAppCreationError(errors::kValidNetworkIconRequired, _)); secure_payment_confirmation_app_factory_->Create(mock_delegate->GetWeakPtr()); } @@ -341,7 +354,8 @@ auto mock_delegate = std::make_unique<MockPaymentAppFactoryDelegate>( web_contents_, std::move(method_data)); - EXPECT_CALL(*mock_delegate, OnPaymentAppCreationError(_, _)); + EXPECT_CALL(*mock_delegate, + OnPaymentAppCreationError(errors::kValidNetworkIconRequired, _)); secure_payment_confirmation_app_factory_->Create(mock_delegate->GetWeakPtr()); } @@ -361,7 +375,8 @@ auto mock_delegate = std::make_unique<MockPaymentAppFactoryDelegate>( web_contents_, std::move(method_data)); - EXPECT_CALL(*mock_delegate, OnPaymentAppCreationError(_, _)); + EXPECT_CALL(*mock_delegate, + OnPaymentAppCreationError(errors::kIssuerNameRequired, _)); secure_payment_confirmation_app_factory_->Create(mock_delegate->GetWeakPtr()); } @@ -380,7 +395,8 @@ auto mock_delegate = std::make_unique<MockPaymentAppFactoryDelegate>( web_contents_, std::move(method_data)); - EXPECT_CALL(*mock_delegate, OnPaymentAppCreationError(_, _)); + EXPECT_CALL(*mock_delegate, + OnPaymentAppCreationError(errors::kValidIssuerIconRequired, _)); secure_payment_confirmation_app_factory_->Create(mock_delegate->GetWeakPtr()); } @@ -399,10 +415,115 @@ auto mock_delegate = std::make_unique<MockPaymentAppFactoryDelegate>( web_contents_, std::move(method_data)); - EXPECT_CALL(*mock_delegate, OnPaymentAppCreationError(_, _)); + EXPECT_CALL(*mock_delegate, + OnPaymentAppCreationError(errors::kValidIssuerIconRequired, _)); secure_payment_confirmation_app_factory_->Create(mock_delegate->GetWeakPtr()); } +// Test that parsing a SecurePaymentConfirmationRequest with a null +// PaymentEntityLogo fails. +TEST_F(SecurePaymentConfirmationAppFactoryTest, + SecureConfirmationPaymentRequest_NullPaymentEntityLogo) { + auto method_data = mojom::PaymentMethodData::New(); + method_data->supported_method = "secure-payment-confirmation"; + mojom::SecurePaymentConfirmationRequestPtr spc_request = + CreateSecurePaymentConfirmationRequest(); + spc_request->payment_entities_logos.push_back(nullptr); + method_data->secure_payment_confirmation = std::move(spc_request); + + auto mock_delegate = std::make_unique<MockPaymentAppFactoryDelegate>( + web_contents_, std::move(method_data)); + + EXPECT_CALL( + *mock_delegate, + OnPaymentAppCreationError(errors::kNonNullPaymentEntityLogoRequired, _)); + secure_payment_confirmation_app_factory_->Create(mock_delegate->GetWeakPtr()); +} + +// Test that parsing a SecurePaymentConfirmationRequest with a PaymentEntityLogo +// that has an empty url fails. +TEST_F(SecurePaymentConfirmationAppFactoryTest, + SecureConfirmationPaymentRequest_EmptyPaymentEntityLogoUrl) { + auto method_data = mojom::PaymentMethodData::New(); + method_data->supported_method = "secure-payment-confirmation"; + mojom::SecurePaymentConfirmationRequestPtr spc_request = + CreateSecurePaymentConfirmationRequest(); + spc_request->payment_entities_logos.push_back( + mojom::PaymentEntityLogo::New(GURL(), "Label")); + method_data->secure_payment_confirmation = std::move(spc_request); + + auto mock_delegate = std::make_unique<MockPaymentAppFactoryDelegate>( + web_contents_, std::move(method_data)); + + EXPECT_CALL(*mock_delegate, + OnPaymentAppCreationError(errors::kValidLogoUrlRequired, _)); + secure_payment_confirmation_app_factory_->Create(mock_delegate->GetWeakPtr()); +} + +// Test that parsing a SecurePaymentConfirmationRequest with a PaymentEntityLogo +// that has an invalid url fails. +TEST_F(SecurePaymentConfirmationAppFactoryTest, + SecureConfirmationPaymentRequest_InvalidPaymentEntityLogoUrl) { + auto method_data = mojom::PaymentMethodData::New(); + method_data->supported_method = "secure-payment-confirmation"; + mojom::SecurePaymentConfirmationRequestPtr spc_request = + CreateSecurePaymentConfirmationRequest(); + spc_request->payment_entities_logos.push_back( + mojom::PaymentEntityLogo::New(GURL("thisisnotaurl"), "Label")); + method_data->secure_payment_confirmation = std::move(spc_request); + + auto mock_delegate = std::make_unique<MockPaymentAppFactoryDelegate>( + web_contents_, std::move(method_data)); + + EXPECT_CALL(*mock_delegate, + OnPaymentAppCreationError(errors::kValidLogoUrlRequired, _)); + secure_payment_confirmation_app_factory_->Create(mock_delegate->GetWeakPtr()); +} + +// Test that parsing a SecurePaymentConfirmationRequest with a PaymentEntityLogo +// that has a url with a disallowed scheme fails. +TEST_F(SecurePaymentConfirmationAppFactoryTest, + SecureConfirmationPaymentRequest_DisallowedSchemePaymentEntityLogoUrl) { + auto method_data = mojom::PaymentMethodData::New(); + method_data->supported_method = "secure-payment-confirmation"; + mojom::SecurePaymentConfirmationRequestPtr spc_request = + CreateSecurePaymentConfirmationRequest(); + spc_request->payment_entities_logos.push_back(mojom::PaymentEntityLogo::New( + GURL("blob://blob.foo.com/logo.png"), "Label")); + method_data->secure_payment_confirmation = std::move(spc_request); + + auto mock_delegate = std::make_unique<MockPaymentAppFactoryDelegate>( + web_contents_, std::move(method_data)); + + EXPECT_CALL(*mock_delegate, OnPaymentAppCreationError( + errors::kValidLogoUrlSchemeRequired, _)); + secure_payment_confirmation_app_factory_->Create(mock_delegate->GetWeakPtr()); +} + +// Test that parsing a SecurePaymentConfirmationRequest with a PaymentEntityLogo +// that has an empty label fails. +TEST_F(SecurePaymentConfirmationAppFactoryTest, + SecureConfirmationPaymentRequest_EmptyPaymentEntityLogoLabel) { + auto method_data = mojom::PaymentMethodData::New(); + method_data->supported_method = "secure-payment-confirmation"; + mojom::SecurePaymentConfirmationRequestPtr spc_request = + CreateSecurePaymentConfirmationRequest(); + spc_request->payment_entities_logos.push_back( + mojom::PaymentEntityLogo::New(GURL("https://entity.example/icon.png"), + /*label=*/"")); + method_data->secure_payment_confirmation = std::move(spc_request); + + auto mock_delegate = std::make_unique<MockPaymentAppFactoryDelegate>( + web_contents_, std::move(method_data)); + + EXPECT_CALL(*mock_delegate, + OnPaymentAppCreationError(errors::kLogoLabelRequired, _)); + secure_payment_confirmation_app_factory_->Create(mock_delegate->GetWeakPtr()); +} + +// TODO(crbug.com/417683819): Add tests verifying that paymentEntitiesLogos is +// correctly converted into icons to be downloaded. + class SecurePaymentConfirmationAppFactoryUsingCredentialStoreAPIsTest : public SecurePaymentConfirmationAppFactoryTest { public:
diff --git a/components/payments/core/native_error_strings.cc b/components/payments/core/native_error_strings.cc index 62d3731..c41ef6d1 100644 --- a/components/payments/core/native_error_strings.cc +++ b/components/payments/core/native_error_strings.cc
@@ -266,5 +266,22 @@ "The \"secure-payment-confirmation\" method requires a valid URL in the " "\"issuerInfo.icon\" field."; +const char kNonNullPaymentEntityLogoRequired[] = + "The \"secure-payment-confirmation\" method requires that each entry in " + "\"paymentEntitiesLogos\" is non-null."; + +extern const char kValidLogoUrlRequired[] = + "The \"secure-payment-confirmation\" method requires that each entry in " + "\"paymentEntitiesLogos\" has a valid URL in the \"url\" field."; + +extern const char kValidLogoUrlSchemeRequired[] = + "The \"secure-payment-confirmation\" method requires that each entry in " + "\"paymentEntitiesLogos\" has a URL whose scheme is one of \"https\", " + "\"http\", or \"data\" in the \"url\" field."; + +extern const char kLogoLabelRequired[] = + "The \"secure-payment-confirmation\" method requires that each entry in " + "\"paymentEntitiesLogos\" has a non-empty \"label\" field."; + } // namespace errors } // namespace payments
diff --git a/components/payments/core/native_error_strings.h b/components/payments/core/native_error_strings.h index de8c1ef6..6c44d83d 100644 --- a/components/payments/core/native_error_strings.h +++ b/components/payments/core/native_error_strings.h
@@ -305,6 +305,24 @@ // was not a valid URL in the "secure-payment-confirmation" method. extern const char kValidIssuerIconRequired[]; +// Used when a logo in the paymentEntitiesLogo list is null. A well-behaving +// renderer cannot end up in this situation, but we must handle it gracefully as +// renderers cannot be trusted. +extern const char kNonNullPaymentEntityLogoRequired[]; + +// Used when a logo in the paymentEntitiesLogo list had a non-valid URL in its +// url field in the "secure-payment-confirmation" method. +extern const char kValidLogoUrlRequired[]; + +// Used when a logo in the paymentEntitiesLogo list had a URL in its url field +// whose scheme was not one of "https", "http", or "data" in the +// "secure-payment-confirmation" method. +extern const char kValidLogoUrlSchemeRequired[]; + +// Used when a logo in the paymentEntitiesLogo list had an empty label field in +// the "secure-payment-confirmation" method. +extern const char kLogoLabelRequired[]; + } // namespace errors } // namespace payments
diff --git a/components/permissions/android/java/src/org/chromium/components/permissions/AndroidPermissionRequester.java b/components/permissions/android/java/src/org/chromium/components/permissions/AndroidPermissionRequester.java index 757aefe..d48e338 100644 --- a/components/permissions/android/java/src/org/chromium/components/permissions/AndroidPermissionRequester.java +++ b/components/permissions/android/java/src/org/chromium/components/permissions/AndroidPermissionRequester.java
@@ -308,7 +308,7 @@ public static void showMissingPermissionDialog( WindowAndroid windowAndroid, String message, - Consumer<PropertyModel> onPositiveButtonClicked, + Consumer<@Nullable PropertyModel> onPositiveButtonClicked, Runnable onCancelled) { final ModalDialogManager modalDialogManager = windowAndroid.getModalDialogManager(); assert modalDialogManager != null : "ModalDialogManager is null";
diff --git a/components/viz/host/BUILD.gn b/components/viz/host/BUILD.gn index 2f6b8750..a3b2a3e 100644 --- a/components/viz/host/BUILD.gn +++ b/components/viz/host/BUILD.gn
@@ -37,6 +37,7 @@ deps = [ "//base", + "//components/input", "//gpu/ipc/client", "//gpu/ipc/common", "//services/viz/privileged/mojom",
diff --git a/components/viz/host/DEPS b/components/viz/host/DEPS index 5074cb6..25676c5 100644 --- a/components/viz/host/DEPS +++ b/components/viz/host/DEPS
@@ -3,6 +3,7 @@ include_rules = [ "+components/discardable_memory/public/mojom", "+components/input/render_input_router.mojom.h", + "+components/input/utils.h", "+gpu/command_buffer/client", "+gpu/command_buffer/common", "+gpu/config",
diff --git a/components/viz/host/host_frame_sink_manager.cc b/components/viz/host/host_frame_sink_manager.cc index 6edcf11..c81e547 100644 --- a/components/viz/host/host_frame_sink_manager.cc +++ b/components/viz/host/host_frame_sink_manager.cc
@@ -16,6 +16,7 @@ #include "base/task/sequenced_task_runner.h" #include "base/task/single_thread_task_runner.h" #include "base/time/time.h" +#include "components/input/utils.h" #include "components/viz/common/performance_hint_utils.h" #include "components/viz/common/surfaces/surface_info.h" #include "components/viz/host/renderer_settings_creation.h" @@ -51,6 +52,11 @@ frame_sink_manager_remote_.set_disconnect_handler(base::BindOnce( &HostFrameSinkManager::OnConnectionLost, base::Unretained(this))); + if (input::InputUtils::IsTransferInputToVizSupported()) { + frame_sink_manager_->SetupRendererInputRouterDelegateRegistry( + rir_delegate_registry_.BindNewPipeAndPassReceiver()); + } + if (connection_was_lost_) { RegisterAfterConnectionLoss(); connection_was_lost_ = false; @@ -309,13 +315,15 @@ } void HostFrameSinkManager::SetupRenderInputRouterDelegateConnection( - base::UnguessableToken grouping_id, - mojo::PendingRemote<input::mojom::RenderInputRouterDelegateClient> + const FrameSinkId& frame_sink_id, + mojo::PendingAssociatedRemote<input::mojom::RenderInputRouterDelegateClient> rir_delegate_client_remote, - mojo::PendingReceiver<input::mojom::RenderInputRouterDelegate> + mojo::PendingAssociatedReceiver<input::mojom::RenderInputRouterDelegate> rir_delegate_receiver) { - frame_sink_manager_->SetupRenderInputRouterDelegateConnection( - grouping_id, std::move(rir_delegate_client_remote), + CHECK(input::InputUtils::IsTransferInputToVizSupported()); + + rir_delegate_registry_->SetupRenderInputRouterDelegateConnection( + frame_sink_id, std::move(rir_delegate_client_remote), std::move(rir_delegate_receiver)); } @@ -387,6 +395,7 @@ // frame_sink_manager_remote_.reset() to avoid dangling ptr. frame_sink_manager_ = nullptr; frame_sink_manager_remote_.reset(); + rir_delegate_registry_.reset(); metrics_recorder_remote_.reset();
diff --git a/components/viz/host/host_frame_sink_manager.h b/components/viz/host/host_frame_sink_manager.h index 52f93c6..cbb4c12 100644 --- a/components/viz/host/host_frame_sink_manager.h +++ b/components/viz/host/host_frame_sink_manager.h
@@ -208,17 +208,18 @@ std::unique_ptr<CopyOutputRequest> request, bool capture_exact_surface_id = false); - // Setup the connection between the Browser (at WebContentsImpl level) and the - // VizCompositor thread (at InputManager level) to allow transferring + // Setup the connection between the Browser (at RenderWidgetHost level) and + // the VizCompositor thread (at InputManager level) to allow transferring // information from Viz to the Browser and vice versa. Viz can inform Browser // about inputs that it process on VizCompositor thread, and Browser can // inform Viz about |TouchTransferState| to start processing input events for // a sequence. void SetupRenderInputRouterDelegateConnection( - base::UnguessableToken grouping_id, - mojo::PendingRemote<input::mojom::RenderInputRouterDelegateClient> + const FrameSinkId& frame_sink_id, + mojo::PendingAssociatedRemote< + input::mojom::RenderInputRouterDelegateClient> rir_delegate_client_remote, - mojo::PendingReceiver<input::mojom::RenderInputRouterDelegate> + mojo::PendingAssociatedReceiver<input::mojom::RenderInputRouterDelegate> rir_delegate_receiver); // Notifies the VizCompositor thread (at InputManager level) about block state @@ -371,6 +372,8 @@ destination_token, std::unique_ptr<CopyOutputResult> copy_output_result) override; + mojo::Remote<mojom::RendererInputRouterDelegateRegistry> + rir_delegate_registry_; // Connections to/from FrameSinkManagerImpl. mojo::Remote<mojom::FrameSinkManager> frame_sink_manager_remote_; // This will point to |frame_sink_manager_remote_| if using mojo or it may
diff --git a/components/viz/service/display/display_scheduler.cc b/components/viz/service/display/display_scheduler.cc index 263df80..7195dc7 100644 --- a/components/viz/service/display/display_scheduler.cc +++ b/components/viz/service/display/display_scheduler.cc
@@ -387,7 +387,7 @@ // here the 0.8 constant is chosen to bias rounding up. int deadline_max_pending_swaps = (total_time_nanos + 0.8 * interval_nanos) / interval_nanos; - return std::clamp(deadline_max_pending_swaps, 0, param_max_pending_swaps); + return std::clamp(deadline_max_pending_swaps, 1, param_max_pending_swaps); } void DisplayScheduler::SetNeedsOneBeginFrame(bool needs_draw) {
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc index a93d044..774bec5 100644 --- a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc +++ b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
@@ -1250,15 +1250,10 @@ test_api_receiver_.Bind(std::move(receiver)); } -void FrameSinkManagerImpl::SetupRenderInputRouterDelegateConnection( - const base::UnguessableToken& grouping_id, - mojo::PendingRemote<input::mojom::RenderInputRouterDelegateClient> - rir_delegate_client_remote, - mojo::PendingReceiver<input::mojom::RenderInputRouterDelegate> - rir_delegate_receiver) { - input_manager_->SetupRenderInputRouterDelegateConnection( - grouping_id, std::move(rir_delegate_client_remote), - std::move(rir_delegate_receiver)); +void FrameSinkManagerImpl::SetupRendererInputRouterDelegateRegistry( + mojo::PendingReceiver<mojom::RendererInputRouterDelegateRegistry> + receiver) { + input_manager_->SetupRendererInputRouterDelegateRegistry(std::move(receiver)); } void FrameSinkManagerImpl::NotifyRendererBlockStateChanged(
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_impl.h b/components/viz/service/frame_sinks/frame_sink_manager_impl.h index 4bff8c9..3ebefa4 100644 --- a/components/viz/service/frame_sinks/frame_sink_manager_impl.h +++ b/components/viz/service/frame_sinks/frame_sink_manager_impl.h
@@ -186,12 +186,9 @@ override; void EnableFrameSinkManagerTestApi( mojo::PendingReceiver<mojom::FrameSinkManagerTestApi> receiver) override; - void SetupRenderInputRouterDelegateConnection( - const base::UnguessableToken& grouping_id, - mojo::PendingRemote<input::mojom::RenderInputRouterDelegateClient> - rir_delegate_client_remote, - mojo::PendingReceiver<input::mojom::RenderInputRouterDelegate> - rir_delegate_receiver) override; + void SetupRendererInputRouterDelegateRegistry( + mojo::PendingReceiver<mojom::RendererInputRouterDelegateRegistry> + receiver) override; void NotifyRendererBlockStateChanged( bool blocked, const std::vector<FrameSinkId>& render_input_routers) override;
diff --git a/components/viz/service/input/DEPS b/components/viz/service/input/DEPS index 145c84a..3c939b6 100644 --- a/components/viz/service/input/DEPS +++ b/components/viz/service/input/DEPS
@@ -2,7 +2,7 @@ include_rules = [ "+components/viz/service/frame_sinks", - "+mojo/public/cpp/bindings/receiver_set.h", + "+mojo/public/cpp/bindings/associated_receiver_set.h", "+ui/events", ]
diff --git a/components/viz/service/input/android_state_transfer_handler.cc b/components/viz/service/input/android_state_transfer_handler.cc index 100f72a..0551d10 100644 --- a/components/viz/service/input/android_state_transfer_handler.cc +++ b/components/viz/service/input/android_state_transfer_handler.cc
@@ -51,19 +51,12 @@ EmitPendingTransfersHistogram(); - // TODO(crbug.com/383323530): Convert it to CHECK once we are using - // AssociatedRemotes for passing state from Browser to Viz. const bool state_received_out_of_order = (!pending_transferred_states_.empty() && (state->down_time_ms < pending_transferred_states_.back().transfer_state->down_time_ms)); - if (state_received_out_of_order) { - TRACE_EVENT_INSTANT("viz", "OutOfOrderTransferStateDropped"); - // Drop out of order state received. - // It is possible since the state transfers coming from different web - // contents come over different mojo pipes. - return; - } + + CHECK(!state_received_out_of_order); MaybeDropEventsFromEarlierSequences(state);
diff --git a/components/viz/service/input/input_manager.cc b/components/viz/service/input/input_manager.cc index 37c5b36..e057482 100644 --- a/components/viz/service/input/input_manager.cc +++ b/components/viz/service/input/input_manager.cc
@@ -213,7 +213,7 @@ // |rir_delegate| should outlive |render_input_router|. auto rir_delegate = std::make_unique<RenderInputRouterDelegateImpl>( - it->second, *this, frame_sink_id, grouping_id); + it->second, *this, frame_sink_id); // Sets up RenderInputRouter. auto render_input_router = std::make_unique<input::RenderInputRouter>( @@ -446,46 +446,13 @@ return std::move(rirs); } -void InputManager::NotifyObserversOfInputEvent( - const FrameSinkId& frame_sink_id, - const base::UnguessableToken& grouping_id, - std::unique_ptr<blink::WebCoalescedInputEvent> event, - bool dispatched_to_renderer) { - rir_delegate_remote_map_.at(grouping_id) - ->NotifyObserversOfInputEvent(frame_sink_id, std::move(event), - dispatched_to_renderer); -} - -void InputManager::NotifyObserversOfInputEventAcks( - const FrameSinkId& frame_sink_id, - const base::UnguessableToken& grouping_id, - blink::mojom::InputEventResultSource ack_source, - blink::mojom::InputEventResultState ack_result, - std::unique_ptr<blink::WebCoalescedInputEvent> event) { - rir_delegate_remote_map_.at(grouping_id) - ->NotifyObserversOfInputEventAcks(frame_sink_id, ack_source, ack_result, - std::move(event)); -} - -void InputManager::OnInvalidInputEventSource( - const FrameSinkId& frame_sink_id, - const base::UnguessableToken& grouping_id) { - rir_delegate_remote_map_.at(grouping_id) - ->OnInvalidInputEventSource(frame_sink_id); -} - -void InputManager::RendererInputResponsivenessChanged( - const FrameSinkId& frame_sink_id, - const base::UnguessableToken& grouping_id, - bool is_responsive, - std::optional<base::TimeTicks> ack_timeout_ts) { - auto itr = rir_delegate_remote_map_.find(grouping_id); +input::mojom::RenderInputRouterDelegateClient* +InputManager::GetRIRDelegateClientRemote(const FrameSinkId& frame_sink_id) { + auto itr = rir_delegate_remote_map_.find(frame_sink_id); if (itr == rir_delegate_remote_map_.end()) { - return; + return nullptr; } - - itr->second->RendererInputResponsivenessChanged(frame_sink_id, is_responsive, - std::move(ack_timeout_ts)); + return itr->second.get(); } std::optional<bool> InputManager::IsDelegatedInkHovering( @@ -499,12 +466,6 @@ ->delegated_ink_metadata->is_hovering(); } -void InputManager::DidOverscroll(const FrameSinkId& frame_sink_id, - const base::UnguessableToken& grouping_id, - blink::mojom::DidOverscrollParamsPtr params) { - rir_delegate_remote_map_.at(grouping_id) - ->StateOnOverscrollTransfer(frame_sink_id, std::move(params)); -} void InputManager::StateOnTouchTransfer( input::mojom::TouchTransferStatePtr state) { @@ -554,12 +515,10 @@ void InputManager::ForceEnableZoomStateChanged( bool force_enable_zoom, - const std::vector<FrameSinkId>& frame_sink_ids) { - for (auto& frame_sink_id : frame_sink_ids) { - auto itr = rir_map_.find(frame_sink_id); - if (itr != rir_map_.end()) { - itr->second->SetForceEnableZoom(force_enable_zoom); - } + const FrameSinkId& frame_sink_id) { + auto itr = rir_map_.find(frame_sink_id); + if (itr != rir_map_.end()) { + itr->second->SetForceEnableZoom(force_enable_zoom); } } @@ -606,18 +565,23 @@ #endif } -void InputManager::SetupRenderInputRouterDelegateConnection( - const base::UnguessableToken& grouping_id, - mojo::PendingRemote<input::mojom::RenderInputRouterDelegateClient> - rir_delegate_remote, - mojo::PendingReceiver<input::mojom::RenderInputRouterDelegate> - rir_delegate_receiver) { - TRACE_EVENT("viz", "InputManager::SetupRenderInputRouterDelegateConnection"); +void InputManager::SetupRendererInputRouterDelegateRegistry( + mojo::PendingReceiver<mojom::RendererInputRouterDelegateRegistry> + receiver) { + TRACE_EVENT("viz", "InputManager::SetupRendererInputRouterDelegateRegistry"); + registry_receiver_.Bind(std::move(receiver)); +} - rir_delegate_remote_map_[grouping_id].Bind(std::move(rir_delegate_remote)); - rir_delegate_remote_map_[grouping_id].set_disconnect_handler( +void InputManager::SetupRenderInputRouterDelegateConnection( + const FrameSinkId& frame_sink_id, + mojo::PendingAssociatedRemote<input::mojom::RenderInputRouterDelegateClient> + rir_delegate_remote, + mojo::PendingAssociatedReceiver<input::mojom::RenderInputRouterDelegate> + rir_delegate_receiver) { + rir_delegate_remote_map_[frame_sink_id].Bind(std::move(rir_delegate_remote)); + rir_delegate_remote_map_[frame_sink_id].set_disconnect_handler( base::BindOnce(&InputManager::OnRIRDelegateClientDisconnected, - base::Unretained(this), grouping_id)); + base::Unretained(this), frame_sink_id)); rir_delegate_receivers_.Add(this, std::move(rir_delegate_receiver)); } @@ -744,8 +708,8 @@ } void InputManager::OnRIRDelegateClientDisconnected( - const base::UnguessableToken& grouping_id) { - rir_delegate_remote_map_.erase(grouping_id); + const FrameSinkId& frame_sink_id) { + rir_delegate_remote_map_.erase(frame_sink_id); } #if BUILDFLAG(IS_ANDROID)
diff --git a/components/viz/service/input/input_manager.h b/components/viz/service/input/input_manager.h index 57849b6..67061a7 100644 --- a/components/viz/service/input/input_manager.h +++ b/components/viz/service/input/input_manager.h
@@ -20,7 +20,7 @@ #include "components/viz/service/input/render_input_router_delegate_impl.h" #include "components/viz/service/input/render_input_router_support_base.h" #include "gpu/ipc/common/surface_handle.h" -#include "mojo/public/cpp/bindings/receiver_set.h" +#include "mojo/public/cpp/bindings/associated_receiver_set.h" #if BUILDFLAG(IS_ANDROID) #include "components/input/android/input_receiver_data.h" @@ -62,7 +62,8 @@ #endif public RenderInputRouterSupportBase::Delegate, public RenderInputRouterDelegateImpl::Delegate, - public input::mojom::RenderInputRouterDelegate { + public input::mojom::RenderInputRouterDelegate, + public mojom::RendererInputRouterDelegateRegistry { public: explicit InputManager(FrameSinkManagerImpl* frame_sink_manager); @@ -115,37 +116,16 @@ // RenderInputRouterDelegateImpl::Delegate implementation. std::unique_ptr<input::RenderInputRouterIterator> GetEmbeddedRenderInputRouters(const FrameSinkId& id) override; - void NotifyObserversOfInputEvent( - const FrameSinkId& frame_sink_id, - const base::UnguessableToken& grouping_id, - std::unique_ptr<blink::WebCoalescedInputEvent> event, - bool dispatched_to_renderer) override; - void NotifyObserversOfInputEventAcks( - const FrameSinkId& frame_sink_id, - const base::UnguessableToken& grouping_id, - blink::mojom::InputEventResultSource ack_source, - blink::mojom::InputEventResultState ack_result, - std::unique_ptr<blink::WebCoalescedInputEvent> event) override; - void OnInvalidInputEventSource( - const FrameSinkId& frame_sink_id, - const base::UnguessableToken& grouping_id) override; - void RendererInputResponsivenessChanged( - const FrameSinkId& frame_sink_id, - const base::UnguessableToken& grouping_id, - bool is_responsive, - std::optional<base::TimeTicks> ack_timeout_ts) override; + input::mojom::RenderInputRouterDelegateClient* GetRIRDelegateClientRemote( + const FrameSinkId& frame_sink_id) override; std::optional<bool> IsDelegatedInkHovering( const FrameSinkId& frame_sink_id) override; - void DidOverscroll(const FrameSinkId& frame_sink_id, - const base::UnguessableToken& grouping_id, - blink::mojom::DidOverscrollParamsPtr params) override; GpuServiceImpl* GetGpuService() override; // input::mojom::RenderInputRouterDelegate implementation. void StateOnTouchTransfer(input::mojom::TouchTransferStatePtr state) override; - void ForceEnableZoomStateChanged( - bool force_enable_zoom, - const std::vector<FrameSinkId>& frame_sink_ids) override; + void ForceEnableZoomStateChanged(bool force_enable_zoom, + const FrameSinkId& frame_sink_id) override; void StopFlingingOnViz(const FrameSinkId& frame_sink_id) override; void RestartInputEventAckTimeoutIfNecessary( const FrameSinkId& frame_sink_id) override; @@ -154,12 +134,17 @@ void ResetGestureDetection( const FrameSinkId& root_widget_frame_sink_id) override; + // mojom::RendererInputRouterDelegateRegistry implementation. void SetupRenderInputRouterDelegateConnection( - const base::UnguessableToken& grouping_id, - mojo::PendingRemote<input::mojom::RenderInputRouterDelegateClient> - rir_delegate_client_remote, - mojo::PendingReceiver<input::mojom::RenderInputRouterDelegate> - rir_delegate_receiver); + const FrameSinkId& frame_sink_id, + mojo::PendingAssociatedRemote< + input::mojom::RenderInputRouterDelegateClient> rir_delegate_remote, + mojo::PendingAssociatedReceiver<input::mojom::RenderInputRouterDelegate> + rir_delegate_receiver) override; + + void SetupRendererInputRouterDelegateRegistry( + mojo::PendingReceiver<mojom::RendererInputRouterDelegateRegistry> + receiver); void NotifyRendererBlockStateChanged(bool blocked, const std::vector<FrameSinkId>& rirs); @@ -187,8 +172,7 @@ input::RenderInputRouter* rir, const FrameSinkId& frame_sink_id); - void OnRIRDelegateClientDisconnected( - const base::UnguessableToken& grouping_id); + void OnRIRDelegateClientDisconnected(const FrameSinkId& frame_sink_id); void SetupRenderInputRouter( input::RenderInputRouter* render_input_router, @@ -234,14 +218,19 @@ base::flat_map<FrameSinkId, std::unique_ptr<input::RenderInputRouter>> rir_map_; + mojo::Receiver<mojom::RendererInputRouterDelegateRegistry> registry_receiver_{ + this}; + // Keeps track of RIRDelegateClient connections, which are between - // WebContentsImpl (in the Browser) and InputManager (in Viz) using a - // CompositorFrameSink grouping_id sent from the browser. This interface is - // used by Viz to update browser's state of input event handling in Viz. - base::flat_map</*grouping_id=*/base::UnguessableToken, - mojo::Remote<input::mojom::RenderInputRouterDelegateClient>> + // RenderWidgetHosts (in the Browser) and InputManager (in Viz) using the + // FrameSinkId associated with the RenderWidgetHost sent from the browser. + // This interface is used by Viz to update browser's state of input event + // handling in Viz. + base::flat_map< + FrameSinkId, + mojo::AssociatedRemote<input::mojom::RenderInputRouterDelegateClient>> rir_delegate_remote_map_; - mojo::ReceiverSet<input::mojom::RenderInputRouterDelegate> + mojo::AssociatedReceiverSet<input::mojom::RenderInputRouterDelegate> rir_delegate_receivers_; raw_ptr<FrameSinkManagerImpl> frame_sink_manager_;
diff --git a/components/viz/service/input/render_input_router_delegate_impl.cc b/components/viz/service/input/render_input_router_delegate_impl.cc index 05fa958..5b008f24 100644 --- a/components/viz/service/input/render_input_router_delegate_impl.cc +++ b/components/viz/service/input/render_input_router_delegate_impl.cc
@@ -28,12 +28,10 @@ RenderInputRouterDelegateImpl::RenderInputRouterDelegateImpl( scoped_refptr<input::RenderWidgetHostInputEventRouter> rwhier, Delegate& delegate, - const FrameSinkId& frame_sink_id, - const base::UnguessableToken& grouping_id) + const FrameSinkId& frame_sink_id) : rwhier_(std::move(rwhier)), delegate_(delegate), - frame_sink_id_(frame_sink_id), - grouping_id_(grouping_id) { + frame_sink_id_(frame_sink_id) { TRACE_EVENT_INSTANT( "input", "RenderInputRouterDelegateImpl::RenderInputRouterDelegateImpl", "frame_sink_id", frame_sink_id); @@ -93,9 +91,9 @@ auto web_coalesced_event = std::make_unique<blink::WebCoalescedInputEvent>(event, ui::LatencyInfo()); - delegate_->NotifyObserversOfInputEvent(frame_sink_id_, grouping_id_, - std::move(web_coalesced_event), - dispatched_to_renderer); + delegate_->GetRIRDelegateClientRemote(frame_sink_id_) + ->NotifyObserversOfInputEvent(std::move(web_coalesced_event), + dispatched_to_renderer); } void RenderInputRouterDelegateImpl::NotifyObserversOfInputEventAcks( @@ -108,9 +106,9 @@ auto web_coalesced_event = std::make_unique<blink::WebCoalescedInputEvent>(event, ui::LatencyInfo()); - delegate_->NotifyObserversOfInputEventAcks(frame_sink_id_, grouping_id_, - ack_source, ack_result, - std::move(web_coalesced_event)); + delegate_->GetRIRDelegateClientRemote(frame_sink_id_) + ->NotifyObserversOfInputEventAcks(ack_source, ack_result, + std::move(web_coalesced_event)); } bool RenderInputRouterDelegateImpl::IsInitializedAndNotDead() { @@ -127,7 +125,8 @@ } void RenderInputRouterDelegateImpl::OnInvalidInputEventSource() { - delegate_->OnInvalidInputEventSource(frame_sink_id_, grouping_id_); + delegate_->GetRIRDelegateClientRemote(frame_sink_id_) + ->OnInvalidInputEventSource(); } std::unique_ptr<PeakGpuMemoryTracker> @@ -152,8 +151,12 @@ return; } is_responsive_ = false; - delegate_->RendererInputResponsivenessChanged( - frame_sink_id_, grouping_id_, is_responsive_, std::move(ack_timeout_ts)); + auto* remote = delegate_->GetRIRDelegateClientRemote(frame_sink_id_); + if (!remote) { + return; + } + remote->RendererInputResponsivenessChanged(is_responsive_, + std::move(ack_timeout_ts)); } void RenderInputRouterDelegateImpl::RendererIsResponsive() { @@ -161,8 +164,11 @@ return; } is_responsive_ = true; - delegate_->RendererInputResponsivenessChanged(frame_sink_id_, grouping_id_, - is_responsive_, std::nullopt); + auto* remote = delegate_->GetRIRDelegateClientRemote(frame_sink_id_); + if (!remote) { + return; + } + remote->RendererInputResponsivenessChanged(is_responsive_, std::nullopt); } void RenderInputRouterDelegateImpl::DidOverscroll( @@ -173,7 +179,8 @@ // |RenderInputRouterSupportAndroid::GestureEventAck| which calls in // StopFlingingIfNecessary, so the decision to stop any fling due to // overscroll is handled within the Viz process. - delegate_->DidOverscroll(frame_sink_id_, grouping_id_, std::move(params)); + delegate_->GetRIRDelegateClientRemote(frame_sink_id_) + ->StateOnOverscrollTransfer(std::move(params)); } } // namespace viz
diff --git a/components/viz/service/input/render_input_router_delegate_impl.h b/components/viz/service/input/render_input_router_delegate_impl.h index 8ce42ae..4b576ee 100644 --- a/components/viz/service/input/render_input_router_delegate_impl.h +++ b/components/viz/service/input/render_input_router_delegate_impl.h
@@ -9,12 +9,12 @@ #include "base/memory/scoped_refptr.h" #include "components/input/event_with_latency_info.h" +#include "components/input/render_input_router.mojom.h" #include "components/input/render_input_router_delegate.h" #include "components/input/render_input_router_iterator.h" #include "components/viz/common/resources/peak_gpu_memory_tracker.h" #include "components/viz/common/surfaces/frame_sink_id.h" #include "components/viz/service/viz_service_export.h" -#include "third_party/blink/public/common/input/web_coalesced_input_event.h" namespace input { class RenderWidgetHostViewInput; @@ -36,38 +36,17 @@ public: virtual std::unique_ptr<input::RenderInputRouterIterator> GetEmbeddedRenderInputRouters(const FrameSinkId& id) = 0; - virtual void NotifyObserversOfInputEvent( - const FrameSinkId& frame_sink_id, - const base::UnguessableToken& grouping_id, - std::unique_ptr<blink::WebCoalescedInputEvent> event, - bool dispatched_to_renderer) = 0; - virtual void NotifyObserversOfInputEventAcks( - const FrameSinkId& frame_sink_id, - const base::UnguessableToken& grouping_id, - blink::mojom::InputEventResultSource ack_source, - blink::mojom::InputEventResultState ack_result, - std::unique_ptr<blink::WebCoalescedInputEvent> event) = 0; - virtual void OnInvalidInputEventSource( - const FrameSinkId& frame_sink_id, - const base::UnguessableToken& grouping_id) = 0; - virtual void RendererInputResponsivenessChanged( - const FrameSinkId& frame_sink_id, - const base::UnguessableToken& grouping_id, - bool is_responsive, - std::optional<base::TimeTicks> ack_timeout_ts) = 0; + virtual input::mojom::RenderInputRouterDelegateClient* + GetRIRDelegateClientRemote(const FrameSinkId& frame_sink_id) = 0; virtual std::optional<bool> IsDelegatedInkHovering( const FrameSinkId& frame_sink_id) = 0; - virtual void DidOverscroll(const FrameSinkId& frame_sink_id, - const base::UnguessableToken& grouping_id, - blink::mojom::DidOverscrollParamsPtr params) = 0; virtual GpuServiceImpl* GetGpuService() = 0; }; RenderInputRouterDelegateImpl( scoped_refptr<input::RenderWidgetHostInputEventRouter> rwhier, Delegate& delegate, - const FrameSinkId& frame_sink_id, - const base::UnguessableToken& grouping_id); + const FrameSinkId& frame_sink_id); ~RenderInputRouterDelegateImpl() override; @@ -117,7 +96,6 @@ scoped_refptr<input::RenderWidgetHostInputEventRouter> rwhier_; raw_ref<Delegate> delegate_; const FrameSinkId frame_sink_id_; - const base::UnguessableToken grouping_id_; }; } // namespace viz
diff --git a/components/viz/test/test_frame_sink_manager.h b/components/viz/test/test_frame_sink_manager.h index d3700d5..df110e53 100644 --- a/components/viz/test/test_frame_sink_manager.h +++ b/components/viz/test/test_frame_sink_manager.h
@@ -91,12 +91,9 @@ void EnableFrameSinkManagerTestApi( mojo::PendingReceiver<mojom::FrameSinkManagerTestApi> receiver) override { } - void SetupRenderInputRouterDelegateConnection( - const base::UnguessableToken& grouping_id, - mojo::PendingRemote<input::mojom::RenderInputRouterDelegateClient> - rir_delegate_client_remote, - mojo::PendingReceiver<input::mojom::RenderInputRouterDelegate> - rir_delegate_receiver) override {} + void SetupRendererInputRouterDelegateRegistry( + mojo::PendingReceiver<mojom::RendererInputRouterDelegateRegistry> + receiver) override {} void NotifyRendererBlockStateChanged( bool blocked, const std::vector<FrameSinkId>& render_input_routers) override {}
diff --git a/components/webapps/isolated_web_apps/iwa_key_distribution_info_provider.cc b/components/webapps/isolated_web_apps/iwa_key_distribution_info_provider.cc index 8a973b2..8426108 100644 --- a/components/webapps/isolated_web_apps/iwa_key_distribution_info_provider.cc +++ b/components/webapps/isolated_web_apps/iwa_key_distribution_info_provider.cc
@@ -201,7 +201,9 @@ } void IwaKeyDistributionInfoProvider::SetUp( + bool is_on_demand_supported, QueueOnDemandUpdateCallback callback) { + is_on_demand_supported_ = is_on_demand_supported; queue_on_demand_update_ = callback; } @@ -299,7 +301,7 @@ base::OneShotEvent& IwaKeyDistributionInfoProvider::OnMaybeDownloadedComponentDataReady() { - if (!queue_on_demand_update_) { + if (!is_on_demand_supported_) { return AlreadySignalled(); } @@ -408,6 +410,7 @@ void IwaKeyDistributionInfoProvider::MaybeQueueComponentUpdate() { CHECK(maybe_queue_component_update_posted_); CHECK(any_data_ready_.is_signaled()); + CHECK(is_on_demand_supported_); CHECK(queue_on_demand_update_); if (!data_ || data_->is_preloaded) {
diff --git a/components/webapps/isolated_web_apps/iwa_key_distribution_info_provider.h b/components/webapps/isolated_web_apps/iwa_key_distribution_info_provider.h index 7fe3246..459c4aa 100644 --- a/components/webapps/isolated_web_apps/iwa_key_distribution_info_provider.h +++ b/components/webapps/isolated_web_apps/iwa_key_distribution_info_provider.h
@@ -111,7 +111,7 @@ // Sets up the `IwaKeyDistributionInfoProvider`, i.e. adds the capability to // schedule on demand callbacks. - void SetUp(QueueOnDemandUpdateCallback callback); + void SetUp(bool is_on_demand_supported, QueueOnDemandUpdateCallback callback); // Asynchronously loads new component data and replaces the current `data_` // upon success and if `component_version` is greater than the stored one, and @@ -188,6 +188,7 @@ base::OneShotEvent maybe_downloaded_data_ready_; bool maybe_queue_component_update_posted_ = false; + bool is_on_demand_supported_ = false; QueueOnDemandUpdateCallback queue_on_demand_update_;
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 933abcca..6d414af 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -1902,6 +1902,8 @@ "renderer_host/mixed_content_checker.h", "renderer_host/mixed_content_navigation_throttle.cc", "renderer_host/mixed_content_navigation_throttle.h", + "renderer_host/mojo_render_input_router_delegate_impl.cc", + "renderer_host/mojo_render_input_router_delegate_impl.h", "renderer_host/navigation_controller_delegate.h", "renderer_host/navigation_controller_impl.cc", "renderer_host/navigation_controller_impl.h",
diff --git a/content/browser/devtools/protocol/storage_handler.cc b/content/browser/devtools/protocol/storage_handler.cc index 563ef15..6127e1a 100644 --- a/content/browser/devtools/protocol/storage_handler.cc +++ b/content/browser/devtools/protocol/storage_handler.cc
@@ -1667,7 +1667,6 @@ SharedStorageRuntimeManager::SharedStorageObserverInterface::AccessMethod method, int operation_id, - int worklet_ordinal_id, const base::UnguessableToken& worklet_devtools_token, GlobalRenderFrameHostId main_frame_id, const std::string& owner_origin) {
diff --git a/content/browser/devtools/protocol/storage_handler.h b/content/browser/devtools/protocol/storage_handler.h index d428463..0b98bef 100644 --- a/content/browser/devtools/protocol/storage_handler.h +++ b/content/browser/devtools/protocol/storage_handler.h
@@ -242,7 +242,6 @@ SharedStorageRuntimeManager::SharedStorageObserverInterface::AccessMethod method, int operation_id, - int worklet_ordinal_id, const base::UnguessableToken& worklet_devtools_token, GlobalRenderFrameHostId main_frame_id, const std::string& owner_origin) override;
diff --git a/content/browser/picture_in_picture/document_picture_in_picture_navigation_throttle.cc b/content/browser/picture_in_picture/document_picture_in_picture_navigation_throttle.cc index 1a194290..87189a8 100644 --- a/content/browser/picture_in_picture/document_picture_in_picture_navigation_throttle.cc +++ b/content/browser/picture_in_picture/document_picture_in_picture_navigation_throttle.cc
@@ -14,30 +14,32 @@ namespace content { // static -std::unique_ptr<DocumentPictureInPictureNavigationThrottle> -DocumentPictureInPictureNavigationThrottle::MaybeCreateThrottleFor( - NavigationHandle* handle) { +void DocumentPictureInPictureNavigationThrottle::MaybeCreateAndAdd( + NavigationThrottleRegistry& registry) { // We prevent the main frame of document picture-in-picture windows from doing // cross-document navigation. - if (!handle->IsInMainFrame() || handle->IsSameDocument() || - !handle->GetWebContents() || - !handle->GetWebContents()->GetPictureInPictureOptions().has_value()) { - return nullptr; + NavigationHandle& handle = registry.GetNavigationHandle(); + if (!handle.IsInMainFrame() || handle.IsSameDocument() || + !handle.GetWebContents() || + !handle.GetWebContents()->GetPictureInPictureOptions().has_value()) { + return; } // Allow a command-line flag to opt-out of navigation throttling. if (base::FeatureList::IsEnabled( media::kDocumentPictureInPictureNavigation)) { - return nullptr; + return; } - return std::make_unique<DocumentPictureInPictureNavigationThrottle>( - base::PassKey<DocumentPictureInPictureNavigationThrottle>(), handle); + registry.AddThrottle( + std::make_unique<DocumentPictureInPictureNavigationThrottle>( + base::PassKey<DocumentPictureInPictureNavigationThrottle>(), + registry)); } DocumentPictureInPictureNavigationThrottle:: DocumentPictureInPictureNavigationThrottle( base::PassKey<DocumentPictureInPictureNavigationThrottle>, - NavigationHandle* handle) - : NavigationThrottle(handle) {} + NavigationThrottleRegistry& registry) + : NavigationThrottle(registry) {} DocumentPictureInPictureNavigationThrottle:: ~DocumentPictureInPictureNavigationThrottle() = default;
diff --git a/content/browser/picture_in_picture/document_picture_in_picture_navigation_throttle.h b/content/browser/picture_in_picture/document_picture_in_picture_navigation_throttle.h index 481b42289..9813a54 100644 --- a/content/browser/picture_in_picture/document_picture_in_picture_navigation_throttle.h +++ b/content/browser/picture_in_picture/document_picture_in_picture_navigation_throttle.h
@@ -5,8 +5,6 @@ #ifndef CONTENT_BROWSER_PICTURE_IN_PICTURE_DOCUMENT_PICTURE_IN_PICTURE_NAVIGATION_THROTTLE_H_ #define CONTENT_BROWSER_PICTURE_IN_PICTURE_DOCUMENT_PICTURE_IN_PICTURE_NAVIGATION_THROTTLE_H_ -#include <memory> - #include "base/types/pass_key.h" #include "content/public/browser/navigation_throttle.h" @@ -17,12 +15,11 @@ // to navigate. class DocumentPictureInPictureNavigationThrottle : public NavigationThrottle { public: - static std::unique_ptr<DocumentPictureInPictureNavigationThrottle> - MaybeCreateThrottleFor(NavigationHandle* handle); + static void MaybeCreateAndAdd(NavigationThrottleRegistry& registry); DocumentPictureInPictureNavigationThrottle( base::PassKey<DocumentPictureInPictureNavigationThrottle>, - NavigationHandle* handle); + NavigationThrottleRegistry& registry); DocumentPictureInPictureNavigationThrottle( const DocumentPictureInPictureNavigationThrottle&) = delete; DocumentPictureInPictureNavigationThrottle& operator=(
diff --git a/content/browser/preloading/prefetch/contamination_delay_navigation_throttle.cc b/content/browser/preloading/prefetch/contamination_delay_navigation_throttle.cc index 8cd0997..b3033a7 100644 --- a/content/browser/preloading/prefetch/contamination_delay_navigation_throttle.cc +++ b/content/browser/preloading/prefetch/contamination_delay_navigation_throttle.cc
@@ -4,11 +4,22 @@ #include "content/browser/preloading/prefetch/contamination_delay_navigation_throttle.h" +#include "content/browser/preloading/prefetch/prefetch_features.h" #include "content/browser/renderer_host/navigation_request.h" #include "content/public/browser/navigation_handle.h" namespace content { +// static +void ContaminationDelayNavigationThrottle::MaybeCreateAndAdd( + NavigationThrottleRegistry& registry) { + if (base::FeatureList::IsEnabled( + features::kPrefetchStateContaminationMitigation)) { + registry.AddThrottle( + std::make_unique<ContaminationDelayNavigationThrottle>(registry)); + } +} + ContaminationDelayNavigationThrottle::~ContaminationDelayNavigationThrottle() = default;
diff --git a/content/browser/preloading/prefetch/contamination_delay_navigation_throttle.h b/content/browser/preloading/prefetch/contamination_delay_navigation_throttle.h index 18daab8..999b7e2 100644 --- a/content/browser/preloading/prefetch/contamination_delay_navigation_throttle.h +++ b/content/browser/preloading/prefetch/contamination_delay_navigation_throttle.h
@@ -15,6 +15,8 @@ // commit would otherwise reveal information about those checks. class ContaminationDelayNavigationThrottle : public NavigationThrottle { public: + static void MaybeCreateAndAdd(NavigationThrottleRegistry& registry); + using NavigationThrottle::NavigationThrottle; ~ContaminationDelayNavigationThrottle() override;
diff --git a/content/browser/preloading/prerender/prerender_navigation_throttle.cc b/content/browser/preloading/prerender/prerender_navigation_throttle.cc index 67a8e23..172ff2a 100644 --- a/content/browser/preloading/prerender/prerender_navigation_throttle.cc +++ b/content/browser/preloading/prerender/prerender_navigation_throttle.cc
@@ -58,21 +58,20 @@ } // namespace -PrerenderNavigationThrottle::~PrerenderNavigationThrottle() = default; - // static -std::unique_ptr<PrerenderNavigationThrottle> -PrerenderNavigationThrottle::MaybeCreateThrottleFor( - NavigationHandle* navigation_handle) { - auto* navigation_request = NavigationRequest::From(navigation_handle); +void PrerenderNavigationThrottle::MaybeCreateAndAdd( + NavigationThrottleRegistry& registry) { + auto* navigation_request = + NavigationRequest::From(®istry.GetNavigationHandle()); FrameTreeNode* frame_tree_node = navigation_request->frame_tree_node(); if (frame_tree_node->GetFrameType() == FrameType::kPrerenderMainFrame) { - return base::WrapUnique( - new PrerenderNavigationThrottle(navigation_request)); + registry.AddThrottle( + base::WrapUnique(new PrerenderNavigationThrottle(registry))); } - return nullptr; } +PrerenderNavigationThrottle::~PrerenderNavigationThrottle() = default; + const char* PrerenderNavigationThrottle::GetNameForLogging() { return "PrerenderNavigationThrottle"; } @@ -88,10 +87,13 @@ } PrerenderNavigationThrottle::PrerenderNavigationThrottle( - NavigationRequest* navigation_request) - : NavigationThrottle(navigation_request), + NavigationThrottleRegistry& registry) + : NavigationThrottle(registry), prerender_host_(static_cast<PrerenderHost*>( - navigation_request->frame_tree_node()->frame_tree().delegate())) { + NavigationRequest::From(®istry.GetNavigationHandle()) + ->frame_tree_node() + ->frame_tree() + .delegate())) { CHECK(prerender_host_); // This throttle is responsible for setting the initial navigation id on the @@ -102,7 +104,8 @@ // will later cancel the navigation in Will*Request(). Just do nothing // until then. } else { - prerender_host_->SetInitialNavigation(navigation_request); + prerender_host_->SetInitialNavigation( + NavigationRequest::From(®istry.GetNavigationHandle())); } }
diff --git a/content/browser/preloading/prerender/prerender_navigation_throttle.h b/content/browser/preloading/prerender/prerender_navigation_throttle.h index 09805eed..83e13ea 100644 --- a/content/browser/preloading/prerender/prerender_navigation_throttle.h +++ b/content/browser/preloading/prerender/prerender_navigation_throttle.h
@@ -9,7 +9,6 @@ namespace content { -class NavigationRequest; class PrerenderHost; enum class PrerenderFinalStatus; @@ -22,10 +21,9 @@ // - Cross-origin navigation from a prerendered page class PrerenderNavigationThrottle : public NavigationThrottle { public: - ~PrerenderNavigationThrottle() override; + static void MaybeCreateAndAdd(NavigationThrottleRegistry& registry); - static std::unique_ptr<PrerenderNavigationThrottle> MaybeCreateThrottleFor( - NavigationHandle* navigation_handle); + ~PrerenderNavigationThrottle() override; // NavigationThrottle const char* GetNameForLogging() override; @@ -34,7 +32,7 @@ ThrottleCheckResult WillProcessResponse() override; private: - explicit PrerenderNavigationThrottle(NavigationRequest* navigation_request); + explicit PrerenderNavigationThrottle(NavigationThrottleRegistry& registry); ThrottleCheckResult WillStartOrRedirectRequest(bool is_redirection);
diff --git a/content/browser/preloading/prerender/prerender_subframe_navigation_throttle.cc b/content/browser/preloading/prerender/prerender_subframe_navigation_throttle.cc index c8501d8c..47ff78f 100644 --- a/content/browser/preloading/prerender/prerender_subframe_navigation_throttle.cc +++ b/content/browser/preloading/prerender/prerender_subframe_navigation_throttle.cc
@@ -17,28 +17,29 @@ namespace content { // static -std::unique_ptr<PrerenderSubframeNavigationThrottle> -PrerenderSubframeNavigationThrottle::MaybeCreateThrottleFor( - NavigationHandle* navigation_handle) { - auto* navigation_request = NavigationRequest::From(navigation_handle); +void PrerenderSubframeNavigationThrottle::MaybeCreateAndAdd( + NavigationThrottleRegistry& registry) { + auto* navigation_request = + NavigationRequest::From(®istry.GetNavigationHandle()); FrameTreeNode* frame_tree_node = navigation_request->frame_tree_node(); if (frame_tree_node->IsMainFrame() || !frame_tree_node->frame_tree().is_prerendering()) { - return nullptr; + return; } - return base::WrapUnique( - new PrerenderSubframeNavigationThrottle(navigation_handle)); + registry.AddThrottle( + base::WrapUnique(new PrerenderSubframeNavigationThrottle(registry))); } PrerenderSubframeNavigationThrottle::PrerenderSubframeNavigationThrottle( - NavigationHandle* nav_handle) - : NavigationThrottle(nav_handle), - prerender_root_ftn_id_(NavigationRequest::From(nav_handle) - ->frame_tree_node() - ->frame_tree() - .root() - ->frame_tree_node_id()) {} + NavigationThrottleRegistry& registry) + : NavigationThrottle(registry), + prerender_root_ftn_id_( + NavigationRequest::From(®istry.GetNavigationHandle()) + ->frame_tree_node() + ->frame_tree() + .root() + ->frame_tree_node_id()) {} PrerenderSubframeNavigationThrottle::~PrerenderSubframeNavigationThrottle() = default; @@ -61,8 +62,9 @@ PrerenderSubframeNavigationThrottle::WillProcessResponse() { auto* navigation_request = NavigationRequest::From(navigation_handle()); FrameTreeNode* frame_tree_node = navigation_request->frame_tree_node(); - if (!frame_tree_node->frame_tree().is_prerendering()) + if (!frame_tree_node->frame_tree().is_prerendering()) { return NavigationThrottle::PROCEED; + } // TODO(crbug.com/40222993): Delay until activation instead of cancellation. if (navigation_handle()->IsDownload()) { @@ -80,8 +82,9 @@ // Don't run cross-origin subframe navigation check for non-renderable // contents like 204/205 as their GetOriginToCommit() is invalid. In this // case, we can safely proceed with navigation without deferring it. - if (!navigation_request->response_should_be_rendered()) + if (!navigation_request->response_should_be_rendered()) { return PROCEED; + } // Defer cross-origin subframe navigation until page activation. The check is // added here, because this is the first place that the throttle can properly @@ -123,8 +126,9 @@ // prerendering frame tree that this subframe navigation started in. auto* finished_navigation = NavigationRequest::From(nav_handle); if (finished_navigation->prerender_frame_tree_node_id() != - prerender_root_ftn_id_) + prerender_root_ftn_id_) { return; + } // The activation is finished. There is no need to listen to the WebContents // anymore. @@ -133,12 +137,14 @@ // If the finished navigation did not commit, do not Resume(). We expect that // the prerendered page and therefore the subframe navigation will eventually // be cancelled. - if (!finished_navigation->HasCommitted()) + if (!finished_navigation->HasCommitted()) { return; + } // Resume the subframe navigation. - if (!is_deferred_) + if (!is_deferred_) { return; + } is_deferred_ = false; Resume(); // Resume() may have deleted `this`. @@ -197,8 +203,9 @@ CHECK(!frame_tree_node->IsMainFrame()); // Proceed if the page isn't in the prerendering state. - if (!frame_tree_node->frame_tree().is_prerendering()) + if (!frame_tree_node->frame_tree().is_prerendering()) { return NavigationThrottle::PROCEED; + } // Defer cross-origin subframe navigation until page activation. // Using url::Origin::Create() to check same-origin might not be @@ -212,8 +219,9 @@ // through the NavigationThrottle, so it's not a problem here RenderFrameHostImpl* rfhi = frame_tree_node->frame_tree().GetMainFrame(); const url::Origin& main_origin = rfhi->GetLastCommittedOrigin(); - if (!main_origin.IsSameOriginWith(navigation_handle()->GetURL())) + if (!main_origin.IsSameOriginWith(navigation_handle()->GetURL())) { return DeferOrCancelCrossOriginSubframeNavigation(*frame_tree_node); + } return NavigationThrottle::PROCEED; }
diff --git a/content/browser/preloading/prerender/prerender_subframe_navigation_throttle.h b/content/browser/preloading/prerender/prerender_subframe_navigation_throttle.h index 2ade680..9e08e02 100644 --- a/content/browser/preloading/prerender/prerender_subframe_navigation_throttle.h +++ b/content/browser/preloading/prerender/prerender_subframe_navigation_throttle.h
@@ -23,12 +23,11 @@ public: ~PrerenderSubframeNavigationThrottle() override; - static std::unique_ptr<PrerenderSubframeNavigationThrottle> - MaybeCreateThrottleFor(NavigationHandle* navigation_handle); + static void MaybeCreateAndAdd(NavigationThrottleRegistry& registry); private: explicit PrerenderSubframeNavigationThrottle( - NavigationHandle* navigation_handle); + NavigationThrottleRegistry& registry); // NavigationThrottle const char* GetNameForLogging() override;
diff --git a/content/browser/renderer_host/ancestor_throttle.cc b/content/browser/renderer_host/ancestor_throttle.cc index 861a31a..b8da850 100644 --- a/content/browser/renderer_host/ancestor_throttle.cc +++ b/content/browser/renderer_host/ancestor_throttle.cc
@@ -94,11 +94,10 @@ } // namespace // static -std::unique_ptr<NavigationThrottle> AncestorThrottle::MaybeCreateThrottleFor( - NavigationHandle* handle) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); +void AncestorThrottle::CreateAndAdd(NavigationThrottleRegistry& registry) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); - return base::WrapUnique(new AncestorThrottle(handle)); + registry.AddThrottle(base::WrapUnique(new AncestorThrottle(registry))); } AncestorThrottle::~AncestorThrottle() {} @@ -164,8 +163,8 @@ return "AncestorThrottle"; } -AncestorThrottle::AncestorThrottle(NavigationHandle* handle) - : NavigationThrottle(handle) {} +AncestorThrottle::AncestorThrottle(NavigationThrottleRegistry& registry) + : NavigationThrottle(registry) {} void AncestorThrottle::ParseXFrameOptionsError( const net::HttpResponseHeaders* headers,
diff --git a/content/browser/renderer_host/ancestor_throttle.h b/content/browser/renderer_host/ancestor_throttle.h index bf4aaee..de03d39 100644 --- a/content/browser/renderer_host/ancestor_throttle.h +++ b/content/browser/renderer_host/ancestor_throttle.h
@@ -20,14 +20,12 @@ } namespace content { -class NavigationHandle; // An AncestorThrottle is responsible for enforcing a resource's embedding // rules, and blocking requests which violate them. class CONTENT_EXPORT AncestorThrottle : public NavigationThrottle { public: - static std::unique_ptr<NavigationThrottle> MaybeCreateThrottleFor( - NavigationHandle* handle); + static void CreateAndAdd(NavigationThrottleRegistry& registry); AncestorThrottle(const AncestorThrottle&) = delete; AncestorThrottle& operator=(const AncestorThrottle&) = delete; @@ -47,7 +45,7 @@ FRIEND_TEST_ALL_PREFIXES(AncestorThrottleTest, IgnoreWhenFrameAncestorsPresent); - explicit AncestorThrottle(NavigationHandle* handle); + explicit AncestorThrottle(NavigationThrottleRegistry& registry); NavigationThrottle::ThrottleCheckResult ProcessResponseImpl( LoggingDisposition logging, bool is_response_check);
diff --git a/content/browser/renderer_host/blocked_scheme_navigation_throttle.cc b/content/browser/renderer_host/blocked_scheme_navigation_throttle.cc index 58ab425..810f4900 100644 --- a/content/browser/renderer_host/blocked_scheme_navigation_throttle.cc +++ b/content/browser/renderer_host/blocked_scheme_navigation_throttle.cc
@@ -32,22 +32,24 @@ url, blink::StorageKey::CreateFirstParty(url::Origin::Create(url))); return file_system_url.is_valid(); } -} +} // namespace BlockedSchemeNavigationThrottle::BlockedSchemeNavigationThrottle( - NavigationHandle* navigation_handle) - : NavigationThrottle(navigation_handle) {} + NavigationThrottleRegistry& registry) + : NavigationThrottle(registry) {} BlockedSchemeNavigationThrottle::~BlockedSchemeNavigationThrottle() {} NavigationThrottle::ThrottleCheckResult BlockedSchemeNavigationThrottle::WillStartRequest() { NavigationRequest* request = NavigationRequest::From(navigation_handle()); - if (!request->GetURL().SchemeIs(url::kFileSystemScheme)) + if (!request->GetURL().SchemeIs(url::kFileSystemScheme)) { return PROCEED; + } - if (base::FeatureList::IsEnabled(blink::features::kFileSystemUrlNavigation)) + if (base::FeatureList::IsEnabled(blink::features::kFileSystemUrlNavigation)) { return PROCEED; + } RenderFrameHost* top_frame = request->frame_tree_node()->frame_tree().root()->current_frame_host(); @@ -75,8 +77,9 @@ NavigationThrottle::ThrottleCheckResult BlockedSchemeNavigationThrottle::WillProcessResponse() { NavigationRequest* request = NavigationRequest::From(navigation_handle()); - if (request->IsDownload()) + if (request->IsDownload()) { return PROCEED; + } RenderFrameHost* top_frame = request->frame_tree_node()->frame_tree().root()->current_frame_host(); @@ -92,30 +95,29 @@ } // static -std::unique_ptr<NavigationThrottle> -BlockedSchemeNavigationThrottle::CreateThrottleForNavigation( - NavigationHandle* navigation_handle) { - NavigationRequest* request = NavigationRequest::From(navigation_handle); +void BlockedSchemeNavigationThrottle::MaybeCreateAndAdd( + NavigationThrottleRegistry& registry) { + NavigationHandle& handle = registry.GetNavigationHandle(); // Create throttles when going to blocked schemes via renderer-initiated // navigations (which are cross-document in the main frame). Note that history // navigations can bypass this, because the blocked scheme must have // originally committed in a permitted case (e.g., omnibox navigation). - if (request->IsInMainFrame() && request->IsRendererInitiated() && - !request->IsSameDocument() && - !NavigationTypeUtils::IsHistory( - request->common_params().navigation_type) && - (request->GetURL().SchemeIs(url::kDataScheme) || - request->GetURL().SchemeIs(url::kFileSystemScheme)) && + if (handle.IsInMainFrame() && handle.IsRendererInitiated() && + !handle.IsSameDocument() && !handle.IsHistory() && + (handle.GetURL().SchemeIs(url::kDataScheme) || + handle.GetURL().SchemeIs(url::kFileSystemScheme)) && !base::FeatureList::IsEnabled( features::kAllowContentInitiatedDataUrlNavigations)) { - return std::make_unique<BlockedSchemeNavigationThrottle>(request); + registry.AddThrottle( + std::make_unique<BlockedSchemeNavigationThrottle>(registry)); + return; } // Block all renderer initiated navigations to filesystem: URLs except for // when explicitly allowed by the embedder. These won't load anyway since no // URL Loader exists for them, but the throttle lets us add a message to the // console. RenderFrameHost* current_frame_host = - request->frame_tree_node()->current_frame_host(); + NavigationRequest::From(&handle)->frame_tree_node()->current_frame_host(); BrowserContext* browser_context = current_frame_host->GetBrowserContext(); // A navigation is permitted if the relevant feature flag is enabled, the // request origin is equivalent to the initiator origin, and the embedder @@ -123,24 +125,25 @@ bool is_navigation_allowed = base::FeatureList::IsEnabled( blink::features::kFileSystemUrlNavigationForChromeAppsOnly) && - (url::Origin::Create(request->GetURL()) == - request->GetInitiatorOrigin()) && + (url::Origin::Create(handle.GetURL()) == handle.GetInitiatorOrigin()) && GetContentClient()->browser()->IsFileSystemURLNavigationAllowed( - browser_context, request->GetURL()); + browser_context, handle.GetURL()); if (!is_navigation_allowed && !base::FeatureList::IsEnabled( blink::features::kFileSystemUrlNavigation) && - request->IsRendererInitiated() && - request->GetURL().SchemeIs(url::kFileSystemScheme)) { - return std::make_unique<BlockedSchemeNavigationThrottle>(request); + handle.IsRendererInitiated() && + handle.GetURL().SchemeIs(url::kFileSystemScheme)) { + registry.AddThrottle( + std::make_unique<BlockedSchemeNavigationThrottle>(registry)); + return; } // Block any external mounted files. if (!base::FeatureList::IsEnabled( blink::features::kFileSystemUrlNavigation) && - IsExternalMountedFile(request->GetURL())) { - return std::make_unique<BlockedSchemeNavigationThrottle>(request); + IsExternalMountedFile(handle.GetURL())) { + registry.AddThrottle( + std::make_unique<BlockedSchemeNavigationThrottle>(registry)); } - return nullptr; } } // namespace content
diff --git a/content/browser/renderer_host/blocked_scheme_navigation_throttle.h b/content/browser/renderer_host/blocked_scheme_navigation_throttle.h index a4ebb68f..cb759cb2 100644 --- a/content/browser/renderer_host/blocked_scheme_navigation_throttle.h +++ b/content/browser/renderer_host/blocked_scheme_navigation_throttle.h
@@ -5,8 +5,6 @@ #ifndef CONTENT_BROWSER_RENDERER_HOST_BLOCKED_SCHEME_NAVIGATION_THROTTLE_H_ #define CONTENT_BROWSER_RENDERER_HOST_BLOCKED_SCHEME_NAVIGATION_THROTTLE_H_ -#include <memory> - #include "content/public/browser/navigation_throttle.h" namespace content { @@ -15,7 +13,8 @@ // (currently data: and filesystem:). class BlockedSchemeNavigationThrottle : public NavigationThrottle { public: - explicit BlockedSchemeNavigationThrottle(NavigationHandle* navigation_handle); + explicit BlockedSchemeNavigationThrottle( + NavigationThrottleRegistry& registry); BlockedSchemeNavigationThrottle(const BlockedSchemeNavigationThrottle&) = delete; @@ -29,8 +28,7 @@ ThrottleCheckResult WillProcessResponse() override; const char* GetNameForLogging() override; - static std::unique_ptr<NavigationThrottle> CreateThrottleForNavigation( - NavigationHandle* navigation_handle); + static void MaybeCreateAndAdd(NavigationThrottleRegistry& registry); }; } // namespace content
diff --git a/content/browser/renderer_host/isolated_web_app_throttle.cc b/content/browser/renderer_host/isolated_web_app_throttle.cc index b6158e1..71e7c46 100644 --- a/content/browser/renderer_host/isolated_web_app_throttle.cc +++ b/content/browser/renderer_host/isolated_web_app_throttle.cc
@@ -72,23 +72,23 @@ } // namespace // static -std::unique_ptr<IsolatedWebAppThrottle> -IsolatedWebAppThrottle::MaybeCreateThrottleFor(NavigationHandle* handle) { - BrowserContext* browser_context = NavigationRequest::From(handle) - ->frame_tree_node() - ->navigator() - .controller() - .GetBrowserContext(); +void IsolatedWebAppThrottle::MaybeCreateAndAdd( + NavigationThrottleRegistry& registry) { + BrowserContext* browser_context = + NavigationRequest::From(®istry.GetNavigationHandle()) + ->frame_tree_node() + ->navigator() + .controller() + .GetBrowserContext(); if (AreIsolatedWebAppsEnabled(browser_context)) { - return std::make_unique<IsolatedWebAppThrottle>(handle); + registry.AddThrottle(std::make_unique<IsolatedWebAppThrottle>(registry)); } - return nullptr; } IsolatedWebAppThrottle::IsolatedWebAppThrottle( - NavigationHandle* navigation_handle) - : NavigationThrottle(navigation_handle) {} + NavigationThrottleRegistry& registry) + : NavigationThrottle(registry) {} IsolatedWebAppThrottle::~IsolatedWebAppThrottle() = default;
diff --git a/content/browser/renderer_host/isolated_web_app_throttle.h b/content/browser/renderer_host/isolated_web_app_throttle.h index 7f58c01d..5362b554 100644 --- a/content/browser/renderer_host/isolated_web_app_throttle.h +++ b/content/browser/renderer_host/isolated_web_app_throttle.h
@@ -19,10 +19,10 @@ using NavigationThrottle::ThrottleAction; using NavigationThrottle::ThrottleCheckResult; - static std::unique_ptr<IsolatedWebAppThrottle> MaybeCreateThrottleFor( - NavigationHandle* handle); + static void MaybeCreateAndAdd( + NavigationThrottleRegistry& registry); - explicit IsolatedWebAppThrottle(NavigationHandle* navigation_handle); + explicit IsolatedWebAppThrottle(NavigationThrottleRegistry& registry); ~IsolatedWebAppThrottle() override; IsolatedWebAppThrottle() = delete; IsolatedWebAppThrottle(const IsolatedWebAppThrottle&) = delete;
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc index 61454ad..d1e8e97 100644 --- a/content/browser/renderer_host/media/media_stream_manager.cc +++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -309,6 +309,8 @@ return "REQUEST_CANCELLED"; case blink::mojom::MediaStreamRequestResult::START_TIMEOUT: return "START_TIMEOUT"; + case blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED_BY_USER: + return "PERMISSION_DENIED_BY_USER"; case blink::mojom::MediaStreamRequestResult::NUM_MEDIA_REQUEST_RESULTS: break; // Not a valid enum value. }
diff --git a/content/browser/renderer_host/media/media_stream_metrics.cc b/content/browser/renderer_host/media/media_stream_metrics.cc index 6792809..a8e1dd19 100644 --- a/content/browser/renderer_host/media/media_stream_metrics.cc +++ b/content/browser/renderer_host/media/media_stream_metrics.cc
@@ -35,7 +35,8 @@ kDeviceInUse = 16, kRequestCancelled = 17, kStartTimeout = 18, - kMaxValue = kStartTimeout + kPermissionDeniedByUser = 19, + kMaxValue = kPermissionDeniedByUser }; MediaStreamRequestResult2 MapResultToResult2( @@ -80,8 +81,10 @@ return MediaStreamRequestResult2::kRequestCancelled; case MediaStreamRequestResult::START_TIMEOUT: return MediaStreamRequestResult2::kStartTimeout; + case MediaStreamRequestResult::PERMISSION_DENIED_BY_USER: + return MediaStreamRequestResult2::kPermissionDeniedByUser; case MediaStreamRequestResult::NUM_MEDIA_REQUEST_RESULTS: - break; + break; // Not a valid enum value. } NOTREACHED(); }
diff --git a/content/browser/renderer_host/mixed_content_navigation_throttle.cc b/content/browser/renderer_host/mixed_content_navigation_throttle.cc index bc228001..9865263 100644 --- a/content/browser/renderer_host/mixed_content_navigation_throttle.cc +++ b/content/browser/renderer_host/mixed_content_navigation_throttle.cc
@@ -20,15 +20,15 @@ namespace content { // static -std::unique_ptr<NavigationThrottle> -MixedContentNavigationThrottle::CreateThrottleForNavigation( - NavigationHandle* navigation_handle) { - return std::make_unique<MixedContentNavigationThrottle>(navigation_handle); +void MixedContentNavigationThrottle::CreateAndAdd( + NavigationThrottleRegistry& registry) { + registry.AddThrottle( + std::make_unique<MixedContentNavigationThrottle>(registry)); } MixedContentNavigationThrottle::MixedContentNavigationThrottle( - NavigationHandle* navigation_handle) - : NavigationThrottle(navigation_handle) {} + NavigationThrottleRegistry& registry) + : NavigationThrottle(registry) {} MixedContentNavigationThrottle::~MixedContentNavigationThrottle() {}
diff --git a/content/browser/renderer_host/mixed_content_navigation_throttle.h b/content/browser/renderer_host/mixed_content_navigation_throttle.h index 31fb6eaf..0e68345 100644 --- a/content/browser/renderer_host/mixed_content_navigation_throttle.h +++ b/content/browser/renderer_host/mixed_content_navigation_throttle.h
@@ -5,8 +5,6 @@ #ifndef CONTENT_BROWSER_RENDERER_HOST_MIXED_CONTENT_NAVIGATION_THROTTLE_H_ #define CONTENT_BROWSER_RENDERER_HOST_MIXED_CONTENT_NAVIGATION_THROTTLE_H_ -#include <set> - #include "base/gtest_prod_util.h" #include "content/browser/renderer_host/mixed_content_checker.h" #include "content/common/content_export.h" @@ -29,10 +27,9 @@ // https://w3c.github.io/webappsec-mixed-content/ class MixedContentNavigationThrottle : public NavigationThrottle { public: - static std::unique_ptr<NavigationThrottle> CreateThrottleForNavigation( - NavigationHandle* navigation_handle); + static void CreateAndAdd(NavigationThrottleRegistry& registry); - MixedContentNavigationThrottle(NavigationHandle* navigation_handle); + explicit MixedContentNavigationThrottle(NavigationThrottleRegistry& registry); MixedContentNavigationThrottle(const MixedContentNavigationThrottle&) = delete;
diff --git a/content/browser/renderer_host/mojo_render_input_router_delegate_impl.cc b/content/browser/renderer_host/mojo_render_input_router_delegate_impl.cc new file mode 100644 index 0000000..aefef51 --- /dev/null +++ b/content/browser/renderer_host/mojo_render_input_router_delegate_impl.cc
@@ -0,0 +1,72 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/renderer_host/mojo_render_input_router_delegate_impl.h" + +#include "components/viz/host/host_frame_sink_manager.h" +#include "content/browser/compositor/surface_utils.h" +#include "content/browser/renderer_host/render_widget_host_impl.h" + +namespace content { + +MojoRenderInputRouterDelegateImpl::MojoRenderInputRouterDelegateImpl( + RenderWidgetHostImpl* host) + : host_(*host) {} + +MojoRenderInputRouterDelegateImpl::~MojoRenderInputRouterDelegateImpl() = + default; + +void MojoRenderInputRouterDelegateImpl:: + SetupRenderInputRouterDelegateConnection() { + rir_delegate_client_receiver_.reset(); + rir_delegate_remote_.reset(); + GetHostFrameSinkManager()->SetupRenderInputRouterDelegateConnection( + host_->GetFrameSinkId(), + rir_delegate_client_receiver_.BindNewEndpointAndPassRemote(), + rir_delegate_remote_.BindNewEndpointAndPassReceiver()); +} + +input::mojom::RenderInputRouterDelegate* +MojoRenderInputRouterDelegateImpl::GetRenderInputRouterDelegateRemote() { + if (!rir_delegate_remote_) { + return nullptr; + } + return rir_delegate_remote_.get(); +} + +void MojoRenderInputRouterDelegateImpl::NotifyObserversOfInputEvent( + std::unique_ptr<blink::WebCoalescedInputEvent> event, + bool dispatched_to_renderer) { + host_->NotifyObserversOfInputEvent(event->Event(), dispatched_to_renderer); +} + +void MojoRenderInputRouterDelegateImpl::NotifyObserversOfInputEventAcks( + blink::mojom::InputEventResultSource ack_source, + blink::mojom::InputEventResultState ack_result, + std::unique_ptr<blink::WebCoalescedInputEvent> event) { + host_->NotifyObserversOfInputEventAcks(ack_source, ack_result, + event->Event()); +} + +void MojoRenderInputRouterDelegateImpl::OnInvalidInputEventSource() { + host_->OnInvalidInputEventSource(); +} + +void MojoRenderInputRouterDelegateImpl::StateOnOverscrollTransfer( + blink::mojom::DidOverscrollParamsPtr params) { + host_->DidOverscroll(std::move(params)); +} + +void MojoRenderInputRouterDelegateImpl::RendererInputResponsivenessChanged( + bool is_responsive, + std::optional<base::TimeTicks> ack_timeout_ts) { + if (is_responsive) { + host_->RendererIsResponsive(); + } else { + CHECK(ack_timeout_ts.has_value()); + host_->OnInputEventAckTimeout(*ack_timeout_ts); + } +} + +} // namespace content
diff --git a/content/browser/renderer_host/mojo_render_input_router_delegate_impl.h b/content/browser/renderer_host/mojo_render_input_router_delegate_impl.h new file mode 100644 index 0000000..ae5a492 --- /dev/null +++ b/content/browser/renderer_host/mojo_render_input_router_delegate_impl.h
@@ -0,0 +1,81 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_RENDERER_HOST_MOJO_RENDER_INPUT_ROUTER_DELEGATE_IMPL_H_ +#define CONTENT_BROWSER_RENDERER_HOST_MOJO_RENDER_INPUT_ROUTER_DELEGATE_IMPL_H_ + +#include <memory> + +#include "base/memory/scoped_refptr.h" +#include "components/input/render_input_router.mojom.h" +#include "mojo/public/cpp/bindings/associated_receiver.h" +#include "mojo/public/cpp/bindings/associated_remote.h" +#include "third_party/blink/public/common/input/web_coalesced_input_event.h" +#include "third_party/blink/public/mojom/input/input_event_result.mojom-shared.h" + +namespace content { + +class RenderWidgetHostImpl; + +// This class is owned by RenderWidgetHostImpl and its lifetime is directly tied +// to the RenderWidgetHostImpl instance that creates it. This class encapsulates +// the mojo-specific communication logic for syncing input handling related +// state, acting as an intermediary between the RenderWidgetHostImpl (on the +// CrBrowserMain thread) and the InputManager (on the VizCompositorThread). See +// mojo interfaces `RenderInputRouterDelegate` and +// `RenderInputRouterDelegateClient` for relevant state syncing methods. +class MojoRenderInputRouterDelegateImpl + : public input::mojom::RenderInputRouterDelegateClient { + public: + explicit MojoRenderInputRouterDelegateImpl(RenderWidgetHostImpl* host); + + ~MojoRenderInputRouterDelegateImpl() override; + + // Sets up RenderInputRouterDelegate mojo connections with InputManager on + // the VizCompositorThread for input handling with InputVizard. + void SetupRenderInputRouterDelegateConnection(); + + // Get remote for making calls to RenderInputRouterDelegate interface. Returns + // nullptr if the remote is not bound yet. The mojo connection is setup when + // layer tree frame sinks from renderer are being requested (see + // RenderWidgetHostImpl::CreateFrameSink). This connection is setup before + // input handling starts on VizCompositorThread for its corresponding + // `frame_sink_id`. + input::mojom::RenderInputRouterDelegate* GetRenderInputRouterDelegateRemote(); + + // input::mojom::RenderInputRouterDelegateClient overrides. + void NotifyObserversOfInputEvent( + std::unique_ptr<blink::WebCoalescedInputEvent> event, + bool dispatched_to_renderer) override; + void NotifyObserversOfInputEventAcks( + blink::mojom::InputEventResultSource ack_source, + blink::mojom::InputEventResultState ack_result, + std::unique_ptr<blink::WebCoalescedInputEvent> event) override; + void OnInvalidInputEventSource() override; + void StateOnOverscrollTransfer( + blink::mojom::DidOverscrollParamsPtr params) override; + void RendererInputResponsivenessChanged( + bool is_responsive, + std::optional<base::TimeTicks> ack_timeout_ts) override; + + void SetRenderInputRouterDelegateRemoteForTesting( + mojo::PendingAssociatedRemote<input::mojom::RenderInputRouterDelegate> + remote) { + rir_delegate_remote_.Bind(std::move(remote)); + } + + private: + mojo::AssociatedReceiver<input::mojom::RenderInputRouterDelegateClient> + rir_delegate_client_receiver_{this}; + mojo::AssociatedRemote<input::mojom::RenderInputRouterDelegate> + rir_delegate_remote_; + + // It is safe to use `raw_ref` here since RenderWidgetHostImpl owns this class + // and is bound to outlive |this|. + raw_ref<RenderWidgetHostImpl> host_; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_RENDERER_HOST_MOJO_RENDER_INPUT_ROUTER_DELEGATE_IMPL_H_
diff --git a/content/browser/renderer_host/navigation_throttle_runner.cc b/content/browser/renderer_host/navigation_throttle_runner.cc index 58da2608..94ff95c 100644 --- a/content/browser/renderer_host/navigation_throttle_runner.cc +++ b/content/browser/renderer_host/navigation_throttle_runner.cc
@@ -13,7 +13,6 @@ #include "build/build_config.h" #include "content/browser/devtools/devtools_instrumentation.h" #include "content/browser/preloading/prefetch/contamination_delay_navigation_throttle.h" -#include "content/browser/preloading/prefetch/prefetch_features.h" #include "content/browser/preloading/prerender/prerender_navigation_throttle.h" #include "content/browser/preloading/prerender/prerender_subframe_navigation_throttle.h" #include "content/browser/renderer_host/ancestor_throttle.h" @@ -223,44 +222,34 @@ // Check for renderer-inititated main frame navigations to blocked URL schemes // (data, filesystem). This is done early as it may block the main frame // navigation altogether. - MaybeAddThrottle( - BlockedSchemeNavigationThrottle::CreateThrottleForNavigation(request)); + BlockedSchemeNavigationThrottle::MaybeCreateAndAdd(*this); #if !BUILDFLAG(IS_ANDROID) // Prevent cross-document navigations from document picture-in-picture // windows. - MaybeAddThrottle( - DocumentPictureInPictureNavigationThrottle::MaybeCreateThrottleFor( - request)); + DocumentPictureInPictureNavigationThrottle::MaybeCreateAndAdd(*this); #endif // !BUILDFLAG(IS_ANDROID) - MaybeAddThrottle(AncestorThrottle::MaybeCreateThrottleFor(request)); + AncestorThrottle::CreateAndAdd(*this); // Check for mixed content. This is done after the AncestorThrottle and the // FormSubmissionThrottle so that when folks block mixed content with a CSP // policy, they don't get a warning. They'll still get a warning in the // console about CSP blocking the load. - AddThrottle( - MixedContentNavigationThrottle::CreateThrottleForNavigation(request)); + MixedContentNavigationThrottle::CreateAndAdd(*this); - if (base::FeatureList::IsEnabled( - features::kPrefetchStateContaminationMitigation)) { - // Delay response processing for certain prefetch responses where it might - // otherwise reveal information about cross-site state. - AddThrottle( - std::make_unique<ContaminationDelayNavigationThrottle>(request)); - } + // Delay response processing for certain prefetch responses where it might + // otherwise reveal information about cross-site state. + ContaminationDelayNavigationThrottle::MaybeCreateAndAdd(*this); // Block certain requests that are not permitted for prerendering. - MaybeAddThrottle( - PrerenderNavigationThrottle::MaybeCreateThrottleFor(request)); + PrerenderNavigationThrottle::MaybeCreateAndAdd(*this); // Defer cross-origin subframe loading during prerendering state. - MaybeAddThrottle( - PrerenderSubframeNavigationThrottle::MaybeCreateThrottleFor(request)); + PrerenderSubframeNavigationThrottle::MaybeCreateAndAdd(*this); // Prevent navigations to/from Isolated Web Apps. - MaybeAddThrottle(IsolatedWebAppThrottle::MaybeCreateThrottleFor(request)); + IsolatedWebAppThrottle::MaybeCreateAndAdd(*this); devtools_instrumentation::CreateAndAddNavigationThrottles(*this); @@ -333,8 +322,7 @@ SubframeHistoryNavigationThrottle::MaybeCreateThrottleFor(request)); // Defer cross-origin about:srcdoc subframe loading during prerendering state. - MaybeAddThrottle( - PrerenderSubframeNavigationThrottle::MaybeCreateThrottleFor(request)); + PrerenderSubframeNavigationThrottle::MaybeCreateAndAdd(*this); // Defer subframe navigation in bfcached page. MaybeAddThrottle(
diff --git a/content/browser/renderer_host/render_widget_host_delegate.cc b/content/browser/renderer_host/render_widget_host_delegate.cc index 0b57828..c75785d 100644 --- a/content/browser/renderer_host/render_widget_host_delegate.cc +++ b/content/browser/renderer_host/render_widget_host_delegate.cc
@@ -187,11 +187,6 @@ return true; } -input::mojom::RenderInputRouterDelegate* -RenderWidgetHostDelegate::GetRenderInputRouterDelegateRemote() { - return nullptr; -} - #if BUILDFLAG(IS_ANDROID) float RenderWidgetHostDelegate::GetCurrentTouchSequenceYOffset() { return 0.f;
diff --git a/content/browser/renderer_host/render_widget_host_delegate.h b/content/browser/renderer_host/render_widget_host_delegate.h index a54a0de..09eadc0 100644 --- a/content/browser/renderer_host/render_widget_host_delegate.h +++ b/content/browser/renderer_host/render_widget_host_delegate.h
@@ -374,10 +374,6 @@ // Notifies when an input event is ignored. virtual void OnInputIgnored(const blink::WebInputEvent& event) {} - // Get remote for making calls to RenderInputRouterDelegate interface. - virtual input::mojom::RenderInputRouterDelegate* - GetRenderInputRouterDelegateRemote(); - #if BUILDFLAG(IS_ANDROID) // Get the y value by which the touch sequence is offsetted by. For e.g. // visible top controls will result in a non zero offset to be added to touch
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 52f7728..252edf0bb 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -1503,7 +1503,7 @@ void RenderWidgetHostImpl::NotifyVizOfPageVisibilityUpdates() { if (auto* delegate_remote = - delegate()->GetRenderInputRouterDelegateRemote()) { + mojo_rir_delegate_impl_.GetRenderInputRouterDelegateRemote()) { delegate_remote->NotifyVisibilityChanged(frame_sink_id_, is_hidden_); } } @@ -1514,7 +1514,8 @@ } // Notifies RenderInputRouters on both browser and VizCompositor to restart // their input event ack timers. - if (auto* remote = delegate()->GetRenderInputRouterDelegateRemote()) { + if (auto* remote = + mojo_rir_delegate_impl_.GetRenderInputRouterDelegateRemote()) { remote->RestartInputEventAckTimeoutIfNecessary(GetFrameSinkId()); } GetRenderInputRouter()->RestartInputEventAckTimeoutIfNecessary(); @@ -3632,6 +3633,11 @@ std::move(compositor_frame_sink_client), std::move(viz_rir_client_remote), GetRenderInputRouter()->GetForceEnableZoom()); + if (input::InputUtils::IsTransferInputToVizSupported()) { + // Handles setting up GPU mojo endpoint connections for + // RenderInputRouterDelegate[Client] interfaces. + mojo_rir_delegate_impl_.SetupRenderInputRouterDelegateConnection(); + } MaybeDispatchBufferedFrameSinkRequest(); } @@ -3739,6 +3745,10 @@ } void RenderWidgetHostImpl::SetForceEnableZoom(bool enabled) { + if (auto* remote = + mojo_rir_delegate_impl_.GetRenderInputRouterDelegateRemote()) { + remote->ForceEnableZoomStateChanged(enabled, frame_sink_id_); + } GetRenderInputRouter()->SetForceEnableZoom(enabled); }
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index 0bc94f22..f24d020 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -43,6 +43,7 @@ #include "content/browser/renderer_host/agent_scheduling_group_host.h" #include "content/browser/renderer_host/frame_token_message_queue.h" #include "content/browser/renderer_host/input/touch_emulator_impl.h" +#include "content/browser/renderer_host/mojo_render_input_router_delegate_impl.h" #include "content/browser/renderer_host/render_frame_metadata_provider_impl.h" #include "content/browser/renderer_host/render_widget_host_delegate.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" @@ -420,6 +421,9 @@ void SetView(RenderWidgetHostViewBase* view); RenderWidgetHostDelegate* delegate() const { return delegate_; } + MojoRenderInputRouterDelegateImpl* mojo_rir_delegate() { + return &mojo_rir_delegate_impl_; + } // Bind the provided widget interfaces. void BindWidgetInterfaces( @@ -1246,6 +1250,11 @@ // True if |Destroy()| has been called. bool destroyed_ = false; + // Handles mojo connections for RenderInputRouterDelegate[Client] interface to + // allow sycing information between the Browser and the GPU process for input + // handling with InputVizard. + MojoRenderInputRouterDelegateImpl mojo_rir_delegate_impl_{this}; + // Our delegate, which wants to know mainly about keyboard events. // It will remain non-null until DetachDelegate() is called. raw_ptr<RenderWidgetHostDelegate, FlakyDanglingUntriaged> delegate_;
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index df4f06d9..a9642fcf 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -1378,7 +1378,8 @@ bool browser_would_have_handled) { TRACE_EVENT("input", "RenderWidgetHostViewAndroid::StateOnTouchTransfer"); CHECK(host()); - auto* remote = host()->delegate()->GetRenderInputRouterDelegateRemote(); + auto* remote = + host()->mojo_rir_delegate()->GetRenderInputRouterDelegateRemote(); const float y_offset_pix = host()->delegate()->GetCurrentTouchSequenceYOffset(); remote->StateOnTouchTransfer(input::mojom::TouchTransferState::New( @@ -1564,8 +1565,9 @@ } else if (event.GetAction() == ui::MotionEvent::Action::DOWN) { // Stop any ongoing fling on VizCompositorThread if the new input sequence // is going to be handled on the Browser. - if (auto* remote = - host()->delegate()->GetRenderInputRouterDelegateRemote()) { + if (auto* remote = host() + ->mojo_rir_delegate() + ->GetRenderInputRouterDelegateRemote()) { remote->StopFlingingOnViz(host()->GetFrameSinkId()); } } @@ -1621,7 +1623,8 @@ if (!host()) { return; } - auto* remote = host()->delegate()->GetRenderInputRouterDelegateRemote(); + auto* remote = + host()->mojo_rir_delegate()->GetRenderInputRouterDelegateRemote(); remote->ResetGestureDetection(GetFrameSinkId()); return; }
diff --git a/content/browser/renderer_host/render_widget_host_view_android_unittest.cc b/content/browser/renderer_host/render_widget_host_view_android_unittest.cc index e167adc..0b52cdb8b 100644 --- a/content/browser/renderer_host/render_widget_host_view_android_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_android_unittest.cc
@@ -117,9 +117,9 @@ MockMojoRenderInputRouterDelegate() = default; ~MockMojoRenderInputRouterDelegate() override = default; - mojo::PendingRemote<input::mojom::RenderInputRouterDelegate> + mojo::PendingAssociatedRemote<input::mojom::RenderInputRouterDelegate> GetPendingRemote() { - return receiver_.BindNewPipeAndPassRemote(); + return receiver_.BindNewEndpointAndPassDedicatedRemote(); } MOCK_METHOD1(StateOnTouchTransfer, @@ -129,7 +129,7 @@ const viz::FrameSinkId& frame_sink_id)); MOCK_METHOD2(ForceEnableZoomStateChanged, void(bool force_enable_zoom, - const std::vector<viz::FrameSinkId>& frame_sink_ids)); + const viz::FrameSinkId& frame_sink_id)); MOCK_METHOD1(StopFlingingOnViz, void(const viz::FrameSinkId& frame_sink_id)); MOCK_METHOD1(RestartInputEventAckTimeoutIfNecessary, void(const viz::FrameSinkId& frame_sink_id)); @@ -139,7 +139,8 @@ void(const viz::FrameSinkId& frame_sink_id)); private: - mojo::Receiver<input::mojom::RenderInputRouterDelegate> receiver_{this}; + mojo::AssociatedReceiver<input::mojom::RenderInputRouterDelegate> receiver_{ + this}; }; class RenderWidgetHostViewAndroidTest : public RenderViewHostImplTestHarness { @@ -529,8 +530,10 @@ rwhva->SetInputTransferHandlerForTesting(handler); MockMojoRenderInputRouterDelegate rir_delegate; - delegate()->set_render_input_router_delegate_remote( - rir_delegate.GetPendingRemote()); + rwhva->host() + ->mojo_rir_delegate() + ->SetRenderInputRouterDelegateRemoteForTesting( + rir_delegate.GetPendingRemote()); EXPECT_CALL(*handler, IsTouchSequencePotentiallyActiveOnViz()) .WillOnce(Return(true)); @@ -550,8 +553,10 @@ rwhva->SetInputTransferHandlerForTesting(handler); MockMojoRenderInputRouterDelegate rir_delegate; - delegate()->set_render_input_router_delegate_remote( - rir_delegate.GetPendingRemote()); + rwhva->host() + ->mojo_rir_delegate() + ->SetRenderInputRouterDelegateRemoteForTesting( + rir_delegate.GetPendingRemote()); gfx::Point point(/*x=*/100, /*y=*/100); ui::MotionEventAndroid::Pointer p(0, point.x(), point.y(), 10, 0, 0, 0, 0, 0);
diff --git a/content/browser/shared_storage/shared_storage_browsertest.cc b/content/browser/shared_storage/shared_storage_browsertest.cc index 7827687..50a7a4b8 100644 --- a/content/browser/shared_storage/shared_storage_browsertest.cc +++ b/content/browser/shared_storage/shared_storage_browsertest.cc
@@ -727,8 +727,7 @@ ExpectOperationFinishedInfosObserved( {{base::TimeDelta(), AccessMethod::kRun, /*operation_id=*/0, - /*worklet_ordinal_id=*/0, GetFirstWorkletHostDevToolsToken(), - MainFrameId(), origin_str}}); + GetFirstWorkletHostDevToolsToken(), MainFrameId(), origin_str}}); } IN_PROC_BROWSER_TEST_P(SharedStorageBrowserTest, @@ -1024,8 +1023,7 @@ ExpectOperationFinishedInfosObserved( {{base::TimeDelta(), AccessMethod::kRun, /*operation_id=*/0, - /*worklet_ordinal_id=*/0, GetFirstWorkletHostDevToolsToken(), - MainFrameId(), origin_str}}); + GetFirstWorkletHostDevToolsToken(), MainFrameId(), origin_str}}); } IN_PROC_BROWSER_TEST_P( @@ -1122,11 +1120,9 @@ ExpectOperationFinishedInfosObserved( {{base::TimeDelta(), AccessMethod::kRun, /*operation_id=*/0, - /*worklet_ordinal_id=*/0, GetFirstWorkletHostDevToolsToken(), - MainFrameId(), origin_str}, + GetFirstWorkletHostDevToolsToken(), MainFrameId(), origin_str}, {base::TimeDelta(), AccessMethod::kRun, /*operation_id=*/1, - /*worklet_ordinal_id=*/0, GetFirstWorkletHostDevToolsToken(), - MainFrameId(), origin_str}}); + GetFirstWorkletHostDevToolsToken(), MainFrameId(), origin_str}}); } IN_PROC_BROWSER_TEST_P( @@ -1608,7 +1604,7 @@ ExpectOperationFinishedInfosObserved( {{base::TimeDelta(), AccessMethod::kRun, /*operation_id=*/0, - /*worklet_ordinal_id=*/0, GetFirstWorkletHostDevToolsToken(), + GetFirstWorkletHostDevToolsToken(), /*main_frame_id=*/GlobalRenderFrameHostId(), origin_str}}); } @@ -1750,7 +1746,7 @@ ExpectOperationFinishedInfosObserved( {{base::TimeDelta(), AccessMethod::kSelectURL, /*operation_id=*/0, - /*worklet_ordinal_id=*/0, GetFirstWorkletHostDevToolsToken(), + GetFirstWorkletHostDevToolsToken(), /*main_frame_id=*/GlobalRenderFrameHostId(), origin_str}}); } @@ -9800,11 +9796,9 @@ ExpectOperationFinishedInfosObserved( {{base::TimeDelta(), AccessMethod::kRun, /*operation_id=*/0, - /*worklet_ordinal_id=*/0, cached_worklet_devtools_tokens[0], - MainFrameId(), origin_str}, + cached_worklet_devtools_tokens[0], MainFrameId(), origin_str}, {base::TimeDelta(), AccessMethod::kRun, /*operation_id=*/0, - /*worklet_ordinal_id=*/1, cached_worklet_devtools_tokens[1], - MainFrameId(), origin_str}}); + cached_worklet_devtools_tokens[1], MainFrameId(), origin_str}}); } IN_PROC_BROWSER_TEST_P(
diff --git a/content/browser/shared_storage/shared_storage_fenced_frame_browsertest.cc b/content/browser/shared_storage/shared_storage_fenced_frame_browsertest.cc index 4eaabb1..03d48b0b0 100644 --- a/content/browser/shared_storage/shared_storage_fenced_frame_browsertest.cc +++ b/content/browser/shared_storage/shared_storage_fenced_frame_browsertest.cc
@@ -3096,8 +3096,7 @@ GetFirstWorkletHostDevToolsToken())}); expected_finished_infos.push_back( {base::TimeDelta(), AccessMethod::kSelectURL, /*operation_id=*/call, - /*worklet_ordinal_id=*/0, GetFirstWorkletHostDevToolsToken(), - MainFrameId(), origin_str}); + GetFirstWorkletHostDevToolsToken(), MainFrameId(), origin_str}); } expected_accesses.push_back( {AccessScope::kWindow, AccessMethod::kSelectURL, MainFrameId(), @@ -3112,8 +3111,7 @@ /*worklet_ordinal_id=*/0, GetFirstWorkletHostDevToolsToken())}); expected_finished_infos.push_back( {base::TimeDelta(), AccessMethod::kSelectURL, /*operation_id=*/call_limit, - /*worklet_ordinal_id=*/0, GetFirstWorkletHostDevToolsToken(), - MainFrameId(), origin_str}); + GetFirstWorkletHostDevToolsToken(), MainFrameId(), origin_str}); for (int call = 0; call < call_limit; call++) { expected_accesses.push_back( {AccessScope::kWindow, AccessMethod::kSelectURL, MainFrameId(), @@ -3131,7 +3129,7 @@ /*worklet_ordinal_id=*/0, GetFirstWorkletHostDevToolsToken())}); expected_finished_infos.push_back( {base::TimeDelta(), AccessMethod::kSelectURL, - /*operation_id=*/call_limit + 1 + call, /*worklet_ordinal_id=*/0, + /*operation_id=*/call_limit + 1 + call, GetFirstWorkletHostDevToolsToken(), MainFrameId(), origin_str}); } @@ -3263,8 +3261,7 @@ cached_worklet_devtools_tokens[call])}); expected_finished_infos.push_back( {base::TimeDelta(), AccessMethod::kSelectURL, /*operation_id=*/0, - /*worklet_ordinal_id=*/call, cached_worklet_devtools_tokens[call], - MainFrameId(), origin_str}); + cached_worklet_devtools_tokens[call], MainFrameId(), origin_str}); } origin_str = https_server()->GetOrigin("b.test").Serialize(); expected_accesses.push_back( @@ -3289,7 +3286,6 @@ cached_worklet_devtools_tokens[call_limit])}); expected_finished_infos.push_back( {base::TimeDelta(), AccessMethod::kSelectURL, /*operation_id=*/0, - /*worklet_ordinal_id=*/call_limit, cached_worklet_devtools_tokens[call_limit], MainFrameId(), origin_str}); for (int call = 0; call < call_limit; call++) { host = base::StrCat({"subdomain", base::NumberToString(call), ".b.test"}); @@ -3318,7 +3314,6 @@ cached_worklet_devtools_tokens[call_limit + 1 + call])}); expected_finished_infos.push_back( {base::TimeDelta(), AccessMethod::kSelectURL, /*operation_id=*/0, - /*worklet_ordinal_id=*/call_limit + 1 + call, cached_worklet_devtools_tokens[call_limit + 1 + call], MainFrameId(), origin_str}); }
diff --git a/content/browser/shared_storage/shared_storage_runtime_manager.cc b/content/browser/shared_storage/shared_storage_runtime_manager.cc index 8149a7d..213f1db 100644 --- a/content/browser/shared_storage/shared_storage_runtime_manager.cc +++ b/content/browser/shared_storage/shared_storage_runtime_manager.cc
@@ -153,7 +153,6 @@ base::TimeDelta execution_time, SharedStorageObserverInterface::AccessMethod method, int operation_id, - int worklet_ordinal_id, const base::UnguessableToken& worklet_devtools_token, GlobalRenderFrameHostId main_frame_id, const std::string& owner_origin) { @@ -171,8 +170,8 @@ // however, that there may be a discrepancy between `execution_time` and // `finished_time - start-time`. observer.OnSharedStorageWorkletOperationExecutionFinished( - now, execution_time, method, operation_id, worklet_ordinal_id, - worklet_devtools_token, main_frame_id, owner_origin); + now, execution_time, method, operation_id, worklet_devtools_token, + main_frame_id, owner_origin); } }
diff --git a/content/browser/shared_storage/shared_storage_runtime_manager.h b/content/browser/shared_storage/shared_storage_runtime_manager.h index 7476747..3c789a7 100644 --- a/content/browser/shared_storage/shared_storage_runtime_manager.h +++ b/content/browser/shared_storage/shared_storage_runtime_manager.h
@@ -78,13 +78,11 @@ virtual void OnSharedStorageSelectUrlConfigPopulated( const std::optional<FencedFrameConfig>& config) = 0; - // TODO(crbug.com/401011862): Remove `worklet_ordinal_id` parameter. virtual void OnSharedStorageWorkletOperationExecutionFinished( base::Time finished_time, base::TimeDelta execution_time, AccessMethod method, int operation_id, - int worklet_ordinal_id, const base::UnguessableToken& worklet_devtools_token, GlobalRenderFrameHostId main_frame_id, const std::string& owner_origin) = 0; @@ -123,12 +121,10 @@ const std::string& owner_origin, const SharedStorageEventParams& params); - // TODO(crbug.com/401011862): Remove `worklet_ordinal_id` parameter. void NotifyWorkletOperationExecutionFinished( base::TimeDelta execution_time, SharedStorageObserverInterface::AccessMethod method, int operation_id, - int worklet_ordinal_id, const base::UnguessableToken& worklet_devtools_token, GlobalRenderFrameHostId main_frame_id, const std::string& owner_origin); @@ -190,10 +186,9 @@ base::ObserverList<SharedStorageObserverInterface> observers_; - // A monotonically increasing ID assigned to each SharedStorageWorkletHost. - // This ID is assigned during construction of the SharedStorageWorkletHost. - // TODO(crbug.com/401011862): Use the worklet IDs generated in DevTools - // reporting. + // A monotonically increasing number assigned to each + // SharedStorageWorkletHost. This ordinal is assigned during construction of + // the SharedStorageWorkletHost. int next_worklet_ordinal_id_ = 0; };
diff --git a/content/browser/shared_storage/shared_storage_worklet_host.cc b/content/browser/shared_storage/shared_storage_worklet_host.cc index 1ac4689..b90bca104 100644 --- a/content/browser/shared_storage/shared_storage_worklet_host.cc +++ b/content/browser/shared_storage/shared_storage_worklet_host.cc
@@ -1423,8 +1423,8 @@ shared_storage_runtime_manager_->NotifyWorkletOperationExecutionFinished( base::TimeTicks::Now() - run_start_time, AccessMethod::kRun, operation_id, - worklet_ordinal_id_, GetWorkletDevToolsToken(), - GetMainFrameIdIfAvailable(), shared_storage_origin_.Serialize()); + GetWorkletDevToolsToken(), GetMainFrameIdIfAvailable(), + shared_storage_origin_.Serialize()); base::UmaHistogramLongTimes( "Storage.SharedStorage.Document.Timing.Run.ExecutedInWorklet", @@ -1557,8 +1557,8 @@ shared_storage_runtime_manager_->NotifyWorkletOperationExecutionFinished( base::TimeTicks::Now() - select_url_start_time, AccessMethod::kSelectURL, - operation_id, worklet_ordinal_id_, GetWorkletDevToolsToken(), - GetMainFrameIdIfAvailable(), shared_storage_origin_.Serialize()); + operation_id, GetWorkletDevToolsToken(), GetMainFrameIdIfAvailable(), + shared_storage_origin_.Serialize()); base::UmaHistogramLongTimes( "Storage.SharedStorage.Document.Timing.SelectURL.ExecutedInWorklet",
diff --git a/content/browser/shared_storage/test_shared_storage_observer.cc b/content/browser/shared_storage/test_shared_storage_observer.cc index 81fe832..da8a9ee 100644 --- a/content/browser/shared_storage/test_shared_storage_observer.cc +++ b/content/browser/shared_storage/test_shared_storage_observer.cc
@@ -98,14 +98,12 @@ base::TimeDelta execution_time, AccessMethod method, int operation_id, - int worklet_ordinal_id, const base::UnguessableToken& worklet_devtools_token, GlobalRenderFrameHostId main_frame_id, std::string owner_origin) : execution_time(execution_time), method(method), operation_id(operation_id), - worklet_ordinal_id(worklet_ordinal_id), worklet_devtools_token(worklet_devtools_token), main_frame_id(std::move(main_frame_id)), owner_origin(std::move(owner_origin)) {} @@ -161,13 +159,12 @@ base::TimeDelta execution_time, AccessMethod method, int operation_id, - int worklet_ordinal_id, const base::UnguessableToken& worklet_devtools_token, GlobalRenderFrameHostId main_frame_id, const std::string& owner_origin) { - operation_finished_infos_.emplace_back( - execution_time, method, operation_id, worklet_ordinal_id, - worklet_devtools_token, main_frame_id, owner_origin); + operation_finished_infos_.emplace_back(execution_time, method, operation_id, + worklet_devtools_token, main_frame_id, + owner_origin); } void TestSharedStorageObserver::ExpectAccessObserved( @@ -198,7 +195,6 @@ const TestSharedStorageObserver::OperationFinishedInfo& rhs) { // Do not compare `execution_time` when checking for equality in tests. return lhs.method == rhs.method && lhs.operation_id == rhs.operation_id && - lhs.worklet_ordinal_id == rhs.worklet_ordinal_id && lhs.worklet_devtools_token == rhs.worklet_devtools_token && lhs.main_frame_id == rhs.main_frame_id && lhs.owner_origin == rhs.owner_origin; @@ -210,7 +206,6 @@ os << "{ Execution Time: " << info.execution_time.InMicroseconds() << "; Access Method: " << SerializeMethod(info.method) << "; Operation ID: " << info.operation_id - << "; Worklet Ordinal ID: " << info.worklet_ordinal_id << "; Worklet Devtools Token: " << info.worklet_devtools_token << "; Main Frame ID: " << info.main_frame_id << "; Owner Origin: " << info.owner_origin << " }";
diff --git a/content/browser/shared_storage/test_shared_storage_observer.h b/content/browser/shared_storage/test_shared_storage_observer.h index 2bfe6d0..ed5cb83 100644 --- a/content/browser/shared_storage/test_shared_storage_observer.h +++ b/content/browser/shared_storage/test_shared_storage_observer.h
@@ -38,7 +38,6 @@ base::TimeDelta execution_time; AccessMethod method; int operation_id; - int worklet_ordinal_id; base::UnguessableToken worklet_devtools_token; GlobalRenderFrameHostId main_frame_id; std::string owner_origin; @@ -46,7 +45,6 @@ OperationFinishedInfo(base::TimeDelta execution_time, AccessMethod method, int operation_id, - int worklet_ordinal_id, const base::UnguessableToken& worklet_devtools_token, GlobalRenderFrameHostId main_frame_id, std::string owner_origin); @@ -81,7 +79,6 @@ base::TimeDelta execution_time, AccessMethod method, int operation_id, - int worklet_ordinal_id, const base::UnguessableToken& worklet_devtools_token, GlobalRenderFrameHostId main_frame_id, const std::string& owner_origin) override;
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index e5795154..f3204a3 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -1434,10 +1434,6 @@ SharedStorageBudgetCharger::CreateForWebContents(this); } - if (input::InputUtils::IsTransferInputToVizSupported()) { - SetupRenderInputRouterDelegateConnection(); - } - if (base::FeatureList::IsEnabled( fingerprinting_protection_interventions::features::kCanvasNoise)) { renderer_preferences_.canvas_noise_token = @@ -1445,22 +1441,6 @@ } } -void WebContentsImpl::SetupRenderInputRouterDelegateConnection() { - // Handles setting up GPU mojo endpoint connections. In general, the number of - // retries for setting up these mojo connections is capped by the maximum - // number of attempts to restart the GPU process, see - // GpuProcessHost::GetFallbackCrashLimit(). - rir_delegate_client_receiver_.reset(); - rir_delegate_remote_.reset(); - GetHostFrameSinkManager()->SetupRenderInputRouterDelegateConnection( - compositor_frame_sink_grouping_id_, - rir_delegate_client_receiver_.BindNewPipeAndPassRemote(), - rir_delegate_remote_.BindNewPipeAndPassReceiver()); - rir_delegate_client_receiver_.set_disconnect_handler( - base::BindOnce(&WebContentsImpl::SetupRenderInputRouterDelegateConnection, - weak_factory_.GetWeakPtr())); -} - WebContentsImpl::~WebContentsImpl() { TRACE_EVENT0("content", "WebContentsImpl::~WebContentsImpl"); WebContentsOfBrowserContext::Detach(*this); @@ -3847,10 +3827,6 @@ } } } - // Notify VizCompositor thread of force_enable_zoom state changes. - if (auto* remote = GetRenderInputRouterDelegateRemote()) { - remote->ForceEnableZoomStateChanged(force_enable_zoom_, frame_sink_ids); - } } #endif @@ -7537,82 +7513,6 @@ return touch_emulator_.get(); } -void WebContentsImpl::NotifyObserversOfInputEvent( - const viz::FrameSinkId& frame_sink_id, - std::unique_ptr<blink::WebCoalescedInputEvent> event, - bool dispatched_to_renderer) { - auto iter = created_widgets_.find(frame_sink_id); - // This adds a safeguard against race condition where a RenderWidgetHostImpl - // is being destroyed & removed from |created_widgets_|, but Viz may still - // send a mojo call referencing it. - if (iter == created_widgets_.end()) { - return; - } - iter->second->NotifyObserversOfInputEvent(event->Event(), - dispatched_to_renderer); -} - -void WebContentsImpl::NotifyObserversOfInputEventAcks( - const viz::FrameSinkId& frame_sink_id, - blink::mojom::InputEventResultSource ack_source, - blink::mojom::InputEventResultState ack_result, - std::unique_ptr<blink::WebCoalescedInputEvent> event) { - auto iter = created_widgets_.find(frame_sink_id); - // This adds a safeguard against race condition where a RenderWidgetHostImpl - // is being destroyed & removed from |created_widgets_|, but Viz may still - // send a mojo call referencing it. - if (iter == created_widgets_.end()) { - return; - } - iter->second->NotifyObserversOfInputEventAcks(ack_source, ack_result, - event->Event()); -} - -void WebContentsImpl::OnInvalidInputEventSource( - const viz::FrameSinkId& frame_sink_id) { - auto iter = created_widgets_.find(frame_sink_id); - // This adds a safeguard against race condition where a RenderWidgetHostImpl - // is being destroyed & removed from |created_widgets_|, but Viz may still - // send a mojo call referencing it. - if (iter == created_widgets_.end()) { - return; - } - iter->second->OnInvalidInputEventSource(); -} - -void WebContentsImpl::StateOnOverscrollTransfer( - const viz::FrameSinkId& frame_sink_id, - blink::mojom::DidOverscrollParamsPtr params) { - auto iter = created_widgets_.find(frame_sink_id); - // This adds a safeguard against race condition where a RenderWidgetHostImpl - // is being destroyed & removed from |created_widgets_|, but Viz may still - // send a mojo call referencing it. - if (iter == created_widgets_.end()) { - return; - } - iter->second->DidOverscroll(std::move(params)); -} - -void WebContentsImpl::RendererInputResponsivenessChanged( - const viz::FrameSinkId& frame_sink_id, - bool is_responsive, - std::optional<base::TimeTicks> ack_timeout_ts) { - auto iter = created_widgets_.find(frame_sink_id); - // This adds a safeguard against race condition where a RenderWidgetHostImpl - // is being destroyed & removed from |created_widgets_|, but Viz may still - // send a mojo call referencing it. - if (iter == created_widgets_.end()) { - return; - } - - if (is_responsive) { - iter->second->RendererIsResponsive(); - } else { - CHECK(ack_timeout_ts.has_value()); - iter->second->OnInputEventAckTimeout(*ack_timeout_ts); - } -} - void WebContentsImpl::DidNavigateMainFramePreCommit( NavigationHandle* navigation_handle, bool navigation_is_within_page) { @@ -12068,14 +11968,6 @@ #endif } -input::mojom::RenderInputRouterDelegate* -WebContentsImpl::GetRenderInputRouterDelegateRemote() { - if (!rir_delegate_remote_) { - return nullptr; - } - return rir_delegate_remote_.get(); -} - #if BUILDFLAG(IS_ANDROID) float WebContentsImpl::GetCurrentTouchSequenceYOffset() { ui::ViewAndroid* view_android = GetNativeView();
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 478c9df..183643a2 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -31,7 +31,6 @@ #include "base/types/pass_key.h" #include "build/build_config.h" #include "components/download/public/common/download_url_parameters.h" -#include "components/input/render_input_router.mojom.h" #include "components/input/render_widget_host_input_event_router.h" #include "content/browser/media/audio_stream_monitor.h" #include "content/browser/media/forwarding_audio_stream_factory.h" @@ -215,8 +214,7 @@ public ui::NativeThemeObserver, public ui::ColorProviderSourceObserver, public SlowWebPreferenceCacheObserver, - public input::RenderWidgetHostInputEventRouter::Delegate, - public input::mojom::RenderInputRouterDelegateClient { + public input::RenderWidgetHostInputEventRouter::Delegate { public: class FriendWrapper; @@ -1202,8 +1200,6 @@ gfx::mojom::DelegatedInkPointRenderer* GetDelegatedInkRenderer( ui::Compositor* compositor) override; void OnInputIgnored(const blink::WebInputEvent& event) override; - input::mojom::RenderInputRouterDelegate* GetRenderInputRouterDelegateRemote() - override; #if BUILDFLAG(IS_ANDROID) float GetCurrentTouchSequenceYOffset() override; #endif @@ -1289,26 +1285,6 @@ // RenderWidgetHostInputEventRouter::Delegate ------------------------------- input::TouchEmulator* GetTouchEmulator(bool create_if_necessary) override; - // input::mojom::RenderInputRouterDelegateClient ----------------------------- - void NotifyObserversOfInputEvent( - const viz::FrameSinkId& frame_sink_id, - std::unique_ptr<blink::WebCoalescedInputEvent> event, - bool dispatched_to_renderer) override; - void NotifyObserversOfInputEventAcks( - const viz::FrameSinkId& frame_sink_id, - blink::mojom::InputEventResultSource ack_source, - blink::mojom::InputEventResultState ack_result, - std::unique_ptr<blink::WebCoalescedInputEvent> event) override; - void OnInvalidInputEventSource( - const viz::FrameSinkId& frame_sink_id) override; - void StateOnOverscrollTransfer( - const viz::FrameSinkId& frame_sink_id, - blink::mojom::DidOverscrollParamsPtr params) override; - void RendererInputResponsivenessChanged( - const viz::FrameSinkId& frame_sink_id, - bool is_responsive, - std::optional<base::TimeTicks> ack_timeout_ts) override; - // Invoked before a form repost warning is shown. void NotifyBeforeFormRepostWarningShow() override; @@ -2233,10 +2209,6 @@ // JavascriptDialogManager. void CancelDialogManagerDialogs(bool reset_state); - // Sets up RenderInputRouterDelegate mojo connections with InputManager on - // the VizCompositorThread for input handling with InputVizard. - void SetupRenderInputRouterDelegateConnection(); - // See GetPartitionedPopinEmbedderOrigin for details. GURL GetPartitionedPopinEmbedderOriginImpl() const; @@ -2753,11 +2725,6 @@ // input event routing with InputVizard. const base::UnguessableToken compositor_frame_sink_grouping_id_; - mojo::Receiver<input::mojom::RenderInputRouterDelegateClient> - rir_delegate_client_receiver_{this}; - - mojo::Remote<input::mojom::RenderInputRouterDelegate> rir_delegate_remote_; - // Indicates if the instance is hosted in a preview window. // This will be set in Init() and will be reset in WillActivatePreviewPage(). bool is_in_preview_mode_ = false;
diff --git a/content/test/mock_render_widget_host_delegate.cc b/content/test/mock_render_widget_host_delegate.cc index f482796b..137299b 100644 --- a/content/test/mock_render_widget_host_delegate.cc +++ b/content/test/mock_render_widget_host_delegate.cc
@@ -105,14 +105,6 @@ void MockRenderWidgetHostDelegate::OnInputIgnored( const blink::WebInputEvent& event) {} -input::mojom::RenderInputRouterDelegate* -MockRenderWidgetHostDelegate::GetRenderInputRouterDelegateRemote() { - if (!rir_delegate_remote_.is_bound()) { - return nullptr; - } - return rir_delegate_remote_.get(); -} - input::TouchEmulator* MockRenderWidgetHostDelegate::GetTouchEmulator( bool create_if_necessary) { NOTIMPLEMENTED();
diff --git a/content/test/mock_render_widget_host_delegate.h b/content/test/mock_render_widget_host_delegate.h index 5817de9..c04ca2f 100644 --- a/content/test/mock_render_widget_host_delegate.h +++ b/content/test/mock_render_widget_host_delegate.h
@@ -44,10 +44,6 @@ KeyboardEventProcessingResult result) { pre_handle_keyboard_event_result_ = result; } - void set_render_input_router_delegate_remote( - mojo::PendingRemote<input::mojom::RenderInputRouterDelegate> remote) { - rir_delegate_remote_.Bind(std::move(remote)); - } void CreateInputEventRouter(); @@ -78,8 +74,6 @@ gfx::mojom::DelegatedInkPointRenderer* GetDelegatedInkRenderer( ui::Compositor* compositor) override; void OnInputIgnored(const blink::WebInputEvent& event) override; - input::mojom::RenderInputRouterDelegate* GetRenderInputRouterDelegateRemote() - override; // RenderWidgetHostInputEventRouter::Delegate input::TouchEmulator* GetTouchEmulator(bool create_if_necessary) override; @@ -96,7 +90,6 @@ raw_ptr<RenderWidgetHostImpl, DanglingUntriaged> focused_widget_ = nullptr; KeyboardEventProcessingResult pre_handle_keyboard_event_result_ = KeyboardEventProcessingResult::NOT_HANDLED; - mojo::Remote<input::mojom::RenderInputRouterDelegate> rir_delegate_remote_; StubRenderViewHostDelegateView rvh_delegate_view_; VisibleTimeRequestTrigger visible_time_request_trigger_; };
diff --git a/content/test/test_select_url_fenced_frame_config_observer_impl.cc b/content/test/test_select_url_fenced_frame_config_observer_impl.cc index db9fd41..a932736 100644 --- a/content/test/test_select_url_fenced_frame_config_observer_impl.cc +++ b/content/test/test_select_url_fenced_frame_config_observer_impl.cc
@@ -64,7 +64,6 @@ base::TimeDelta execution_time, AccessMethod method, int operation_id, - int worklet_ordinal_id, const base::UnguessableToken& worklet_devtools_token, GlobalRenderFrameHostId main_frame_id, const std::string& owner_origin) {}
diff --git a/content/test/test_select_url_fenced_frame_config_observer_impl.h b/content/test/test_select_url_fenced_frame_config_observer_impl.h index 5a15c1b4..f31338d 100644 --- a/content/test/test_select_url_fenced_frame_config_observer_impl.h +++ b/content/test/test_select_url_fenced_frame_config_observer_impl.h
@@ -38,7 +38,6 @@ base::TimeDelta execution_time, AccessMethod method, int operation_id, - int worklet_ordinal_id, const base::UnguessableToken& worklet_devtools_token, GlobalRenderFrameHostId main_frame_id, const std::string& owner_origin) override;
diff --git a/docs/updater/functional_spec.md b/docs/updater/functional_spec.md index 101a956..c041448 100644 --- a/docs/updater/functional_spec.md +++ b/docs/updater/functional_spec.md
@@ -1004,6 +1004,9 @@ be disabled by policy. * If the update check period is set to zero, the updater is qualified without an update check. +* Major/Minor version rollout policy values are sent to the update server to + indicate a preference for taking updates early or late in any gradual rollout + process. Refer to chrome/updater/protos/omaha\_settings.proto for more details.
diff --git a/gpu/command_buffer/service/memory_program_cache_unittest.cc b/gpu/command_buffer/service/memory_program_cache_unittest.cc index 6179e92..ab43645 100644 --- a/gpu/command_buffer/service/memory_program_cache_unittest.cc +++ b/gpu/command_buffer/service/memory_program_cache_unittest.cc
@@ -2,21 +2,22 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "gpu/command_buffer/service/memory_program_cache.h" #include <stddef.h> #include <stdint.h> +#include <array> #include <memory> +#include <numeric> +#include "base/compiler_specific.h" #include "base/containers/heap_array.h" +#include "base/containers/span.h" #include "base/functional/bind.h" #include "base/memory/raw_ptr.h" +#include "base/memory/raw_span.h" +#include "base/numerics/safe_conversions.h" #include "build/build_config.h" #include "gpu/command_buffer/common/gles2_cmd_format.h" #include "gpu/command_buffer/common/shm_count.h" @@ -38,12 +39,8 @@ class ProgramBinaryEmulator { public: - ProgramBinaryEmulator(GLsizei length, - GLenum format, - const char* binary) - : length_(length), - format_(format), - binary_(binary) { } + ProgramBinaryEmulator(GLenum format, base::span<const char> binary) + : format_(format), binary_(binary) {} void GetProgramBinary(GLuint program, GLsizei buffer_size, @@ -51,28 +48,42 @@ GLenum* format, GLvoid* binary) { if (length) { - *length = length_; + *length = binary_.size(); } *format = format_; - memcpy(binary, binary_, length_); + + // SAFETY: This is an OpenGL entry point and cannot be spanified: + // https://docs.gl/es3/glGetProgramBinary + // We can only trust what we're given. + base::span<char> out_arg = + UNSAFE_BUFFERS(base::span(static_cast<char*>(binary), binary_.size())); + out_arg.copy_from(binary_); } void ProgramBinary(GLuint program, GLenum format, const GLvoid* binary, GLsizei length) { + size_t unsigned_length = base::checked_cast<size_t>(length); + + // SAFETY: This is an OpenGL entry point and cannot be spanified: + // https://docs.gl/es3/glProgramBinary + // We can only trust what we're given. + base::span<const char> cast_binary = UNSAFE_BUFFERS( + base::span(static_cast<const char*>(binary), unsigned_length)); + // format and length are verified by matcher - EXPECT_EQ(0, memcmp(binary_, binary, length)); + EXPECT_EQ(binary_.first(unsigned_length), + cast_binary.first(unsigned_length)); } - GLsizei length() const { return length_; } + GLsizei length() const { return binary_.size(); } GLenum format() const { return format_; } - const char* binary() const { return binary_; } + const char* binary() const { return binary_.data(); } private: - GLsizei length_; GLenum format_; - const char* binary_; + base::raw_span<const char> binary_; }; class MemoryProgramCacheTest : public GpuServiceTest, public DecoderClient { @@ -223,15 +234,21 @@ std::vector<std::string> varyings_; }; +namespace { + +std::array<char, 20> TwentyIncrementingChars() { + std::array<char, 20> chars; + std::iota(chars.begin(), chars.end(), 0); + return chars; +} + +} // namespace + TEST_F(MemoryProgramCacheTest, CacheSave) { const GLenum kFormat = 1; const int kProgramId = 10; - const int kBinaryLength = 20; - char test_binary[kBinaryLength]; - for (int i = 0; i < kBinaryLength; ++i) { - test_binary[i] = i; - } - ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary); + const auto test_binary = TwentyIncrementingChars(); + ProgramBinaryEmulator emulator(kFormat, test_binary); SetExpectationsForSaveLinkedProgram(kProgramId, &emulator); cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, @@ -248,12 +265,8 @@ TEST_F(MemoryProgramCacheTest, LoadProgram) { const GLenum kFormat = 1; const int kProgramId = 10; - const int kBinaryLength = 20; - char test_binary[kBinaryLength]; - for (int i = 0; i < kBinaryLength; ++i) { - test_binary[i] = i; - } - ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary); + const auto test_binary = TwentyIncrementingChars(); + ProgramBinaryEmulator emulator(kFormat, test_binary); SetExpectationsForSaveLinkedProgram(kProgramId, &emulator); cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, @@ -280,12 +293,8 @@ TEST_F(MemoryProgramCacheTest, CacheLoadMatchesSave) { const GLenum kFormat = 1; const int kProgramId = 10; - const int kBinaryLength = 20; - char test_binary[kBinaryLength]; - for (int i = 0; i < kBinaryLength; ++i) { - test_binary[i] = i; - } - ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary); + const auto test_binary = TwentyIncrementingChars(); + ProgramBinaryEmulator emulator(kFormat, test_binary); SetExpectationsForSaveLinkedProgram(kProgramId, &emulator); cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, @@ -337,12 +346,8 @@ TEST_F(MemoryProgramCacheTest, LoadProgramMatchesSave) { const GLenum kFormat = 1; const int kProgramId = 10; - const int kBinaryLength = 20; - char test_binary[kBinaryLength]; - for (int i = 0; i < kBinaryLength; ++i) { - test_binary[i] = i; - } - ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary); + const auto test_binary = TwentyIncrementingChars(); + ProgramBinaryEmulator emulator(kFormat, test_binary); SetExpectationsForSaveLinkedProgram(kProgramId, &emulator); cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, @@ -399,12 +404,8 @@ TEST_F(MemoryProgramCacheTest, LoadFailOnLinkFalse) { const GLenum kFormat = 1; const int kProgramId = 10; - const int kBinaryLength = 20; - char test_binary[kBinaryLength]; - for (int i = 0; i < kBinaryLength; ++i) { - test_binary[i] = i; - } - ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary); + const auto test_binary = TwentyIncrementingChars(); + ProgramBinaryEmulator emulator(kFormat, test_binary); SetExpectationsForSaveLinkedProgram(kProgramId, &emulator); cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, @@ -420,12 +421,8 @@ TEST_F(MemoryProgramCacheTest, LoadFailOnDifferentSource) { const GLenum kFormat = 1; const int kProgramId = 10; - const int kBinaryLength = 20; - char test_binary[kBinaryLength]; - for (int i = 0; i < kBinaryLength; ++i) { - test_binary[i] = i; - } - ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary); + const auto test_binary = TwentyIncrementingChars(); + ProgramBinaryEmulator emulator(kFormat, test_binary); SetExpectationsForSaveLinkedProgram(kProgramId, &emulator); cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, @@ -452,12 +449,8 @@ TEST_F(MemoryProgramCacheTest, LoadFailOnDifferentMap) { const GLenum kFormat = 1; const int kProgramId = 10; - const int kBinaryLength = 20; - char test_binary[kBinaryLength]; - for (int i = 0; i < kBinaryLength; ++i) { - test_binary[i] = i; - } - ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary); + const auto test_binary = TwentyIncrementingChars(); + ProgramBinaryEmulator emulator(kFormat, test_binary); SetExpectationsForSaveLinkedProgram(kProgramId, &emulator); ProgramCache::LocationMap binding_map; @@ -479,12 +472,8 @@ TEST_F(MemoryProgramCacheTest, LoadFailOnDifferentTransformFeedbackVaryings) { const GLenum kFormat = 1; const int kProgramId = 10; - const int kBinaryLength = 20; - char test_binary[kBinaryLength]; - for (int i = 0; i < kBinaryLength; ++i) { - test_binary[i] = i; - } - ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary); + const auto test_binary = TwentyIncrementingChars(); + ProgramBinaryEmulator emulator(kFormat, test_binary); SetExpectationsForSaveLinkedProgram(kProgramId, &emulator); varyings_.push_back("test"); @@ -506,12 +495,8 @@ TEST_F(MemoryProgramCacheTest, LoadFailIfTransformFeedbackCachingDisabled) { const GLenum kFormat = 1; const int kProgramId = 10; - const int kBinaryLength = 20; - char test_binary[kBinaryLength]; - for (int i = 0; i < kBinaryLength; ++i) { - test_binary[i] = i; - } - ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary); + const auto test_binary = TwentyIncrementingChars(); + ProgramBinaryEmulator emulator(kFormat, test_binary); // Forcibly reset the program cache so we can disable caching of // programs which include transform feedback varyings. @@ -529,20 +514,15 @@ TEST_F(MemoryProgramCacheTest, MemoryProgramCacheEviction) { const GLenum kFormat = 1; const int kProgramId = 10; - const int kBinaryLength = 20; - char test_binary[kBinaryLength]; - for (int i = 0; i < kBinaryLength; ++i) { - test_binary[i] = i; - } - ProgramBinaryEmulator emulator1(kBinaryLength, kFormat, test_binary); - + const auto test_binary = TwentyIncrementingChars(); + ProgramBinaryEmulator emulator1(kFormat, test_binary); SetExpectationsForSaveLinkedProgram(kProgramId, &emulator1); cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, nullptr, varyings_, GL_NONE, this); const int kEvictingProgramId = 11; - const GLuint kEvictingBinaryLength = kCacheSizeBytes - kBinaryLength + 1; + const GLuint kEvictingBinaryLength = kCacheSizeBytes - test_binary.size() + 1; // save old source and modify for new program const std::string& old_sig = fragment_shader_->last_compiled_signature(); @@ -553,8 +533,7 @@ for (size_t i = 0; i < kEvictingBinaryLength; ++i) { bigTestBinary[i] = i % 250; } - ProgramBinaryEmulator emulator2(kEvictingBinaryLength, kFormat, - bigTestBinary.data()); + ProgramBinaryEmulator emulator2(kFormat, bigTestBinary); SetExpectationsForSaveLinkedProgram(kEvictingProgramId, &emulator2); cache_->SaveLinkedProgram(kEvictingProgramId, vertex_shader_, @@ -575,12 +554,8 @@ TEST_F(MemoryProgramCacheTest, SaveCorrectProgram) { const GLenum kFormat = 1; const int kProgramId = 10; - const int kBinaryLength = 20; - char test_binary[kBinaryLength]; - for (int i = 0; i < kBinaryLength; ++i) { - test_binary[i] = i; - } - ProgramBinaryEmulator emulator1(kBinaryLength, kFormat, test_binary); + const auto test_binary = TwentyIncrementingChars(); + ProgramBinaryEmulator emulator1(kFormat, test_binary); vertex_shader_->set_source("different!"); SetExpectationsForSaveLinkedProgram(kProgramId, &emulator1); @@ -597,12 +572,8 @@ TEST_F(MemoryProgramCacheTest, LoadCorrectProgram) { const GLenum kFormat = 1; const int kProgramId = 10; - const int kBinaryLength = 20; - char test_binary[kBinaryLength]; - for (int i = 0; i < kBinaryLength; ++i) { - test_binary[i] = i; - } - ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary); + const auto test_binary = TwentyIncrementingChars(); + ProgramBinaryEmulator emulator(kFormat, test_binary); SetExpectationsForSaveLinkedProgram(kProgramId, &emulator); cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, @@ -626,22 +597,18 @@ TEST_F(MemoryProgramCacheTest, OverwriteOnNewSave) { const GLenum kFormat = 1; const int kProgramId = 10; - const int kBinaryLength = 20; - char test_binary[kBinaryLength]; - for (int i = 0; i < kBinaryLength; ++i) { - test_binary[i] = i; - } - ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary); + const auto test_binary = TwentyIncrementingChars(); + ProgramBinaryEmulator emulator(kFormat, test_binary); SetExpectationsForSaveLinkedProgram(kProgramId, &emulator); cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, nullptr, varyings_, GL_NONE, this); - char test_binary2[kBinaryLength]; - for (int i = 0; i < kBinaryLength; ++i) { + std::array<char, test_binary.size()> test_binary2; + for (size_t i = 0; i < test_binary.size(); ++i) { test_binary2[i] = (i*2) % 250; } - ProgramBinaryEmulator emulator2(kBinaryLength, kFormat, test_binary2); + ProgramBinaryEmulator emulator2(kFormat, test_binary2); SetExpectationsForSaveLinkedProgram(kProgramId, &emulator2); cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, nullptr, varyings_, GL_NONE, this); @@ -657,12 +624,8 @@ // Insert a 20 byte program. const GLenum kFormat = 1; const int kProgramId = 10; - const int kBinaryLength = 20; - char test_binary[kBinaryLength]; - for (int i = 0; i < kBinaryLength; ++i) { - test_binary[i] = i; - } - ProgramBinaryEmulator emulator1(kBinaryLength, kFormat, test_binary); + const auto test_binary = TwentyIncrementingChars(); + ProgramBinaryEmulator emulator1(kFormat, test_binary); SetExpectationsForSaveLinkedProgram(kProgramId, &emulator1); cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, @@ -674,7 +637,7 @@ fragment_shader_->set_source("al sdfkjdk"); TestHelper::SetShaderStates(gl_.get(), fragment_shader_, true); - ProgramBinaryEmulator emulator2(kBinaryLength, kFormat, test_binary); + ProgramBinaryEmulator emulator2(kFormat, test_binary); SetExpectationsForSaveLinkedProgram(kSecondProgramId, &emulator2); cache_->SaveLinkedProgram(kSecondProgramId, vertex_shader_, fragment_shader_,
diff --git a/infra/config/generated/builder-owners/chrome-blink-engprod@google.com.txt b/infra/config/generated/builder-owners/chrome-blink-engprod@google.com.txt index af22ab5..77a0509b 100644 --- a/infra/config/generated/builder-owners/chrome-blink-engprod@google.com.txt +++ b/infra/config/generated/builder-owners/chrome-blink-engprod@google.com.txt
@@ -7,8 +7,6 @@ try/android-chrome-13-x64-wpt-android-specific try/linux-blink-rel try/linux-wpt-chromium-rel -try/mac11.0-blink-rel -try/mac11.0.arm64-blink-rel try/mac12.0-blink-rel try/mac12.0.arm64-blink-rel try/mac13-blink-rel
diff --git a/infra/config/generated/builders/ci/android-15-tablet-landscape-x64-rel/targets/chromium.android.json b/infra/config/generated/builders/ci/android-15-tablet-landscape-x64-rel/targets/chromium.android.json index 0ded41e..8ac1323 100644 --- a/infra/config/generated/builders/ci/android-15-tablet-landscape-x64-rel/targets/chromium.android.json +++ b/infra/config/generated/builders/ci/android-15-tablet-landscape-x64-rel/targets/chromium.android.json
@@ -6,7 +6,6 @@ "--git-revision=${got_revision}", "--avd-config=../../tools/android/avd/proto/android_35_google_apis_x64_tablet_landscape.textpb", "--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_15_tablet_landscape.chrome_public_test_apk.filter", - "--emulator-debug-tags=all", "--gs-results-bucket=chromium-result-details", "--recover-devices" ],
diff --git a/infra/config/generated/builders/ci/android-15-tablet-x64-rel/targets/chromium.android.json b/infra/config/generated/builders/ci/android-15-tablet-x64-rel/targets/chromium.android.json index bd9d0f6..927e2ff 100644 --- a/infra/config/generated/builders/ci/android-15-tablet-x64-rel/targets/chromium.android.json +++ b/infra/config/generated/builders/ci/android-15-tablet-x64-rel/targets/chromium.android.json
@@ -51,6 +51,7 @@ "args": [ "--avd-config=../../tools/android/avd/proto/android_35_google_apis_x64_tablet.textpb", "--gtest_filter=-InstallableManagerBrowserTest.CheckManifestWithIconThatIsTooSmall", + "--emulator-debug-tags=all", "--gs-results-bucket=chromium-result-details", "--recover-devices" ],
diff --git a/infra/config/generated/builders/gn_args_locations.json b/infra/config/generated/builders/gn_args_locations.json index 0f7a484..465d999 100644 --- a/infra/config/generated/builders/gn_args_locations.json +++ b/infra/config/generated/builders/gn_args_locations.json
@@ -536,8 +536,6 @@ "linux-blink-rel": "try/linux-blink-rel/gn-args.json", "linux-wpt-chromium-rel": "try/linux-wpt-chromium-rel/gn-args.json", "mac-skia-alt-arm64-blink-rel": "try/mac-skia-alt-arm64-blink-rel/gn-args.json", - "mac11.0-blink-rel": "try/mac11.0-blink-rel/gn-args.json", - "mac11.0.arm64-blink-rel": "try/mac11.0.arm64-blink-rel/gn-args.json", "mac12.0-blink-rel": "try/mac12.0-blink-rel/gn-args.json", "mac12.0.arm64-blink-rel": "try/mac12.0.arm64-blink-rel/gn-args.json", "mac13-blink-rel": "try/mac13-blink-rel/gn-args.json",
diff --git a/infra/config/generated/builders/try/android-15-tablet-landscape-x64-rel/targets/chromium.android.json b/infra/config/generated/builders/try/android-15-tablet-landscape-x64-rel/targets/chromium.android.json index 0ded41e..8ac1323 100644 --- a/infra/config/generated/builders/try/android-15-tablet-landscape-x64-rel/targets/chromium.android.json +++ b/infra/config/generated/builders/try/android-15-tablet-landscape-x64-rel/targets/chromium.android.json
@@ -6,7 +6,6 @@ "--git-revision=${got_revision}", "--avd-config=../../tools/android/avd/proto/android_35_google_apis_x64_tablet_landscape.textpb", "--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_15_tablet_landscape.chrome_public_test_apk.filter", - "--emulator-debug-tags=all", "--gs-results-bucket=chromium-result-details", "--recover-devices" ],
diff --git a/infra/config/generated/builders/try/android-15-tablet-x64-rel/targets/chromium.android.json b/infra/config/generated/builders/try/android-15-tablet-x64-rel/targets/chromium.android.json index bd9d0f6..927e2ff 100644 --- a/infra/config/generated/builders/try/android-15-tablet-x64-rel/targets/chromium.android.json +++ b/infra/config/generated/builders/try/android-15-tablet-x64-rel/targets/chromium.android.json
@@ -51,6 +51,7 @@ "args": [ "--avd-config=../../tools/android/avd/proto/android_35_google_apis_x64_tablet.textpb", "--gtest_filter=-InstallableManagerBrowserTest.CheckManifestWithIconThatIsTooSmall", + "--emulator-debug-tags=all", "--gs-results-bucket=chromium-result-details", "--recover-devices" ],
diff --git a/infra/config/generated/builders/try/mac11.0-blink-rel/gn-args.json b/infra/config/generated/builders/try/mac11.0-blink-rel/gn-args.json deleted file mode 100644 index 7633088c..0000000 --- a/infra/config/generated/builders/try/mac11.0-blink-rel/gn-args.json +++ /dev/null
@@ -1,15 +0,0 @@ -{ - "gn_args": { - "dcheck_always_on": false, - "ffmpeg_branding": "Chrome", - "is_component_build": false, - "is_debug": false, - "proprietary_codecs": true, - "symbol_level": 1, - "target_cpu": "x64", - "target_os": "mac", - "use_reclient": false, - "use_remoteexec": true, - "use_siso": true - } -} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/mac11.0-blink-rel/properties.json b/infra/config/generated/builders/try/mac11.0-blink-rel/properties.json deleted file mode 100644 index 5db11717..0000000 --- a/infra/config/generated/builders/try/mac11.0-blink-rel/properties.json +++ /dev/null
@@ -1,66 +0,0 @@ -{ - "$build/chromium_tests_builder_config": { - "builder_config": { - "additional_exclusions": [ - "infra/config/generated/builders/try/mac11.0-blink-rel/gn-args.json" - ], - "builder_db": { - "entries": [ - { - "builder_id": { - "bucket": "try", - "builder": "mac11.0-blink-rel", - "project": "chromium" - }, - "builder_spec": { - "builder_group": "tryserver.blink", - "execution_mode": "COMPILE_AND_TEST", - "legacy_chromium_config": { - "apply_configs": [ - "mb" - ], - "build_config": "Release", - "config": "chromium", - "target_bits": 64, - "target_platform": "mac" - }, - "legacy_gclient_config": { - "config": "chromium" - } - } - } - ] - }, - "builder_ids": [ - { - "bucket": "try", - "builder": "mac11.0-blink-rel", - "project": "chromium" - } - ], - "retry_failed_shards": true, - "targets_spec_directory": "src/infra/config/generated/builders/try/mac11.0-blink-rel/targets" - } - }, - "$build/siso": { - "configs": [ - "builder" - ], - "enable_cloud_monitoring": true, - "enable_cloud_profiler": true, - "enable_cloud_trace": true, - "experiments": [], - "metrics_project": "chromium-reclient-metrics", - "project": "rbe-chromium-untrusted", - "remote_jobs": 150 - }, - "$recipe_engine/resultdb/test_presentation": { - "column_keys": [], - "grouping_keys": [ - "status", - "v.test_suite" - ] - }, - "builder_group": "tryserver.blink", - "recipe": "chromium_trybot" -} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/mac11.0-blink-rel/targets/tryserver.blink.json b/infra/config/generated/builders/try/mac11.0-blink-rel/targets/tryserver.blink.json deleted file mode 100644 index e25709c..0000000 --- a/infra/config/generated/builders/try/mac11.0-blink-rel/targets/tryserver.blink.json +++ /dev/null
@@ -1,123 +0,0 @@ -{ - "mac11.0-blink-rel": { - "isolated_scripts": [ - { - "args": [ - "--num-retries=3", - "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json" - ], - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "blink_web_tests", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "results_handler": "layout tests", - "swarming": { - "dimensions": { - "cpu": "x86-64", - "os": "Mac-11" - }, - "hard_timeout": 2400, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 5 - }, - "test": "blink_web_tests", - "test_id_prefix": "ninja://:blink_web_tests/" - }, - { - "args": [ - "--num-retries=3", - "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json" - ], - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "blink_wpt_tests", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "results_handler": "layout tests", - "swarming": { - "dimensions": { - "cpu": "x86-64", - "os": "Mac-11" - }, - "hard_timeout": 2400, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 - }, - "test": "blink_wpt_tests", - "test_id_prefix": "ninja://:blink_wpt_tests/" - }, - { - "args": [ - "--test-launcher-filter-file=../../third_party/blink/web_tests/TestLists/chrome.filter" - ], - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "chrome_wpt_tests", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "results_handler": "layout tests", - "swarming": { - "dimensions": { - "cpu": "x86-64", - "os": "Mac-11" - }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "chrome_wpt_tests", - "test_id_prefix": "ninja://:chrome_wpt_tests/" - }, - { - "args": [ - "--test-type", - "testharness", - "reftest", - "crashtest", - "print-reftest", - "--inverted-test-launcher-filter-file=../../third_party/blink/web_tests/TestLists/chrome.filter", - "--inverted-test-launcher-filter-file=../../third_party/blink/web_tests/TestLists/content_shell.filter" - ], - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "headless_shell_wpt_tests", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "results_handler": "layout tests", - "swarming": { - "dimensions": { - "cpu": "x86-64", - "os": "Mac-11" - }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 18 - }, - "test": "headless_shell_wpt", - "test_id_prefix": "ninja://:headless_shell_wpt/" - } - ] - } -} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/mac11.0.arm64-blink-rel/gn-args.json b/infra/config/generated/builders/try/mac11.0.arm64-blink-rel/gn-args.json deleted file mode 100644 index 754fd51b..0000000 --- a/infra/config/generated/builders/try/mac11.0.arm64-blink-rel/gn-args.json +++ /dev/null
@@ -1,15 +0,0 @@ -{ - "gn_args": { - "dcheck_always_on": false, - "ffmpeg_branding": "Chrome", - "is_component_build": false, - "is_debug": false, - "proprietary_codecs": true, - "symbol_level": 1, - "target_cpu": "arm64", - "target_os": "mac", - "use_reclient": false, - "use_remoteexec": true, - "use_siso": true - } -} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/mac11.0.arm64-blink-rel/properties.json b/infra/config/generated/builders/try/mac11.0.arm64-blink-rel/properties.json deleted file mode 100644 index 4990b08f..0000000 --- a/infra/config/generated/builders/try/mac11.0.arm64-blink-rel/properties.json +++ /dev/null
@@ -1,67 +0,0 @@ -{ - "$build/chromium_tests_builder_config": { - "builder_config": { - "additional_exclusions": [ - "infra/config/generated/builders/try/mac11.0.arm64-blink-rel/gn-args.json" - ], - "builder_db": { - "entries": [ - { - "builder_id": { - "bucket": "try", - "builder": "mac11.0.arm64-blink-rel", - "project": "chromium" - }, - "builder_spec": { - "build_gs_bucket": "chromium-fyi-archive", - "builder_group": "tryserver.blink", - "execution_mode": "COMPILE_AND_TEST", - "legacy_chromium_config": { - "apply_configs": [ - "mb" - ], - "build_config": "Release", - "config": "chromium", - "target_bits": 64, - "target_platform": "mac" - }, - "legacy_gclient_config": { - "config": "chromium" - } - } - } - ] - }, - "builder_ids": [ - { - "bucket": "try", - "builder": "mac11.0.arm64-blink-rel", - "project": "chromium" - } - ], - "retry_failed_shards": true, - "targets_spec_directory": "src/infra/config/generated/builders/try/mac11.0.arm64-blink-rel/targets" - } - }, - "$build/siso": { - "configs": [ - "builder" - ], - "enable_cloud_monitoring": true, - "enable_cloud_profiler": true, - "enable_cloud_trace": true, - "experiments": [], - "metrics_project": "chromium-reclient-metrics", - "project": "rbe-chromium-untrusted", - "remote_jobs": 150 - }, - "$recipe_engine/resultdb/test_presentation": { - "column_keys": [], - "grouping_keys": [ - "status", - "v.test_suite" - ] - }, - "builder_group": "tryserver.blink", - "recipe": "chromium_trybot" -} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/mac11.0.arm64-blink-rel/targets/tryserver.blink.json b/infra/config/generated/builders/try/mac11.0.arm64-blink-rel/targets/tryserver.blink.json deleted file mode 100644 index 9065399..0000000 --- a/infra/config/generated/builders/try/mac11.0.arm64-blink-rel/targets/tryserver.blink.json +++ /dev/null
@@ -1,123 +0,0 @@ -{ - "mac11.0.arm64-blink-rel": { - "isolated_scripts": [ - { - "args": [ - "--num-retries=3", - "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json" - ], - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "blink_web_tests", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "results_handler": "layout tests", - "swarming": { - "dimensions": { - "cpu": "arm64", - "os": "Mac-11" - }, - "hard_timeout": 2400, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 5 - }, - "test": "blink_web_tests", - "test_id_prefix": "ninja://:blink_web_tests/" - }, - { - "args": [ - "--num-retries=3", - "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json" - ], - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "blink_wpt_tests", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "results_handler": "layout tests", - "swarming": { - "dimensions": { - "cpu": "arm64", - "os": "Mac-11" - }, - "hard_timeout": 2400, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 - }, - "test": "blink_wpt_tests", - "test_id_prefix": "ninja://:blink_wpt_tests/" - }, - { - "args": [ - "--test-launcher-filter-file=../../third_party/blink/web_tests/TestLists/chrome.filter" - ], - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "chrome_wpt_tests", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "results_handler": "layout tests", - "swarming": { - "dimensions": { - "cpu": "arm64", - "os": "Mac-11" - }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "chrome_wpt_tests", - "test_id_prefix": "ninja://:chrome_wpt_tests/" - }, - { - "args": [ - "--test-type", - "testharness", - "reftest", - "crashtest", - "print-reftest", - "--inverted-test-launcher-filter-file=../../third_party/blink/web_tests/TestLists/chrome.filter", - "--inverted-test-launcher-filter-file=../../third_party/blink/web_tests/TestLists/content_shell.filter" - ], - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "headless_shell_wpt_tests", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "results_handler": "layout tests", - "swarming": { - "dimensions": { - "cpu": "arm64", - "os": "Mac-11" - }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 18 - }, - "test": "headless_shell_wpt", - "test_id_prefix": "ninja://:headless_shell_wpt/" - } - ] - } -} \ No newline at end of file
diff --git a/infra/config/generated/luci/commit-queue.cfg b/infra/config/generated/luci/commit-queue.cfg index 5093fba6..14e2214 100644 --- a/infra/config/generated/luci/commit-queue.cfg +++ b/infra/config/generated/luci/commit-queue.cfg
@@ -6495,16 +6495,6 @@ disable_reuse_footers: "Include-Ci-Only-Tests" } builders { - name: "chromium/try/mac11.0-blink-rel" - includable_only: true - disable_reuse_footers: "Include-Ci-Only-Tests" - } - builders { - name: "chromium/try/mac11.0.arm64-blink-rel" - includable_only: true - disable_reuse_footers: "Include-Ci-Only-Tests" - } - builders { name: "chromium/try/mac12-arm64-rel" includable_only: true disable_reuse_footers: "Include-Ci-Only-Tests"
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index e94fe87..a979963 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -123147,227 +123147,6 @@ } } builders { - name: "mac11.0-blink-rel" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:mac11.0-blink-rel" - dimensions: "cpu:x86-64" - dimensions: "os:Mac-15" - dimensions: "pool:luci.chromium.try" - dimensions: "ssd:1" - exe { - cipd_package: "infra/chromium/bootstrapper/${platform}" - cipd_version: "latest" - cmd: "bootstrapper" - } - properties: - '{' - ' "$bootstrap/exe": {' - ' "exe": {' - ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' - ' "cipd_version": "refs/heads/main",' - ' "cmd": [' - ' "luciexe"' - ' ]' - ' }' - ' },' - ' "$bootstrap/properties": {' - ' "properties_file": "infra/config/generated/builders/try/mac11.0-blink-rel/properties.json",' - ' "top_level_project": {' - ' "ref": "refs/heads/main",' - ' "repo": {' - ' "host": "chromium.googlesource.com",' - ' "project": "chromium/src"' - ' }' - ' }' - ' },' - ' "builder_group": "tryserver.blink",' - ' "led_builder_is_bootstrapped": true,' - ' "recipe": "chromium_trybot"' - '}' - execution_timeout_secs: 14400 - expiration_secs: 7200 - grace_period { - seconds: 120 - } - build_numbers: YES - service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "chromium.use_per_builder_build_dir_name" - value: 100 - } - experiments { - key: "luci.buildbucket.canary_software" - value: 5 - } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - resultdb { - enable: true - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "try_test_results" - test_results {} - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "gpu_try_test_results" - test_results { - predicate { - test_id_regexp: "ninja://(chrome|content)/test:telemetry_gpu_integration_test[^/]*/.+" - } - } - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "blink_web_tests_try_test_results" - test_results { - predicate { - test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*_wpt_tests/.+)|(ninja://[^/]*headless_shell_wpt/.+)" - } - } - } - history_options { - use_invocation_timestamp: true - } - } - description_html: "Standalone try builder that <a href=\"https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/web_test_expectations.md#rebaselining-using-try-jobs\">generates new expectations</a> for web platform changes.<br/>Builder owner: <a href=mailto:chrome-blink-engprod@google.com>chrome-blink-engprod@google.com</a>" - contact_team_email: "chrome-blink-engprod@google.com" - custom_metric_definitions { - name: "/chrome/infra/browser/builds/cached_count" - predicates: "has(build.output.properties.is_cached)" - predicates: "string(build.output.properties.is_cached) == \"true\"" - } - custom_metric_definitions { - name: "/chrome/infra/browser/builds/ran_tests_retry_shard_count" - predicates: "has(build.output.properties.ran_tests_retry_shard)" - } - custom_metric_definitions { - name: "/chrome/infra/browser/builds/ran_tests_without_patch_count" - predicates: "has(build.output.properties.ran_tests_without_patch)" - } - custom_metric_definitions { - name: "/chrome/infra/browser/builds/uncached_count" - predicates: "has(build.output.properties.is_cached)" - predicates: "string(build.output.properties.is_cached) == \"false\"" - } - } - builders { - name: "mac11.0.arm64-blink-rel" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "builderless:1" - dimensions: "cpu:arm64" - dimensions: "free_space:standard" - dimensions: "os:Mac-15" - dimensions: "pool:luci.chromium.try" - dimensions: "ssd:1" - exe { - cipd_package: "infra/chromium/bootstrapper/${platform}" - cipd_version: "latest" - cmd: "bootstrapper" - } - properties: - '{' - ' "$bootstrap/exe": {' - ' "exe": {' - ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' - ' "cipd_version": "refs/heads/main",' - ' "cmd": [' - ' "luciexe"' - ' ]' - ' }' - ' },' - ' "$bootstrap/properties": {' - ' "properties_file": "infra/config/generated/builders/try/mac11.0.arm64-blink-rel/properties.json",' - ' "top_level_project": {' - ' "ref": "refs/heads/main",' - ' "repo": {' - ' "host": "chromium.googlesource.com",' - ' "project": "chromium/src"' - ' }' - ' }' - ' },' - ' "builder_group": "tryserver.blink",' - ' "led_builder_is_bootstrapped": true,' - ' "recipe": "chromium_trybot"' - '}' - execution_timeout_secs: 14400 - expiration_secs: 7200 - grace_period { - seconds: 120 - } - build_numbers: YES - service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "chromium.use_per_builder_build_dir_name" - value: 100 - } - experiments { - key: "luci.buildbucket.canary_software" - value: 5 - } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - resultdb { - enable: true - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "try_test_results" - test_results {} - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "gpu_try_test_results" - test_results { - predicate { - test_id_regexp: "ninja://(chrome|content)/test:telemetry_gpu_integration_test[^/]*/.+" - } - } - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "blink_web_tests_try_test_results" - test_results { - predicate { - test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*_wpt_tests/.+)|(ninja://[^/]*headless_shell_wpt/.+)" - } - } - } - history_options { - use_invocation_timestamp: true - } - } - description_html: "Standalone try builder that <a href=\"https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/web_test_expectations.md#rebaselining-using-try-jobs\">generates new expectations</a> for web platform changes.<br/>Builder owner: <a href=mailto:chrome-blink-engprod@google.com>chrome-blink-engprod@google.com</a>" - contact_team_email: "chrome-blink-engprod@google.com" - custom_metric_definitions { - name: "/chrome/infra/browser/builds/cached_count" - predicates: "has(build.output.properties.is_cached)" - predicates: "string(build.output.properties.is_cached) == \"true\"" - } - custom_metric_definitions { - name: "/chrome/infra/browser/builds/ran_tests_retry_shard_count" - predicates: "has(build.output.properties.ran_tests_retry_shard)" - } - custom_metric_definitions { - name: "/chrome/infra/browser/builds/ran_tests_without_patch_count" - predicates: "has(build.output.properties.ran_tests_without_patch)" - } - custom_metric_definitions { - name: "/chrome/infra/browser/builds/uncached_count" - predicates: "has(build.output.properties.is_cached)" - predicates: "string(build.output.properties.is_cached) == \"false\"" - } - } - builders { name: "mac12-arm64-rel" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1"
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg index 112dd73..b5f7f20 100644 --- a/infra/config/generated/luci/luci-milo.cfg +++ b/infra/config/generated/luci/luci-milo.cfg
@@ -27793,12 +27793,6 @@ name: "buildbucket/luci.chromium.try/mac11-arm64-rel" } builders { - name: "buildbucket/luci.chromium.try/mac11.0-blink-rel" - } - builders { - name: "buildbucket/luci.chromium.try/mac11.0.arm64-blink-rel" - } - builders { name: "buildbucket/luci.chromium.try/mac12-arm64-rel" } builders { @@ -28122,12 +28116,6 @@ name: "buildbucket/luci.chromium.try/mac-skia-alt-arm64-blink-rel" } builders { - name: "buildbucket/luci.chromium.try/mac11.0-blink-rel" - } - builders { - name: "buildbucket/luci.chromium.try/mac11.0.arm64-blink-rel" - } - builders { name: "buildbucket/luci.chromium.try/mac12.0-blink-rel" } builders {
diff --git a/infra/config/subprojects/chromium/ci/chromium.android.star b/infra/config/subprojects/chromium/ci/chromium.android.star index 2e737b5d..a837248 100644 --- a/infra/config/subprojects/chromium/ci/chromium.android.star +++ b/infra/config/subprojects/chromium/ci/chromium.android.star
@@ -4483,7 +4483,6 @@ "chrome_public_test_apk": targets.mixin( args = [ "--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_15_tablet_landscape.chrome_public_test_apk.filter", - "--emulator-debug-tags=all", ], ), }, @@ -4554,6 +4553,7 @@ args = [ # https://crbug.com/375086487 "--gtest_filter=-InstallableManagerBrowserTest.CheckManifestWithIconThatIsTooSmall", + "--emulator-debug-tags=all", ], swarming = targets.swarming( shards = 6,
diff --git a/infra/config/subprojects/chromium/try/tryserver.blink.star b/infra/config/subprojects/chromium/try/tryserver.blink.star index 8beef9d..3da43f9 100644 --- a/infra/config/subprojects/chromium/try/tryserver.blink.star +++ b/infra/config/subprojects/chromium/try/tryserver.blink.star
@@ -322,112 +322,6 @@ ) _mac_rebaseline_builder( - name = "mac11.0-blink-rel", - builder_spec = builder_config.builder_spec( - gclient_config = builder_config.gclient_config( - config = "chromium", - ), - chromium_config = builder_config.chromium_config( - config = "chromium", - apply_configs = [ - "mb", - ], - build_config = builder_config.build_config.RELEASE, - target_bits = 64, - target_platform = builder_config.target_platform.MAC, - ), - ), - builder_config_settings = builder_config.try_settings( - retry_failed_shards = True, - ), - gn_args = gn_args.config( - configs = [ - "release_builder", - "remoteexec", - "chrome_with_codecs", - "minimal_symbols", - "mac", - "x64", - ], - ), - targets = targets.bundle( - targets = [ - "chromium_webkit_isolated_scripts", - ], - mixins = [ - "mac_11_x64", - ], - per_test_modifications = { - "blink_wpt_tests": targets.mixin( - swarming = targets.swarming( - hard_timeout_sec = 2400, - ), - ), - "blink_web_tests": targets.mixin( - swarming = targets.swarming( - hard_timeout_sec = 2400, - ), - ), - }, - ), - builderless = False, -) - -_mac_rebaseline_builder( - name = "mac11.0.arm64-blink-rel", - builder_spec = builder_config.builder_spec( - gclient_config = builder_config.gclient_config( - config = "chromium", - ), - chromium_config = builder_config.chromium_config( - config = "chromium", - apply_configs = [ - "mb", - ], - build_config = builder_config.build_config.RELEASE, - target_bits = 64, - target_platform = builder_config.target_platform.MAC, - ), - build_gs_bucket = "chromium-fyi-archive", - ), - builder_config_settings = builder_config.try_settings( - retry_failed_shards = True, - ), - gn_args = gn_args.config( - configs = [ - "release_builder", - "remoteexec", - "chrome_with_codecs", - "arm64", - "minimal_symbols", - "mac", - ], - ), - targets = targets.bundle( - targets = [ - "chromium_webkit_isolated_scripts", - ], - mixins = [ - "mac_11_arm64", - ], - per_test_modifications = { - "blink_wpt_tests": targets.mixin( - swarming = targets.swarming( - hard_timeout_sec = 2400, - ), - ), - "blink_web_tests": targets.mixin( - swarming = targets.swarming( - hard_timeout_sec = 2400, - ), - ), - }, - ), - cores = None, - cpu = cpu.ARM64, -) - -_mac_rebaseline_builder( name = "mac12.0-blink-rel", builder_spec = builder_config.builder_spec( gclient_config = builder_config.gclient_config(
diff --git a/infra/inclusive_language_presubmit_exempt_dirs.txt b/infra/inclusive_language_presubmit_exempt_dirs.txt index a666615..9511d85 100644 --- a/infra/inclusive_language_presubmit_exempt_dirs.txt +++ b/infra/inclusive_language_presubmit_exempt_dirs.txt
@@ -73,7 +73,7 @@ chromecast/media/cma/backend 1 1 chromecast/media/cma/backend/alsa 1 1 chromecast/public 2 1 -chrome/common 4 3 +chrome/common 3 3 chrome/common/chromeos/extensions 2 1 chrome/common/extensions 1 1 chrome/common/extensions/api 2 2
diff --git a/internal b/internal index 6113fc6..0cd9d61 160000 --- a/internal +++ b/internal
@@ -1 +1 @@ -Subproject commit 6113fc67631d1ddb7a8918e5bb92e34d8492710b +Subproject commit 0cd9d611e47ef77b8acd24fba00403d8709bd2da
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index d5a5074..ee57b6d2 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -3053,9 +3053,12 @@ <message name="IDS_IOS_INTENTS_URL_PARAMETER" desc="The URL the user would like to pass as input parameter to Shortcuts that require a URL as input [iOS only]."> URL </message> - <message name="IDS_IOS_IPH_BUBBLE_NEXT" desc="Label of a button that appears in an in-product help Tip. Pressing this button will dismiss the Tip, and the next tip will be shown after dismissal."> + <message name="IDS_IOS_IPH_BUBBLE_GOT_IT" desc="Label of a button that appears in an in-product help Tip. Pressing this button will dismiss the last Tip."> Got it </message> + <message name="IDS_IOS_IPH_BUBBLE_NEXT" desc="Label of a button that appears in an in-product help Tip. Pressing this button will dismiss the Tip, and the next tip will be shown after dismissal."> + Next + </message> <message name="IDS_IOS_IPH_BUBBLE_SNOOZE" desc="Label of a button that appears in an in-product help Tip. Pressing this button will dismiss the Tip, the user will be reminded of the same Tip later on. Used as a button title in an info bubble." meaning="Used as a button title in an info bubble."> Remind me later </message>
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_IPH_BUBBLE_GOT_IT.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_IPH_BUBBLE_GOT_IT.png.sha1 new file mode 100644 index 0000000..beeeaeb --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_IPH_BUBBLE_GOT_IT.png.sha1
@@ -0,0 +1 @@ +6abbed82e279206880683322b8bda366599f7422 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_IPH_BUBBLE_NEXT.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_IPH_BUBBLE_NEXT.png.sha1 index e3e91c4..e4cbd2ef 100644 --- a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_IPH_BUBBLE_NEXT.png.sha1 +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_IPH_BUBBLE_NEXT.png.sha1
@@ -1 +1 @@ -3412f4d8c12f481e7ca0dba98c187544c875c685 \ No newline at end of file +c290332d34d659a498b678596ff0c459abaa5ba4 \ No newline at end of file
diff --git a/ios/chrome/browser/bubble/ui_bundled/bubble_view.mm b/ios/chrome/browser/bubble/ui_bundled/bubble_view.mm index 35a6c5e..6f176576 100644 --- a/ios/chrome/browser/bubble/ui_bundled/bubble_view.mm +++ b/ios/chrome/browser/bubble/ui_bundled/bubble_view.mm
@@ -252,10 +252,12 @@ return label; } -UIButton* BubbleNextButton() { +UIButton* BubbleNextButton(BubblePageControlPage page) { UIButton* button = [UIButton buttonWithType:UIButtonTypeSystem]; button.accessibilityIdentifier = kBubbleViewNextButtonIdentifier; - [button setTitle:l10n_util::GetNSString(IDS_IOS_IPH_BUBBLE_NEXT) + int textID = page == BubblePageControlPageFourth ? IDS_IOS_IPH_BUBBLE_GOT_IT + : IDS_IOS_IPH_BUBBLE_NEXT; + [button setTitle:l10n_util::GetNSString(textID) forState:UIControlStateNormal]; [button setTitleColor:[UIColor colorNamed:kSolidButtonTextColor] forState:UIControlStateNormal]; @@ -406,7 +408,7 @@ _separator.translatesAutoresizingMaskIntoConstraints = NO; _separator.backgroundColor = [UIColor colorNamed:kSeparatorColor]; [self addSubview:_separator]; - _nextButton = BubbleNextButton(); + _nextButton = BubbleNextButton(page); [_nextButton addTarget:self action:@selector(nextButtonWasTapped:) forControlEvents:UIControlEventTouchUpInside];
diff --git a/ios/chrome/browser/intelligence/gemini/model/BUILD.gn b/ios/chrome/browser/intelligence/gemini/model/BUILD.gn index b6698d4..58fa217 100644 --- a/ios/chrome/browser/intelligence/gemini/model/BUILD.gn +++ b/ios/chrome/browser/intelligence/gemini/model/BUILD.gn
@@ -9,6 +9,7 @@ ] deps = [ "//components/keyed_service/core", + "//components/signin/public/identity_manager", "//ios/chrome/browser/signin/model:authentication_service", "//ios/chrome/browser/signin/model:authentication_service_factory", "//ios/public/provider/chrome/browser/glic:glic_api", @@ -24,10 +25,12 @@ ] deps = [ ":model", + "//components/signin/public/identity_manager", "//ios/chrome/browser/intelligence/features", "//ios/chrome/browser/shared/model/application_context", "//ios/chrome/browser/shared/model/profile", "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory", + "//ios/chrome/browser/signin/model", "//ios/chrome/browser/signin/model:authentication_service_factory", "//ios/public/provider/chrome/browser/glic:glic_api", ]
diff --git a/ios/chrome/browser/intelligence/gemini/model/DEPS b/ios/chrome/browser/intelligence/gemini/model/DEPS index 8666819c..674507f 100644 --- a/ios/chrome/browser/intelligence/gemini/model/DEPS +++ b/ios/chrome/browser/intelligence/gemini/model/DEPS
@@ -1,4 +1,5 @@ include_rules = [ "+ios/chrome/browser/signin/model/authentication_service.h", "+ios/chrome/browser/signin/model/authentication_service_factory.h", + "+ios/chrome/browser/signin/model/identity_manager_factory.h", ]
diff --git a/ios/chrome/browser/intelligence/gemini/model/glic_service.h b/ios/chrome/browser/intelligence/gemini/model/glic_service.h index 6646284..4683e3f 100644 --- a/ios/chrome/browser/intelligence/gemini/model/glic_service.h +++ b/ios/chrome/browser/intelligence/gemini/model/glic_service.h
@@ -12,11 +12,15 @@ #import "components/optimization_guide/proto/features/common_quality_data.pb.h" class AuthenticationService; +namespace signin { +class IdentityManager; +} // namespace signin // A browser-context keyed service for Glic. class GlicService : public KeyedService { public: - GlicService(AuthenticationService* auth_service); + GlicService(AuthenticationService* auth_service, + signin::IdentityManager* identity_manager); ~GlicService() override; // Presents the overlay on a given view controller. @@ -24,9 +28,16 @@ UIViewController* base_view_controller, std::unique_ptr<optimization_guide::proto::PageContext> page_context); + // Returns whether the current profile is eligible for Glic. + // TODO(crbug.com/419066154): Use this function to show the entry point. + bool IsEligibleForGlic(); + private: // AuthenticationService used to check if a user is signed in or not. raw_ptr<AuthenticationService> auth_service_ = nullptr; + + // Identity manager used to check account capabilities. + raw_ptr<signin::IdentityManager> identity_manager_ = nullptr; }; #endif // IOS_CHROME_BROWSER_INTELLIGENCE_GEMINI_MODEL_GLIC_SERVICE_H_
diff --git a/ios/chrome/browser/intelligence/gemini/model/glic_service.mm b/ios/chrome/browser/intelligence/gemini/model/glic_service.mm index 1ba541a..ad912e3 100644 --- a/ios/chrome/browser/intelligence/gemini/model/glic_service.mm +++ b/ios/chrome/browser/intelligence/gemini/model/glic_service.mm
@@ -6,11 +6,14 @@ #import <memory> +#import "components/signin/public/identity_manager/identity_manager.h" #import "ios/chrome/browser/signin/model/authentication_service.h" #import "ios/public/provider/chrome/browser/glic/glic_api.h" -GlicService::GlicService(AuthenticationService* auth_service) { +GlicService::GlicService(AuthenticationService* auth_service, + signin::IdentityManager* identity_manager) { auth_service_ = auth_service; + identity_manager_ = identity_manager; } GlicService::~GlicService() = default; @@ -21,3 +24,16 @@ ios::provider::StartGlicOverlay(base_view_controller, auth_service_, std::move(page_context)); } + +bool GlicService::IsEligibleForGlic() { + // TODO(crbug.com/419066154): Check other conditions, such as enterprise. + + AccountCapabilities capabilities = + identity_manager_ + ->FindExtendedAccountInfo(identity_manager_->GetPrimaryAccountInfo( + signin::ConsentLevel::kSignin)) + .capabilities; + + return capabilities.can_use_model_execution_features() == + signin::Tribool::kTrue; +}
diff --git a/ios/chrome/browser/intelligence/gemini/model/glic_service_factory.mm b/ios/chrome/browser/intelligence/gemini/model/glic_service_factory.mm index f1d6f94a7..d1973da4 100644 --- a/ios/chrome/browser/intelligence/gemini/model/glic_service_factory.mm +++ b/ios/chrome/browser/intelligence/gemini/model/glic_service_factory.mm
@@ -4,11 +4,13 @@ #import "ios/chrome/browser/intelligence/gemini/model/glic_service_factory.h" +#import "components/signin/public/identity_manager/identity_manager.h" #import "ios/chrome/browser/intelligence/features/features.h" #import "ios/chrome/browser/intelligence/gemini/model/glic_service.h" #import "ios/chrome/browser/shared/model/application_context/application_context.h" #import "ios/chrome/browser/shared/model/profile/profile_ios.h" #import "ios/chrome/browser/signin/model/authentication_service_factory.h" +#import "ios/chrome/browser/signin/model/identity_manager_factory.h" #import "ios/public/provider/chrome/browser/glic/glic_api.h" class GlicService; @@ -21,7 +23,8 @@ } ProfileIOS* profile = ProfileIOS::FromBrowserState(context); return std::make_unique<GlicService>( - AuthenticationServiceFactory::GetForProfile(profile)); + AuthenticationServiceFactory::GetForProfile(profile), + IdentityManagerFactory::GetForProfile(profile)); } } // namespace @@ -41,6 +44,7 @@ GlicServiceFactory::GlicServiceFactory() : ProfileKeyedServiceFactoryIOS("GlicService") { DependsOn(AuthenticationServiceFactory::GetInstance()); + DependsOn(IdentityManagerFactory::GetInstance()); } GlicServiceFactory::~GlicServiceFactory() = default;
diff --git a/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_view_controller.mm b/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_view_controller.mm index c89f5f4..2e8c354b 100644 --- a/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_view_controller.mm +++ b/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_view_controller.mm
@@ -59,7 +59,7 @@ // Add blurred background. UIBlurEffect* blurEffect = - [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; + [UIBlurEffect effectWithStyle:UIBlurEffectStyleRegular]; UIVisualEffectView* blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect]; blurEffectView.translatesAutoresizingMaskIntoConstraints = NO;
diff --git a/ios/chrome/browser/settings/ui_bundled/BUILD.gn b/ios/chrome/browser/settings/ui_bundled/BUILD.gn index 9957549..e0354557 100644 --- a/ios/chrome/browser/settings/ui_bundled/BUILD.gn +++ b/ios/chrome/browser/settings/ui_bundled/BUILD.gn
@@ -171,7 +171,6 @@ "//ios/chrome/browser/settings/ui_bundled/google_services", "//ios/chrome/browser/settings/ui_bundled/google_services:constants", "//ios/chrome/browser/settings/ui_bundled/google_services/manage_accounts", - "//ios/chrome/browser/settings/ui_bundled/google_services/manage_accounts:manage_accounts_ui", "//ios/chrome/browser/settings/ui_bundled/language", "//ios/chrome/browser/settings/ui_bundled/language:ui", "//ios/chrome/browser/settings/ui_bundled/notifications",
diff --git a/ios/chrome/browser/settings/ui_bundled/settings_table_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/settings_table_view_controller.mm index dd47792..d058986 100644 --- a/ios/chrome/browser/settings/ui_bundled/settings_table_view_controller.mm +++ b/ios/chrome/browser/settings/ui_bundled/settings_table_view_controller.mm
@@ -84,7 +84,6 @@ #import "ios/chrome/browser/settings/ui_bundled/downloads/downloads_settings_coordinator_delegate.h" #import "ios/chrome/browser/settings/ui_bundled/elements/enterprise_info_popover_view_controller.h" #import "ios/chrome/browser/settings/ui_bundled/google_services/google_services_settings_coordinator.h" -#import "ios/chrome/browser/settings/ui_bundled/google_services/manage_accounts/manage_accounts_coordinator.h" #import "ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_coordinator.h" #import "ios/chrome/browser/settings/ui_bundled/language/language_settings_mediator.h" #import "ios/chrome/browser/settings/ui_bundled/language/language_settings_table_view_controller.h" @@ -249,9 +248,6 @@ // Passwords coordinator. PasswordsCoordinator* _passwordsCoordinator; - // Accounts coordinator. - ManageAccountsCoordinator* _manageAccountsCoordinator; - // Feature engagement tracker for the signin IPH. raw_ptr<feature_engagement::Tracker> _featureEngagementTracker; // Presenter for the signin IPH. @@ -2054,9 +2050,6 @@ _passwordsCoordinator.delegate = nil; _passwordsCoordinator = nil; - [_manageAccountsCoordinator stop]; - _manageAccountsCoordinator = nil; - [_notificationsCoordinator stop]; _notificationsCoordinator = nil;
diff --git a/ios/chrome/test/wpt/BUILD.gn b/ios/chrome/test/wpt/BUILD.gn index 17e878f..fe9d25d 100644 --- a/ios/chrome/test/wpt/BUILD.gn +++ b/ios/chrome/test/wpt/BUILD.gn
@@ -11,11 +11,13 @@ import("//testing/test.gni") # Options shared by all script test targets that call `run_wpt_tests.py`. +# TODO(crbug.com/419890016): Consolidate the common options. _common_web_test_options = [ "--no-show-results", "--zero-tests-executed-ok", "--build-directory", "@WrappedPath(.)", + "--verbose", ] if (is_debug) { _common_web_test_options += [ "--debug" ]
diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc index a1741a2..18029db 100644 --- a/media/base/video_frame.cc +++ b/media/base/video_frame.cc
@@ -24,6 +24,8 @@ #include "base/memory/scoped_refptr.h" #include "base/numerics/safe_conversions.h" #include "base/process/memory.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/synchronization/lock.h" #include "base/types/pass_key.h" @@ -1311,6 +1313,27 @@ } } +// static +void VideoFrame::UpdateHashWithFrameForTesting(crypto::hash::Hasher& hasher, + const VideoFrame& frame) { + for (size_t plane = 0; plane < NumPlanes(frame.format()); ++plane) { + for (int row = 0; row < frame.rows(plane); ++row) { + hasher.Update(frame.data_[plane].subspan( + base::checked_cast<size_t>(frame.stride(plane) * row), + base::checked_cast<size_t>(frame.row_bytes(plane)))); + } + } +} + +// static +std::string VideoFrame::HexHashOfFrameForTesting(const VideoFrame& frame) { + crypto::hash::Hasher hasher(crypto::hash::HashKind::kSha256); + UpdateHashWithFrameForTesting(hasher, frame); // IN-TEST + std::array<uint8_t, crypto::hash::kSha256Size> hash; + hasher.Finish(hash); + return base::ToLowerASCII(base::HexEncode(hash)); +} + void VideoFrame::BackWithSharedMemory( const base::ReadOnlySharedMemoryRegion* region) { DCHECK(!shm_region_);
diff --git a/media/base/video_frame.h b/media/base/video_frame.h index a9c22c0..1bcdef5 100644 --- a/media/base/video_frame.h +++ b/media/base/video_frame.h
@@ -31,6 +31,7 @@ #include "base/types/pass_key.h" #include "base/unguessable_token.h" #include "build/build_config.h" +#include "crypto/hash.h" #include "gpu/command_buffer/client/client_shared_image.h" #include "gpu/command_buffer/common/mailbox_holder.h" #include "gpu/ipc/common/vulkan_ycbcr_info.h" @@ -529,9 +530,20 @@ // Used to keep a running hash of seen frames. Expects an initialized MD5 // context. Calls MD5Update with the context and the contents of the frame. + // + // Deprecated, do not use this. + // TODO(https://crbug.com/419771387): Remove this. static void HashFrameForTesting(base::MD5Context* context, const VideoFrame& frame); + // Given a crypto/hash Hasher, hash in the pixels from a single VideoFrame. + static void UpdateHashWithFrameForTesting(crypto::hash::Hasher& hasher, + const VideoFrame& frame); + + // Convenience wrapper around UpdateHashWithFrameForTesting(): produces the + // SHA-256 hash of a single video frame's pixels, as a lowercase hex string. + static std::string HexHashOfFrameForTesting(const VideoFrame& frame); + // Returns true if |frame| is accessible mapped in the VideoFrame memory // space. // static
diff --git a/media/base/video_frame_unittest.cc b/media/base/video_frame_unittest.cc index f96df0c..6a1af98 100644 --- a/media/base/video_frame_unittest.cc +++ b/media/base/video_frame_unittest.cc
@@ -150,8 +150,6 @@ namespace media { -using base::MD5DigestToBase16; - // Helper function that initializes a YV12 frame with white and black scan // lines based on the |white_to_black| parameter. If 0, then the entire // frame will be black, if 1 then the entire frame will be white. @@ -242,12 +240,7 @@ frame->stride(plane) * frame->rows(plane)); } - base::MD5Context context; - base::MD5Init(&context); - VideoFrame::HashFrameForTesting(&context, *frame.get()); - base::MD5Digest digest; - base::MD5Final(&digest, &context); - EXPECT_EQ(MD5DigestToBase16(digest), expected_hash); + EXPECT_EQ(VideoFrame::HexHashOfFrameForTesting(*frame.get()), expected_hash); } TEST(VideoFrame, CreateFrame) { @@ -268,21 +261,15 @@ InitializeYV12Frame(frame.get(), 0.0f); ExpectFrameColor(frame.get(), 0xFF000000); } - base::MD5Digest digest; - base::MD5Context context; - base::MD5Init(&context); - VideoFrame::HashFrameForTesting(&context, *frame.get()); - base::MD5Final(&digest, &context); - EXPECT_EQ(MD5DigestToBase16(digest), "9065c841d9fca49186ef8b4ef547e79b"); + EXPECT_EQ(VideoFrame::HexHashOfFrameForTesting(*frame.get()), + "48a14002453cf6ff6719661fc0715cbf1978214c182d1b4bbb9afb934051d630"); { SCOPED_TRACE(""); InitializeYV12Frame(frame.get(), 1.0f); ExpectFrameColor(frame.get(), 0xFFFFFFFF); } - base::MD5Init(&context); - VideoFrame::HashFrameForTesting(&context, *frame.get()); - base::MD5Final(&digest, &context); - EXPECT_EQ(MD5DigestToBase16(digest), "911991d51438ad2e1a40ed5f6fc7c796"); + EXPECT_EQ(VideoFrame::HexHashOfFrameForTesting(*frame.get()), + "a08db3e63e9b8ca723142d7fb734716a3a2af9f0e655271eb5acc9d2c2088dbb"); // Test single planar frame. frame = VideoFrame::CreateFrame(PIXEL_FORMAT_ARGB, size, gfx::Rect(size), @@ -642,8 +629,12 @@ TEST(VideoFrame, CheckFrameExtents) { // Each call consists of a Format and the expected hash of all // planes if filled with kFillByte (defined in ExpectFrameExtents). - ExpectFrameExtents(PIXEL_FORMAT_YV12, "8e5d54cb23cd0edca111dd35ffb6ff05"); - ExpectFrameExtents(PIXEL_FORMAT_I422, "cce408a044b212db42a10dfec304b3ef"); + ExpectFrameExtents( + PIXEL_FORMAT_YV12, + "cdf392577e7dced37c10e986b82be9aaabdfe32a3e8c1e132c9986a533447740"); + ExpectFrameExtents( + PIXEL_FORMAT_I422, + "df513a840bbb43915da7b3d00c1191ce3f46d6e657db5ab7f65e3f879c6eded0"); } static void TextureCallback(gpu::SyncToken* called_sync_token,
diff --git a/media/ffmpeg/ffmpeg_common.cc b/media/ffmpeg/ffmpeg_common.cc index 023b25c..b835ee7 100644 --- a/media/ffmpeg/ffmpeg_common.cc +++ b/media/ffmpeg/ffmpeg_common.cc
@@ -2,13 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/ffmpeg/ffmpeg_common.h" +#include "base/containers/span.h" #include "base/hash/sha1.h" #include "base/logging.h" #include "base/no_destructor.h" @@ -53,7 +49,7 @@ VideoDecoderConfig::AlphaMode GetAlphaMode(const AVStream* stream) { AVDictionaryEntry* alpha_mode = av_dict_get(stream->metadata, "alpha_mode", nullptr, 0); - return alpha_mode && !strcmp(alpha_mode->value, "1") + return alpha_mode && std::string_view(alpha_mode->value) == "1" ? VideoDecoderConfig::AlphaMode::kHasAlpha : VideoDecoderConfig::AlphaMode::kIsOpaque; } @@ -91,6 +87,46 @@ } } +inline base::span<uint8_t> AVCodecContextToSpan( + const AVCodecContext* codec_context) { + // SAFETY: + // https://ffmpeg.org/doxygen/6.0/structAVCodecContext.html#abe964316aaaa61967b012efdcced79c4 + // ffmpeg documentation: The allocated memory should be + // `AV_INPUT_BUFFER_PADDING_SIZE` bytes larger than `extradata_size`. So when + // we only use extradata_size bytes, it is safe. + return UNSAFE_BUFFERS( + base::span(codec_context->extradata, + base::checked_cast<size_t>(codec_context->extradata_size))); +} + +template <typename T> +void CopyBufferFromConfig(const T& config, AVCodecContext* codec_context) { + if (config.extra_data().empty()) { + codec_context->extradata = nullptr; + codec_context->extradata_size = 0; + return; + } + codec_context->extradata_size = config.extra_data().size(); + codec_context->extradata = reinterpret_cast<uint8_t*>( + av_malloc(config.extra_data().size() + AV_INPUT_BUFFER_PADDING_SIZE)); + // SAFETY: + // https://ffmpeg.org/doxygen/6.0/structAVCodecContext.html#abe964316aaaa61967b012efdcced79c4 + // ffmpeg documentation: The allocated memory should be + // `AV_INPUT_BUFFER_PADDING_SIZE` bytes larger than `extradata_size`. And the + // memory must be allocated using `av_malloc`. + // + // We allocated the appropriate memory according to this rule above and + // converted it to `base::span` here. So this is safe. + base::span allocated_extradata = UNSAFE_BUFFERS( + base::span(codec_context->extradata, + static_cast<size_t>(config.extra_data().size() + + AV_INPUT_BUFFER_PADDING_SIZE))); + auto [extradata, padding] = + allocated_extradata.split_at(config.extra_data().size()); + extradata.copy_from_nonoverlapping(config.extra_data()); + std::ranges::fill(padding, '\0'); +} + } // namespace // Allows faster SIMD YUV convert. Also, FFmpeg overreads/-writes occasionally. @@ -415,8 +451,9 @@ std::vector<uint8_t> extra_data; if (codec_context->extradata_size > 0) { - extra_data.assign(codec_context->extradata, - codec_context->extradata + codec_context->extradata_size); + extra_data.resize(codec_context->extradata_size); + base::span(extra_data) + .copy_from_nonoverlapping(AVCodecContextToSpan(codec_context)); } config->Initialize(codec, sample_format, channel_layout, codec_context->sample_rate, @@ -496,18 +533,7 @@ codec_context->ch_layout.nb_channels = config.channels(); codec_context->sample_rate = config.samples_per_second(); - if (config.extra_data().empty()) { - codec_context->extradata = nullptr; - codec_context->extradata_size = 0; - } else { - codec_context->extradata_size = config.extra_data().size(); - codec_context->extradata = reinterpret_cast<uint8_t*>( - av_malloc(config.extra_data().size() + AV_INPUT_BUFFER_PADDING_SIZE)); - memcpy(codec_context->extradata, &config.extra_data()[0], - config.extra_data().size()); - memset(codec_context->extradata + config.extra_data().size(), '\0', - AV_INPUT_BUFFER_PADDING_SIZE); - } + CopyBufferFromConfig(config, codec_context); ApplyCodecContextSecuritySettings(codec_context); } @@ -750,13 +776,14 @@ std::vector<uint8_t> extra_data; if (codec_context->extradata_size > 0) { - extra_data.assign(codec_context->extradata, - codec_context->extradata + codec_context->extradata_size); + extra_data.resize(codec_context->extradata_size); + base::span(extra_data) + .copy_from_nonoverlapping(AVCodecContextToSpan(codec_context.get())); } VideoTransformation video_transformation = VideoTransformation(); - for (int i = 0; i < stream->codecpar->nb_coded_side_data; ++i) { - const auto& side_data = stream->codecpar->coded_side_data[i]; + for (const auto& side_data : + AVCodecParametersCodedSideToSpan(stream->codecpar)) { switch (side_data.type) { case AV_PKT_DATA_DISPLAYMATRIX: { CHECK_EQ(side_data.size, sizeof(int32_t) * 3 * 3); @@ -868,18 +895,7 @@ if (config.color_space_info().range == gfx::ColorSpace::RangeID::FULL) codec_context->color_range = AVCOL_RANGE_JPEG; - if (config.extra_data().empty()) { - codec_context->extradata = nullptr; - codec_context->extradata_size = 0; - } else { - codec_context->extradata_size = config.extra_data().size(); - codec_context->extradata = reinterpret_cast<uint8_t*>( - av_malloc(config.extra_data().size() + AV_INPUT_BUFFER_PADDING_SIZE)); - memcpy(codec_context->extradata, &config.extra_data()[0], - config.extra_data().size()); - memset(codec_context->extradata + config.extra_data().size(), '\0', - AV_INPUT_BUFFER_PADDING_SIZE); - } + CopyBufferFromConfig(config, codec_context); ApplyCodecContextSecuritySettings(codec_context); } @@ -1014,22 +1030,25 @@ int32_t HashCodecName(const char* codec_name) { // Use the first 32-bits from the SHA1 hash as the identifier. int32_t hash; - memcpy(&hash, base::SHA1HashString(codec_name).substr(0, 4).c_str(), 4); + base::byte_span_from_ref(hash).copy_from_nonoverlapping( + base::as_byte_span(base::SHA1HashString(codec_name)).first<4>()); return hash; } const char* GetAllowedAudioDecoders() { - static const base::NoDestructor<std::string> kAllowedAudioCodecs([]() { - // This should match the configured lists in //third_party/ffmpeg. - std::string allowed_decoders( - "vorbis,libopus,flac,pcm_u8,pcm_s16le,pcm_s24le,pcm_s32le,pcm_f32le," - "mp3,pcm_s16be,pcm_s24be,pcm_mulaw,pcm_alaw"); #if BUILDFLAG(USE_PROPRIETARY_CODECS) - allowed_decoders += ",aac"; +#define EXTRA_CODECS ",aac" +#else +#define EXTRA_CODECS #endif - return allowed_decoders; - }()); - return kAllowedAudioCodecs->c_str(); + + // This should match the configured lists in //third_party/ffmpeg. + static constexpr std::string_view kAllowedAudioCodecs = + "vorbis,libopus,flac,pcm_u8,pcm_s16le,pcm_s24le,pcm_s32le,pcm_f32le," + "mp3,pcm_s16be,pcm_s24be,pcm_mulaw,pcm_alaw" EXTRA_CODECS; +#undef EXTRA_CODECS + + return kAllowedAudioCodecs.data(); } } // namespace media
diff --git a/media/ffmpeg/ffmpeg_common.h b/media/ffmpeg/ffmpeg_common.h index 0225b37..ca0a6d2 100644 --- a/media/ffmpeg/ffmpeg_common.h +++ b/media/ffmpeg/ffmpeg_common.h
@@ -93,6 +93,28 @@ base::span(packet.data, base::checked_cast<size_t>(packet.size))); } +inline base::span<AVStream*> AVFormatContextToSpan( + const AVFormatContext* codec_context) { + // SAFETY: + // https://ffmpeg.org/doxygen/trunk/structAVFormatContext.html#a0b748d924898b08b89ff4974afd17285 + // ffmpeg documentation: `nb_streams` is the number of elements in + // `AVFormatContext.streams`. + return UNSAFE_BUFFERS( + base::span(codec_context->streams, + base::checked_cast<size_t>(codec_context->nb_streams))); +} + +inline base::span<AVPacketSideData> AVCodecParametersCodedSideToSpan( + const AVCodecParameters* codecpar) { + // SAFETY: + // https://ffmpeg.org/doxygen/trunk/structAVCodecParameters.html#a29643cfd94231e2d148a5d17b08d115b + // ffmpeg documentation: `nb_coded_side_data` is the amount of entries in + // `coded_side_data`. + return UNSAFE_BUFFERS( + base::span(codecpar->coded_side_data, + base::checked_cast<size_t>(codecpar->nb_coded_side_data))); +} + // Converts an int64_t timestamp in |time_base| units to a base::TimeDelta. // For example if |timestamp| equals 11025 and |time_base| equals {1, 44100} // then the return value will be a base::TimeDelta for 0.25 seconds since that
diff --git a/media/ffmpeg/ffmpeg_common_unittest.cc b/media/ffmpeg/ffmpeg_common_unittest.cc index 5b1a54a..cb337c3 100644 --- a/media/ffmpeg/ffmpeg_common_unittest.cc +++ b/media/ffmpeg/ffmpeg_common_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/ffmpeg/ffmpeg_common.h" #include <stddef.h> @@ -37,6 +32,17 @@ uint8_t kExtraData[5] = {0x00, 0x01, 0x02, 0x03, 0x04}; +inline base::span<uint8_t> AVCodecParametersExtraDataToSpan( + const AVCodecParameters* codec_context) { + // SAFETY: + // https://ffmpeg.org/doxygen/trunk/structAVCodecParameters.html#a9befe0b86412646017afb0051d144d13 + // ffmpeg documentation: The allocated size of `extradata` must be at least + // `extradata_size + AV_INPUT_BUFFER_PADDING_SIZE`. + return UNSAFE_BUFFERS( + base::span(codec_context->extradata, + base::checked_cast<size_t>(codec_context->extradata_size))); +} + template <typename T> void TestConfigConvertExtraData( AVStream* stream, @@ -63,9 +69,8 @@ EXPECT_TRUE(converter_fn.Run(stream, decoder_config)); EXPECT_EQ(static_cast<size_t>(codec_parameters->extradata_size), decoder_config->extra_data().size()); - EXPECT_EQ( - 0, memcmp(codec_parameters->extradata, &decoder_config->extra_data()[0], - decoder_config->extra_data().size())); + EXPECT_EQ(AVCodecParametersExtraDataToSpan(codec_parameters), + base::span(decoder_config->extra_data())); // Possible combination: extra_data = nullptr && size != 0, but the converter // function considers this valid and having no extra_data, due to behavior of @@ -95,8 +100,7 @@ ASSERT_TRUE(glue.OpenContext()); AVFormatContext* format_context = glue.format_context(); - for (size_t i = 0; i < format_context->nb_streams; ++i) { - AVStream* stream = format_context->streams[i]; + for (auto* stream : AVFormatContextToSpan(format_context)) { AVCodecParameters* codec_parameters = stream->codecpar; AVMediaType codec_type = codec_parameters->codec_type; @@ -124,10 +128,11 @@ // for extradata and extradata_size. bool found_audio = false; bool found_video = false; - for (size_t i = 0; - i < format_context->nb_streams && (!found_audio || !found_video); - ++i) { - AVStream* stream = format_context->streams[i]; + for (AVStream* stream : AVFormatContextToSpan(format_context)) { + if (found_audio && found_video) { + break; + } + AVCodecParameters* codec_parameters = stream->codecpar; AVMediaType codec_type = codec_parameters->codec_type;
diff --git a/media/filters/audio_video_metadata_extractor.cc b/media/filters/audio_video_metadata_extractor.cc index 3ff1d184..1a1333a 100644 --- a/media/filters/audio_video_metadata_extractor.cc +++ b/media/filters/audio_video_metadata_extractor.cc
@@ -2,13 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/filters/audio_video_metadata_extractor.h" +#include <algorithm> + #include "base/functional/bind.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" @@ -106,21 +103,22 @@ has_duration_ = true; } - stream_infos_.push_back(StreamInfo()); + stream_infos_.emplace_back(); StreamInfo& container_info = stream_infos_.back(); container_info.type = format_context->iformat->name; ExtractDictionary(format_context->metadata, &container_info.tags); - for (unsigned int i = 0; i < format_context->nb_streams; ++i) { - stream_infos_.push_back(StreamInfo()); + base::span<AVStream*> format_context_span = + AVFormatContextToSpan(format_context); + std::ranges::for_each(format_context_span, [&](AVStream* stream) { + stream_infos_.emplace_back(); StreamInfo& info = stream_infos_.back(); - AVStream* stream = format_context->streams[i]; - if (!stream) - continue; + if (!stream) { + return; + } - for (int j = 0; j < stream->codecpar->nb_coded_side_data; j++) { - const AVPacketSideData& sd = stream->codecpar->coded_side_data[j]; + for (const auto& sd : AVCodecParametersCodedSideToSpan(stream->codecpar)) { if (sd.type == AV_PKT_DATA_DISPLAYMATRIX) { CHECK_EQ(sd.size, sizeof(int32_t) * 3 * 3); rotation_ = VideoTransformation::FromFFmpegDisplayMatrix( @@ -135,8 +133,9 @@ // metadata to contained streams instead the container itself, like OGG. ExtractDictionary(stream->metadata, &info.tags); - if (!stream->codecpar) - continue; + if (!stream->codecpar) { + return; + } info.type = avcodec_get_name(stream->codecpar->codec_id); @@ -153,12 +152,12 @@ stream->attached_pic.size > 0 && stream->attached_pic.size <= kAttachedImageSizeLimit && stream->attached_pic.data != nullptr) { - attached_images_bytes_.push_back(std::string()); + attached_images_bytes_.emplace_back(); attached_images_bytes_.back().assign( reinterpret_cast<const char*>(stream->attached_pic.data), stream->attached_pic.size); } - } + }); extracted_ = true; return true;
diff --git a/media/filters/dav1d_video_decoder_unittest.cc b/media/filters/dav1d_video_decoder_unittest.cc index af75237..a223c37 100644 --- a/media/filters/dav1d_video_decoder_unittest.cc +++ b/media/filters/dav1d_video_decoder_unittest.cc
@@ -183,15 +183,6 @@ output_frames_.push_back(std::move(frame)); } - std::string GetVideoFrameHash(const VideoFrame& frame) { - base::MD5Context md5_context; - base::MD5Init(&md5_context); - VideoFrame::HashFrameForTesting(&md5_context, frame); - base::MD5Digest digest; - base::MD5Final(&digest, &md5_context); - return base::MD5DigestToBase16(digest); - } - MOCK_METHOD1(DecodeDone, void(DecoderStatus)); base::test::SingleThreadTaskEnvironment task_environment_; @@ -232,7 +223,8 @@ const auto& frame = output_frames_.front(); EXPECT_EQ(PIXEL_FORMAT_I420, frame->format()); - EXPECT_EQ("589dc641b7742ffe7a2b0d4c16aa3e86", GetVideoFrameHash(*frame)); + EXPECT_EQ("52b7d8e65b031f09c0db38d1f36113a332bd7bfcafde95ee794112261535e223", + VideoFrame::HexHashOfFrameForTesting(*frame)); } TEST_F(Dav1dVideoDecoderTest, DecodeFrame_8bitMono) { @@ -246,7 +238,8 @@ EXPECT_EQ(PIXEL_FORMAT_I420, frame->format()); EXPECT_EQ(frame->data(VideoFrame::Plane::kU), frame->data(VideoFrame::Plane::kV)); - EXPECT_EQ("eeba03dcc9c22c4632bf74b481db36b2", GetVideoFrameHash(*frame)); + EXPECT_EQ("3d85366c6607ea2f829bd7058a3f77f23ecd10327612bc62171dbff08421e3ad", + VideoFrame::HexHashOfFrameForTesting(*frame)); } TEST_F(Dav1dVideoDecoderTest, DecodeFrame_10bitMono) { @@ -260,7 +253,8 @@ EXPECT_EQ(PIXEL_FORMAT_YUV420P10, frame->format()); EXPECT_EQ(frame->data(VideoFrame::Plane::kU), frame->data(VideoFrame::Plane::kV)); - EXPECT_EQ("026c1fed9e161f09d816ac7278458a80", GetVideoFrameHash(*frame)); + EXPECT_EQ("0a659dd4f04ecee14ca1881435ad8d18ce862ef519aaa990191cc8fa0ba66eb2", + VideoFrame::HexHashOfFrameForTesting(*frame)); } TEST_F(Dav1dVideoDecoderTest, DecodeFrame_12bitMono) { @@ -274,7 +268,8 @@ EXPECT_EQ(PIXEL_FORMAT_YUV420P12, frame->format()); EXPECT_EQ(frame->data(VideoFrame::Plane::kU), frame->data(VideoFrame::Plane::kV)); - EXPECT_EQ("32115092dc00fbe86823b0b714a0f63e", GetVideoFrameHash(*frame)); + EXPECT_EQ("f1acdafc4a9fa0840d7d938a9dea41ac55f612cecce2d6b89095c44fc7f29c46", + VideoFrame::HexHashOfFrameForTesting(*frame)); } TEST_F(Dav1dVideoDecoderTest, DecodeFrame_AgtmMetadata) {
diff --git a/media/filters/media_file_checker.cc b/media/filters/media_file_checker.cc index 57d6596f..2e73f3b9 100644 --- a/media/filters/media_file_checker.cc +++ b/media/filters/media_file_checker.cc
@@ -2,15 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/filters/media_file_checker.h" #include <stddef.h> #include <stdint.h> + +#include <algorithm> #include <map> #include <memory> #include <utility> @@ -67,22 +64,29 @@ // Remember the codec context for any decodable audio or video streams. bool found_streams = false; std::vector<Decoder> stream_contexts(format_context->nb_streams); - for (size_t i = 0; i < format_context->nb_streams; ++i) { - AVCodecParameters* cp = format_context->streams[i]->codecpar; + base::span<AVStream*> format_context_span = + AVFormatContextToSpan(format_context); + std::ranges::transform( + format_context_span, stream_contexts.begin(), + [&found_streams](AVStream* stream) { + AVCodecParameters* cp = stream->codecpar; - if (cp->codec_type == AVMEDIA_TYPE_AUDIO || - cp->codec_type == AVMEDIA_TYPE_VIDEO) { - auto context = AVStreamToAVCodecContext(format_context->streams[i]); - if (!context) - continue; - const AVCodec* codec = avcodec_find_decoder(cp->codec_id); - if (codec && avcodec_open2(context.get(), codec, nullptr) >= 0) { - auto loop = std::make_unique<FFmpegDecodingLoop>(context.get()); - stream_contexts[i] = {std::move(context), std::move(loop)}; - found_streams = true; - } - } - } + if (cp->codec_type == AVMEDIA_TYPE_AUDIO || + cp->codec_type == AVMEDIA_TYPE_VIDEO) { + auto context = AVStreamToAVCodecContext(stream); + if (!context) { + return Decoder{}; + } + const AVCodec* codec = avcodec_find_decoder(cp->codec_id); + if (codec && avcodec_open2(context.get(), codec, nullptr) >= 0) { + auto loop = std::make_unique<FFmpegDecodingLoop>(context.get()); + found_streams = true; + return Decoder{std::move(context), std::move(loop)}; + } + } + + return Decoder{}; + }); if (!found_streams) return false;
diff --git a/media/gpu/av1_decoder.cc b/media/gpu/av1_decoder.cc index 054820e..f8b2095 100644 --- a/media/gpu/av1_decoder.cc +++ b/media/gpu/av1_decoder.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/gpu/av1_decoder.h" #include <algorithm> @@ -181,8 +176,7 @@ // skip it and will keep skipping until we get a sequence header. current_sequence_header_.reset(); stream_id_ = 0; - stream_ = nullptr; - stream_size_ = 0; + stream_ = {}; on_error_ = false; state_ = std::make_unique<libgav1::DecoderState>(); @@ -200,15 +194,13 @@ void AV1Decoder::SetStream(int32_t id, const DecoderBuffer& decoder_buffer) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - auto decoder_buffer_span = base::span(decoder_buffer); + stream_ = base::span(decoder_buffer); stream_id_ = id; - stream_ = decoder_buffer_span.data(); - stream_size_ = decoder_buffer_span.size(); ClearCurrentFrame(); parser_ = base::WrapUnique(new (std::nothrow) libgav1::ObuParser( - decoder_buffer_span.data(), decoder_buffer_span.size(), - kDefaultOperatingPoint, buffer_pool_.get(), state_.get())); + stream_.data(), stream_.size(), kDefaultOperatingPoint, + buffer_pool_.get(), state_.get())); if (!parser_) { on_error_ = true; return; @@ -226,8 +218,8 @@ secure_handle_ = 0; } - const AV1Accelerator::Status status = accelerator_->SetStream( - base::span(stream_.get(), stream_size_), decrypt_config_.get()); + const AV1Accelerator::Status status = + accelerator_->SetStream(stream_, decrypt_config_.get()); if (status != AV1Accelerator::Status::kOk) { on_error_ = true; return; @@ -580,10 +572,8 @@ // For intra frames, we don't need this assertion because they shouldn't // depend on reference frames. if (!libgav1::IsIntraFrame(current_frame_header_->frame_type)) { - for (size_t i = 0; i < libgav1::kNumInterReferenceFrameTypes; ++i) { - const auto ref_frame_index = - current_frame_header_->reference_frame_index[i]; - + for (int8_t ref_frame_index : + current_frame_header_->reference_frame_index) { // Unless an error occurred in libgav1, |ref_frame_index| should be valid, // and since CheckAndCleanUpReferenceFrames() only gets called if parsing // succeeded, we can assert that validity. @@ -604,16 +594,15 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(pic); DCHECK(current_sequence_header_); - DCHECK(stream_); - DCHECK_GT(stream_size_, 0u); + DCHECK(!stream_.empty()); if (!CheckAndCleanUpReferenceFrames()) { DLOG(ERROR) << "The states of reference frames are different between " << "|ref_frames_| and |state_|"; return AV1Accelerator::Status::kFail; } - const AV1Accelerator::Status status = accelerator_->SubmitDecode( - *pic, *current_sequence_header_, ref_frames_, tile_buffers, - base::span(stream_.get(), stream_size_)); + const AV1Accelerator::Status status = + accelerator_->SubmitDecode(*pic, *current_sequence_header_, ref_frames_, + tile_buffers, base::span(stream_)); if (status != AV1Accelerator::Status::kOk) { if (status == AV1Accelerator::Status::kTryAgain) pending_pic_ = std::move(pic);
diff --git a/media/gpu/av1_decoder.h b/media/gpu/av1_decoder.h index 4d1108c..4f011983 100644 --- a/media/gpu/av1_decoder.h +++ b/media/gpu/av1_decoder.h
@@ -192,8 +192,7 @@ std::optional<gfx::HDRMetadata> hdr_metadata_; int32_t stream_id_ = 0; - raw_ptr<const uint8_t, DanglingUntriaged> stream_ = nullptr; - size_t stream_size_ = 0; + base::raw_span<const uint8_t, DanglingUntriaged> stream_; std::unique_ptr<DecryptConfig> decrypt_config_; // Secure handle to pass through to the accelerator when doing secure playback
diff --git a/media/gpu/av1_decoder_unittest.cc b/media/gpu/av1_decoder_unittest.cc index 5d98592..a8b2c7a 100644 --- a/media/gpu/av1_decoder_unittest.cc +++ b/media/gpu/av1_decoder_unittest.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/gpu/av1_decoder.h" #include <string.h> #include <algorithm> #include <array> +#include <iterator> #include <string> #include <vector> @@ -212,8 +208,7 @@ EXPECT_FALSE(decoder_->current_frame_header_); EXPECT_FALSE(decoder_->current_frame_); EXPECT_NE(decoder_->stream_id_, 0); - EXPECT_TRUE(decoder_->stream_); - EXPECT_GT(decoder_->stream_size_, 0u); + EXPECT_FALSE(decoder_->stream_.empty()); decoder_->Reset(); EXPECT_EQ(decoder_->state_->current_frame_id, -1); @@ -225,8 +220,7 @@ EXPECT_FALSE(decoder_->current_frame_header_); EXPECT_FALSE(decoder_->current_frame_); EXPECT_EQ(decoder_->stream_id_, 0); - EXPECT_FALSE(decoder_->stream_); - EXPECT_EQ(decoder_->stream_size_, 0u); + EXPECT_TRUE(decoder_->stream_.empty()); } scoped_refptr<DecoderBuffer> AV1DecoderTest::ReadDecoderBuffer( @@ -273,19 +267,17 @@ InMemoryUrlProtocol protocol(*webm_data, false); FFmpegGlue glue(&protocol); LOG_ASSERT(glue.OpenContext()); - int stream_index = -1; - for (unsigned int i = 0; i < glue.format_context()->nb_streams; ++i) { - const AVStream* stream = glue.format_context()->streams[i]; + base::span<AVStream*> format_context = + AVFormatContextToSpan(glue.format_context()); + auto iter = std::ranges::find_if(format_context, [](AVStream* stream) { const AVCodecParameters* codec_parameters = stream->codecpar; const AVMediaType codec_type = codec_parameters->codec_type; const AVCodecID codec_id = codec_parameters->codec_id; - if (codec_type == AVMEDIA_TYPE_VIDEO && codec_id == AV_CODEC_ID_AV1) { - stream_index = i; - break; - } - } - EXPECT_NE(stream_index, -1) << "No AV1 data found in " << input_file; - + return codec_type == AVMEDIA_TYPE_VIDEO && codec_id == AV_CODEC_ID_AV1; + }); + EXPECT_NE(iter, format_context.end()) + << "No AV1 data found in " << input_file; + int stream_index = std::distance(format_context.begin(), iter); std::vector<scoped_refptr<DecoderBuffer>> buffers; auto packet = ScopedAVPacket::Allocate(); while (av_read_frame(glue.format_context(), packet.get()) >= 0) { @@ -792,8 +784,11 @@ EXPECT_EQ(av1_picture->frame_header.frame_type, libgav1::kFrameInter); // Next, let's check the reference frames that frame needs. - for (int8_t i = 0; i < libgav1::kNumInterReferenceFrameTypes; ++i) - EXPECT_EQ(av1_picture->frame_header.reference_frame_index[i], i); + base::span<int8_t> reference_frame_index( + av1_picture->frame_header.reference_frame_index); + for (size_t i = 0; i < reference_frame_index.size(); ++i) { + EXPECT_EQ(static_cast<size_t>(reference_frame_index[i]), i); + } // Finally, let's check that libgav1 thought that all the reference frames // were valid.
diff --git a/media/gpu/test/raw_video.cc b/media/gpu/test/raw_video.cc index 241ba34..af09dffe9 100644 --- a/media/gpu/test/raw_video.cc +++ b/media/gpu/test/raw_video.cc
@@ -314,24 +314,22 @@ FFmpegGlue glue(&protocol); LOG_ASSERT(glue.OpenContext()) << "Failed to open AVFormatContext"; // Find the first VP9 stream in the file. - std::optional<size_t> vp9_stream_index; VideoDecoderConfig config; - for (size_t i = 0; i < glue.format_context()->nb_streams; ++i) { - AVStream* stream = glue.format_context()->streams[i]; + base::span<AVStream*> format_context = + AVFormatContextToSpan(glue.format_context()); + auto iter = std::ranges::find_if(format_context, [&config](AVStream* stream) { const AVCodecParameters* codec_parameters = stream->codecpar; const AVMediaType codec_type = codec_parameters->codec_type; const AVCodecID codec_id = codec_parameters->codec_id; - if (codec_type == AVMEDIA_TYPE_VIDEO && codec_id == AV_CODEC_ID_VP9 && - AVStreamToVideoDecoderConfig(stream, &config) && - config.IsValidConfig()) { - vp9_stream_index = i; - break; - } - } - if (!vp9_stream_index) { + return codec_type == AVMEDIA_TYPE_VIDEO && codec_id == AV_CODEC_ID_VP9 && + AVStreamToVideoDecoderConfig(stream, &config) && + config.IsValidConfig(); + }); + if (iter == format_context.end()) { return nullptr; } - + std::optional<size_t> vp9_stream_index = + std::distance(format_context.begin(), iter); auto vp9_data_mmap_file = CreateMemoryMappedFile(vp9_webm_data.size()); uint8_t* const vp9_data = vp9_data_mmap_file->data(); size_t vp9_data_size = 0;
diff --git a/media/gpu/vaapi/h264_vaapi_video_decoder_delegate.cc b/media/gpu/vaapi/h264_vaapi_video_decoder_delegate.cc index 7ec048b..b89d4897 100644 --- a/media/gpu/vaapi/h264_vaapi_video_decoder_delegate.cc +++ b/media/gpu/vaapi/h264_vaapi_video_decoder_delegate.cc
@@ -377,10 +377,20 @@ DVLOG(1) << "Failure submitting encrypted slice header buffers"; return DecodeStatus::kFail; } + if (!vaapi_wrapper_->ExecuteAndDestroyPendingBuffers(surface->id())) { + if (NeedsProtectedSessionRecovery()) { + LOG(ERROR) << "Retry slice header decrypt due to recovery"; + return DecodeStatus::kTryAgain; + } LOG(ERROR) << "Failed executing for slice header decrypt"; return DecodeStatus::kFail; } + + if (IsEncryptedSession()) { + ProtectedDecodedSucceeded(); + } + if (status_buf->status != VA_ENCRYPTION_STATUS_SUCCESSFUL) { LOG(ERROR) << "Failure status in encrypted header parsing: " << static_cast<int>(status_buf->status);
diff --git a/media/mojo/mojom/video_frame_mojom_traits_unittest.cc b/media/mojo/mojom/video_frame_mojom_traits_unittest.cc index e3270a77..572da7e 100644 --- a/media/mojo/mojom/video_frame_mojom_traits_unittest.cc +++ b/media/mojo/mojom/video_frame_mojom_traits_unittest.cc
@@ -90,9 +90,7 @@ EchoVideoFrameCallback callback) override { // Touch all data in the received frame to ensure that it is valid. if (f && f->IsMappable()) { - base::MD5Context md5_context; - base::MD5Init(&md5_context); - VideoFrame::HashFrameForTesting(&md5_context, *f); + VideoFrame::HexHashOfFrameForTesting(*f); } std::move(callback).Run(f);
diff --git a/net/disk_cache/blockfile/backend_impl.cc b/net/disk_cache/blockfile/backend_impl.cc index 3053b6f..91f988b 100644 --- a/net/disk_cache/blockfile/backend_impl.cc +++ b/net/disk_cache/blockfile/backend_impl.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40284755): Remove this and spanify to fix the errors. -#pragma allow_unsafe_buffers -#endif - #include "net/disk_cache/blockfile/backend_impl.h" #include <algorithm> @@ -16,6 +11,7 @@ #include <utility> #include "base/containers/heap_array.h" +#include "base/containers/span.h" #include "base/files/file.h" #include "base/files/file_path.h" #include "base/files/file_util.h" @@ -1307,8 +1303,9 @@ header.table_len = DesiredIndexTableLen(max_size_); header.create_time = Time::Now().ToInternalValue(); - if (!file->Write(&header, sizeof(header), 0)) + if (!file->Write(base::byte_span_from_ref(header), 0)) { return false; + } size_t size = GetIndexSize(header.table_len); if (!file->SetLength(size)) @@ -1322,17 +1319,16 @@ // header), to force allocation now and fail cleanly if there is no space. // // See https://crbug.com/1097518 - const int kPageSize = 4096; + static constexpr size_t kPageSize = 4096; static_assert(sizeof(disk_cache::IndexHeader) < kPageSize, "Code below assumes it wouldn't overwrite header by starting " "at kPageSize"); - auto page = std::make_unique<char[]>(kPageSize); - memset(page.get(), 0, kPageSize); - + auto page = base::HeapArray<uint8_t>::WithSize(kPageSize); for (size_t offset = kPageSize; offset < size; offset += kPageSize) { size_t end = std::min(offset + kPageSize, size); - if (!file->Write(page.get(), end - offset, offset)) + if (!file->Write(page.first(end - offset), offset)) { return false; + } } return true; } @@ -1919,8 +1915,12 @@ return false; } - if (!mask_) - mask_ = data_->header.table_len - 1; + if (!mask_) { + // `data_->header.table_len` may be larger than `kIndexTablesize`. This will + // cause a memory out of bounds error. + mask_ = std::min(static_cast<int>(kIndexTablesize) - 1, + data_->header.table_len - 1); + } // Load the table into memory. return index_->Preload(); @@ -1969,16 +1969,20 @@ bool BackendImpl::CheckEntry(EntryImpl* cache_entry) { bool ok = block_files_.IsValid(cache_entry->entry()->address()); ok = ok && block_files_.IsValid(cache_entry->rankings()->address()); - EntryStore* data = cache_entry->entry()->Data(); - for (size_t i = 0; i < std::size(data->data_addr); i++) { - if (data->data_addr[i]) { - Addr address(data->data_addr[i]); - if (address.is_block_file()) - ok = ok && block_files_.IsValid(address); - } - } + ok = ok && cache_entry->rankings()->VerifyHash(); + ok = ok && std::ranges::all_of( + cache_entry->entry()->Data()->data_addr, + [&block_files = block_files_](const CacheAddr& cache_addr) { + if (cache_addr) { + Addr address(cache_addr); + if (address.is_block_file()) { + return block_files.IsValid(address); + } + } - return ok && cache_entry->rankings()->VerifyHash(); + return true; + }); + return ok; } // static
diff --git a/net/disk_cache/blockfile/disk_format.cc b/net/disk_cache/blockfile/disk_format.cc index 6c75dd1..637e89b 100644 --- a/net/disk_cache/blockfile/disk_format.cc +++ b/net/disk_cache/blockfile/disk_format.cc
@@ -12,10 +12,6 @@ static_assert(sizeof(IndexHeader) == 368); -IndexHeader::IndexHeader() { - std::ranges::fill(base::byte_span_from_ref(*this), 0); - magic = kIndexMagic; - version = kCurrentVersion; -} +IndexHeader::IndexHeader() = default; } // namespace disk_cache
diff --git a/net/disk_cache/blockfile/disk_format.h b/net/disk_cache/blockfile/disk_format.h index 72e62bf..faaa0749 100644 --- a/net/disk_cache/blockfile/disk_format.h +++ b/net/disk_cache/blockfile/disk_format.h
@@ -49,60 +49,63 @@ #include <stdint.h> #include <string.h> +#include <array> + #include "net/base/net_export.h" #include "net/disk_cache/blockfile/disk_format_base.h" namespace disk_cache { -const int kIndexTablesize = 0x10000; -const uint32_t kIndexMagic = 0xC103CAC3; -const uint32_t kVersion2_0 = 0x20000; -const uint32_t kVersion2_1 = 0x20001; -const uint32_t kVersion3_0 = 0x30000; -const uint32_t kCurrentVersion = kVersion3_0; +inline constexpr size_t kIndexTablesize = 0x10000; +inline constexpr uint32_t kIndexMagic = 0xC103CAC3; +inline constexpr uint32_t kVersion2_0 = 0x20000; +inline constexpr uint32_t kVersion2_1 = 0x20001; +inline constexpr uint32_t kVersion3_0 = 0x30000; +inline constexpr uint32_t kCurrentVersion = kVersion3_0; struct LruData { - int32_t pad1[2]; - int32_t filled; // Flag to tell when we filled the cache. - int32_t sizes[5]; - CacheAddr heads[5]; - CacheAddr tails[5]; - CacheAddr transaction; // In-flight operation target. - int32_t operation; // Actual in-flight operation. - int32_t operation_list; // In-flight operation list. - int32_t pad2[7]; + std::array<int32_t, 2> pad1 = {}; + int32_t filled = 0; // Flag to tell when we filled the cache. + std::array<int32_t, 5> sizes = {}; + std::array<CacheAddr, 5> heads = {}; + std::array<CacheAddr, 5> tails = {}; + CacheAddr transaction = 0; // In-flight operation target. + int32_t operation = 0; // Actual in-flight operation. + int32_t operation_list = 0; // In-flight operation list. + std::array<int32_t, 7> pad2 = {}; }; // Header for the master index file. struct NET_EXPORT_PRIVATE IndexHeader { IndexHeader(); - uint32_t magic; - uint32_t version; - int32_t num_entries; // Number of entries currently stored. - int32_t old_v2_num_bytes; // Total size of the stored data, in versions 2.x - int32_t last_file; // Last external file created. - int32_t this_id; // Id for all entries being changed (dirty flag). - CacheAddr stats; // Storage for usage data. - int32_t table_len; // Actual size of the table (0 == kIndexTablesize). - int32_t crash; // Signals a previous crash. - int32_t experiment; // Id of an ongoing test. - uint64_t create_time; // Creation time for this set of files. - int64_t num_bytes; // Total size of the stored data, in version 3.0 - int32_t pad[50]; + uint32_t magic = kIndexMagic; + uint32_t version = kCurrentVersion; + int32_t num_entries = 0; // Number of entries currently stored. + int32_t old_v2_num_bytes = + 0; // Total size of the stored data, in versions 2.x + int32_t last_file = 0; // Last external file created. + int32_t this_id = 0; // Id for all entries being changed (dirty flag). + CacheAddr stats = 0; // Storage for usage data. + int32_t table_len = 0; // Actual size of the table (0 == kIndexTablesize). + int32_t crash = 0; // Signals a previous crash. + int32_t experiment = 0; // Id of an ongoing test. + uint64_t create_time = 0; // Creation time for this set of files. + int64_t num_bytes = 0; // Total size of the stored data, in version 3.0 + std::array<int32_t, 50> pad = {}; LruData lru; // Eviction control data. }; // The structure of the whole index file. struct Index { IndexHeader header; - CacheAddr table[kIndexTablesize]; // Default size. Actual size controlled - // by header.table_len. + // Default size. Actual size controlled by header.table_len. + std::array<CacheAddr, kIndexTablesize> table = {}; }; // Main structure for an entry on the backing storage. If the key is longer than // what can be stored on this structure, it will be extended on consecutive -// blocks (adding 256 bytes each time), up to 4 blocks (1024 - 32 - 1 chars). +// blocks (adding 256 bytes each time), up to 4 blocks (1024 - 96 - 1 chars). // After that point, the whole key will be stored as a data block or external // file. struct EntryStore { @@ -116,7 +119,7 @@ int32_t key_len; CacheAddr long_key; // Optional address of a long key. int32_t data_size[4]; // We can store up to 4 data streams for each - CacheAddr data_addr[4]; // entry. + std::array<CacheAddr, 4> data_addr; // entry. uint32_t flags; // Any combination of EntryFlags. int32_t pad[4]; uint32_t self_hash; // The hash of EntryStore up to this point.
diff --git a/net/disk_cache/blockfile/file.cc b/net/disk_cache/blockfile/file.cc index b37694c0..3142e2d7 100644 --- a/net/disk_cache/blockfile/file.cc +++ b/net/disk_cache/blockfile/file.cc
@@ -13,4 +13,33 @@ File::File(bool mixed_mode) : init_(false), mixed_(mixed_mode) {} +bool File::Read(void* buffer, size_t buffer_len, size_t offset) { + return UNSAFE_TODO( + Read(base::span(static_cast<uint8_t*>(buffer), buffer_len), offset)); +} + +bool File::Write(const void* buffer, size_t buffer_len, size_t offset) { + return UNSAFE_TODO(Write( + base::span(static_cast<const uint8_t*>(buffer), buffer_len), offset)); +} + +bool File::Read(void* buffer, + size_t buffer_len, + size_t offset, + FileIOCallback* callback, + bool* completed) { + return UNSAFE_TODO(Read(base::span(static_cast<uint8_t*>(buffer), buffer_len), + offset, callback, completed)); +} + +bool File::Write(const void* buffer, + size_t buffer_len, + size_t offset, + FileIOCallback* callback, + bool* completed) { + return UNSAFE_TODO( + Write(base::span(static_cast<const uint8_t*>(buffer), buffer_len), offset, + callback, completed)); +} + } // namespace disk_cache
diff --git a/net/disk_cache/blockfile/file.h b/net/disk_cache/blockfile/file.h index 1477343..1e1b339 100644 --- a/net/disk_cache/blockfile/file.h +++ b/net/disk_cache/blockfile/file.h
@@ -10,6 +10,7 @@ #include <stddef.h> #include "base/files/file.h" +#include "base/memory/raw_span.h" #include "base/memory/ref_counted.h" #include "net/base/net_export.h" @@ -54,13 +55,43 @@ bool IsValid() const; // Performs synchronous IO. + // + // Read/Write the content from the file `offset` position, and the content + // will be placed in the `buffer`. If the read/write size is equal to the + // `buffer` size, it returns `true`, otherwise it returns `false`. + bool Read(base::span<uint8_t> buffer, size_t offset); + bool Write(base::span<const uint8_t> buffer, size_t offset); + + // DEPRECATED: Use the above `base::span` variant to avoid unsafe buffer + // usage. + // TODO(https://crbug.com/40284755): Remove this once the callers are gone. bool Read(void* buffer, size_t buffer_len, size_t offset); + + // DEPRECATED: Use the above `base::span` variant to avoid unsafe buffer + // usage. + // TODO(https://crbug.com/40284755): Remove this once the callers are gone. bool Write(const void* buffer, size_t buffer_len, size_t offset); // Performs asynchronous IO. callback will be called when the IO completes, // as an APC on the thread that queued the operation. + bool Read(base::span<uint8_t> buffer, + size_t offset, + FileIOCallback* callback, + bool* completed); + bool Write(base::span<const uint8_t> buffer, + size_t offset, + FileIOCallback* callback, + bool* completed); + + // DEPRECATED: Use the above `base::span` variant to avoid unsafe buffer + // usage. + // TODO(https://crbug.com/40284755): Remove this once the callers are gone. bool Read(void* buffer, size_t buffer_len, size_t offset, FileIOCallback* callback, bool* completed); + + // DEPRECATED: Use the above `base::span` variant to avoid unsafe buffer + // usage. + // TODO(https://crbug.com/40284755): Remove this once the callers are gone. bool Write(const void* buffer, size_t buffer_len, size_t offset, FileIOCallback* callback, bool* completed); @@ -84,12 +115,14 @@ private: // Performs the actual asynchronous write. If notify is set and there is no // callback, the call will be re-synchronized. - bool AsyncWrite(const void* buffer, size_t buffer_len, size_t offset, - FileIOCallback* callback, bool* completed); + bool AsyncWrite(base::span<const uint8_t> buffer, + size_t offset, + FileIOCallback* callback, + bool* completed); // Infrastructure for async IO. - int DoRead(void* buffer, size_t buffer_len, size_t offset); - int DoWrite(const void* buffer, size_t buffer_len, size_t offset); + int DoRead(base::raw_span<uint8_t> buffer, size_t offset); + int DoWrite(base::raw_span<const uint8_t> buffer, size_t offset); void OnOperationComplete(FileIOCallback* callback, int result); bool init_;
diff --git a/net/disk_cache/blockfile/file_ios.cc b/net/disk_cache/blockfile/file_ios.cc index 94ecdbe..92ebaee 100644 --- a/net/disk_cache/blockfile/file_ios.cc +++ b/net/disk_cache/blockfile/file_ios.cc
@@ -12,9 +12,12 @@ #include "base/check.h" #include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/functional/bind.h" #include "base/location.h" #include "base/memory/raw_ptr.h" +#include "base/memory/raw_span.h" +#include "base/numerics/checked_math.h" #include "base/task/thread_pool.h" #include "net/base/net_errors.h" #include "net/disk_cache/blockfile/in_flight_io.h" @@ -31,12 +34,16 @@ // is keeping track of all operations. When done, we notify the controller // (we do NOT invoke the callback), in the worker thead that completed the // operation. - FileBackgroundIO(disk_cache::File* file, const void* buf, size_t buf_len, - size_t offset, disk_cache::FileIOCallback* callback, + FileBackgroundIO(disk_cache::File* file, + base::span<uint8_t> buffer, + size_t offset, + disk_cache::FileIOCallback* callback, disk_cache::InFlightIO* controller) - : disk_cache::BackgroundIO(controller), callback_(callback), file_(file), - buf_(buf), buf_len_(buf_len), offset_(offset) { - } + : disk_cache::BackgroundIO(controller), + callback_(callback), + file_(file), + buffer_(buffer), + offset_(offset) {} FileBackgroundIO(const FileBackgroundIO&) = delete; FileBackgroundIO& operator=(const FileBackgroundIO&) = delete; @@ -63,8 +70,7 @@ raw_ptr<disk_cache::FileIOCallback> callback_; raw_ptr<disk_cache::File> file_; - raw_ptr<const void> buf_; - size_t buf_len_; + base::raw_span<uint8_t> buffer_; size_t offset_; }; @@ -82,10 +88,14 @@ // These methods start an asynchronous operation. The arguments have the same // semantics of the File asynchronous operations, with the exception that the // operation never finishes synchronously. - void PostRead(disk_cache::File* file, void* buf, size_t buf_len, - size_t offset, disk_cache::FileIOCallback* callback); - void PostWrite(disk_cache::File* file, const void* buf, size_t buf_len, - size_t offset, disk_cache::FileIOCallback* callback); + void PostRead(disk_cache::File* file, + base::span<uint8_t> buffer, + size_t offset, + disk_cache::FileIOCallback* callback); + void PostWrite(disk_cache::File* file, + base::span<uint8_t> buffer, + size_t offset, + disk_cache::FileIOCallback* callback); protected: // Invokes the users' completion callback at the end of the IO operation. @@ -100,8 +110,8 @@ // Runs on a worker thread. void FileBackgroundIO::Read() { - if (file_->Read(const_cast<void*>(buf_.get()), buf_len_, offset_)) { - result_ = static_cast<int>(buf_len_); + if (file_->Read(buffer_, offset_)) { + result_ = buffer_.size(); } else { result_ = net::ERR_CACHE_READ_FAILURE; } @@ -110,18 +120,20 @@ // Runs on a worker thread. void FileBackgroundIO::Write() { - bool rv = file_->Write(buf_, buf_len_, offset_); + bool rv = file_->Write(buffer_, offset_); - result_ = rv ? static_cast<int>(buf_len_) : net::ERR_CACHE_WRITE_FAILURE; + result_ = rv ? buffer_.size() : net::ERR_CACHE_WRITE_FAILURE; NotifyController(); } // --------------------------------------------------------------------------- -void FileInFlightIO::PostRead(disk_cache::File *file, void* buf, size_t buf_len, - size_t offset, disk_cache::FileIOCallback *callback) { - auto operation = base::MakeRefCounted<FileBackgroundIO>( - file, buf, buf_len, offset, callback, this); +void FileInFlightIO::PostRead(disk_cache::File* file, + base::span<uint8_t> buffer, + size_t offset, + disk_cache::FileIOCallback* callback) { + auto operation = base::MakeRefCounted<FileBackgroundIO>(file, buffer, offset, + callback, this); file->AddRef(); // Balanced on OnOperationComplete() base::ThreadPool::PostTask( @@ -131,11 +143,12 @@ OnOperationPosted(operation.get()); } -void FileInFlightIO::PostWrite(disk_cache::File* file, const void* buf, - size_t buf_len, size_t offset, - disk_cache::FileIOCallback* callback) { - auto operation = base::MakeRefCounted<FileBackgroundIO>( - file, buf, buf_len, offset, callback, this); +void FileInFlightIO::PostWrite(disk_cache::File* file, + base::span<uint8_t> buffer, + size_t offset, + disk_cache::FileIOCallback* callback) { + auto operation = base::MakeRefCounted<FileBackgroundIO>(file, buffer, offset, + callback, this); file->AddRef(); // Balanced on OnOperationComplete() base::ThreadPool::PostTask( @@ -203,61 +216,78 @@ return base_file_.IsValid(); } -bool File::Read(void* buffer, size_t buffer_len, size_t offset) { +bool File::Read(base::span<uint8_t> buffer, size_t offset) { DCHECK(base_file_.IsValid()); - if (buffer_len > static_cast<size_t>(std::numeric_limits<int32_t>::max()) || - offset > static_cast<size_t>(std::numeric_limits<int32_t>::max())) { + if (!base::IsValueInRangeForNumericType<int32_t>(buffer.size()) || + !base::IsValueInRangeForNumericType<int32_t>(offset)) { return false; } - int ret = UNSAFE_TODO( - base_file_.Read(offset, static_cast<char*>(buffer), buffer_len)); - return (static_cast<size_t>(ret) == buffer_len); + std::optional<size_t> ret = base_file_.Read(offset, buffer); + return ret == buffer.size(); } -bool File::Write(const void* buffer, size_t buffer_len, size_t offset) { +bool File::Write(base::span<const uint8_t> buffer, size_t offset) { DCHECK(base_file_.IsValid()); - if (buffer_len > static_cast<size_t>(std::numeric_limits<int32_t>::max()) || - offset > static_cast<size_t>(std::numeric_limits<int32_t>::max())) { + if (!base::IsValueInRangeForNumericType<int32_t>(buffer.size()) || + !base::IsValueInRangeForNumericType<int32_t>(offset)) { return false; } - int ret = UNSAFE_TODO( - base_file_.Write(offset, static_cast<const char*>(buffer), buffer_len)); - return (static_cast<size_t>(ret) == buffer_len); + std::optional<size_t> ret = base_file_.Write(offset, buffer); + return ret == buffer.size(); } // We have to increase the ref counter of the file before performing the IO to // prevent the completion to happen with an invalid handle (if the file is // closed while the IO is in flight). -bool File::Read(void* buffer, size_t buffer_len, size_t offset, - FileIOCallback* callback, bool* completed) { +bool File::Read(base::span<uint8_t> buffer, + size_t offset, + FileIOCallback* callback, + bool* completed) { DCHECK(base_file_.IsValid()); if (!callback) { if (completed) *completed = true; - return Read(buffer, buffer_len, offset); + return Read(buffer, offset); } - if (buffer_len > ULONG_MAX || offset > ULONG_MAX) + if (offset > ULONG_MAX) { return false; + } - GetFileInFlightIO()->PostRead(this, buffer, buffer_len, offset, callback); + GetFileInFlightIO()->PostRead(this, buffer, offset, callback); *completed = false; return true; } -bool File::Write(const void* buffer, size_t buffer_len, size_t offset, - FileIOCallback* callback, bool* completed) { +bool File::Write(base::span<const uint8_t> buffer, + size_t offset, + FileIOCallback* callback, + bool* completed) { DCHECK(base_file_.IsValid()); if (!callback) { if (completed) *completed = true; - return Write(buffer, buffer_len, offset); + return Write(buffer, offset); } - return AsyncWrite(buffer, buffer_len, offset, callback, completed); + if (offset > ULONG_MAX) { + return false; + } + + GetFileInFlightIO()->PostWrite( + this, + // SAFETY: Converting `base::span<const uint8_t>` to `base::span<uint8_t>` + // does not involve any other changes. + UNSAFE_BUFFERS( + base::span(const_cast<uint8_t*>(buffer.data()), buffer.size())), + offset, callback); + if (completed) { + *completed = false; + } + return true; } bool File::SetLength(size_t length) { @@ -300,17 +330,4 @@ return base_file_.GetPlatformFile(); } -bool File::AsyncWrite(const void* buffer, size_t buffer_len, size_t offset, - FileIOCallback* callback, bool* completed) { - DCHECK(base_file_.IsValid()); - if (buffer_len > ULONG_MAX || offset > ULONG_MAX) - return false; - - GetFileInFlightIO()->PostWrite(this, buffer, buffer_len, offset, callback); - - if (completed) - *completed = false; - return true; -} - } // namespace disk_cache
diff --git a/net/disk_cache/blockfile/file_posix.cc b/net/disk_cache/blockfile/file_posix.cc index 660138b..d272ee1 100644 --- a/net/disk_cache/blockfile/file_posix.cc +++ b/net/disk_cache/blockfile/file_posix.cc
@@ -13,6 +13,7 @@ #include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/location.h" +#include "base/numerics/checked_math.h" #include "base/run_loop.h" #include "base/task/thread_pool.h" #include "base/task/thread_pool/thread_pool_instance.h" @@ -38,65 +39,67 @@ return base_file_.IsValid(); } -bool File::Read(void* buffer, size_t buffer_len, size_t offset) { +bool File::Read(base::span<uint8_t> buffer, size_t offset) { DCHECK(base_file_.IsValid()); - if (buffer_len > static_cast<size_t>(std::numeric_limits<int32_t>::max()) || - offset > static_cast<size_t>(std::numeric_limits<int32_t>::max())) { + if (!base::IsValueInRangeForNumericType<int32_t>(buffer.size()) || + !base::IsValueInRangeForNumericType<int32_t>(offset)) { return false; } - int ret = UNSAFE_TODO( - base_file_.Read(offset, static_cast<char*>(buffer), buffer_len)); - return (static_cast<size_t>(ret) == buffer_len); + std::optional<size_t> ret = base_file_.Read(offset, buffer); + return ret == buffer.size(); } -bool File::Write(const void* buffer, size_t buffer_len, size_t offset) { +bool File::Write(base::span<const uint8_t> buffer, size_t offset) { DCHECK(base_file_.IsValid()); - if (buffer_len > static_cast<size_t>(std::numeric_limits<int32_t>::max()) || - offset > static_cast<size_t>(std::numeric_limits<int32_t>::max())) { + if (!base::IsValueInRangeForNumericType<int32_t>(buffer.size()) || + !base::IsValueInRangeForNumericType<int32_t>(offset)) { return false; } - int ret = UNSAFE_TODO( - base_file_.Write(offset, static_cast<const char*>(buffer), buffer_len)); - return (static_cast<size_t>(ret) == buffer_len); + std::optional<size_t> ret = base_file_.Write(offset, buffer); + return ret == buffer.size(); } -bool File::Read(void* buffer, size_t buffer_len, size_t offset, - FileIOCallback* callback, bool* completed) { +bool File::Read(base::span<uint8_t> buffer, + size_t offset, + FileIOCallback* callback, + bool* completed) { DCHECK(base_file_.IsValid()); if (!callback) { if (completed) *completed = true; - return Read(buffer, buffer_len, offset); + return Read(buffer, offset); } - if (buffer_len > static_cast<size_t>(std::numeric_limits<int32_t>::max()) || - offset > static_cast<size_t>(std::numeric_limits<int32_t>::max())) { + if (!base::IsValueInRangeForNumericType<int32_t>(buffer.size()) || + !base::IsValueInRangeForNumericType<int32_t>(offset)) { return false; } base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, {base::TaskPriority::USER_BLOCKING, base::MayBlock()}, - base::BindOnce(&File::DoRead, base::Unretained(this), buffer, buffer_len, - offset), + base::BindOnce(&File::DoRead, base::Unretained(this), buffer, offset), base::BindOnce(&File::OnOperationComplete, this, callback)); *completed = false; return true; } -bool File::Write(const void* buffer, size_t buffer_len, size_t offset, - FileIOCallback* callback, bool* completed) { +bool File::Write(base::span<const uint8_t> buffer, + size_t offset, + FileIOCallback* callback, + bool* completed) { DCHECK(base_file_.IsValid()); if (!callback) { - if (completed) + if (completed) { *completed = true; - return Write(buffer, buffer_len, offset); + } + return Write(buffer, offset); } - if (buffer_len > static_cast<size_t>(std::numeric_limits<int32_t>::max()) || - offset > static_cast<size_t>(std::numeric_limits<int32_t>::max())) { + if (!base::IsValueInRangeForNumericType<int32_t>(buffer.size()) || + !base::IsValueInRangeForNumericType<int32_t>(offset)) { return false; } @@ -106,8 +109,7 @@ // requests and changing the priority to BACKGROUND. base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, {base::TaskPriority::USER_BLOCKING, base::MayBlock()}, - base::BindOnce(&File::DoWrite, base::Unretained(this), buffer, buffer_len, - offset), + base::BindOnce(&File::DoWrite, base::Unretained(this), buffer, offset), base::BindOnce(&File::OnOperationComplete, this, callback)); *completed = false; @@ -155,17 +157,19 @@ } // Runs on a worker thread. -int File::DoRead(void* buffer, size_t buffer_len, size_t offset) { - if (Read(const_cast<void*>(buffer), buffer_len, offset)) - return static_cast<int>(buffer_len); +int File::DoRead(base::raw_span<uint8_t> buffer, size_t offset) { + if (Read(buffer, offset)) { + return static_cast<int>(buffer.size()); + } return net::ERR_CACHE_READ_FAILURE; } // Runs on a worker thread. -int File::DoWrite(const void* buffer, size_t buffer_len, size_t offset) { - if (Write(const_cast<void*>(buffer), buffer_len, offset)) - return static_cast<int>(buffer_len); +int File::DoWrite(base::raw_span<const uint8_t> buffer, size_t offset) { + if (Write(buffer, offset)) { + return static_cast<int>(buffer.size()); + } return net::ERR_CACHE_WRITE_FAILURE; }
diff --git a/net/disk_cache/blockfile/file_win.cc b/net/disk_cache/blockfile/file_win.cc index 1698359..4c18f92 100644 --- a/net/disk_cache/blockfile/file_win.cc +++ b/net/disk_cache/blockfile/file_win.cc
@@ -138,46 +138,49 @@ return base_file_.IsValid() || sync_base_file_.IsValid(); } -bool File::Read(void* buffer, size_t buffer_len, size_t offset) { +bool File::Read(base::span<uint8_t> buffer, size_t offset) { DCHECK(init_); - if (buffer_len > ULONG_MAX || offset > LONG_MAX) + if (buffer.size() > ULONG_MAX || offset > LONG_MAX) { return false; + } - int ret = UNSAFE_TODO( - sync_base_file_.Read(offset, static_cast<char*>(buffer), buffer_len)); - return static_cast<int>(buffer_len) == ret; + std::optional<size_t> ret = sync_base_file_.Read(offset, buffer); + return ret == buffer.size(); } -bool File::Write(const void* buffer, size_t buffer_len, size_t offset) { +bool File::Write(base::span<const uint8_t> buffer, size_t offset) { DCHECK(init_); - if (buffer_len > ULONG_MAX || offset > ULONG_MAX) + if (buffer.size() > ULONG_MAX || offset > ULONG_MAX) { return false; + } - int ret = UNSAFE_TODO(sync_base_file_.Write( - offset, static_cast<const char*>(buffer), buffer_len)); - return static_cast<int>(buffer_len) == ret; + std::optional<size_t> ret = sync_base_file_.Write(offset, buffer); + return ret == buffer.size(); } // We have to increase the ref counter of the file before performing the IO to // prevent the completion to happen with an invalid handle (if the file is // closed while the IO is in flight). -bool File::Read(void* buffer, size_t buffer_len, size_t offset, - FileIOCallback* callback, bool* completed) { +bool File::Read(base::span<uint8_t> buffer, + size_t offset, + FileIOCallback* callback, + bool* completed) { DCHECK(init_); if (!callback) { if (completed) *completed = true; - return Read(buffer, buffer_len, offset); + return Read(buffer, offset); } - if (buffer_len > ULONG_MAX || offset > ULONG_MAX) + if (buffer.size() > ULONG_MAX || offset > ULONG_MAX) { return false; + } MyOverlapped* data = new MyOverlapped(this, offset, callback); - DWORD size = static_cast<DWORD>(buffer_len); + DWORD size = static_cast<DWORD>(buffer.size()); DWORD actual; - if (!ReadFile(base_file_.GetPlatformFile(), buffer, size, &actual, + if (!ReadFile(base_file_.GetPlatformFile(), buffer.data(), size, &actual, data->overlapped())) { *completed = false; if (GetLastError() == ERROR_IO_PENDING) @@ -194,16 +197,18 @@ return *completed; } -bool File::Write(const void* buffer, size_t buffer_len, size_t offset, - FileIOCallback* callback, bool* completed) { +bool File::Write(base::span<const uint8_t> buffer, + size_t offset, + FileIOCallback* callback, + bool* completed) { DCHECK(init_); if (!callback) { if (completed) *completed = true; - return Write(buffer, buffer_len, offset); + return Write(buffer, offset); } - return AsyncWrite(buffer, buffer_len, offset, callback, completed); + return AsyncWrite(buffer, offset, callback, completed); } File::~File() = default; @@ -214,19 +219,22 @@ sync_base_file_.GetPlatformFile(); } -bool File::AsyncWrite(const void* buffer, size_t buffer_len, size_t offset, - FileIOCallback* callback, bool* completed) { +bool File::AsyncWrite(base::span<const uint8_t> buffer, + size_t offset, + FileIOCallback* callback, + bool* completed) { DCHECK(init_); DCHECK(callback); DCHECK(completed); - if (buffer_len > ULONG_MAX || offset > ULONG_MAX) + if (buffer.size() > ULONG_MAX || offset > ULONG_MAX) { return false; + } MyOverlapped* data = new MyOverlapped(this, offset, callback); - DWORD size = static_cast<DWORD>(buffer_len); + DWORD size = static_cast<DWORD>(buffer.size()); DWORD actual; - if (!WriteFile(base_file_.GetPlatformFile(), buffer, size, &actual, + if (!WriteFile(base_file_.GetPlatformFile(), buffer.data(), size, &actual, data->overlapped())) { *completed = false; if (GetLastError() == ERROR_IO_PENDING)
diff --git a/net/disk_cache/entry_unittest.cc b/net/disk_cache/entry_unittest.cc index dce9fa0..c51de4d 100644 --- a/net/disk_cache/entry_unittest.cc +++ b/net/disk_cache/entry_unittest.cc
@@ -5518,6 +5518,35 @@ SparseReadLength0(); } +TEST_F(DiskCacheEntryTest, BlockFileKeyLenCalc) { + constexpr int kFirstBlockPortion = + sizeof(disk_cache::EntryStore) - offsetof(disk_cache::EntryStore, key); + constexpr int kOtherBlocksPortion = sizeof(disk_cache::EntryStore); + EXPECT_EQ(1, + disk_cache::EntryImpl::NumBlocksForEntry(kFirstBlockPortion - 1)); + // This needs 2 blocks for terminating nul. This pattern continues on below. + EXPECT_EQ(2, disk_cache::EntryImpl::NumBlocksForEntry(kFirstBlockPortion)); + + EXPECT_EQ(2, disk_cache::EntryImpl::NumBlocksForEntry( + kFirstBlockPortion + kOtherBlocksPortion - 1)); + EXPECT_EQ(3, disk_cache::EntryImpl::NumBlocksForEntry(kFirstBlockPortion + + kOtherBlocksPortion)); + + EXPECT_EQ(3, disk_cache::EntryImpl::NumBlocksForEntry( + kFirstBlockPortion + 2 * kOtherBlocksPortion - 1)); + EXPECT_EQ(4, disk_cache::EntryImpl::NumBlocksForEntry( + kFirstBlockPortion + 2 * kOtherBlocksPortion)); + + EXPECT_EQ(4, disk_cache::EntryImpl::NumBlocksForEntry( + kFirstBlockPortion + 3 * kOtherBlocksPortion - 1)); + + // And this now requires an external block. + EXPECT_EQ(1, disk_cache::EntryImpl::NumBlocksForEntry( + kFirstBlockPortion + 3 * kOtherBlocksPortion)); + EXPECT_EQ(kFirstBlockPortion + 3 * kOtherBlocksPortion, + disk_cache::kMaxInternalKeyLength + 1); +} + class DiskCacheSimplePrefetchTest : public DiskCacheEntryTest { public: DiskCacheSimplePrefetchTest() = default;
diff --git a/pdf/pdf_features.cc b/pdf/pdf_features.cc index 7c534b6..655719c0 100644 --- a/pdf/pdf_features.cc +++ b/pdf/pdf_features.cc
@@ -45,6 +45,7 @@ "PdfSaveOriginalFromMemory", base::FEATURE_DISABLED_BY_DEFAULT); +// TODO(crbug.com/419436546): Deprecated, remove. BASE_FEATURE(kPdfSearchify, "PdfSearchify", base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kPdfSearchifySave,
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc index 19f5c95..5692c6c 100644 --- a/pdf/pdfium/pdfium_engine.cc +++ b/pdf/pdfium/pdfium_engine.cc
@@ -4348,8 +4348,7 @@ void PDFiumEngine::StartSearchify( GetOcrMaxImageDimensionCallbackAsync get_max_dimension, PerformOcrCallbackAsync perform_ocr_callback) { - if (!base::FeatureList::IsEnabled(chrome_pdf::features::kPdfSearchify) || - !base::FeatureList::IsEnabled(ax::mojom::features::kScreenAIOCREnabled)) { + if (!base::FeatureList::IsEnabled(ax::mojom::features::kScreenAIOCREnabled)) { return; } // Searchify requests may be sent to the engine when PDF pages are loaded and @@ -4403,8 +4402,7 @@ return; } - if (!base::FeatureList::IsEnabled(chrome_pdf::features::kPdfSearchify) || - !base::FeatureList::IsEnabled(ax::mojom::features::kScreenAIOCREnabled)) { + if (!base::FeatureList::IsEnabled(ax::mojom::features::kScreenAIOCREnabled)) { return; }
diff --git a/pdf/pdfium/pdfium_font_helpers.cc b/pdf/pdfium/pdfium_font_helpers.cc index afdaffb..c381d41 100644 --- a/pdf/pdfium/pdfium_font_helpers.cc +++ b/pdf/pdfium/pdfium_font_helpers.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "pdf/pdfium/pdfium_font_helpers.h" #include <algorithm> #include <optional> +#include <string_view> #include "base/i18n/encoding_detection.h" #include "base/i18n/icu_string_conversions.h" @@ -23,6 +19,49 @@ namespace { +struct PdfFontSubstitution { + std::string_view pdf_name; + std::string_view face; + bool bold; + bool italic; +}; + +constexpr PdfFontSubstitution kPdfFontSubstitutions[] = { + {"Courier", "Courier New", false, false}, + {"Courier-Bold", "Courier New", true, false}, + {"Courier-BoldOblique", "Courier New", true, true}, + {"Courier-Oblique", "Courier New", false, true}, + {"Helvetica", "Arial", false, false}, + {"Helvetica-Bold", "Arial", true, false}, + {"Helvetica-BoldOblique", "Arial", true, true}, + {"Helvetica-Oblique", "Arial", false, true}, + {"Times-Roman", "Times New Roman", false, false}, + {"Times-Bold", "Times New Roman", true, false}, + {"Times-BoldItalic", "Times New Roman", true, true}, + {"Times-Italic", "Times New Roman", false, true}, + + // MS P?(Mincho|Gothic) are the most notable fonts in Japanese PDF files + // without embedding the glyphs. Sometimes the font names are encoded + // in Japanese Windows's locale (CP932/Shift_JIS) without space. + // Most Linux systems don't have the exact font, but for outsourcing + // fontconfig to find substitutable font in the system, we pass ASCII + // font names to it. + {"MS-PGothic", "MS PGothic", false, false}, + {"MS-Gothic", "MS Gothic", false, false}, + {"MS-PMincho", "MS PMincho", false, false}, + {"MS-Mincho", "MS Mincho", false, false}, + // MS PGothic in Shift_JIS encoding. + {"\x82\x6C\x82\x72\x82\x6F\x83\x53\x83\x56\x83\x62\x83\x4E", "MS PGothic", + false, false}, + // MS Gothic in Shift_JIS encoding. + {"\x82\x6C\x82\x72\x83\x53\x83\x56\x83\x62\x83\x4E", "MS Gothic", false, + false}, + // MS PMincho in Shift_JIS encoding. + {"\x82\x6C\x82\x72\x82\x6F\x96\xBE\x92\xA9", "MS PMincho", false, false}, + // MS Mincho in Shift_JIS encoding. + {"\x82\x6C\x82\x72\x96\xBE\x92\xA9", "MS Mincho", false, false}, +}; + blink::WebFontDescription::Weight WeightToBlinkWeight(int weight) { static_assert(blink::WebFontDescription::kWeight100 == 0, "Blink Weight min"); static_assert(blink::WebFontDescription::kWeight900 == 8, "Blink Weight max"); @@ -43,7 +82,8 @@ const char* face) { // Pretend the system does not have the Symbol font to force a fallback to // the built in Symbol font in CFX_FontMapper::FindSubstFont(). - if (strcmp(face, "Symbol") == 0) { + static constexpr std::string_view kSymbol("Symbol"); + if (face == kSymbol) { return std::nullopt; } @@ -56,51 +96,10 @@ desc.generic_family = blink::WebFontDescription::kGenericFamilyStandard; } - static constexpr struct { - const char* pdf_name; - const char* face; - bool bold; - bool italic; - } kPdfFontSubstitutions[] = { - {"Courier", "Courier New", false, false}, - {"Courier-Bold", "Courier New", true, false}, - {"Courier-BoldOblique", "Courier New", true, true}, - {"Courier-Oblique", "Courier New", false, true}, - {"Helvetica", "Arial", false, false}, - {"Helvetica-Bold", "Arial", true, false}, - {"Helvetica-BoldOblique", "Arial", true, true}, - {"Helvetica-Oblique", "Arial", false, true}, - {"Times-Roman", "Times New Roman", false, false}, - {"Times-Bold", "Times New Roman", true, false}, - {"Times-BoldItalic", "Times New Roman", true, true}, - {"Times-Italic", "Times New Roman", false, true}, - - // MS P?(Mincho|Gothic) are the most notable fonts in Japanese PDF files - // without embedding the glyphs. Sometimes the font names are encoded - // in Japanese Windows's locale (CP932/Shift_JIS) without space. - // Most Linux systems don't have the exact font, but for outsourcing - // fontconfig to find substitutable font in the system, we pass ASCII - // font names to it. - {"MS-PGothic", "MS PGothic", false, false}, - {"MS-Gothic", "MS Gothic", false, false}, - {"MS-PMincho", "MS PMincho", false, false}, - {"MS-Mincho", "MS Mincho", false, false}, - // MS PGothic in Shift_JIS encoding. - {"\x82\x6C\x82\x72\x82\x6F\x83\x53\x83\x56\x83\x62\x83\x4E", "MS PGothic", - false, false}, - // MS Gothic in Shift_JIS encoding. - {"\x82\x6C\x82\x72\x83\x53\x83\x56\x83\x62\x83\x4E", "MS Gothic", false, - false}, - // MS PMincho in Shift_JIS encoding. - {"\x82\x6C\x82\x72\x82\x6F\x96\xBE\x92\xA9", "MS PMincho", false, false}, - // MS Mincho in Shift_JIS encoding. - {"\x82\x6C\x82\x72\x96\xBE\x92\xA9", "MS Mincho", false, false}, - }; - // Map from the standard PDF fonts to TrueType font names. bool found_substitution = false; for (const auto& substitution : kPdfFontSubstitutions) { - if (strcmp(face, substitution.pdf_name) == 0) { + if (face == substitution.pdf_name) { desc.family = blink::WebString::FromUTF8(substitution.face); if (substitution.bold) { desc.weight = blink::WebFontDescription::kWeightBold;
diff --git a/pdf/pdfium/pdfium_ocr.cc b/pdf/pdfium/pdfium_ocr.cc index 34a3ca3..a0310e12d 100644 --- a/pdf/pdfium/pdfium_ocr.cc +++ b/pdf/pdfium/pdfium_ocr.cc
@@ -39,8 +39,7 @@ SkBitmap GetImageForOcr(FPDF_DOCUMENT doc, FPDF_PAGE page, FPDF_PAGEOBJECT page_object, - uint32_t max_image_dimension, - bool rotate_image_to_upright) { + uint32_t max_image_dimension) { SkBitmap bitmap; if (FPDFPageObj_GetType(page_object) != FPDF_PAGEOBJ_IMAGE) { @@ -86,37 +85,13 @@ effective_height = pixel_height; } - if (rotate_image_to_upright) { - // Scale the matrix to get image with highest resolution and keep the - // rotation. If image is stretched differently in horizontal and vertical - // directions, the one with no enlargement of the original height and width - // is selected. - float width_scale = hypotf(original_matrix.a, original_matrix.c); - float height_scale = hypotf(original_matrix.b, original_matrix.d); - if (width_scale == 0 || height_scale == 0) { - return bitmap; - } - float ratio = std::min(effective_width / width_scale, - effective_height / height_scale); - const FS_MATRIX new_matrix = { - original_matrix.a * ratio, original_matrix.b * ratio, - original_matrix.c * ratio, original_matrix.d * ratio, - original_matrix.e, original_matrix.f}; + // Scale the image to the highest (capped) resolution while keeping its + // rotation as it is. + const FS_MATRIX new_matrix = {effective_width, 0, 0, effective_height, 0, 0}; - if (!FPDFPageObj_SetMatrix(page_object, &new_matrix)) { - DLOG(ERROR) << "Failed to set new matrix on image"; - return bitmap; - } - } else { - // Scale the image to the highest (capped) resolution, but do not rotate the - // image to make it upright. - const FS_MATRIX new_matrix = {effective_width, 0, 0, - effective_height, 0, 0}; - - if (!FPDFPageObj_SetMatrix(page_object, &new_matrix)) { - DLOG(ERROR) << "Failed to set new matrix on image"; - return bitmap; - } + if (!FPDFPageObj_SetMatrix(page_object, &new_matrix)) { + DLOG(ERROR) << "Failed to set new matrix on image"; + return bitmap; } ScopedFPDFBitmap raw_bitmap(
diff --git a/pdf/pdfium/pdfium_ocr.h b/pdf/pdfium/pdfium_ocr.h index 17c2536..04e2123 100644 --- a/pdf/pdfium/pdfium_ocr.h +++ b/pdf/pdfium/pdfium_ocr.h
@@ -11,14 +11,10 @@ namespace chrome_pdf { -// TODO(crbug.com/c/360803943): Remove `rotate_image_to_upright` when PDF OCR -// support is removed and set the default behavior to -// rotate_image_to_upright = false. SkBitmap GetImageForOcr(FPDF_DOCUMENT doc, FPDF_PAGE page, FPDF_PAGEOBJECT page_object, - uint32_t max_image_dimension, - bool rotate_image_to_upright); + uint32_t max_image_dimension); // Returns image bound's size in page coordinates. Returns (0,0) if fails. gfx::SizeF GetImageSize(FPDF_PAGEOBJECT page_object);
diff --git a/pdf/pdfium/pdfium_on_demand_searchifier_unittest.cc b/pdf/pdfium/pdfium_on_demand_searchifier_unittest.cc index 1764938..4d818cc 100644 --- a/pdf/pdfium/pdfium_on_demand_searchifier_unittest.cc +++ b/pdf/pdfium/pdfium_on_demand_searchifier_unittest.cc
@@ -16,11 +16,9 @@ #include "base/strings/utf_string_conversions.h" #include "base/task/single_thread_task_runner.h" #include "base/test/metrics/histogram_tester.h" -#include "base/test/scoped_feature_list.h" #include "base/test/test_future.h" #include "base/time/time.h" #include "pdf/accessibility_structs.h" -#include "pdf/pdf_features.h" #include "pdf/pdfium/pdfium_print.h" #include "pdf/pdfium/pdfium_range.h" #include "pdf/pdfium/pdfium_test_base.h" @@ -126,11 +124,6 @@ class PDFiumOnDemandSearchifierTest : public PDFiumTestBase { public: - PDFiumOnDemandSearchifierTest() { - scoped_feature_list_.InitAndEnableFeature( - chrome_pdf::features::kPdfSearchify); - } - void CreateEngine(const base::FilePath::CharType* test_filename) { engine_ = InitializeEngine(&client_, test_filename); ASSERT_TRUE(engine_) << test_filename; @@ -221,7 +214,6 @@ } private: - base::test::ScopedFeatureList scoped_feature_list_; std::unique_ptr<PDFiumEngine> engine_; SearchifierTestClient client_; int performed_ocrs_ = 0;
diff --git a/pdf/pdfium/pdfium_page.cc b/pdf/pdfium/pdfium_page.cc index 01ddaf5..bacd323 100644 --- a/pdf/pdfium/pdfium_page.cc +++ b/pdf/pdfium/pdfium_page.cc
@@ -53,7 +53,6 @@ #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) #include "third_party/skia/include/core/SkBitmap.h" -#include "ui/gfx/skbitmap_operations.h" #endif using printing::ConvertUnitFloat; @@ -951,31 +950,8 @@ int max_image_dimension) { FPDF_PAGE page = GetPage(); FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, page_object_index); - bool rotate_image_to_upright = - !base::FeatureList::IsEnabled(chrome_pdf::features::kPdfSearchify); - SkBitmap bitmap = ::chrome_pdf::GetImageForOcr( - engine_->doc(), page, page_object, max_image_dimension, - rotate_image_to_upright); - - if (!rotate_image_to_upright) { - return bitmap; - } - SkBitmapOperations::RotationAmount rotation; - switch (FPDFPage_GetRotation(page)) { - case 0: - return bitmap; - case 1: - rotation = SkBitmapOperations::RotationAmount::ROTATION_90_CW; - break; - case 2: - rotation = SkBitmapOperations::RotationAmount::ROTATION_180_CW; - break; - case 3: - rotation = SkBitmapOperations::RotationAmount::ROTATION_270_CW; - break; - } - - return SkBitmapOperations::Rotate(bitmap, rotation); + return ::chrome_pdf::GetImageForOcr(engine_->doc(), page, page_object, + max_image_dimension); } void PDFiumPage::OnSearchifyGotOcrResult(bool added_text) {
diff --git a/pdf/pdfium/pdfium_page_unittest.cc b/pdf/pdfium/pdfium_page_unittest.cc index bdc1187..134e984 100644 --- a/pdf/pdfium/pdfium_page_unittest.cc +++ b/pdf/pdfium/pdfium_page_unittest.cc
@@ -17,7 +17,6 @@ #include "build/build_config.h" #include "pdf/accessibility_structs.h" #include "pdf/buildflags.h" -#include "pdf/pdf_features.h" #include "pdf/pdfium/pdfium_engine.h" #include "pdf/pdfium/pdfium_test_base.h" #include "pdf/test/test_client.h" @@ -628,17 +627,9 @@ SkBitmap image_bitmap = engine->GetImageForOcr( /*page_index=*/0, page.images_[0].page_object_index); - if (base::FeatureList::IsEnabled(chrome_pdf::features::kPdfSearchify)) { - // When PDF Searchify is enabled, page rotation does not affect the images - // that are sent to OCR. - EXPECT_EQ(image_bitmap.width(), 100); - EXPECT_EQ(image_bitmap.height(), 25); - } else { - // This page is rotated, therefore the extracted image size is 25x100 while - // the stored image is 100x25. - EXPECT_EQ(image_bitmap.width(), 25); - EXPECT_EQ(image_bitmap.height(), 100); - } + // Page rotation does not affect the images that are sent to OCR. + EXPECT_EQ(image_bitmap.width(), 100); + EXPECT_EQ(image_bitmap.height(), 25); } TEST_P(PDFiumPageImageForOcrTest, NonImage) {
diff --git a/pdf/pdfium/pdfium_range.cc b/pdf/pdfium/pdfium_range.cc index c4e3e616..6d7381f 100644 --- a/pdf/pdfium/pdfium_range.cc +++ b/pdf/pdfium/pdfium_range.cc
@@ -8,7 +8,6 @@ #include "base/check_op.h" #include "base/containers/span.h" -#include "base/feature_list.h" #include "base/strings/string_util.h" #include "pdf/accessibility_structs.h" #include "pdf/pdfium/pdfium_api_string_buffer_adapter.h" @@ -21,12 +20,6 @@ namespace { -// Enables AccessibilityTextRunInfo-based screen rects. -// TODO(crbug.com/40448046): Remove this kill switch after a safe rollout. -BASE_FEATURE(kPdfAccessibilityTextRunInfoScreenRects, - "PdfAccessibilityTextRunInfoScreenRects", - base::FEATURE_ENABLED_BY_DEFAULT); - void AdjustForBackwardsRange(int& index, int& count) { if (count < 0) { count *= -1; @@ -195,25 +188,6 @@ DCHECK_LT(char_index, FPDFText_CountChars(text_page)) << " start: " << char_index_ << " count: " << char_count_; - if (!base::FeatureList::IsEnabled(kPdfAccessibilityTextRunInfoScreenRects)) { - int count = FPDFText_CountRects(text_page, char_index, char_count); - for (int i = 0; i < count; ++i) { - double left; - double top; - double right; - double bottom; - FPDFText_GetRect(text_page, i, &left, &top, &right, &bottom); - gfx::Rect rect = page_->PageToScreen(point, zoom, left, top, right, - bottom, orientation); - if (rect.IsEmpty()) { - continue; - } - cached_screen_rects_.push_back(rect); - } - - return cached_screen_rects_; - } - std::vector<ScreenRectTextRunInfo> text_runs; const int end_char_index = char_index + char_count; bool reached_end = false;
diff --git a/pdf/pdfium/pdfium_searchify.cc b/pdf/pdfium/pdfium_searchify.cc index 8e8119c0..aeb21e2 100644 --- a/pdf/pdfium/pdfium_searchify.cc +++ b/pdf/pdfium/pdfium_searchify.cc
@@ -286,8 +286,7 @@ // GetImageForOcr() checks for null `image`. FPDF_PAGEOBJECT image = FPDFPage_GetObject(page.get(), object_index); SkBitmap bitmap = GetImageForOcr(document.get(), page.get(), image, - screen_ai::GetMaxDimensionForOCR(), - /*rotate_image_to_upright=*/false); + screen_ai::GetMaxDimensionForOCR()); // The object is not an image or failed to get the bitmap from the image. if (bitmap.empty()) { continue;
diff --git a/remoting/base/typed_buffer.h b/remoting/base/typed_buffer.h index 20e55878..a190d21 100644 --- a/remoting/base/typed_buffer.h +++ b/remoting/base/typed_buffer.h
@@ -6,13 +6,14 @@ #ifndef REMOTING_BASE_TYPED_BUFFER_H_ #define REMOTING_BASE_TYPED_BUFFER_H_ -#include <assert.h> #include <stdint.h> #include <algorithm> -#include <memory> #include <type_traits> +#include "base/check.h" +#include "base/containers/heap_array.h" + namespace remoting { // A scoper for a variable-length structure such as SID, SECURITY_DESCRIPTOR and @@ -26,9 +27,9 @@ TypedBuffer() = default; // Creates an instance of the object allocating a buffer of the given size. - constexpr explicit TypedBuffer(uint32_t length) : length_(length) { - if (length_ > 0) { - buffer_ = std::make_unique<uint8_t[]>(length); + constexpr explicit TypedBuffer(uint32_t length) { + if (length > 0) { + buffer_ = base::HeapArray<uint8_t>::Uninit(length); } } @@ -45,46 +46,44 @@ } // Accessors to get the owned buffer. - // operator* and operator-> will assert() if there is no current buffer. + // operator* and operator-> are fatal if there is no current buffer. T& operator*() { - assert(buffer_); - return *(reinterpret_cast<T*>(buffer_.get())); + CHECK(!buffer_.empty()); + return *(reinterpret_cast<T*>(buffer_.data())); } T* operator->() { - assert(buffer_); - return reinterpret_cast<T*>(buffer_.get()); + CHECK(!buffer_.empty()); + return reinterpret_cast<T*>(buffer_.data()); } - T* get() { return buffer_ ? reinterpret_cast<T*>(&buffer_[0]) : nullptr; } + T* get() { + return buffer_.empty() ? nullptr : reinterpret_cast<T*>(buffer_.data()); + } // `const` variants of the above. const T& operator*() const { - assert(buffer_); - return *(reinterpret_cast<const T*>(buffer_.get())); + CHECK(!buffer_.empty()); + return *(reinterpret_cast<const T*>(buffer_.data())); } const T* operator->() const { - assert(buffer_); - return reinterpret_cast<const T*>(buffer_.get()); + CHECK(!buffer_.empty()); + return reinterpret_cast<const T*>(buffer_.data()); } const T* get() const { - return buffer_ ? reinterpret_cast<const T*>(&buffer_[0]) : nullptr; + return buffer_.empty() ? nullptr + : reinterpret_cast<const T*>(buffer_.data()); } - uint32_t length() const { return length_; } + size_t length() const { return buffer_.size(); } - explicit operator bool() const { return buffer_.operator bool(); } + explicit operator bool() const { return !buffer_.empty(); } // Swap two buffers. void Swap(TypedBuffer& other) { std::swap(buffer_, other.buffer_); - std::swap(length_, other.length_); } private: - // Points to the owned buffer. - std::unique_ptr<uint8_t[]> buffer_; - - // Length of the owned buffer in bytes. - uint32_t length_ = 0; + base::HeapArray<uint8_t> buffer_; }; } // namespace remoting
diff --git a/remoting/host/BUILD.gn b/remoting/host/BUILD.gn index 6c7b85d3..cfc150f 100644 --- a/remoting/host/BUILD.gn +++ b/remoting/host/BUILD.gn
@@ -400,8 +400,6 @@ "host_power_save_blocker.h", "host_secret.cc", "host_secret.h", - "host_status_logger.cc", - "host_status_logger.h", "host_status_monitor.cc", "host_status_monitor.h", "host_status_observer.h", @@ -459,8 +457,6 @@ "remoting_register_support_host_request.h", "resizing_host_observer.cc", "resizing_host_observer.h", - "server_log_entry_host.cc", - "server_log_entry_host.h", "session_policies_from_dict.cc", "session_policies_from_dict.h", "shutdown_watchdog.cc", @@ -807,7 +803,6 @@ "host_experiment_session_plugin_unittest.cc", "host_extension_session_manager_unittest.cc", "host_power_save_blocker_unittest.cc", - "host_status_logger_unittest.cc", "input_monitor/local_input_monitor_unittest.cc", "ipc_desktop_environment_unittest.cc", "it2me/it2me_confirmation_dialog_proxy_unittest.cc", @@ -825,7 +820,6 @@ "remoting_register_support_host_request_unittest.cc", "resizing_host_observer_unittest.cc", "resources_unittest.cc", - "server_log_entry_host_unittest.cc", "session_policies_from_dict_unittest.cc", "setup/host_starter_oauth_helper_unittest.cc", "setup/me2me_native_messaging_host_unittest.cc",
diff --git a/remoting/host/heartbeat_sender.cc b/remoting/host/heartbeat_sender.cc index e1a2b7c6..2ef3ad0 100644 --- a/remoting/host/heartbeat_sender.cc +++ b/remoting/host/heartbeat_sender.cc
@@ -25,7 +25,6 @@ #include "remoting/base/protobuf_http_request_config.h" #include "remoting/base/service_urls.h" #include "remoting/host/host_config.h" -#include "remoting/host/server_log_entry_host.h" #include "remoting/signaling/ftl_signal_strategy.h" #include "remoting/signaling/signaling_address.h" #include "services/network/public/cpp/shared_url_loader_factory.h"
diff --git a/remoting/host/host_status_logger.cc b/remoting/host/host_status_logger.cc deleted file mode 100644 index 7ef81e0..0000000 --- a/remoting/host/host_status_logger.cc +++ /dev/null
@@ -1,69 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "remoting/host/host_status_logger.h" - -#include "base/functional/bind.h" -#include "remoting/base/constants.h" -#include "remoting/host/host_status_monitor.h" -#include "remoting/host/server_log_entry_host.h" -#include "remoting/protocol/transport.h" -#include "remoting/signaling/server_log_entry.h" - -namespace remoting { - -HostStatusLogger::HostStatusLogger(scoped_refptr<HostStatusMonitor> monitor, - LogToServer* log_to_server) - : log_to_server_(log_to_server), monitor_(monitor) { - DCHECK(log_to_server_); - DCHECK(monitor_); - monitor_->AddStatusObserver(this); -} - -HostStatusLogger::~HostStatusLogger() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - monitor_->RemoveStatusObserver(this); -} - -void HostStatusLogger::LogSessionStateChange(const std::string& jid, - bool connected) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - std::unique_ptr<ServerLogEntry> entry( - MakeLogEntryForSessionStateChange(connected)); - AddHostFieldsToLogEntry(entry.get()); - entry->AddModeField(log_to_server_->mode()); - - if (connected && connection_route_type_.count(jid) > 0) { - AddConnectionTypeToLogEntry(entry.get(), connection_route_type_[jid]); - } - - log_to_server_->Log(*entry.get()); -} - -void HostStatusLogger::OnClientConnected(const std::string& jid) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - LogSessionStateChange(jid, true); -} - -void HostStatusLogger::OnClientDisconnected(const std::string& jid) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - LogSessionStateChange(jid, false); - connection_route_type_.erase(jid); -} - -void HostStatusLogger::OnClientRouteChange( - const std::string& jid, - const std::string& channel_name, - const protocol::TransportRoute& route) { - // Store connection type for the video channel. It is logged later - // when client authentication is finished. For WebRTC clients, the - // route-change notification is not per-channel, so the channel_name is - // empty. - if (channel_name.empty() || channel_name == kVideoChannelName) { - connection_route_type_[jid] = route.type; - } -} - -} // namespace remoting
diff --git a/remoting/host/host_status_logger.h b/remoting/host/host_status_logger.h deleted file mode 100644 index 76407bf..0000000 --- a/remoting/host/host_status_logger.h +++ /dev/null
@@ -1,60 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef REMOTING_HOST_HOST_STATUS_LOGGER_H_ -#define REMOTING_HOST_HOST_STATUS_LOGGER_H_ - -#include <map> - -#include "base/memory/raw_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/sequence_checker.h" -#include "remoting/host/host_status_observer.h" -#include "remoting/protocol/transport.h" -#include "remoting/signaling/log_to_server.h" - -namespace remoting { - -class HostStatusMonitor; - -// HostStatusLogger sends host log entries to a server. -// The contents of the log entries are described in server_log_entry_host.cc. -// They do not contain any personally identifiable information. -class HostStatusLogger : public HostStatusObserver { - public: - HostStatusLogger(scoped_refptr<HostStatusMonitor> monitor, - LogToServer* log_to_server); - - HostStatusLogger(const HostStatusLogger&) = delete; - HostStatusLogger& operator=(const HostStatusLogger&) = delete; - - ~HostStatusLogger() override; - - // Logs a session state change. Currently, this is either - // connection or disconnection. - void LogSessionStateChange(const std::string& jid, bool connected); - - // HostStatusObserver interface. - void OnClientConnected(const std::string& jid) override; - void OnClientDisconnected(const std::string& jid) override; - void OnClientRouteChange(const std::string& jid, - const std::string& channel_name, - const protocol::TransportRoute& route) override; - - private: - raw_ptr<LogToServer> log_to_server_; - - scoped_refptr<HostStatusMonitor> monitor_; - - // A map from client JID to the route type of that client's connection to - // this host. - std::map<std::string, protocol::TransportRoute::RouteType> - connection_route_type_; - - SEQUENCE_CHECKER(sequence_checker_); -}; - -} // namespace remoting - -#endif // REMOTING_HOST_HOST_STATUS_LOGGER_H_
diff --git a/remoting/host/host_status_logger_unittest.cc b/remoting/host/host_status_logger_unittest.cc deleted file mode 100644 index fd78047b..0000000 --- a/remoting/host/host_status_logger_unittest.cc +++ /dev/null
@@ -1,257 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "remoting/host/host_status_logger.h" - -#include "base/run_loop.h" -#include "base/test/task_environment.h" -#include "remoting/host/host_status_monitor.h" -#include "remoting/signaling/mock_signal_strategy.h" -#include "remoting/signaling/xmpp_log_to_server.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/libjingle_xmpp/xmllite/xmlelement.h" - -using jingle_xmpp::QName; -using jingle_xmpp::XmlElement; -using testing::_; -using testing::DeleteArg; -using testing::DoAll; -using testing::InSequence; -using testing::Return; - -namespace remoting { - -namespace { - -ACTION_P(QuitRunLoop, run_loop) { - run_loop->QuitWhenIdle(); -} - -const char kJabberClientNamespace[] = "jabber:client"; -const char kChromotingNamespace[] = "google:remoting"; -const char kTestBotJid[] = "remotingunittest@bot.talk.google.com"; -const char kClientJid1[] = "client@domain.com/1234"; -const char kClientJid2[] = "client@domain.com/5678"; -const char kHostJid[] = "host@domain.com/1234"; - -bool IsLogEntryForConnection(XmlElement* node, const char* connection_type) { - return (node->Name() == QName(kChromotingNamespace, "entry") && - node->Attr(QName(std::string(), "event-name")) == "session-state" && - node->Attr(QName(std::string(), "session-state")) == "connected" && - node->Attr(QName(std::string(), "role")) == "host" && - node->Attr(QName(std::string(), "mode")) == "me2me" && - node->Attr(QName(std::string(), "connection-type")) == - connection_type); -} - -MATCHER_P(IsClientConnected, connection_type, "") { - if (arg->Name() != QName(kJabberClientNamespace, "iq")) { - return false; - } - jingle_xmpp::XmlElement* log_stanza = arg->FirstChild()->AsElement(); - if (log_stanza->Name() != QName(kChromotingNamespace, "log")) { - return false; - } - if (log_stanza->NextChild()) { - return false; - } - jingle_xmpp::XmlElement* log_entry = log_stanza->FirstChild()->AsElement(); - if (!IsLogEntryForConnection(log_entry, connection_type)) { - return false; - } - if (log_entry->NextChild()) { - return false; - } - return true; -} - -MATCHER_P2(IsTwoClientsConnected, connection_type1, connection_type2, "") { - if (arg->Name() != QName(kJabberClientNamespace, "iq")) { - return false; - } - jingle_xmpp::XmlElement* log_stanza = arg->FirstChild()->AsElement(); - if (log_stanza->Name() != QName(kChromotingNamespace, "log")) { - return false; - } - if (log_stanza->NextChild()) { - return false; - } - jingle_xmpp::XmlElement* log_entry = log_stanza->FirstChild()->AsElement(); - if (!IsLogEntryForConnection(log_entry, connection_type1)) { - return false; - } - log_entry = log_entry->NextChild()->AsElement(); - if (!IsLogEntryForConnection(log_entry, connection_type2)) { - return false; - } - if (log_entry->NextChild()) { - return false; - } - return true; -} - -bool IsLogEntryForDisconnection(XmlElement* node) { - return (node->Name() == QName(kChromotingNamespace, "entry") && - node->Attr(QName(std::string(), "event-name")) == "session-state" && - node->Attr(QName(std::string(), "session-state")) == "closed" && - node->Attr(QName(std::string(), "role")) == "host" && - node->Attr(QName(std::string(), "mode")) == "me2me"); -} - -MATCHER(IsClientDisconnected, "") { - if (arg->Name() != QName(kJabberClientNamespace, "iq")) { - return false; - } - jingle_xmpp::XmlElement* log_stanza = arg->FirstChild()->AsElement(); - if (log_stanza->Name() != QName(kChromotingNamespace, "log")) { - return false; - } - if (log_stanza->NextChild()) { - return false; - } - jingle_xmpp::XmlElement* log_entry = log_stanza->FirstChild()->AsElement(); - if (!IsLogEntryForDisconnection(log_entry)) { - return false; - } - if (log_entry->NextChild()) { - return false; - } - return true; -} - -} // namespace - -class HostStatusLoggerTest : public testing::Test { - public: - HostStatusLoggerTest() - : signal_strategy_(SignalingAddress(kHostJid)), - host_status_monitor_(new HostStatusMonitor()) {} - void SetUp() override { - EXPECT_CALL(signal_strategy_, AddListener(_)); - log_to_server_ = std::make_unique<XmppLogToServer>( - ServerLogEntry::ME2ME, &signal_strategy_, kTestBotJid); - host_status_logger_ = std::make_unique<HostStatusLogger>( - host_status_monitor_, log_to_server_.get()); - EXPECT_CALL(signal_strategy_, RemoveListener(_)); - } - - protected: - base::test::SingleThreadTaskEnvironment task_environment_; - MockSignalStrategy signal_strategy_; - std::unique_ptr<XmppLogToServer> log_to_server_; - std::unique_ptr<HostStatusLogger> host_status_logger_; - scoped_refptr<HostStatusMonitor> host_status_monitor_; -}; - -TEST_F(HostStatusLoggerTest, SendNow) { - base::RunLoop run_loop; - { - InSequence s; - EXPECT_CALL(signal_strategy_, AddListener(_)); - EXPECT_CALL(signal_strategy_, GetNextId()); - EXPECT_CALL(signal_strategy_, SendStanzaPtr(IsClientConnected("direct"))) - .WillOnce(DoAll(DeleteArg<0>(), Return(true))); - EXPECT_CALL(signal_strategy_, RemoveListener(_)) - .WillOnce(QuitRunLoop(&run_loop)) - .RetiresOnSaturation(); - } - log_to_server_->OnSignalStrategyStateChange(SignalStrategy::CONNECTED); - protocol::TransportRoute route; - route.type = protocol::TransportRoute::DIRECT; - host_status_logger_->OnClientRouteChange(kClientJid1, "video", route); - host_status_logger_->OnClientAuthenticated(kClientJid1); - host_status_logger_->OnClientConnected(kClientJid1); - log_to_server_->OnSignalStrategyStateChange(SignalStrategy::DISCONNECTED); - run_loop.Run(); -} - -TEST_F(HostStatusLoggerTest, SendLater) { - base::RunLoop run_loop; - protocol::TransportRoute route; - route.type = protocol::TransportRoute::DIRECT; - host_status_logger_->OnClientRouteChange(kClientJid1, "video", route); - host_status_logger_->OnClientAuthenticated(kClientJid1); - host_status_logger_->OnClientConnected(kClientJid1); - - { - InSequence s; - EXPECT_CALL(signal_strategy_, AddListener(_)); - EXPECT_CALL(signal_strategy_, GetNextId()); - EXPECT_CALL(signal_strategy_, SendStanzaPtr(IsClientConnected("direct"))) - .WillOnce(DoAll(DeleteArg<0>(), Return(true))); - EXPECT_CALL(signal_strategy_, RemoveListener(_)) - .WillOnce(QuitRunLoop(&run_loop)) - .RetiresOnSaturation(); - } - log_to_server_->OnSignalStrategyStateChange(SignalStrategy::CONNECTED); - log_to_server_->OnSignalStrategyStateChange(SignalStrategy::DISCONNECTED); - run_loop.Run(); -} - -TEST_F(HostStatusLoggerTest, SendTwoEntriesLater) { - base::RunLoop run_loop; - protocol::TransportRoute route1; - route1.type = protocol::TransportRoute::DIRECT; - host_status_logger_->OnClientRouteChange(kClientJid1, "video", route1); - host_status_logger_->OnClientAuthenticated(kClientJid1); - host_status_logger_->OnClientConnected(kClientJid1); - protocol::TransportRoute route2; - route2.type = protocol::TransportRoute::STUN; - host_status_logger_->OnClientRouteChange(kClientJid2, "video", route2); - host_status_logger_->OnClientAuthenticated(kClientJid2); - host_status_logger_->OnClientConnected(kClientJid2); - - { - InSequence s; - EXPECT_CALL(signal_strategy_, AddListener(_)); - EXPECT_CALL(signal_strategy_, GetNextId()); - EXPECT_CALL(signal_strategy_, - SendStanzaPtr(IsTwoClientsConnected("direct", "stun"))) - .WillOnce(DoAll(DeleteArg<0>(), Return(true))); - EXPECT_CALL(signal_strategy_, RemoveListener(_)) - .WillOnce(QuitRunLoop(&run_loop)) - .RetiresOnSaturation(); - } - log_to_server_->OnSignalStrategyStateChange(SignalStrategy::CONNECTED); - log_to_server_->OnSignalStrategyStateChange(SignalStrategy::DISCONNECTED); - run_loop.Run(); -} - -TEST_F(HostStatusLoggerTest, HandleRouteChangeInUnusualOrder) { - base::RunLoop run_loop; - - { - InSequence s; - EXPECT_CALL(signal_strategy_, AddListener(_)); - EXPECT_CALL(signal_strategy_, GetNextId()); - EXPECT_CALL(signal_strategy_, SendStanzaPtr(IsClientConnected("direct"))) - .WillOnce(DoAll(DeleteArg<0>(), Return(true))); - EXPECT_CALL(signal_strategy_, GetNextId()); - EXPECT_CALL(signal_strategy_, SendStanzaPtr(IsClientDisconnected())) - .WillOnce(DoAll(DeleteArg<0>(), Return(true))); - EXPECT_CALL(signal_strategy_, GetNextId()); - EXPECT_CALL(signal_strategy_, SendStanzaPtr(IsClientConnected("stun"))) - .WillOnce(DoAll(DeleteArg<0>(), Return(true))); - EXPECT_CALL(signal_strategy_, RemoveListener(_)) - .WillOnce(QuitRunLoop(&run_loop)) - .RetiresOnSaturation(); - } - log_to_server_->OnSignalStrategyStateChange(SignalStrategy::CONNECTED); - protocol::TransportRoute route1; - route1.type = protocol::TransportRoute::DIRECT; - host_status_logger_->OnClientRouteChange(kClientJid1, "video", route1); - host_status_logger_->OnClientAuthenticated(kClientJid1); - host_status_logger_->OnClientConnected(kClientJid1); - protocol::TransportRoute route2; - route2.type = protocol::TransportRoute::STUN; - host_status_logger_->OnClientRouteChange(kClientJid2, "video", route2); - host_status_logger_->OnClientDisconnected(kClientJid1); - host_status_logger_->OnClientAuthenticated(kClientJid2); - host_status_logger_->OnClientConnected(kClientJid2); - log_to_server_->OnSignalStrategyStateChange(SignalStrategy::DISCONNECTED); - run_loop.Run(); -} - -} // namespace remoting
diff --git a/remoting/host/it2me/it2me_host.cc b/remoting/host/it2me/it2me_host.cc index ba4d44c7..bad83dd 100644 --- a/remoting/host/it2me/it2me_host.cc +++ b/remoting/host/it2me/it2me_host.cc
@@ -46,7 +46,6 @@ #include "remoting/host/host_event_logger.h" #include "remoting/host/host_event_reporter.h" #include "remoting/host/host_secret.h" -#include "remoting/host/host_status_logger.h" #include "remoting/host/it2me/it2me_confirmation_dialog.h" #include "remoting/host/it2me/it2me_confirmation_dialog_proxy.h" #include "remoting/host/it2me/it2me_helpers.h" @@ -280,10 +279,8 @@ SetState(It2MeHostState::kStarting, ErrorCode::OK); auto connection_context = std::move(create_context).Run(host_context_.get()); - log_to_server_ = std::move(connection_context->log_to_server); signal_strategy_ = std::move(connection_context->signal_strategy); api_token_getter_ = std::move(connection_context->api_token_getter); - DCHECK(log_to_server_); DCHECK(signal_strategy_); if (connection_context->use_ftl_signaling) { @@ -415,8 +412,6 @@ base::Unretained(this)), local_session_policies_provider_.get()); host_->status_monitor()->AddStatusObserver(this); - host_status_logger_ = std::make_unique<HostStatusLogger>( - host_->status_monitor(), log_to_server_.get()); // Create event logger. host_event_logger_ = @@ -819,8 +814,6 @@ } register_request_ = nullptr; - host_status_logger_ = nullptr; - log_to_server_ = nullptr; ftl_signaling_connector_ = nullptr; reconnect_params_.reset();
diff --git a/remoting/host/it2me/it2me_host.h b/remoting/host/it2me/it2me_host.h index 8598a1b..7747fed 100644 --- a/remoting/host/it2me/it2me_host.h +++ b/remoting/host/it2me/it2me_host.h
@@ -38,9 +38,7 @@ class FtlSignalingConnector; class HostEventLogger; class HostEventReporter; -class HostStatusLogger; class HostStatusMonitor; -class LogToServer; class OAuthTokenGetter; class RegisterSupportHostRequest; class RsaKeyPair; @@ -57,7 +55,6 @@ DeferredConnectContext(); ~DeferredConnectContext(); - std::unique_ptr<LogToServer> log_to_server; std::unique_ptr<RegisterSupportHostRequest> register_request; std::unique_ptr<SignalStrategy> signal_strategy; @@ -247,7 +244,6 @@ base::WeakPtr<It2MeHost::Observer> observer_; std::unique_ptr<SignalStrategy> signal_strategy_; std::unique_ptr<FtlSignalingConnector> ftl_signaling_connector_; - std::unique_ptr<LogToServer> log_to_server_; std::unique_ptr<OAuthTokenGetter> api_token_getter_; It2MeHostState state_ = It2MeHostState::kDisconnected; @@ -262,7 +258,6 @@ std::string ftl_device_id_; scoped_refptr<RsaKeyPair> host_key_pair_; std::unique_ptr<RegisterSupportHostRequest> register_request_; - std::unique_ptr<HostStatusLogger> host_status_logger_; std::unique_ptr<DesktopEnvironmentFactory> desktop_environment_factory_; std::unique_ptr<HostEventLogger> host_event_logger_; std::unique_ptr<LocalSessionPoliciesProvider>
diff --git a/remoting/host/it2me/it2me_host_unittest.cc b/remoting/host/it2me/it2me_host_unittest.cc index 5634b2ac..b5fdc5b 100644 --- a/remoting/host/it2me/it2me_host_unittest.cc +++ b/remoting/host/it2me/it2me_host_unittest.cc
@@ -51,8 +51,6 @@ #include "remoting/protocol/errors.h" #include "remoting/protocol/transport_context.h" #include "remoting/signaling/fake_signal_strategy.h" -#include "remoting/signaling/remoting_log_to_server.h" -#include "remoting/signaling/xmpp_log_to_server.h" #include "services/network/test/test_shared_url_loader_factory.h" #include "testing/gtest/include/gtest/gtest.h" @@ -443,10 +441,6 @@ context->use_corp_session_authz = use_corp_session_authz; context->register_request = std::make_unique<FakeRegisterSupportHostRequest>(); - context->log_to_server = std::make_unique<RemotingLogToServer>( - ServerLogEntry::IT2ME, - std::make_unique<OAuthTokenGetterProxy>(token_getter), - host_context->url_loader_factory()); context->signaling_token_getter = std::make_unique<OAuthTokenGetterProxy>(token_getter); context->api_token_getter =
diff --git a/remoting/host/it2me/it2me_native_messaging_host.cc b/remoting/host/it2me/it2me_native_messaging_host.cc index a9f7e41..ab2de565 100644 --- a/remoting/host/it2me/it2me_native_messaging_host.cc +++ b/remoting/host/it2me/it2me_native_messaging_host.cc
@@ -53,9 +53,6 @@ #include "remoting/signaling/delegating_signal_strategy.h" #include "remoting/signaling/ftl_signal_strategy.h" #include "remoting/signaling/ftl_support_host_device_id_provider.h" -#include "remoting/signaling/remoting_log_to_server.h" -#include "remoting/signaling/server_log_entry.h" -#include "remoting/signaling/xmpp_log_to_server.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #if BUILDFLAG(IS_WIN) @@ -115,9 +112,6 @@ std::make_unique<It2MeHost::DeferredConnectContext>(); connection_context->register_request = std::make_unique<XmppRegisterSupportHostRequest>(kDirectoryBotJidValue); - connection_context->log_to_server = std::make_unique<XmppLogToServer>( - ServerLogEntry::IT2ME, signal_strategy.get(), kDirectoryBotJidValue, - context->network_task_runner()); connection_context->signal_strategy = std::move(signal_strategy); return connection_context; } @@ -158,11 +152,6 @@ api_token_getter, oauth_token_getter_task_runner), host_context->url_loader_factory()); } - connection_context->log_to_server = std::make_unique<RemotingLogToServer>( - ServerLogEntry::IT2ME, - std::make_unique<OAuthTokenGetterProxy>(api_token_getter, - oauth_token_getter_task_runner), - host_context->url_loader_factory()); connection_context->signaling_token_getter = std::make_unique<OAuthTokenGetterProxy>(signaling_token_getter, oauth_token_getter_task_runner);
diff --git a/remoting/host/it2me/it2me_native_messaging_host_unittest.cc b/remoting/host/it2me/it2me_native_messaging_host_unittest.cc index dfaaba2..2e69508 100644 --- a/remoting/host/it2me/it2me_native_messaging_host_unittest.cc +++ b/remoting/host/it2me/it2me_native_messaging_host_unittest.cc
@@ -46,7 +46,6 @@ #include "remoting/host/setup/test_util.h" #include "remoting/protocol/errors.h" #include "remoting/protocol/ice_config.h" -#include "remoting/signaling/log_to_server.h" #include "services/network/test/test_shared_url_loader_factory.h" #include "testing/gtest/include/gtest/gtest.h" @@ -213,7 +212,6 @@ return; } - log_to_server_.reset(); register_request_.reset(); signal_strategy_.reset(); session_policies_finalized_ = false; @@ -227,7 +225,6 @@ CreateDeferredConnectContext create_connection_context) { DCHECK(host_context()->network_task_runner()->BelongsToCurrentThread()); auto context = std::move(create_connection_context).Run(host_context()); - log_to_server_ = std::move(context->log_to_server); register_request_ = std::move(context->register_request); signal_strategy_ = std::move(context->signal_strategy); signaling_token_getter_ = std::move(context->signaling_token_getter);
diff --git a/remoting/host/server_log_entry_host.cc b/remoting/host/server_log_entry_host.cc deleted file mode 100644 index 8e9fc3ad..0000000 --- a/remoting/host/server_log_entry_host.cc +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "remoting/host/server_log_entry_host.h" - -#include "base/strings/stringize_macros.h" -#include "remoting/host/host_details.h" -#include "remoting/signaling/server_log_entry.h" - -namespace remoting { - -namespace { -const char kValueEventNameSessionState[] = "session-state"; - -const char kValueRoleHost[] = "host"; - -const char kKeySessionState[] = "session-state"; -const char kValueSessionStateConnected[] = "connected"; -const char kValueSessionStateClosed[] = "closed"; - -const char kKeyOsName[] = "os-name"; -const char kKeyOsVersion[] = "os-version"; - -const char kKeyHostVersion[] = "host-version"; - -const char kKeyConnectionType[] = "connection-type"; - -const char* GetValueSessionState(bool connected) { - return connected ? kValueSessionStateConnected : kValueSessionStateClosed; -} - -} // namespace - -std::unique_ptr<ServerLogEntry> MakeLogEntryForSessionStateChange( - bool connected) { - std::unique_ptr<ServerLogEntry> entry(new ServerLogEntry()); - entry->AddRoleField(kValueRoleHost); - entry->AddEventNameField(kValueEventNameSessionState); - entry->Set(kKeySessionState, GetValueSessionState(connected)); - return entry; -} - -void AddHostFieldsToLogEntry(ServerLogEntry* entry) { - // TODO os name, os version, and version will be in the main message body, - // remove these fields at a later date to remove redundancy. - entry->Set(kKeyOsName, GetHostOperatingSystemName()); - entry->Set(kKeyOsVersion, GetHostOperatingSystemVersion()); - entry->Set(kKeyHostVersion, STRINGIZE(VERSION)); - entry->AddCpuField(); -} - -void AddConnectionTypeToLogEntry(ServerLogEntry* entry, - protocol::TransportRoute::RouteType type) { - entry->Set(kKeyConnectionType, protocol::TransportRoute::GetTypeString(type)); -} - -} // namespace remoting
diff --git a/remoting/host/server_log_entry_host.h b/remoting/host/server_log_entry_host.h deleted file mode 100644 index 3187b44..0000000 --- a/remoting/host/server_log_entry_host.h +++ /dev/null
@@ -1,28 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef REMOTING_HOST_SERVER_LOG_ENTRY_HOST_H_ -#define REMOTING_HOST_SERVER_LOG_ENTRY_HOST_H_ - -#include "remoting/protocol/transport.h" - -namespace remoting { - -class ServerLogEntry; - -// Constructs a log entry for a session state change. -// Currently this is either connection or disconnection. -std::unique_ptr<ServerLogEntry> MakeLogEntryForSessionStateChange( - bool connected); - -// Adds fields describing the host to this log entry. -void AddHostFieldsToLogEntry(ServerLogEntry* entry); - -// Adds a field describing connection type (direct/stun/relay). -void AddConnectionTypeToLogEntry(ServerLogEntry* entry, - protocol::TransportRoute::RouteType type); - -} // namespace remoting - -#endif // REMOTING_HOST_SERVER_LOG_ENTRY_HOST_H_
diff --git a/remoting/host/server_log_entry_host_unittest.cc b/remoting/host/server_log_entry_host_unittest.cc deleted file mode 100644 index c64c89a1..0000000 --- a/remoting/host/server_log_entry_host_unittest.cc +++ /dev/null
@@ -1,103 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "remoting/host/server_log_entry_host.h" - -#include <memory> - -#include "base/strings/stringize_macros.h" -#include "build/build_config.h" -#include "remoting/signaling/server_log_entry.h" -#include "remoting/signaling/server_log_entry_unittest.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/libjingle_xmpp/xmllite/xmlelement.h" - -using jingle_xmpp::XmlAttr; -using jingle_xmpp::XmlElement; - -namespace remoting { - -TEST(ServerLogEntryHostTest, MakeForSessionStateChange) { - std::unique_ptr<ServerLogEntry> entry( - MakeLogEntryForSessionStateChange(true)); - std::unique_ptr<XmlElement> stanza = entry->ToStanza(); - std::string error; - std::map<std::string, std::string> key_value_pairs; - key_value_pairs["role"] = "host"; - key_value_pairs["event-name"] = "session-state"; - key_value_pairs["session-state"] = "connected"; - std::set<std::string> keys; - ASSERT_TRUE(VerifyStanza(key_value_pairs, keys, stanza.get(), &error)) - << error; -} - -TEST(ServerLogEntryHostTest, AddHostFields) { - std::unique_ptr<ServerLogEntry> entry( - MakeLogEntryForSessionStateChange(true)); - AddHostFieldsToLogEntry(entry.get()); - std::unique_ptr<XmlElement> stanza = entry->ToStanza(); - std::string error; - std::map<std::string, std::string> key_value_pairs; - key_value_pairs["role"] = "host"; - key_value_pairs["event-name"] = "session-state"; - key_value_pairs["session-state"] = "connected"; - std::set<std::string> keys; - keys.insert("cpu"); -#if BUILDFLAG(IS_WIN) - key_value_pairs["os-name"] = "Windows"; - keys.insert("os-version"); -#elif BUILDFLAG(IS_APPLE) - key_value_pairs["os-name"] = "Mac"; - keys.insert("os-version"); -#elif BUILDFLAG(IS_CHROMEOS) - key_value_pairs["os-name"] = "ChromeOS"; - keys.insert("os-version"); -#elif BUILDFLAG(IS_LINUX) - key_value_pairs["os-name"] = "Linux"; - keys.insert("os-version"); -#endif - -// The check below will compile but fail if VERSION isn't defined (STRINGIZE -// silently converts undefined values). -#ifndef VERSION -#error VERSION must be defined -#endif - key_value_pairs["host-version"] = STRINGIZE(VERSION); - ASSERT_TRUE(VerifyStanza(key_value_pairs, keys, stanza.get(), &error)) - << error; -} - -TEST(ServerLogEntryHostTest, AddModeField1) { - std::unique_ptr<ServerLogEntry> entry( - MakeLogEntryForSessionStateChange(true)); - entry->AddModeField(ServerLogEntry::IT2ME); - std::unique_ptr<XmlElement> stanza = entry->ToStanza(); - std::string error; - std::map<std::string, std::string> key_value_pairs; - key_value_pairs["role"] = "host"; - key_value_pairs["event-name"] = "session-state"; - key_value_pairs["session-state"] = "connected"; - key_value_pairs["mode"] = "it2me"; - std::set<std::string> keys; - ASSERT_TRUE(VerifyStanza(key_value_pairs, keys, stanza.get(), &error)) - << error; -} - -TEST(ServerLogEntryHostTest, AddModeField2) { - std::unique_ptr<ServerLogEntry> entry( - MakeLogEntryForSessionStateChange(true)); - entry->AddModeField(ServerLogEntry::ME2ME); - std::unique_ptr<XmlElement> stanza = entry->ToStanza(); - std::string error; - std::map<std::string, std::string> key_value_pairs; - key_value_pairs["role"] = "host"; - key_value_pairs["event-name"] = "session-state"; - key_value_pairs["session-state"] = "connected"; - key_value_pairs["mode"] = "me2me"; - std::set<std::string> keys; - ASSERT_TRUE(VerifyStanza(key_value_pairs, keys, stanza.get(), &error)) - << error; -} - -} // namespace remoting
diff --git a/remoting/signaling/BUILD.gn b/remoting/signaling/BUILD.gn index af7fb6b..451147d 100644 --- a/remoting/signaling/BUILD.gn +++ b/remoting/signaling/BUILD.gn
@@ -30,10 +30,6 @@ "message_tracker.h", "messaging_client.h", "registration_manager.h", - "remoting_log_to_server.cc", - "remoting_log_to_server.h", - "server_log_entry.cc", - "server_log_entry.h", "signal_strategy.cc", "signal_strategy.h", "signaling_address.cc", @@ -43,8 +39,6 @@ "signaling_tracker.h", "xmpp_constants.cc", "xmpp_constants.h", - "xmpp_log_to_server.cc", - "xmpp_log_to_server.h", ] configs += [ @@ -103,12 +97,8 @@ "ftl_signal_strategy_unittest.cc", "iq_sender_unittest.cc", "message_tracker_unittest.cc", - "remoting_log_to_server_unittest.cc", - "server_log_entry_unittest.cc", - "server_log_entry_unittest.h", "signaling_address_unittest.cc", "signaling_id_util_unittest.cc", - "xmpp_log_to_server_unittest.cc", ] deps = [
diff --git a/remoting/signaling/log_to_server.h b/remoting/signaling/log_to_server.h deleted file mode 100644 index 6a0e750..0000000 --- a/remoting/signaling/log_to_server.h +++ /dev/null
@@ -1,28 +0,0 @@ -// Copyright 2019 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef REMOTING_SIGNALING_LOG_TO_SERVER_H_ -#define REMOTING_SIGNALING_LOG_TO_SERVER_H_ - -#include "remoting/signaling/server_log_entry.h" - -namespace remoting { - -// LogToServer sends log entries to a server. -// The contents of the log entries are described in server_log_entry.cc. -// They do not contain any personally identifiable information. -class LogToServer { - public: - virtual ~LogToServer() = default; - - virtual void Log(const ServerLogEntry& entry) = 0; - virtual ServerLogEntry::Mode mode() const = 0; - - protected: - LogToServer() = default; -}; - -} // namespace remoting - -#endif // REMOTING_SIGNALING_LOG_TO_SERVER_H_
diff --git a/remoting/signaling/remoting_log_to_server.cc b/remoting/signaling/remoting_log_to_server.cc deleted file mode 100644 index e9444b9..0000000 --- a/remoting/signaling/remoting_log_to_server.cc +++ /dev/null
@@ -1,223 +0,0 @@ -// Copyright 2019 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "remoting/signaling/remoting_log_to_server.h" - -#include <sstream> - -#include "base/functional/bind.h" -#include "base/logging.h" -#include "net/traffic_annotation/network_traffic_annotation.h" -#include "remoting/base/http_status.h" -#include "remoting/base/protobuf_http_client.h" -#include "remoting/base/protobuf_http_request.h" -#include "remoting/base/protobuf_http_request_config.h" -#include "remoting/base/service_urls.h" -#include "remoting/proto/remoting/v1/telemetry_messages.pb.h" -#include "services/network/public/cpp/shared_url_loader_factory.h" - -namespace remoting { - -namespace { - -const net::BackoffEntry::Policy kBackoffPolicy = { - // Number of initial errors (in sequence) to ignore before applying - // exponential back-off rules. - 0, - - // Initial delay for exponential back-off in ms. - 1000, - - // Factor by which the waiting time will be multiplied. - 2, - - // Fuzzing percentage. ex: 10% will spread requests randomly - // between 90%-100% of the calculated time. - 0.5, - - // Maximum amount of time we are willing to delay our request in ms. - 60000, - - // Time to keep an entry from being discarded even when it - // has no significant state, -1 to never discard. - -1, - - // Starts with initial delay. - false, -}; - -constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation = - net::DefineNetworkTrafficAnnotation("remoting_log_to_server", - R"( - semantics { - sender: "Chrome Remote Desktop" - description: - "Sends telemetry logs for Chrome Remote Desktop." - trigger: - "These requests are sent periodically when a session is connected, " - "i.e. CRD host is running and is connected to a client." - user_data { - type: OTHER - } - data: - "Anonymous usage statistics, which includes CRD host version, OS " - "name, OS version, and CPU architecture (e.g. x86_64)." - destination: GOOGLE_OWNED_SERVICE - internal { - contacts { email: "garykac@chromium.org" } - contacts { email: "jamiewalch@chromium.org" } - contacts { email: "joedow@chromium.org" } - contacts { email: "lambroslambrou@chromium.org" } - contacts { email: "rkjnsn@chromium.org" } - contacts { email: "yuweih@chromium.org" } - } - last_reviewed: "2023-07-07" - } - policy { - cookies_allowed: NO - setting: - "This request cannot be stopped in settings, but will not be sent " - "if the user does not use Chrome Remote Desktop." - chrome_policy { - RemoteAccessHostAllowRemoteSupportConnections { - RemoteAccessHostAllowRemoteSupportConnections: false - } - RemoteAccessHostAllowEnterpriseRemoteSupportConnections { - RemoteAccessHostAllowEnterpriseRemoteSupportConnections: false - } - } - })"); - -constexpr char kCreateLogEntryPath[] = "/v1/telemetry:createlogentry"; - -using CreateLogEntryResponseCallback = - base::OnceCallback<void(const HttpStatus&, - std::unique_ptr<apis::v1::CreateLogEntryResponse>)>; - -class TelemetryClient { - public: - TelemetryClient( - OAuthTokenGetter* token_getter, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory); - - TelemetryClient(const TelemetryClient&) = delete; - TelemetryClient& operator=(const TelemetryClient&) = delete; - - ~TelemetryClient(); - - void CreateLogEntry(const apis::v1::CreateLogEntryRequest& request, - CreateLogEntryResponseCallback callback); - - private: - ProtobufHttpClient http_client_; -}; - -TelemetryClient::TelemetryClient( - OAuthTokenGetter* token_getter, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) - : http_client_(ServiceUrls::GetInstance()->remoting_server_endpoint(), - token_getter, - url_loader_factory) {} - -TelemetryClient::~TelemetryClient() = default; - -void TelemetryClient::CreateLogEntry( - const apis::v1::CreateLogEntryRequest& request, - CreateLogEntryResponseCallback callback) { - auto request_config = - std::make_unique<ProtobufHttpRequestConfig>(kTrafficAnnotation); - request_config->path = kCreateLogEntryPath; - request_config->request_message = - std::make_unique<apis::v1::CreateLogEntryRequest>(request); - auto http_request = - std::make_unique<ProtobufHttpRequest>(std::move(request_config)); - http_request->SetResponseCallback(std::move(callback)); - http_client_.ExecuteRequest(std::move(http_request)); -} - -} // namespace - -RemotingLogToServer::RemotingLogToServer( - ServerLogEntry::Mode mode, - std::unique_ptr<OAuthTokenGetter> token_getter, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) - : mode_(mode), - token_getter_(std::move(token_getter)), - backoff_(&kBackoffPolicy), - create_log_entry_(base::BindRepeating( - &TelemetryClient::CreateLogEntry, - std::make_unique<TelemetryClient>(token_getter_.get(), - url_loader_factory))) {} - -RemotingLogToServer::~RemotingLogToServer() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); -} - -void RemotingLogToServer::Log(const ServerLogEntry& entry) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - apis::v1::CreateLogEntryRequest request; - *request.mutable_payload()->mutable_entry() = entry.ToGenericLogEntry(); - SendLogRequestWithBackoff(request, kMaxSendLogAttempts); -} - -void RemotingLogToServer::SendLogRequest( - const apis::v1::CreateLogEntryRequest& request, - int attempts_left) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (VLOG_IS_ON(1)) { - std::ostringstream log_stream; - log_stream << "Sending log entry with " << attempts_left - << " attempts left: \n"; - for (const auto& field : request.payload().entry().field()) { - log_stream << field.key() << ": " << field.value() << "\n"; - } - log_stream << "========================================================="; - VLOG(1) << log_stream.str(); - } - create_log_entry_.Run( - request, - base::BindOnce(&RemotingLogToServer::OnSendLogRequestResult, - base::Unretained(this), request, attempts_left - 1)); -} - -void RemotingLogToServer::SendLogRequestWithBackoff( - const apis::v1::CreateLogEntryRequest& request, - int attempts_left) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - auto time_until_release = backoff_.GetTimeUntilRelease(); - VLOG(1) << "Scheduling request in " << time_until_release - << ", attempts left: " << attempts_left; - backoff_timer_.Start( - FROM_HERE, time_until_release, - base::BindOnce(&RemotingLogToServer::SendLogRequest, - base::Unretained(this), request, attempts_left)); -} - -void RemotingLogToServer::OnSendLogRequestResult( - const apis::v1::CreateLogEntryRequest& request, - int attempts_left, - const HttpStatus& status, - std::unique_ptr<apis::v1::CreateLogEntryResponse> response) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (status.ok()) { - VLOG(1) << "One log has been successfully sent."; - backoff_.InformOfRequest(true); - return; - } - LOG(WARNING) << "Failed to send one log." - << " Error: " << static_cast<int>(status.error_code()) - << " Message: " << status.error_message(); - backoff_.InformOfRequest(false); - if (attempts_left <= 0) { - LOG(WARNING) << "Exceeded maximum retry attempts. Dropping it..."; - return; - } - SendLogRequestWithBackoff(request, attempts_left); -} - -ServerLogEntry::Mode RemotingLogToServer::mode() const { - return mode_; -} - -} // namespace remoting
diff --git a/remoting/signaling/remoting_log_to_server.h b/remoting/signaling/remoting_log_to_server.h deleted file mode 100644 index 9e3c4b4..0000000 --- a/remoting/signaling/remoting_log_to_server.h +++ /dev/null
@@ -1,86 +0,0 @@ -// Copyright 2019 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef REMOTING_SIGNALING_REMOTING_LOG_TO_SERVER_H_ -#define REMOTING_SIGNALING_REMOTING_LOG_TO_SERVER_H_ - -#include <memory> - -#include "base/functional/callback.h" -#include "base/memory/scoped_refptr.h" -#include "base/sequence_checker.h" -#include "base/timer/timer.h" -#include "net/base/backoff_entry.h" -#include "remoting/signaling/log_to_server.h" - -namespace network { -class SharedURLLoaderFactory; -} // namespace network - -namespace remoting { - -namespace apis { -namespace v1 { -class CreateLogEntryRequest; -class CreateLogEntryResponse; -} // namespace v1 -} // namespace apis - -class HttpStatus; -class OAuthTokenGetter; - -// RemotingLogToServer sends log entries to to the remoting telemetry server. -class RemotingLogToServer : public LogToServer { - public: - RemotingLogToServer( - ServerLogEntry::Mode mode, - std::unique_ptr<OAuthTokenGetter> token_getter, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory); - - RemotingLogToServer(const RemotingLogToServer&) = delete; - RemotingLogToServer& operator=(const RemotingLogToServer&) = delete; - - ~RemotingLogToServer() override; - - // LogToServer interface. - void Log(const ServerLogEntry& entry) override; - ServerLogEntry::Mode mode() const override; - - private: - static constexpr int kMaxSendLogAttempts = 5; - - using CreateLogEntryResponseCallback = base::OnceCallback<void( - const HttpStatus&, - std::unique_ptr<apis::v1::CreateLogEntryResponse>)>; - using CreateLogEntryCallback = - base::RepeatingCallback<void(const apis::v1::CreateLogEntryRequest&, - CreateLogEntryResponseCallback callback)>; - - friend class RemotingLogToServerTest; - - void SendLogRequest(const apis::v1::CreateLogEntryRequest& request, - int attempts_left); - void SendLogRequestWithBackoff(const apis::v1::CreateLogEntryRequest& request, - int attempts_left); - void OnSendLogRequestResult( - const apis::v1::CreateLogEntryRequest& request, - int attempts_left, - const HttpStatus& status, - std::unique_ptr<apis::v1::CreateLogEntryResponse> response); - - ServerLogEntry::Mode mode_; - std::unique_ptr<OAuthTokenGetter> token_getter_; - net::BackoffEntry backoff_; - base::OneShotTimer backoff_timer_; - - // Callback used to send the log entry to the server. Replaceable for - // unittest. - CreateLogEntryCallback create_log_entry_; - - SEQUENCE_CHECKER(sequence_checker_); -}; - -} // namespace remoting - -#endif // REMOTING_SIGNALING_REMOTING_LOG_TO_SERVER_H_
diff --git a/remoting/signaling/remoting_log_to_server_unittest.cc b/remoting/signaling/remoting_log_to_server_unittest.cc deleted file mode 100644 index f0c2b28f..0000000 --- a/remoting/signaling/remoting_log_to_server_unittest.cc +++ /dev/null
@@ -1,166 +0,0 @@ -// Copyright 2019 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "remoting/signaling/remoting_log_to_server.h" - -#include "base/test/mock_callback.h" -#include "base/test/task_environment.h" -#include "remoting/base/fake_oauth_token_getter.h" -#include "remoting/base/http_status.h" -#include "remoting/proto/remoting/v1/telemetry_messages.pb.h" -#include "services/network/public/cpp/shared_url_loader_factory.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace remoting { - -namespace { - -using testing::_; - -} // namespace - -class RemotingLogToServerTest : public testing::Test { - public: - RemotingLogToServerTest() { - EXPECT_EQ(ServerLogEntry::ME2ME, log_to_server_.mode()); - log_to_server_.create_log_entry_ = mock_create_log_entry_.Get(); - } - - ~RemotingLogToServerTest() override { - task_environment_.FastForwardUntilNoTasksRemain(); - } - - protected: - const net::BackoffEntry& GetBackoffEntry() const { - return log_to_server_.backoff_; - } - - int GetMaxSendLogAttempts() const { - return log_to_server_.kMaxSendLogAttempts; - } - - using CreateLogEntryResponseCallback = - RemotingLogToServer::CreateLogEntryResponseCallback; - - base::test::TaskEnvironment task_environment_{ - base::test::TaskEnvironment::TimeSource::MOCK_TIME}; - - base::MockCallback<RemotingLogToServer::CreateLogEntryCallback> - mock_create_log_entry_; - - RemotingLogToServer log_to_server_{ - ServerLogEntry::ME2ME, - std::make_unique<FakeOAuthTokenGetter>(OAuthTokenGetter::SUCCESS, - OAuthTokenInfo()), - nullptr}; -}; - -TEST_F(RemotingLogToServerTest, SuccessfullySendOneLog) { - EXPECT_CALL(mock_create_log_entry_, Run(_, _)) - .WillOnce([&](const apis::v1::CreateLogEntryRequest& request, - CreateLogEntryResponseCallback callback) { - ASSERT_EQ(1, request.payload().entry().field_size()); - ASSERT_EQ("test-key", request.payload().entry().field(0).key()); - ASSERT_EQ("test-value", request.payload().entry().field(0).value()); - std::move(callback).Run( - HttpStatus::OK(), - std::make_unique<apis::v1::CreateLogEntryResponse>()); - }); - - ServerLogEntry entry; - entry.Set("test-key", "test-value"); - log_to_server_.Log(entry); - - task_environment_.FastForwardUntilNoTasksRemain(); - - ASSERT_EQ(0, GetBackoffEntry().failure_count()); -} - -TEST_F(RemotingLogToServerTest, FailedToSend_RetryWithBackoff) { - EXPECT_CALL(mock_create_log_entry_, Run(_, _)) - .Times(GetMaxSendLogAttempts()) - .WillRepeatedly([&](const apis::v1::CreateLogEntryRequest& request, - CreateLogEntryResponseCallback callback) { - ASSERT_EQ(1, request.payload().entry().field_size()); - ASSERT_EQ("test-key", request.payload().entry().field(0).key()); - ASSERT_EQ("test-value", request.payload().entry().field(0).value()); - std::move(callback).Run( - HttpStatus(HttpStatus::Code::UNAVAILABLE, "unavailable"), nullptr); - }); - - ServerLogEntry entry; - entry.Set("test-key", "test-value"); - log_to_server_.Log(entry); - - for (int i = 1; i <= GetMaxSendLogAttempts(); i++) { - task_environment_.FastForwardBy(GetBackoffEntry().GetTimeUntilRelease()); - ASSERT_EQ(i, GetBackoffEntry().failure_count()); - } -} - -TEST_F(RemotingLogToServerTest, FailedToSendTwoLogs_RetryThenSucceeds) { - CreateLogEntryResponseCallback response_callback_1; - CreateLogEntryResponseCallback response_callback_2; - EXPECT_CALL(mock_create_log_entry_, Run(_, _)) - .WillOnce([&](const apis::v1::CreateLogEntryRequest& request, - CreateLogEntryResponseCallback callback) { - ASSERT_EQ(1, request.payload().entry().field_size()); - ASSERT_EQ("test-key-1", request.payload().entry().field(0).key()); - ASSERT_EQ("test-value-1", request.payload().entry().field(0).value()); - response_callback_1 = std::move(callback); - }) - .WillOnce([&](const apis::v1::CreateLogEntryRequest& request, - CreateLogEntryResponseCallback callback) { - ASSERT_EQ(1, request.payload().entry().field_size()); - ASSERT_EQ("test-key-2", request.payload().entry().field(0).key()); - ASSERT_EQ("test-value-2", request.payload().entry().field(0).value()); - response_callback_2 = std::move(callback); - }) - .WillOnce([&](const apis::v1::CreateLogEntryRequest& request, - CreateLogEntryResponseCallback callback) { - ASSERT_EQ(1, request.payload().entry().field_size()); - ASSERT_EQ("test-key-1", request.payload().entry().field(0).key()); - ASSERT_EQ("test-value-1", request.payload().entry().field(0).value()); - response_callback_1 = std::move(callback); - }) - .WillOnce([&](const apis::v1::CreateLogEntryRequest& request, - CreateLogEntryResponseCallback callback) { - ASSERT_EQ(1, request.payload().entry().field_size()); - ASSERT_EQ("test-key-2", request.payload().entry().field(0).key()); - ASSERT_EQ("test-value-2", request.payload().entry().field(0).value()); - response_callback_2 = std::move(callback); - }); - - ServerLogEntry entry_1; - entry_1.Set("test-key-1", "test-value-1"); - log_to_server_.Log(entry_1); - task_environment_.FastForwardUntilNoTasksRemain(); - - ServerLogEntry entry_2; - entry_2.Set("test-key-2", "test-value-2"); - log_to_server_.Log(entry_2); - task_environment_.FastForwardUntilNoTasksRemain(); - - ASSERT_EQ(0, GetBackoffEntry().failure_count()); - - std::move(response_callback_1) - .Run(HttpStatus(HttpStatus::Code::UNAVAILABLE, "unavailable"), nullptr); - task_environment_.FastForwardUntilNoTasksRemain(); - std::move(response_callback_2) - .Run(HttpStatus(HttpStatus::Code::UNAVAILABLE, "unavailable"), nullptr); - task_environment_.FastForwardUntilNoTasksRemain(); - ASSERT_EQ(2, GetBackoffEntry().failure_count()); - - std::move(response_callback_1) - .Run(HttpStatus::OK(), - std::make_unique<apis::v1::CreateLogEntryResponse>()); - std::move(response_callback_2) - .Run(HttpStatus::OK(), - std::make_unique<apis::v1::CreateLogEntryResponse>()); - task_environment_.FastForwardUntilNoTasksRemain(); - ASSERT_EQ(0, GetBackoffEntry().failure_count()); -} - -} // namespace remoting
diff --git a/remoting/signaling/server_log_entry.cc b/remoting/signaling/server_log_entry.cc deleted file mode 100644 index 8f2bd62f..0000000 --- a/remoting/signaling/server_log_entry.cc +++ /dev/null
@@ -1,98 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "remoting/signaling/server_log_entry.h" - -#include "base/notreached.h" -#include "base/system/sys_info.h" -#include "remoting/base/constants.h" -#include "third_party/libjingle_xmpp/xmllite/xmlelement.h" - -using base::SysInfo; -using jingle_xmpp::QName; -using jingle_xmpp::XmlElement; - -namespace remoting { - -namespace { - -const char kLogCommand[] = "log"; -const char kLogEntry[] = "entry"; - -const char kKeyEventName[] = "event-name"; - -const char kKeyRole[] = "role"; - -const char kKeyMode[] = "mode"; -const char kValueModeIt2Me[] = "it2me"; -const char kValueModeMe2Me[] = "me2me"; - -const char kKeyCpu[] = "cpu"; - -} // namespace - -ServerLogEntry::ServerLogEntry() = default; - -ServerLogEntry::ServerLogEntry(const ServerLogEntry& other) = default; - -ServerLogEntry::~ServerLogEntry() = default; - -void ServerLogEntry::Set(const std::string& key, const std::string& value) { - values_map_[key] = value; -} - -void ServerLogEntry::AddCpuField() { - Set(kKeyCpu, SysInfo::OperatingSystemArchitecture()); -} - -void ServerLogEntry::AddModeField(ServerLogEntry::Mode mode) { - const char* mode_value = nullptr; - switch (mode) { - case IT2ME: - mode_value = kValueModeIt2Me; - break; - case ME2ME: - mode_value = kValueModeMe2Me; - break; - default: - NOTREACHED(); - } - Set(kKeyMode, mode_value); -} - -void ServerLogEntry::AddRoleField(const char* role) { - Set(kKeyRole, role); -} - -void ServerLogEntry::AddEventNameField(const char* name) { - Set(kKeyEventName, name); -} - -// static -std::unique_ptr<XmlElement> ServerLogEntry::MakeStanza() { - return std::make_unique<XmlElement>( - QName(kChromotingXmlNamespace, kLogCommand)); -} - -std::unique_ptr<XmlElement> ServerLogEntry::ToStanza() const { - std::unique_ptr<XmlElement> stanza( - new XmlElement(QName(kChromotingXmlNamespace, kLogEntry))); - ValuesMap::const_iterator iter; - for (iter = values_map_.begin(); iter != values_map_.end(); ++iter) { - stanza->AddAttr(QName(std::string(), iter->first), iter->second); - } - return stanza; -} - -apis::v1::GenericLogEntry ServerLogEntry::ToGenericLogEntry() const { - apis::v1::GenericLogEntry log_entry; - for (auto pair : values_map_) { - auto* field = log_entry.add_field(); - field->set_key(pair.first); - field->set_value(pair.second); - } - return log_entry; -} - -} // namespace remoting
diff --git a/remoting/signaling/server_log_entry.h b/remoting/signaling/server_log_entry.h deleted file mode 100644 index 10db6cf..0000000 --- a/remoting/signaling/server_log_entry.h +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef REMOTING_SIGNALING_SERVER_LOG_ENTRY_H_ -#define REMOTING_SIGNALING_SERVER_LOG_ENTRY_H_ - -#include <map> -#include <memory> -#include <string> - -#include "remoting/proto/remoting/v1/generic_log_entry.pb.h" - -namespace jingle_xmpp { -class XmlElement; -} // namespace jingle_xmpp - -namespace remoting { - -// Utility class for building log entries to send to the remoting bot. This is -// a wrapper around a key/value map and is copyable so it can be used in STL -// containers. -class ServerLogEntry { - public: - // The mode of a connection. - enum Mode { IT2ME, ME2ME }; - - ServerLogEntry(); - ServerLogEntry(const ServerLogEntry& other); - ~ServerLogEntry(); - - // Sets an arbitrary key/value entry. - void Set(const std::string& key, const std::string& value); - - // Adds a field describing the CPU type of the platform. - void AddCpuField(); - - // Adds a field describing the mode of a connection to this log entry. - void AddModeField(Mode mode); - - // Adds a field describing the role (client/host). - void AddRoleField(const char* role); - - // Adds a field describing the type of log entry. - void AddEventNameField(const char* name); - - // Constructs a log stanza. The caller should add one or more log entry - // stanzas as children of this stanza, before sending the log stanza to - // the remoting bot. - static std::unique_ptr<jingle_xmpp::XmlElement> MakeStanza(); - - // Converts this object to an XML stanza. - std::unique_ptr<jingle_xmpp::XmlElement> ToStanza() const; - - apis::v1::GenericLogEntry ToGenericLogEntry() const; - - private: - typedef std::map<std::string, std::string> ValuesMap; - - ValuesMap values_map_; -}; - -} // namespace remoting - -#endif // REMOTING_SIGNALING_SERVER_LOG_ENTRY_H_
diff --git a/remoting/signaling/server_log_entry_unittest.cc b/remoting/signaling/server_log_entry_unittest.cc deleted file mode 100644 index 3956789..0000000 --- a/remoting/signaling/server_log_entry_unittest.cc +++ /dev/null
@@ -1,94 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "remoting/signaling/server_log_entry_unittest.h" - -#include <sstream> - -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/libjingle_xmpp/xmllite/xmlelement.h" - -using jingle_xmpp::QName; -using jingle_xmpp::XmlAttr; -using jingle_xmpp::XmlElement; - -namespace remoting { - -const char kJabberClientNamespace[] = "jabber:client"; -const char kChromotingNamespace[] = "google:remoting"; - -XmlElement* GetLogElementFromStanza(XmlElement* stanza) { - if (stanza->Name() != QName(kJabberClientNamespace, "iq")) { - ADD_FAILURE() << "Expected element 'iq'"; - return nullptr; - } - XmlElement* log_element = stanza->FirstChild()->AsElement(); - if (log_element->Name() != QName(kChromotingNamespace, "log")) { - ADD_FAILURE() << "Expected element 'log'"; - return nullptr; - } - if (log_element->NextChild()) { - ADD_FAILURE() << "Expected only 1 child of 'iq'"; - return nullptr; - } - return log_element; -} - -XmlElement* GetSingleLogEntryFromStanza(XmlElement* stanza) { - XmlElement* log_element = GetLogElementFromStanza(stanza); - if (!log_element) { - // Test failure already recorded, so just return nullptr here. - return nullptr; - } - XmlElement* entry = log_element->FirstChild()->AsElement(); - if (entry->Name() != QName(kChromotingNamespace, "entry")) { - ADD_FAILURE() << "Expected element 'entry'"; - return nullptr; - } - if (entry->NextChild()) { - ADD_FAILURE() << "Expected only 1 child of 'log'"; - return nullptr; - } - return entry; -} - -bool VerifyStanza(const std::map<std::string, std::string>& key_value_pairs, - const std::set<std::string> keys, - const XmlElement* elem, - std::string* error) { - int attrCount = 0; - for (const XmlAttr* attr = elem->FirstAttr(); attr != nullptr; - attr = attr->NextAttr(), attrCount++) { - if (attr->Name().Namespace().length() != 0) { - *error = "attribute has non-empty namespace " + attr->Name().Namespace(); - return false; - } - const std::string& key = attr->Name().LocalPart(); - const std::string& value = attr->Value(); - auto iter = key_value_pairs.find(key); - if (iter == key_value_pairs.end()) { - if (keys.find(key) == keys.end()) { - *error = "unexpected attribute " + key; - return false; - } - } else { - if (iter->second != value) { - *error = "attribute " + key + " has value " + iter->second + - ": expected " + value; - return false; - } - } - } - int attr_count_expected = key_value_pairs.size() + keys.size(); - if (attrCount != attr_count_expected) { - std::stringstream s; - s << "stanza has " << attrCount << " keys: expected " - << attr_count_expected; - *error = s.str(); - return false; - } - return true; -} - -} // namespace remoting
diff --git a/remoting/signaling/server_log_entry_unittest.h b/remoting/signaling/server_log_entry_unittest.h deleted file mode 100644 index 221d57c..0000000 --- a/remoting/signaling/server_log_entry_unittest.h +++ /dev/null
@@ -1,42 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef REMOTING_SIGNALING_SERVER_LOG_ENTRY_UNITTEST_H_ -#define REMOTING_SIGNALING_SERVER_LOG_ENTRY_UNITTEST_H_ - -#include <map> -#include <set> -#include <string> - -namespace jingle_xmpp { -class XmlElement; -} // namespace jingle_xmpp - -namespace remoting { - -extern const char kJabberClientNamespace[]; -extern const char kChromotingNamespace[]; - -// Verifies that |stanza| contains a <log> element and returns it. Otherwise -// returns nullptr and records a test failure. -jingle_xmpp::XmlElement* GetLogElementFromStanza( - jingle_xmpp::XmlElement* stanza); - -// Verifies that |stanza| contains only 1 log entry, and returns the <entry> -// element. Otherwise returns nullptr and records a test failure. -jingle_xmpp::XmlElement* GetSingleLogEntryFromStanza( - jingle_xmpp::XmlElement* stanza); - -// Verifies a logging stanza. -// |keyValuePairs| lists the keys that must have specified values, and |keys| -// lists the keys that must be present, but may have arbitrary values. -// There must be no other keys. -bool VerifyStanza(const std::map<std::string, std::string>& key_value_pairs, - const std::set<std::string> keys, - const jingle_xmpp::XmlElement* elem, - std::string* error); - -} // namespace remoting - -#endif // REMOTING_SIGNALING_SERVER_LOG_ENTRY_UNITTEST_H_
diff --git a/remoting/signaling/xmpp_log_to_server.cc b/remoting/signaling/xmpp_log_to_server.cc deleted file mode 100644 index fbb60e76..0000000 --- a/remoting/signaling/xmpp_log_to_server.cc +++ /dev/null
@@ -1,95 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "remoting/signaling/xmpp_log_to_server.h" - -#include <memory> -#include <utility> - -#include "base/functional/bind.h" -#include "base/task/sequenced_task_runner.h" -#include "remoting/base/constants.h" -#include "remoting/signaling/iq_sender.h" -#include "remoting/signaling/signal_strategy.h" -#include "remoting/signaling/xmpp_constants.h" -#include "third_party/libjingle_xmpp/xmllite/xmlelement.h" - -using jingle_xmpp::QName; -using jingle_xmpp::XmlElement; - -namespace remoting { - -XmppLogToServer::XmppLogToServer( - ServerLogEntry::Mode mode, - SignalStrategy* signal_strategy, - const std::string& directory_bot_jid, - scoped_refptr<base::SequencedTaskRunner> caller_task_runner) - : mode_(mode), - signal_strategy_(signal_strategy), - directory_bot_jid_(directory_bot_jid) { - DETACH_FROM_SEQUENCE(sequence_checker_); - if (!caller_task_runner || caller_task_runner->RunsTasksInCurrentSequence()) { - Init(); - return; - } - caller_task_runner->PostTask( - FROM_HERE, - base::BindOnce(&XmppLogToServer::Init, weak_factory_.GetWeakPtr())); -} - -XmppLogToServer::~XmppLogToServer() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - signal_strategy_->RemoveListener(this); -} - -void XmppLogToServer::OnSignalStrategyStateChange(SignalStrategy::State state) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - if (state == SignalStrategy::CONNECTED) { - iq_sender_ = std::make_unique<IqSender>(signal_strategy_); - SendPendingEntries(); - } else if (state == SignalStrategy::DISCONNECTED) { - iq_sender_.reset(); - } -} - -bool XmppLogToServer::OnSignalStrategyIncomingStanza( - const jingle_xmpp::XmlElement* stanza) { - return false; -} - -void XmppLogToServer::Log(const ServerLogEntry& entry) { - pending_entries_.push_back(entry); - SendPendingEntries(); -} - -void XmppLogToServer::Init() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - signal_strategy_->AddListener(this); -} - -void XmppLogToServer::SendPendingEntries() { - if (iq_sender_ == nullptr) { - return; - } - if (pending_entries_.empty()) { - return; - } - // Make one stanza containing all the pending entries. - std::unique_ptr<XmlElement> stanza(ServerLogEntry::MakeStanza()); - while (!pending_entries_.empty()) { - ServerLogEntry& entry = pending_entries_.front(); - stanza->AddElement(entry.ToStanza().release()); - pending_entries_.pop_front(); - } - // Send the stanza to the server and ignore the response. - iq_sender_->SendIq(kIqTypeSet, directory_bot_jid_, std::move(stanza), - IqSender::ReplyCallback()); -} - -ServerLogEntry::Mode XmppLogToServer::mode() const { - return mode_; -} - -} // namespace remoting
diff --git a/remoting/signaling/xmpp_log_to_server.h b/remoting/signaling/xmpp_log_to_server.h deleted file mode 100644 index 2256865c..0000000 --- a/remoting/signaling/xmpp_log_to_server.h +++ /dev/null
@@ -1,73 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef REMOTING_SIGNALING_XMPP_LOG_TO_SERVER_H_ -#define REMOTING_SIGNALING_XMPP_LOG_TO_SERVER_H_ - -#include <map> -#include <string> - -#include "base/containers/circular_deque.h" -#include "base/memory/raw_ptr.h" -#include "base/memory/scoped_refptr.h" -#include "base/memory/weak_ptr.h" -#include "base/sequence_checker.h" -#include "base/task/sequenced_task_runner.h" -#include "remoting/signaling/log_to_server.h" -#include "remoting/signaling/server_log_entry.h" -#include "remoting/signaling/signal_strategy.h" - -namespace jingle_xmpp { -class XmlElement; -} // namespace jingle_xmpp - -namespace remoting { - -class IqSender; - -// XmppLogToServer sends log entries to a server through the signaling strategy. -class XmppLogToServer : public LogToServer, public SignalStrategy::Listener { - public: - // The instance will be initialized on |caller_task_runner|, and thereafter - // it must be used on the sequence of |caller_task_runner|. By default it will - // be initialized on the current active sequence. - XmppLogToServer( - ServerLogEntry::Mode mode, - SignalStrategy* signal_strategy, - const std::string& directory_bot_jid, - scoped_refptr<base::SequencedTaskRunner> caller_task_runner = {}); - - XmppLogToServer(const XmppLogToServer&) = delete; - XmppLogToServer& operator=(const XmppLogToServer&) = delete; - - ~XmppLogToServer() override; - - // SignalStrategy::Listener interface. - void OnSignalStrategyStateChange(SignalStrategy::State state) override; - bool OnSignalStrategyIncomingStanza( - const jingle_xmpp::XmlElement* stanza) override; - - // LogToServer interface. - void Log(const ServerLogEntry& entry) override; - ServerLogEntry::Mode mode() const override; - - private: - void Init(); - void SendPendingEntries(); - - ServerLogEntry::Mode mode_; - raw_ptr<SignalStrategy> signal_strategy_; - std::unique_ptr<IqSender> iq_sender_; - std::string directory_bot_jid_; - - base::circular_deque<ServerLogEntry> pending_entries_; - - SEQUENCE_CHECKER(sequence_checker_); - - base::WeakPtrFactory<XmppLogToServer> weak_factory_{this}; -}; - -} // namespace remoting - -#endif // REMOTING_SIGNALING_XMPP_LOG_TO_SERVER_H_
diff --git a/remoting/signaling/xmpp_log_to_server_unittest.cc b/remoting/signaling/xmpp_log_to_server_unittest.cc deleted file mode 100644 index 31c50e9..0000000 --- a/remoting/signaling/xmpp_log_to_server_unittest.cc +++ /dev/null
@@ -1,92 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "remoting/signaling/xmpp_log_to_server.h" - -#include <memory> - -#include "base/run_loop.h" -#include "base/test/task_environment.h" -#include "remoting/signaling/mock_signal_strategy.h" -#include "remoting/signaling/server_log_entry_unittest.h" -#include "remoting/signaling/signaling_address.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using jingle_xmpp::QName; -using jingle_xmpp::XmlElement; -using testing::_; -using testing::DeleteArg; -using testing::DoAll; -using testing::InSequence; -using testing::Return; - -namespace remoting { - -namespace { - -const char kTestBotJid[] = "remotingunittest@bot.talk.google.com"; -const char kClientJid[] = "host@domain.com/1234"; - -MATCHER_P2(IsLogEntry, key, value, "") { - XmlElement* entry = GetSingleLogEntryFromStanza(arg); - if (!entry) { - return false; - } - - return entry->Attr(QName(std::string(), key)) == value; -} - -} // namespace - -class XmppLogToServerTest : public testing::Test { - public: - XmppLogToServerTest() : signal_strategy_(SignalingAddress(kClientJid)) {} - void SetUp() override { - EXPECT_CALL(signal_strategy_, AddListener(_)); - EXPECT_CALL(signal_strategy_, RemoveListener(_)); - xmpp_log_to_server_ = std::make_unique<XmppLogToServer>( - ServerLogEntry::ME2ME, &signal_strategy_, kTestBotJid); - } - - protected: - base::test::SingleThreadTaskEnvironment task_environment_; - base::RunLoop run_loop_; - MockSignalStrategy signal_strategy_; - std::unique_ptr<XmppLogToServer> xmpp_log_to_server_; -}; - -TEST_F(XmppLogToServerTest, LogWhenConnected) { - { - InSequence s; - EXPECT_CALL(signal_strategy_, AddListener(_)); - EXPECT_CALL(signal_strategy_, GetNextId()); - EXPECT_CALL(signal_strategy_, SendStanzaPtr(IsLogEntry("a", "1"))) - .WillOnce(DoAll(DeleteArg<0>(), Return(true))); - EXPECT_CALL(signal_strategy_, GetNextId()); - EXPECT_CALL(signal_strategy_, SendStanzaPtr(IsLogEntry("b", "2"))) - .WillOnce(DoAll(DeleteArg<0>(), Return(true))); - EXPECT_CALL(signal_strategy_, RemoveListener(_)).RetiresOnSaturation(); - } - - ServerLogEntry entry1; - ServerLogEntry entry2; - entry1.Set("a", "1"); - entry2.Set("b", "2"); - xmpp_log_to_server_->Log(entry1); - xmpp_log_to_server_->OnSignalStrategyStateChange(SignalStrategy::CONNECTED); - xmpp_log_to_server_->Log(entry2); - run_loop_.RunUntilIdle(); -} - -TEST_F(XmppLogToServerTest, DontLogWhenDisconnected) { - EXPECT_CALL(signal_strategy_, SendStanzaPtr(_)).Times(0); - - ServerLogEntry entry; - entry.Set("foo", "bar"); - xmpp_log_to_server_->Log(entry); - run_loop_.RunUntilIdle(); -} - -} // namespace remoting
diff --git a/services/screen_ai/screen_ai_ocr_perf_test.cc b/services/screen_ai/screen_ai_ocr_perf_test.cc index 36c7443..da2911c4 100644 --- a/services/screen_ai/screen_ai_ocr_perf_test.cc +++ b/services/screen_ai/screen_ai_ocr_perf_test.cc
@@ -12,6 +12,7 @@ #include "base/command_line.h" #include "base/compiler_specific.h" #include "base/containers/map_util.h" +#include "base/files/file_enumerator.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/json/json_file_value_serializer.h" @@ -43,12 +44,14 @@ screen_ai_ocr_perf [options] Options: - --help Show this help message and exit. - --jpeg_image The image to test in JPEG format. - --output_path The path to store the perf result in JSON format. + --help Show this help message and exit. + --jpeg_image The single image to test in JPEG format. + --image_folder The path to a folder containing batch JPEG images to test. + --output_path The path to store the perf result in JSON format. )"; constexpr char kJpegImageOption[] = "jpeg_image"; +constexpr char kImageFolderOption[] = "image_folder"; constexpr char kOutputPathOption[] = "output_path"; constexpr int kWarmUpIterationCount = 3; @@ -95,12 +98,24 @@ } OcrTestEnvironment(const std::string& output_path, - const std::string& jpeg_image_path) - : output_path_(output_path), - jpeg_image_(GetBitmap(base::FilePath(jpeg_image_path))) {} + const std::string& jpeg_image_path, + const std::string& image_folder) + : output_path_(output_path) { + if (!jpeg_image_path.empty()) { + jpeg_images_.push_back(GetBitmap(base::FilePath(jpeg_image_path))); + } else if (!image_folder.empty()) { + base::FileEnumerator enumerator(base::FilePath(image_folder), + /*recursive=*/false, + base::FileEnumerator::FILES); + for (base::FilePath current_image = enumerator.Next(); + !current_image.empty(); current_image = enumerator.Next()) { + jpeg_images_.push_back(GetBitmap(base::FilePath(current_image))); + } + } + } void SetUp() override { - CHECK(!jpeg_image_.empty()); + CHECK(!jpeg_images_.empty()); base::FilePath directory_path(kLibraryDirectoryPath); base::FilePath library_path = directory_path.Append(kLibraryName); @@ -146,7 +161,11 @@ } } - void PerformOcr() { library_->PerformOcr(jpeg_image_); } + void PerformOcr() { + for (const auto& image : jpeg_images_) { + library_->PerformOcr(image); + } + } void Benchmark(const std::string& metrics_name, base::RepeatingClosure target_ops) { @@ -182,7 +201,7 @@ base::Value::Dict perf_values_; base::FilePath output_path_; - SkBitmap jpeg_image_; + std::vector<SkBitmap> jpeg_images_; std::unique_ptr<ScreenAILibraryWrapper> library_; }; @@ -213,18 +232,27 @@ std::string jpeg_image = cmd_line->GetSwitchValueASCII(screen_ai::kJpegImageOption); + std::string image_folder = + cmd_line->GetSwitchValueASCII(screen_ai::kImageFolderOption); std::string output_path = cmd_line->GetSwitchValueASCII(screen_ai::kOutputPathOption); - if (jpeg_image.empty() || output_path.empty()) { - LOG(ERROR) << "Missing required options: " << screen_ai::kJpegImageOption - << ", " << screen_ai::kOutputPathOption << "\n"; + if (jpeg_image.empty() && image_folder.empty()) { + LOG(ERROR) << "Missing required option: " << screen_ai::kJpegImageOption + << " or " << screen_ai::kImageFolderOption << "\n"; + return EXIT_FAILURE; + } + + if (output_path.empty()) { + LOG(ERROR) << "Missing required option: " << screen_ai::kOutputPathOption + << "\n"; return EXIT_FAILURE; } ::testing::InitGoogleTest(&argc, argv); - screen_ai::g_env = new screen_ai::OcrTestEnvironment(output_path, jpeg_image); + screen_ai::g_env = + new screen_ai::OcrTestEnvironment(output_path, jpeg_image, image_folder); ::testing::AddGlobalTestEnvironment(screen_ai::g_env); return RUN_ALL_TESTS(); }
diff --git a/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom b/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom index 4828bfc..3066550 100644 --- a/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom +++ b/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom
@@ -219,17 +219,11 @@ EnableFrameSinkManagerTestApi( pending_receiver<FrameSinkManagerTestApi> receiver); - // Setup the connection between the Browser (at WebContentsImpl level) and - // the VizCompositor thread (at InputManager level) in both directions to - // allow transferring information from Viz to the Browser and vice versa, - // when the VizCompositor thread is handling input using RenderInputRouters - // with InputVizard. - SetupRenderInputRouterDelegateConnection( - mojo_base.mojom.UnguessableToken grouping_id, - pending_remote<input.mojom.RenderInputRouterDelegateClient> - rir_delegate_client_remote, - pending_receiver<input.mojom.RenderInputRouterDelegate> - rir_delegate_receiver); + // Sets up the RendererInputRouterDelegateRegistry interface for managing + // RenderInputRouterDelegate connections between RenderWidgetHosts (on + // CrBrowserMain thread) and the InputManager (on VizCompositor thread). + SetupRendererInputRouterDelegateRegistry( + pending_receiver<RendererInputRouterDelegateRegistry> receiver); // Notifies list of RenderInputRouters of their block state changes for input // event handling on the VizCompositorThread. @@ -282,3 +276,22 @@ blink.mojom.SameDocNavigationScreenshotDestinationToken destination_token, CopyOutputResult copy_output_result); }; + +// Implemented by the GPU process (VizCompositorThread) and called from the +// browser process (CrBrowserMain thread). This allows the +// RenderInputRouterDelegate[Client] interface to use the same mojo pipe to +// send/receive information for input handling between the CrBrowserMain and the +// VizCompositorThread. +interface RendererInputRouterDelegateRegistry { + // Setup the connection between the Browser (at RenderWidgetHost level) and + // the VizCompositor thread (at InputManager level) in both directions to + // allow transferring information from Viz to the Browser and vice versa, + // when the VizCompositor thread is handling input using RenderInputRouters + // with InputVizard. This connection is per FrameSinkId. + SetupRenderInputRouterDelegateConnection( + FrameSinkId id, + pending_associated_remote<input.mojom.RenderInputRouterDelegateClient> + rir_delegate_client_remote, + pending_associated_receiver<input.mojom.RenderInputRouterDelegate> + rir_delegate_receiver); +};
diff --git a/services/webnn/ort/graph_builder_ort.h b/services/webnn/ort/graph_builder_ort.h index ae1c2359a..fe51838e 100644 --- a/services/webnn/ort/graph_builder_ort.h +++ b/services/webnn/ort/graph_builder_ort.h
@@ -39,8 +39,8 @@ // external data (weights). // // Returns unexpected if it fails. - [[nodiscard]] base::expected<std::unique_ptr<ModelEditor::ModelInfo>, - mojom::ErrorPtr> + [[nodiscard]] static base::expected<std::unique_ptr<ModelEditor::ModelInfo>, + mojom::ErrorPtr> CreateAndBuild( const mojom::GraphInfo& graph_info, ContextProperties context_properties,
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index b78d898..7f5c4e40 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -5232,6 +5232,21 @@ ] } ], + "ClankMostVisitedTilesCustomization": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "MostVisitedTilesCustomization" + ] + } + ] + } + ], "ClankMostVisitedTilesNewScoring": [ { "platforms": [ @@ -23811,7 +23826,8 @@ "TimedHTMLParserBudgetForAndroid": [ { "platforms": [ - "android" + "android", + "android_webview" ], "experiments": [ {
diff --git a/third_party/androidx/build.gradle b/third_party/androidx/build.gradle index 954bf4c..b9fc5843 100644 --- a/third_party/androidx/build.gradle +++ b/third_party/androidx/build.gradle
@@ -305,7 +305,7 @@ google() maven { // This URL is generated by the fetch_all_androidx.py script. - url 'https://androidx.dev/snapshots/builds/13555495/artifacts/repository' + url 'https://androidx.dev/snapshots/builds/13558109/artifacts/repository' } mavenCentral() }
diff --git a/third_party/angle b/third_party/angle index 2f6f051..90668ec 160000 --- a/third_party/angle +++ b/third_party/angle
@@ -1 +1 @@ -Subproject commit 2f6f0514563d81e439e04ba09eee9e8a1d6ca8d1 +Subproject commit 90668ecf2978f085de9a9bdef4d8e5bad79df71e
diff --git a/third_party/blink/public/mojom/mediastream/media_stream.mojom b/third_party/blink/public/mojom/mediastream/media_stream.mojom index 482dfbeb..360ae63 100644 --- a/third_party/blink/public/mojom/mediastream/media_stream.mojom +++ b/third_party/blink/public/mojom/mediastream/media_stream.mojom
@@ -55,6 +55,24 @@ // Elements in this enum should not be deleted or rearranged; the only // permitted operation is to add new elements before NUM_MEDIA_REQUEST_RESULTS. +// +// This enum is used by GenerateStreams(), which is a critical part +// of such Web API calls as getDisplayMedia() and getUserMedia(). +// +// Much of the logic is shared, and so are the enum values. +// However, some enum values are specific to gDM/gUM, +// and some values are used slightly differently between +// calls associated with gDM/gUM. +// +// These differences were not exhaustively documented. +// We provide partial documentation starting now; +// hopefully this can be extended over time. +// +// The non-exhaustive list of differences includes: +// - Calls to gDM which result in the user explicitly rejecting the prompt +// result in PERMISSION_DENIED_BY_USER. This allows a distinct error name, +// message or type to be exposed to the caller. +// In contrast, gUM returns PERMISSION_DENIED in such cases - for now. enum MediaStreamRequestResult { OK, PERMISSION_DENIED, @@ -75,6 +93,7 @@ DEVICE_IN_USE, REQUEST_CANCELLED, START_TIMEOUT, + PERMISSION_DENIED_BY_USER, NUM_MEDIA_REQUEST_RESULTS, };
diff --git a/third_party/blink/public/mojom/payments/payment_request.mojom b/third_party/blink/public/mojom/payments/payment_request.mojom index dfd2990..a054d85 100644 --- a/third_party/blink/public/mojom/payments/payment_request.mojom +++ b/third_party/blink/public/mojom/payments/payment_request.mojom
@@ -179,8 +179,16 @@ // Experimental members that allow specifying information about the card // network and issuer, including icons for both. These are controlled by the // SecurePaymentConfirmationNetworkAndIssuerIcons Blink runtime feature. + // + // Note: These parameters are deprecated in favour of + // |payment_entities_logos|, but are being kept for now to support partner + // testing while the updated API is in development. NetworkOrIssuerInformation? network_info; NetworkOrIssuerInformation? issuer_info; + + // A list of logos representing entities that are facilitating the payment + // that this SPC call is for. + array<PaymentEntityLogo> payment_entities_logos; }; struct NetworkOrIssuerInformation { @@ -188,6 +196,12 @@ url.mojom.Url icon; }; +struct PaymentEntityLogo { + // Only HTTP(s) or data URLs are permitted. + url.mojom.Url url; + string label; +}; + struct PaymentMethodData { string supported_method;
diff --git a/third_party/blink/renderer/bindings/core/v8/script_promise_resolver_with_tracker.h b/third_party/blink/renderer/bindings/core/v8/script_promise_resolver_with_tracker.h index a56e2db..e8ce91e 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_promise_resolver_with_tracker.h +++ b/third_party/blink/renderer/bindings/core/v8/script_promise_resolver_with_tracker.h
@@ -127,8 +127,8 @@ return; is_result_recorded_ = true; - base::UmaHistogramEnumeration(metric_name_prefix_ + "." + result_suffix_, - result); + base::UmaHistogramEnumeration( + base::StrCat({metric_name_prefix_, ".", result_suffix_}), result); } void RecordLatency() {
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni index 3e985636..39168d3 100644 --- a/third_party/blink/renderer/bindings/generated_in_modules.gni +++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -950,6 +950,8 @@ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_payment_details_modifier.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_payment_details_update.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_payment_details_update.h", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_payment_entity_logo.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_payment_entity_logo.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_payment_handler_response.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_payment_handler_response.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_payment_item.cc",
diff --git a/third_party/blink/renderer/bindings/idl_in_modules.gni b/third_party/blink/renderer/bindings/idl_in_modules.gni index 35714f5..37a640d9 100644 --- a/third_party/blink/renderer/bindings/idl_in_modules.gni +++ b/third_party/blink/renderer/bindings/idl_in_modules.gni
@@ -557,6 +557,7 @@ "//third_party/blink/renderer/modules/payments/payment_details_init.idl", "//third_party/blink/renderer/modules/payments/payment_details_modifier.idl", "//third_party/blink/renderer/modules/payments/payment_details_update.idl", + "//third_party/blink/renderer/modules/payments/payment_entity_logo.idl", "//third_party/blink/renderer/modules/payments/payment_handler_response.idl", "//third_party/blink/renderer/modules/payments/payment_item.idl", "//third_party/blink/renderer/modules/payments/payment_manager.idl",
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index da2b0c7ca6..47c6a924 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -398,11 +398,6 @@ #include "third_party/blink/renderer/platform/wtf/text/text_encoding_registry.h" #include "third_party/blink/renderer/platform/wtf/text/utf16.h" -#ifndef NDEBUG -using WeakDocumentSet = blink::HeapHashSet<blink::WeakMember<blink::Document>>; -static WeakDocumentSet& LiveDocumentSet(); -#endif - namespace blink { namespace { @@ -414,6 +409,15 @@ bool SkipNonAtomicInlineObservations() const final; }; +using WeakDocumentSet = blink::HeapHashSet<blink::WeakMember<blink::Document>>; + +WeakDocumentSet& LiveDocumentSet() { + using WeakDocumentSetHolder = blink::DisallowNewWrapper<WeakDocumentSet>; + DEFINE_STATIC_LOCAL(blink::Persistent<WeakDocumentSetHolder>, holder, + (blink::MakeGarbageCollected<WeakDocumentSetHolder>())); + return holder->Value(); +} + // Returns true if any of <object> ancestors don't start loading or are loading // plugins/frames/images. If there are no <object> ancestors, this function // returns false. @@ -973,9 +977,7 @@ DCHECK(!ParentDocument() || !ParentDocument()->domWindow()->IsContextPaused()); -#ifndef NDEBUG LiveDocumentSet().insert(this); -#endif } Document::~Document() { @@ -9554,12 +9556,17 @@ void Document::OnLocalRootWidgetCreated() { if (!features::kThrottleFrameRateOnInitialization.Get() || !GetFrame() || - !GetFrame()->GetPage() || !GetFrame()->IsAttached() || - !GetExecutionContext()->CrossOriginIsolatedCapability()) { + !GetFrame()->GetPage() || !GetFrame()->IsAttached()) { return; } - GetFrame()->GetPage()->GetChromeClient().SetShouldThrottleFrameRate( - true, *GetFrame()); + bool allowed_by_security = CanThrottleFrameRate(); + base::UmaHistogramBoolean( + "Blink.ThrottleFrameRate.AllowedBySecurity.DocumentInitialization", + allowed_by_security); + if (allowed_by_security) { + GetFrame()->GetPage()->GetChromeClient().SetShouldThrottleFrameRate( + true, *GetFrame()); + } } void Document::ProcessScheduledShadowTreeCreationsNow() { @@ -9605,12 +9612,16 @@ } void Document::UpdateRenderFrameRate() { - if (!GetFrame() || !GetFrame()->GetPage() || !GetFrame()->IsAttached() || - !GetExecutionContext()->CrossOriginIsolatedCapability()) { + if (!GetFrame() || !GetFrame()->GetPage() || !GetFrame()->IsAttached()) { return; } - GetFrame()->GetPage()->GetChromeClient().SetShouldThrottleFrameRate( - has_frame_rate_blocking_expect_link_elements_, *GetFrame()); + bool allowed_by_security = CanThrottleFrameRate(); + base::UmaHistogramBoolean("Blink.ThrottleFrameRate.AllowedBySecurity.API", + allowed_by_security); + if (allowed_by_security) { + GetFrame()->GetPage()->GetChromeClient().SetShouldThrottleFrameRate( + has_frame_rate_blocking_expect_link_elements_, *GetFrame()); + } } // static @@ -9780,19 +9791,30 @@ return cached_top_frame_site_for_visited_links_.value(); } +bool Document::CanThrottleFrameRate() { + // To prevent side-channel attacks by monitoring the frame rate to detect + // page loads from other origins, we only allow the frame rate to be throttled + // if the renderer process is only hosting pages from one origin. + CHECK(GetExecutionContext()); + const SecurityOrigin* expected_security_origin = + GetExecutionContext()->GetSecurityOrigin(); + for (blink::Document* document : blink::LiveDocumentSet()) { + if (!document->GetExecutionContext() || + !document->GetExecutionContext()->GetSecurityOrigin()->IsSameOriginWith( + expected_security_origin)) { + return false; + } + } + return true; +} + template class CORE_TEMPLATE_EXPORT Supplement<Document>; } // namespace blink -#ifndef NDEBUG -static WeakDocumentSet& LiveDocumentSet() { - using WeakDocumentSetHolder = blink::DisallowNewWrapper<WeakDocumentSet>; - DEFINE_STATIC_LOCAL(blink::Persistent<WeakDocumentSetHolder>, holder, - (blink::MakeGarbageCollected<WeakDocumentSetHolder>())); - return holder->Value(); -} +#ifndef NDEBUG void ShowLiveDocumentInstances() { - WeakDocumentSet& set = LiveDocumentSet(); + blink::WeakDocumentSet& set = blink::LiveDocumentSet(); fprintf(stderr, "There are %u documents currently alive:\n", set.size()); for (blink::Document* document : set) { fprintf(stderr, "- Document %p URL: %s\n", document,
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h index 00ef003..cbda08b1 100644 --- a/third_party/blink/renderer/core/dom/document.h +++ b/third_party/blink/renderer/core/dom/document.h
@@ -2494,6 +2494,8 @@ const String& html, ExceptionState& exception_state); + bool CanThrottleFrameRate(); + // Mutable because the token is lazily-generated on demand if no token is // explicitly set. mutable std::optional<DocumentToken> token_;
diff --git a/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.cc b/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.cc index a8cf2d3..107dc31 100644 --- a/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.cc +++ b/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.cc
@@ -255,6 +255,16 @@ return buffer; } +DOMArrayBuffer* DOMArrayBuffer::CreateUninitialized(size_t num_elements, + size_t element_byte_size) { + ArrayBufferContents contents( + num_elements, element_byte_size, ArrayBufferContents::kNotShared, + ArrayBufferContents::kDontInitialize, + ArrayBufferContents::AllocationFailureBehavior::kCrash); + CHECK(contents.IsValid()); + return Create(std::move(contents)); +} + DOMArrayBuffer* DOMArrayBuffer::CreateUninitializedOrNull( size_t num_elements, size_t element_byte_size) {
diff --git a/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h b/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h index 5fbaa02..384f2ca 100644 --- a/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h +++ b/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h
@@ -44,12 +44,6 @@ contents.ByteSpan().copy_from(source); return Create(std::move(contents)); } - // TODO(tsepez): should be declared UNSAFE_BUFFER_USAGE. - static DOMArrayBuffer* Create(const void* source, size_t byte_length) { - // SAFETY: Caller guarantees that `source` contains `byte_length` bytes. - return Create(UNSAFE_BUFFERS( - base::span(static_cast<const uint8_t*>(source), byte_length))); - } static DOMArrayBuffer* Create(scoped_refptr<SharedBuffer>); static DOMArrayBuffer* Create(const Vector<base::span<const char>>&); @@ -57,13 +51,10 @@ static DOMArrayBuffer* CreateOrNull(size_t num_elements, size_t element_byte_size); static DOMArrayBuffer* CreateOrNull(base::span<const uint8_t> source); - // TODO(tsepez): should be declared UNSAFE_BUFFER_USAGE. - static DOMArrayBuffer* CreateOrNull(const void* source, size_t byte_length) { - // SAFETY: Caller guarantees that `source` contains `byte_length` bytes. - return CreateOrNull(UNSAFE_BUFFERS( - base::span(static_cast<const uint8_t*>(source), byte_length))); - } + // For use by DOMTypedArray. + static DOMArrayBuffer* CreateUninitialized(size_t num_elements, + size_t element_byte_size); // Only for use by XMLHttpRequest::responseArrayBuffer, // Internals::serializeObject, and // FetchDataLoaderAsArrayBuffer::OnStateChange.
diff --git a/third_party/blink/renderer/core/typed_arrays/dom_typed_array.h b/third_party/blink/renderer/core/typed_arrays/dom_typed_array.h index 53352a42..454fb5c6f 100644 --- a/third_party/blink/renderer/core/typed_arrays/dom_typed_array.h +++ b/third_party/blink/renderer/core/typed_arrays/dom_typed_array.h
@@ -34,12 +34,11 @@ static ThisType* Create(base::span<const ValueType> array) requires std::is_trivially_copyable_v<ValueType> { - // Intentionally avoids using `as_bytes`, since that requires - // `std::has_unique_object_representations_v<ValueType>`, which we neither - // need here nor can guarantee. DOMArrayBuffer* buffer = - DOMArrayBuffer::Create(array.data(), array.size_bytes()); - return Create(buffer, 0, array.size()); + DOMArrayBuffer::CreateUninitialized(array.size(), sizeof(ValueType)); + ThisType* typed_array = Create(buffer, 0, array.size()); + typed_array->AsSpan().copy_from(array); + return typed_array; } static ThisType* CreateOrNull(size_t length) { @@ -51,12 +50,11 @@ static ThisType* CreateOrNull(base::span<const ValueType> array) requires std::is_trivially_copyable_v<ValueType> { - // Intentionally avoids using `as_bytes`, since that requires - // `std::has_unique_object_representations_v<ValueType>`, which we neither - // need here nor can guarantee. - DOMArrayBuffer* buffer = - DOMArrayBuffer::CreateOrNull(array.data(), array.size_bytes()); - return buffer ? Create(buffer, 0, array.size()) : nullptr; + ThisType* typed_array = CreateUninitializedOrNull(array.size()); + if (typed_array) { + typed_array->AsSpan().copy_from(array); + } + return typed_array; } static ThisType* CreateUninitializedOrNull(size_t length) {
diff --git a/third_party/blink/renderer/modules/ai/language_model.cc b/third_party/blink/renderer/modules/ai/language_model.cc index 5560b4b..578806a9 100644 --- a/third_party/blink/renderer/modules/ai/language_model.cc +++ b/third_party/blink/renderer/modules/ai/language_model.cc
@@ -596,12 +596,6 @@ return std::nullopt; } - if (!input->IsString() && - !RuntimeEnabledFeatures::AIPromptAPIMultimodalInputEnabled()) { - exception_state.ThrowTypeError("Input type not supported"); - return std::nullopt; - } - AbortSignal* signal = options->getSignalOr(nullptr); if (HandleAbortSignal(signal, script_state, exception_state)) { return std::nullopt; @@ -643,12 +637,6 @@ MakeGarbageCollected<ScriptPromiseResolver<IDLUndefined>>(script_state); auto promise = resolver->Promise(); - // The API impl only accepts a string by default for now, more to come soon! - if (!input->IsString() && - !RuntimeEnabledFeatures::AIPromptAPIMultimodalInputEnabled()) { - exception_state.ThrowTypeError("Input type not supported"); - return promise; - } if (!language_model_remote_) { ThrowSessionDestroyedException(exception_state); return promise; @@ -716,13 +704,6 @@ return EmptyPromise(); } - // The API impl only accepts a string by default for now, more to come soon! - if (!input->IsString() && - !RuntimeEnabledFeatures::AIPromptAPIMultimodalInputEnabled()) { - exception_state.ThrowTypeError("Input type not supported"); - return EmptyPromise(); - } - base::UmaHistogramEnumeration(AIMetrics::GetAIAPIUsageMetricName( AIMetrics::AISessionType::kLanguageModel), AIMetrics::AIAPI::kSessionCountPromptTokens);
diff --git a/third_party/blink/renderer/modules/ai/language_model_prompt_builder.cc b/third_party/blink/renderer/modules/ai/language_model_prompt_builder.cc index 32e7b20..b49ecc7 100644 --- a/third_party/blink/renderer/modules/ai/language_model_prompt_builder.cc +++ b/third_party/blink/renderer/modules/ai/language_model_prompt_builder.cc
@@ -251,13 +251,19 @@ break; } } - // Multimodal (non-text) input is not supported for the assistant role. - if (message->role() == V8LanguageModelMessageRole::Enum::kAssistant && - is_multimodal) { - Reject(DOMException::Create( - "Multimodal input is not supported for the assistant role.", - DOMException::GetErrorName(DOMExceptionCode::kNotSupportedError))); - return; + if (is_multimodal) { + if (!RuntimeEnabledFeatures::AIPromptAPIMultimodalInputEnabled()) { + v8::Isolate* isolate = script_state_->GetIsolate(); + Reject(ScriptValue(isolate, V8ThrowException::CreateTypeError( + isolate, "Input type not supported"))); + return; + } + if (message->role() == V8LanguageModelMessageRole::Enum::kAssistant) { + Reject(DOMException::Create( + "Multimodal input is not supported for the assistant role.", + DOMException::GetErrorName(DOMExceptionCode::kNotSupportedError))); + return; + } } }
diff --git a/third_party/blink/renderer/modules/cache_storage/cache_storage.cc b/third_party/blink/renderer/modules/cache_storage/cache_storage.cc index 1800d5d..97d3302 100644 --- a/third_party/blink/renderer/modules/cache_storage/cache_storage.cc +++ b/third_party/blink/renderer/modules/cache_storage/cache_storage.cc
@@ -288,7 +288,8 @@ base::TimeDelta actual_delay = base::TimeTicks::Now() - start_time; base::UmaHistogramTimes( - "ServiceWorkerCache.Cache.Renderer." + + "ServiceWorkerCache.CacheStorage." + "Renderer." + operation_name + ".AblationDelay", actual_delay); },
diff --git a/third_party/blink/renderer/modules/mediastream/media_devices.cc b/third_party/blink/renderer/modules/mediastream/media_devices.cc index 63b1a2384..707bae42 100644 --- a/third_party/blink/renderer/modules/mediastream/media_devices.cc +++ b/third_party/blink/renderer/modules/mediastream/media_devices.cc
@@ -476,9 +476,11 @@ // This timeout of base::Seconds(8) is an initial value and based on the data // in Media.MediaDevices.GetUserMedia.Latency, it should be iterated upon. + // Records the `Media.MediaDevices.GetUserMedia.Result2` histogram. auto* resolver = MakeGarbageCollected< ScriptPromiseResolverWithTracker<UserMediaRequestResult, MediaStream>>( script_state, "Media.MediaDevices.GetUserMedia", base::Seconds(8)); + resolver->SetResultSuffix("Result2"); const auto promise = resolver->Promise(); DCHECK(options); // Guaranteed by the default value in the IDL. @@ -607,9 +609,11 @@ // This timeout of base::Seconds(6) is an initial value and based on the data // in Media.MediaDevices.GetAllScreensMedia.Latency, it should be iterated // upon. + // Records the `Media.MediaDevices.GetAllScreensMedia.Result2` histogram. auto* resolver = MakeGarbageCollected<ScriptPromiseResolverWithTracker< UserMediaRequestResult, IDLSequence<MediaStream>>>( script_state, "Media.MediaDevices.GetAllScreensMedia", base::Seconds(6)); + resolver->SetResultSuffix("Result2"); auto promise = resolver->Promise(); ExecutionContext* const context = GetExecutionContext(); @@ -661,9 +665,11 @@ // Using timeout of base::Seconds(12) based on the // Media.MediaDevices.GetDisplayMedia.Latency values. + // Records the `Media.MediaDevices.GetDisplayMedia.Result2` histogram. auto* resolver = MakeGarbageCollected< ScriptPromiseResolverWithTracker<UserMediaRequestResult, MediaStream>>( script_state, "Media.MediaDevices.GetDisplayMedia", base::Seconds(12)); + resolver->SetResultSuffix("Result2"); auto promise = resolver->Promise(); if (!window) {
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_processor.cc b/third_party/blink/renderer/modules/mediastream/user_media_processor.cc index 85f95b7..ee637397 100644 --- a/third_party/blink/renderer/modules/mediastream/user_media_processor.cc +++ b/third_party/blink/renderer/modules/mediastream/user_media_processor.cc
@@ -119,6 +119,8 @@ return "REQUEST_CANCELLED"; case MediaStreamRequestResult::START_TIMEOUT: return "START_TIMEOUT"; + case MediaStreamRequestResult::PERMISSION_DENIED_BY_USER: + return "PERMISSION_DENIED_BY_USER"; case MediaStreamRequestResult::NUM_MEDIA_REQUEST_RESULTS: break; } @@ -291,6 +293,8 @@ return "Timeout starting video source"; case MediaStreamRequestResult::CONSTRAINT_NOT_SATISFIED: return "Constraint not satisfied"; + case MediaStreamRequestResult::PERMISSION_DENIED_BY_USER: + return "Permission denied by user"; case MediaStreamRequestResult::NUM_MEDIA_REQUEST_RESULTS: break; // Not a valid enum value. }
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_request.cc b/third_party/blink/renderer/modules/mediastream/user_media_request.cc index 7c17721..f674e9c 100644 --- a/third_party/blink/renderer/modules/mediastream/user_media_request.cc +++ b/third_party/blink/renderer/modules/mediastream/user_media_request.cc
@@ -862,6 +862,10 @@ exception_code = DOMExceptionCode::kNotAllowedError; result_enum = UserMediaRequestResult::kNotAllowedError; break; + case Result::PERMISSION_DENIED_BY_USER: + exception_code = DOMExceptionCode::kNotAllowedError; + result_enum = UserMediaRequestResult::kNotAllowedByUserError; + break; case Result::NO_HARDWARE: exception_code = DOMExceptionCode::kNotFoundError; result_enum = UserMediaRequestResult::kNotFoundError;
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_request.h b/third_party/blink/renderer/modules/mediastream/user_media_request.h index 4aee660..87025ce 100644 --- a/third_party/blink/renderer/modules/mediastream/user_media_request.h +++ b/third_party/blink/renderer/modules/mediastream/user_media_request.h
@@ -52,6 +52,8 @@ enum class UserMediaRequestType { kUserMedia, kDisplayMedia, kAllScreensMedia }; +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class UserMediaRequestResult { kOk = 0, kTimedOut = 1, @@ -66,7 +68,8 @@ kNotSupportedError = 10, kInsecureContext = 11, kInvalidStateError = 12, - kMaxValue = kInvalidStateError + kNotAllowedByUserError = 13, + kMaxValue = kNotAllowedByUserError }; class MODULES_EXPORT UserMediaRequest final
diff --git a/third_party/blink/renderer/modules/payments/payment_entity_logo.idl b/third_party/blink/renderer/modules/payments/payment_entity_logo.idl new file mode 100644 index 0000000..a1e6f8f --- /dev/null +++ b/third_party/blink/renderer/modules/payments/payment_entity_logo.idl
@@ -0,0 +1,9 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// https://w3c.github.io/secure-payment-confirmation/#sctn-paymententitylogo-dictionary +dictionary PaymentEntityLogo { + required USVString url; + required USVString label; +};
diff --git a/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper.cc b/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper.cc index cf561130..230b28c7 100644 --- a/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper.cc +++ b/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper.cc
@@ -10,9 +10,10 @@ #include "third_party/blink/public/mojom/payments/payment_request.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h" #include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_payment_credential_instrument.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_secure_payment_confirmation_request.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_network_or_issuer_information.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_payment_credential_instrument.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_payment_entity_logo.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_secure_payment_confirmation_request.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/modules/payments/secure_payment_confirmation_type_converter.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" @@ -175,6 +176,43 @@ } } + if (request->hasPaymentEntitiesLogos()) { + for (const PaymentEntityLogo* logo : request->paymentEntitiesLogos()) { + // The IDL bindings code does not allow the sequence to contain null + // entries. + CHECK(logo); + + if (logo->url().empty()) { + exception_state.ThrowTypeError( + "The \"secure-payment-confirmation\" method requires that each " + "entry in \"paymentEntitiesLogos\" has a non-empty \"url\" field."); + return nullptr; + } + KURL logo_url(logo->url()); + if (!logo_url.IsValid()) { + exception_state.ThrowTypeError( + "The \"secure-payment-confirmation\" method requires that each " + "entry in \"paymentEntitiesLogos\" has a valid URL in the \"url\" " + "field."); + return nullptr; + } + if (!logo_url.ProtocolIsInHTTPFamily() && !logo_url.ProtocolIsData()) { + exception_state.ThrowTypeError( + "The \"secure-payment-confirmation\" method requires that each " + "entry in \"paymentEntitiesLogos\" has a URL whose scheme is one " + "of \"https\", \"http\", or \"data\" in the \"url\" field."); + return nullptr; + } + if (logo->label().empty()) { + exception_state.ThrowTypeError( + "The \"secure-payment-confirmation\" method requires that each " + "entry in \"paymentEntitiesLogos\" has a non-empty \"label\" " + "field."); + return nullptr; + } + } + } + return mojo::ConvertTo< payments::mojom::blink::SecurePaymentConfirmationRequestPtr>(request); }
diff --git a/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper_test.cc b/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper_test.cc index 4b1d695..3249f9b9 100644 --- a/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper_test.cc +++ b/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper_test.cc
@@ -18,6 +18,7 @@ #include "third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_prf_values.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_network_or_issuer_information.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_payment_credential_instrument.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_payment_entity_logo.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_public_key_credential_parameters.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_secure_payment_confirmation_request.h" #include "third_party/blink/renderer/modules/payments/payment_test_helper.h" @@ -32,6 +33,11 @@ static const uint8_t kPrfInputData[] = {1, 2, 3, 4, 5, 6}; +constexpr char kPngImageDataUrl[] = + "data:image/png;base64," + "iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAFElEQVQYlWNk+M/" + "wn4GBgYGJAQoAHhgCAh6X4CYAAAAASUVORK5CYII="; + WTF::Vector<uint8_t> CreateVector(base::span<const uint8_t> buffer) { WTF::Vector<uint8_t> vector; vector.AppendSpan(buffer); @@ -124,6 +130,14 @@ issuerInfo->setIcon("https://bank.example/icon.png"); request->setIssuerInfo(issuerInfo); + PaymentEntityLogo* logo1 = PaymentEntityLogo::Create(scope.GetIsolate()); + logo1->setUrl("https://entity1.example/icon.png"); + logo1->setLabel("Label 1"); + PaymentEntityLogo* logo2 = PaymentEntityLogo::Create(scope.GetIsolate()); + logo2->setUrl(kPngImageDataUrl); + logo2->setLabel("Label 2"); + request->setPaymentEntitiesLogos({logo1, logo2}); + ScriptValue script_value(scope.GetIsolate(), ToV8Traits<SecurePaymentConfirmationRequest>::ToV8( scope.GetScriptState(), request)); @@ -145,6 +159,11 @@ EXPECT_EQ(parsed_request->issuer_info->name, "Issuer Name"); EXPECT_EQ(parsed_request->issuer_info->icon.GetString(), "https://bank.example/icon.png"); + + // This field is behind a default-disabled flag, however when set directly + // into the request as above it will still be present and we can test that the + // mojo parsing works correctly. + EXPECT_EQ(parsed_request->payment_entities_logos.size(), 2u); } // Test that parsing a SecurePaymentConfirmationRequest with an empty @@ -591,6 +610,99 @@ scope.GetExceptionState().CodeAs<ESErrorType>()); } +// Test that parsing a SecurePaymentConfirmationRequest with a PaymentEntityLogo +// entry that has an empty url throws. +TEST(SecurePaymentConfirmationHelperTest, Parse_EmptyPaymentEntityLogoUrl) { + test::TaskEnvironment task_environment; + V8TestingScope scope; + SecurePaymentConfirmationRequest* request = + CreateSecurePaymentConfirmationRequest(scope); + + PaymentEntityLogo* logo = PaymentEntityLogo::Create(scope.GetIsolate()); + logo->setUrl(""); + logo->setLabel("Label"); + request->setPaymentEntitiesLogos({logo}); + + ScriptValue script_value(scope.GetIsolate(), + ToV8Traits<SecurePaymentConfirmationRequest>::ToV8( + scope.GetScriptState(), request)); + SecurePaymentConfirmationHelper::ParseSecurePaymentConfirmationData( + script_value, *scope.GetExecutionContext(), scope.GetExceptionState()); + EXPECT_TRUE(scope.GetExceptionState().HadException()); + EXPECT_EQ(ESErrorType::kTypeError, + scope.GetExceptionState().CodeAs<ESErrorType>()); +} + +// Test that parsing a SecurePaymentConfirmationRequest with a PaymentEntityLogo +// entry that has an invalid url throws. +TEST(SecurePaymentConfirmationHelperTest, Parse_InvalidPaymentEntityLogoUrl) { + test::TaskEnvironment task_environment; + V8TestingScope scope; + SecurePaymentConfirmationRequest* request = + CreateSecurePaymentConfirmationRequest(scope); + + PaymentEntityLogo* logo = PaymentEntityLogo::Create(scope.GetIsolate()); + logo->setUrl("thisisnotaurl"); + logo->setLabel("Label"); + request->setPaymentEntitiesLogos({logo}); + + ScriptValue script_value(scope.GetIsolate(), + ToV8Traits<SecurePaymentConfirmationRequest>::ToV8( + scope.GetScriptState(), request)); + SecurePaymentConfirmationHelper::ParseSecurePaymentConfirmationData( + script_value, *scope.GetExecutionContext(), scope.GetExceptionState()); + EXPECT_TRUE(scope.GetExceptionState().HadException()); + EXPECT_EQ(ESErrorType::kTypeError, + scope.GetExceptionState().CodeAs<ESErrorType>()); +} + +// Test that parsing a SecurePaymentConfirmationRequest with a PaymentEntityLogo +// entry that has a url with a disallowed protocol throws. +TEST(SecurePaymentConfirmationHelperTest, + Parse_DisallowedProtocolPaymentEntityLogoUrl) { + test::TaskEnvironment task_environment; + V8TestingScope scope; + SecurePaymentConfirmationRequest* request = + CreateSecurePaymentConfirmationRequest(scope); + + PaymentEntityLogo* logo = PaymentEntityLogo::Create(scope.GetIsolate()); + logo->setUrl("blob://blob.foo.com/logo.png"); + logo->setLabel("Label"); + request->setPaymentEntitiesLogos({logo}); + + ScriptValue script_value(scope.GetIsolate(), + ToV8Traits<SecurePaymentConfirmationRequest>::ToV8( + scope.GetScriptState(), request)); + SecurePaymentConfirmationHelper::ParseSecurePaymentConfirmationData( + script_value, *scope.GetExecutionContext(), scope.GetExceptionState()); + EXPECT_TRUE(scope.GetExceptionState().HadException()); + EXPECT_EQ(ESErrorType::kTypeError, + scope.GetExceptionState().CodeAs<ESErrorType>()); +} + +// Test that parsing a SecurePaymentConfirmationRequest with a PaymentEntityLogo +// entry that has an empty label throws. +TEST(SecurePaymentConfirmationHelperTest, Parse_EmptyPaymentEntityLogoLabel) { + test::TaskEnvironment task_environment; + V8TestingScope scope; + SecurePaymentConfirmationRequest* request = + CreateSecurePaymentConfirmationRequest(scope); + + PaymentEntityLogo* logo = PaymentEntityLogo::Create(scope.GetIsolate()); + logo->setUrl("https://entity.example/icon.png"); + logo->setLabel(""); + request->setPaymentEntitiesLogos({logo}); + + ScriptValue script_value(scope.GetIsolate(), + ToV8Traits<SecurePaymentConfirmationRequest>::ToV8( + scope.GetScriptState(), request)); + SecurePaymentConfirmationHelper::ParseSecurePaymentConfirmationData( + script_value, *scope.GetExecutionContext(), scope.GetExceptionState()); + EXPECT_TRUE(scope.GetExceptionState().HadException()); + EXPECT_EQ(ESErrorType::kTypeError, + scope.GetExceptionState().CodeAs<ESErrorType>()); +} + // Test that parsing a SecurePaymentConfirmationRequest converts the browser // bound public key credential parameters. TEST(SecurePaymentConfirmationHelperTest, Parse_BrowserBroundPubKeyCredParams) {
diff --git a/third_party/blink/renderer/modules/payments/secure_payment_confirmation_request.idl b/third_party/blink/renderer/modules/payments/secure_payment_confirmation_request.idl index d9e6a5d..453e2fb 100644 --- a/third_party/blink/renderer/modules/payments/secure_payment_confirmation_request.idl +++ b/third_party/blink/renderer/modules/payments/secure_payment_confirmation_request.idl
@@ -24,8 +24,16 @@ // were to launch this we should find a non-card specific way to encode // this information in the SecurePaymentConfirmationRequest, or better // encapsulate it into a single sub-dictionary. + // + // Note: These parameters are deprecated in favour of + // |paymentEntitiesLogos|, but are being kept for now to support partner + // testing while the updated API is in development. [RuntimeEnabled=SecurePaymentConfirmationNetworkAndIssuerIcons] NetworkOrIssuerInformation networkInfo; [RuntimeEnabled=SecurePaymentConfirmationNetworkAndIssuerIcons] NetworkOrIssuerInformation issuerInfo; + + // A list of logos representing entities that are facilitating the payment + // that this SPC call is for. + [RuntimeEnabled=SecurePaymentConfirmationUxRefresh] sequence<PaymentEntityLogo> paymentEntitiesLogos; }; dictionary NetworkOrIssuerInformation {
diff --git a/third_party/blink/renderer/modules/payments/secure_payment_confirmation_type_converter.cc b/third_party/blink/renderer/modules/payments/secure_payment_confirmation_type_converter.cc index 0d54b93f..276f424 100644 --- a/third_party/blink/renderer/modules/payments/secure_payment_confirmation_type_converter.cc +++ b/third_party/blink/renderer/modules/payments/secure_payment_confirmation_type_converter.cc
@@ -10,8 +10,9 @@ #include "third_party/blink/public/mojom/webauthn/authenticator.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_client_inputs.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_payment_credential_instrument.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_network_or_issuer_information.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_payment_credential_instrument.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_payment_entity_logo.h" #include "third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/wtf/vector.h" @@ -66,6 +67,12 @@ blink::KURL(input->issuerInfo()->icon())); } + if (input->hasPaymentEntitiesLogos()) { + output->payment_entities_logos = + ConvertTo<WTF::Vector<payments::mojom::blink::PaymentEntityLogoPtr>>( + input->paymentEntitiesLogos()); + } + if (input->hasBrowserBoundPubKeyCredParams()) { output->browser_bound_pub_key_cred_params = ConvertTo< WTF::Vector<blink::mojom::blink::PublicKeyCredentialParametersPtr>>( @@ -77,4 +84,11 @@ return output; } +payments::mojom::blink::PaymentEntityLogoPtr TypeConverter< + payments::mojom::blink::PaymentEntityLogoPtr, + blink::PaymentEntityLogo*>::Convert(const blink::PaymentEntityLogo* input) { + return payments::mojom::blink::PaymentEntityLogo::New( + blink::KURL(input->url()), input->label()); +} + } // namespace mojo
diff --git a/third_party/blink/renderer/modules/payments/secure_payment_confirmation_type_converter.h b/third_party/blink/renderer/modules/payments/secure_payment_confirmation_type_converter.h index f6914e03..3c5a58e 100644 --- a/third_party/blink/renderer/modules/payments/secure_payment_confirmation_type_converter.h +++ b/third_party/blink/renderer/modules/payments/secure_payment_confirmation_type_converter.h
@@ -19,6 +19,13 @@ const blink::SecurePaymentConfirmationRequest* input); }; +template <> +struct TypeConverter<payments::mojom::blink::PaymentEntityLogoPtr, + blink::PaymentEntityLogo*> { + static payments::mojom::blink::PaymentEntityLogoPtr Convert( + const blink::PaymentEntityLogo* input); +}; + } // namespace mojo #endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_SECURE_PAYMENT_CONFIRMATION_TYPE_CONVERTER_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc index 7281405..fd52dfa9 100644 --- a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc +++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc
@@ -869,9 +869,9 @@ (candidate->SdpMLineIndex() ? String::Number(*candidate->SdpMLineIndex()) : "null") + ", candidate: " + String(candidate->Candidate()) + - (!url.IsNull() ? ", url: " + url : String()) + - (!relay_protocol.IsNull() ? ", relayProtocol: " + relay_protocol - : String()); + (!url.empty() ? ", url: " + url : String()) + + (!relay_protocol.empty() ? ", relayProtocol: " + relay_protocol + : String()); // OnIceCandidate always succeeds as it's a callback from the browser. DCHECK(source != kSourceLocal || succeeded);
diff --git a/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc b/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc index 9fd9bd9..678ef69 100644 --- a/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc +++ b/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc
@@ -91,8 +91,8 @@ const wc_fuzzer::ConfigureVideoDecoder& proto) { auto* config = VideoDecoderConfig::Create(); config->setCodec(proto.codec().c_str()); - DOMArrayBuffer* data_copy = DOMArrayBuffer::Create( - proto.description().data(), proto.description().size()); + DOMArrayBuffer* data_copy = + DOMArrayBuffer::Create(base::as_byte_span(proto.description())); config->setDescription( MakeGarbageCollected<AllowSharedBufferSource>(data_copy)); return config; @@ -105,8 +105,8 @@ config->setSampleRate(proto.sample_rate()); config->setNumberOfChannels(proto.number_of_channels()); - DOMArrayBuffer* data_copy = DOMArrayBuffer::Create( - proto.description().data(), proto.description().size()); + DOMArrayBuffer* data_copy = + DOMArrayBuffer::Create(base::as_byte_span(proto.description())); config->setDescription( MakeGarbageCollected<AllowSharedBufferSource>(data_copy)); @@ -358,7 +358,7 @@ ScriptState* script_state, const wc_fuzzer::EncodedVideoChunk& proto) { auto* data = MakeGarbageCollected<AllowSharedBufferSource>( - DOMArrayBuffer::Create(proto.data().data(), proto.data().size())); + DOMArrayBuffer::Create(base::as_byte_span(proto.data()))); auto* init = EncodedVideoChunkInit::Create(); init->setTimestamp(proto.timestamp()); @@ -376,7 +376,7 @@ ScriptState* script_state, const wc_fuzzer::EncodedAudioChunk& proto) { auto* data = MakeGarbageCollected<AllowSharedBufferSource>( - DOMArrayBuffer::Create(proto.data().data(), proto.data().size())); + DOMArrayBuffer::Create(base::as_byte_span(proto.data()))); auto* init = EncodedAudioChunkInit::Create(); init->setTimestamp(proto.timestamp());
diff --git a/third_party/blink/renderer/modules/webcodecs/image_decoder_fuzzer.cc b/third_party/blink/renderer/modules/webcodecs/image_decoder_fuzzer.cc index 140bad1..14f5c49 100644 --- a/third_party/blink/renderer/modules/webcodecs/image_decoder_fuzzer.cc +++ b/third_party/blink/renderer/modules/webcodecs/image_decoder_fuzzer.cc
@@ -109,8 +109,8 @@ Persistent<ImageDecoderInit> image_decoder_init = MakeGarbageCollected<ImageDecoderInit>(); image_decoder_init->setType(proto.config().type().c_str()); - Persistent<DOMArrayBuffer> data_copy = DOMArrayBuffer::Create( - proto.config().data().data(), proto.config().data().size()); + Persistent<DOMArrayBuffer> data_copy = + DOMArrayBuffer::Create(base::as_byte_span(proto.config().data())); image_decoder_init->setData( MakeGarbageCollected<V8ImageBufferSource>(data_copy)); image_decoder_init->setColorSpaceConversion(ToColorSpaceConversion(
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_external_texture.cc b/third_party/blink/renderer/modules/webgpu/gpu_external_texture.cc index e06bc88..a6c4f51 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_external_texture.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_external_texture.cc
@@ -171,8 +171,13 @@ // Keep mailbox texture alive until callback returns. auto* callback = BindWGPUOnceCallback( +#if defined(WGPU_BREAKING_CHANGE_QUEUE_WORK_DONE_CALLBACK_MESSAGE) + [](scoped_refptr<WebGPUMailboxTexture> mailbox_texture, + wgpu::QueueWorkDoneStatus, wgpu::StringView) {}, +#else // defined(WGPU_BREAKING_CHANGE_QUEUE_WORK_DONE_CALLBACK_MESSAGE) [](scoped_refptr<WebGPUMailboxTexture> mailbox_texture, wgpu::QueueWorkDoneStatus) {}, +#endif // defined(WGPU_BREAKING_CHANGE_QUEUE_WORK_DONE_CALLBACK_MESSAGE) std::move(mailbox_texture)); device()->queue()->GetHandle().OnSubmittedWorkDone(
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_queue.cc b/third_party/blink/renderer/modules/webgpu/gpu_queue.cc index cd9a4cb..1b5b7e6 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_queue.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_queue.cc
@@ -436,6 +436,25 @@ UseCounter::Count(execution_context, WebFeature::kWebGPUQueueSubmit); } +#if defined(WGPU_BREAKING_CHANGE_QUEUE_WORK_DONE_CALLBACK_MESSAGE) +void OnWorkDoneCallback(ScriptPromiseResolver<IDLUndefined>* resolver, + wgpu::QueueWorkDoneStatus status, + wgpu::StringView message) { + switch (status) { + case wgpu::QueueWorkDoneStatus::Success: + resolver->Resolve(); + break; + case wgpu::QueueWorkDoneStatus::Error: + resolver->RejectWithDOMException(DOMExceptionCode::kOperationError, + String::FromUTF8(message)); + break; + case wgpu::QueueWorkDoneStatus::CallbackCancelled: + resolver->RejectWithDOMException(DOMExceptionCode::kOperationError, + String::FromUTF8(message)); + break; + } +} +#else // defined(WGPU_BREAKING_CHANGE_QUEUE_WORK_DONE_CALLBACK_MESSAGE) void OnWorkDoneCallback(ScriptPromiseResolver<IDLUndefined>* resolver, wgpu::QueueWorkDoneStatus status) { switch (status) { @@ -454,6 +473,7 @@ break; } } +#endif // defined(WGPU_BREAKING_CHANGE_QUEUE_WORK_DONE_CALLBACK_MESSAGE) ScriptPromise<IDLUndefined> GPUQueue::onSubmittedWorkDone( ScriptState* script_state) {
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 27d8e0d..b973895a 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -352,6 +352,8 @@ "Linux": "experimental", "default": "", }, + base_feature_status: "enabled", + copied_from_base_feature_if: "overridden", }, { // Gates access to the responseConstraint enhancement for "AIPromptAPI".
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/DEPS b/third_party/blink/renderer/platform/scheduler/main_thread/DEPS index 8f8292bd..5bf2455 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/DEPS +++ b/third_party/blink/renderer/platform/scheduler/main_thread/DEPS
@@ -16,11 +16,11 @@ "+base/task/sequence_manager/enqueue_order.h" ], "main_thread_scheduler_impl.cc": [ - "+base/android/pre_freeze_background_memory_trimmer.h", + "+base/android/self_compaction_manager.h", "+components/performance_manager/scenario_api/performance_scenarios.h" ], "memory_purge_manager.cc": [ - "+base/android/pre_freeze_background_memory_trimmer.h" + "+base/android/self_compaction_manager.h" ], "frame_scheduler_impl.h": [ "+net/base/request_priority.h"
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc index d60b592..c7c326c 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
@@ -68,7 +68,7 @@ #include "v8/include/v8.h" #if BUILDFLAG(IS_ANDROID) -#include "base/android/pre_freeze_background_memory_trimmer.h" +#include "base/android/self_compaction_manager.h" #endif namespace base { @@ -2269,8 +2269,8 @@ void MainThreadSchedulerImpl::OnPageFrozen( base::MemoryReductionTaskContext called_from) { #if BUILDFLAG(IS_ANDROID) - base::android::PreFreezeBackgroundMemoryTrimmer:: - SetOnStartSelfCompactionCallback(base::BindRepeating( + base::android::SelfCompactionManager::SetOnStartSelfCompactionCallback( + base::BindRepeating( [](scoped_refptr<base::SequencedTaskRunner> task_runner, base::WeakPtr<MainThreadSchedulerImpl> s) { task_runner->PostTask(
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.cc b/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.cc index 010beb4..65b8108 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.cc
@@ -7,7 +7,7 @@ #include "build/build_config.h" #if BUILDFLAG(IS_ANDROID) -#include "base/android/pre_freeze_background_memory_trimmer.h" +#include "base/android/self_compaction_manager.h" #endif #include "base/feature_list.h" #include "base/memory/memory_pressure_listener.h" @@ -112,9 +112,9 @@ #if BUILDFLAG(IS_ANDROID) // Cancel a pending compaction, since we are resuming now, and will // presumably touch most of that memory soon. - base::android::PreFreezeBackgroundMemoryTrimmer::MaybeCancelCompaction( - base::android::PreFreezeBackgroundMemoryTrimmer:: - CompactCancellationReason::kPageResumed); + base::android::SelfCompactionManager::MaybeCancelCompaction( + base::android::SelfCompactionManager::CompactCancellationReason:: + kPageResumed); #endif } @@ -172,7 +172,7 @@ if (AreAllPagesFrozen()) { base::MemoryPressureListener::SetNotificationsSuppressed(true); #if BUILDFLAG(IS_ANDROID) - base::android::PreFreezeBackgroundMemoryTrimmer::OnRunningCompact(); + base::android::SelfCompactionManager::OnRunningCompact(); #endif }
diff --git a/third_party/blink/renderer/platform/wtf/text/wtf_string.h b/third_party/blink/renderer/platform/wtf/text/wtf_string.h index 6191f99..c077898 100644 --- a/third_party/blink/renderer/platform/wtf/text/wtf_string.h +++ b/third_party/blink/renderer/platform/wtf/text/wtf_string.h
@@ -180,10 +180,6 @@ return impl_->Bytes(); } - // Return characters8() or characters16() depending on CharacterType. - template <typename CharacterType> - inline const CharacterType* GetCharacters() const; - bool Is8Bit() const { return impl_->Is8Bit(); } [[nodiscard]] std::string Ascii() const;
diff --git a/third_party/blink/tools/blinkpy/common/config/builders.json b/third_party/blink/tools/blinkpy/common/config/builders.json index f689298..844aaae 100644 --- a/third_party/blink/tools/blinkpy/common/config/builders.json +++ b/third_party/blink/tools/blinkpy/common/config/builders.json
@@ -81,30 +81,6 @@ }, "is_try_builder": true }, - "mac11.0-blink-rel": { - "main": "tryserver.blink", - "port_name": "mac-mac11", - "specifiers": ["Mac11", "Release"], - "steps": { - "blink_web_tests": {}, - "blink_wpt_tests": {}, - "chrome_wpt_tests": {}, - "headless_shell_wpt_tests": {} - }, - "is_try_builder": true - }, - "mac11.0.arm64-blink-rel": { - "main": "tryserver.blink", - "port_name": "mac-mac11-arm64", - "specifiers": ["Mac11-arm64", "Release"], - "steps": { - "blink_web_tests": {}, - "blink_wpt_tests": {}, - "chrome_wpt_tests": {}, - "headless_shell_wpt_tests": {} - }, - "is_try_builder": true - }, "mac12.0-blink-rel": { "main": "tryserver.blink", "port_name": "mac-mac12",
diff --git a/third_party/blink/tools/blinkpy/wpt_tests/logging.py b/third_party/blink/tools/blinkpy/wpt_tests/logging.py index 5d44c63a..80b0c8d 100644 --- a/third_party/blink/tools/blinkpy/wpt_tests/logging.py +++ b/third_party/blink/tools/blinkpy/wpt_tests/logging.py
@@ -12,11 +12,14 @@ from datetime import datetime import logging +from typing import Optional from blinkpy.common import path_finder +from blinkpy.wpt_tests.test_loader import wpt_url_to_blink_test path_finder.bootstrap_wpt_imports() import mozlog +from mozlog.formatters.base import BaseFormatter class GroupingFormatter(mozlog.formatters.GroupingFormatter): @@ -33,15 +36,13 @@ self._start = datetime.now() def get_test_name_output(self, subsuite, test_name): - if not test_name.startswith('/wpt_internal/'): - test_name = '/external/wpt' + test_name - return f'virtual/{subsuite}{test_name}' if subsuite else test_name[1:] + test_name = wpt_url_to_blink_test(test_name) + return f'virtual/{subsuite}/{test_name}' if subsuite else test_name def log(self, data): - timestamp = datetime.now().isoformat(sep=' ', timespec='milliseconds') # Place mandatory fields first so that logs are vertically aligned as # much as possible. - message = f'{timestamp} {data["level"]} {data["message"]}' + message = f'{format_timestamp()} {data["level"]} {data["message"]}' if 'stack' in data: message = f'{message}\n{data["stack"]}' return self.generate_output(text=message + '\n') @@ -74,6 +75,20 @@ super().__init__(*args, **kwargs) self.reset_before_suite = reset_before_suite + def __call__(self, data): + self.summary(data) + + # pylint: disable=bad-super-call; intentional call to grandparent class + output = super(BaseFormatter, self).__call__(data) + if output is None: + return + + timestamp = self.color_formatter.time(format_timestamp()) + thread = data.get('thread', '') + if thread: + thread += ' ' + return f'{timestamp} {thread}{output}\n' + def suite_start(self, data) -> str: output = super().suite_start(data) if self.reset_before_suite: @@ -87,6 +102,33 @@ self.summary.current['harness_errors'].clear() return output + def process_output(self, data) -> Optional[str]: + if not self.verbose: + return None + return super().process_output(data) + + def test_start(self, data) -> Optional[str]: + # Log the test ID as part of `test_end` so that results from different + # tests aren't interleaved confusingly. + return None + + def test_end(self, data) -> Optional[str]: + test_id = self._get_test_id(data) + # We need this string replacement hack because the base formatter + # doesn't have an overridable hook for this. + # TODO(web-platform-tests/wpt#48948): Fork `MachFormatter` and write the + # desired format. + return super().test_end(data).replace('TEST_END', test_id, 1) + + def _get_test_id(self, data) -> str: + test_name = wpt_url_to_blink_test(data['test']) + subsuite = data.get('subsuite') + return f'virtual/{subsuite}/{test_name}' if subsuite else test_name + + +def format_timestamp() -> str: + return datetime.now().isoformat(sep=' ', timespec='milliseconds') + class StructuredLogAdapter(logging.Handler):
diff --git a/third_party/blink/tools/blinkpy/wpt_tests/wpt_adapter.py b/third_party/blink/tools/blinkpy/wpt_tests/wpt_adapter.py index 1158c43..e69ceba8 100644 --- a/third_party/blink/tools/blinkpy/wpt_tests/wpt_adapter.py +++ b/third_party/blink/tools/blinkpy/wpt_tests/wpt_adapter.py
@@ -203,19 +203,16 @@ if verbose_level >= 1: runner_options.log_mach = '-' runner_options.log_mach_level = 'info' - runner_options.log_mach_verbose = True if verbose_level >= 2: - runner_options.log_mach_level = 'debug' + # Log individual subtest results and `chromedriver` process output. + runner_options.log_mach_verbose = True if verbose_level >= 3: + # Trace test runner and testdriver events. + runner_options.log_mach_level = 'debug' + # Trace individual CDP requests and events. runner_options.webdriver_args.append('--verbose') else: - # Disable all `chromedriver` logs except from `chrome_launcher.cc`, - # which logs the `chrome` command that `WPTResultsProcessor` will - # extract. - runner_options.webdriver_args.extend([ - '--log-level=INFO', - '--vmodule=chrome_launcher=0,*/chrome/test/chromedriver/*=-1', - ]) + runner_options.webdriver_args.append('--log-level=WARNING') if self.options.use_upstream_wpt: runner_options.log_wptreport = [
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 9f60bf1..500a915 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -1444,11 +1444,6 @@ # Failing on Intel Mac11 crbug.com/379233396 [ Mac11 ] external/wpt/ai/translator/* [ Failure ] -# Failing (PRECONDITION_FAILED) without blink::features::kAIPromptAPIMultimodalInput flag -crbug.com/419853199 wpt_internal/ai/language-model-api-availability-available-multimodal.https.window.html [ Failure Pass ] -crbug.com/419853199 wpt_internal/ai/language-model-api-create-multimodal.https.window.html [ Failure Pass ] -crbug.com/419853199 wpt_internal/ai/language-model-api-prompt-multimodal.https.window.html [ Failure Pass ] - ### sheriff 2018-05-28 crbug.com/767269 [ Win ] inspector-protocol/layout-fonts/cjk-ideograph-fallback-by-lang.js [ Failure Pass ] @@ -2770,6 +2765,8 @@ crbug.com/413411328 external/wpt/css/css-values/urls/referrer-policy/unsafe-url/url-image-referrerpolicy-same-origin.sub.html [ Failure ] # ====== New tests from wpt-importer added here ====== +[ Mac14 ] external/wpt/html/cross-origin-opener-policy/historical/popup-same-site-with-same-site.https.html [ Crash ] +[ Mac12 ] external/wpt/html/cross-origin-opener-policy/historical/popup-same-site-with-same-site.https.html [ Crash ] crbug.com/420198856 [ Win10.20h2 ] virtual/close-watcher/external/wpt/close-watcher/iframes/dialog-same-origin-ynn.html [ Skip Timeout ] crbug.com/419216929 [ Win10.20h2 ] virtual/close-watcher/external/wpt/close-watcher/iframes/dialog-same-origin-ynyn.html [ Skip Timeout ] crbug.com/419216929 [ Mac12 ] virtual/close-watcher/external/wpt/close-watcher/iframes/dialog-same-origin-ynyn.html [ Skip Timeout ] @@ -9389,7 +9386,7 @@ crbug.com/418362694 [ Linux ] external/wpt/geolocation/enabled-by-permission-policy-attribute-redirect-on-load.https.sub.html [ Crash Timeout ] # Susceptible to subtle timing flakes -crbug.com/415870039 external/wpt/web-animations/interfaces/Animation/finished.html [ Pass Failure ] +crbug.com/415870039 external/wpt/web-animations/interfaces/Animation/finished.html [ Failure Pass ] # Skipped due to feature implementation in progress crbug.com/420393952 external/wpt/html/semantics/permission-element/quirks-mode-no-height-is-still-bounded.tentative.html [ Failure Skip ]
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 a7b31bf..caea408 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
@@ -6964,13 +6964,6 @@ {} ] ], - "indent-outdent-after-closing-editable-dialog-element.html": [ - "7f73de048d714c99ce47ae4da61d7128e53216e8", - [ - null, - {} - ] - ], "insert-image-with-joining-header-element-and-body.html": [ "cf5b2df225be06c833fea6d3bf2ceab6b1231018", [ @@ -86374,7 +86367,7 @@ ] ], "corner-shape-render-fuzzy.html": [ - "12cd2546bf484282a8cab7163c610b5b88d0b9f8", + "2d4b56f831b91eb70fd44abc02000213664a480b", [ "css/css-borders/tentative/corner-shape/corner-shape-render-fuzzy.html?border-radius=30%&corner-shape=superellipse(-1.5)&box-shadow=10px%2010px%200%2010px%20black", [ @@ -86636,10 +86629,10 @@ } ], [ - "css/css-borders/tentative/corner-shape/corner-shape-render-fuzzy.html?corner-shape=superellipse(0.8)&border-radius=40px&border-width=10px&border-left-color=purple", + "css/css-borders/tentative/corner-shape/corner-shape-render-fuzzy.html?corner-shape=superellipse(0.8)&border-radius=40px&border-width=10px", [ [ - "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-shape=superellipse(0.8)&border-radius=40px&border-width=10px&border-left-color=purple", + "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-shape=superellipse(0.8)&border-radius=40px&border-width=10px", "==" ] ], @@ -86871,7 +86864,7 @@ ] ], "corner-shape-render-precise.html": [ - "5293589222a3f2d918bdbfeecd11280f667578c2", + "4a0c575b3b7cef4cbfb1dea4efc53ec40e01ef13", [ "css/css-borders/tentative/corner-shape/corner-shape-render-precise.html?border-radius=50%&corner-shape=bevel&box-shadow=10px%2010px%200%2010px%20black", [ @@ -87055,6 +87048,32 @@ } ], [ + "css/css-borders/tentative/corner-shape/corner-shape-render-precise.html?corner-shape=notch&border-radius=30px&border-width=30px", + [ + [ + "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-shape=notch&border-radius=30px&border-width=30px", + "==" + ] + ], + { + "fuzzy": [ + [ + null, + [ + [ + 0, + 180 + ], + [ + 0, + 350 + ] + ] + ] + ] + } + ], + [ "css/css-borders/tentative/corner-shape/corner-shape-render-precise.html?corner-shape=square&border-bottom-left-radius=5px", [ [ @@ -87263,10 +87282,10 @@ } ], [ - "css/css-borders/tentative/corner-shape/corner-shape-render-precise.html?corner-top-left-shape=bevel&border-width=10px&border-color=black", + "css/css-borders/tentative/corner-shape/corner-shape-render-precise.html?corner-top-left-shape=bevel&border-width=10px", [ [ - "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-top-left-shape=bevel&border-width=10px&border-color=black", + "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-top-left-shape=bevel&border-width=10px", "==" ] ], @@ -87393,10 +87412,10 @@ } ], [ - "css/css-borders/tentative/corner-shape/corner-shape-render-precise.html?corner-top-right-shape=bevel&border-width=10px&border-color=black", + "css/css-borders/tentative/corner-shape/corner-shape-render-precise.html?corner-top-right-shape=bevel&border-width=10px", [ [ - "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-top-right-shape=bevel&border-width=10px&border-color=black", + "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-top-right-shape=bevel&border-width=10px", "==" ] ], @@ -159351,6 +159370,37 @@ ] }, "css-masking": { + "animations": { + "clip-path-interpolation-shape-arc-direction-agnostic-radius.html": [ + "aa91e1828a7841c4036f6c2d15639ebd2f1bf4e4", + [ + null, + [ + [ + "/css/css-masking/animations/clip-path-interpolation-shape-arc-direction-agnostic-radius-ref.html", + "==" + ] + ], + { + "fuzzy": [ + [ + null, + [ + [ + 0, + 10 + ], + [ + 0, + 360 + ] + ] + ] + ] + } + ] + ] + }, "clip": { "clip-absolute-positioned-001.html": [ "c5b0d9001c442012aea33142d47ca1a8d68e319e", @@ -227031,6 +227081,19 @@ {} ] ], + "individual-transform-3.html": [ + "2c81cb12156134ee8deca6abf0043848ac8bc750", + [ + null, + [ + [ + "/css/reference/ref-filled-green-200px-square.html", + "==" + ] + ], + {} + ] + ], "stacking-context-001.html": [ "1a754c5d70b607396ffe2db1d04f2294aeca1041", [ @@ -232085,6 +232148,19 @@ {} ] ], + "transform-matrix-009.html": [ + "81f04db0d103202180aba2625205643c376483af", + [ + null, + [ + [ + "/css/reference/ref-filled-green-200px-square.html", + "==" + ] + ], + {} + ] + ], "transform-origin": { "svg-origin-length-001.html": [ "2f2256361cadd4f69aa08fd775a4305219a41fdd", @@ -255296,6 +255372,35 @@ } ] ], + "inline-child-with-composited-filter.html": [ + "36ba9803e1edb2c87d8d3e57b5f2589d349df964", + [ + null, + [ + [ + "/css/css-view-transitions/inline-child-with-filter-ref.html", + "==" + ] + ], + { + "fuzzy": [ + [ + null, + [ + [ + 0, + 2 + ], + [ + 0, + 2400 + ] + ] + ] + ] + } + ] + ], "inline-child-with-filter.html": [ "61f0f1f6a8c389cd7298c56d8c2e35c3f101027b", [ @@ -303826,6 +303931,34 @@ {} ] ], + "permission-icon": { + "icon-hidden-reftest.html": [ + "79055da1badfc827e5cc02ed3be7db3842b49855", + [ + null, + [ + [ + "/html/semantics/permission-element/permission-icon/standard-location-permission-element-ref.html", + "!=" + ] + ], + {} + ] + ], + "icon-unique-per-type-reftest.html": [ + "d51b1c4d398a42c8e59f047c0e457c533eae16ee", + [ + null, + [ + [ + "/html/semantics/permission-element/permission-icon/standard-location-permission-element-ref.html", + "!=" + ] + ], + {} + ] + ] + }, "pseudo-elements-in-div.tentative.html": [ "24a2be07fabae34fd969fa89c233b2a209c0c08f", [ @@ -336136,11 +336269,11 @@ ], "resources": { "corner-shape.js": [ - "4757a43ad051f42a88ddefeba344bcea0b9a0149", + "c08a95c7d7511e84eb92015d13578e23ad2f2ec5", [] ], "corner-utils.js": [ - "ad3b235addff11e418d78e372b20c09a2ebd4a19", + "b6f329e82484f14f853c999dbd99a15771db1e8d", [] ], "resolve-corner-style.js": [ @@ -355815,6 +355948,10 @@ "758ef35275eeacc96b6e584f672f86c4b170e0e1", [] ], + "clip-path-interpolation-shape-arc-direction-agnostic-radius-ref.html": [ + "2869d38a982b23d72ae49543d16d01bda6f28b21", + [] + ], "mask-border-outset-composition-expected.txt": [ "4bba8f7a629ac8b69ed57c62b538575248620c2a", [] @@ -360397,6 +360534,10 @@ ] }, "overlay": { + "WEB_FEATURES.yml": [ + "a1a4402ee421efa24e9b02a2337c90812759a4e2", + [] + ], "green-ref.html": [ "bef7405e96f8181f88fb073ebd212b4af6382e33", [] @@ -374622,6 +374763,10 @@ "bf99b25f76b176520715a245ef3abf01258fdc5a", [] ], + "inline-child-with-composited-filter-ref.html": [ + "9dd26f2c3b1afb49d60bedb5e721dcb1f193d423", + [] + ], "inline-child-with-filter-ref.html": [ "44a41f1bf93366e06f2eae0cbfcd4acb126d192f", [] @@ -381279,7 +381424,7 @@ [] ], "idlharness.window-expected.txt": [ - "b5b3128599152fc8361e9e39df200376c012e7c8", + "73b50e7884b31d31be24e60058480c17750b9fbe", [] ], "initial-about-blank.window-expected.txt": [ @@ -406445,6 +406590,12 @@ "8b48bb93febed1c7fd88f62fe747b3379b349e22", [] ], + "permission-icon": { + "standard-location-permission-element-ref.html": [ + "15ffe751c51b3f8caeaa8b93f1286a3950c9a815", + [] + ] + }, "pseudo-elements-in-div-ref.html": [ "8e6267f9aa350333cef620d248dfce40b85b43e2", [] @@ -411620,7 +411771,7 @@ [] ], "OWNERS": [ - "dee5bb0f00575c0ca7226355c1adbc5131914db4", + "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", [] ], "iframeChild.html": [ @@ -412715,6 +412866,10 @@ "6f93db15a74e052913a277e5130226280a3f9311", [] ], + "scoped-custom-elements-registry.idl": [ + "46ca2d6b9c45805d8aa684af7fe91af6dd5d7919", + [] + ], "screen-capture.idl": [ "db9282ce0a57bb3b84ea45f5ed2d7e69bc3a8a32", [] @@ -413455,6 +413610,10 @@ "9d5ea8bae27a7ed694cb383965a5ffd14dd22d9a", [] ], + "WEB_FEATURES.yml": [ + "335b072c1868c1817dbe7ed6c1901907aa8decbc", + [] + ], "idlharness-expected.txt": [ "c514368f772065595dae7a81b1c55d5c65a73f2b", [] @@ -426678,13 +426837,17 @@ [] ], "executor.sub.html": [ - "bb2d58dc9c9cfac6d98380b0b587bc242fbd5e11", + "b89c45e4f5c25b274925afd6569d6384d5183fe4", [] ], "executor.sub.html.headers": [ "4030ea1d3ddb186a2b5361eb1a3f2404a45531fc", [] ], + "post-navigation-handler.py": [ + "1749517710ed19eda399f01321e1ffcedfc9b09b", + [] + ], "prefetch.py": [ "14ac4d1699ea0c52ac4b40f0a4a0f71c99147073", [] @@ -426905,6 +427068,10 @@ "10a48df58cf9dd9f13eca87e69c54098af1b64b0", [] ], + "image-with-headers-stash.py": [ + "dcb8838d4a167d91ded325e7d3fc6b50055c7746", + [] + ], "indexedb-utils.js": [ "7c57000d5cf48a3bbf74c0b0d8f812922f0575ef", [] @@ -430964,6 +431131,10 @@ "b92b53ee45cd98933a3c2fbcf404478eb8f66a06", [] ], + "urlpattern-generate-test-data.json": [ + "c118f0a73b5fe108ab1a1f39d41148648daa7baa", + [] + ], "urlpattern-hasregexpgroups-tests.js": [ "4be886e4a5390d7d43356d853cc00c7bbb23d361", [] @@ -436008,7 +436179,7 @@ [] ], "RTCConfiguration-iceServers-expected.txt": [ - "92a76728663c4702649309d3919bfe16197efdaa", + "be4b1ea79a5e5ead781dfd7ccbed266251ff67e1", [] ], "RTCDTMFSender-helper.js": [ @@ -491185,7 +491356,7 @@ ] ], "encoding.https.any.js": [ - "941639bdaec01d0eb619a5850b1d878bdf77f695", + "f5d2ca15e717a0837f1e08031ab682db5aa965ea", [ "cookie-store/encoding.https.any.html", { @@ -491226,7 +491397,7 @@ ] ], "httponly_cookies.https.window.js": [ - "605e94e67440aaedbcaa39f185270fe77b316ad3", + "836f47da3f6e0f8f2c89445d1b2fbdfdf9ddc9e6", [ "cookie-store/httponly_cookies.https.window.html", { @@ -511977,7 +512148,7 @@ ] ], "clip-path-interpolation-shape.html": [ - "f35552386f3a1d0f2a420f2951c4ae0f81b4cce0", + "f725e1fc6fa0cbde5928c1e45e5e7c5f72b1a7dd", [ null, {} @@ -530631,7 +530802,7 @@ ] ], "if-conditionals.html": [ - "caead7864d550f8732eff919c1b555c8f759508d", + "f6d981798ae7a03f97b4fd089ee02141c7f90813", [ null, {} @@ -531380,6 +531551,13 @@ {} ] ], + "var-ident-function.html": [ + "3453cd5b64942b9d7bccdde418baa50e8018205a", + [ + null, + {} + ] + ], "var-parsing.html": [ "0c69342f2ee11bdfdbe991be375a70732956bee7", [ @@ -548987,13 +549165,6 @@ } ] ], - "move-inserted-node-from-DOMNodeInserted-during-exec-command-insertHTML.html": [ - "41e012a62e9617f372f85d0a0cedefe8ad42fbd6", - [ - null, - {} - ] - ], "no-beforeinput-when-no-selection.html": [ "098a95863a606393502d4e2fc517fcb8ad144d35", [ @@ -653863,34 +654034,6 @@ {} ] ], - "042.html": [ - "df3a2f88f29f2e8035d8c778c3397ad464688e18", - [ - null, - {} - ] - ], - "043.html": [ - "bcfd90cba47880efa48f9e809f37209f5f024dd6", - [ - null, - {} - ] - ], - "044.html": [ - "8d412079e45f9f8a3d074d707db39a55e1d8b946", - [ - null, - {} - ] - ], - "045.html": [ - "254e0d13662786d8542d03de3547b39ecf684ede", - [ - null, - {} - ] - ], "046.html": [ "4f145d63e1d619df2df429ec6fd713e77e303cb3", [ @@ -653949,20 +654092,6 @@ {} ] ], - "054.html": [ - "29ede23414ec57950717a05e375cbc15547c0b4d", - [ - null, - {} - ] - ], - "055.html": [ - "c837d78174b108d8b90cca4dccbc91bef8e1efad", - [ - null, - {} - ] - ], "056.html": [ "e2d0868034e1b243e610b3e3afdea18d78c418c8", [ @@ -701506,7 +701635,7 @@ ] ], "content-encoding.https.html": [ - "0d67bfc7d4f9a9c471272a8a475655d1c5225552", + "80473552f08b0c5f857533bdebf7a168283d5953", [ null, {} @@ -704820,7 +704949,7 @@ ] ], "animation-trigger-repeat.tentative.html": [ - "cfbe9d3c9334148789d4cebc7a01a2f9e848b22d", + "6c01e762e5acd18a1def36673c93d7fcdedf4964", [ null, {} @@ -714647,6 +714776,15 @@ {} ] ], + "no-prefetch-for-post.https.html": [ + "7739f4f8c7105b2c4e9ed4671081b00d0c0b8c6e", + [ + null, + { + "timeout": "long" + } + ] + ], "no-vary-search": { "prefetch-single-with-hint.https.html": [ "f2d8b3090e1f8447f86bd62a6f24ca9daae06ec7", @@ -715639,6 +715777,15 @@ } ] ], + "headers.https.html": [ + "2ef6b5ce072866d3c88ce7a86fcea6436de3364a", + [ + null, + { + "timeout": "long" + } + ] + ], "iframe-added-post-activation.https.html": [ "d22b511e108d8b7c7f0b63f28e5bf485eca98758", [ @@ -736856,13 +737003,6 @@ }, "legacy-domevents-tests": { "approved": { - "ProcessingInstruction.DOMCharacterDataModified.html": [ - "2da0a389e2e3bc51861fef752b11a629203897d0", - [ - null, - {} - ] - ], "dispatchEvent.click.checkbox.html": [ "8cb548f84c60eb6b528c1049884649b26c4f18ba", [ @@ -736870,13 +737010,6 @@ {} ] ], - "domnodeinserted.html": [ - "e5064d8d46cd9aad4768aa81dacb18b989e2c993", - [ - null, - {} - ] - ], "stopImmediatePropagation.effect.html": [ "a414d60298acece6dce5d970e6f0448a99fd65da", [ @@ -740184,6 +740317,53 @@ } ] ], + "urlpattern-generate.tentative.any.js": [ + "1f6962942d88f88684c5302175202e0278d3d971", + [ + "urlpattern/urlpattern-generate.tentative.any.html", + { + "script_metadata": [ + [ + "global", + "window,worker" + ] + ] + } + ], + [ + "urlpattern/urlpattern-generate.tentative.any.serviceworker.html", + { + "script_metadata": [ + [ + "global", + "window,worker" + ] + ] + } + ], + [ + "urlpattern/urlpattern-generate.tentative.any.sharedworker.html", + { + "script_metadata": [ + [ + "global", + "window,worker" + ] + ] + } + ], + [ + "urlpattern/urlpattern-generate.tentative.any.worker.html", + { + "script_metadata": [ + [ + "global", + "window,worker" + ] + ] + } + ] + ], "urlpattern-hasregexpgroups.any.js": [ "33133d2511b065ca94cc5e793066cc8111b4d6e6", [ @@ -796864,7 +797044,7 @@ ] ], "RTCConfiguration-iceServers.html": [ - "bc7831361ab5f417b46a507b0e5977bef9bedd49", + "65a6015f52a7233260ab8405fb43bc347fa0ff4b", [ null, {}
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/overlay/WEB_FEATURES.yml b/third_party/blink/web_tests/external/wpt/css/css-position/overlay/WEB_FEATURES.yml new file mode 100644 index 0000000..a1a4402 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-position/overlay/WEB_FEATURES.yml
@@ -0,0 +1,3 @@ +features: +- name: overlay + files: "**"
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/individual-transform/individual-transform-3.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/individual-transform/individual-transform-3.html new file mode 100644 index 0000000..2c81cb12 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/individual-transform/individual-transform-3.html
@@ -0,0 +1,40 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Individual transform: non-invertible matrix</title> +<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-transforms-2/#individual-transforms"> +<link rel="help" href="https://drafts.csswg.org/css-transforms-2/#ctm"> +<link rel="help" href="https://drafts.csswg.org/css-transforms-1/#transform-function-lists"> +<link rel="help" href="https://github.com/servo/servo/issues/37146"> +<link rel="match" href="../../reference/ref-filled-green-200px-square.html"> +<meta name="assert" content="Tests that the element isn't rendered when + the current transformation matrix is non-invertible because of `scale`."> + +<style> +.wrapper { + width: 200px; + height: 200px; + background: green; +} +.wrapper > div { + width: 200px; + height: 20px; + background: red; +} +</style> + +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> + +<div class="wrapper"> + <div style="scale: 0"></div> + <div style="scale: 0 0"></div> + <div style="scale: 0 1"></div> + <div style="scale: 1 0"></div> + <div style="scale: 0 0 0"></div> + <div style="scale: 0 0 1"></div> + <div style="scale: 0 1 0"></div> + <div style="scale: 0 1 1"></div> + <div style="scale: 1 0 0"></div> + <div style="scale: 1 0 1"></div> + <div style="scale: 1 1 0"></div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-matrix-009.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-matrix-009.html new file mode 100644 index 0000000..81f04db0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-matrix-009.html
@@ -0,0 +1,41 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Test (Transforms): matrix() with zeros in the diagonal</title> +<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com"> +<link rel="help" href="https://www.w3.org/TR/css-transforms-1/#funcdef-transform-matrix"> +<link rel="help" href="https://www.w3.org/TR/css-transforms-1/#transform-function-lists"> +<link rel="help" href="https://github.com/servo/servo/issues/37146"> +<link rel="match" href="../reference/ref-filled-green-200px-square.html"> +<meta name="assert" content="Tests that the element is still rendered, + even though the current transformation matrix has zeros in the diagonal, + as long as the matrix remains invertible."> + +<style> +.wrapper { + width: 200px; + height: 200px; + background: red; +} +.test { + width: 200px; + height: 200px; + background: green; + transform: matrix(0,1, 1,0, 0,0); + /* + The resulting matrix is: + ┌ ┐ + │ 0 1 0 0 │ + │ 1 0 0 0 │ + │ 0 0 1 0 │ + │ 0 0 0 1 │ + └ ┘ + It could result from e.g. `scaleX(-1) rotate(90deg)`. + */ +} +</style> + +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> + +<div class="wrapper"> + <div class="test"></div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/inline-child-with-composited-filter-ref.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/inline-child-with-composited-filter-ref.html new file mode 100644 index 0000000..9dd26f2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/inline-child-with-composited-filter-ref.html
@@ -0,0 +1,31 @@ +<!DOCTYPE html> +<title>View transitions: inline child with filter (ref)</title> +<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/"> +<link rel="author" href="mailto:vmpstr@chromium.org"> +<link rel="author" href="mailto:mattwoodrow@apple.com"> + +<style> +body { margin : 0; } +#target { + width: 100px; + height: 100px; + background-color: grey; + overflow-clip-margin: 40px; + contain: paint; + view-transition-name: target; +} + +#child { + position: relative; + left: 100px; + top: 100px; + color: lightgreen; + background-color: darkgreen; + filter: blur(30px); + transform: translateZ(0px); +} +</style> + +<div id="target"> + <span id="child">INLINEBOX</span> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/inline-child-with-composited-filter.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/inline-child-with-composited-filter.html new file mode 100644 index 0000000..36ba980 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/inline-child-with-composited-filter.html
@@ -0,0 +1,57 @@ +<!DOCTYPE html> +<html class=reftest-wait> +<title>View transitions: inline child with filter</title> +<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/"> +<link rel="author" href="mailto:vmpstr@chromium.org"> +<link rel="author" href="mailto:mattwoodrow@apple.com"> +<link rel="match" href="inline-child-with-filter-ref.html"> +<meta name=fuzzy content="maxDifference=0-2;totalPixels=0-2400"> +<script src="/common/reftest-wait.js"></script> + +<style> +body { margin : 0; } +#target { + width: 100px; + height: 100px; + background-color: grey; + overflow-clip-margin: 40px; + contain: paint; + view-transition-name: target; +} + +#child { + position: relative; + left: 100px; + top: 100px; + color: lightgreen; + background-color: darkgreen; + filter: blur(30px); + transform: translateZ(0px); +} + +html::view-transition-group(root) { animation-duration: 300s; } +html::view-transition-old(target) { + animation: unset; + opacity: 1; +} +html::view-transition-new(target) { + animation: unset; + opacity: 0; +} +</style> + +<div id="target"> + <span id="child">INLINEBOX</span> +</div> + +<script> +failIfNot(document.startViewTransition, "Missing document.startViewTransition"); + +async function runTest() { + let transition = document.startViewTransition(async () => { + document.getElementById("target").remove(); + }); + transition.ready.then(() => requestAnimationFrame(takeScreenshot)); +} +onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest)); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/custom-elements/registries/idlharness.window-expected.txt b/third_party/blink/web_tests/external/wpt/custom-elements/registries/idlharness.window-expected.txt index b5b3128..73b50e78 100644 --- a/third_party/blink/web_tests/external/wpt/custom-elements/registries/idlharness.window-expected.txt +++ b/third_party/blink/web_tests/external/wpt/custom-elements/registries/idlharness.window-expected.txt
@@ -1,5 +1,19 @@ This is a testharness.js-based test. -[FAIL] idl_test setup - promise_test: Unhandled rejection with value: object "Error fetching /interfaces/scoped-custom-elements-registry.idl." +[FAIL] idl_test validation + Validation error at line 4 in scoped-custom-elements-registry, inside `partial interface CustomElementRegistry`:\n undefined initialize(Node root)\n ^ The operation "initialize" has already been defined for the base interface "CustomElementRegistry" either in itself or in a mixin\n\nValidation error at line 320 in dom, inside `dictionary ImportNodeOptions`:\ndictionary ImportNodeOptions {\n ^ The name "ImportNodeOptions" of type "dictionary" was already seen +[FAIL] Partial interface CustomElementRegistry: member names are unique + assert_true: member undefined is unique expected true got false +[FAIL] Partial interface HTMLTemplateElement: member names are unique + assert_true: member shadowRootCustomElementRegistry is unique expected true got false +[FAIL] Partial interface Element: member names are unique + assert_true: member customElementRegistry is unique expected true got false +[FAIL] Partial dictionary ShadowRootInit: member names are unique + assert_true: member customElementRegistry is unique expected true got false +[FAIL] Partial dictionary ElementCreationOptions: member names are unique + assert_true: member customElementRegistry is unique expected true got false +[FAIL] Document includes DocumentOrShadowRoot: member names are unique + assert_true: member customElementRegistry is unique expected true got false +[FAIL] ShadowRoot includes DocumentOrShadowRoot: member names are unique + assert_true: member customElementRegistry is unique expected true got false Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/actions/OWNERS b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/actions/OWNERS index dee5bb0f..e69de29 100644 --- a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/actions/OWNERS +++ b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/actions/OWNERS
@@ -1 +0,0 @@ -lanwei@chromium.org
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/scoped-custom-elements-registry.idl b/third_party/blink/web_tests/external/wpt/interfaces/scoped-custom-elements-registry.idl new file mode 100644 index 0000000..46ca2d6b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/interfaces/scoped-custom-elements-registry.idl
@@ -0,0 +1,38 @@ +[Exposed=Window] +partial interface CustomElementRegistry { + constructor(); + undefined initialize(Node root); +}; + +[Exposed=Window] +partial interface HTMLTemplateElement { + [CEReactions] attribute DOMString shadowRootCustomElementRegistry; +}; + +[Exposed=Window] +partial interface Document { + readonly attribute CustomElementRegistry? customElementRegistry; +}; + +[Exposed=Window] +partial interface Element { + readonly attribute CustomElementRegistry? customElementRegistry; +}; + +[Exposed=Window] +partial interface ShadowRoot { + readonly attribute CustomElementRegistry? customElementRegistry; +}; + +dictionary ImportNodeOptions { + CustomElementRegistry customElementRegistry; + boolean selfOnly = false; +}; + +partial dictionary ShadowRootInit { + CustomElementRegistry customElementRegistry; +}; + +partial dictionary ElementCreationOptions { + CustomElementRegistry customElementRegistry; +};
diff --git a/third_party/blink/web_tests/external/wpt/layout-instability/WEB_FEATURES.yml b/third_party/blink/web_tests/external/wpt/layout-instability/WEB_FEATURES.yml new file mode 100644 index 0000000..335b072 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/layout-instability/WEB_FEATURES.yml
@@ -0,0 +1,3 @@ +features: +- name: layout-instability + files: "**"
diff --git a/third_party/blink/web_tests/platform/mac-mac11/external/wpt/custom-elements/registries/idlharness.window-expected.txt b/third_party/blink/web_tests/platform/mac-mac11/external/wpt/custom-elements/registries/idlharness.window-expected.txt new file mode 100644 index 0000000..b5b3128 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11/external/wpt/custom-elements/registries/idlharness.window-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +[FAIL] idl_test setup + promise_test: Unhandled rejection with value: object "Error fetching /interfaces/scoped-custom-elements-registry.idl." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac11/virtual/scoped-custom-element-registry-disabled/external/wpt/custom-elements/registries/idlharness.window-expected.txt b/third_party/blink/web_tests/platform/mac-mac11/virtual/scoped-custom-element-registry-disabled/external/wpt/custom-elements/registries/idlharness.window-expected.txt new file mode 100644 index 0000000..b5b3128 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11/virtual/scoped-custom-element-registry-disabled/external/wpt/custom-elements/registries/idlharness.window-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +[FAIL] idl_test setup + promise_test: Unhandled rejection with value: object "Error fetching /interfaces/scoped-custom-elements-registry.idl." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/scoped-custom-element-registry-disabled/external/wpt/custom-elements/registries/idlharness.window-expected.txt b/third_party/blink/web_tests/virtual/scoped-custom-element-registry-disabled/external/wpt/custom-elements/registries/idlharness.window-expected.txt new file mode 100644 index 0000000..bc8bef8a --- /dev/null +++ b/third_party/blink/web_tests/virtual/scoped-custom-element-registry-disabled/external/wpt/custom-elements/registries/idlharness.window-expected.txt
@@ -0,0 +1,31 @@ +This is a testharness.js-based test. +[FAIL] idl_test setup + promise_test: Unhandled rejection with value: object "TypeError: Failed to construct 'CustomElementRegistry': Illegal constructor" +[FAIL] idl_test validation + Validation error at line 4 in scoped-custom-elements-registry, inside `partial interface CustomElementRegistry`:\n undefined initialize(Node root)\n ^ The operation "initialize" has already been defined for the base interface "CustomElementRegistry" either in itself or in a mixin\n\nValidation error at line 320 in dom, inside `dictionary ImportNodeOptions`:\ndictionary ImportNodeOptions {\n ^ The name "ImportNodeOptions" of type "dictionary" was already seen +[FAIL] Partial interface CustomElementRegistry: member names are unique + assert_true: member undefined is unique expected true got false +[FAIL] Partial interface HTMLTemplateElement: member names are unique + assert_true: member shadowRootCustomElementRegistry is unique expected true got false +[FAIL] Partial interface Element: member names are unique + assert_true: member customElementRegistry is unique expected true got false +[FAIL] Partial dictionary ShadowRootInit: member names are unique + assert_true: member customElementRegistry is unique expected true got false +[FAIL] Partial dictionary ElementCreationOptions: member names are unique + assert_true: member customElementRegistry is unique expected true got false +[FAIL] Document includes DocumentOrShadowRoot: member names are unique + assert_true: member customElementRegistry is unique expected true got false +[FAIL] ShadowRoot includes DocumentOrShadowRoot: member names are unique + assert_true: member customElementRegistry is unique expected true got false +[FAIL] HTMLTemplateElement interface: attribute shadowRootCustomElementRegistry + assert_true: The prototype object must have a property "shadowRootCustomElementRegistry" expected true got false +[FAIL] CustomElementRegistry interface: operation initialize(Node) + assert_own_property: interface prototype object missing non-static operation expected property "initialize" missing +[FAIL] Document interface: attribute customElementRegistry + assert_true: The prototype object must have a property "customElementRegistry" expected true got false +[FAIL] ShadowRoot interface: attribute customElementRegistry + assert_true: The prototype object must have a property "customElementRegistry" expected true got false +[FAIL] Element interface: attribute customElementRegistry + assert_true: The prototype object must have a property "customElementRegistry" expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/wpt_internal/ai/language-model-api-create-multimodal.https.window.js b/third_party/blink/web_tests/wpt_internal/ai/language-model-api-create-multimodal.https.window.js index eed3549e..c9b2e98 100644 --- a/third_party/blink/web_tests/wpt_internal/ai/language-model-api-create-multimodal.https.window.js +++ b/third_party/blink/web_tests/wpt_internal/ai/language-model-api-create-multimodal.https.window.js
@@ -49,7 +49,6 @@ { expectedInputs: [{type: 'image'}], initialPrompts: [{role: 'user', content: [audioContent]}] }, ]; for (const options of kUnsupportedCreateOptions) { - // TODO(crbug.com/419599702): Ensure the model actually gets initialPrompts. - await promise_rejects_js(t, TypeError, LanguageModel.create(options), JSON.stringify(options)); + await promise_rejects_dom(t, 'NotSupportedError', LanguageModel.create(options), JSON.stringify(options)); } }, 'LanguageModel.create() fails with unsupported multimodal initialPrompts');
diff --git a/third_party/catapult b/third_party/catapult index 61f9c08..3af14c3 160000 --- a/third_party/catapult +++ b/third_party/catapult
@@ -1 +1 @@ -Subproject commit 61f9c08d6ae028f8440b1ddddb330cfdf028c159 +Subproject commit 3af14c3b4e2496ad1b85e1f33823f006e30fe8e0
diff --git a/third_party/depot_tools b/third_party/depot_tools index 0772b51..0b1d80a 160000 --- a/third_party/depot_tools +++ b/third_party/depot_tools
@@ -1 +1 @@ -Subproject commit 0772b51a975ba1ecf983b52665528d5b1db8a433 +Subproject commit 0b1d80ab9e9f1413234641d193639e5daa92dd5b
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src index a178b7d..c7d5f74c 160000 --- a/third_party/devtools-frontend/src +++ b/third_party/devtools-frontend/src
@@ -1 +1 @@ -Subproject commit a178b7d51c21c468b397db564aa21e34c7cc0aa2 +Subproject commit c7d5f74c859abdd3219524ec9f77ce98d54a9a15
diff --git a/third_party/libc++abi/src b/third_party/libc++abi/src index 9810fb23..241ef36 160000 --- a/third_party/libc++abi/src +++ b/third_party/libc++abi/src
@@ -1 +1 @@ -Subproject commit 9810fb23f6ba666f017c2b67c67de2bcac2b44bd +Subproject commit 241ef367ab2d135197377a82da5f7aee49a082f8
diff --git a/third_party/mutter/README.chromium b/third_party/mutter/README.chromium index fb321c9..024161e 100644 --- a/third_party/mutter/README.chromium +++ b/third_party/mutter/README.chromium
@@ -1,7 +1,7 @@ Name: mutter URL: https://gitlab.gnome.org/GNOME/mutter Version: 48.alpha -Revision: e99ff5359c4134093efe3cb2aa208e4addf565c6 +Revision: 881058e0a3c395b93986d734d2cff164376a1ec7 License: GPL-2.0 License File: LICENSE Shipped: no
diff --git a/third_party/mutter/src b/third_party/mutter/src index e99ff53..881058e 160000 --- a/third_party/mutter/src +++ b/third_party/mutter/src
@@ -1 +1 @@ -Subproject commit e99ff5359c4134093efe3cb2aa208e4addf565c6 +Subproject commit 881058e0a3c395b93986d734d2cff164376a1ec7
diff --git a/third_party/node/README.chromium b/third_party/node/README.chromium index 98bc57a..c0c9a42 100644 --- a/third_party/node/README.chromium +++ b/third_party/node/README.chromium
@@ -389,6 +389,9 @@ License: MIT Security Critical: no Shipped: no +Mitigated: CVE-2022-37620 +CVE-2022-37620: Local patch was applied to completely remove affected code as +there is no upstream fix. Description: HTMLMinifier is a highly configurable, well-tested, JavaScript-based HTML @@ -398,8 +401,16 @@ of shipped HTML files though. Local Modifications: -Removed uglify-js dependency since we don't plan to use the --minify-js flag in -Chromium. + - Removed uglify-js dependency since we don't plan to use the --minify-js flag + in Chromium. + - Applied local patch patches/html_minifier2.patch to address vulnerability, + see https://osv.dev/vulnerability/GHSA-pfq8-rq6v-vf5m and + https://github.com/kangax/html-minifier/issues/1135. The local patch + completely removes the affected code, making it impossible to trigger it from + client code, since there is no later version with the vulnerability fixed + provided by the tool's authors. The tool should eventually be replaced with a + more modern tool as part of crbug.com/40943411. + -------------------- DEPENDENCY DIVIDER --------------------
diff --git a/third_party/node/node_modules.tar.gz.sha1 b/third_party/node/node_modules.tar.gz.sha1 index 6457c93..5ac4e316 100644 --- a/third_party/node/node_modules.tar.gz.sha1 +++ b/third_party/node/node_modules.tar.gz.sha1
@@ -1 +1 @@ -13eea9a3163f9e91f343e6a3197079986d7276b2 +782009f3247d27e3c0a9663eb3a35c78bdca6745
diff --git a/third_party/node/patches/html_minifier2.patch b/third_party/node/patches/html_minifier2.patch new file mode 100644 index 0000000..c5feaf2 --- /dev/null +++ b/third_party/node/patches/html_minifier2.patch
@@ -0,0 +1,63 @@ +diff --git a/node_modules/html-minifier/src/htmlminifier.js b/node_modules/html-minifier/src/htmlminifier.js +index eb19dd6b33ff3..e9dd3141874d4 100644 +--- a/node_modules/html-minifier/src/htmlminifier.js ++++ b/node_modules/html-minifier/src/htmlminifier.js +@@ -868,56 +868,8 @@ function minify(value, options, partialMarkup) { + return token; + }); + +- var customFragments = options.ignoreCustomFragments.map(function(re) { +- return re.source; +- }); +- if (customFragments.length) { +- var reCustomIgnore = new RegExp('\\s*(?:' + customFragments.join('|') + ')+\\s*', 'g'); +- // temporarily replace custom ignored fragments with unique attributes +- value = value.replace(reCustomIgnore, function(match) { +- if (!uidAttr) { +- uidAttr = uniqueId(value); +- uidPattern = new RegExp('(\\s*)' + uidAttr + '([0-9]+)' + uidAttr + '(\\s*)', 'g'); +- if (options.minifyCSS) { +- options.minifyCSS = (function(fn) { +- return function(text, type) { +- text = text.replace(uidPattern, function(match, prefix, index) { +- var chunks = ignoredCustomMarkupChunks[+index]; +- return chunks[1] + uidAttr + index + uidAttr + chunks[2]; +- }); +- var ids = []; +- new CleanCSS().minify(wrapCSS(text, type)).warnings.forEach(function(warning) { +- var match = uidPattern.exec(warning); +- if (match) { +- var id = uidAttr + match[2] + uidAttr; +- text = text.replace(id, ignoreCSS(id)); +- ids.push(id); +- } +- }); +- text = fn(text, type); +- ids.forEach(function(id) { +- text = text.replace(ignoreCSS(id), id); +- }); +- return text; +- }; +- })(options.minifyCSS); +- } +- if (options.minifyJS) { +- options.minifyJS = (function(fn) { +- return function(text, type) { +- return fn(text.replace(uidPattern, function(match, prefix, index) { +- var chunks = ignoredCustomMarkupChunks[+index]; +- return chunks[1] + uidAttr + index + uidAttr + chunks[2]; +- }), type); +- }; +- })(options.minifyJS); +- } +- } +- var token = uidAttr + ignoredCustomMarkupChunks.length + uidAttr; +- ignoredCustomMarkupChunks.push(/^(\s*)[\s\S]*?(\s*)$/.exec(match)); +- return '\t' + token + '\t'; +- }); +- } ++ // Chromium patch for https://github.com/kangax/html-minifier/issues/1135. ++ // Removed ignoreCustomFragments processing completely as it is not needed anyway. + + if (options.sortAttributes && typeof options.sortAttributes !== 'function' || + options.sortClassName && typeof options.sortClassName !== 'function') {
diff --git a/third_party/node/update_npm_deps b/third_party/node/update_npm_deps index ec800ee..0cd3a57d 100755 --- a/third_party/node/update_npm_deps +++ b/third_party/node/update_npm_deps
@@ -64,6 +64,7 @@ echo 'Step 3: Applying local patches...' patch -d node_modules/@types/d3/ -p1 < patches/chromium_d3_types_index.patch patch -d node_modules/html-minifier/ -p1 < patches/html_minifier.patch +patch -p1 < patches/html_minifier2.patch patch -p1 < patches/lit_html.patch patch -p1 < patches/types_chai.patch patch -p1 < patches/types_trusted_types.patch
diff --git a/third_party/pdfium b/third_party/pdfium index cf433ae..66b63bb 160000 --- a/third_party/pdfium +++ b/third_party/pdfium
@@ -1 +1 @@ -Subproject commit cf433ae5520d061db56391155b59b34e67484f39 +Subproject commit 66b63bba62fc2587bf91d3a055a9079f5984b8c6
diff --git a/third_party/rust/chromium_crates_io/Cargo.lock b/third_party/rust/chromium_crates_io/Cargo.lock index 4fbe5da..79c58cc 100644 --- a/third_party/rust/chromium_crates_io/Cargo.lock +++ b/third_party/rust/chromium_crates_io/Cargo.lock
@@ -74,7 +74,7 @@ [[package]] name = "cc" -version = "1.2.23" +version = "1.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "shlex",
diff --git a/third_party/rust/chromium_crates_io/supply-chain/config.toml b/third_party/rust/chromium_crates_io/supply-chain/config.toml index 03fe52f..89f449b 100644 --- a/third_party/rust/chromium_crates_io/supply-chain/config.toml +++ b/third_party/rust/chromium_crates_io/supply-chain/config.toml
@@ -74,7 +74,7 @@ [policy."calendrical_calculations:0.2.0"] criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"] -[policy."cc:1.2.23"] +[policy."cc:1.2.24"] criteria = [] [policy."cfg-if:1.0.0"]
diff --git a/third_party/rust/chromium_crates_io/vendor/cc-v1/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/cc-v1/Cargo.toml index 2453d9a2..4076815 100644 --- a/third_party/rust/chromium_crates_io/vendor/cc-v1/Cargo.toml +++ b/third_party/rust/chromium_crates_io/vendor/cc-v1/Cargo.toml
@@ -6,13 +6,13 @@ # by `tools/crates/run_gnrt.py vendor`. Do not edit! # # This is an empty placeholder that has replaced the -# `cc-1.2.23` crate. +# `cc-1.2.24` crate. # # See `//tools/crates/gnrt/removed_crate.md` to learn more. [package] name = "cc" -version = "1.2.23" +version = "1.2.24" [package.metadata.gnrt] is_placeholder = true
diff --git a/third_party/rust/chromium_crates_io/vendor/cc-v1/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/cc-v1/src/lib.rs index 4ce2fe1..b5b46e96 100644 --- a/third_party/rust/chromium_crates_io/vendor/cc-v1/src/lib.rs +++ b/third_party/rust/chromium_crates_io/vendor/cc-v1/src/lib.rs
@@ -6,6 +6,6 @@ // by `tools/crates/run_gnrt.py vendor`. Do not edit! // // This is an empty placeholder that has replaced the -// `cc-1.2.23` crate. +// `cc-1.2.24` crate. // // See `//tools/crates/gnrt/removed_crate.md` to learn more.
diff --git a/third_party/skia b/third_party/skia index e2dc10a..82d326f 160000 --- a/third_party/skia +++ b/third_party/skia
@@ -1 +1 @@ -Subproject commit e2dc10af85db2b3c8e95fe0b7f5817614fb31419 +Subproject commit 82d326fc2148181e8d9ca848b17237fa4db75331
diff --git a/third_party/vulkan-deps b/third_party/vulkan-deps index 9b8253b..7a77f5b 160000 --- a/third_party/vulkan-deps +++ b/third_party/vulkan-deps
@@ -1 +1 @@ -Subproject commit 9b8253ba5637b5ad10835a8e412f3b29b4cd9dae +Subproject commit 7a77f5b6428118e42f8a35586578a4fabeba7135
diff --git a/third_party/vulkan-validation-layers/src b/third_party/vulkan-validation-layers/src index ee2b1e4..30f98bc 160000 --- a/third_party/vulkan-validation-layers/src +++ b/third_party/vulkan-validation-layers/src
@@ -1 +1 @@ -Subproject commit ee2b1e4837b496cacac158f13bac28ad543223f3 +Subproject commit 30f98bc36f99860a6c2cd18c4af5f3f387e0b933
diff --git a/third_party/wayland-protocols/BUILD.gn b/third_party/wayland-protocols/BUILD.gn index da8491c..4bcbc2c 100644 --- a/third_party/wayland-protocols/BUILD.gn +++ b/third_party/wayland-protocols/BUILD.gn
@@ -168,11 +168,6 @@ } wayland_protocol("ui_controls_protocol") { - sources = [ "unstable/ui-controls/ui-controls-unstable-v2.xml" ] -} - -wayland_protocol("ui_controls_v1_protocol") { - # This is used by exo. sources = [ "unstable/ui-controls/ui-controls-unstable-v1.xml" ] }
diff --git a/third_party/wayland-protocols/unstable/ui-controls/ui-controls-unstable-v2.xml b/third_party/wayland-protocols/unstable/ui-controls/ui-controls-unstable-v2.xml deleted file mode 100644 index ed579528..0000000 --- a/third_party/wayland-protocols/unstable/ui-controls/ui-controls-unstable-v2.xml +++ /dev/null
@@ -1,139 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<protocol name="ui_controls_unstable_v2"> - <copyright> - Copyright 2022 The Chromium Authors. - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice (including the next - paragraph) shall be included in all copies or substantial portions of the - Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - </copyright> - - <interface name="zcr_ui_controls_v2" version="1"> - <description summary="requests for input emulation"> - This global provides requests for different type of input emulation that - mirror the semantics of Chrome's ui_controls functions. - </description> - - <enum name="key_state" bitfield="true"> - <description - summary="whether to press, release, or press and release a key"> - These flags signal which key events to emulate: press; release; or - press, then release. - </description> - <!-- same values as ui_controls::KeyEventType --> - <entry name="press" value="1"/> - <entry name="release" value="2"/> - </enum> - - <enum name="mouse_button"> - <description summary="which mouse button to emulate"> - Which mouse button to emulate an event for. - </description> - <!-- same values as ui_controls::MouseButton --> - <entry name="left" value="0"/> - <entry name="middle" value="1"/> - <entry name="right" value="2"/> - </enum> - - <enum name="mouse_button_state" bitfield="true"> - <description summary="whether to press, release, or click a mouse button"> - These flags signal which mouse button events to emulate: press; release; - or press, then release. - </description> - <!-- same values as ui_controls::MouseButtonState --> - <entry name="up" value="1"/> - <entry name="down" value="2"/> - </enum> - - <enum name="modifier" bitfield="true"> - <description summary="pressed modifiers"> - These flags signal which modifiers should be pressed during an emulated - input, if any. - </description> - <!-- same values as ui_controls::AcceleratorState --> - <entry name="none" value="0"/> - <entry name="shift" value="1"/> - <entry name="control" value="2"/> - <entry name="alt" value="4"/> - </enum> - - <request name="send_key_events"> - <description summary="emulate a key press/release/press and release"> - Requests the compositor to emulate a key press, release, or press and - release for the key corresponding to the given keycode, together with - the specified modifiers. The compositor will decide which specific - events to generate in response to this request. After the compositor has - finished processing this request, a request_processed event with a - matching `id` will be emitted. - </description> - <arg name="key" type="uint" summary="evdev key code"/> - <arg name="key_state" type="uint" enum="key_state" - summary="whether to press, release, or press and release the key"/> - <arg name="pressed_modifiers" type="uint" enum="modifier" - summary="pressed modifier keys"/> - <arg name="id" type="uint" - summary="will be echoed back in the matching sent event"/> - </request> - - <request name="send_mouse_move"> - <description summary="emulate a mouse move to the given location"> - Requests the compositor to emulate a mouse move to the given location. - The compositor will decide which specific events to generate in response - to this request. After the compositor has finished processing this - request, a request_processed event with a matching `id` will be emitted. - - If `surface` is null, `x` and `y` are global screen coordinates; else, - they are surface-local coordinates relative to `surface`. - </description> - <arg name="x" type="int" summary="x-coordinate in DIP"/> - <arg name="y" type="int" summary="x-coordinate in DIP"/> - <arg name="surface" type="object" interface="wl_surface" - allow-null="true" summary="surface that x and y are relative to"/> - <arg name="id" type="uint" - summary="will be echoed back in the matching sent event"/> - </request> - - <request name="send_mouse_button"> - <description summary="emulate a mouse button press/release/click"> - Requests the compositor to emulate an up (if `state` is up) / down (if - `state` is down) / click (i.e. down and up, if `state` is down|up) for - the specified mouse button at the current mouse position, together with - the specified modifiers. The compositor will decide which specific - events to generate in response to this request. After the compositor has - finished processing this request, a request_processed event with a - matching `id` will be emitted. - </description> - <arg name="button" type="uint" enum="mouse_button" - summary="button code of the mouse button"/> - <arg name="button_state" type="uint" enum="mouse_button_state" - summary="whether to press, release, or click the button"/> - <arg name="pressed_modifiers" type="uint" enum="modifier" - summary="pressed modifier keys"/> - <arg name="id" type="uint" - summary="will be echoed back in the matching sent event"/> - </request> - - <event name="request_processed"> - <description summary="request has been processed"> - The request with ID `id` has been fully processed. - </description> - <arg name="id" type="uint" summary="ID of the processed request"/> - </event> - - </interface> -</protocol>
diff --git a/third_party/webgpu-cts/src b/third_party/webgpu-cts/src index 905c7cb..00bbf54 160000 --- a/third_party/webgpu-cts/src +++ b/third_party/webgpu-cts/src
@@ -1 +1 @@ -Subproject commit 905c7cbfeaac1cf3feb4c6056dd6f3dbaa06b074 +Subproject commit 00bbf5422c1b7a71285c51b2dc1e1637e618b916
diff --git a/third_party/weston/src b/third_party/weston/src index bdba2f9..4eb10b1 160000 --- a/third_party/weston/src +++ b/third_party/weston/src
@@ -1 +1 @@ -Subproject commit bdba2f9adaca673fd58339d8140bc04727ee279d +Subproject commit 4eb10b123b483327214d8da5da67e8bbeeaed8fe
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index c992acaa..a1abe83 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -10216,6 +10216,16 @@ </description> </action> +<action name="DomDistiller.Android.OnStartedReaderMode"> + <owner>wylieb@google.com</owner> + <owner>chrome-reader-mode-team@google.com</owner> + <description> + Recorded when a user started reader mode through an interaction with a + message or the magic toolbar button. This doesn't record when the actual + viewer appears, but rather when the viewer is requested. + </description> +</action> + <action name="DomDistiller.Android.ThemeChanged"> <owner>wylieb@google.com</owner> <owner>chrome-reader-mode-team@google.com</owner> @@ -10225,6 +10235,9 @@ </action> <action name="DomDistiller_DistilledPageOpened"> + <obsolete> + Long dead, reimplemented as DomDistiller.Android.OnStartedReaderMode. + </obsolete> <owner>smaslo@chromium.org</owner> <owner>yfriedman@chromium.org</owner> <description>User opens reader mode on a page.</description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index dbd3c5d..f7e09f6 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -12372,7 +12372,6 @@ <int value="-582570706" label="PPAPISharedImagesSwapChain:disabled"/> <int value="-582300629" label="UserNotes:enabled"/> <int value="-581236612" label="ConnectivityDiagnosticsWebUi:disabled"/> - <int value="-581218894" label="TabResumptionModuleAndroid:disabled"/> <int value="-580897686" label="SharedHighlightingAmp:enabled"/> <int value="-580051880" label="BirchWeather:disabled"/> <int value="-579897981" label="EnableEdgeDetection:enabled"/> @@ -16435,7 +16434,6 @@ <int value="957333504" label="OmniboxSteadyStateHeight:enabled"/> <int value="957458620" label="MediaRouterOTRInstance:enabled"/> <int value="960413971" label="GlanceablesV2CalendarView:disabled"/> - <int value="960696967" label="TabResumptionModuleAndroid:enabled"/> <int value="960883599" label="IPH_SupervisedUserProfileSignin:enabled"/> <int value="961019394" label="IOSPromoRefreshedPasswordBubble:disabled"/> <int value="962191833" label="StopAppIndexingReport:disabled"/> @@ -20086,6 +20084,7 @@ <int value="16" label="Device In Use (NotReadableError)"/> <int value="17" label="Request cancelled (?)"/> <int value="18" label="Start timeout (AbortError)"/> + <int value="19" label="Permission denied by user (NotAllowedError)"/> </enum> <enum name="MediaStreamType">
diff --git a/tools/metrics/histograms/metadata/blink/histograms.xml b/tools/metrics/histograms/metadata/blink/histograms.xml index 82e08c7..3a11aee 100644 --- a/tools/metrics/histograms/metadata/blink/histograms.xml +++ b/tools/metrics/histograms/metadata/blink/histograms.xml
@@ -5087,6 +5087,29 @@ </summary> </histogram> +<histogram name="Blink.ThrottleFrameRate.AllowedBySecurity.API" enum="Boolean" + expires_after="2025-12-31"> + <owner>gjc@google.com</owner> + <owner>chrome-loading@google.com</owner> + <summary> + Whether the frame rate throttling feature is allowed by the security check. + Recorded each time the link blocking="full-frame-rate" API is + triggered. + </summary> +</histogram> + +<histogram + name="Blink.ThrottleFrameRate.AllowedBySecurity.DocumentInitialization" + enum="Boolean" expires_after="2025-12-31"> + <owner>gjc@google.com</owner> + <owner>chrome-loading@google.com</owner> + <summary> + Whether the frame rate throttling feature is allowed by the security check. + Recorded each time the browser attempts to throttle the frame rate when the + document is initialized and the corresponding feature is enabled. + </summary> +</histogram> + <histogram name="Blink.UpdateViewportIntersection.RemoteFrameNeedsUpdate" enum="BooleanYesNo" expires_after="2025-10-26"> <owner>lizeb@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/chromeos/histograms.xml b/tools/metrics/histograms/metadata/chromeos/histograms.xml index da9ab22..1ba89cf 100644 --- a/tools/metrics/histograms/metadata/chromeos/histograms.xml +++ b/tools/metrics/histograms/metadata/chromeos/histograms.xml
@@ -1176,9 +1176,9 @@ </histogram> <histogram name="ChromeOS.CWP.CollectPerf" - enum="ChromeOSProfileCollectionStatus" expires_after="2025-06-22"> - <owner>aalexand@google.com</owner> + enum="ChromeOSProfileCollectionStatus" expires_after="2026-06-22"> <owner>gmx@chromium.org</owner> + <owner>aalexand@google.com</owner> <owner>cwp-team@google.com</owner> <summary> A count of successes and various failure modes related to collecting and
diff --git a/tools/metrics/histograms/metadata/chromeos_settings/histograms.xml b/tools/metrics/histograms/metadata/chromeos_settings/histograms.xml index b23e00a..26a040b8 100644 --- a/tools/metrics/histograms/metadata/chromeos_settings/histograms.xml +++ b/tools/metrics/histograms/metadata/chromeos_settings/histograms.xml
@@ -218,7 +218,7 @@ name="ChromeOS.Settings.Device.Keyboard.AutoBrightnessEnabled.Changed" enum="BooleanToggled" expires_after="2025-12-31"> <owner>longbowei@google.com</owner> - <owner>dpad@google.com</owner> + <owner>jimmyxgong@chromium.org</owner> <owner>cros-device-enablement@google.com</owner> <summary> Records each time a user toggles the keyboard auto-brightness setting via @@ -229,7 +229,7 @@ <histogram name="ChromeOS.Settings.Device.Keyboard.BrightnessSliderAdjusted" units="%" expires_after="2025-12-31"> <owner>longbo@google.com</owner> - <owner>dpad@google.com</owner> + <owner>jimmyxgong@chromium.org</owner> <owner>cros-device-enablement@google.com</owner> <summary> Records each time a user changes the keyboard brightness using slider in @@ -263,7 +263,7 @@ <histogram name="ChromeOS.Settings.Device.KeyboardColorLinkClicks" enum="Boolean" expires_after="2025-12-31"> <owner>longbowei@google.com</owner> - <owner>dpad@google.com</owner> + <owner>jimmyxgong@chromium.org</owner> <owner>cros-device-enablement@google.com</owner> <summary> Records when a user clicks the "Keyboard Color" link within @@ -489,7 +489,7 @@ <histogram name="ChromeOS.Settings.Keyboard.Modifiers.Hash" units="hash" expires_after="2026-03-22"> - <owner>dpad@google.com</owner> + <owner>jimmyxgong@chromium.org</owner> <owner>cros-device-enablement@google.com</owner> <summary> Records the configured modifier remapping set for all modifiers as a hash. @@ -502,7 +502,7 @@ <histogram name="ChromeOS.Settings.Keyboard.Modifiers.{Modifier}RemappedTo.Changed" enum="KeyboardModifierRemappingKeys" expires_after="2026-03-22"> - <owner>dpad@google.com</owner> + <owner>jimmyxgong@chromium.org</owner> <owner>cros-device-enablement@google.com</owner> <summary> Records the configured modifier remapping for the {Modifier} key when a user @@ -524,7 +524,7 @@ <histogram name="ChromeOS.Settings.Keyboard.Modifiers.{Modifier}RemappedTo.Started" enum="KeyboardModifierRemappingKeys" expires_after="2026-03-22"> - <owner>dpad@google.com</owner> + <owner>jimmyxgong@chromium.org</owner> <owner>cros-device-enablement@google.com</owner> <summary> Records the configured modifier remapping for the {Modifier} key when a user
diff --git a/tools/metrics/histograms/metadata/media/enums.xml b/tools/metrics/histograms/metadata/media/enums.xml index 538d419..3c137a9e 100644 --- a/tools/metrics/histograms/metadata/media/enums.xml +++ b/tools/metrics/histograms/metadata/media/enums.xml
@@ -2001,6 +2001,7 @@ <int value="10" label="Not Supported Error"/> <int value="11" label="Insecure Context"/> <int value="12" label="Invalid State Error"/> + <int value="13" label="Explicit User Rejection"/> </enum> <enum name="V4l2VideoDecoderFunctions">
diff --git a/tools/metrics/histograms/metadata/media/histograms.xml b/tools/metrics/histograms/metadata/media/histograms.xml index 4032680d9..911db388 100644 --- a/tools/metrics/histograms/metadata/media/histograms.xml +++ b/tools/metrics/histograms/metadata/media/histograms.xml
@@ -4289,6 +4289,30 @@ </summary> </histogram> +<histogram name="Media.MediaDevices.GetAllScreensMedia.Latency" units="ms" + expires_after="2023-05-01"> + <owner>simonha@google.com</owner> + <owner>video-cmi-apis@google.com</owner> + <summary> + The latency of calls to the navigator.mediaDevices.GetAllScreensMedia() API + which resolve, including both successes and failures. Note very long calls + which record a GetAllScreensMedia.Result of kTimedOut but do eventually + resolve will have their latency recorded. + </summary> +</histogram> + +<histogram name="Media.MediaDevices.GetAllScreensMedia.Result2" + enum="UserMediaRequestResult" expires_after="2023-05-01"> + <owner>simonha@google.com</owner> + <owner>video-cmi-apis@google.com</owner> + <summary> + The results of all calls to the navigator.mediaDevices.GetAllScreensMedia() + API, including successful promise resolutions, error codes, or kTimedOut, if + the promise was still pending after 6 seconds. The suffix 2 was added at + milestone 138, after kNotAllowedByUserError was added. + </summary> +</histogram> + <histogram name="Media.MediaDevices.GetDisplayMedia.Latency" units="ms" expires_after="2025-11-02"> <owner>toprice@chromium.org</owner> @@ -4302,7 +4326,7 @@ </summary> </histogram> -<histogram name="Media.MediaDevices.GetDisplayMedia.Result" +<histogram name="Media.MediaDevices.GetDisplayMedia.Result2" enum="UserMediaRequestResult" expires_after="2025-11-09"> <owner>toprice@chromium.org</owner> <owner>agpalak@chromium.org</owner> @@ -4310,30 +4334,8 @@ <summary> The results of all calls to the navigator.mediaDevices.GetDisplayMedia() API, including successful promise resolutions, error codes, or kTimedOut, if - the promise was still pending after 6 seconds. - </summary> -</histogram> - -<histogram name="Media.MediaDevices.GetDisplayMediaSet.Latency" units="ms" - expires_after="2023-05-01"> - <owner>simonha@google.com</owner> - <owner>video-cmi-apis@google.com</owner> - <summary> - The latency of calls to the navigator.mediaDevices.GetDisplayMediaSet() API - which resolve, including both successes and failures. Note very long calls - which record a GetDisplayMediaSet.Result of kTimedOut but do eventually - resolve will have their latency recorded. - </summary> -</histogram> - -<histogram name="Media.MediaDevices.GetDisplayMediaSet.Result" - enum="UserMediaRequestResult" expires_after="2023-05-01"> - <owner>simonha@google.com</owner> - <owner>video-cmi-apis@google.com</owner> - <summary> - The results of all calls to the navigator.mediaDevices.GetDisplayMediaSet() - API, including successful promise resolutions, error codes, or kTimedOut, if - the promise was still pending after 6 seconds. + the promise was still pending after 6 seconds. The suffix 2 was added at + milestone 138, after kNotAllowedByUserError was added. </summary> </histogram> @@ -4361,7 +4363,7 @@ </summary> </histogram> -<histogram name="Media.MediaDevices.GetUserMedia.Result" +<histogram name="Media.MediaDevices.GetUserMedia.Result2" enum="UserMediaRequestResult" expires_after="2025-10-26"> <owner>toprice@chromium.org</owner> <owner>agpalak@chromium.org</owner> @@ -4370,6 +4372,9 @@ The results of all calls to the navigator.mediaDevices.GetUserMedia() API, including successful promise resolutions, error codes, or kTimedOut, if the promise was still pending after 8 seconds. + + The suffix 2 was added at milestone 138, after kNotAllowedByUserError was + added. </summary> </histogram>
diff --git a/tools/metrics/histograms/metadata/navigation/histograms.xml b/tools/metrics/histograms/metadata/navigation/histograms.xml index 95e0402c..8bc1ce5 100644 --- a/tools/metrics/histograms/metadata/navigation/histograms.xml +++ b/tools/metrics/histograms/metadata/navigation/histograms.xml
@@ -866,7 +866,7 @@ </histogram> <histogram name="Navigation.DeferSpeculativeRFHAction" - enum="DeferSpeculativeRFHAction" expires_after="2025-06-08"> + enum="DeferSpeculativeRFHAction" expires_after="2025-12-08"> <owner>gjc@google.com</owner> <owner>rakina@chromium.org</owner> <owner>chrome-navigation@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/web_rtc/histograms.xml b/tools/metrics/histograms/metadata/web_rtc/histograms.xml index f31aee3b..9741e7e 100644 --- a/tools/metrics/histograms/metadata/web_rtc/histograms.xml +++ b/tools/metrics/histograms/metadata/web_rtc/histograms.xml
@@ -1128,7 +1128,7 @@ </histogram> <histogram name="WebRTC.DesktopCapture.Win.WgcCapturerResult" - enum="WebRtcWgcCapturerResult" expires_after="2025-07-05"> + enum="WebRtcWgcCapturerResult" expires_after="2025-11-19"> <owner>alcooper@chromium.org</owner> <owner>henrika@chromium.org</owner> <owner>edgecapabilitiesdev@microsoft.com</owner> @@ -1139,7 +1139,7 @@ </histogram> <histogram name="WebRTC.DesktopCapture.Win.WgcCaptureSessionGetFrameResult" - enum="WebRtcWgcCaptureSessionGetFrameResult" expires_after="2025-07-05"> + enum="WebRtcWgcCaptureSessionGetFrameResult" expires_after="2025-11-19"> <owner>alcooper@chromium.org</owner> <owner>henrika@chromium.org</owner> <owner>edgecapabilitiesdev@microsoft.com</owner> @@ -1149,7 +1149,7 @@ </histogram> <histogram name="WebRTC.DesktopCapture.Win.WgcCaptureSessionStartResult" - enum="WebRtcWgcCaptureSessionStartResult" expires_after="2025-07-05"> + enum="WebRtcWgcCaptureSessionStartResult" expires_after="2025-11-19"> <owner>alcooper@chromium.org</owner> <owner>henrika@chromium.org</owner> <owner>edgecapabilitiesdev@microsoft.com</owner>
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml index 70d6153..700f3705a 100644 --- a/tools/traffic_annotation/summary/annotations.xml +++ b/tools/traffic_annotation/summary/annotations.xml
@@ -170,7 +170,6 @@ <item id="remoting_directory_get_host_list" added_in_milestone="86" content_hash_code="03933aa0" os_list="linux,windows,chromeos,android" file_path="remoting/base/directory_service_client.cc" /> <item id="remoting_directory_register_host" added_in_milestone="86" content_hash_code="046c936d" os_list="linux,windows,chromeos,android" file_path="remoting/base/directory_service_client.cc" /> <item id="remoting_ice_config_request" added_in_milestone="86" content_hash_code="001d0a98" os_list="linux,windows,chromeos,android" file_path="remoting/protocol/ice_config_fetcher_default.cc" /> - <item id="remoting_log_to_server" added_in_milestone="86" content_hash_code="04dfdf0a" os_list="linux,windows,chromeos,android" file_path="remoting/signaling/remoting_log_to_server.cc" /> <item id="remoting_register_support_host_request" added_in_milestone="86" content_hash_code="04fd7da8" os_list="linux,windows,chromeos" file_path="remoting/host/remoting_register_support_host_request.cc" /> <item id="remoting_telemetry_log_writer" added_in_milestone="86" content_hash_code="04df471b" os_list="linux,windows,chromeos,android" file_path="remoting/base/telemetry_log_writer.cc" /> <item id="render_view_context_menu" added_in_milestone="62" content_hash_code="04240bc2" os_list="linux,windows,chromeos" file_path="chrome/browser/renderer_context_menu/render_view_context_menu.cc" />
diff --git a/tools/traffic_annotation/summary/grouping.xml b/tools/traffic_annotation/summary/grouping.xml index 218c9256..44af999 100644 --- a/tools/traffic_annotation/summary/grouping.xml +++ b/tools/traffic_annotation/summary/grouping.xml
@@ -116,7 +116,6 @@ <annotation id="ftl_messaging_client_receive_messages"/> <annotation id="ftl_messaging_client_send_messages"/> <annotation id="ftl_registration_manager"/> - <annotation id="remoting_log_to_server"/> <annotation id="remoting_provision_corp_machine"/> <annotation id="omnibox_result_change"/> <annotation id="browser_switcher_ieem_sitelist"/>
diff --git a/ui/android/java/src/org/chromium/ui/interpolators/Interpolators.java b/ui/android/java/src/org/chromium/ui/interpolators/Interpolators.java index bab6e695..be21773 100644 --- a/ui/android/java/src/org/chromium/ui/interpolators/Interpolators.java +++ b/ui/android/java/src/org/chromium/ui/interpolators/Interpolators.java
@@ -63,10 +63,6 @@ public static final LinearInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator(); public static final OvershootInterpolator OVERSHOOT_INTERPOLATOR = new OvershootInterpolator(); - /** Custom interpolator for the new background tab animation arc motion. */ - public static final Interpolator NEW_BACKGROUND_TAB_ANIMATION_PATH_INTERPOLATOR = - PathInterpolatorCompat.create(0.41f, 0.12f, 0.38f, 1f); - /** * Custom interpolator for the new background tab fake tab switcher button translation animator. */ @@ -76,8 +72,4 @@ /** Custom interpolator for the new background tab fake tab switcher button shrink animator. */ public static final Interpolator NEW_BACKGROUND_TAB_ANIMATION_BOUNCE_INTERPOLATOR = PathInterpolatorCompat.create(0.2f, 0f, 0f, 2f); - - /** Custom interpolator for the new background tab animation arc motion. */ - public static final Interpolator NEW_BACKGROUND_TAB_ANIMATION_SECOND_PATH_INTERPOLATOR = - PathInterpolatorCompat.create(0.34f, 0.17f, 0.26f, 0.99f); }
diff --git a/ui/ozone/platform/wayland/emulate/wayland_input_emulate.cc b/ui/ozone/platform/wayland/emulate/wayland_input_emulate.cc index 90e202a6..4c50dab3 100644 --- a/ui/ozone/platform/wayland/emulate/wayland_input_emulate.cc +++ b/ui/ozone/platform/wayland/emulate/wayland_input_emulate.cc
@@ -4,7 +4,7 @@ #include "ui/ozone/platform/wayland/emulate/wayland_input_emulate.h" -#include <ui-controls-unstable-v2-client-protocol.h> +#include <ui-controls-unstable-v1-client-protocol.h> #include <wayland-client-protocol.h> #include <cstdint> @@ -21,6 +21,7 @@ #include "ui/ozone/platform/wayland/host/wayland_toplevel_window.h" #include "ui/ozone/platform/wayland/host/wayland_window.h" #include "ui/ozone/platform/wayland/host/xdg_popup.h" +#include "ui/ozone/platform/wayland/host/xdg_surface.h" #include "ui/ozone/platform/wayland/host/xdg_toplevel.h" #if BUILDFLAG(IS_CHROMEOS) @@ -29,6 +30,13 @@ #include "ui/display/test/display_test_util.h" #endif +namespace { + +// send_key_events() is only available since version 2. +constexpr uint32_t kMinVersion = 2; + +} // namespace + namespace wl { WaylandInputEmulate::PendingRequest::PendingRequest( @@ -67,16 +75,16 @@ LOG(FATAL) << "ui-controls protocol extension is not available."; } - static constexpr zcr_ui_controls_v2_listener kUiControlsListener = { + static constexpr zcr_ui_controls_v1_listener kUiControlsListener = { .request_processed = &OnRequestProcessed}; - zcr_ui_controls_v2_add_listener(ui_controls_, &kUiControlsListener, this); + zcr_ui_controls_v1_add_listener(ui_controls_, &kUiControlsListener, this); } WaylandInputEmulate::~WaylandInputEmulate() { auto* wayland_proxy = wl::WaylandProxy::GetInstance(); wayland_proxy->SetDelegate(nullptr); - zcr_ui_controls_v2_destroy(ui_controls_); + zcr_ui_controls_v1_destroy(ui_controls_); wl_registry_destroy(registry_); } @@ -99,7 +107,7 @@ << " state=" << key_state << " accelerator_state=" << accelerator_state; - zcr_ui_controls_v2_send_key_events( + zcr_ui_controls_v1_send_key_events( ui_controls_, ui::KeycodeConverter::DomCodeToEvdevCode(dom_code), key_state, accelerator_state, request_id); @@ -133,12 +141,16 @@ auto* wayland_proxy = wl::WaylandProxy::GetInstance(); - struct wl_surface* target_surface = nullptr; + struct xdg_surface* target_surface = nullptr; gfx::Point target_location = mouse_screen_location; if (widget) { auto* window = wayland_proxy->GetWaylandWindowForAcceleratedWidget(widget); - struct wl_surface* surface = - window->root_surface() ? window->root_surface()->surface() : nullptr; + struct xdg_surface* xdg_surface = nullptr; + if (auto* toplevel_window = window->AsWaylandToplevelWindow()) { + xdg_surface = toplevel_window->xdg_toplevel()->xdg_surface(); + } else if (auto* popup = window->AsWaylandPopup()) { + xdg_surface = popup->xdg_popup()->xdg_surface(); + } bool screen_coordinates = false; if (force_use_screen_coordinates_once_) { screen_coordinates = true; @@ -147,9 +159,9 @@ // If we can't use screen coordinates, we must have a surface so we can use // surface-local coordinates. - DCHECK(screen_coordinates || surface); + DCHECK(screen_coordinates || xdg_surface); - target_surface = screen_coordinates ? nullptr : surface; + target_surface = screen_coordinates ? nullptr : xdg_surface; // Ignore `force_use_screen_coordinates_once_` for selecting which // coordinates to use. This is because the only difference between // `mouse_screen_location` and `mouse_surface_location` is that the former @@ -167,7 +179,7 @@ VLOG(1) << "Requesting pointer motion: location=" << target_location.ToString(); - zcr_ui_controls_v2_send_mouse_move(ui_controls_, target_location.x(), + zcr_ui_controls_v1_send_mouse_move(ui_controls_, target_location.x(), target_location.y(), target_surface, request_id); wayland_proxy->FlushForTesting(); @@ -190,13 +202,37 @@ VLOG(1) << "Requesting pointer button: button=" << button << " button_state=" << button_state; - zcr_ui_controls_v2_send_mouse_button(ui_controls_, button, button_state, + zcr_ui_controls_v1_send_mouse_button(ui_controls_, button, button_state, accelerator_state, request_id); auto* wayland_proxy = wl::WaylandProxy::GetInstance(); wayland_proxy->FlushForTesting(); } +void WaylandInputEmulate::EmulateTouch(int action, + const gfx::Point& touch_screen_location, + int touch_id, + uint32_t request_id) { + if (AnyWindowWaitingForBufferCommit()) { + auto pending_request = + std::make_unique<PendingRequest>(PendingRequestType::Touch, request_id); + pending_request->action = action; + pending_request->touch_screen_location = touch_screen_location; + pending_request->touch_id = touch_id; + pending_requests_.emplace_back(std::move(pending_request)); + return; + } + + VLOG(1) << "Requesting touch: location=" << touch_screen_location.ToString() + << " action=" << action << " touch_id=" << touch_id; + + zcr_ui_controls_v1_send_touch( + ui_controls_, action, touch_id, touch_screen_location.x(), + touch_screen_location.y(), /*surface=*/nullptr, request_id); + auto* wayland_proxy = wl::WaylandProxy::GetInstance(); + wayland_proxy->FlushForTesting(); +} + void WaylandInputEmulate::ForceUseScreenCoordinatesOnce() { force_use_screen_coordinates_once_ = true; } @@ -294,7 +330,7 @@ // static void WaylandInputEmulate::OnRequestProcessed(void* data, - zcr_ui_controls_v2* ui_controls, + zcr_ui_controls_v1* ui_controls, uint32_t id) { auto* self = static_cast<WaylandInputEmulate*>(data); self->request_processed_callback_.Run(id); @@ -307,10 +343,11 @@ const char* interface, uint32_t version) { auto* self = static_cast<WaylandInputEmulate*>(data); - if (std::string_view(interface) == "zcr_ui_controls_v2") { + if (UNSAFE_TODO(strcmp(interface, "zcr_ui_controls_v1")) == 0 && + version >= kMinVersion) { const wl_interface* wayland_interface = - static_cast<const wl_interface*>(&zcr_ui_controls_v2_interface); - self->ui_controls_ = static_cast<zcr_ui_controls_v2*>( + static_cast<const wl_interface*>(&zcr_ui_controls_v1_interface); + self->ui_controls_ = static_cast<zcr_ui_controls_v1*>( wl_registry_bind(registry, name, wayland_interface, version)); } } @@ -385,6 +422,10 @@ EmulatePointerButton(event->button, event->button_state, event->accelerator_state, event->request_id); break; + case PendingRequestType::Touch: + EmulateTouch(event->action, event->touch_screen_location, + event->touch_id, event->request_id); + break; } } }
diff --git a/ui/ozone/platform/wayland/emulate/wayland_input_emulate.h b/ui/ozone/platform/wayland/emulate/wayland_input_emulate.h index f867225..b63933f7 100644 --- a/ui/ozone/platform/wayland/emulate/wayland_input_emulate.h +++ b/ui/ozone/platform/wayland/emulate/wayland_input_emulate.h
@@ -23,7 +23,7 @@ struct wl_buffer; struct wl_registry; -struct zcr_ui_controls_v2; +struct zcr_ui_controls_v1; struct wl_callback; namespace wl { @@ -56,6 +56,12 @@ int accelerator_state, uint32_t request_id); + // |touch_screen_location| is in DIP. + void EmulateTouch(int action, + const gfx::Point& touch_screen_location, + int touch_id, + uint32_t request_id); + void ForceUseScreenCoordinatesOnce(); private: @@ -63,6 +69,7 @@ KeyPress, MouseMove, MouseButton, + Touch, }; // Pending emulation request. @@ -138,9 +145,9 @@ bool is_configured) override; void OnWindowRoleAssigned(gfx::AcceleratedWidget widget) override; - // zcr_ui_controls_v2_listener callbacks: + // zcr_ui_controls_v1_listener callbacks: static void OnRequestProcessed(void* data, - zcr_ui_controls_v2* ui_controls, + zcr_ui_controls_v1* ui_controls, uint32_t id); // wl_registry_listener callbacks: @@ -179,7 +186,7 @@ base::RepeatingCallback<void(uint32_t)> request_processed_callback_; // If true, the next `EmulatePointerMotion` call will use global screen - // coordinates, i.e. send zcr_ui_controls_v2.mouse_move with the `surface` + // coordinates, i.e. send zcr_ui_controls_v1.mouse_move with the `surface` // parameter set to NULL. // Note: this does not affect whether `EmulatePointerMotion` uses the // coordinates from its `mouse_surface_location` or `mouse_screen_location` @@ -190,7 +197,7 @@ // class belongs to cannot depend on the "wayland" target in the // //ui/ozone/platform/wayland/BUILD.gn raw_ptr<wl_registry> registry_ = nullptr; - raw_ptr<zcr_ui_controls_v2> ui_controls_ = nullptr; + raw_ptr<zcr_ui_controls_v1> ui_controls_ = nullptr; }; } // namespace wl
diff --git a/v8 b/v8 index e180c60..61ddd47 160000 --- a/v8 +++ b/v8
@@ -1 +1 @@ -Subproject commit e180c60cc3eb265924e992248b0fe2c68e122cab +Subproject commit 61ddd471ece346840bbebbb308dceb4b4ce31b28