diff --git a/DEPS b/DEPS index 01c3d7b..fe9d108f 100644 --- a/DEPS +++ b/DEPS
@@ -138,11 +138,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '0cb2fdefc219df122cd764b333fce7e826ab5158', + 'skia_revision': '66661df8e9f964b5113783a28a5aad7e29a0d21c', # 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': 'bcf517c0366d4af6dfb600e5344ef37e65a09d0b', + 'v8_revision': '2cb25737c9eb7893ac752674e75d400b4419f67c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -150,15 +150,15 @@ # 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': '5a808b86d8901b9cb7a4d174356c0c1b0e2fc0e3', + 'angle_revision': 'ded5f903261a8bee3481aad98d7ed47308b59563', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '90cb260644cdcdb81e87c6e3bf3ec5885eb23f3b', + 'swiftshader_revision': 'ca8e3d7c153e7b89f881c02c8ca7ba0581afc5b1', # 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': '12d7da217249af8585e35d0807ee8c3686870714', + 'pdfium_revision': '4e2aa897a424d907282e089da36836576d80210a', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -201,7 +201,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': 'a7b33124672f301cebe0ca94a67ca7d0362e3d6a', + 'catapult_revision': '5db62d36c9b55e85168a772a66dcaa352d2754fd', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -257,7 +257,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'spv_tools_revision': '5a06fa466186698bcb0757bea201828e47527b98', + 'spv_tools_revision': 'f051812343eb6ed34f3a327e1e82bebc06aa6a0f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -807,7 +807,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '162eba28f2077dd9a64e326588b478b2c3cbdf37', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'a730bef0e7549ed488c1d4c797c51e0751f23a96', 'condition': 'checkout_linux', }, @@ -832,7 +832,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'c5b8a73247c432dbdbc010997f47994e9c3fff43', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '4ce909c11c06bca34057e56ccefc72a1bf1e7e8c', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -1378,7 +1378,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/${{platform}}', - 'version': 'git_revision:f3b1cb52b997b012c7f0381fd12d964a160bab17', + 'version': 'git_revision:655c9feb61e01564abecebe451ca90c26035e938', }, ], 'dep_type': 'cipd', @@ -1391,7 +1391,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@fd40163541b48d82731dad362f4111481bde4e33', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@76ce2f554e7af6822d19b014c7f451dcf0069562', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/docs/images/webview_implementations_menu.png b/android_webview/docs/images/webview_implementations_menu.png new file mode 100644 index 0000000..535ff9dd --- /dev/null +++ b/android_webview/docs/images/webview_implementations_menu.png Binary files differ
diff --git a/android_webview/docs/navbar.md b/android_webview/docs/navbar.md index da2e804b..29485b7 100644 --- a/android_webview/docs/navbar.md +++ b/android_webview/docs/navbar.md
@@ -4,6 +4,7 @@ * [Quick start](/android_webview/docs/quick-start.md) * [Device Setup](/android_webview/docs/device-setup.md) * [Test instructions](/android_webview/docs/test-instructions.md) +* [WebView Beta](/android_webview/docs/prerelease.md) * [WebView Shell](/android_webview/docs/webview-shell.md) * [Commandline flags](/android_webview/docs/commandline-flags.md) * [Net debugging](/android_webview/docs/net-debugging.md)
diff --git a/android_webview/docs/prerelease.md b/android_webview/docs/prerelease.md new file mode 100644 index 0000000..635ea9f --- /dev/null +++ b/android_webview/docs/prerelease.md
@@ -0,0 +1,121 @@ +# Try out WebView Beta, Dev, or Canary + +Using a pre-release channel of WebView allows you to test new, upcoming features +and enhancements to WebView. This is especially useful for Android app +developers who use WebView in their apps. + +[TOC] + +## Which channel do I want? + +Like [Chrome](https://www.chromium.org/getting-involved/dev-channel), WebView +has four release channels: + +- Stable channel + - Installed and updated by default on every Android device with WebView + - Fully tested; least likely to crash or have other major bugs + - Updated every 2-3 weeks with minor releases, and every 6 weeks with major + releases +- Beta channel + - Available on Android 5 (Lollipop) and later + - Tested before release, but not as extensively as stable + - One major update ahead of stable, minor updates every week +- Dev channel + - Publicly available on Android 7 (Nougat) and later + - Two major updates ahead of stable, representing what is actively being + developed + - Updated once per week + - Minimally tested +- Canary build + - Available on Android 7 (Nougat) and later + - Released daily + - Includes the latest code changes from the previous day + - Has not been tested or used + +On Android 7 (Nougat) and later, you can install multiple channels at the same +time. This allows you to play with our latest code, while still keeping a tested +version of WebView around. + +## How do I try a pre-release channel? + +Steps depend on your version of Android: + +### Android 7 through 9 (Nougat/Oreo/Pie) + +Pre-release channels must be downloaded and installed as separate apps, but one +must be chosen to provide the system's WebView implementation at any given time. + +1. Download a pre-release channel of Chrome from the play store, available here: + - [Chrome Beta](https://play.google.com/store/apps/details?id=com.chrome.beta) + - [Chrome Dev](https://play.google.com/store/apps/details?id=com.chrome.dev) + - [Chrome Canary](https://play.google.com/store/apps/details?id=com.chrome.canary) +2. Follow the [steps to enable Android's developer options + menu](https://developer.android.com/studio/debug/dev-options) +3. Choose Developer Options > WebView implementation (see figure) + +  + +4. Choose the Chrome channel that you would like to use for WebView + +#### Returning to stable WebView + +1. To return to WebView stable, select Chrome again in the WebView + implementation menu + +### Android 5 or 6 (Lollipop/Marshmallow) and Android TV + +Only one installation of WebView is allowed, but users can opt to receive the +latest beta updates from the Play Store. + +1. [Join the beta tester program on Google + Play](https://play.google.com/apps/testing/com.google.android.webview) +2. On your device, update Android System Webview [in the Play + Store](https://play.google.com/store/apps/details?id=com.google.android.webview) +3. When the Play Store finishes updating, you will be using WebView beta! + +#### Returning to stable WebView + +1. [Leave the tester + program](https://play.google.com/apps/testing/com.google.android.webview) +2. Uninstall all updates by visiting Settings > Apps > Android System WebView > + Three dots menu in the top right > Uninstall updates +3. [Visit the Play Store + page](https://play.google.com/store/apps/details?id=com.google.android.webview) + one more time to install the latest updates to WebView stable, which will + include important security fixes. + +### Android 4.4 (KitKat) or earlier + +WebView does not receive updates on these versions of Android, so the +pre-release channels of WebView are not available. + +## Reporting problems with pre-release WebView + +Any WebView-related bugs can be filed [here](https://goo.gl/9qkbdn). + +To best enable us to resolve the issue, please ensure you provide all of the +information requested in the bug report template. + +## Command line tools + +Choosing your WebView implementation on Android 7 (Nougat) or later can also +be done using adb, instead of the Settings UI: + +```shell +adb shell cmd webviewupdate set-webview-implementation <packagename> +``` + +Package names are as follows: + +|App name |Package name | +|-----------------------:|----------------------------------------| +|Chrome (stable) |com.android.chrome | +|Chrome Beta |com.chrome.beta | +|Chrome Dev |com.chrome.dev | +|Chrome Canary |com.chrome.canary | + +## See also +- [WebView channels in detail](/android_webview/docs/channels.md) +- [Chrome Release + Channels](https://www.chromium.org/getting-involved/dev-channel) +
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwActivityTestRule.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwActivityTestRule.java index efd9942..88052e03 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwActivityTestRule.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwActivityTestRule.java
@@ -435,6 +435,23 @@ } /** + * Adds a JavaScript interface to the AwContents. Does its work synchronously on the UI thread, + * and can be called from any thread. All the rules of {@link + * android.webkit.WebView#addJavascriptInterface} apply to this method (ex. you must call this + * <b>prior</b> to loading the frame you intend to load the JavaScript interface into). + * + * @param awContents the AwContents in which to insert the JavaScript interface. + * @param objectToInject the JavaScript interface to inject. + * @param javascriptIdentifier the name with which to refer to {@code objectToInject} from + * JavaScript code. + */ + public static void addJavascriptInterfaceOnUiThread(final AwContents awContents, + final Object objectToInject, final String javascriptIdentifier) { + TestThreadUtils.runOnUiThreadBlocking( + () -> awContents.addJavascriptInterface(objectToInject, javascriptIdentifier)); + } + + /** * Wrapper around CriteriaHelper.pollInstrumentationThread. This uses AwActivityTestRule-specifc * timeouts and treats timeouts and exceptions as test failures automatically. */
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnRendererUnresponsiveTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnRendererUnresponsiveTest.java index f10a295..05b764d 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnRendererUnresponsiveTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnRendererUnresponsiveTest.java
@@ -148,8 +148,7 @@ } private void addJsBlockerInterface(final AwContents awContents, final JSBlocker blocker) { - PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, - () -> { awContents.addJavascriptInterface(blocker, "blocker"); }); + AwActivityTestRule.addJavascriptInterfaceOnUiThread(awContents, blocker, "blocker"); } // This test requires the ability to terminate the renderer in order to recover from a
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsGarbageCollectionTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsGarbageCollectionTest.java index 32bae58..21115d4 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsGarbageCollectionTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsGarbageCollectionTest.java
@@ -307,8 +307,7 @@ AwActivityTestRule.enableJavaScriptOnUiThread(containerViews[i].getAwContents()); final AwContents awContents = containerViews[i].getAwContents(); final Test jsObject = new Test(i, awContents); - InstrumentationRegistry.getInstrumentation().runOnMainSync( - () -> awContents.addJavascriptInterface(jsObject, "test")); + AwActivityTestRule.addJavascriptInterfaceOnUiThread(awContents, jsObject, "test"); mActivityTestRule.loadDataSync( awContents, contentsClient.getOnPageFinishedHelper(), html, "text/html", false); Assert.assertEquals(String.valueOf(i),
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java index c80b01c8..a354c27d 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java
@@ -450,13 +450,12 @@ mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient); final CallbackHelper callback = new CallbackHelper(); - InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { - AwContents awContents = testView.getAwContents(); - AwSettings awSettings = awContents.getSettings(); - awSettings.setJavaScriptEnabled(true); - awContents.addJavascriptInterface(new JavaScriptObject(callback), "bridge"); - awContents.evaluateJavaScriptForTests("window.bridge.run();", null); - }); + AwContents awContents = testView.getAwContents(); + AwActivityTestRule.enableJavaScriptOnUiThread(awContents); + AwActivityTestRule.addJavascriptInterfaceOnUiThread( + awContents, new JavaScriptObject(callback), "bridge"); + mActivityTestRule.executeJavaScriptAndWaitForResult( + awContents, mContentsClient, "window.bridge.run();"); callback.waitForCallback(0, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwJavaBridgeTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwJavaBridgeTest.java index 51561c7..05bd2ee1 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwJavaBridgeTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwJavaBridgeTest.java
@@ -66,8 +66,7 @@ } AwActivityTestRule.enableJavaScriptOnUiThread(awContents); - InstrumentationRegistry.getInstrumentation().runOnMainSync( - () -> awContents.addJavascriptInterface(new Test(), "test")); + AwActivityTestRule.addJavascriptInterfaceOnUiThread(awContents, new Test(), "test"); mActivityTestRule.loadDataSync( awContents, mContentsClient.getOnPageFinishedHelper(), html, "text/html", false); @@ -107,10 +106,8 @@ private int mValue; } - InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { - awContents1.addJavascriptInterface(new Test(1), "test"); - awContents2.addJavascriptInterface(new Test(2), "test"); - }); + AwActivityTestRule.addJavascriptInterfaceOnUiThread(awContents1, new Test(1), "test"); + AwActivityTestRule.addJavascriptInterfaceOnUiThread(awContents2, new Test(2), "test"); final String html = "<html>Hello World</html>"; mActivityTestRule.loadDataSync( awContents1, mContentsClient.getOnPageFinishedHelper(), html, "text/html", false); @@ -143,8 +140,7 @@ private int mValue; } - InstrumentationRegistry.getInstrumentation().runOnMainSync( - () -> awContents1.addJavascriptInterface(new Test(1), "test")); + AwActivityTestRule.addJavascriptInterfaceOnUiThread(awContents1, new Test(1), "test"); final String html = "<html>Hello World</html>"; mActivityTestRule.loadDataSync( awContents1, mContentsClient.getOnPageFinishedHelper(), html, "text/html", false); @@ -158,8 +154,7 @@ final AwContents awContents2 = view2.getAwContents(); AwActivityTestRule.enableJavaScriptOnUiThread(awContents2); - InstrumentationRegistry.getInstrumentation().runOnMainSync( - () -> awContents2.addJavascriptInterface(new Test(2), "test")); + AwActivityTestRule.addJavascriptInterfaceOnUiThread(awContents2, new Test(2), "test"); mActivityTestRule.loadDataSync( awContents2, client2.getOnPageFinishedHelper(), html, "text/html", false);
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwNetworkConfigurationTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwNetworkConfigurationTest.java index 4baba6b..84e17af 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwNetworkConfigurationTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwNetworkConfigurationTest.java
@@ -4,8 +4,13 @@ package org.chromium.android_webview.test; +import static org.chromium.android_webview.test.AwActivityTestRule.WAIT_TIMEOUT_MS; + import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; +import android.webkit.JavascriptInterface; + +import com.google.common.util.concurrent.SettableFuture; import org.junit.Assert; import org.junit.Before; @@ -23,6 +28,7 @@ import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.TimeUnit; /** * A test suite for WebView's network-related configuration. This tests WebView's default settings, @@ -194,6 +200,60 @@ } } + @Test + @SmallTest + @Feature({"AndroidWebView", "Network"}) + public void testAccessControlAllowOriginHeader() throws Throwable { + mTestServer = EmbeddedTestServer.createAndStartServer( + InstrumentationRegistry.getInstrumentation().getContext()); + try { + AwActivityTestRule.enableJavaScriptOnUiThread(mAwContents); + + final SettableFuture<Boolean> fetchResultFuture = SettableFuture.create(); + Object injectedObject = new Object() { + @JavascriptInterface + public void success() { + fetchResultFuture.set(true); + } + @JavascriptInterface + public void error() { + fetchResultFuture.set(false); + } + }; + AwActivityTestRule.addJavascriptInterfaceOnUiThread( + mAwContents, injectedObject, "injectedObject"); + + // The test server will add the Access-Control-Allow-Origin header to the HTTP response + // for this resource. We should check WebView correctly respects this. + final String fetchWithAllowOrigin = + mTestServer.getURL("/set-header?Access-Control-Allow-Origin:%20*"); + String html = "<html>" + + " <head>" + + " </head>" + + " <body>" + + " HTML content does not matter." + + " </body>" + + "</html>"; + final String baseUrl = "http://some.origin.test/index.html"; + mActivityTestRule.loadDataWithBaseUrlSync(mAwContents, + mContentsClient.getOnPageFinishedHelper(), html, + /* mimeType */ null, /* isBase64Encoded */ false, baseUrl, + /* historyUrl */ null); + + String script = "fetch('" + fetchWithAllowOrigin + "')" + + " .then(() => { injectedObject.success(); })" + + " .catch(() => { injectedObject.failure(); });"; + mActivityTestRule.executeJavaScriptAndWaitForResult( + mAwContents, mContentsClient, script); + Assert.assertTrue("fetch() should succeed, due to Access-Control-Allow-Origin header", + fetchResultFuture.get(WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS)); + // If we timeout, this indicates the fetch() was erroneously blocked by CORS (as was the + // root cause of https://crbug.com/960165). + } finally { + mTestServer.stopAndDestroyServer(); + } + } + /** * Like {@link AwActivityTestRule#getJavaScriptResultBodyTextContent}, but it gets the text * content of the iframe instead. This assumes the main frame has only a single iframe.
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java index 1eaedee..281c023 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java
@@ -2184,9 +2184,8 @@ + "</body></html>"; // Actual test. Blocking should trigger onerror handler. awSettings.setBlockNetworkLoads(true); - InstrumentationRegistry.getInstrumentation().runOnMainSync( - () -> awContents.addJavascriptInterface(new AudioEvent(callback), - "AudioEvent")); + AwActivityTestRule.addJavascriptInterfaceOnUiThread( + awContents, new AudioEvent(callback), "AudioEvent"); int count = callback.getCallCount(); mActivityTestRule.loadDataSync(awContents, contentClient.getOnPageFinishedHelper(), pageHtml, "text/html", false);
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/PopupWindowTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/PopupWindowTest.java index 074783d..52cebea2 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/PopupWindowTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/PopupWindowTest.java
@@ -115,8 +115,7 @@ } final DummyJavaScriptInterface obj = new DummyJavaScriptInterface(); - InstrumentationRegistry.getInstrumentation().runOnMainSync( - () -> popupContents.addJavascriptInterface(obj, "dummy")); + AwActivityTestRule.addJavascriptInterfaceOnUiThread(popupContents, obj, "dummy"); mActivityTestRule.loadPopupContents(mParentContents, popupInfo, null);
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/PostMessageTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/PostMessageTest.java index 23439a4..fa730c3 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/PostMessageTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/PostMessageTest.java
@@ -138,8 +138,8 @@ AwActivityTestRule.enableJavaScriptOnUiThread(mAwContents); try { - InstrumentationRegistry.getInstrumentation().runOnMainSync( - () -> mAwContents.addJavascriptInterface(mMessageObject, "messageObject")); + AwActivityTestRule.addJavascriptInterfaceOnUiThread( + mAwContents, mMessageObject, "messageObject"); } catch (Throwable t) { throw new RuntimeException(t); }
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 6c24ecc..982009b 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -1017,8 +1017,10 @@ "voice_interaction/voice_interaction_controller.h", "wallpaper/wallpaper_base_view.cc", "wallpaper/wallpaper_base_view.h", - "wallpaper/wallpaper_controller_impl.cc", - "wallpaper/wallpaper_controller_impl.h", + "wallpaper/wallpaper_controller.cc", + "wallpaper/wallpaper_controller.h", + "wallpaper/wallpaper_controller_observer.h", + "wallpaper/wallpaper_info.h", "wallpaper/wallpaper_utils/wallpaper_color_calculator.cc", "wallpaper/wallpaper_utils/wallpaper_color_calculator.h", "wallpaper/wallpaper_utils/wallpaper_color_calculator_observer.h",
diff --git a/ash/accelerators/debug_commands.cc b/ash/accelerators/debug_commands.cc index 0258861e..d161a8b 100644 --- a/ash/accelerators/debug_commands.cc +++ b/ash/accelerators/debug_commands.cc
@@ -11,7 +11,7 @@ #include "ash/system/toast/toast_data.h" #include "ash/system/toast/toast_manager.h" #include "ash/touch/touch_devices_controller.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "ash/wm/window_properties.h" #include "ash/wm/window_state.h" @@ -126,7 +126,8 @@ void HandleToggleWallpaperMode() { static int index = 0; - auto* wallpaper_controller = Shell::Get()->wallpaper_controller(); + WallpaperController* wallpaper_controller = + Shell::Get()->wallpaper_controller(); WallpaperInfo info("", WALLPAPER_LAYOUT_STRETCH, DEFAULT, base::Time::Now().LocalMidnight()); switch (++index % 4) {
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc index 8d54ed8..85cfb96 100644 --- a/ash/app_list/app_list_controller_impl.cc +++ b/ash/app_list/app_list_controller_impl.cc
@@ -35,7 +35,7 @@ #include "ash/shelf/shelf_layout_manager.h" #include "ash/shell.h" #include "ash/voice_interaction/voice_interaction_controller.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "ash/wm/mru_window_tracker.h" #include "ash/wm/overview/overview_controller.h" #include "ash/wm/splitview/split_view_controller.h" @@ -1019,9 +1019,9 @@ client_->StartSearch(base::string16()); } -const std::vector<SkColor>& -AppListControllerImpl::GetWallpaperProminentColors() { - return Shell::Get()->wallpaper_controller()->GetWallpaperColors(); +void AppListControllerImpl::GetWallpaperProminentColors( + GetWallpaperProminentColorsCallback callback) { + Shell::Get()->wallpaper_controller()->GetWallpaperColors(std::move(callback)); } void AppListControllerImpl::ActivateItem(const std::string& id,
diff --git a/ash/app_list/app_list_controller_impl.h b/ash/app_list/app_list_controller_impl.h index 6d4ed88..430fb47 100644 --- a/ash/app_list/app_list_controller_impl.h +++ b/ash/app_list/app_list_controller_impl.h
@@ -25,10 +25,10 @@ #include "ash/public/cpp/app_list/app_list_controller.h" #include "ash/public/cpp/assistant/default_voice_interaction_observer.h" #include "ash/public/cpp/shelf_types.h" -#include "ash/public/cpp/wallpaper_controller_observer.h" #include "ash/public/interfaces/voice_interaction_controller.mojom.h" #include "ash/session/session_observer.h" #include "ash/shell_observer.h" +#include "ash/wallpaper/wallpaper_controller_observer.h" #include "ash/wm/mru_window_tracker.h" #include "ash/wm/overview/overview_observer.h" #include "ash/wm/tablet_mode/tablet_mode_observer.h" @@ -176,7 +176,8 @@ void ViewShown(int64_t display_id) override; void ViewClosing() override; void ViewClosed() override; - const std::vector<SkColor>& GetWallpaperProminentColors() override; + void GetWallpaperProminentColors( + GetWallpaperProminentColorsCallback callback) override; void ActivateItem(const std::string& id, int event_flags, AppListLaunchedFrom launched_from) override;
diff --git a/ash/app_list/app_list_view_delegate.h b/ash/app_list/app_list_view_delegate.h index e59ed53..64542f4e 100644 --- a/ash/app_list/app_list_view_delegate.h +++ b/ash/app_list/app_list_view_delegate.h
@@ -110,7 +110,10 @@ virtual void ViewClosed() = 0; // Gets the wallpaper prominent colors. - virtual const std::vector<SkColor>& GetWallpaperProminentColors() = 0; + using GetWallpaperProminentColorsCallback = + base::OnceCallback<void(const std::vector<SkColor>&)>; + virtual void GetWallpaperProminentColors( + GetWallpaperProminentColorsCallback callback) = 0; // Activates (opens) the item. virtual void ActivateItem(const std::string& id,
diff --git a/ash/app_list/test/app_list_test_view_delegate.cc b/ash/app_list/test/app_list_test_view_delegate.cc index 958d5fe..af1a553 100644 --- a/ash/app_list/test/app_list_test_view_delegate.cc +++ b/ash/app_list/test/app_list_test_view_delegate.cc
@@ -83,11 +83,6 @@ search_model_->SetSearchEngineIsGoogle(is_google); } -const std::vector<SkColor>& -AppListTestViewDelegate::GetWallpaperProminentColors() { - return wallpaper_prominent_colors_; -} - void AppListTestViewDelegate::ActivateItem( const std::string& id, int event_flags,
diff --git a/ash/app_list/test/app_list_test_view_delegate.h b/ash/app_list/test/app_list_test_view_delegate.h index 9eb472f0..7919d45 100644 --- a/ash/app_list/test/app_list_test_view_delegate.h +++ b/ash/app_list/test/app_list_test_view_delegate.h
@@ -80,7 +80,8 @@ void DismissAppList() override; void ViewClosing() override {} void ViewClosed() override {} - const std::vector<SkColor>& GetWallpaperProminentColors() override; + void GetWallpaperProminentColors( + GetWallpaperProminentColorsCallback callback) override {} void ActivateItem(const std::string& id, int event_flags, ash::AppListLaunchedFrom launched_from) override;
diff --git a/ash/app_list/views/app_list_view.cc b/ash/app_list/views/app_list_view.cc index 6eaa211..4174ff0 100644 --- a/ash/app_list/views/app_list_view.cc +++ b/ash/app_list/views/app_list_view.cc
@@ -23,6 +23,7 @@ #include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/public/cpp/wallpaper_types.h" +#include "base/bind.h" #include "base/macros.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" @@ -130,20 +131,21 @@ DISALLOW_COPY_AND_ASSIGN(SearchBoxFocusHost); }; -SkColor GetBackgroundShieldColor(const std::vector<SkColor>& colors, +SkColor GetBackgroundShieldColor(const std::vector<SkColor>& prominent_colors, float color_opacity) { const U8CPU sk_opacity_value = static_cast<U8CPU>(255 * color_opacity); const SkColor default_color = SkColorSetA( app_list::AppListView::kDefaultBackgroundColor, sk_opacity_value); - if (colors.empty()) + if (prominent_colors.empty()) return default_color; DCHECK_EQ(static_cast<size_t>(ColorProfileType::NUM_OF_COLOR_PROFILES), - colors.size()); + prominent_colors.size()); + const SkColor dark_muted = - colors[static_cast<int>(ColorProfileType::DARK_MUTED)]; + prominent_colors[static_cast<int>(ColorProfileType::DARK_MUTED)]; if (SK_ColorTRANSPARENT == dark_muted) return default_color; @@ -1989,6 +1991,11 @@ return coefficient * shield_opacity + (1 - coefficient) * shelf_opacity; } +void AppListView::GetWallpaperProminentColors( + AppListViewDelegate::GetWallpaperProminentColorsCallback callback) { + delegate_->GetWallpaperProminentColors(std::move(callback)); +} + void AppListView::SetBackgroundShieldColor() { // There is a chance when AppListView::OnWallpaperColorsChanged is called // from AppListViewDelegate, the |app_list_background_shield_| is not @@ -2011,8 +2018,13 @@ color_opacity = kAppListOpacityWithBlur; } - app_list_background_shield_->UpdateColor(GetBackgroundShieldColor( - delegate_->GetWallpaperProminentColors(), color_opacity)); + GetWallpaperProminentColors(base::BindOnce( + [](base::WeakPtr<AppListView> self, float color_opacity, + const std::vector<SkColor>& prominent_colors) { + self->app_list_background_shield_->UpdateColor( + GetBackgroundShieldColor(prominent_colors, color_opacity)); + }, + weak_ptr_factory_.GetWeakPtr(), color_opacity)); } void AppListView::RecordFolderMetrics() {
diff --git a/ash/app_list/views/app_list_view.h b/ash/app_list/views/app_list_view.h index 3e6d166..133d1c3 100644 --- a/ash/app_list/views/app_list_view.h +++ b/ash/app_list/views/app_list_view.h
@@ -411,7 +411,8 @@ // Gets app list background opacity during dragging. float GetAppListBackgroundOpacityDuringDragging(); - const std::vector<SkColor>& GetWallpaperProminentColors(); + void GetWallpaperProminentColors( + AppListViewDelegate::GetWallpaperProminentColorsCallback callback); void SetBackgroundShieldColor(); // Records the number of folders, and the number of items in folders for UMA
diff --git a/ash/app_list/views/search_box_view.cc b/ash/app_list/views/search_box_view.cc index 379a2b3..bd53841a 100644 --- a/ash/app_list/views/search_box_view.cc +++ b/ash/app_list/views/search_box_view.cc
@@ -396,18 +396,9 @@ } void SearchBoxView::OnWallpaperColorsChanged() { - const auto& colors = view_delegate_->GetWallpaperProminentColors(); - if (colors.empty()) - return; - - DCHECK_EQ(static_cast<size_t>(ColorProfileType::NUM_OF_COLOR_PROFILES), - colors.size()); - - SetSearchBoxColor(colors[static_cast<int>(ColorProfileType::DARK_MUTED)]); - UpdateSearchIcon(); - search_box()->set_placeholder_text_color(search_box_color()); - UpdateBackgroundColor(search_box::kSearchBoxBackgroundDefault); - SchedulePaint(); + GetWallpaperProminentColors( + base::BindOnce(&SearchBoxView::OnWallpaperProminentColorsReceived, + weak_ptr_factory_.GetWeakPtr())); } void SearchBoxView::ProcessAutocomplete() { @@ -448,6 +439,26 @@ ClearAutocompleteText(); } +void SearchBoxView::GetWallpaperProminentColors( + AppListViewDelegate::GetWallpaperProminentColorsCallback callback) { + view_delegate_->GetWallpaperProminentColors(std::move(callback)); +} + +void SearchBoxView::OnWallpaperProminentColorsReceived( + const std::vector<SkColor>& prominent_colors) { + if (prominent_colors.empty()) + return; + DCHECK_EQ(static_cast<size_t>(ColorProfileType::NUM_OF_COLOR_PROFILES), + prominent_colors.size()); + + SetSearchBoxColor( + prominent_colors[static_cast<int>(ColorProfileType::DARK_MUTED)]); + UpdateSearchIcon(); + search_box()->set_placeholder_text_color(search_box_color()); + UpdateBackgroundColor(search_box::kSearchBoxBackgroundDefault); + SchedulePaint(); +} + void SearchBoxView::AcceptAutocompleteText() { if (!ShouldProcessAutocomplete()) return;
diff --git a/ash/app_list/views/search_box_view.h b/ash/app_list/views/search_box_view.h index 2af523e..5198637 100644 --- a/ash/app_list/views/search_box_view.h +++ b/ash/app_list/views/search_box_view.h
@@ -109,6 +109,15 @@ } private: + // Gets the wallpaper prominent colors. + void GetWallpaperProminentColors( + AppListViewDelegate::GetWallpaperProminentColorsCallback callback); + + // Callback invoked when the wallpaper prominent colors are returned after + // calling |AppListViewDelegate::GetWallpaperProminentColors|. + void OnWallpaperProminentColorsReceived( + const std::vector<SkColor>& prominent_colors); + // Notifies SearchBoxViewDelegate that the autocomplete text is valid. void AcceptAutocompleteText();
diff --git a/ash/ash_prefs.cc b/ash/ash_prefs.cc index ade78c0e..5f55958 100644 --- a/ash/ash_prefs.cc +++ b/ash/ash_prefs.cc
@@ -23,7 +23,7 @@ #include "ash/system/power/power_prefs.h" #include "ash/system/session/logout_button_tray.h" #include "ash/touch/touch_devices_controller.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" namespace ash { @@ -53,7 +53,7 @@ void RegisterLocalStatePrefs(PrefRegistrySimple* registry, bool for_test) { PaletteTray::RegisterLocalStatePrefs(registry); - WallpaperControllerImpl::RegisterLocalStatePrefs(registry); + WallpaperController::RegisterLocalStatePrefs(registry); BluetoothPowerController::RegisterLocalStatePrefs(registry); DetachableBaseHandler::RegisterPrefs(registry); PowerPrefs::RegisterLocalStatePrefs(registry);
diff --git a/ash/frame/non_client_frame_view_ash.cc b/ash/frame/non_client_frame_view_ash.cc index a14f00ce..323cce96 100644 --- a/ash/frame/non_client_frame_view_ash.cc +++ b/ash/frame/non_client_frame_view_ash.cc
@@ -146,9 +146,6 @@ DISALLOW_COPY_AND_ASSIGN(NonClientFrameViewAshImmersiveHelper); }; -// static -bool NonClientFrameViewAsh::use_empty_minimum_size_for_test_ = false; - /////////////////////////////////////////////////////////////////////////////// // NonClientFrameViewAsh::OverlayView @@ -380,7 +377,7 @@ } gfx::Size NonClientFrameViewAsh::GetMinimumSize() const { - if (use_empty_minimum_size_for_test_ || !GetEnabled()) + if (!GetEnabled()) return gfx::Size(); gfx::Size min_client_view_size(frame_->client_view()->GetMinimumSize());
diff --git a/ash/frame/non_client_frame_view_ash.h b/ash/frame/non_client_frame_view_ash.h index 71e78fb48..2656e57 100644 --- a/ash/frame/non_client_frame_view_ash.h +++ b/ash/frame/non_client_frame_view_ash.h
@@ -118,12 +118,6 @@ views::Widget* frame() { return frame_; } - // Methods for testing. - static void set_use_empty_minimum_size_for_test( - bool use_empty_minimum_size_for_test) { - use_empty_minimum_size_for_test_ = use_empty_minimum_size_for_test; - } - protected: // Called when overview mode or split view state changed. If overview mode // and split view mode are both active at the same time, the header of the @@ -133,7 +127,6 @@ private: class OverlayView; - friend class NonClientFrameViewAshSizeLock; friend class NonClientFrameViewAshTestWidgetDelegate; friend class TestWidgetConstraintsDelegate; friend class WindowServiceDelegateImplTest; @@ -157,8 +150,6 @@ OverlayView* overlay_view_ = nullptr; - static bool use_empty_minimum_size_for_test_; - // Track whether the device is in overview mode. Set this to true when // overview mode started and false when overview mode finished. Use this to // check whether we should paint when splitview state changes instead of
diff --git a/ash/highlighter/highlighter_controller.cc b/ash/highlighter/highlighter_controller.cc index 9d58217..4bff6bf 100644 --- a/ash/highlighter/highlighter_controller.cc +++ b/ash/highlighter/highlighter_controller.cc
@@ -59,8 +59,7 @@ } // namespace -HighlighterController::HighlighterController() - : binding_(this), weak_factory_(this) { +HighlighterController::HighlighterController() : weak_factory_(this) { Shell::Get()->AddPreTargetHandler(this); } @@ -100,19 +99,6 @@ UpdateEnabledState(HighlighterEnabledState::kDisabledBySessionAbort); } -void HighlighterController::BindRequest( - mojom::HighlighterControllerRequest request) { - binding_.Bind(std::move(request)); -} - -void HighlighterController::SetClient( - mojom::HighlighterControllerClientPtr client) { - client_ = std::move(client); - client_.set_connection_error_handler( - base::BindOnce(&HighlighterController::OnClientConnectionLost, - weak_factory_.GetWeakPtr())); -} - void HighlighterController::SetEnabled(bool enabled) { FastInkPointerController::SetEnabled(enabled); if (enabled) { @@ -132,13 +118,6 @@ if (highlighter_view_ && !highlighter_view_->animating()) DestroyPointerView(); } - - if (client_) - client_->HandleEnabledStateChange(enabled); -} - -void HighlighterController::ExitHighlighterMode() { - CallExitCallback(); } views::View* HighlighterController::GetPointerView() const { @@ -241,9 +220,6 @@ ? gfx::ToEnclosingRect(box) : gfx::ToEnclosingRect( gfx::ScaleRect(box, GetScreenshotScale(current_window))); - if (client_) - client_->HandleSelection(selection_rect); - for (auto& observer : observers_) observer.OnHighlighterSelectionRecognized(selection_rect); @@ -302,21 +278,9 @@ result_view_.reset(); } -void HighlighterController::OnClientConnectionLost() { - client_.reset(); - binding_.Close(); - // The client has detached, force-exit the highlighter mode. - CallExitCallback(); -} - void HighlighterController::CallExitCallback() { if (!exit_callback_.is_null()) std::move(exit_callback_).Run(); } -void HighlighterController::FlushMojoForTesting() { - if (client_) - client_.FlushForTesting(); -} - } // namespace ash
diff --git a/ash/highlighter/highlighter_controller.h b/ash/highlighter/highlighter_controller.h index 4267dd6f..21ec70a2 100644 --- a/ash/highlighter/highlighter_controller.h +++ b/ash/highlighter/highlighter_controller.h
@@ -9,16 +9,18 @@ #include "ash/ash_export.h" #include "ash/components/fast_ink/fast_ink_pointer_controller.h" -#include "ash/public/interfaces/highlighter_controller.mojom.h" #include "base/callback.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" -#include "mojo/public/cpp/bindings/binding.h" namespace base { class OneShotTimer; } +namespace gfx { +class Rect; +} + namespace ash { class HighlighterResultView; @@ -42,8 +44,7 @@ // Enables/disables highlighter as well as receives points // and passes them off to be rendered. class ASH_EXPORT HighlighterController - : public fast_ink::FastInkPointerController, - public mojom::HighlighterController { + : public fast_ink::FastInkPointerController { public: // Interface for classes that wish to be notified with highlighter status. class Observer { @@ -79,12 +80,6 @@ // calling this method is a no-op. void AbortSession(); - void BindRequest(mojom::HighlighterControllerRequest request); - - // mojom::HighlighterController: - void SetClient(mojom::HighlighterControllerClientPtr client) override; - void ExitHighlighterMode() override; - private: friend class HighlighterControllerTestApi; @@ -107,14 +102,9 @@ // Destroys |result_view_|, if it exists. void DestroyResultView(); - // Called when the mojo connection with the client is closed. - void OnClientConnectionLost(); - // Calls and clears the mode exit callback, if it is set. void CallExitCallback(); - void FlushMojoForTesting(); - // Caches the highlighter enabled state. HighlighterEnabledState enabled_state_ = HighlighterEnabledState::kDisabledByUser; @@ -151,12 +141,6 @@ // If true, the mode is not exited until a valid selection is made. bool require_success_ = true; - // Binding for mojom::HighlighterController interface. - mojo::Binding<ash::mojom::HighlighterController> binding_; - - // Interface to highlighter controller client (chrome). - mojom::HighlighterControllerClientPtr client_; - base::ObserverList<Observer>::Unchecked observers_; base::WeakPtrFactory<HighlighterController> weak_factory_;
diff --git a/ash/highlighter/highlighter_controller_test_api.cc b/ash/highlighter/highlighter_controller_test_api.cc index 89a7b77..1a49dbb 100644 --- a/ash/highlighter/highlighter_controller_test_api.cc +++ b/ash/highlighter/highlighter_controller_test_api.cc
@@ -13,12 +13,12 @@ HighlighterControllerTestApi::HighlighterControllerTestApi( HighlighterController* instance) - : binding_(this), instance_(instance) { + : instance_(instance) { AttachClient(); } HighlighterControllerTestApi::~HighlighterControllerTestApi() { - if (binding_.is_bound()) + if (scoped_observer_) DetachClient(); if (instance_->enabled()) instance_->SetEnabled(false); @@ -26,25 +26,19 @@ } void HighlighterControllerTestApi::AttachClient() { - DCHECK(!binding_.is_bound()); - DCHECK(!highlighter_controller_); - instance_->BindRequest(mojo::MakeRequest(&highlighter_controller_)); - ash::mojom::HighlighterControllerClientPtr client; - binding_.Bind(mojo::MakeRequest(&client)); - highlighter_controller_->SetClient(std::move(client)); - highlighter_controller_.FlushForTesting(); + scoped_observer_ = std::make_unique<ScopedObserver>(this); + scoped_observer_->Add(instance_); } void HighlighterControllerTestApi::DetachClient() { - DCHECK(binding_.is_bound()); - DCHECK(highlighter_controller_); - highlighter_controller_ = nullptr; - binding_.Close(); - instance_->FlushMojoForTesting(); + scoped_observer_.reset(); + instance_->CallExitCallback(); } void HighlighterControllerTestApi::SetEnabled(bool enabled) { - instance_->SetEnabled(enabled); + instance_->UpdateEnabledState( + enabled ? HighlighterEnabledState::kEnabled + : HighlighterEnabledState::kDisabledBySessionComplete); } void HighlighterControllerTestApi::DestroyPointerView() { @@ -85,21 +79,22 @@ } bool HighlighterControllerTestApi::HandleEnabledStateChangedCalled() { - instance_->FlushMojoForTesting(); return handle_enabled_state_changed_called_; } bool HighlighterControllerTestApi::HandleSelectionCalled() { - instance_->FlushMojoForTesting(); return handle_selection_called_; } -void HighlighterControllerTestApi::HandleSelection(const gfx::Rect& rect) { +void HighlighterControllerTestApi::OnHighlighterSelectionRecognized( + const gfx::Rect& rect) { handle_selection_called_ = true; selection_ = rect; } -void HighlighterControllerTestApi::HandleEnabledStateChange(bool enabled) { +void HighlighterControllerTestApi::OnHighlighterEnabledChanged( + HighlighterEnabledState state) { + const bool enabled = (state == HighlighterEnabledState::kEnabled); handle_enabled_state_changed_called_ = true; enabled_ = enabled; }
diff --git a/ash/highlighter/highlighter_controller_test_api.h b/ash/highlighter/highlighter_controller_test_api.h index 8349d32..b5fbedd 100644 --- a/ash/highlighter/highlighter_controller_test_api.h +++ b/ash/highlighter/highlighter_controller_test_api.h
@@ -5,9 +5,9 @@ #ifndef ASH_HIGHLIGHTER_HIGHLIGHTER_CONTROLLER_TEST_API_H_ #define ASH_HIGHLIGHTER_HIGHLIGHTER_CONTROLLER_TEST_API_H_ -#include "ash/public/interfaces/highlighter_controller.mojom.h" +#include "ash/highlighter/highlighter_controller.h" #include "base/macros.h" -#include "mojo/public/cpp/bindings/binding.h" +#include "base/scoped_observer.h" #include "ui/gfx/geometry/rect.h" namespace fast_ink { @@ -16,13 +16,11 @@ namespace ash { -class HighlighterController; - // An api for testing the HighlighterController class. // Implements ash::mojom::HighlighterControllerClient and binds itself as the // client to provide the tests with access to gesture recognition results. class HighlighterControllerTestApi - : public ash::mojom::HighlighterControllerClient { + : public ash::HighlighterController::Observer { public: explicit HighlighterControllerTestApi(HighlighterController* instance); ~HighlighterControllerTestApi() override; @@ -46,28 +44,22 @@ const fast_ink::FastInkPoints& predicted_points() const; void ResetEnabledState() { handle_enabled_state_changed_called_ = false; } - // Flushes the mojo connection, then checks whether HandleEnabledStateChange - // has been called on the client since the last call to ResetEnabledState. bool HandleEnabledStateChangedCalled(); bool enabled() const { return enabled_; } void ResetSelection() { handle_selection_called_ = false; } - // Flushes the mojo connection, then checks whether HandleSelection - // has been called on the client since the last call to ResetSelection. bool HandleSelectionCalled(); const gfx::Rect& selection() const { return selection_; } private: + using ScopedObserver = + ScopedObserver<HighlighterController, HighlighterController::Observer>; + // HighlighterSelectionObserver: - void HandleSelection(const gfx::Rect& rect) override; - void HandleEnabledStateChange(bool enabled) override; + void OnHighlighterSelectionRecognized(const gfx::Rect& rect) override; + void OnHighlighterEnabledChanged(HighlighterEnabledState state) override; - // Binds to the client interface. - mojo::Binding<ash::mojom::HighlighterControllerClient> binding_; - - // HighlighterController interface. - ash::mojom::HighlighterControllerPtr highlighter_controller_; - + std::unique_ptr<ScopedObserver> scoped_observer_; HighlighterController* instance_; bool handle_selection_called_ = false;
diff --git a/ash/home_screen/home_screen_controller.cc b/ash/home_screen/home_screen_controller.cc index 77d46ea6..e436114 100644 --- a/ash/home_screen/home_screen_controller.cc +++ b/ash/home_screen/home_screen_controller.cc
@@ -10,7 +10,7 @@ #include "ash/session/session_controller_impl.h" #include "ash/shelf/shelf.h" #include "ash/shell.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "ash/wm/mru_window_tracker.h" #include "ash/wm/overview/overview_controller.h" #include "ash/wm/overview/overview_session.h"
diff --git a/ash/home_screen/home_screen_controller.h b/ash/home_screen/home_screen_controller.h index fb6469b..ca51256 100644 --- a/ash/home_screen/home_screen_controller.h +++ b/ash/home_screen/home_screen_controller.h
@@ -9,7 +9,7 @@ #include "ash/ash_export.h" #include "ash/home_screen/home_screen_presenter.h" -#include "ash/public/cpp/wallpaper_controller_observer.h" +#include "ash/wallpaper/wallpaper_controller_observer.h" #include "ash/wm/overview/overview_observer.h" #include "base/macros.h"
diff --git a/ash/login/login_screen_controller.cc b/ash/login/login_screen_controller.cc index a1c241c..3c2ea1f 100644 --- a/ash/login/login_screen_controller.cc +++ b/ash/login/login_screen_controller.cc
@@ -334,14 +334,6 @@ NOTIMPLEMENTED(); } -void LoginScreenController::ShowWarningBanner(const base::string16& message) { - login_data_dispatcher_.ShowWarningBanner(message); -} - -void LoginScreenController::HideWarningBanner() { - login_data_dispatcher_.HideWarningBanner(); -} - void LoginScreenController::ClearErrors() { NOTIMPLEMENTED(); }
diff --git a/ash/login/login_screen_controller.h b/ash/login/login_screen_controller.h index 4e5059077..6f2165c 100644 --- a/ash/login/login_screen_controller.h +++ b/ash/login/login_screen_controller.h
@@ -118,8 +118,6 @@ const std::string& error_text, const std::string& help_link_text, int32_t help_topic_id) override; - void ShowWarningBanner(const base::string16& message) override; - void HideWarningBanner() override; void ClearErrors() override; void SetAuthType(const AccountId& account_id, proximity_auth::mojom::AuthType auth_type,
diff --git a/ash/login/login_screen_controller_unittest.cc b/ash/login/login_screen_controller_unittest.cc index d4c93af..abac013 100644 --- a/ash/login/login_screen_controller_unittest.cc +++ b/ash/login/login_screen_controller_unittest.cc
@@ -15,7 +15,7 @@ #include "ash/system/tray/system_tray_notifier.h" #include "ash/system/unified/unified_system_tray.h" #include "ash/test/ash_test_base.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "base/bind.h" #include "base/run_loop.h" #include "base/test/bind_test_util.h"
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc index 75e8c83..8aa4961 100644 --- a/ash/login/ui/lock_contents_view.cc +++ b/ash/login/ui/lock_contents_view.cc
@@ -874,13 +874,19 @@ } } -void LockContentsView::OnShowWarningBanner(const base::string16& message) { - DCHECK(!message.empty()); +void LockContentsView::OnWarningMessageUpdated(const base::string16& message) { + if (message.empty()) { + if (warning_banner_bubble_->GetVisible()) + warning_banner_bubble_->Hide(); + return; + } + if (!CurrentBigUserView() || !CurrentBigUserView()->auth_user()) { LOG(ERROR) << "Unable to find the current active big user to show a " "warning banner."; return; } + if (warning_banner_bubble_->GetVisible()) warning_banner_bubble_->Hide(); // Shows warning banner as a persistent error bubble. @@ -898,11 +904,6 @@ warning_banner_bubble_->Show(); } -void LockContentsView::OnHideWarningBanner() { - if (warning_banner_bubble_->GetVisible()) - warning_banner_bubble_->Hide(); -} - void LockContentsView::OnLockScreenNoteStateChanged( mojom::TrayActionState state) { if (disable_lock_screen_note_)
diff --git a/ash/login/ui/lock_contents_view.h b/ash/login/ui/lock_contents_view.h index d0a0d017..10cc494e 100644 --- a/ash/login/ui/lock_contents_view.h +++ b/ash/login/ui/lock_contents_view.h
@@ -152,8 +152,7 @@ void OnForceOnlineSignInForUser(const AccountId& user) override; void OnShowEasyUnlockIcon(const AccountId& user, const EasyUnlockIconOptions& icon) override; - void OnShowWarningBanner(const base::string16& message) override; - void OnHideWarningBanner() override; + void OnWarningMessageUpdated(const base::string16& message) override; void OnSystemInfoChanged(bool show, const std::string& os_version_label_text, const std::string& enterprise_info_text,
diff --git a/ash/login/ui/lock_contents_view_unittest.cc b/ash/login/ui/lock_contents_view_unittest.cc index 0c0b2c4f..54e0a97 100644 --- a/ash/login/ui/lock_contents_view_unittest.cc +++ b/ash/login/ui/lock_contents_view_unittest.cc
@@ -2167,15 +2167,15 @@ EXPECT_FALSE(test_api.warning_banner_bubble()->GetVisible()); // Verifies that a warning banner is shown by giving a non-empty message. - DataDispatcher()->ShowWarningBanner(base::ASCIIToUTF16("foo")); + DataDispatcher()->UpdateWarningMessage(base::ASCIIToUTF16("foo")); EXPECT_TRUE(test_api.warning_banner_bubble()->GetVisible()); // Verifies that a warning banner is hidden by HideWarningBanner(). - DataDispatcher()->HideWarningBanner(); + DataDispatcher()->UpdateWarningMessage({}); EXPECT_FALSE(test_api.warning_banner_bubble()->GetVisible()); // Shows a warning banner again. - DataDispatcher()->ShowWarningBanner(base::ASCIIToUTF16("foo")); + DataDispatcher()->UpdateWarningMessage(base::ASCIIToUTF16("foo")); EXPECT_TRUE(test_api.warning_banner_bubble()->GetVisible()); // Attempt and fail user auth - an auth error is expected to be shown.
diff --git a/ash/login/ui/lock_debug_view.cc b/ash/login/ui/lock_debug_view.cc index b24f61f..91915f34 100644 --- a/ash/login/ui/lock_debug_view.cc +++ b/ash/login/ui/lock_debug_view.cc
@@ -24,7 +24,7 @@ #include "ash/shelf/shelf.h" #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "base/bind.h" #include "base/memory/ptr_util.h" #include "base/optional.h" @@ -436,12 +436,10 @@ enterprise_info, bluetooth_name); } - void ShowWarningBanner(const base::string16& message) { - debug_dispatcher_.ShowWarningBanner(message); + void UpdateWarningMessage(const base::string16& message) { + debug_dispatcher_.UpdateWarningMessage(message); } - void HideWarningBanner() { debug_dispatcher_.HideWarningBanner(); } - // LoginDataDispatcher::Observer: void OnUsersChanged(const std::vector<LoginUserInfo>& users) override { // Update root_users_ to new source data. @@ -975,9 +973,9 @@ // Show or hide warning banner. if (sender->GetID() == ButtonId::kGlobalToggleWarningBanner) { if (is_warning_banner_shown_) { - debug_data_dispatcher_->HideWarningBanner(); + debug_data_dispatcher_->UpdateWarningMessage({}); } else { - debug_data_dispatcher_->ShowWarningBanner(base::ASCIIToUTF16( + debug_data_dispatcher_->UpdateWarningMessage(base::ASCIIToUTF16( "A critical update is ready to install. Sign in to get started.")); } is_warning_banner_shown_ = !is_warning_banner_shown_;
diff --git a/ash/login/ui/lock_screen.cc b/ash/login/ui/lock_screen.cc index 7eedb40..4bf83d4 100644 --- a/ash/login/ui/lock_screen.cc +++ b/ash/login/ui/lock_screen.cc
@@ -18,7 +18,7 @@ #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/tray_action/tray_action.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "base/bind.h" #include "base/command_line.h" #include "chromeos/constants/chromeos_switches.h"
diff --git a/ash/login/ui/login_auth_user_view.cc b/ash/login/ui/login_auth_user_view.cc index 93e6284c..72f2388 100644 --- a/ash/login/ui/login_auth_user_view.cc +++ b/ash/login/ui/login_auth_user_view.cc
@@ -24,7 +24,7 @@ #include "ash/strings/grit/ash_strings.h" #include "ash/system/night_light/time_of_day.h" #include "ash/system/toast/toast_manager.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "base/bind.h" #include "base/i18n/time_formatting.h" #include "base/strings/utf_string_conversions.h"
diff --git a/ash/login/ui/login_big_user_view.cc b/ash/login/ui/login_big_user_view.cc index c1e4a105..80afdbf2 100644 --- a/ash/login/ui/login_big_user_view.cc +++ b/ash/login/ui/login_big_user_view.cc
@@ -5,7 +5,7 @@ #include "ash/login/ui/login_big_user_view.h" #include "ash/public/cpp/login_constants.h" #include "ash/shell.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "components/account_id/account_id.h" #include "ui/views/background.h" #include "ui/views/layout/fill_layout.h"
diff --git a/ash/login/ui/login_big_user_view.h b/ash/login/ui/login_big_user_view.h index daeda31..4ac774fb 100644 --- a/ash/login/ui/login_big_user_view.h +++ b/ash/login/ui/login_big_user_view.h
@@ -12,7 +12,7 @@ #include "ash/login/ui/non_accessible_view.h" #include "ash/login/ui/parent_access_view.h" #include "ash/public/cpp/session/user_info.h" -#include "ash/public/cpp/wallpaper_controller_observer.h" +#include "ash/wallpaper/wallpaper_controller_observer.h" namespace ash {
diff --git a/ash/login/ui/login_data_dispatcher.cc b/ash/login/ui/login_data_dispatcher.cc index b5070c0e..587e1a7 100644 --- a/ash/login/ui/login_data_dispatcher.cc +++ b/ash/login/ui/login_data_dispatcher.cc
@@ -48,11 +48,9 @@ const AccountId& user, const EasyUnlockIconOptions& icon) {} -void LoginDataDispatcher::Observer::OnShowWarningBanner( +void LoginDataDispatcher::Observer::OnWarningMessageUpdated( const base::string16& message) {} -void LoginDataDispatcher::Observer::OnHideWarningBanner() {} - void LoginDataDispatcher::Observer::OnSystemInfoChanged( bool show, const std::string& os_version_label_text, @@ -167,14 +165,9 @@ observer.OnShowEasyUnlockIcon(user, icon); } -void LoginDataDispatcher::ShowWarningBanner(const base::string16& message) { +void LoginDataDispatcher::UpdateWarningMessage(const base::string16& message) { for (auto& observer : observers_) - observer.OnShowWarningBanner(message); -} - -void LoginDataDispatcher::HideWarningBanner() { - for (auto& observer : observers_) - observer.OnHideWarningBanner(); + observer.OnWarningMessageUpdated(message); } void LoginDataDispatcher::SetSystemInfo(
diff --git a/ash/login/ui/login_data_dispatcher.h b/ash/login/ui/login_data_dispatcher.h index c943ced..761b517 100644 --- a/ash/login/ui/login_data_dispatcher.h +++ b/ash/login/ui/login_data_dispatcher.h
@@ -86,11 +86,9 @@ virtual void OnShowEasyUnlockIcon(const AccountId& user, const EasyUnlockIconOptions& icon); - // Called when a warning banner message should be displayed. - virtual void OnShowWarningBanner(const base::string16& message); - - // Called when a warning banner message should be hidden. - virtual void OnHideWarningBanner(); + // Called when a warning message should be displayed, or hidden if |message| + // is empty. + virtual void OnWarningMessageUpdated(const base::string16& message); // Called when the system info has changed. virtual void OnSystemInfoChanged(bool show, @@ -168,8 +166,7 @@ void SetLockScreenNoteState(mojom::TrayActionState state); void ShowEasyUnlockIcon(const AccountId& user, const EasyUnlockIconOptions& icon) override; - void ShowWarningBanner(const base::string16& message); - void HideWarningBanner(); + void UpdateWarningMessage(const base::string16& message) override; void SetSystemInfo(bool show_if_hidden, const std::string& os_version_label_text, const std::string& enterprise_info_text,
diff --git a/ash/login/ui/login_keyboard_test_base.cc b/ash/login/ui/login_keyboard_test_base.cc index c4cd4bcb..f4f87cc 100644 --- a/ash/login/ui/login_keyboard_test_base.cc +++ b/ash/login/ui/login_keyboard_test_base.cc
@@ -15,6 +15,7 @@ #include "ash/root_window_controller.h" #include "ash/session/test_session_controller_client.h" #include "ash/shell.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "base/command_line.h" #include "base/strings/strcat.h"
diff --git a/ash/login/ui/login_test_base.cc b/ash/login/ui/login_test_base.cc index 86c34440..ab14fc2 100644 --- a/ash/login/ui/login_test_base.cc +++ b/ash/login/ui/login_test_base.cc
@@ -13,7 +13,7 @@ #include "ash/public/interfaces/tray_action.mojom.h" #include "ash/session/test_session_controller_client.h" #include "ash/shell.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "base/bind.h" #include "base/strings/strcat.h" #include "ui/views/widget/widget.h"
diff --git a/ash/login/ui/parent_access_view.cc b/ash/login/ui/parent_access_view.cc index 61ef1676..af1d35b 100644 --- a/ash/login/ui/parent_access_view.cc +++ b/ash/login/ui/parent_access_view.cc
@@ -15,7 +15,7 @@ #include "ash/resources/vector_icons/vector_icons.h" #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "base/bind.h" #include "base/logging.h" #include "base/optional.h"
diff --git a/ash/login/ui/scrollable_users_list_view.cc b/ash/login/ui/scrollable_users_list_view.cc index a7fddacf..76b2a02 100644 --- a/ash/login/ui/scrollable_users_list_view.cc +++ b/ash/login/ui/scrollable_users_list_view.cc
@@ -13,7 +13,7 @@ #include "ash/login/ui/views_utils.h" #include "ash/public/cpp/login_constants.h" #include "ash/shell.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "base/bind.h" #include "base/numerics/ranges.h" #include "base/timer/timer.h" @@ -387,7 +387,7 @@ // Only draw a gradient if the wallpaper is blurred. Otherwise, draw a rounded // rectangle. - if (Shell::Get()->wallpaper_controller()->IsWallpaperBlurred()) { + if (ash::Shell::Get()->wallpaper_controller()->IsWallpaperBlurred()) { cc::PaintFlags flags; // Only draw a gradient if the content can be scrolled.
diff --git a/ash/login/ui/scrollable_users_list_view.h b/ash/login/ui/scrollable_users_list_view.h index 6a4637f5..5e0e9e0 100644 --- a/ash/login/ui/scrollable_users_list_view.h +++ b/ash/login/ui/scrollable_users_list_view.h
@@ -10,7 +10,7 @@ #include "ash/ash_export.h" #include "ash/login/ui/login_display_style.h" #include "ash/login/ui/login_user_view.h" -#include "ash/public/cpp/wallpaper_controller_observer.h" +#include "ash/wallpaper/wallpaper_controller_observer.h" #include "base/scoped_observer.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/views/controls/scroll_view.h" @@ -97,7 +97,8 @@ GradientParams gradient_params_; - ScopedObserver<WallpaperController, ScrollableUsersListView> observer_{this}; + ScopedObserver<WallpaperController, WallpaperControllerObserver> observer_{ + this}; DISALLOW_COPY_AND_ASSIGN(ScrollableUsersListView); };
diff --git a/ash/mojo_interface_factory.cc b/ash/mojo_interface_factory.cc index ffde7009..8a4a08a 100644 --- a/ash/mojo_interface_factory.cc +++ b/ash/mojo_interface_factory.cc
@@ -17,7 +17,6 @@ #include "ash/autotest/shelf_integration_test_api.h" #include "ash/display/cros_display_config.h" #include "ash/events/event_rewriter_controller.h" -#include "ash/highlighter/highlighter_controller.h" #include "ash/ime/ime_controller.h" #include "ash/keyboard/ash_keyboard_controller.h" #include "ash/keyboard/ui/keyboard_controller.h" @@ -35,6 +34,7 @@ #include "ash/system/night_light/night_light_controller.h" #include "ash/tray_action/tray_action.h" #include "ash/voice_interaction/voice_interaction_controller.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "base/bind.h" #include "base/command_line.h" @@ -111,11 +111,6 @@ Shell::Get()->event_rewriter_controller()->BindRequest(std::move(request)); } -void BindHighlighterControllerRequestOnMainThread( - mojom::HighlighterControllerRequest request) { - Shell::Get()->highlighter_controller()->BindRequest(std::move(request)); -} - void BindImeControllerRequestOnMainThread(mojom::ImeControllerRequest request) { Shell::Get()->ime_controller()->BindRequest(std::move(request)); } @@ -177,6 +172,11 @@ Shell::Get()->vpn_list()->BindRequest(std::move(request)); } +void BindWallpaperRequestOnMainThread( + mojom::WallpaperControllerRequest request) { + Shell::Get()->wallpaper_controller()->BindRequest(std::move(request)); +} + } // namespace void RegisterInterfaces( @@ -227,9 +227,6 @@ base::BindRepeating(&BindEventRewriterControllerRequestOnMainThread), main_thread_task_runner); registry->AddInterface( - base::BindRepeating(&BindHighlighterControllerRequestOnMainThread), - main_thread_task_runner); - registry->AddInterface( base::BindRepeating(&BindImeControllerRequestOnMainThread), main_thread_task_runner); registry->AddInterface( @@ -261,6 +258,8 @@ main_thread_task_runner); registry->AddInterface(base::BindRepeating(&BindVpnListRequestOnMainThread), main_thread_task_runner); + registry->AddInterface(base::BindRepeating(&BindWallpaperRequestOnMainThread), + main_thread_task_runner); if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kAshEnableTestInterfaces)) {
diff --git a/ash/multi_user/multi_user_window_manager_impl.cc b/ash/multi_user/multi_user_window_manager_impl.cc index 22188ba..bdea8799 100644 --- a/ash/multi_user/multi_user_window_manager_impl.cc +++ b/ash/multi_user/multi_user_window_manager_impl.cc
@@ -12,7 +12,6 @@ #include "ash/public/cpp/multi_user_window_manager_delegate.h" #include "ash/public/cpp/multi_user_window_manager_observer.h" #include "ash/public/cpp/shell_window_ids.h" -#include "ash/public/cpp/wallpaper_user_info.h" #include "ash/session/session_controller_impl.h" #include "ash/shell.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" @@ -59,18 +58,20 @@ return false; } -WallpaperUserInfo WallpaperUserInfoForAccount(const AccountId& account_id) { +mojom::WallpaperUserInfoPtr WallpaperUserInfoForAccount( + const AccountId& account_id) { DCHECK(account_id.is_valid()); - WallpaperUserInfo wallpaper_user_info; + mojom::WallpaperUserInfoPtr wallpaper_user_info = + mojom::WallpaperUserInfo::New(); SessionControllerImpl* session_controller = Shell::Get()->session_controller(); for (const std::unique_ptr<UserSession>& user_session : session_controller->GetUserSessions()) { if (user_session->user_info.account_id == account_id) { - wallpaper_user_info.account_id = account_id; - wallpaper_user_info.type = user_session->user_info.type; - wallpaper_user_info.is_ephemeral = user_session->user_info.is_ephemeral; - wallpaper_user_info.has_gaia_account = + wallpaper_user_info->account_id = account_id; + wallpaper_user_info->type = user_session->user_info.type; + wallpaper_user_info->is_ephemeral = user_session->user_info.is_ephemeral; + wallpaper_user_info->has_gaia_account = user_session->user_info.has_gaia_account; return wallpaper_user_info; }
diff --git a/ash/multi_user/user_switch_animator.cc b/ash/multi_user/user_switch_animator.cc index 78eabc79..7abe9c4b 100644 --- a/ash/multi_user/user_switch_animator.cc +++ b/ash/multi_user/user_switch_animator.cc
@@ -7,7 +7,7 @@ #include "ash/multi_user/multi_user_window_manager_impl.h" #include "ash/public/cpp/multi_user_window_manager_delegate.h" #include "ash/shell.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "ash/wm/mru_window_tracker.h" #include "ash/wm/window_positioner.h" #include "base/bind.h" @@ -82,11 +82,11 @@ UserSwitchAnimator::UserSwitchAnimator( MultiUserWindowManagerImpl* owner, - const WallpaperUserInfo& wallpaper_user_info, + mojom::WallpaperUserInfoPtr wallpaper_user_info, base::TimeDelta animation_speed) : owner_(owner), - wallpaper_user_info_(wallpaper_user_info), - new_account_id_(wallpaper_user_info_.account_id), + wallpaper_user_info_(std::move(wallpaper_user_info)), + new_account_id_(wallpaper_user_info_->account_id), animation_speed_(animation_speed), animation_step_(ANIMATION_STEP_HIDE_OLD_USER), screen_cover_(GetScreenCover(NULL)), @@ -160,7 +160,8 @@ } void UserSwitchAnimator::TransitionWallpaper(AnimationStep animation_step) { - auto* wallpaper_controller = Shell::Get()->wallpaper_controller(); + WallpaperController* wallpaper_controller = + Shell::Get()->wallpaper_controller(); // Handle the wallpaper switch. if (animation_step == ANIMATION_STEP_HIDE_OLD_USER) { @@ -171,7 +172,8 @@ wallpaper_controller->SetAnimationDuration( duration > kMinimalAnimationTime ? duration : kMinimalAnimationTime); if (screen_cover_ != NEW_USER_COVERS_SCREEN) { - wallpaper_controller->ShowUserWallpaper(wallpaper_user_info_); + DCHECK(wallpaper_user_info_); + wallpaper_controller->ShowUserWallpaper(std::move(wallpaper_user_info_)); wallpaper_user_id_for_test_ = (NO_USER_COVERS_SCREEN == screen_cover_ ? "->" : "") + new_account_id_.Serialize(); @@ -179,8 +181,10 @@ } else if (animation_step == ANIMATION_STEP_FINALIZE) { // Revert the wallpaper cross dissolve animation duration back to the // default. - if (screen_cover_ == NEW_USER_COVERS_SCREEN) - wallpaper_controller->ShowUserWallpaper(wallpaper_user_info_); + if (screen_cover_ == NEW_USER_COVERS_SCREEN) { + DCHECK(wallpaper_user_info_); + wallpaper_controller->ShowUserWallpaper(std::move(wallpaper_user_info_)); + } // Coming here the wallpaper user id is the final result. No matter how we // got here.
diff --git a/ash/multi_user/user_switch_animator.h b/ash/multi_user/user_switch_animator.h index 79a2414..78978e6 100644 --- a/ash/multi_user/user_switch_animator.h +++ b/ash/multi_user/user_switch_animator.h
@@ -10,7 +10,7 @@ #include <string> #include "ash/ash_export.h" -#include "ash/public/cpp/wallpaper_user_info.h" +#include "ash/public/interfaces/wallpaper.mojom.h" #include "base/macros.h" #include "base/time/time.h" #include "base/timer/timer.h" @@ -39,7 +39,7 @@ // Creates a UserSwitchAnimator to animate between the current user and // |user_info|. UserSwitchAnimator(MultiUserWindowManagerImpl* owner, - const WallpaperUserInfo& user_info, + mojom::WallpaperUserInfoPtr user_info, base::TimeDelta animation_speed); ~UserSwitchAnimator(); @@ -103,7 +103,7 @@ // Contains the wallpaper configuration for the user switching to. This is // passed to the WallpaperController at the right time. - WallpaperUserInfo wallpaper_user_info_; + mojom::WallpaperUserInfoPtr wallpaper_user_info_; // The new user to set. AccountId new_account_id_;
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn index 4247ccdb7..a6b0858 100644 --- a/ash/public/cpp/BUILD.gn +++ b/ash/public/cpp/BUILD.gn
@@ -149,14 +149,7 @@ "tablet_mode.h", "touch_uma.cc", "touch_uma.h", - "wallpaper_controller.cc", - "wallpaper_controller.h", - "wallpaper_controller_client.h", - "wallpaper_controller_observer.cc", - "wallpaper_controller_observer.h", - "wallpaper_info.h", "wallpaper_types.h", - "wallpaper_user_info.h", "window_animation_types.h", "window_properties.cc", "window_properties.h", @@ -192,7 +185,6 @@ "//ash/public/interfaces:interfaces_internal", "//base", "//components/session_manager:base", - "//components/user_manager", "//ui/gfx", ]
diff --git a/ash/public/cpp/login_screen_model.h b/ash/public/cpp/login_screen_model.h index 4d44f088..6285807 100644 --- a/ash/public/cpp/login_screen_model.h +++ b/ash/public/cpp/login_screen_model.h
@@ -8,6 +8,7 @@ #include <string> #include "ash/public/cpp/ash_public_export.h" +#include "base/strings/string16.h" class AccountId; @@ -31,6 +32,12 @@ virtual void ShowEasyUnlockIcon(const AccountId& account_id, const EasyUnlockIconOptions& icon) = 0; + // Shows a warning banner message on the login screen. A warning banner is + // used to notify users of important messages before they log in to their + // session. (e.g. Tell the user that an update of the user data will start + // on login.) If |message| is empty, the banner will be hidden. + virtual void UpdateWarningMessage(const base::string16& message) = 0; + // Set the users who are displayed on the login UI. |users| is filtered // and does not correspond to every user on the device. virtual void SetUserList(const std::vector<LoginUserInfo>& users) = 0;
diff --git a/ash/public/cpp/manifest.cc b/ash/public/cpp/manifest.cc index 8859baa..4f3fabe 100644 --- a/ash/public/cpp/manifest.cc +++ b/ash/public/cpp/manifest.cc
@@ -12,7 +12,6 @@ #include "ash/public/interfaces/constants.mojom.h" #include "ash/public/interfaces/cros_display_config.mojom.h" #include "ash/public/interfaces/event_rewriter_controller.mojom.h" -#include "ash/public/interfaces/highlighter_controller.mojom.h" #include "ash/public/interfaces/ime_controller.mojom.h" #include "ash/public/interfaces/keyboard_controller.mojom.h" #include "ash/public/interfaces/kiosk_next_shell.mojom.h" @@ -26,6 +25,7 @@ #include "ash/public/interfaces/tray_action.mojom.h" #include "ash/public/interfaces/voice_interaction_controller.mojom.h" #include "ash/public/interfaces/vpn_list.mojom.h" +#include "ash/public/interfaces/wallpaper.mojom.h" #include "base/no_destructor.h" #include "chromeos/services/multidevice_setup/public/mojom/constants.mojom.h" #include "chromeos/services/network_config/public/mojom/constants.mojom.h" @@ -68,13 +68,13 @@ mojom::AssistantVolumeControl, mojom::KioskNextShellController, mojom::CrosDisplayConfigController, - mojom::EventRewriterController, mojom::HighlighterController, - mojom::ImeController, mojom::KeyboardController, - mojom::LocaleUpdateController, mojom::LoginScreen, - mojom::MediaController, mojom::NightLightController, - mojom::ShutdownController, mojom::TabletModeController, - mojom::TrayAction, mojom::VoiceInteractionController, - mojom::VpnList>()) + mojom::EventRewriterController, mojom::ImeController, + mojom::KeyboardController, mojom::LocaleUpdateController, + mojom::LoginScreen, mojom::MediaController, + mojom::NightLightController, mojom::ShutdownController, + mojom::TabletModeController, mojom::TrayAction, + mojom::VoiceInteractionController, mojom::VpnList, + mojom::WallpaperController>()) .ExposeCapability("test", service_manager::Manifest::InterfaceList< mojom::ShelfIntegrationTestApi>()) .RequireCapability("*", "accessibility")
diff --git a/ash/public/cpp/wallpaper_controller.cc b/ash/public/cpp/wallpaper_controller.cc deleted file mode 100644 index 17eaa8b..0000000 --- a/ash/public/cpp/wallpaper_controller.cc +++ /dev/null
@@ -1,17 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/public/cpp/wallpaper_controller.h" - -namespace ash { - -// static -WallpaperController* WallpaperController::Get() { - return g_instance_; -} - -// static -WallpaperController* WallpaperController::g_instance_ = nullptr; - -} // namespace ash
diff --git a/ash/public/cpp/wallpaper_controller.h b/ash/public/cpp/wallpaper_controller.h deleted file mode 100644 index d570a36..0000000 --- a/ash/public/cpp/wallpaper_controller.h +++ /dev/null
@@ -1,278 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_PUBLIC_CPP_WALLPAPER_CONTROLLER_H_ -#define ASH_PUBLIC_CPP_WALLPAPER_CONTROLLER_H_ - -#include <string> -#include <vector> - -#include "ash/public/cpp/ash_public_export.h" -#include "ash/public/cpp/wallpaper_info.h" -#include "ash/public/cpp/wallpaper_types.h" -#include "base/files/file_path.h" -#include "base/time/time.h" - -namespace gfx { -class ImageSkia; -} - -namespace ash { - -class WallpaperControllerObserver; -class WallpaperControllerClient; -struct WallpaperUserInfo; - -// Used by Chrome to set the wallpaper displayed by ash. -class ASH_PUBLIC_EXPORT WallpaperController { - public: - static WallpaperController* Get(); - - // Do the initialization: Sets the client interface, the paths of wallpaper - // directories and the device wallpaper policy enforcement flag. The paths - // must be sent over IPC because chrome owns the concept of user data - // directory. - // |client|: The client interface. - // |user_data_path|: Directory where user data can be written. - // |chromeos_wallpapers_path|: Directory where downloaded chromeos wallpapers - // reside. - // |chromeos_custom_wallpapers_path|: Directory where custom wallpapers - // reside. - // |device_policy_wallpaper_path|: The file path of the device policy - // wallpaper (if any). - virtual void Init(WallpaperControllerClient* client, - const base::FilePath& user_data_path, - const base::FilePath& chromeos_wallpapers_path, - const base::FilePath& chromeos_custom_wallpapers_path, - const base::FilePath& device_policy_wallpaper_path) = 0; - - // Sets wallpaper from a local file and updates the saved wallpaper info for - // the user. - // |user_info|: The user's information related to wallpaper. - // |wallpaper_files_id|: The file id for user_info.account_id. - // |file_name|: The name of the wallpaper file. - // |layout|: The layout of the wallpaper, used for wallpaper resizing. - // |image|: The wallpaper image. - // |preview_mode|: If true, show the wallpaper immediately but doesn't change - // the user wallpaper info until |ConfirmPreviewWallpaper| is - // called. - virtual void SetCustomWallpaper(const WallpaperUserInfo& user_info, - const std::string& wallpaper_files_id, - const std::string& file_name, - WallpaperLayout layout, - const gfx::ImageSkia& image, - bool preview_mode) = 0; - - // Sets wallpaper from the Chrome OS wallpaper picker. If the wallpaper file - // corresponding to |url| already exists in local file system (i.e. - // |SetOnlineWallpaperFromData| was called earlier with the same |url|), - // returns true and sets wallpaper for the user, otherwise returns false. - // |user_info|: The user's information related to wallpaper. - // |url|: The wallpaper url. - // |layout|: The layout of the wallpaper, used for wallpaper resizing. - // |preview_mode|: If true, show the wallpaper immediately but doesn't change - // the user wallpaper info until |ConfirmPreviewWallpaper| is - // called. - // Responds with true if the wallpaper file exists in local file system. - using SetOnlineWallpaperIfExistsCallback = base::OnceCallback<void(bool)>; - virtual void SetOnlineWallpaperIfExists( - const WallpaperUserInfo& user_info, - const std::string& url, - WallpaperLayout layout, - bool preview_mode, - SetOnlineWallpaperIfExistsCallback callback) = 0; - - // Sets wallpaper from the Chrome OS wallpaper picker and saves the wallpaper - // to local file system. After this, |SetOnlineWallpaperIfExists| will return - // true for the same |url|, so that there's no need to provide |image_data| - // when the same wallpaper needs to be set again or for another user. - // |user_info|: The user's information related to wallpaper. - // |url|: The wallpaper url. - // |layout|: The layout of the wallpaper, used for wallpaper resizing. - // |preview_mode|: If true, show the wallpaper immediately but doesn't change - // the user wallpaper info until |ConfirmPreviewWallpaper| is - // called. - // Responds with true if the wallpaper is set successfully (i.e. no decoding - // error etc.). - using SetOnlineWallpaperFromDataCallback = base::OnceCallback<void(bool)>; - virtual void SetOnlineWallpaperFromData( - const WallpaperUserInfo& user_info, - const std::string& image_data, - const std::string& url, - WallpaperLayout layout, - bool preview_mode, - SetOnlineWallpaperFromDataCallback callback) = 0; - - // Sets the user's wallpaper to be the default wallpaper. Note: different user - // types may have different default wallpapers. - // |wallpaper_files_id|: The file id for user_info.account_id. - // |show_wallpaper|: If false, don't show the new wallpaper now but only - // update cache. - virtual void SetDefaultWallpaper(const WallpaperUserInfo& user_info, - const std::string& wallpaper_files_id, - bool show_wallpaper) = 0; - - // Sets the paths of the customized default wallpaper to be used wherever a - // default wallpaper is needed. If a default wallpaper is being shown, updates - // the screen to replace the old default wallpaper. Note: it doesn't change - // the default wallpaper for guest and child accounts. - // |customized_default_small_path|: The file path of the small-size customized - // default wallpaper, if any. - // |customized_default_large_path|: The file path of the large-size customized - // default wallpaper, if any. - virtual void SetCustomizedDefaultWallpaperPaths( - const base::FilePath& customized_default_small_path, - const base::FilePath& customized_default_large_path) = 0; - - // Sets wallpaper from policy. If the user has logged in, show the policy - // wallpaper immediately, otherwise, the policy wallpaper will be shown the - // next time |ShowUserWallpaper| is called. Note: it is different from device - // policy. - // |user_info|: The user's information related to wallpaper. - // |wallpaper_files_id|: The file id for user_info.account_id. - // |data|: The data used to decode the image. - virtual void SetPolicyWallpaper(const WallpaperUserInfo& user_info, - const std::string& wallpaper_files_id, - const std::string& data) = 0; - - // Sets the path of device policy wallpaper. - // |device_policy_wallpaper_path|: The file path of the device policy - // wallpaper if it was set or empty value if - // it was cleared. - virtual void SetDevicePolicyWallpaperPath( - const base::FilePath& device_policy_wallpaper_path) = 0; - - // Sets wallpaper from a third-party app (as opposed to the Chrome OS - // wallpaper picker). - // |user_info|: The user's information related to wallpaper. - // |wallpaper_files_id|: The file id for user_info.account_id. - // |file_name|: The name of the wallpaper file. - // |layout|: The layout of the wallpaper, used for wallpaper resizing. - // |image|: The wallpaper image. - // Returns if the wallpaper is allowed to be shown on screen. It's false if: - // 1) the user is not permitted to change wallpaper, or - // 2) updating the on-screen wallpaper is not allowed at the given moment. - virtual bool SetThirdPartyWallpaper(const WallpaperUserInfo& user_info, - const std::string& wallpaper_files_id, - const std::string& file_name, - WallpaperLayout layout, - const gfx::ImageSkia& image) = 0; - - // Confirms the wallpaper being previewed to be set as the actual user - // wallpaper. Must be called in preview mode. - virtual void ConfirmPreviewWallpaper() = 0; - - // Cancels the wallpaper preview and reverts to the user wallpaper. Must be - // called in preview mode. - virtual void CancelPreviewWallpaper() = 0; - - // Updates the layout for the user's custom wallpaper and reloads the - // wallpaper with the new layout. - // |user_info|: The user's information related to wallpaper. - // |layout|: The new layout of the wallpaper. - virtual void UpdateCustomWallpaperLayout(const WallpaperUserInfo& user_info, - WallpaperLayout layout) = 0; - - // Shows the user's wallpaper, which is determined in the following order: - // 1) Use device policy wallpaper if it exists AND we are at the login screen. - // 2) Use user policy wallpaper if it exists. - // 3) Use the wallpaper set by the user (either by |SetOnlineWallpaper| or - // |SetCustomWallpaper|), if any. - // 4) Use the default wallpaper of this user. - virtual void ShowUserWallpaper(const WallpaperUserInfo& user_info) = 0; - - // Used by the gaia-signin UI. Signin wallpaper is considered either as the - // device policy wallpaper or the default wallpaper. - virtual void ShowSigninWallpaper() = 0; - - // Shows a one-shot wallpaper, which does not belong to any particular user - // and is not saved to file. Note: the wallpaper will never be dimmed or - // blurred because it's assumed that the caller wants to show the image as is - // when using this method. - virtual void ShowOneShotWallpaper(const gfx::ImageSkia& image) = 0; - - // Shows a wallpaper that stays on top of everything except for the power off - // animation. All other wallpaper requests are ignored when the always-on-top - // wallpaper is being shown. - // |image_path|: The file path to read the image data from. - virtual void ShowAlwaysOnTopWallpaper(const base::FilePath& image_path) = 0; - - // Removes the always-on-top wallpaper. The wallpaper will revert to the - // previous one, or a default one if there was none. No-op if the current - // wallpaper is not always-on-top. - virtual void RemoveAlwaysOnTopWallpaper() = 0; - - // Removes all of the user's saved wallpapers and related info. - // |wallpaper_files_id|: The file id for user_info.account_id. - virtual void RemoveUserWallpaper(const WallpaperUserInfo& user_info, - const std::string& wallpaper_files_id) = 0; - - // Removes all of the user's saved wallpapers and related info if the - // wallpaper was set by |SetPolicyWallpaper|. In addition, sets the user's - // wallpaper to be the default. If the user has logged in, show the default - // wallpaper immediately, otherwise, the default wallpaper will be shown the - // next time |ShowUserWallpaper| is called. - // |user_info|: The user's information related to wallpaper. - // |wallpaper_files_id|: The file id for user_info.account_id. - virtual void RemovePolicyWallpaper(const WallpaperUserInfo& user_info, - const std::string& wallpaper_files_id) = 0; - - // Returns the urls of the wallpapers that exist in local file system (i.e. - // |SetOnlineWallpaperFromData| was called earlier). The url is used as id - // to identify which wallpapers are available to be set offline. - using GetOfflineWallpaperListCallback = - base::OnceCallback<void(const std::vector<std::string>&)>; - virtual void GetOfflineWallpaperList( - GetOfflineWallpaperListCallback callback) = 0; - - // Sets wallpaper animation duration. Passing an empty value disables the - // animation. - virtual void SetAnimationDuration(base::TimeDelta animation_duration) = 0; - - // Opens the wallpaper picker if the active user is not controlled by policy - // and it's allowed to change wallpaper per the user type and the login state. - virtual void OpenWallpaperPickerIfAllowed() = 0; - - // Minimizes all windows except the active window. - // |user_id_hash|: The hash value corresponding to |User::username_hash|. - virtual void MinimizeInactiveWindows(const std::string& user_id_hash) = 0; - - // Restores all minimized windows to their previous states. This should only - // be called after calling |MinimizeInactiveWindows|. - // |user_id_hash|: The hash value corresponding to |User::username_hash|. - virtual void RestoreMinimizedWindows(const std::string& user_id_hash) = 0; - - // Add and remove wallpaper observers. - virtual void AddObserver(WallpaperControllerObserver* observer) = 0; - virtual void RemoveObserver(WallpaperControllerObserver* observer) = 0; - - // Returns the wallpaper image currently being shown. - virtual gfx::ImageSkia GetWallpaperImage() = 0; - - // Returns the wallpaper prominent colors. - virtual const std::vector<SkColor>& GetWallpaperColors() = 0; - - // Returns whether the current wallpaper is blurred. - virtual bool IsWallpaperBlurred() = 0; - - // Returns true if the wallpaper of the currently active user (if any) is - // controlled by policy (excluding device policy). If there's no active user, - // returns false. - virtual bool IsActiveUserWallpaperControlledByPolicy() = 0; - - // Returns a struct with info about the active user's wallpaper; the location - // is an empty string and the layout is invalid if there's no active user. - virtual WallpaperInfo GetActiveUserWallpaperInfo() = 0; - - // Returns true if the wallpaper setting (used to open the wallpaper picker) - // should be visible. - virtual bool ShouldShowWallpaperSetting() = 0; - - protected: - static WallpaperController* g_instance_; -}; - -} // namespace ash - -#endif // ASH_PUBLIC_CPP_WALLPAPER_CONTROLLER_H_
diff --git a/ash/public/cpp/wallpaper_controller_client.h b/ash/public/cpp/wallpaper_controller_client.h deleted file mode 100644 index 8556241..0000000 --- a/ash/public/cpp/wallpaper_controller_client.h +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_PUBLIC_CPP_WALLPAPER_CONTROLLER_CLIENT_H_ -#define ASH_PUBLIC_CPP_WALLPAPER_CONTROLLER_CLIENT_H_ - -#include "ash/public/cpp/ash_public_export.h" - -namespace ash { - -// Used by ash to control a Chrome client of the WallpaperController. -class ASH_PUBLIC_EXPORT WallpaperControllerClient { - public: - // Opens the wallpaper picker window. - virtual void OpenWallpaperPicker() = 0; - - // Signals to the client that ash is ready to set wallpapers. The client is - // able to decide whatever the first wallpaper it wants to display. - virtual void OnReadyToSetWallpaper() = 0; - - // Notifies the client that the animation of the first wallpaper since the - // controller initialization has completed. - // TODO(crbug.com/875128): Remove this after web-ui login code is completely - // removed. - virtual void OnFirstWallpaperAnimationFinished() = 0; -}; - -} // namespace ash - -#endif // ASH_PUBLIC_CPP_WALLPAPER_CONTROLLER_CLIENT_H_
diff --git a/ash/public/cpp/wallpaper_controller_observer.cc b/ash/public/cpp/wallpaper_controller_observer.cc deleted file mode 100644 index 3fc933e..0000000 --- a/ash/public/cpp/wallpaper_controller_observer.cc +++ /dev/null
@@ -1,13 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/public/cpp/wallpaper_controller_observer.h" - -namespace ash { - -WallpaperControllerObserver::WallpaperControllerObserver() = default; - -WallpaperControllerObserver::~WallpaperControllerObserver() = default; - -} // namespace ash
diff --git a/ash/public/cpp/wallpaper_controller_observer.h b/ash/public/cpp/wallpaper_controller_observer.h deleted file mode 100644 index 6d58154..0000000 --- a/ash/public/cpp/wallpaper_controller_observer.h +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_PUBLIC_CPP_WALLPAPER_CONTROLLER_OBSERVER_H_ -#define ASH_PUBLIC_CPP_WALLPAPER_CONTROLLER_OBSERVER_H_ - -#include "ash/public/cpp/ash_public_export.h" -#include "base/macros.h" - -namespace ash { - -// Used to listen for wallpaper state changes. -class ASH_PUBLIC_EXPORT WallpaperControllerObserver { - public: - WallpaperControllerObserver(); - - // Invoked when the wallpaper is changed. - virtual void OnWallpaperChanged() {} - - // Invoked when the colors extracted from the current wallpaper change. - virtual void OnWallpaperColorsChanged() {} - - // Invoked when the blur state of the wallpaper changes. - // TODO(crbug.com/875128): Remove this after web-ui login code is completely - // removed. - virtual void OnWallpaperBlurChanged() {} - - // Invoked when the wallpaper preview mode starts. - virtual void OnWallpaperPreviewStarted() {} - - // Invoked when the wallpaper preview mode ends. - virtual void OnWallpaperPreviewEnded() {} - - // Invoked when the first wallpaper is set. The first wallpaper is the one - // shown right after boot splash screen or after a session restart. - virtual void OnFirstWallpaperShown() {} - - protected: - virtual ~WallpaperControllerObserver(); - - private: - DISALLOW_COPY_AND_ASSIGN(WallpaperControllerObserver); -}; - -} // namespace ash - -#endif // ASH_PUBLIC_CPP_WALLPAPER_CONTROLLER_OBSERVER_H_
diff --git a/ash/public/cpp/wallpaper_struct_traits.h b/ash/public/cpp/wallpaper_struct_traits.h new file mode 100644 index 0000000..590eed9 --- /dev/null +++ b/ash/public/cpp/wallpaper_struct_traits.h
@@ -0,0 +1,55 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_PUBLIC_CPP_WALLPAPER_STRUCT_TRAITS_H_ +#define ASH_PUBLIC_CPP_WALLPAPER_STRUCT_TRAITS_H_ + +#include "ash/public/cpp/wallpaper_types.h" +#include "ash/public/interfaces/wallpaper.mojom.h" + +namespace mojo { + +template <> +struct EnumTraits<ash::mojom::WallpaperLayout, ash::WallpaperLayout> { + static ash::mojom::WallpaperLayout ToMojom(ash::WallpaperLayout input) { + switch (input) { + case ash::WALLPAPER_LAYOUT_CENTER: + return ash::mojom::WallpaperLayout::CENTER; + case ash::WALLPAPER_LAYOUT_CENTER_CROPPED: + return ash::mojom::WallpaperLayout::CENTER_CROPPED; + case ash::WALLPAPER_LAYOUT_STRETCH: + return ash::mojom::WallpaperLayout::STRETCH; + case ash::WALLPAPER_LAYOUT_TILE: + return ash::mojom::WallpaperLayout::TILE; + case ash::NUM_WALLPAPER_LAYOUT: + break; + } + NOTREACHED(); + return ash::mojom::WallpaperLayout::CENTER; + } + + static bool FromMojom(ash::mojom::WallpaperLayout input, + ash::WallpaperLayout* out) { + switch (input) { + case ash::mojom::WallpaperLayout::CENTER: + *out = ash::WALLPAPER_LAYOUT_CENTER; + return true; + case ash::mojom::WallpaperLayout::CENTER_CROPPED: + *out = ash::WALLPAPER_LAYOUT_CENTER_CROPPED; + return true; + case ash::mojom::WallpaperLayout::STRETCH: + *out = ash::WALLPAPER_LAYOUT_STRETCH; + return true; + case ash::mojom::WallpaperLayout::TILE: + *out = ash::WALLPAPER_LAYOUT_TILE; + return true; + } + NOTREACHED(); + return false; + } +}; + +} // namespace mojo + +#endif // ASH_PUBLIC_CPP_WALLPAPER_STRUCT_TRAITS_H_
diff --git a/ash/public/cpp/wallpaper_user_info.h b/ash/public/cpp/wallpaper_user_info.h deleted file mode 100644 index 254d4964..0000000 --- a/ash/public/cpp/wallpaper_user_info.h +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_PUBLIC_CPP_WALLPAPER_USER_INFO_H_ -#define ASH_PUBLIC_CPP_WALLPAPER_USER_INFO_H_ - -#include "ash/public/cpp/ash_public_export.h" -#include "components/account_id/account_id.h" -#include "components/user_manager/user_type.h" - -namespace ash { - -// User info needed to set wallpapers. Clients must specify the user because -// it's not always the same as the active user, e.g., when showing wallpapers -// for different user pods at login screen, or setting wallpapers selectively -// for primary user and active user during a multi-profile session. -struct ASH_PUBLIC_EXPORT WallpaperUserInfo { - // The user's account id. - AccountId account_id = EmptyAccountId(); - - // The user type. - user_manager::UserType type = user_manager::USER_TYPE_REGULAR; - - // True if the user's non-cryptohome data (wallpaper, avatar etc.) is - // ephemeral. See |UserManager::IsCurrentUserNonCryptohomeDataEphemeral| for - // more details. - bool is_ephemeral = false; - - // True if the user has gaia account. - bool has_gaia_account = false; -}; - -} // namespace ash - -#endif // ASH_PUBLIC_CPP_WALLPAPER_USER_INFO_H_
diff --git a/ash/public/interfaces/BUILD.gn b/ash/public/interfaces/BUILD.gn index 14536b5..175dbf3 100644 --- a/ash/public/interfaces/BUILD.gn +++ b/ash/public/interfaces/BUILD.gn
@@ -27,7 +27,6 @@ "constants.mojom", "cros_display_config.mojom", "event_rewriter_controller.mojom", - "highlighter_controller.mojom", "ime_controller.mojom", "ime_info.mojom", "keyboard_config.mojom", @@ -45,6 +44,7 @@ "update.mojom", "voice_interaction_controller.mojom", "vpn_list.mojom", + "wallpaper.mojom", "window_pin_type.mojom", "window_properties.mojom", ]
diff --git a/ash/public/interfaces/highlighter_controller.mojom b/ash/public/interfaces/highlighter_controller.mojom deleted file mode 100644 index 4a643d0..0000000 --- a/ash/public/interfaces/highlighter_controller.mojom +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module ash.mojom; - -import "ui/gfx/geometry/mojo/geometry.mojom"; - -// Interface for ash client (e.g. Chrome) to connect to the highlighter -// controller, the component implementing on-screen content selection -// with a stylus. -interface HighlighterController { - // Sets the client interface. - SetClient(HighlighterControllerClient client); - - // Exits the highlighter mode if it is currently enabled. - ExitHighlighterMode(); -}; - -// Interface for ash to notify the client (e.g. Chrome) about the highlighter -// selection and state. -interface HighlighterControllerClient { - // Called when when a valid selection is made. Selected rectangle is in - // screen coordinates, clipped to screen bounds if necessary. - HandleSelection(gfx.mojom.Rect rect); - - // Called when the highlighter tool becomes enabled or disabled. - HandleEnabledStateChange(bool enabled); -};
diff --git a/ash/public/interfaces/login_screen.mojom b/ash/public/interfaces/login_screen.mojom index 80ac9302..37e7b83 100644 --- a/ash/public/interfaces/login_screen.mojom +++ b/ash/public/interfaces/login_screen.mojom
@@ -63,18 +63,6 @@ string help_link_text, int32 help_topic_id); - // Shows a warning banner message on the login screen. A warning banner is - // used to notify users of important messages before they log in to their - // session. (e.g. Tell the user that an update of the user data will start - // on login) - // |message|: The message to show. - ShowWarningBanner(mojo_base.mojom.String16 message); - - // Hide a warning banner if it is displayed. - // TODO(fukino): Ideally chrome-side should not have this level of UI - // control. Make the API simpler and let ash determine the UI behavior. - HideWarningBanner(); - // Requests to close any displayed error messages in ash lock screen. ClearErrors();
diff --git a/ash/public/interfaces/typemaps.gni b/ash/public/interfaces/typemaps.gni index 085a6c0..7305cb5 100644 --- a/ash/public/interfaces/typemaps.gni +++ b/ash/public/interfaces/typemaps.gni
@@ -2,4 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -typemaps = [ "//ash/public/interfaces/shelf_integration_test_api.typemap" ] +typemaps = [ + "//ash/public/interfaces/shelf_integration_test_api.typemap", + "//ash/public/interfaces/wallpaper.typemap", +]
diff --git a/ash/public/interfaces/wallpaper.mojom b/ash/public/interfaces/wallpaper.mojom new file mode 100644 index 0000000..3e0d540 --- /dev/null +++ b/ash/public/interfaces/wallpaper.mojom
@@ -0,0 +1,343 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module ash.mojom; + +import "components/account_id/interfaces/account_id.mojom"; +import "mojo/public/mojom/base/file_path.mojom"; +import "mojo/public/mojom/base/time.mojom"; +import "ui/gfx/image/mojo/image.mojom"; +import "url/mojom/url.mojom"; + +// These values match ash::WallpaperLayout. +enum WallpaperLayout { + CENTER, + CENTER_CROPPED, + STRETCH, + TILE, +}; + +// Matches user_manager::UserType. +enum UserType { + // Regular user, has a user name and password. + REGULAR, + + // Guest user, logs in without authentication. + GUEST, + + // Public account user, logs in without authentication. Available only if + // enabled through policy. + PUBLIC_ACCOUNT, + + // Supervised user, logs in only with local authentication. + SUPERVISED, + + // Kiosk app robot, logs in without authentication. + KIOSK, + + // Child user, with supervised options. + CHILD, + + // Android app in kiosk mode, logs in without authentication. + ARC_KIOSK, + + // Active Directory user. Authenticates against Active Directory server. + ACTIVE_DIRECTORY, +}; + +// User info needed to set wallpapers. Clients must specify the user because +// it's not always the same with the active user, e.g., when showing wallpapers +// for different user pods at login screen, or setting wallpapers selectively +// for primary user and active user during a multi-profile session. +struct WallpaperUserInfo { + // The user's account id. + signin.mojom.AccountId account_id; + + // The user type. + UserType type; + + // True if the user's non-cryptohome data (wallpaper, avatar etc.) is + // ephemeral. See |UserManager::IsCurrentUserNonCryptohomeDataEphemeral| for + // more details. + bool is_ephemeral; + + // True if the user has gaia account. + bool has_gaia_account; +}; + +// Used by Chrome to set the wallpaper displayed by ash. +interface WallpaperController { + // Do the initialization: Sets the client interface, the paths of wallpaper + // directories and the device wallpaper policy enforcement flag. The paths + // must be sent over IPC because chrome owns the concept of user data + // directory. + // |client|: The client interface. + // |user_data_path|: Directory where user data can be written. + // |chromeos_wallpapers_path|: Directory where downloaded chromeos wallpapers + // reside. + // |chromeos_custom_wallpapers_path|: Directory where custom wallpapers + // reside. + // |device_policy_wallpaper_path|: The file path of the device policy + // wallpaper (if any). + Init(WallpaperControllerClient client, + mojo_base.mojom.FilePath user_data_path, + mojo_base.mojom.FilePath chromeos_wallpapers_path, + mojo_base.mojom.FilePath chromeos_custom_wallpapers_path, + mojo_base.mojom.FilePath device_policy_wallpaper_path); + + // Sets wallpaper from a local file and updates the saved wallpaper info for + // the user. + // |user_info|: The user's information related to wallpaper. + // |wallpaper_files_id|: The file id for user_info.account_id. + // |file_name|: The name of the wallpaper file. + // |layout|: The layout of the wallpaper, used for wallpaper resizing. + // |image|: The wallpaper image. + // |preview_mode|: If true, show the wallpaper immediately but doesn't change + // the user wallpaper info until |ConfirmPreviewWallpaper| is + // called. + SetCustomWallpaper(WallpaperUserInfo user_info, + string wallpaper_files_id, + string file_name, + WallpaperLayout layout, + gfx.mojom.ImageSkia image, + bool preview_mode); + + // Sets wallpaper from the Chrome OS wallpaper picker. If the wallpaper file + // corresponding to |url| already exists in local file system (i.e. + // |SetOnlineWallpaperFromData| was called earlier with the same |url|), + // returns true and sets wallpaper for the user, otherwise returns false. + // |user_info|: The user's information related to wallpaper. + // |url|: The wallpaper url. + // |layout|: The layout of the wallpaper, used for wallpaper resizing. + // |preview_mode|: If true, show the wallpaper immediately but doesn't change + // the user wallpaper info until |ConfirmPreviewWallpaper| is + // called. + // |file_exists|: If the wallpaper file exists in local file system. + SetOnlineWallpaperIfExists(WallpaperUserInfo user_info, + string url, + WallpaperLayout layout, + bool preview_mode) => (bool file_exists); + + // Sets wallpaper from the Chrome OS wallpaper picker and saves the wallpaper + // to local file system. After this, |SetOnlineWallpaperIfExists| will return + // true for the same |url|, so that there's no need to provide |image_data| + // when the same wallpaper needs to be set again or for another user. + // |user_info|: The user's information related to wallpaper. + // |url|: The wallpaper url. + // |layout|: The layout of the wallpaper, used for wallpaper resizing. + // |preview_mode|: If true, show the wallpaper immediately but doesn't change + // the user wallpaper info until |ConfirmPreviewWallpaper| is + // called. + // |success|: If the wallpaper is set successfully (i.e. no decoding error + // etc.). + SetOnlineWallpaperFromData(WallpaperUserInfo user_info, + string image_data, + string url, + WallpaperLayout layout, + bool preview_mode) => (bool success); + + // Sets the user's wallpaper to be the default wallpaper. Note: different user + // types may have different default wallpapers. + // |wallpaper_files_id|: The file id for user_info.account_id. + // |show_wallpaper|: If false, don't show the new wallpaper now but only + // update cache. + SetDefaultWallpaper(WallpaperUserInfo user_info, + string wallpaper_files_id, + bool show_wallpaper); + + // Sets the paths of the customized default wallpaper to be used wherever a + // default wallpaper is needed. If a default wallpaper is being shown, updates + // the screen to replace the old default wallpaper. Note: it doesn't change + // the default wallpaper for guest and child accounts. + // |customized_default_small_path|: The file path of the small-size customized + // default wallpaper, if any. + // |customized_default_large_path|: The file path of the large-size customized + // default wallpaper, if any. + SetCustomizedDefaultWallpaperPaths( + mojo_base.mojom.FilePath customized_default_small_path, + mojo_base.mojom.FilePath customized_default_large_path); + + // Sets wallpaper from policy. If the user has logged in, show the policy + // wallpaper immediately, otherwise, the policy wallpaper will be shown the + // next time |ShowUserWallpaper| is called. Note: it is different from device + // policy. + // |user_info|: The user's information related to wallpaper. + // |wallpaper_files_id|: The file id for user_info.account_id. + // |data|: The data used to decode the image. + SetPolicyWallpaper(WallpaperUserInfo user_info, + string wallpaper_files_id, + string data); + + // Sets the path of device policy wallpaper. + // |device_policy_wallpaper_path|: The file path of the device policy + // wallpaper if it was set or empty value if + // it was cleared. + SetDevicePolicyWallpaperPath( + mojo_base.mojom.FilePath device_policy_wallpaper_path); + + // Sets wallpaper from a third-party app (as opposed to the Chrome OS + // wallpaper picker). + // |user_info|: The user's information related to wallpaper. + // |wallpaper_files_id|: The file id for user_info.account_id. + // |file_name|: The name of the wallpaper file. + // |layout|: The layout of the wallpaper, used for wallpaper resizing. + // |image|: The wallpaper image. + // |allowed|: If the wallpaper is allowed to be shown on screen. It's false if + // 1) the user is not permitted to change wallpaper, or + // 2) updating the on-screen wallpaper is not allowed at the + // given moment. + // |image_id|: A unique id assigned to the image. Clients may be interested in + // observing all wallpaper changes and acting differently based on + // if the wallpaper change is due to their own request. In order + // to do so, they should compare this value with the one that's + // returned by |OnWallpaperChanged|. + SetThirdPartyWallpaper(WallpaperUserInfo user_info, + string wallpaper_files_id, + string file_name, + WallpaperLayout layout, + gfx.mojom.ImageSkia image) + => (bool allowed, uint32 image_id); + + // Confirms the wallpaper being previewed to be set as the actual user + // wallpaper. Must be called in preview mode. + ConfirmPreviewWallpaper(); + + // Cancels the wallpaper preview and reverts to the user wallpaper. Must be + // called in preview mode. + CancelPreviewWallpaper(); + + // Updates the layout for the user's custom wallpaper and reloads the + // wallpaper with the new layout. + // |user_info|: The user's information related to wallpaper. + // |layout|: The new layout of the wallpaper. + UpdateCustomWallpaperLayout(WallpaperUserInfo user_info, + WallpaperLayout layout); + + // Shows the user's wallpaper, which is determined in the following order: + // 1) Use device policy wallpaper if it exists AND we are at the login screen. + // 2) Use user policy wallpaper if it exists. + // 3) Use the wallpaper set by the user (either by |SetOnlineWallpaper| or + // |SetCustomWallpaper|), if any. + // 4) Use the default wallpaper of this user. + ShowUserWallpaper(WallpaperUserInfo user_info); + + // Used by the gaia-signin UI. Signin wallpaper is considered either as the + // device policy wallpaper or the default wallpaper. + ShowSigninWallpaper(); + + // Shows a one-shot wallpaper, which does not belong to any particular user + // and is not saved to file. Note: the wallpaper will never be dimmed or + // blurred because it's assumed that the caller wants to show the image as is + // when using this method. + ShowOneShotWallpaper(gfx.mojom.ImageSkia image); + + // Shows a wallpaper that stays on top of everything except for the power off + // animation. All other wallpaper requests are ignored when the always-on-top + // wallpaper is being shown. + // |image_path|: The file path to read the image data from. + ShowAlwaysOnTopWallpaper(mojo_base.mojom.FilePath image_path); + + // Removes the always-on-top wallpaper. The wallpaper will revert to the + // previous one, or a default one if there was none. No-op if the current + // wallpaper is not always-on-top. + RemoveAlwaysOnTopWallpaper(); + + // Removes all of the user's saved wallpapers and related info. + // |wallpaper_files_id|: The file id for user_info.account_id. + RemoveUserWallpaper(WallpaperUserInfo user_info, string wallpaper_files_id); + + // Removes all of the user's saved wallpapers and related info if the + // wallpaper was set by |SetPolicyWallpaper|. In addition, sets the user's + // wallpaper to be the default. If the user has logged in, show the default + // wallpaper immediately, otherwise, the default wallpaper will be shown the + // next time |ShowUserWallpaper| is called. + // |user_info|: The user's information related to wallpaper. + // |wallpaper_files_id|: The file id for user_info.account_id. + RemovePolicyWallpaper(WallpaperUserInfo user_info, string wallpaper_files_id); + + // Returns the urls of the wallpapers that exist in local file system (i.e. + // |SetOnlineWallpaperFromData| was called earlier). The url is used as id + // to identify which wallpapers are available to be set offline. + GetOfflineWallpaperList() => (array<string> url_list); + + // Sets wallpaper animation duration. Passing an empty value disables the + // animation. + SetAnimationDuration(mojo_base.mojom.TimeDelta animation_duration); + + // Opens the wallpaper picker if the active user is not controlled by policy + // and it's allowed to change wallpaper per the user type and the login state. + OpenWallpaperPickerIfAllowed(); + + // Minimizes all windows except the active window. + // |user_id_hash|: The hash value corresponding to |User::username_hash|. + MinimizeInactiveWindows(string user_id_hash); + + // Restores all minimized windows to their previous states. This should only + // be called after calling |MinimizeInactiveWindows|. + // |user_id_hash|: The hash value corresponding to |User::username_hash|. + RestoreMinimizedWindows(string user_id_hash); + + // Calling this method triggers an initial notification of the wallpaper + // state. Observers are automatically removed as their connections are closed. + AddObserver(associated WallpaperObserver observer); + + // Returns the wallpaper image currently being shown. + GetWallpaperImage() => (gfx.mojom.ImageSkia image); + + // Returns the wallpaper prominent colors. + GetWallpaperColors() => (array<uint32> prominent_colors); + + // Returns whether the current wallpaper is blurred. + IsWallpaperBlurred() => (bool blurred); + + // Returns true if the wallpaper of the currently active user (if any) is + // controlled by policy (excluding device policy). If there's no active user, + // returns false. + IsActiveUserWallpaperControlledByPolicy() => (bool controlled); + + // Returns the location and the layout of the active user's wallpaper. The + // location is either a url or a file path, corresponding to + // |WallpaperInfo.location|. Returns an empty string and an invalid layout if + // there's no active user. + GetActiveUserWallpaperInfo() => (string location, WallpaperLayout layout); + + // Returns true if the wallpaper setting (used to open the wallpaper picker) + // should be visible. + ShouldShowWallpaperSetting() => (bool show); +}; + +// Used by ash to control a Chrome client. +interface WallpaperControllerClient { + // Opens the wallpaper picker window. + OpenWallpaperPicker(); + + // Signals to the client that ash is ready to set wallpapers. The client is + // able to decide whatever the first wallpaper it wants to display. + OnReadyToSetWallpaper(); + + // Notifies the client that the animation of the first wallpaper since the + // controller initialization has completed. + // TODO(crbug.com/875128): Remove this after web-ui login code is completely + // removed. + OnFirstWallpaperAnimationFinished(); +}; + +// Used to listen for wallpaper state changed. +interface WallpaperObserver { + // Invoked when the wallpaper is changed. |image_id| is the unique id assigned + // to the current wallpaper image. It should only be used to compare against + // the value returned by a setting wallpaper request earlier + // (e.g. SetThirdPartyWallpaper). This value is unique to each |ImageSkia| + // object and is different for two objects with the same pixels. + OnWallpaperChanged(uint32 image_id); + + // Invoked when the colors extracted from the current wallpaper change. Colors + // are ordered and are referenced in wallpaper::ColorProfileType. + OnWallpaperColorsChanged(array<uint32> prominent_colors); + + // Invoked when the blur state of the wallpaper changes. + // TODO(crbug.com/875128): Remove this after web-ui login code is completely + // removed. + OnWallpaperBlurChanged(bool blurred); +};
diff --git a/ash/public/interfaces/wallpaper.typemap b/ash/public/interfaces/wallpaper.typemap new file mode 100644 index 0000000..01525b3 --- /dev/null +++ b/ash/public/interfaces/wallpaper.typemap
@@ -0,0 +1,20 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +mojom = "//ash/public/interfaces/wallpaper.mojom" +public_headers = [ + "//ash/public/cpp/wallpaper_types.h", + "//components/user_manager/user_type.h", +] +traits_headers = [ + "//ash/public/cpp/wallpaper_struct_traits.h", + "//ash/public/interfaces/user_info_traits.h", +] +public_deps = [ + "//components/user_manager", +] +type_mappings = [ + "ash.mojom.WallpaperLayout=ash::WallpaperLayout", + "ash.mojom.UserType=user_manager::UserType", +]
diff --git a/ash/shelf/shelf_background_animator.cc b/ash/shelf/shelf_background_animator.cc index 7b03596..79f24ba 100644 --- a/ash/shelf/shelf_background_animator.cc +++ b/ash/shelf/shelf_background_animator.cc
@@ -13,7 +13,7 @@ #include "ash/shelf/shelf.h" #include "ash/shelf/shelf_background_animator_observer.h" #include "ash/shelf/shelf_constants.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "ui/gfx/animation/slide_animation.h" #include "ui/gfx/color_analysis.h" #include "ui/gfx/color_palette.h" @@ -57,7 +57,7 @@ ShelfBackgroundAnimator::ShelfBackgroundAnimator( ShelfBackgroundType background_type, Shelf* shelf, - WallpaperControllerImpl* wallpaper_controller) + WallpaperController* wallpaper_controller) : shelf_(shelf), wallpaper_controller_(wallpaper_controller) { if (wallpaper_controller_) wallpaper_controller_->AddObserver(this);
diff --git a/ash/shelf/shelf_background_animator.h b/ash/shelf/shelf_background_animator.h index d43884c..022fbeb 100644 --- a/ash/shelf/shelf_background_animator.h +++ b/ash/shelf/shelf_background_animator.h
@@ -10,8 +10,8 @@ #include "ash/ash_export.h" #include "ash/public/cpp/shelf_types.h" -#include "ash/public/cpp/wallpaper_controller_observer.h" #include "ash/shelf/shelf_observer.h" +#include "ash/wallpaper/wallpaper_controller_observer.h" #include "base/macros.h" #include "base/observer_list.h" #include "third_party/skia/include/core/SkColor.h" @@ -27,7 +27,7 @@ class Shelf; class ShelfBackgroundAnimatorObserver; class ShelfBackgroundAnimatorTestApi; -class WallpaperControllerImpl; +class WallpaperController; // Central controller for the Shelf and Dock opacity animations. // @@ -51,7 +51,7 @@ // wallpaper changes if not null. ShelfBackgroundAnimator(ShelfBackgroundType background_type, Shelf* shelf, - WallpaperControllerImpl* wallpaper_controller); + WallpaperController* wallpaper_controller); ~ShelfBackgroundAnimator() override; ShelfBackgroundType target_background_type() const { @@ -159,7 +159,7 @@ Shelf* shelf_; // The wallpaper controller to observe for changes and to extract colors from. - WallpaperControllerImpl* wallpaper_controller_; + WallpaperController* wallpaper_controller_; // The background type that this is animating towards or has reached. ShelfBackgroundType target_background_type_ = SHELF_BACKGROUND_DEFAULT;
diff --git a/ash/shelf/shelf_context_menu_model.cc b/ash/shelf/shelf_context_menu_model.cc index 0117a53..38c578f 100644 --- a/ash/shelf/shelf_context_menu_model.cc +++ b/ash/shelf/shelf_context_menu_model.cc
@@ -21,7 +21,7 @@ #include "ash/session/session_controller_impl.h" #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "base/metrics/user_metrics.h" #include "base/numerics/safe_conversions.h"
diff --git a/ash/shelf/shelf_context_menu_model_unittest.cc b/ash/shelf/shelf_context_menu_model_unittest.cc index 6d239a3c..70397b9 100644 --- a/ash/shelf/shelf_context_menu_model_unittest.cc +++ b/ash/shelf/shelf_context_menu_model_unittest.cc
@@ -6,13 +6,12 @@ #include "ash/public/cpp/app_menu_constants.h" #include "ash/public/cpp/shelf_item_delegate.h" -#include "ash/public/cpp/wallpaper_controller_client.h" #include "ash/session/test_session_controller_client.h" #include "ash/shelf/shelf.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" #include "ash/test_shell_delegate.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "base/strings/utf_string_conversions.h" #include "ui/display/display.h" @@ -41,20 +40,27 @@ }; // A test wallpaper controller client class. -class TestWallpaperControllerClient : public WallpaperControllerClient { +class TestWallpaperControllerClient : public mojom::WallpaperControllerClient { public: - TestWallpaperControllerClient() = default; - ~TestWallpaperControllerClient() = default; + TestWallpaperControllerClient() : binding_(this) {} + ~TestWallpaperControllerClient() override = default; size_t open_count() const { return open_count_; } - // WallpaperControllerClient: + mojom::WallpaperControllerClientPtr CreateInterfacePtr() { + mojom::WallpaperControllerClientPtr ptr; + binding_.Bind(mojo::MakeRequest(&ptr)); + return ptr; + } + + // mojom::WallpaperControllerClient: void OpenWallpaperPicker() override { open_count_++; } void OnReadyToSetWallpaper() override {} void OnFirstWallpaperAnimationFinished() override {} private: size_t open_count_ = 0; + mojo::Binding<mojom::WallpaperControllerClient> binding_; DISALLOW_COPY_AND_ASSIGN(TestWallpaperControllerClient); }; @@ -141,11 +147,13 @@ EXPECT_TRUE(submenu->IsItemCheckedAt(0)); TestWallpaperControllerClient client; - Shell::Get()->wallpaper_controller()->SetClientForTesting(&client); + Shell::Get()->wallpaper_controller()->SetClientForTesting( + client.CreateInterfacePtr()); EXPECT_EQ(0u, client.open_count()); // Click the third option, wallpaper picker. It should open. menu3.ActivatedAt(2); + Shell::Get()->wallpaper_controller()->FlushForTesting(); EXPECT_EQ(1u, client.open_count()); }
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc index e96a726..b41962a0 100644 --- a/ash/shelf/shelf_layout_manager.cc +++ b/ash/shelf/shelf_layout_manager.cc
@@ -30,7 +30,7 @@ #include "ash/shell.h" #include "ash/system/locale/locale_update_controller.h" #include "ash/system/status_area_widget.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "ash/wm/fullscreen_window_finder.h" #include "ash/wm/lock_state_controller.h" #include "ash/wm/mru_window_tracker.h"
diff --git a/ash/shelf/shelf_layout_manager.h b/ash/shelf/shelf_layout_manager.h index c93365c..1c72070 100644 --- a/ash/shelf/shelf_layout_manager.h +++ b/ash/shelf/shelf_layout_manager.h
@@ -11,12 +11,12 @@ #include "ash/ash_export.h" #include "ash/home_screen/home_launcher_gesture_handler_observer.h" #include "ash/public/cpp/shelf_types.h" -#include "ash/public/cpp/wallpaper_controller_observer.h" #include "ash/rotator/screen_rotation_animator_observer.h" #include "ash/session/session_observer.h" #include "ash/shelf/shelf.h" #include "ash/shell_observer.h" #include "ash/system/locale/locale_update_controller.h" +#include "ash/wallpaper/wallpaper_controller_observer.h" #include "ash/wm/lock_state_observer.h" #include "ash/wm/overview/overview_observer.h" #include "ash/wm/wm_snap_to_pixel_layout_manager.h" @@ -45,7 +45,6 @@ class ShelfLayoutManagerObserver; class ShelfLayoutManagerTest; class ShelfWidget; -class WallpaperController; // ShelfLayoutManager is the layout manager responsible for the shelf and // status widgets. The shelf is given the total available width and told the
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc index 475f414..47f2bf3c 100644 --- a/ash/shelf/shelf_layout_manager_unittest.cc +++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -26,7 +26,6 @@ #include "ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/public/cpp/test/shell_test_api.h" -#include "ash/public/cpp/wallpaper_controller_observer.h" #include "ash/public/cpp/window_properties.h" #include "ash/root_window_controller.h" #include "ash/screen_util.h" @@ -42,7 +41,7 @@ #include "ash/system/status_area_widget_test_helper.h" #include "ash/system/unified/unified_system_tray.h" #include "ash/test/ash_test_base.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "ash/window_factory.h" #include "ash/wm/lock_state_controller.h" #include "ash/wm/overview/overview_controller.h" @@ -1264,7 +1263,8 @@ // Assertions around the login screen. TEST_F(ShelfLayoutManagerTest, VisibleWhenLoginScreenShowing) { Shelf* shelf = GetPrimaryShelf(); - auto* wallpaper_controller = Shell::Get()->wallpaper_controller(); + WallpaperController* wallpaper_controller = + Shell::Get()->wallpaper_controller(); WallpaperShownWaiter waiter; SessionInfo info;
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc index e9cb7e7..854765e63 100644 --- a/ash/shelf/shelf_view_unittest.cc +++ b/ash/shelf/shelf_view_unittest.cc
@@ -46,7 +46,7 @@ #include "ash/test/ash_test_base.h" #include "ash/test/ash_test_helper.h" #include "ash/test_shell_delegate.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "ash/wallpaper/wallpaper_controller_test_api.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "base/i18n/rtl.h"
diff --git a/ash/shell.cc b/ash/shell.cc index 063bb6f..5fc3fc9 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -120,7 +120,7 @@ #include "ash/tray_action/tray_action.h" #include "ash/utility/screenshot_controller.h" #include "ash/voice_interaction/voice_interaction_controller.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "ash/wayland/wayland_server_controller.h" #include "ash/wm/ash_focus_rules.h" #include "ash/wm/container_finder.h" @@ -909,8 +909,7 @@ // Shelf, and WallPaper could be created by the factory. views::FocusManagerFactory::Install(new AshFocusManagerFactory); - wallpaper_controller_ = - std::make_unique<WallpaperControllerImpl>(local_state_); + wallpaper_controller_ = std::make_unique<WallpaperController>(local_state_); window_positioner_ = std::make_unique<WindowPositioner>();
diff --git a/ash/shell.h b/ash/shell.h index 39245a3..568cbe8 100644 --- a/ash/shell.h +++ b/ash/shell.h
@@ -188,7 +188,7 @@ class VideoDetector; class VoiceInteractionController; class VpnList; -class WallpaperControllerImpl; +class WallpaperController; class WaylandServerController; class WindowCycleController; class WindowPositioner; @@ -496,7 +496,7 @@ return voice_interaction_controller_.get(); } VpnList* vpn_list() { return vpn_list_.get(); } - WallpaperControllerImpl* wallpaper_controller() { + WallpaperController* wallpaper_controller() { return wallpaper_controller_.get(); } WindowCycleController* window_cycle_controller() { @@ -693,7 +693,7 @@ std::unique_ptr<TrayAction> tray_action_; std::unique_ptr<VoiceInteractionController> voice_interaction_controller_; std::unique_ptr<VpnList> vpn_list_; - std::unique_ptr<WallpaperControllerImpl> wallpaper_controller_; + std::unique_ptr<WallpaperController> wallpaper_controller_; std::unique_ptr<WindowCycleController> window_cycle_controller_; std::unique_ptr<OverviewController> overview_controller_; // Owned by |focus_controller_|.
diff --git a/ash/system/network/network_list_view.cc b/ash/system/network/network_list_view.cc index e7be515..4b695f3 100644 --- a/ash/system/network/network_list_view.cc +++ b/ash/system/network/network_list_view.cc
@@ -27,8 +27,6 @@ #include "ash/system/tray/tri_view.h" #include "base/i18n/number_formatting.h" #include "base/strings/utf_string_conversions.h" -#include "chromeos/network/network_handler.h" -#include "chromeos/network/proxy/ui_proxy_config_service.h" #include "chromeos/services/network_config/public/cpp/cros_network_config_util.h" #include "chromeos/services/network_config/public/mojom/constants.mojom.h" #include "components/device_event_log/device_event_log.h" @@ -51,9 +49,11 @@ using chromeos::network_config::mojom::DeviceStateType; using chromeos::network_config::mojom::FilterType; using chromeos::network_config::mojom::NetworkFilter; +using chromeos::network_config::mojom::NetworkStateProperties; using chromeos::network_config::mojom::NetworkStatePropertiesPtr; using chromeos::network_config::mojom::NetworkType; using chromeos::network_config::mojom::ONCSource; +using chromeos::network_config::mojom::ProxyMode; namespace ash { namespace tray { @@ -223,15 +223,9 @@ // Keep an index where the next child should be inserted. int index = 0; - bool using_proxy = false; - // TODO(https://crbug.com/718072): Create UIProxyConfigService under mash, or - // provide this via network_config.mojom. - if (!::features::IsMultiProcessMash()) { - using_proxy = chromeos::NetworkHandler::Get() - ->ui_proxy_config_service() - ->HasDefaultNetworkProxyConfigured(); - } - + const NetworkStateProperties* default_network = model_->default_network(); + bool using_proxy = default_network && + default_network->proxy_mode == ProxyMode::kFixedServers; // Show a warning that the connection might be monitored if connected to a VPN // or if the default network has a proxy installed. if (vpn_connected_ || using_proxy) {
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc index b545db8..1f42194 100644 --- a/ash/test/ash_test_helper.cc +++ b/ash/test/ash_test_helper.cc
@@ -26,7 +26,7 @@ #include "ash/system/screen_layout_observer.h" #include "ash/test/ash_test_views_delegate.h" #include "ash/test_shell_delegate.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "ash/wm/overview/overview_controller.h" #include "base/bind.h" #include "base/run_loop.h"
diff --git a/ash/wallpaper/wallpaper_base_view.cc b/ash/wallpaper/wallpaper_base_view.cc index a792f97..ffc2e4be0 100644 --- a/ash/wallpaper/wallpaper_base_view.cc +++ b/ash/wallpaper/wallpaper_base_view.cc
@@ -7,7 +7,7 @@ #include "ash/public/cpp/login_constants.h" #include "ash/public/cpp/wallpaper_types.h" #include "ash/shell.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "ash/wm/overview/overview_controller.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "ui/gfx/canvas.h" @@ -62,7 +62,7 @@ // to fill the wallpaper. Ideally the image should be larger than the largest // display supported, if not we will scale and center it if the layout is // WALLPAPER_LAYOUT_CENTER_CROPPED. - auto* controller = Shell::Get()->wallpaper_controller(); + WallpaperController* controller = Shell::Get()->wallpaper_controller(); gfx::ImageSkia wallpaper = controller->GetWallpaper(); WallpaperLayout layout = controller->GetWallpaperLayout();
diff --git a/ash/wallpaper/wallpaper_controller_impl.cc b/ash/wallpaper/wallpaper_controller.cc similarity index 77% rename from ash/wallpaper/wallpaper_controller_impl.cc rename to ash/wallpaper/wallpaper_controller.cc index 4aded0b1..587ea0d 100644 --- a/ash/wallpaper/wallpaper_controller_impl.cc +++ b/ash/wallpaper/wallpaper_controller.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include <memory> #include <numeric> @@ -14,12 +14,11 @@ #include "ash/public/cpp/ash_switches.h" #include "ash/public/cpp/login_constants.h" #include "ash/public/cpp/shell_window_ids.h" -#include "ash/public/cpp/wallpaper_controller_client.h" -#include "ash/public/cpp/wallpaper_controller_observer.h" #include "ash/root_window_controller.h" #include "ash/session/session_controller_impl.h" #include "ash/shell.h" #include "ash/shell_delegate.h" +#include "ash/wallpaper/wallpaper_controller_observer.h" #include "ash/wallpaper/wallpaper_utils/wallpaper_color_calculator.h" #include "ash/wallpaper/wallpaper_utils/wallpaper_decoder.h" #include "ash/wallpaper/wallpaper_utils/wallpaper_resizer.h" @@ -122,21 +121,21 @@ } // Returns the appropriate wallpaper resolution for all root windows. -WallpaperControllerImpl::WallpaperResolution GetAppropriateResolution() { - gfx::Size size = WallpaperControllerImpl::GetMaxDisplaySizeInNative(); +WallpaperController::WallpaperResolution GetAppropriateResolution() { + gfx::Size size = WallpaperController::GetMaxDisplaySizeInNative(); return (size.width() > kSmallWallpaperMaxWidth || size.height() > kSmallWallpaperMaxHeight) - ? WallpaperControllerImpl::WALLPAPER_RESOLUTION_LARGE - : WallpaperControllerImpl::WALLPAPER_RESOLUTION_SMALL; + ? WallpaperController::WALLPAPER_RESOLUTION_LARGE + : WallpaperController::WALLPAPER_RESOLUTION_SMALL; } // Returns the path of the online wallpaper corresponding to |url| and // |resolution|. base::FilePath GetOnlineWallpaperPath( const std::string& url, - WallpaperControllerImpl::WallpaperResolution resolution) { + WallpaperController::WallpaperResolution resolution) { std::string file_name = GURL(url).ExtractFileName(); - if (resolution == WallpaperControllerImpl::WALLPAPER_RESOLUTION_SMALL) { + if (resolution == WallpaperController::WALLPAPER_RESOLUTION_SMALL) { file_name = base::FilePath(file_name) .InsertBeforeExtension(kSmallWallpaperSuffix) .value(); @@ -147,11 +146,11 @@ // Returns wallpaper subdirectory name for current resolution. std::string GetCustomWallpaperSubdirForCurrentResolution() { - WallpaperControllerImpl::WallpaperResolution resolution = + WallpaperController::WallpaperResolution resolution = GetAppropriateResolution(); - return resolution == WallpaperControllerImpl::WALLPAPER_RESOLUTION_SMALL - ? WallpaperControllerImpl::kSmallWallpaperSubDir - : WallpaperControllerImpl::kLargeWallpaperSubDir; + return resolution == WallpaperController::WALLPAPER_RESOLUTION_SMALL + ? WallpaperController::kSmallWallpaperSubDir + : WallpaperController::kLargeWallpaperSubDir; } // Resizes |image| to a resolution which is nearest to |preferred_width| and @@ -295,21 +294,21 @@ // Creates all new custom wallpaper directories for |wallpaper_files_id| if they // don't exist. void EnsureCustomWallpaperDirectories(const std::string& wallpaper_files_id) { - base::FilePath dir = WallpaperControllerImpl::GetCustomWallpaperDir( - WallpaperControllerImpl::kSmallWallpaperSubDir) + base::FilePath dir = WallpaperController::GetCustomWallpaperDir( + WallpaperController::kSmallWallpaperSubDir) .Append(wallpaper_files_id); if (!base::PathExists(dir)) base::CreateDirectory(dir); - dir = WallpaperControllerImpl::GetCustomWallpaperDir( - WallpaperControllerImpl::kLargeWallpaperSubDir) + dir = WallpaperController::GetCustomWallpaperDir( + WallpaperController::kLargeWallpaperSubDir) .Append(wallpaper_files_id); if (!base::PathExists(dir)) base::CreateDirectory(dir); - dir = WallpaperControllerImpl::GetCustomWallpaperDir( - WallpaperControllerImpl::kOriginalWallpaperSubDir) + dir = WallpaperController::GetCustomWallpaperDir( + WallpaperController::kOriginalWallpaperSubDir) .Append(wallpaper_files_id); if (!base::PathExists(dir)) base::CreateDirectory(dir); @@ -321,27 +320,27 @@ const base::FilePath& original_path, WallpaperLayout layout, gfx::ImageSkia image) { - base::DeleteFile(WallpaperControllerImpl::GetCustomWallpaperDir( - WallpaperControllerImpl::kOriginalWallpaperSubDir) + base::DeleteFile(WallpaperController::GetCustomWallpaperDir( + WallpaperController::kOriginalWallpaperSubDir) .Append(wallpaper_files_id), true /* recursive */); - base::DeleteFile(WallpaperControllerImpl::GetCustomWallpaperDir( - WallpaperControllerImpl::kSmallWallpaperSubDir) + base::DeleteFile(WallpaperController::GetCustomWallpaperDir( + WallpaperController::kSmallWallpaperSubDir) .Append(wallpaper_files_id), true /* recursive */); - base::DeleteFile(WallpaperControllerImpl::GetCustomWallpaperDir( - WallpaperControllerImpl::kLargeWallpaperSubDir) + base::DeleteFile(WallpaperController::GetCustomWallpaperDir( + WallpaperController::kLargeWallpaperSubDir) .Append(wallpaper_files_id), true /* recursive */); EnsureCustomWallpaperDirectories(wallpaper_files_id); const std::string file_name = original_path.BaseName().value(); const base::FilePath small_wallpaper_path = - WallpaperControllerImpl::GetCustomWallpaperPath( - WallpaperControllerImpl::kSmallWallpaperSubDir, wallpaper_files_id, + WallpaperController::GetCustomWallpaperPath( + WallpaperController::kSmallWallpaperSubDir, wallpaper_files_id, file_name); const base::FilePath large_wallpaper_path = - WallpaperControllerImpl::GetCustomWallpaperPath( - WallpaperControllerImpl::kLargeWallpaperSubDir, wallpaper_files_id, + WallpaperController::GetCustomWallpaperPath( + WallpaperController::kLargeWallpaperSubDir, wallpaper_files_id, file_name); // Re-encode orginal file to jpeg format and saves the result in case that @@ -365,30 +364,28 @@ *active_user_type == user_manager::USER_TYPE_KIOSK_APP; } -// Returns the currently active user session (at index 0). -const UserSession* GetActiveUserSession() { - return Shell::Get()->session_controller()->GetUserSession(/*user index=*/0); -} - // Checks if |account_id| is the current active user. bool IsActiveUser(const AccountId& account_id) { - const UserSession* const session = GetActiveUserSession(); - return session && session->user_info.account_id == account_id; + // The current active user has index 0. + const UserSession* const active_user_session = + Shell::Get()->session_controller()->GetUserSession(/*user index=*/0); + return active_user_session && + active_user_session->user_info.account_id == account_id; } // Returns the file path of the wallpaper corresponding to |url| if it exists in // local file system, otherwise returns an empty file path. base::FilePath GetExistingOnlineWallpaperPath(const std::string& url) { - WallpaperControllerImpl::WallpaperResolution resolution = + WallpaperController::WallpaperResolution resolution = GetAppropriateResolution(); base::FilePath wallpaper_path = GetOnlineWallpaperPath(url, resolution); if (base::PathExists(wallpaper_path)) return wallpaper_path; // Falls back to the large wallpaper if the small one doesn't exist. - if (resolution == WallpaperControllerImpl::WALLPAPER_RESOLUTION_SMALL) { + if (resolution == WallpaperController::WALLPAPER_RESOLUTION_SMALL) { wallpaper_path = GetOnlineWallpaperPath( - url, WallpaperControllerImpl::WALLPAPER_RESOLUTION_LARGE); + url, WallpaperController::WALLPAPER_RESOLUTION_LARGE); if (base::PathExists(wallpaper_path)) return wallpaper_path; } @@ -407,18 +404,18 @@ } ResizeAndSaveWallpaper( image, - GetOnlineWallpaperPath( - url, WallpaperControllerImpl::WALLPAPER_RESOLUTION_LARGE), + GetOnlineWallpaperPath(url, + WallpaperController::WALLPAPER_RESOLUTION_LARGE), layout, image.width(), image.height()); ResizeAndSaveWallpaper( image, - GetOnlineWallpaperPath( - url, WallpaperControllerImpl::WALLPAPER_RESOLUTION_SMALL), + GetOnlineWallpaperPath(url, + WallpaperController::WALLPAPER_RESOLUTION_SMALL), WALLPAPER_LAYOUT_CENTER_CROPPED, kSmallWallpaperMaxWidth, kSmallWallpaperMaxHeight); } -// Implementation of |WallpaperControllerImpl::GetOfflineWallpaper|. +// Implementation of |WallpaperController::GetOfflineWallpaper|. std::vector<std::string> GetOfflineWallpaperListImpl() { DCHECK(!GlobalChromeOSWallpapersDir().empty()); std::vector<std::string> url_list; @@ -441,11 +438,11 @@ } // namespace -const char WallpaperControllerImpl::kSmallWallpaperSubDir[] = "small"; -const char WallpaperControllerImpl::kLargeWallpaperSubDir[] = "large"; -const char WallpaperControllerImpl::kOriginalWallpaperSubDir[] = "original"; +const char WallpaperController::kSmallWallpaperSubDir[] = "small"; +const char WallpaperController::kLargeWallpaperSubDir[] = "large"; +const char WallpaperController::kOriginalWallpaperSubDir[] = "original"; -WallpaperControllerImpl::WallpaperControllerImpl(PrefService* local_state) +WallpaperController::WallpaperController(PrefService* local_state) : locked_(false), wallpaper_mode_(WALLPAPER_NONE), color_profiles_(GetProminentColorProfiles()), @@ -456,8 +453,6 @@ scoped_session_observer_(this), local_state_(local_state), weak_factory_(this) { - DCHECK(!g_instance_); - g_instance_ = this; DCHECK(!color_profiles_.empty()); prominent_colors_ = std::vector<SkColor>(color_profiles_.size(), kInvalidWallpaperColor); @@ -465,7 +460,7 @@ Shell::Get()->AddShellObserver(this); } -WallpaperControllerImpl::~WallpaperControllerImpl() { +WallpaperController::~WallpaperController() { if (current_wallpaper_) current_wallpaper_->RemoveObserver(this); if (color_calculator_) @@ -473,19 +468,17 @@ Shell::Get()->window_tree_host_manager()->RemoveObserver(this); Shell::Get()->RemoveShellObserver(this); weak_factory_.InvalidateWeakPtrs(); - DCHECK_EQ(g_instance_, this); - g_instance_ = nullptr; } // static -void WallpaperControllerImpl::RegisterLocalStatePrefs( +void WallpaperController::RegisterLocalStatePrefs( PrefRegistrySimple* registry) { registry->RegisterDictionaryPref(prefs::kUserWallpaperInfo); registry->RegisterDictionaryPref(prefs::kWallpaperColors); } // static -gfx::Size WallpaperControllerImpl::GetMaxDisplaySizeInNative() { +gfx::Size WallpaperController::GetMaxDisplaySizeInNative() { // Return an empty size for test environments where the screen is null. if (!display::Screen::GetScreen()) return gfx::Size(); @@ -509,7 +502,7 @@ } // static -base::FilePath WallpaperControllerImpl::GetCustomWallpaperPath( +base::FilePath WallpaperController::GetCustomWallpaperPath( const std::string& sub_dir, const std::string& wallpaper_files_id, const std::string& file_name) { @@ -518,21 +511,21 @@ } // static -base::FilePath WallpaperControllerImpl::GetCustomWallpaperDir( +base::FilePath WallpaperController::GetCustomWallpaperDir( const std::string& sub_dir) { DCHECK(!GlobalChromeOSCustomWallpapersDir().empty()); return GlobalChromeOSCustomWallpapersDir().Append(sub_dir); } // static -void WallpaperControllerImpl::SetWallpaperFromPath( +void WallpaperController::SetWallpaperFromPath( const AccountId& account_id, const user_manager::UserType& user_type, const WallpaperInfo& info, const base::FilePath& wallpaper_path, bool show_wallpaper, const scoped_refptr<base::SingleThreadTaskRunner>& reply_task_runner, - base::WeakPtr<WallpaperControllerImpl> weak_ptr) { + base::WeakPtr<WallpaperController> weak_ptr) { base::FilePath valid_path = wallpaper_path; if (!base::PathExists(valid_path)) { // Falls back to the original file if the file with correct resolution does @@ -547,37 +540,51 @@ << " doesn't exist. Falls back to default wallpaper."; reply_task_runner->PostTask( FROM_HERE, - base::BindOnce(&WallpaperControllerImpl::SetDefaultWallpaperImpl, - weak_ptr, account_id, user_type, show_wallpaper)); + base::BindOnce(&WallpaperController::SetDefaultWallpaperImpl, weak_ptr, + account_id, user_type, show_wallpaper)); } else { reply_task_runner->PostTask( - FROM_HERE, base::BindOnce(&WallpaperControllerImpl::StartDecodeFromPath, + FROM_HERE, base::BindOnce(&WallpaperController::StartDecodeFromPath, weak_ptr, account_id, user_type, valid_path, info, show_wallpaper)); } } -SkColor WallpaperControllerImpl::GetProminentColor( +void WallpaperController::BindRequest( + mojom::WallpaperControllerRequest request) { + bindings_.AddBinding(this, std::move(request)); +} + +void WallpaperController::AddObserver(WallpaperControllerObserver* observer) { + observers_.AddObserver(observer); +} + +void WallpaperController::RemoveObserver( + WallpaperControllerObserver* observer) { + observers_.RemoveObserver(observer); +} + +SkColor WallpaperController::GetProminentColor( ColorProfile color_profile) const { ColorProfileType type = GetColorProfileType(color_profile); return prominent_colors_[static_cast<int>(type)]; } -gfx::ImageSkia WallpaperControllerImpl::GetWallpaper() const { +gfx::ImageSkia WallpaperController::GetWallpaper() const { return current_wallpaper_ ? current_wallpaper_->image() : gfx::ImageSkia(); } -WallpaperLayout WallpaperControllerImpl::GetWallpaperLayout() const { +WallpaperLayout WallpaperController::GetWallpaperLayout() const { return current_wallpaper_ ? current_wallpaper_->wallpaper_info().layout : NUM_WALLPAPER_LAYOUT; } -WallpaperType WallpaperControllerImpl::GetWallpaperType() const { +WallpaperType WallpaperController::GetWallpaperType() const { return current_wallpaper_ ? current_wallpaper_->wallpaper_info().type : WALLPAPER_TYPE_COUNT; } -bool WallpaperControllerImpl::ShouldShowInitialAnimation() { +bool WallpaperController::ShouldShowInitialAnimation() { // The slower initial animation is only applicable if: // 1) It's the first run after system boot, not after user sign-out. if (!base::CommandLine::ForCurrentProcess()->HasSwitch( @@ -598,7 +605,7 @@ return true; } -void WallpaperControllerImpl::OnWallpaperAnimationFinished() { +void WallpaperController::OnWallpaperAnimationFinished() { // TODO(crbug.com/875128): Remove this after web-ui login code is completely // removed. if (wallpaper_controller_client_ && is_first_wallpaper_) { @@ -606,19 +613,19 @@ } } -bool WallpaperControllerImpl::CanOpenWallpaperPicker() { - return ShouldShowWallpaperSetting() && - !IsActiveUserWallpaperControlledByPolicy(); +bool WallpaperController::CanOpenWallpaperPicker() { + return ShouldShowWallpaperSettingImpl() && + !IsActiveUserWallpaperControlledByPolicyImpl(); } -bool WallpaperControllerImpl::HasShownAnyWallpaper() const { +bool WallpaperController::HasShownAnyWallpaper() const { return !!current_wallpaper_; } -void WallpaperControllerImpl::ShowWallpaperImage(const gfx::ImageSkia& image, - WallpaperInfo info, - bool preview_mode, - bool always_on_top) { +void WallpaperController::ShowWallpaperImage(const gfx::ImageSkia& image, + WallpaperInfo info, + bool preview_mode, + bool always_on_top) { // Prevent showing other wallpapers if there is an always-on-top wallpaper. if (is_always_on_top_wallpaper_ && !always_on_top) return; @@ -665,22 +672,23 @@ for (auto& observer : observers_) observer.OnFirstWallpaperShown(); } - for (auto& observer : observers_) - observer.OnWallpaperChanged(); + mojo_observers_.ForAllPtrs([this](mojom::WallpaperObserver* observer) { + observer->OnWallpaperChanged(current_wallpaper_->original_image_id()); + }); wallpaper_mode_ = WALLPAPER_IMAGE; InstallDesktopControllerForAllWindows(); ++wallpaper_count_for_testing_; } -bool WallpaperControllerImpl::IsPolicyControlled(const AccountId& account_id, - bool is_ephemeral) const { +bool WallpaperController::IsPolicyControlled(const AccountId& account_id, + bool is_ephemeral) const { WallpaperInfo info; return GetUserWallpaperInfo(account_id, &info, is_ephemeral) && info.type == POLICY; } -void WallpaperControllerImpl::UpdateWallpaperBlur(bool blur) { +void WallpaperController::UpdateWallpaperBlur(bool blur) { bool needs_blur = blur && IsBlurAllowed(); if (needs_blur == is_wallpaper_blurred_) return; @@ -693,9 +701,12 @@ is_wallpaper_blurred_ = needs_blur; for (auto& observer : observers_) observer.OnWallpaperBlurChanged(); + mojo_observers_.ForAllPtrs([this](mojom::WallpaperObserver* observer) { + observer->OnWallpaperBlurChanged(is_wallpaper_blurred_); + }); } -bool WallpaperControllerImpl::ShouldApplyDimming() const { +bool WallpaperController::ShouldApplyDimming() const { // Dim the wallpaper in a blocked user session or in tablet mode unless during // wallpaper preview. const bool should_dim = @@ -707,17 +718,17 @@ return should_dim && !IsOneShotWallpaper(); } -bool WallpaperControllerImpl::IsBlurAllowed() const { +bool WallpaperController::IsBlurAllowed() const { return !IsDevicePolicyWallpaper() && !IsOneShotWallpaper(); } -bool WallpaperControllerImpl::IsWallpaperBlurred() const { +bool WallpaperController::IsWallpaperBlurred() const { return is_wallpaper_blurred_; } -bool WallpaperControllerImpl::SetUserWallpaperInfo(const AccountId& account_id, - const WallpaperInfo& info, - bool is_ephemeral) { +bool WallpaperController::SetUserWallpaperInfo(const AccountId& account_id, + const WallpaperInfo& info, + bool is_ephemeral) { if (is_ephemeral) { ephemeral_users_wallpaper_info_[account_id] = info; return true; @@ -749,9 +760,9 @@ return true; } -bool WallpaperControllerImpl::GetUserWallpaperInfo(const AccountId& account_id, - WallpaperInfo* info, - bool is_ephemeral) const { +bool WallpaperController::GetUserWallpaperInfo(const AccountId& account_id, + WallpaperInfo* info, + bool is_ephemeral) const { if (is_ephemeral) { // Ephemeral users do not save anything to local state. Return true if the // info can be found in the map, otherwise return false. @@ -796,8 +807,8 @@ return true; } -bool WallpaperControllerImpl::GetWallpaperFromCache(const AccountId& account_id, - gfx::ImageSkia* image) { +bool WallpaperController::GetWallpaperFromCache(const AccountId& account_id, + gfx::ImageSkia* image) { CustomWallpaperMap::const_iterator it = wallpaper_cache_map_.find(account_id); if (it != wallpaper_cache_map_.end() && !it->second.second.isNull()) { *image = it->second.second; @@ -806,8 +817,8 @@ return false; } -bool WallpaperControllerImpl::GetPathFromCache(const AccountId& account_id, - base::FilePath* path) { +bool WallpaperController::GetPathFromCache(const AccountId& account_id, + base::FilePath* path) { CustomWallpaperMap::const_iterator it = wallpaper_cache_map_.find(account_id); if (it != wallpaper_cache_map_.end()) { *path = it->second.first; @@ -816,7 +827,7 @@ return false; } -void WallpaperControllerImpl::AddFirstWallpaperAnimationEndCallback( +void WallpaperController::AddFirstWallpaperAnimationEndCallback( base::OnceClosure callback, aura::Window* window) { WallpaperWidgetController* wallpaper_widget_controller = @@ -830,58 +841,57 @@ } } -void WallpaperControllerImpl::StartDecodeFromPath( +void WallpaperController::StartDecodeFromPath( const AccountId& account_id, const user_manager::UserType& user_type, const base::FilePath& wallpaper_path, const WallpaperInfo& info, bool show_wallpaper) { ReadAndDecodeWallpaper( - base::BindOnce(&WallpaperControllerImpl::OnWallpaperDecoded, + base::BindOnce(&WallpaperController::OnWallpaperDecoded, weak_factory_.GetWeakPtr(), account_id, user_type, wallpaper_path, info, show_wallpaper), sequenced_task_runner_, wallpaper_path); } -void WallpaperControllerImpl::Init( - WallpaperControllerClient* client, +void WallpaperController::Init( + mojom::WallpaperControllerClientPtr client, const base::FilePath& user_data_path, const base::FilePath& chromeos_wallpapers_path, const base::FilePath& chromeos_custom_wallpapers_path, const base::FilePath& device_policy_wallpaper_path) { - DCHECK(!wallpaper_controller_client_); + DCHECK(!wallpaper_controller_client_.get()); + wallpaper_controller_client_ = std::move(client); + DCHECK(local_state_); - wallpaper_controller_client_ = client; + wallpaper_controller_client_->OnReadyToSetWallpaper(); SetGlobalUserDataDir(user_data_path); SetGlobalChromeOSWallpapersDir(chromeos_wallpapers_path); SetGlobalChromeOSCustomWallpapersDir(chromeos_custom_wallpapers_path); SetDevicePolicyWallpaperPath(device_policy_wallpaper_path); - - wallpaper_controller_client_->OnReadyToSetWallpaper(); } -void WallpaperControllerImpl::SetCustomWallpaper( - const WallpaperUserInfo& user_info, +void WallpaperController::SetCustomWallpaper( + mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id, const std::string& file_name, WallpaperLayout layout, const gfx::ImageSkia& image, bool preview_mode) { DCHECK(Shell::Get()->session_controller()->IsActiveUserSessionStarted()); - if (!CanSetUserWallpaper(user_info.account_id, user_info.is_ephemeral)) + if (!CanSetUserWallpaper(user_info->account_id, user_info->is_ephemeral)) return; - const bool is_active_user = IsActiveUser(user_info.account_id); + const bool is_active_user = IsActiveUser(user_info->account_id); if (preview_mode) { DCHECK(is_active_user); - confirm_preview_wallpaper_callback_ = - base::BindOnce(&WallpaperControllerImpl::SaveAndSetWallpaper, - weak_factory_.GetWeakPtr(), user_info, - wallpaper_files_id, file_name, CUSTOMIZED, layout, - /*show_wallpaper=*/false, image); + confirm_preview_wallpaper_callback_ = base::BindOnce( + &WallpaperController::SaveAndSetWallpaper, weak_factory_.GetWeakPtr(), + std::move(user_info), wallpaper_files_id, file_name, CUSTOMIZED, layout, + /*show_wallpaper=*/false, image); reload_preview_wallpaper_callback_ = - base::BindRepeating(&WallpaperControllerImpl::ShowWallpaperImage, + base::BindRepeating(&WallpaperController::ShowWallpaperImage, weak_factory_.GetWeakPtr(), image, WallpaperInfo{std::string(), layout, CUSTOMIZED, base::Time::Now().LocalMidnight()}, @@ -889,46 +899,49 @@ // Show the preview wallpaper. reload_preview_wallpaper_callback_.Run(); } else { - SaveAndSetWallpaper(user_info, wallpaper_files_id, file_name, CUSTOMIZED, - layout, /*show_wallpaper=*/is_active_user, image); + SaveAndSetWallpaper(std::move(user_info), wallpaper_files_id, file_name, + CUSTOMIZED, layout, /*show_wallpaper=*/is_active_user, + image); } } -void WallpaperControllerImpl::SetOnlineWallpaperIfExists( - const WallpaperUserInfo& user_info, +void WallpaperController::SetOnlineWallpaperIfExists( + mojom::WallpaperUserInfoPtr user_info, const std::string& url, WallpaperLayout layout, bool preview_mode, SetOnlineWallpaperIfExistsCallback callback) { DCHECK(Shell::Get()->session_controller()->IsActiveUserSessionStarted()); - DCHECK(CanSetUserWallpaper(user_info.account_id, user_info.is_ephemeral)); + DCHECK(CanSetUserWallpaper(user_info->account_id, user_info->is_ephemeral)); - const OnlineWallpaperParams params = { - user_info.account_id, user_info.is_ephemeral, url, layout, preview_mode}; + const OnlineWallpaperParams params = {user_info->account_id, + user_info->is_ephemeral, url, layout, + preview_mode}; base::PostTaskAndReplyWithResult( sequenced_task_runner_.get(), FROM_HERE, base::BindOnce(&GetExistingOnlineWallpaperPath, url), - base::BindOnce(&WallpaperControllerImpl::SetOnlineWallpaperFromPath, + base::BindOnce(&WallpaperController::SetOnlineWallpaperFromPath, weak_factory_.GetWeakPtr(), std::move(callback), params)); } -void WallpaperControllerImpl::SetOnlineWallpaperFromData( - const WallpaperUserInfo& user_info, +void WallpaperController::SetOnlineWallpaperFromData( + mojom::WallpaperUserInfoPtr user_info, const std::string& image_data, const std::string& url, WallpaperLayout layout, bool preview_mode, SetOnlineWallpaperFromDataCallback callback) { if (!Shell::Get()->session_controller()->IsActiveUserSessionStarted() || - !CanSetUserWallpaper(user_info.account_id, user_info.is_ephemeral)) { + !CanSetUserWallpaper(user_info->account_id, user_info->is_ephemeral)) { std::move(callback).Run(/*success=*/false); return; } - const OnlineWallpaperParams params = { - user_info.account_id, user_info.is_ephemeral, url, layout, preview_mode}; + const OnlineWallpaperParams params = {user_info->account_id, + user_info->is_ephemeral, url, layout, + preview_mode}; LoadedCallback decoded_callback = - base::BindOnce(&WallpaperControllerImpl::OnOnlineWallpaperDecoded, + base::BindOnce(&WallpaperController::OnOnlineWallpaperDecoded, weak_factory_.GetWeakPtr(), params, /*save_file=*/true, std::move(callback)); if (bypass_decode_for_testing_) { @@ -944,26 +957,27 @@ std::move(decoded_callback)); } -void WallpaperControllerImpl::SetDefaultWallpaper( - const WallpaperUserInfo& user_info, +void WallpaperController::SetDefaultWallpaper( + mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id, bool show_wallpaper) { - if (!CanSetUserWallpaper(user_info.account_id, user_info.is_ephemeral)) + if (!CanSetUserWallpaper(user_info->account_id, user_info->is_ephemeral)) return; - RemoveUserWallpaper(user_info, wallpaper_files_id); - if (!InitializeUserWallpaperInfo(user_info.account_id, - user_info.is_ephemeral)) { + const AccountId account_id = user_info->account_id; + const bool is_ephemeral = user_info->is_ephemeral; + const user_manager::UserType type = user_info->type; + + RemoveUserWallpaper(std::move(user_info), wallpaper_files_id); + if (!InitializeUserWallpaperInfo(account_id, is_ephemeral)) { LOG(ERROR) << "Initializing user wallpaper info fails. This should never " "happen except in tests."; } - if (show_wallpaper) { - SetDefaultWallpaperImpl(user_info.account_id, user_info.type, - /*show_wallpaper=*/true); - } + if (show_wallpaper) + SetDefaultWallpaperImpl(account_id, type, /*show_wallpaper=*/true); } -void WallpaperControllerImpl::SetCustomizedDefaultWallpaperPaths( +void WallpaperController::SetCustomizedDefaultWallpaperPaths( const base::FilePath& customized_default_small_path, const base::FilePath& customized_default_large_path) { customized_default_small_path_ = customized_default_small_path; @@ -980,8 +994,8 @@ show_wallpaper); } -void WallpaperControllerImpl::SetPolicyWallpaper( - const WallpaperUserInfo& user_info, +void WallpaperController::SetPolicyWallpaper( + mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id, const std::string& data) { // There is no visible wallpaper in kiosk mode. @@ -992,9 +1006,9 @@ const bool show_wallpaper = Shell::Get()->session_controller()->IsActiveUserSessionStarted(); LoadedCallback callback = base::BindOnce( - &WallpaperControllerImpl::SaveAndSetWallpaper, weak_factory_.GetWeakPtr(), - user_info, wallpaper_files_id, kPolicyWallpaperFile, POLICY, - WALLPAPER_LAYOUT_CENTER_CROPPED, show_wallpaper); + &WallpaperController::SaveAndSetWallpaper, weak_factory_.GetWeakPtr(), + base::Passed(&user_info), wallpaper_files_id, kPolicyWallpaperFile, + POLICY, WALLPAPER_LAYOUT_CENTER_CROPPED, show_wallpaper); if (bypass_decode_for_testing_) { std::move(callback).Run(CreateSolidColorWallpaper(kDefaultWallpaperColor)); @@ -1006,7 +1020,7 @@ std::move(callback)); } -void WallpaperControllerImpl::SetDevicePolicyWallpaperPath( +void WallpaperController::SetDevicePolicyWallpaperPath( const base::FilePath& device_policy_wallpaper_path) { const bool was_device_policy_wallpaper_enforced = !device_policy_wallpaper_path_.empty(); @@ -1024,24 +1038,27 @@ } } -bool WallpaperControllerImpl::SetThirdPartyWallpaper( - const WallpaperUserInfo& user_info, +void WallpaperController::SetThirdPartyWallpaper( + mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id, const std::string& file_name, WallpaperLayout layout, - const gfx::ImageSkia& image) { + const gfx::ImageSkia& image, + SetThirdPartyWallpaperCallback callback) { + const uint32_t image_id = WallpaperResizer::GetImageId(image); bool allowed_to_set_wallpaper = - CanSetUserWallpaper(user_info.account_id, user_info.is_ephemeral); - bool allowed_to_show_wallpaper = IsActiveUser(user_info.account_id); + CanSetUserWallpaper(user_info->account_id, user_info->is_ephemeral); + bool allowed_to_show_wallpaper = IsActiveUser(user_info->account_id); + std::move(callback).Run(allowed_to_set_wallpaper && allowed_to_show_wallpaper, + image_id); if (allowed_to_set_wallpaper) { - SaveAndSetWallpaper(user_info, wallpaper_files_id, file_name, CUSTOMIZED, - layout, allowed_to_show_wallpaper, image); + SaveAndSetWallpaper(std::move(user_info), wallpaper_files_id, file_name, + CUSTOMIZED, layout, allowed_to_show_wallpaper, image); } - return allowed_to_set_wallpaper && allowed_to_show_wallpaper; } -void WallpaperControllerImpl::ConfirmPreviewWallpaper() { +void WallpaperController::ConfirmPreviewWallpaper() { if (!confirm_preview_wallpaper_callback_) { DCHECK(!reload_preview_wallpaper_callback_); return; @@ -1052,7 +1069,7 @@ observer.OnWallpaperPreviewEnded(); } -void WallpaperControllerImpl::CancelPreviewWallpaper() { +void WallpaperController::CancelPreviewWallpaper() { if (!confirm_preview_wallpaper_callback_) { DCHECK(!reload_preview_wallpaper_callback_); return; @@ -1064,18 +1081,21 @@ observer.OnWallpaperPreviewEnded(); } -void WallpaperControllerImpl::UpdateCustomWallpaperLayout( - const WallpaperUserInfo& user_info, +void WallpaperController::UpdateCustomWallpaperLayout( + mojom::WallpaperUserInfoPtr user_info, WallpaperLayout layout) { // This method has a very specific use case: the user should be active and // have a custom wallpaper. - const UserSession* const session = GetActiveUserSession(); - if (!session || session->user_info.account_id != user_info.account_id) + // The currently active user has index 0. + const UserSession* const active_user_session = + Shell::Get()->session_controller()->GetUserSession(/*user index=*/0); + if (!active_user_session || + active_user_session->user_info.account_id != user_info->account_id) { return; - + } WallpaperInfo info; - if (!GetUserWallpaperInfo(user_info.account_id, &info, - user_info.is_ephemeral) || + if (!GetUserWallpaperInfo(user_info->account_id, &info, + user_info->is_ephemeral) || info.type != CUSTOMIZED) { return; } @@ -1083,20 +1103,21 @@ return; info.layout = layout; - if (!SetUserWallpaperInfo(user_info.account_id, info, - user_info.is_ephemeral)) { + if (!SetUserWallpaperInfo(user_info->account_id, info, + user_info->is_ephemeral)) { LOG(ERROR) << "Setting user wallpaper info fails. This should never happen " "except in tests."; } - ShowUserWallpaper(user_info); + ShowUserWallpaper(std::move(user_info)); } -void WallpaperControllerImpl::ShowUserWallpaper( - const WallpaperUserInfo& user_info) { - current_user_ = user_info; +void WallpaperController::ShowUserWallpaper( + mojom::WallpaperUserInfoPtr user_info) { + current_user_ = std::move(user_info); + const user_manager::UserType user_type = current_user_->type; - if (current_user_.type == user_manager::USER_TYPE_KIOSK_APP || - current_user_.type == user_manager::USER_TYPE_ARC_KIOSK_APP) { + if (user_type == user_manager::USER_TYPE_KIOSK_APP || + user_type == user_manager::USER_TYPE_ARC_KIOSK_APP) { return; } @@ -1105,8 +1126,8 @@ return; } - const AccountId account_id = current_user_.account_id; - const bool is_ephemeral = current_user_.is_ephemeral; + const AccountId account_id = current_user_->account_id; + const bool is_ephemeral = current_user_->is_ephemeral; WallpaperInfo info; if (!GetUserWallpaperInfo(account_id, &info, is_ephemeral)) { if (!InitializeUserWallpaperInfo(account_id, is_ephemeral)) @@ -1129,14 +1150,14 @@ } if (info.type == DEFAULT) { - SetDefaultWallpaperImpl(account_id, current_user_.type, + SetDefaultWallpaperImpl(account_id, current_user_->type, /*show_wallpaper=*/true); return; } if (info.type != CUSTOMIZED && info.type != POLICY && info.type != DEVICE) { // Load wallpaper according to WallpaperInfo. - SetWallpaperFromInfo(account_id, current_user_.type, info, + SetWallpaperFromInfo(account_id, current_user_->type, info, /*show_wallpaper=*/true); return; } @@ -1168,14 +1189,14 @@ sequenced_task_runner_->PostTask( FROM_HERE, - base::BindOnce(&SetWallpaperFromPath, account_id, current_user_.type, + base::BindOnce(&SetWallpaperFromPath, account_id, current_user_->type, info, wallpaper_path, /*show_wallpaper=*/true, base::ThreadTaskRunnerHandle::Get(), weak_factory_.GetWeakPtr())); } -void WallpaperControllerImpl::ShowSigninWallpaper() { - current_user_ = WallpaperUserInfo(); +void WallpaperController::ShowSigninWallpaper() { + current_user_.reset(); if (ShouldSetDevicePolicyWallpaper()) { SetDevicePolicyWallpaper(); } else { @@ -1184,8 +1205,7 @@ } } -void WallpaperControllerImpl::ShowOneShotWallpaper( - const gfx::ImageSkia& image) { +void WallpaperController::ShowOneShotWallpaper(const gfx::ImageSkia& image) { const WallpaperInfo info = { std::string(), WallpaperLayout::WALLPAPER_LAYOUT_STRETCH, WallpaperType::ONE_SHOT, base::Time::Now().LocalMidnight()}; @@ -1193,19 +1213,19 @@ /*always_on_top=*/false); } -void WallpaperControllerImpl::ShowAlwaysOnTopWallpaper( +void WallpaperController::ShowAlwaysOnTopWallpaper( const base::FilePath& image_path) { is_always_on_top_wallpaper_ = true; const WallpaperInfo info = { std::string(), WallpaperLayout::WALLPAPER_LAYOUT_CENTER_CROPPED, WallpaperType::ONE_SHOT, base::Time::Now().LocalMidnight()}; ReadAndDecodeWallpaper( - base::BindOnce(&WallpaperControllerImpl::OnAlwaysOnTopWallpaperDecoded, + base::BindOnce(&WallpaperController::OnAlwaysOnTopWallpaperDecoded, weak_factory_.GetWeakPtr(), info), sequenced_task_runner_, image_path); } -void WallpaperControllerImpl::RemoveAlwaysOnTopWallpaper() { +void WallpaperController::RemoveAlwaysOnTopWallpaper() { if (!is_always_on_top_wallpaper_) { DCHECK(!reload_always_on_top_wallpaper_callback_); return; @@ -1215,17 +1235,17 @@ ReloadWallpaper(/*clear_cache=*/false); } -void WallpaperControllerImpl::RemoveUserWallpaper( - const WallpaperUserInfo& user_info, +void WallpaperController::RemoveUserWallpaper( + mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id) { - RemoveUserWallpaperInfo(user_info.account_id, user_info.is_ephemeral); - RemoveUserWallpaperImpl(user_info.account_id, wallpaper_files_id); + RemoveUserWallpaperInfo(user_info->account_id, user_info->is_ephemeral); + RemoveUserWallpaperImpl(user_info->account_id, wallpaper_files_id); } -void WallpaperControllerImpl::RemovePolicyWallpaper( - const WallpaperUserInfo& user_info, +void WallpaperController::RemovePolicyWallpaper( + mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id) { - if (!IsPolicyControlled(user_info.account_id, user_info.is_ephemeral)) + if (!IsPolicyControlled(user_info->account_id, user_info->is_ephemeral)) return; // Updates the screen only when the user has logged in. @@ -1233,29 +1253,29 @@ Shell::Get()->session_controller()->IsActiveUserSessionStarted(); // Removes the wallpaper info so that the user is no longer policy controlled, // otherwise setting default wallpaper is not allowed. - RemoveUserWallpaperInfo(user_info.account_id, user_info.is_ephemeral); - SetDefaultWallpaper(user_info, wallpaper_files_id, show_wallpaper); + RemoveUserWallpaperInfo(user_info->account_id, user_info->is_ephemeral); + SetDefaultWallpaper(std::move(user_info), wallpaper_files_id, show_wallpaper); } -void WallpaperControllerImpl::GetOfflineWallpaperList( +void WallpaperController::GetOfflineWallpaperList( GetOfflineWallpaperListCallback callback) { base::PostTaskAndReplyWithResult(sequenced_task_runner_.get(), FROM_HERE, base::BindOnce(&GetOfflineWallpaperListImpl), std::move(callback)); } -void WallpaperControllerImpl::SetAnimationDuration( +void WallpaperController::SetAnimationDuration( base::TimeDelta animation_duration) { animation_duration_ = animation_duration; } -void WallpaperControllerImpl::OpenWallpaperPickerIfAllowed() { +void WallpaperController::OpenWallpaperPickerIfAllowed() { if (wallpaper_controller_client_ && CanOpenWallpaperPicker()) { wallpaper_controller_client_->OpenWallpaperPicker(); } } -void WallpaperControllerImpl::MinimizeInactiveWindows( +void WallpaperController::MinimizeInactiveWindows( const std::string& user_id_hash) { if (!window_state_manager_) window_state_manager_ = std::make_unique<WallpaperWindowStateManager>(); @@ -1263,7 +1283,7 @@ window_state_manager_->MinimizeInactiveWindows(user_id_hash); } -void WallpaperControllerImpl::RestoreMinimizedWindows( +void WallpaperController::RestoreMinimizedWindows( const std::string& user_id_hash) { if (!window_state_manager_) { NOTREACHED() << "This should only be called after calling " @@ -1273,62 +1293,50 @@ window_state_manager_->RestoreMinimizedWindows(user_id_hash); } -void WallpaperControllerImpl::AddObserver( - WallpaperControllerObserver* observer) { - observers_.AddObserver(observer); +void WallpaperController::AddObserver( + mojom::WallpaperObserverAssociatedPtrInfo observer) { + mojom::WallpaperObserverAssociatedPtr observer_ptr; + observer_ptr.Bind(std::move(observer)); + observer_ptr->OnWallpaperColorsChanged(prominent_colors_); + mojo_observers_.AddPtr(std::move(observer_ptr)); } -void WallpaperControllerImpl::RemoveObserver( - WallpaperControllerObserver* observer) { - observers_.RemoveObserver(observer); +void WallpaperController::GetWallpaperImage( + GetWallpaperImageCallback callback) { + std::move(callback).Run(GetWallpaper()); } -gfx::ImageSkia WallpaperControllerImpl::GetWallpaperImage() { - return GetWallpaper(); +void WallpaperController::GetWallpaperColors( + GetWallpaperColorsCallback callback) { + std::move(callback).Run(prominent_colors_); } -const std::vector<SkColor>& WallpaperControllerImpl::GetWallpaperColors() { - return prominent_colors_; +void WallpaperController::IsWallpaperBlurred( + IsWallpaperBlurredCallback callback) { + std::move(callback).Run(is_wallpaper_blurred_); } -bool WallpaperControllerImpl::IsWallpaperBlurred() { - return is_wallpaper_blurred_; +void WallpaperController::IsActiveUserWallpaperControlledByPolicy( + IsActiveUserWallpaperControlledByPolicyCallback callback) { + std::move(callback).Run(IsActiveUserWallpaperControlledByPolicyImpl()); } -bool WallpaperControllerImpl::IsActiveUserWallpaperControlledByPolicy() { - const UserSession* const active_user_session = GetActiveUserSession(); - if (!active_user_session) - return false; - return IsPolicyControlled(active_user_session->user_info.account_id, - active_user_session->user_info.is_ephemeral); -} - -WallpaperInfo WallpaperControllerImpl::GetActiveUserWallpaperInfo() { +void WallpaperController::GetActiveUserWallpaperInfo( + GetActiveUserWallpaperInfoCallback callback) { WallpaperInfo info; - const UserSession* const active_user_session = GetActiveUserSession(); - if (!active_user_session || - !GetUserWallpaperInfo(active_user_session->user_info.account_id, &info, - active_user_session->user_info.is_ephemeral)) { - info.location = std::string(); - info.layout = NUM_WALLPAPER_LAYOUT; + if (!GetActiveUserWallpaperInfoImpl(&info)) { + std::move(callback).Run(std::string(), ash::NUM_WALLPAPER_LAYOUT); + return; } - - return info; + std::move(callback).Run(info.location, info.layout); } -bool WallpaperControllerImpl::ShouldShowWallpaperSetting() { - const UserSession* const active_user_session = GetActiveUserSession(); - if (!active_user_session) - return false; - - user_manager::UserType active_user_type = active_user_session->user_info.type; - return active_user_type == user_manager::USER_TYPE_REGULAR || - active_user_type == user_manager::USER_TYPE_PUBLIC_ACCOUNT || - active_user_type == user_manager::USER_TYPE_SUPERVISED || - active_user_type == user_manager::USER_TYPE_CHILD; +void WallpaperController::ShouldShowWallpaperSetting( + ShouldShowWallpaperSettingCallback callback) { + std::move(callback).Run(ShouldShowWallpaperSettingImpl()); } -void WallpaperControllerImpl::OnDisplayConfigurationChanged() { +void WallpaperController::OnDisplayConfigurationChanged() { gfx::Size max_display_size = GetMaxDisplaySizeInNative(); if (current_max_display_size_ == max_display_size) return; @@ -1339,12 +1347,12 @@ GetInternalDisplayCompositorLock(); timer_.Start( FROM_HERE, wallpaper_reload_delay_, - base::BindRepeating(&WallpaperControllerImpl::ReloadWallpaper, + base::BindRepeating(&WallpaperController::ReloadWallpaper, weak_factory_.GetWeakPtr(), /*clear_cache=*/false)); } } -void WallpaperControllerImpl::OnRootWindowAdded(aura::Window* root_window) { +void WallpaperController::OnRootWindowAdded(aura::Window* root_window) { // The wallpaper hasn't been set yet. if (wallpaper_mode_ == WALLPAPER_NONE) return; @@ -1360,20 +1368,20 @@ InstallDesktopController(root_window); } -void WallpaperControllerImpl::OnShellInitialized() { +void WallpaperController::OnShellInitialized() { Shell::Get()->tablet_mode_controller()->AddObserver(this); } -void WallpaperControllerImpl::OnShellDestroying() { +void WallpaperController::OnShellDestroying() { Shell::Get()->tablet_mode_controller()->RemoveObserver(this); } -void WallpaperControllerImpl::OnWallpaperResized() { +void WallpaperController::OnWallpaperResized() { CalculateWallpaperColors(); compositor_lock_.reset(); } -void WallpaperControllerImpl::OnColorCalculationComplete() { +void WallpaperController::OnColorCalculationComplete() { const std::vector<SkColor> colors = color_calculator_->prominent_colors(); color_calculator_.reset(); // Use |WallpaperInfo::location| as the key for storing |prominent_colors_| in @@ -1386,7 +1394,7 @@ SetProminentColors(colors); } -void WallpaperControllerImpl::OnSessionStateChanged( +void WallpaperController::OnSessionStateChanged( session_manager::SessionState state) { // Replace the device policy wallpaper with a user wallpaper if necessary. if (IsDevicePolicyWallpaper() && !ShouldSetDevicePolicyWallpaper()) @@ -1413,19 +1421,19 @@ MoveToLockedContainer(); } -void WallpaperControllerImpl::OnTabletModeStarted() { +void WallpaperController::OnTabletModeStarted() { RepaintWallpaper(); } -void WallpaperControllerImpl::OnTabletModeEnded() { +void WallpaperController::OnTabletModeEnded() { RepaintWallpaper(); } -void WallpaperControllerImpl::CompositorLockTimedOut() { +void WallpaperController::CompositorLockTimedOut() { compositor_lock_.reset(); } -void WallpaperControllerImpl::InitializePathsForTesting( +void WallpaperController::InitializePathsForTesting( const base::FilePath& user_data_path, const base::FilePath& chromeos_wallpapers_path, const base::FilePath& chromeos_custom_wallpapers_path) { @@ -1434,25 +1442,30 @@ SetGlobalChromeOSCustomWallpapersDir(chromeos_custom_wallpapers_path); } -void WallpaperControllerImpl::ShowDefaultWallpaperForTesting() { +void WallpaperController::ShowDefaultWallpaperForTesting() { SetDefaultWallpaperImpl(EmptyAccountId(), user_manager::USER_TYPE_REGULAR, /*show_wallpaper=*/true); } -void WallpaperControllerImpl::CreateEmptyWallpaperForTesting() { +void WallpaperController::CreateEmptyWallpaperForTesting() { ResetProminentColors(); current_wallpaper_.reset(); wallpaper_mode_ = WALLPAPER_IMAGE; InstallDesktopControllerForAllWindows(); } -void WallpaperControllerImpl::SetClientForTesting( - WallpaperControllerClient* client) { - wallpaper_controller_client_ = client; +void WallpaperController::SetClientForTesting( + mojom::WallpaperControllerClientPtr client) { + wallpaper_controller_client_ = std::move(client); } -void WallpaperControllerImpl::InstallDesktopController( - aura::Window* root_window) { +void WallpaperController::FlushForTesting() { + if (wallpaper_controller_client_) + wallpaper_controller_client_.FlushForTesting(); + mojo_observers_.FlushForTesting(); +} + +void WallpaperController::InstallDesktopController(aura::Window* root_window) { DCHECK_EQ(WALLPAPER_IMAGE, wallpaper_mode_); const bool is_wallpaper_blurred = @@ -1462,6 +1475,9 @@ is_wallpaper_blurred_ = is_wallpaper_blurred; for (auto& observer : observers_) observer.OnWallpaperBlurChanged(); + mojo_observers_.ForAllPtrs([this](mojom::WallpaperObserver* observer) { + observer->OnWallpaperBlurChanged(is_wallpaper_blurred_); + }); } const int container_id = GetWallpaperContainerId(locked_); @@ -1495,13 +1511,13 @@ current_wallpaper_view, blur); } -void WallpaperControllerImpl::InstallDesktopControllerForAllWindows() { +void WallpaperController::InstallDesktopControllerForAllWindows() { for (aura::Window* root : Shell::GetAllRootWindows()) InstallDesktopController(root); current_max_display_size_ = GetMaxDisplaySizeInNative(); } -bool WallpaperControllerImpl::ReparentWallpaper(int container) { +bool WallpaperController::ReparentWallpaper(int container) { bool moved = false; for (auto* root_window_controller : Shell::GetAllRootWindowControllers()) { if (root_window_controller->wallpaper_widget_controller()->Reparent( @@ -1512,7 +1528,7 @@ return moved; } -int WallpaperControllerImpl::GetWallpaperContainerId(bool locked) { +int WallpaperController::GetWallpaperContainerId(bool locked) { if (is_always_on_top_wallpaper_) return kShellWindowId_AlwaysOnTopWallpaperContainer; @@ -1520,9 +1536,8 @@ : kShellWindowId_WallpaperContainer; } -void WallpaperControllerImpl::RemoveUserWallpaperInfo( - const AccountId& account_id, - bool is_ephemeral) { +void WallpaperController::RemoveUserWallpaperInfo(const AccountId& account_id, + bool is_ephemeral) { if (wallpaper_cache_map_.find(account_id) != wallpaper_cache_map_.end()) wallpaper_cache_map_.erase(account_id); @@ -1540,7 +1555,7 @@ wallpaper_colors_update->RemoveWithoutPathExpansion(info.location, nullptr); } -void WallpaperControllerImpl::RemoveUserWallpaperImpl( +void WallpaperController::RemoveUserWallpaperImpl( const AccountId& account_id, const std::string& wallpaper_files_id) { if (wallpaper_files_id.empty()) @@ -1567,7 +1582,7 @@ base::BindOnce(&DeleteWallpaperInList, std::move(files_to_remove))); } -void WallpaperControllerImpl::SetDefaultWallpaperImpl( +void WallpaperController::SetDefaultWallpaperImpl( const AccountId& account_id, const user_manager::UserType& user_type, bool show_wallpaper) { @@ -1621,15 +1636,15 @@ cached_default_wallpaper_.image); } else { ReadAndDecodeWallpaper( - base::BindOnce(&WallpaperControllerImpl::OnDefaultWallpaperDecoded, + base::BindOnce(&WallpaperController::OnDefaultWallpaperDecoded, weak_factory_.GetWeakPtr(), file_path, layout, show_wallpaper), sequenced_task_runner_, file_path); } } -bool WallpaperControllerImpl::CanSetUserWallpaper(const AccountId& account_id, - bool is_ephemeral) const { +bool WallpaperController::CanSetUserWallpaper(const AccountId& account_id, + bool is_ephemeral) const { // There is no visible wallpaper in kiosk mode. if (IsInKioskMode()) return false; @@ -1639,7 +1654,7 @@ return true; } -bool WallpaperControllerImpl::WallpaperIsAlreadyLoaded( +bool WallpaperController::WallpaperIsAlreadyLoaded( const gfx::ImageSkia& image, bool compare_layouts, WallpaperLayout layout) const { @@ -1654,7 +1669,7 @@ current_wallpaper_->original_image_id(); } -void WallpaperControllerImpl::ReadAndDecodeWallpaper( +void WallpaperController::ReadAndDecodeWallpaper( LoadedCallback callback, scoped_refptr<base::SequencedTaskRunner> task_runner, const base::FilePath& file_path) { @@ -1671,7 +1686,7 @@ base::Passed(base::WrapUnique(data)))); } -bool WallpaperControllerImpl::InitializeUserWallpaperInfo( +bool WallpaperController::InitializeUserWallpaperInfo( const AccountId& account_id, bool is_ephemeral) { const WallpaperInfo info = {std::string(), WALLPAPER_LAYOUT_CENTER_CROPPED, @@ -1679,7 +1694,7 @@ return SetUserWallpaperInfo(account_id, info, is_ephemeral); } -void WallpaperControllerImpl::SetOnlineWallpaperFromPath( +void WallpaperController::SetOnlineWallpaperFromPath( SetOnlineWallpaperIfExistsCallback callback, const OnlineWallpaperParams& params, const base::FilePath& file_path) { @@ -1687,14 +1702,14 @@ std::move(callback).Run(file_exists); if (file_exists) { ReadAndDecodeWallpaper( - base::BindOnce(&WallpaperControllerImpl::OnOnlineWallpaperDecoded, + base::BindOnce(&WallpaperController::OnOnlineWallpaperDecoded, weak_factory_.GetWeakPtr(), params, /*save_file=*/false, SetOnlineWallpaperFromDataCallback()), sequenced_task_runner_, file_path); } } -void WallpaperControllerImpl::OnOnlineWallpaperDecoded( +void WallpaperController::OnOnlineWallpaperDecoded( const OnlineWallpaperParams& params, bool save_file, SetOnlineWallpaperFromDataCallback callback, @@ -1719,10 +1734,10 @@ if (params.preview_mode) { DCHECK(is_active_user); confirm_preview_wallpaper_callback_ = base::BindOnce( - &WallpaperControllerImpl::SetOnlineWallpaperImpl, + &WallpaperController::SetOnlineWallpaperImpl, weak_factory_.GetWeakPtr(), params, image, /*show_wallpaper=*/false); reload_preview_wallpaper_callback_ = - base::BindRepeating(&WallpaperControllerImpl::ShowWallpaperImage, + base::BindRepeating(&WallpaperController::ShowWallpaperImage, weak_factory_.GetWeakPtr(), image, WallpaperInfo{params.url, params.layout, ONLINE, base::Time::Now().LocalMidnight()}, @@ -1734,7 +1749,7 @@ } } -void WallpaperControllerImpl::SetOnlineWallpaperImpl( +void WallpaperController::SetOnlineWallpaperImpl( const OnlineWallpaperParams& params, const gfx::ImageSkia& image, bool show_wallpaper) { @@ -1754,7 +1769,7 @@ CustomWallpaperElement(base::FilePath(), image); } -void WallpaperControllerImpl::SetWallpaperFromInfo( +void WallpaperController::SetWallpaperFromInfo( const AccountId& account_id, const user_manager::UserType& user_type, const WallpaperInfo& info, @@ -1791,7 +1806,7 @@ return; ReadAndDecodeWallpaper( - base::BindOnce(&WallpaperControllerImpl::OnWallpaperDecoded, + base::BindOnce(&WallpaperController::OnWallpaperDecoded, weak_factory_.GetWeakPtr(), account_id, user_type, wallpaper_path, info, show_wallpaper), sequenced_task_runner_, wallpaper_path); @@ -1805,14 +1820,14 @@ wallpaper_path = GlobalUserDataDir().Append(info.location); ReadAndDecodeWallpaper( - base::BindOnce(&WallpaperControllerImpl::OnWallpaperDecoded, + base::BindOnce(&WallpaperController::OnWallpaperDecoded, weak_factory_.GetWeakPtr(), account_id, user_type, wallpaper_path, info, show_wallpaper), sequenced_task_runner_, wallpaper_path); } } -void WallpaperControllerImpl::OnDefaultWallpaperDecoded( +void WallpaperController::OnDefaultWallpaperDecoded( const base::FilePath& path, WallpaperLayout layout, bool show_wallpaper, @@ -1835,8 +1850,8 @@ } } -void WallpaperControllerImpl::SaveAndSetWallpaper( - const WallpaperUserInfo& user_info, +void WallpaperController::SaveAndSetWallpaper( + mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id, const std::string& file_name, WallpaperType type, @@ -1857,20 +1872,20 @@ // appropriate wallpaper resolution. WallpaperInfo info = {relative_path, layout, type, base::Time::Now().LocalMidnight()}; - if (!SetUserWallpaperInfo(user_info.account_id, info, - user_info.is_ephemeral)) { + if (!SetUserWallpaperInfo(user_info->account_id, info, + user_info->is_ephemeral)) { LOG(ERROR) << "Setting user wallpaper info fails. This should never happen " "except in tests."; } base::FilePath wallpaper_path = - GetCustomWallpaperPath(WallpaperControllerImpl::kOriginalWallpaperSubDir, + GetCustomWallpaperPath(WallpaperController::kOriginalWallpaperSubDir, wallpaper_files_id, file_name); const bool should_save_to_disk = - !user_info.is_ephemeral || + !user_info->is_ephemeral || (type == POLICY && - user_info.type == user_manager::USER_TYPE_PUBLIC_ACCOUNT); + user_info->type == user_manager::USER_TYPE_PUBLIC_ACCOUNT); if (should_save_to_disk) { image.EnsureRepsForSupportedScales(); @@ -1891,11 +1906,11 @@ /*always_on_top=*/false); } - wallpaper_cache_map_[user_info.account_id] = + wallpaper_cache_map_[user_info->account_id] = CustomWallpaperElement(wallpaper_path, image); } -void WallpaperControllerImpl::OnWallpaperDecoded( +void WallpaperController::OnWallpaperDecoded( const AccountId& account_id, const user_manager::UserType& user_type, const base::FilePath& path, @@ -1917,7 +1932,7 @@ } } -void WallpaperControllerImpl::ReloadWallpaper(bool clear_cache) { +void WallpaperController::ReloadWallpaper(bool clear_cache) { current_wallpaper_.reset(); if (clear_cache) wallpaper_cache_map_.clear(); @@ -1926,13 +1941,13 @@ reload_always_on_top_wallpaper_callback_.Run(); else if (reload_preview_wallpaper_callback_) reload_preview_wallpaper_callback_.Run(); - else if (current_user_.account_id.is_valid()) - ShowUserWallpaper(current_user_); + else if (current_user_) + ShowUserWallpaper(std::move(current_user_)); else ShowSigninWallpaper(); } -void WallpaperControllerImpl::SetProminentColors( +void WallpaperController::SetProminentColors( const std::vector<SkColor>& colors) { if (prominent_colors_ == colors) return; @@ -1940,15 +1955,18 @@ prominent_colors_ = colors; for (auto& observer : observers_) observer.OnWallpaperColorsChanged(); + mojo_observers_.ForAllPtrs([this](mojom::WallpaperObserver* observer) { + observer->OnWallpaperColorsChanged(prominent_colors_); + }); } -void WallpaperControllerImpl::ResetProminentColors() { +void WallpaperController::ResetProminentColors() { static const std::vector<SkColor> kInvalidColors(color_profiles_.size(), kInvalidWallpaperColor); SetProminentColors(kInvalidColors); } -void WallpaperControllerImpl::CalculateWallpaperColors() { +void WallpaperController::CalculateWallpaperColors() { if (!current_wallpaper_) return; @@ -1984,14 +2002,14 @@ } } -bool WallpaperControllerImpl::ShouldCalculateColors() const { +bool WallpaperController::ShouldCalculateColors() const { gfx::ImageSkia image = GetWallpaper(); return Shell::Get()->session_controller()->GetSessionState() == session_manager::SessionState::ACTIVE && !image.isNull(); } -void WallpaperControllerImpl::CacheProminentColors( +void WallpaperController::CacheProminentColors( const std::vector<SkColor>& colors, const std::string& current_location) { if (!local_state_) @@ -2005,7 +2023,7 @@ std::move(wallpaper_colors)); } -base::Optional<std::vector<SkColor>> WallpaperControllerImpl::GetCachedColors( +base::Optional<std::vector<SkColor>> WallpaperController::GetCachedColors( const std::string& current_location) const { base::Optional<std::vector<SkColor>> cached_colors_out; const base::ListValue* prominent_colors = nullptr; @@ -2023,7 +2041,7 @@ return cached_colors_out; } -void WallpaperControllerImpl::OnAlwaysOnTopWallpaperDecoded( +void WallpaperController::OnAlwaysOnTopWallpaperDecoded( const WallpaperInfo& info, const gfx::ImageSkia& image) { // Do nothing if |RemoveAlwaysOnTopWallpaper| was called before decoding @@ -2035,13 +2053,13 @@ return; } reload_always_on_top_wallpaper_callback_ = - base::BindRepeating(&WallpaperControllerImpl::ShowWallpaperImage, + base::BindRepeating(&WallpaperController::ShowWallpaperImage, weak_factory_.GetWeakPtr(), image, info, /*preview_mode=*/false, /*always_on_top=*/true); reload_always_on_top_wallpaper_callback_.Run(); } -bool WallpaperControllerImpl::MoveToLockedContainer() { +bool WallpaperController::MoveToLockedContainer() { if (locked_) return false; @@ -2049,7 +2067,7 @@ return ReparentWallpaper(GetWallpaperContainerId(true)); } -bool WallpaperControllerImpl::MoveToUnlockedContainer() { +bool WallpaperController::MoveToUnlockedContainer() { if (!locked_) return false; @@ -2057,17 +2075,17 @@ return ReparentWallpaper(GetWallpaperContainerId(false)); } -bool WallpaperControllerImpl::IsDevicePolicyWallpaper() const { +bool WallpaperController::IsDevicePolicyWallpaper() const { return current_wallpaper_ && current_wallpaper_->wallpaper_info().type == WallpaperType::DEVICE; } -bool WallpaperControllerImpl::IsOneShotWallpaper() const { +bool WallpaperController::IsOneShotWallpaper() const { return current_wallpaper_ && current_wallpaper_->wallpaper_info().type == WallpaperType::ONE_SHOT; } -bool WallpaperControllerImpl::ShouldSetDevicePolicyWallpaper() const { +bool WallpaperController::ShouldSetDevicePolicyWallpaper() const { // Only allow the device wallpaper if the policy is in effect for enterprise // managed devices. if (device_policy_wallpaper_path_.empty()) @@ -2078,16 +2096,15 @@ session_manager::SessionState::LOGIN_PRIMARY; } -void WallpaperControllerImpl::SetDevicePolicyWallpaper() { +void WallpaperController::SetDevicePolicyWallpaper() { DCHECK(ShouldSetDevicePolicyWallpaper()); ReadAndDecodeWallpaper( - base::BindRepeating( - &WallpaperControllerImpl::OnDevicePolicyWallpaperDecoded, - weak_factory_.GetWeakPtr()), + base::BindRepeating(&WallpaperController::OnDevicePolicyWallpaperDecoded, + weak_factory_.GetWeakPtr()), sequenced_task_runner_.get(), device_policy_wallpaper_path_); } -void WallpaperControllerImpl::OnDevicePolicyWallpaperDecoded( +void WallpaperController::OnDevicePolicyWallpaperDecoded( const gfx::ImageSkia& image) { // It might be possible that the device policy controlled wallpaper finishes // decoding after the user logs in. In this case do nothing. @@ -2108,7 +2125,46 @@ } } -void WallpaperControllerImpl::GetInternalDisplayCompositorLock() { +bool WallpaperController::IsActiveUserWallpaperControlledByPolicyImpl() const { + // The currently active user has index 0. + const UserSession* const active_user_session = + Shell::Get()->session_controller()->GetUserSession(/*user index=*/0); + if (!active_user_session) + return false; + return IsPolicyControlled(active_user_session->user_info.account_id, + active_user_session->user_info.is_ephemeral); +} + +bool WallpaperController::GetActiveUserWallpaperInfoImpl( + WallpaperInfo* info_out) const { + // The currently active user has index 0. + const UserSession* const active_user_session = + Shell::Get()->session_controller()->GetUserSession(/*user index=*/0); + if (!active_user_session) + return false; + + if (!GetUserWallpaperInfo(active_user_session->user_info.account_id, info_out, + active_user_session->user_info.is_ephemeral)) { + return false; + } + return true; +} + +bool WallpaperController::ShouldShowWallpaperSettingImpl() const { + // The currently active user has index 0. + const UserSession* const active_user_session = + Shell::Get()->session_controller()->GetUserSession(/*user index=*/0); + if (!active_user_session) + return false; + + user_manager::UserType active_user_type = active_user_session->user_info.type; + return active_user_type == user_manager::USER_TYPE_REGULAR || + active_user_type == user_manager::USER_TYPE_PUBLIC_ACCOUNT || + active_user_type == user_manager::USER_TYPE_SUPERVISED || + active_user_type == user_manager::USER_TYPE_CHILD; +} + +void WallpaperController::GetInternalDisplayCompositorLock() { if (!display::Display::HasInternalDisplay()) return; @@ -2121,7 +2177,7 @@ this, kCompositorLockTimeout); } -void WallpaperControllerImpl::RepaintWallpaper() { +void WallpaperController::RepaintWallpaper() { for (auto* root_window_controller : Shell::GetAllRootWindowControllers()) { auto* wallpaper_view = root_window_controller->wallpaper_widget_controller()->wallpaper_view();
diff --git a/ash/wallpaper/wallpaper_controller_impl.h b/ash/wallpaper/wallpaper_controller.h similarity index 86% rename from ash/wallpaper/wallpaper_controller_impl.h rename to ash/wallpaper/wallpaper_controller.h index c605894..1f31c1b9 100644 --- a/ash/wallpaper/wallpaper_controller_impl.h +++ b/ash/wallpaper/wallpaper_controller.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_WALLPAPER_WALLPAPER_CONTROLLER_IMPL_H_ -#define ASH_WALLPAPER_WALLPAPER_CONTROLLER_IMPL_H_ +#ifndef ASH_WALLPAPER_WALLPAPER_CONTROLLER_H_ +#define ASH_WALLPAPER_WALLPAPER_CONTROLLER_H_ #include <map> #include <memory> @@ -13,12 +13,11 @@ #include "ash/ash_export.h" #include "ash/display/window_tree_host_manager.h" -#include "ash/public/cpp/wallpaper_controller.h" -#include "ash/public/cpp/wallpaper_info.h" #include "ash/public/cpp/wallpaper_types.h" -#include "ash/public/cpp/wallpaper_user_info.h" +#include "ash/public/interfaces/wallpaper.mojom.h" #include "ash/session/session_observer.h" #include "ash/shell_observer.h" +#include "ash/wallpaper/wallpaper_info.h" #include "ash/wallpaper/wallpaper_utils/wallpaper_color_calculator_observer.h" #include "ash/wallpaper/wallpaper_utils/wallpaper_resizer_observer.h" #include "ash/wm/tablet_mode/tablet_mode_observer.h" @@ -27,6 +26,8 @@ #include "base/observer_list.h" #include "base/timer/timer.h" #include "components/user_manager/user_type.h" +#include "mojo/public/cpp/bindings/binding_set.h" +#include "mojo/public/cpp/bindings/interface_ptr_set.h" #include "ui/compositor/compositor_lock.h" #include "ui/gfx/image/image_skia.h" @@ -43,6 +44,7 @@ namespace ash { class WallpaperColorCalculator; +class WallpaperControllerObserver; class WallpaperResizer; class WallpaperWindowStateManager; @@ -61,15 +63,14 @@ // - Move wallpaper to locked container(s) when session state is not ACTIVE to // hide the user desktop and move it to unlocked container when session // state is ACTIVE; -class ASH_EXPORT WallpaperControllerImpl - : public WallpaperController, - public WindowTreeHostManager::Observer, - public ShellObserver, - public WallpaperResizerObserver, - public WallpaperColorCalculatorObserver, - public SessionObserver, - public TabletModeObserver, - public ui::CompositorLockClient { +class ASH_EXPORT WallpaperController : public mojom::WallpaperController, + public WindowTreeHostManager::Observer, + public ShellObserver, + public WallpaperResizerObserver, + public WallpaperColorCalculatorObserver, + public SessionObserver, + public TabletModeObserver, + public ui::CompositorLockClient { public: enum WallpaperResolution { WALLPAPER_RESOLUTION_LARGE, @@ -81,8 +82,8 @@ static const char kLargeWallpaperSubDir[]; static const char kOriginalWallpaperSubDir[]; - explicit WallpaperControllerImpl(PrefService* local_state); - ~WallpaperControllerImpl() override; + explicit WallpaperController(PrefService* local_state); + ~WallpaperController() override; static void RegisterLocalStatePrefs(PrefRegistrySimple* registry); @@ -112,7 +113,14 @@ const base::FilePath& wallpaper_path, bool show_wallpaper, const scoped_refptr<base::SingleThreadTaskRunner>& reply_task_runner, - base::WeakPtr<WallpaperControllerImpl> weak_ptr); + base::WeakPtr<WallpaperController> weak_ptr); + + // Binds the mojom::WallpaperController interface request to this object. + void BindRequest(mojom::WallpaperControllerRequest request); + + // Add/Remove observers. + void AddObserver(WallpaperControllerObserver* observer); + void RemoveObserver(WallpaperControllerObserver* observer); // Returns the prominent color based on |color_profile|. SkColor GetProminentColor(color_utils::ColorProfile color_profile) const; @@ -210,59 +218,60 @@ const WallpaperInfo& info, bool show_wallpaper); - // WallpaperController: - void Init(WallpaperControllerClient* client, + // mojom::WallpaperController: + void Init(mojom::WallpaperControllerClientPtr client, const base::FilePath& user_data_path, const base::FilePath& chromeos_wallpapers_path, const base::FilePath& chromeos_custom_wallpapers_path, const base::FilePath& device_policy_wallpaper_path) override; - void SetCustomWallpaper(const WallpaperUserInfo& user_info, + void SetCustomWallpaper(mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id, const std::string& file_name, WallpaperLayout layout, const gfx::ImageSkia& image, bool preview_mode) override; void SetOnlineWallpaperIfExists( - const WallpaperUserInfo& user_info, + mojom::WallpaperUserInfoPtr user_info, const std::string& url, WallpaperLayout layout, bool preview_mode, SetOnlineWallpaperIfExistsCallback callback) override; void SetOnlineWallpaperFromData( - const WallpaperUserInfo& user_info, + mojom::WallpaperUserInfoPtr user_info, const std::string& image_data, const std::string& url, WallpaperLayout layout, bool preview_mode, SetOnlineWallpaperFromDataCallback callback) override; - void SetDefaultWallpaper(const WallpaperUserInfo& user_info, + void SetDefaultWallpaper(mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id, bool show_wallpaper) override; void SetCustomizedDefaultWallpaperPaths( const base::FilePath& customized_default_small_path, const base::FilePath& customized_default_large_path) override; - void SetPolicyWallpaper(const WallpaperUserInfo& user_info, + void SetPolicyWallpaper(mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id, const std::string& data) override; void SetDevicePolicyWallpaperPath( const base::FilePath& device_policy_wallpaper_path) override; - bool SetThirdPartyWallpaper(const WallpaperUserInfo& user_info, + void SetThirdPartyWallpaper(mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id, const std::string& file_name, WallpaperLayout layout, - const gfx::ImageSkia& image) override; + const gfx::ImageSkia& image, + SetThirdPartyWallpaperCallback callback) override; void ConfirmPreviewWallpaper() override; void CancelPreviewWallpaper() override; - void UpdateCustomWallpaperLayout(const WallpaperUserInfo& user_info, + void UpdateCustomWallpaperLayout(mojom::WallpaperUserInfoPtr user_info, WallpaperLayout layout) override; - void ShowUserWallpaper(const WallpaperUserInfo& user_info) override; + void ShowUserWallpaper(mojom::WallpaperUserInfoPtr user_info) override; void ShowSigninWallpaper() override; void ShowOneShotWallpaper(const gfx::ImageSkia& image) override; void ShowAlwaysOnTopWallpaper(const base::FilePath& image_path) override; void RemoveAlwaysOnTopWallpaper() override; - void RemoveUserWallpaper(const WallpaperUserInfo& user_info, + void RemoveUserWallpaper(mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id) override; - void RemovePolicyWallpaper(const WallpaperUserInfo& user_info, + void RemovePolicyWallpaper(mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id) override; void GetOfflineWallpaperList( GetOfflineWallpaperListCallback callback) override; @@ -270,14 +279,16 @@ void OpenWallpaperPickerIfAllowed() override; void MinimizeInactiveWindows(const std::string& user_id_hash) override; void RestoreMinimizedWindows(const std::string& user_id_hash) override; - void AddObserver(WallpaperControllerObserver* observer) override; - void RemoveObserver(WallpaperControllerObserver* observer) override; - gfx::ImageSkia GetWallpaperImage() override; - const std::vector<SkColor>& GetWallpaperColors() override; - bool IsWallpaperBlurred() override; - bool IsActiveUserWallpaperControlledByPolicy() override; - WallpaperInfo GetActiveUserWallpaperInfo() override; - bool ShouldShowWallpaperSetting() override; + void AddObserver(mojom::WallpaperObserverAssociatedPtrInfo observer) override; + void GetWallpaperImage(GetWallpaperImageCallback callback) override; + void GetWallpaperColors(GetWallpaperColorsCallback callback) override; + void IsWallpaperBlurred(IsWallpaperBlurredCallback callback) override; + void IsActiveUserWallpaperControlledByPolicy( + IsActiveUserWallpaperControlledByPolicyCallback callback) override; + void GetActiveUserWallpaperInfo( + GetActiveUserWallpaperInfoCallback callback) override; + void ShouldShowWallpaperSetting( + ShouldShowWallpaperSettingCallback callback) override; // WindowTreeHostManager::Observer: void OnDisplayConfigurationChanged() override; @@ -320,8 +331,11 @@ // empty widget for those tests to prevent crashes. void CreateEmptyWallpaperForTesting(); - // Sets a test client. - void SetClientForTesting(WallpaperControllerClient* client); + // Sets a test client interface with empty file paths. + void SetClientForTesting(mojom::WallpaperControllerClientPtr client); + + // Flushes the mojo message pipe to chrome. + void FlushForTesting(); void set_wallpaper_reload_no_delay_for_test() { wallpaper_reload_delay_ = base::TimeDelta::FromMilliseconds(0); @@ -443,7 +457,7 @@ // policy wallpaper for public accounts. Shows the wallpaper immediately if // |show_wallpaper| is true, otherwise only sets the wallpaper info and // updates the cache. - void SaveAndSetWallpaper(const WallpaperUserInfo& user_info, + void SaveAndSetWallpaper(mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id, const std::string& file_name, WallpaperType type, @@ -528,6 +542,15 @@ // Called when the device policy controlled wallpaper has been decoded. void OnDevicePolicyWallpaperDecoded(const gfx::ImageSkia& image); + // Implementation of |IsActiveUserWallpaperControlledByPolicy|. + bool IsActiveUserWallpaperControlledByPolicyImpl() const; + + // Implementation of |GetActiveUserWallpaperInfo|. + bool GetActiveUserWallpaperInfoImpl(WallpaperInfo* info_out) const; + + // Implementation of |ShouldShowWallpaperSetting|. + bool ShouldShowWallpaperSettingImpl() const; + // When wallpaper resizes, we can check which displays will be affected. For // simplicity, we only lock the compositor for the internal display. void GetInternalDisplayCompositorLock(); @@ -541,10 +564,15 @@ WallpaperMode wallpaper_mode_; // Client interface in chrome browser. - WallpaperControllerClient* wallpaper_controller_client_ = nullptr; + mojom::WallpaperControllerClientPtr wallpaper_controller_client_; + + // Bindings for the WallpaperController interface. + mojo::BindingSet<mojom::WallpaperController> bindings_; base::ObserverList<WallpaperControllerObserver>::Unchecked observers_; + mojo::AssociatedInterfacePtrSet<mojom::WallpaperObserver> mojo_observers_; + std::unique_ptr<WallpaperResizer> current_wallpaper_; // Asynchronous task to extract colors from the wallpaper. @@ -566,7 +594,7 @@ std::map<AccountId, WallpaperInfo> ephemeral_users_wallpaper_info_; // Cached user info of the current user. - WallpaperUserInfo current_user_; + mojom::WallpaperUserInfoPtr current_user_; // Cached wallpapers of users. CustomWallpaperMap wallpaper_cache_map_; @@ -633,15 +661,15 @@ std::vector<base::FilePath> decode_requests_for_testing_; // PrefService provided by Shell when constructing this. - // Valid for the lifetime of ash::Shell which owns WallpaperControllerImpl. + // Valid for the lifetime of ash::Shell which owns WallpaperController. // May be null in tests. PrefService* local_state_ = nullptr; - base::WeakPtrFactory<WallpaperControllerImpl> weak_factory_; + base::WeakPtrFactory<WallpaperController> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(WallpaperControllerImpl); + DISALLOW_COPY_AND_ASSIGN(WallpaperController); }; } // namespace ash -#endif // ASH_WALLPAPER_WALLPAPER_CONTROLLER_IMPL_H_ +#endif // ASH_WALLPAPER_WALLPAPER_CONTROLLER_H_
diff --git a/ash/wallpaper/wallpaper_controller_observer.h b/ash/wallpaper/wallpaper_controller_observer.h new file mode 100644 index 0000000..c8c1199 --- /dev/null +++ b/ash/wallpaper/wallpaper_controller_observer.h
@@ -0,0 +1,36 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_WALLPAPER_WALLPAPER_CONTROLLER_OBSERVER_H_ +#define ASH_WALLPAPER_WALLPAPER_CONTROLLER_OBSERVER_H_ + +#include "ash/ash_export.h" + +namespace ash { + +class ASH_EXPORT WallpaperControllerObserver { + public: + // Invoked when the colors extracted from the current wallpaper change. + virtual void OnWallpaperColorsChanged() {} + + // Invoked when the blur state of the wallpaper changes. + virtual void OnWallpaperBlurChanged() {} + + // Invoked when the wallpaper preview mode starts. + virtual void OnWallpaperPreviewStarted() {} + + // Invoked when the wallpaper preview mode ends. + virtual void OnWallpaperPreviewEnded() {} + + // Invoked when the first wallpaper is set. The first wallpaper is the one + // shown right after boot splash screen or after a session restart. + virtual void OnFirstWallpaperShown() {} + + protected: + virtual ~WallpaperControllerObserver() {} +}; + +} // namespace ash + +#endif // ASH_WALLPAPER_WALLPAPER_CONTROLLER_OBSERVER_H_
diff --git a/ash/wallpaper/wallpaper_controller_test_api.cc b/ash/wallpaper/wallpaper_controller_test_api.cc index f0dc2de..a60389f8 100644 --- a/ash/wallpaper/wallpaper_controller_test_api.cc +++ b/ash/wallpaper/wallpaper_controller_test_api.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. #include "ash/wallpaper/wallpaper_controller_test_api.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "base/bind.h" #include "ui/gfx/canvas.h" #include "ui/gfx/color_utils.h" @@ -26,7 +26,7 @@ } // namespace WallpaperControllerTestApi::WallpaperControllerTestApi( - WallpaperControllerImpl* controller) + WallpaperController* controller) : controller_(controller) {} WallpaperControllerTestApi::~WallpaperControllerTestApi() = default; @@ -44,13 +44,13 @@ // Preview mode is considered active when the two callbacks have non-empty // values. Their specific values don't matter for testing purpose. controller_->confirm_preview_wallpaper_callback_ = - base::BindOnce(&WallpaperControllerImpl::SetWallpaperFromInfo, + base::BindOnce(&WallpaperController::SetWallpaperFromInfo, controller_->weak_factory_.GetWeakPtr(), AccountId::FromUserEmail("user@test.com"), user_manager::USER_TYPE_REGULAR, kTestWallpaperInfo, /*show_wallpaper=*/true); controller_->reload_preview_wallpaper_callback_ = base::BindRepeating( - &WallpaperControllerImpl::ShowWallpaperImage, + &WallpaperController::ShowWallpaperImage, controller_->weak_factory_.GetWeakPtr(), CreateImageWithColor(SK_ColorBLUE), kTestWallpaperInfo, /*preview_mode=*/true, /*always_on_top=*/false);
diff --git a/ash/wallpaper/wallpaper_controller_test_api.h b/ash/wallpaper/wallpaper_controller_test_api.h index 90aca5b..02f11f64 100644 --- a/ash/wallpaper/wallpaper_controller_test_api.h +++ b/ash/wallpaper/wallpaper_controller_test_api.h
@@ -11,14 +11,14 @@ namespace ash { -class WallpaperControllerImpl; +class WallpaperController; class ASH_EXPORT WallpaperControllerTestApi { public: - explicit WallpaperControllerTestApi(WallpaperControllerImpl* controller); + explicit WallpaperControllerTestApi(WallpaperController* controller); virtual ~WallpaperControllerTestApi(); - // Creates and sets a new wallpaper that causes the prominent color of the + // Creates and sets a new wallpaper that cause the prominent color of the // |controller_| to be a valid (i.e. not kInvalidWallpaperColor) color. The // WallpaperControllerObservers should be notified as well. This assumes the // default DARK-MUTED luma-saturation ranges are in effect. @@ -35,7 +35,7 @@ void EndWallpaperPreview(bool confirm_preview_wallpaper); private: - WallpaperControllerImpl* controller_; + WallpaperController* controller_; DISALLOW_COPY_AND_ASSIGN(WallpaperControllerTestApi); };
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc index c061a4e..f962980 100644 --- a/ash/wallpaper/wallpaper_controller_unittest.cc +++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include <cmath> #include <cstdlib> @@ -10,12 +10,12 @@ #include "ash/public/cpp/ash_switches.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/public/cpp/test/shell_test_api.h" -#include "ash/public/cpp/wallpaper_controller_observer.h" #include "ash/root_window_controller.h" #include "ash/session/session_controller_impl.h" #include "ash/session/test_session_controller_client.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" +#include "ash/wallpaper/wallpaper_controller_observer.h" #include "ash/wallpaper/wallpaper_utils/wallpaper_resizer.h" #include "ash/wallpaper/wallpaper_view.h" #include "ash/wallpaper/wallpaper_widget_controller.h" @@ -31,6 +31,7 @@ #include "base/test/bind_test_util.h" #include "base/time/time_override.h" #include "chromeos/constants/chromeos_switches.h" +#include "mojo/public/cpp/bindings/associated_binding.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/aura/window.h" @@ -153,9 +154,8 @@ const std::string& wallpaper_files_id, const std::string& file_name) { base::ScopedAllowBlockingForTesting allow_blocking; - base::FilePath wallpaper_path = - WallpaperControllerImpl::GetCustomWallpaperPath( - sub_dir, wallpaper_files_id, file_name); + base::FilePath wallpaper_path = WallpaperController::GetCustomWallpaperPath( + sub_dir, wallpaper_files_id, file_name); if (!base::DirectoryExists(wallpaper_path.DirName())) base::CreateDirectory(wallpaper_path.DirName()); @@ -166,16 +166,16 @@ const std::string wallpaper_file_id = GetDummyFileId(account_id); base::FilePath small_wallpaper_dir = - WallpaperControllerImpl::GetCustomWallpaperDir( - WallpaperControllerImpl::kSmallWallpaperSubDir) + WallpaperController::GetCustomWallpaperDir( + WallpaperController::kSmallWallpaperSubDir) .Append(wallpaper_file_id); base::FilePath large_wallpaper_dir = - WallpaperControllerImpl::GetCustomWallpaperDir( - WallpaperControllerImpl::kLargeWallpaperSubDir) + WallpaperController::GetCustomWallpaperDir( + WallpaperController::kLargeWallpaperSubDir) .Append(wallpaper_file_id); base::FilePath original_wallpaper_dir = - WallpaperControllerImpl::GetCustomWallpaperDir( - WallpaperControllerImpl::kOriginalWallpaperSubDir) + WallpaperController::GetCustomWallpaperDir( + WallpaperController::kOriginalWallpaperSubDir) .Append(wallpaper_file_id); while (base::PathExists(small_wallpaper_dir) || @@ -220,33 +220,50 @@ } } -// A test implementation of the WallpaperControllerObserver interface. -class TestWallpaperControllerObserver : public WallpaperControllerObserver { +// A test implementation of the WallpaperObserver mojo interface. +class TestWallpaperObserver : public mojom::WallpaperObserver { public: - explicit TestWallpaperControllerObserver(WallpaperController* controller) - : controller_(controller) { - controller_->AddObserver(this); + TestWallpaperObserver() = default; + ~TestWallpaperObserver() override = default; + + // mojom::WallpaperObserver: + void OnWallpaperChanged(uint32_t image_id) override {} + + void OnWallpaperColorsChanged( + const std::vector<SkColor>& prominent_colors) override { + ++wallpaper_colors_changed_count_; + if (run_loop_) + run_loop_->Quit(); } - ~TestWallpaperControllerObserver() override { - controller_->RemoveObserver(this); + void OnWallpaperBlurChanged(bool blurred) override {} + + int wallpaper_colors_changed_count() const { + return wallpaper_colors_changed_count_; } - // WallpaperControllerObserver - void OnWallpaperColorsChanged() override { ++colors_changed_count_; } - void OnWallpaperBlurChanged() override { ++blur_changed_count_; } - void OnFirstWallpaperShown() override { ++first_shown_count_; } - - int colors_changed_count() const { return colors_changed_count_; } - int blur_changed_count() const { return blur_changed_count_; } - int first_shown_count() const { return first_shown_count_; } + void set_run_loop(base::RunLoop* loop) { run_loop_ = loop; } private: - WallpaperController* controller_; - int colors_changed_count_ = 0; - int blur_changed_count_ = 0; - int first_shown_count_ = 0; + base::RunLoop* run_loop_ = nullptr; + int wallpaper_colors_changed_count_ = 0; + DISALLOW_COPY_AND_ASSIGN(TestWallpaperObserver); +}; + +class TestWallpaperControllerObserver : public WallpaperControllerObserver { + public: + TestWallpaperControllerObserver() = default; + + void OnWallpaperBlurChanged() override { ++wallpaper_blur_changed_count_; } + void OnFirstWallpaperShown() override { ++first_wallpaper_shown_count_; } + + void Reset() { wallpaper_blur_changed_count_ = 0; } + + int wallpaper_blur_changed_count_ = 0; + int first_wallpaper_shown_count_ = 0; + + private: DISALLOW_COPY_AND_ASSIGN(TestWallpaperControllerObserver); }; @@ -352,15 +369,16 @@ base::Time::Now().LocalMidnight()); } - // Helper function to create a |WallpaperUserInfo| structwith default values. - // In addition, clear the wallpaper count and the decoding request list. May - // be called multiple times for the same |account_id|. - WallpaperUserInfo InitializeUser(const AccountId& account_id) { - WallpaperUserInfo wallpaper_user_info; - wallpaper_user_info.account_id = account_id; - wallpaper_user_info.type = user_manager::USER_TYPE_REGULAR; - wallpaper_user_info.is_ephemeral = false; - wallpaper_user_info.has_gaia_account = true; + // Helper function to create a new |mojom::WallpaperUserInfoPtr| instance with + // default values. In addition, clear the wallpaper count and the decoding + // request list. May be called multiple times for the same |account_id|. + mojom::WallpaperUserInfoPtr InitializeUser(const AccountId& account_id) { + mojom::WallpaperUserInfoPtr wallpaper_user_info = + mojom::WallpaperUserInfo::New(); + wallpaper_user_info->account_id = account_id; + wallpaper_user_info->type = user_manager::USER_TYPE_REGULAR; + wallpaper_user_info->is_ephemeral = false; + wallpaper_user_info->has_gaia_account = true; ClearWallpaperCount(); ClearDecodeFilePaths(); @@ -374,10 +392,10 @@ std::string wallpaper_files_id = GetDummyFileId(account_id); std::string file_name = GetDummyFileName(account_id); base::FilePath small_wallpaper_path = - GetCustomWallpaperPath(WallpaperControllerImpl::kSmallWallpaperSubDir, + GetCustomWallpaperPath(WallpaperController::kSmallWallpaperSubDir, wallpaper_files_id, file_name); base::FilePath large_wallpaper_path = - GetCustomWallpaperPath(WallpaperControllerImpl::kLargeWallpaperSubDir, + GetCustomWallpaperPath(WallpaperController::kLargeWallpaperSubDir, wallpaper_files_id, file_name); // Saves the small/large resolution wallpapers to small/large custom @@ -464,7 +482,7 @@ // A helper to test the behavior of setting online wallpaper after the image // is decoded. This is needed because image decoding is not supported in unit - // tests. + // tests (the connector for the mojo service manager is null). void SetOnlineWallpaperFromImage( const AccountId& account_id, const gfx::ImageSkia& image, @@ -472,8 +490,8 @@ WallpaperLayout layout, bool save_file, bool preview_mode, - WallpaperControllerImpl::SetOnlineWallpaperFromDataCallback callback) { - const WallpaperControllerImpl::OnlineWallpaperParams params = { + WallpaperController::SetOnlineWallpaperFromDataCallback callback) { + const WallpaperController::OnlineWallpaperParams params = { account_id, false /*is_ephemeral=*/, url, layout, preview_mode}; controller_->OnOnlineWallpaperDecoded(params, save_file, std::move(callback), image); @@ -490,6 +508,11 @@ // Wrapper for private ShouldCalculateColors(). bool ShouldCalculateColors() { return controller_->ShouldCalculateColors(); } + // Wrapper for private IsActiveUserWallpaperControlledByPolicyImpl(). + bool IsActiveUserWallpaperControlledByPolicy() { + return controller_->IsActiveUserWallpaperControlledByPolicyImpl(); + } + // Wrapper for private IsDevicePolicyWallpaper(). bool IsDevicePolicyWallpaper() { return controller_->IsDevicePolicyWallpaper(); @@ -515,7 +538,7 @@ return controller_->GetWallpaperContainerId(controller_->locked_); } - WallpaperControllerImpl* controller_; // Not owned. + WallpaperController* controller_; // Not owned. base::ScopedTempDir user_data_dir_; base::ScopedTempDir online_wallpaper_dir_; @@ -527,7 +550,7 @@ }; TEST_F(WallpaperControllerTest, BasicReparenting) { - WallpaperControllerImpl* controller = Shell::Get()->wallpaper_controller(); + WallpaperController* controller = Shell::Get()->wallpaper_controller(); controller->CreateEmptyWallpaperForTesting(); // Wallpaper view/window exists in the wallpaper container and nothing is in @@ -559,7 +582,7 @@ ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); // Create the wallpaper and its view. - WallpaperControllerImpl* controller = Shell::Get()->wallpaper_controller(); + WallpaperController* controller = Shell::Get()->wallpaper_controller(); controller->CreateEmptyWallpaperForTesting(); // The new wallpaper is ready to animate. @@ -584,7 +607,7 @@ ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); // Reset wallpaper state, see ControllerOwnership above. - WallpaperControllerImpl* controller = Shell::Get()->wallpaper_controller(); + WallpaperController* controller = Shell::Get()->wallpaper_controller(); controller->CreateEmptyWallpaperForTesting(); // Run wallpaper show animation to completion. @@ -632,7 +655,7 @@ ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); // Reset wallpaper state, see ControllerOwnership above. - WallpaperControllerImpl* controller = Shell::Get()->wallpaper_controller(); + WallpaperController* controller = Shell::Get()->wallpaper_controller(); controller->CreateEmptyWallpaperForTesting(); // Run wallpaper show animation to completion. @@ -697,32 +720,32 @@ // Device scale factor shouldn't affect the native size. UpdateDisplay("1000x300*2"); EXPECT_EQ("1000x300", - WallpaperControllerImpl::GetMaxDisplaySizeInNative().ToString()); + WallpaperController::GetMaxDisplaySizeInNative().ToString()); // Rotated display should return the rotated size. UpdateDisplay("1000x300*2/r"); EXPECT_EQ("300x1000", - WallpaperControllerImpl::GetMaxDisplaySizeInNative().ToString()); + WallpaperController::GetMaxDisplaySizeInNative().ToString()); // UI Scaling shouldn't affect the native size. UpdateDisplay("1000x300*2@1.5"); EXPECT_EQ("1000x300", - WallpaperControllerImpl::GetMaxDisplaySizeInNative().ToString()); + WallpaperController::GetMaxDisplaySizeInNative().ToString()); // First display has maximum size. UpdateDisplay("400x300,100x100"); EXPECT_EQ("400x300", - WallpaperControllerImpl::GetMaxDisplaySizeInNative().ToString()); + WallpaperController::GetMaxDisplaySizeInNative().ToString()); // Second display has maximum size. UpdateDisplay("400x300,500x600"); EXPECT_EQ("500x600", - WallpaperControllerImpl::GetMaxDisplaySizeInNative().ToString()); + WallpaperController::GetMaxDisplaySizeInNative().ToString()); // Maximum width and height belongs to different displays. UpdateDisplay("400x300,100x500"); EXPECT_EQ("400x500", - WallpaperControllerImpl::GetMaxDisplaySizeInNative().ToString()); + WallpaperController::GetMaxDisplaySizeInNative().ToString()); } // Test that the wallpaper is always fitted to the native display resolution @@ -836,15 +859,27 @@ EXPECT_FALSE(ShouldCalculateColors()); } -TEST_F(WallpaperControllerTest, EnableShelfColoringNotifiesObservers) { - TestWallpaperControllerObserver observer(controller_); - EXPECT_EQ(0, observer.colors_changed_count()); +TEST_F(WallpaperControllerTest, MojoWallpaperObserverTest) { + TestWallpaperObserver observer; + mojom::WallpaperObserverAssociatedPtr observer_ptr; + mojo::AssociatedBinding<mojom::WallpaperObserver> binding( + &observer, mojo::MakeRequestAssociatedWithDedicatedPipe(&observer_ptr)); + controller_->AddObserver(observer_ptr.PassInterface()); + controller_->FlushForTesting(); + + // Adding an observer fires OnWallpaperColorsChanged() immediately. + EXPECT_EQ(1, observer.wallpaper_colors_changed_count()); // Enable shelf coloring will set a customized wallpaper image and change // session state to ACTIVE, which will trigger wallpaper colors calculation. + base::RunLoop run_loop; + observer.set_run_loop(&run_loop); EnableShelfColoring(); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1, observer.colors_changed_count()); + // Color calculation may be asynchronous. + run_loop.Run(); + // Mojo methods are called after color calculation finishes. + controller_->FlushForTesting(); + EXPECT_EQ(2, observer.wallpaper_colors_changed_count()); } TEST_F(WallpaperControllerTest, SetCustomWallpaper) { @@ -926,7 +961,7 @@ controller_->SetOnlineWallpaperFromData( InitializeUser(account_id_1), std::string() /*image_data=*/, kDummyUrl, layout, false /*preview_mode=*/, - WallpaperControllerImpl::SetOnlineWallpaperFromDataCallback()); + WallpaperController::SetOnlineWallpaperFromDataCallback()); RunAllTasksUntilIdle(); EXPECT_EQ(1, GetWallpaperCount()); EXPECT_EQ(controller_->GetWallpaperType(), ONLINE); @@ -980,7 +1015,7 @@ controller_->SetOnlineWallpaperFromData( InitializeUser(account_id_1), std::string() /*image_data=*/, kDummyUrl2, layout, false /*preview_mode=*/, - WallpaperControllerImpl::SetOnlineWallpaperFromDataCallback()); + WallpaperController::SetOnlineWallpaperFromDataCallback()); RunAllTasksUntilIdle(); EXPECT_EQ(0, GetWallpaperCount()); EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, @@ -1111,11 +1146,21 @@ // Set a third-party wallpaper for |kUser1|. const WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER; gfx::ImageSkia third_party_wallpaper = CreateImage(640, 480, kWallpaperColor); - EXPECT_TRUE(controller_->SetThirdPartyWallpaper( + bool allowed_to_update_wallpaper = false; + std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>(); + controller_->SetThirdPartyWallpaper( InitializeUser(account_id_1), wallpaper_files_id_1, file_name_1, layout, - third_party_wallpaper)); + third_party_wallpaper, + base::BindLambdaForTesting([&allowed_to_update_wallpaper, &run_loop]( + bool allowed, uint32_t image_id) { + allowed_to_update_wallpaper = allowed; + run_loop->Quit(); + })); + run_loop->Run(); // Verify the wallpaper is shown. EXPECT_EQ(1, GetWallpaperCount()); + // Verify the callback function gets the correct value. + EXPECT_TRUE(allowed_to_update_wallpaper); // Verify the user wallpaper info is updated. EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, false /*is_ephemeral=*/)); @@ -1125,14 +1170,23 @@ EXPECT_EQ(wallpaper_info, expected_wallpaper_info); // Switch active user to |kUser2|, but set another third-party wallpaper for - // |kUser1|; the operation should not be allowed, because |kUser1| is not the - // active user. + // |kUser1|. + allowed_to_update_wallpaper = true; SimulateUserLogin(kUser2); - EXPECT_FALSE(controller_->SetThirdPartyWallpaper( + run_loop.reset(new base::RunLoop()); + controller_->SetThirdPartyWallpaper( InitializeUser(account_id_1), wallpaper_files_id_2, file_name_2, layout, - third_party_wallpaper)); - // Verify the wallpaper is not shown. + third_party_wallpaper, + base::BindLambdaForTesting([&allowed_to_update_wallpaper, &run_loop]( + bool allowed, uint32_t image_id) { + allowed_to_update_wallpaper = allowed; + run_loop->Quit(); + })); + run_loop->Run(); + // Verify the wallpaper is not shown because |kUser1| is not the active user. EXPECT_EQ(0, GetWallpaperCount()); + // Verify the callback function gets the correct value. + EXPECT_FALSE(allowed_to_update_wallpaper); // Verify the wallpaper info for |kUser1| is updated, because setting // wallpaper is still allowed for non-active users. EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info, @@ -1150,20 +1204,30 @@ RunAllTasksUntilIdle(); EXPECT_TRUE( controller_->IsPolicyControlled(account_id_2, false /*is_ephemeral=*/)); - EXPECT_TRUE(controller_->IsActiveUserWallpaperControlledByPolicy()); + EXPECT_TRUE(IsActiveUserWallpaperControlledByPolicy()); - // Setting a third-party wallpaper for |kUser2| should not be allowed, because - // third-party wallpapers cannot be set for policy controlled users. - EXPECT_FALSE(controller_->SetThirdPartyWallpaper( + // Set a third-party wallpaper for |kUser2|. + allowed_to_update_wallpaper = true; + run_loop.reset(new base::RunLoop()); + controller_->SetThirdPartyWallpaper( InitializeUser(account_id_2), wallpaper_files_id_1, file_name_1, layout, - third_party_wallpaper)); - // Verify the wallpaper is not shown. + third_party_wallpaper, + base::BindLambdaForTesting([&allowed_to_update_wallpaper, &run_loop]( + bool allowed, uint32_t image_id) { + allowed_to_update_wallpaper = allowed; + run_loop->Quit(); + })); + run_loop->Run(); + // Verify the wallpaper is not shown because third-party wallpaper cannot be + // set for policy controlled users. EXPECT_EQ(0, GetWallpaperCount()); + // Verify the callback gets the correct value. + EXPECT_FALSE(allowed_to_update_wallpaper); // Verify |kUser2| is still policy controlled and has the policy wallpaper // info. EXPECT_TRUE( controller_->IsPolicyControlled(account_id_2, false /*is_ephemeral=*/)); - EXPECT_TRUE(controller_->IsActiveUserWallpaperControlledByPolicy()); + EXPECT_TRUE(IsActiveUserWallpaperControlledByPolicy()); EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_2, &wallpaper_info, false /*is_ephemeral=*/)); WallpaperInfo policy_wallpaper_info(base::FilePath(wallpaper_files_id_2) @@ -1263,10 +1327,12 @@ // path. UpdateDisplay("1600x1200"); RunAllTasksUntilIdle(); - WallpaperUserInfo wallpaper_user_info = InitializeUser(child_account_id); - wallpaper_user_info.type = user_manager::USER_TYPE_CHILD; - controller_->SetDefaultWallpaper( - wallpaper_user_info, child_wallpaper_files_id, true /*show_wallpaper=*/); + mojom::WallpaperUserInfoPtr wallpaper_user_info = + InitializeUser(child_account_id); + wallpaper_user_info->type = user_manager::USER_TYPE_CHILD; + controller_->SetDefaultWallpaper(std::move(wallpaper_user_info), + child_wallpaper_files_id, + true /*show_wallpaper=*/); RunAllTasksUntilIdle(); EXPECT_EQ(1, GetWallpaperCount()); EXPECT_EQ(controller_->GetWallpaperType(), DEFAULT); @@ -1279,9 +1345,10 @@ UpdateDisplay("800x600"); RunAllTasksUntilIdle(); wallpaper_user_info = InitializeUser(child_account_id); - wallpaper_user_info.type = user_manager::USER_TYPE_CHILD; - controller_->SetDefaultWallpaper( - wallpaper_user_info, child_wallpaper_files_id, true /*show_wallpaper=*/); + wallpaper_user_info->type = user_manager::USER_TYPE_CHILD; + controller_->SetDefaultWallpaper(std::move(wallpaper_user_info), + child_wallpaper_files_id, + true /*show_wallpaper=*/); RunAllTasksUntilIdle(); EXPECT_EQ(1, GetWallpaperCount()); EXPECT_EQ(controller_->GetWallpaperType(), DEFAULT); @@ -1458,7 +1525,7 @@ controller_->SetOnlineWallpaperFromData( InitializeUser(account_id_1), std::string() /*image_data=*/, kDummyUrl, WALLPAPER_LAYOUT_CENTER, false /*preview_mode=*/, - WallpaperControllerImpl::SetOnlineWallpaperFromDataCallback()); + WallpaperController::SetOnlineWallpaperFromDataCallback()); RunAllTasksUntilIdle(); EXPECT_TRUE( controller_->GetWallpaperFromCache(account_id_1, &cached_wallpaper)); @@ -1502,10 +1569,10 @@ TEST_F(WallpaperControllerTest, ShowCustomWallpaperWithCorrectResolution) { CreateDefaultWallpapers(); const base::FilePath small_custom_wallpaper_path = - GetCustomWallpaperPath(WallpaperControllerImpl::kSmallWallpaperSubDir, + GetCustomWallpaperPath(WallpaperController::kSmallWallpaperSubDir, wallpaper_files_id_1, file_name_1); const base::FilePath large_custom_wallpaper_path = - GetCustomWallpaperPath(WallpaperControllerImpl::kLargeWallpaperSubDir, + GetCustomWallpaperPath(WallpaperController::kLargeWallpaperSubDir, wallpaper_files_id_1, file_name_1); const base::FilePath small_default_wallpaper_path = default_wallpaper_dir_.GetPath().Append(kDefaultSmallWallpaperName); @@ -1693,7 +1760,7 @@ controller_->SetOnlineWallpaperFromData( InitializeUser(account_id_1), std::string() /*image_data=*/, kDummyUrl, layout, false /*preview_mode=*/, - WallpaperControllerImpl::SetOnlineWallpaperFromDataCallback()); + WallpaperController::SetOnlineWallpaperFromDataCallback()); RunAllTasksUntilIdle(); EXPECT_EQ(1, GetWallpaperCount()); EXPECT_EQ(controller_->GetWallpaperType(), ONLINE); @@ -1723,7 +1790,7 @@ TEST_F(WallpaperControllerTest, RemoveUserWithCustomWallpaper) { SimulateUserLogin(kUser1); base::FilePath small_wallpaper_path_1 = - GetCustomWallpaperPath(WallpaperControllerImpl::kSmallWallpaperSubDir, + GetCustomWallpaperPath(WallpaperController::kSmallWallpaperSubDir, wallpaper_files_id_1, file_name_1); // Set a custom wallpaper for |kUser1| and verify the wallpaper exists. CreateAndSaveWallpapers(account_id_1); @@ -1732,7 +1799,7 @@ // Now login another user and set a custom wallpaper for the user. SimulateUserLogin(kUser2); base::FilePath small_wallpaper_path_2 = GetCustomWallpaperPath( - WallpaperControllerImpl::kSmallWallpaperSubDir, wallpaper_files_id_2, + WallpaperController::kSmallWallpaperSubDir, wallpaper_files_id_2, GetDummyFileName(account_id_2)); CreateAndSaveWallpapers(account_id_2); EXPECT_TRUE(base::PathExists(small_wallpaper_path_2)); @@ -1754,7 +1821,7 @@ TEST_F(WallpaperControllerTest, RemoveUserWithDefaultWallpaper) { SimulateUserLogin(kUser1); base::FilePath small_wallpaper_path_1 = - GetCustomWallpaperPath(WallpaperControllerImpl::kSmallWallpaperSubDir, + GetCustomWallpaperPath(WallpaperController::kSmallWallpaperSubDir, wallpaper_files_id_1, file_name_1); // Set a custom wallpaper for |kUser1| and verify the wallpaper exists. CreateAndSaveWallpapers(account_id_1); @@ -1779,73 +1846,78 @@ // Simulate the login screen. Verify that it returns false since there's no // active user. ClearLogin(); - EXPECT_FALSE(controller_->IsActiveUserWallpaperControlledByPolicy()); + EXPECT_FALSE(IsActiveUserWallpaperControlledByPolicy()); SimulateUserLogin(kUser1); - EXPECT_FALSE(controller_->IsActiveUserWallpaperControlledByPolicy()); + EXPECT_FALSE(IsActiveUserWallpaperControlledByPolicy()); // Set a policy wallpaper for the active user. Verify that the active user // becomes policy controlled. controller_->SetPolicyWallpaper(InitializeUser(account_id_1), wallpaper_files_id_1, std::string() /*data=*/); RunAllTasksUntilIdle(); - EXPECT_TRUE(controller_->IsActiveUserWallpaperControlledByPolicy()); + EXPECT_TRUE(IsActiveUserWallpaperControlledByPolicy()); // Switch the active user. Verify the active user is not policy controlled. SimulateUserLogin(kUser2); - EXPECT_FALSE(controller_->IsActiveUserWallpaperControlledByPolicy()); + EXPECT_FALSE(IsActiveUserWallpaperControlledByPolicy()); // Logs out. Verify that it returns false since there's no active user. ClearLogin(); - EXPECT_FALSE(controller_->IsActiveUserWallpaperControlledByPolicy()); + EXPECT_FALSE(IsActiveUserWallpaperControlledByPolicy()); } TEST_F(WallpaperControllerTest, WallpaperBlur) { - TestWallpaperControllerObserver observer(controller_); - ASSERT_TRUE(controller_->IsBlurAllowed()); ASSERT_FALSE(controller_->IsWallpaperBlurred()); + TestWallpaperControllerObserver observer; + controller_->AddObserver(&observer); + SetSessionState(SessionState::ACTIVE); EXPECT_FALSE(controller_->IsWallpaperBlurred()); - EXPECT_EQ(0, observer.blur_changed_count()); + EXPECT_EQ(0, observer.wallpaper_blur_changed_count_); SetSessionState(SessionState::LOCKED); EXPECT_TRUE(controller_->IsWallpaperBlurred()); - EXPECT_EQ(1, observer.blur_changed_count()); + EXPECT_EQ(1, observer.wallpaper_blur_changed_count_); SetSessionState(SessionState::LOGGED_IN_NOT_ACTIVE); EXPECT_FALSE(controller_->IsWallpaperBlurred()); - EXPECT_EQ(2, observer.blur_changed_count()); + EXPECT_EQ(2, observer.wallpaper_blur_changed_count_); SetSessionState(SessionState::LOGIN_SECONDARY); EXPECT_TRUE(controller_->IsWallpaperBlurred()); - EXPECT_EQ(3, observer.blur_changed_count()); + EXPECT_EQ(3, observer.wallpaper_blur_changed_count_); // Blur state does not change below. + observer.Reset(); SetSessionState(SessionState::LOGIN_PRIMARY); EXPECT_TRUE(controller_->IsWallpaperBlurred()); - EXPECT_EQ(3, observer.blur_changed_count()); + EXPECT_EQ(0, observer.wallpaper_blur_changed_count_); SetSessionState(SessionState::OOBE); EXPECT_TRUE(controller_->IsWallpaperBlurred()); - EXPECT_EQ(3, observer.blur_changed_count()); + EXPECT_EQ(0, observer.wallpaper_blur_changed_count_); SetSessionState(SessionState::UNKNOWN); EXPECT_TRUE(controller_->IsWallpaperBlurred()); - EXPECT_EQ(3, observer.blur_changed_count()); + EXPECT_EQ(0, observer.wallpaper_blur_changed_count_); + + controller_->RemoveObserver(&observer); } TEST_F(WallpaperControllerTest, WallpaperBlurDuringLockScreenTransition) { - TestWallpaperControllerObserver observer(controller_); - ASSERT_TRUE(controller_->IsBlurAllowed()); ASSERT_FALSE(controller_->IsWallpaperBlurred()); + TestWallpaperControllerObserver observer; + controller_->AddObserver(&observer); + // Simulate lock and unlock sequence. controller_->UpdateWallpaperBlur(true); EXPECT_TRUE(controller_->IsWallpaperBlurred()); - EXPECT_EQ(1, observer.blur_changed_count()); + EXPECT_EQ(1, observer.wallpaper_blur_changed_count_); SetSessionState(SessionState::LOCKED); EXPECT_TRUE(controller_->IsWallpaperBlurred()); @@ -1854,7 +1926,9 @@ // UpdateWallpaperBlur(false) SetSessionState(SessionState::ACTIVE); EXPECT_FALSE(controller_->IsWallpaperBlurred()); - EXPECT_EQ(2, observer.blur_changed_count()); + EXPECT_EQ(2, observer.wallpaper_blur_changed_count_); + + controller_->RemoveObserver(&observer); } TEST_F(WallpaperControllerTest, OnlyShowDevicePolicyWallpaperOnLoginScreen) { @@ -2120,7 +2194,7 @@ SetOnlineWallpaperFromImage( account_id_1, online_wallpaper, kDummyUrl, layout, false /*save_file=*/, true /*preview_mode=*/, - WallpaperControllerImpl::SetOnlineWallpaperFromDataCallback()); + WallpaperController::SetOnlineWallpaperFromDataCallback()); RunAllTasksUntilIdle(); EXPECT_EQ(1, GetWallpaperCount()); EXPECT_EQ(online_wallpaper_color, GetWallpaperColor()); @@ -2220,7 +2294,7 @@ SetOnlineWallpaperFromImage( account_id_1, online_wallpaper, kDummyUrl, layout, false /*save_file=*/, true /*preview_mode=*/, - WallpaperControllerImpl::SetOnlineWallpaperFromDataCallback()); + WallpaperController::SetOnlineWallpaperFromDataCallback()); RunAllTasksUntilIdle(); EXPECT_EQ(1, GetWallpaperCount()); EXPECT_EQ(kWallpaperColor, GetWallpaperColor()); @@ -2238,7 +2312,7 @@ SetOnlineWallpaperFromImage( account_id_1, synced_online_wallpaper, kDummyUrl2, layout, false /*save_file=*/, false /*preview_mode=*/, - WallpaperControllerImpl::SetOnlineWallpaperFromDataCallback()); + WallpaperController::SetOnlineWallpaperFromDataCallback()); RunAllTasksUntilIdle(); EXPECT_EQ(0, GetWallpaperCount()); EXPECT_EQ(kWallpaperColor, GetWallpaperColor()); @@ -2369,9 +2443,10 @@ } TEST_F(WallpaperControllerTest, OnFirstWallpaperShown) { - TestWallpaperControllerObserver observer(controller_); + TestWallpaperControllerObserver observer; + controller_->AddObserver(&observer); EXPECT_EQ(0, GetWallpaperCount()); - EXPECT_EQ(0, observer.first_shown_count()); + EXPECT_EQ(0, observer.first_wallpaper_shown_count_); // Show the first wallpaper, verify the observer is notified. controller_->ShowWallpaperImage(CreateImage(640, 480, SK_ColorBLUE), CreateWallpaperInfo(WALLPAPER_LAYOUT_STRETCH), @@ -2380,7 +2455,7 @@ RunAllTasksUntilIdle(); EXPECT_EQ(SK_ColorBLUE, GetWallpaperColor()); EXPECT_EQ(1, GetWallpaperCount()); - EXPECT_EQ(1, observer.first_shown_count()); + EXPECT_EQ(1, observer.first_wallpaper_shown_count_); // Show the second wallpaper, verify the observer is not notified. controller_->ShowWallpaperImage(CreateImage(640, 480, SK_ColorCYAN), CreateWallpaperInfo(WALLPAPER_LAYOUT_STRETCH), @@ -2389,15 +2464,17 @@ RunAllTasksUntilIdle(); EXPECT_EQ(SK_ColorCYAN, GetWallpaperColor()); EXPECT_EQ(2, GetWallpaperCount()); - EXPECT_EQ(1, observer.first_shown_count()); + EXPECT_EQ(1, observer.first_wallpaper_shown_count_); + controller_->RemoveObserver(&observer); } // Although ephemeral users' custom wallpapers are not saved to disk, they // should be kept within the user session. Test for https://crbug.com/825237. TEST_F(WallpaperControllerTest, ShowWallpaperForEphemeralUser) { auto initialize_ephemeral_user = [&](const AccountId& account_id) { - WallpaperUserInfo wallpaper_user_info = InitializeUser(account_id); - wallpaper_user_info.is_ephemeral = true; + mojom::WallpaperUserInfoPtr wallpaper_user_info = + InitializeUser(account_id); + wallpaper_user_info->is_ephemeral = true; return wallpaper_user_info; };
diff --git a/ash/public/cpp/wallpaper_info.h b/ash/wallpaper/wallpaper_info.h similarity index 89% rename from ash/public/cpp/wallpaper_info.h rename to ash/wallpaper/wallpaper_info.h index c88ddf4..671f32c3 100644 --- a/ash/public/cpp/wallpaper_info.h +++ b/ash/wallpaper/wallpaper_info.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_PUBLIC_CPP_WALLPAPER_INFO_H_ -#define ASH_PUBLIC_CPP_WALLPAPER_INFO_H_ +#ifndef ASH_WALLPAPER_WALLPAPER_INFO_H_ +#define ASH_WALLPAPER_WALLPAPER_INFO_H_ #include "ash/public/cpp/wallpaper_types.h" #include "base/time/time.h" @@ -40,4 +40,4 @@ } // namespace ash -#endif // ASH_PUBLIC_CPP_WALLPAPER_INFO_H_ +#endif // ASH_WALLPAPER_WALLPAPER_INFO_H_
diff --git a/ash/wallpaper/wallpaper_utils/wallpaper_resizer.h b/ash/wallpaper/wallpaper_utils/wallpaper_resizer.h index bc78add8..f0b9efc0 100644 --- a/ash/wallpaper/wallpaper_utils/wallpaper_resizer.h +++ b/ash/wallpaper/wallpaper_utils/wallpaper_resizer.h
@@ -8,7 +8,7 @@ #include <stdint.h> #include "ash/ash_export.h" -#include "ash/public/cpp/wallpaper_info.h" +#include "ash/wallpaper/wallpaper_info.h" #include "ash/wallpaper/wallpaper_utils/wallpaper_resizer_observer.h" #include "base/macros.h" #include "base/memory/ref_counted.h"
diff --git a/ash/wallpaper/wallpaper_view.cc b/ash/wallpaper/wallpaper_view.cc index 46e19e3..3783273e 100644 --- a/ash/wallpaper/wallpaper_view.cc +++ b/ash/wallpaper/wallpaper_view.cc
@@ -8,7 +8,7 @@ #include "ash/root_window_controller.h" #include "ash/session/session_controller_impl.h" #include "ash/shell.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "ash/wallpaper/wallpaper_widget_controller.h" #include "ash/wm/overview/overview_controller.h" #include "ash/wm/overview/overview_utils.h" @@ -210,7 +210,7 @@ int blur, float opacity, WallpaperView** out_wallpaper_view) { - auto* controller = Shell::Get()->wallpaper_controller(); + WallpaperController* controller = Shell::Get()->wallpaper_controller(); views::Widget* wallpaper_widget = new views::Widget; views::Widget::InitParams params(
diff --git a/ash/wallpaper/wallpaper_widget_controller.cc b/ash/wallpaper/wallpaper_widget_controller.cc index f6b2395..73eabab0 100644 --- a/ash/wallpaper/wallpaper_widget_controller.cc +++ b/ash/wallpaper/wallpaper_widget_controller.cc
@@ -9,7 +9,7 @@ #include "ash/ash_export.h" #include "ash/root_window_controller.h" #include "ash/shell.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "base/scoped_observer.h" #include "ui/aura/window.h" #include "ui/aura/window_observer.h"
diff --git a/ash/wm/lock_state_controller.cc b/ash/wm/lock_state_controller.cc index aed6ed59..f21237a 100644 --- a/ash/wm/lock_state_controller.cc +++ b/ash/wm/lock_state_controller.cc
@@ -17,7 +17,7 @@ #include "ash/shell_delegate.h" #include "ash/shutdown_controller.h" #include "ash/shutdown_reason.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "ash/wm/session_state_animator.h" #include "ash/wm/session_state_animator_impl.h" #include "base/bind.h"
diff --git a/ash/wm/overview/overview_controller.cc b/ash/wm/overview/overview_controller.cc index f97087ca..049d959 100644 --- a/ash/wm/overview/overview_controller.cc +++ b/ash/wm/overview/overview_controller.cc
@@ -13,7 +13,7 @@ #include "ash/scoped_animation_disabler.h" #include "ash/session/session_controller_impl.h" #include "ash/shell.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "ash/wallpaper/wallpaper_view.h" #include "ash/wallpaper/wallpaper_widget_controller.h" #include "ash/wm/mru_window_tracker.h"
diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc index 85ee620..ec3837bb 100644 --- a/ash/wm/overview/overview_session_unittest.cc +++ b/ash/wm/overview/overview_session_unittest.cc
@@ -18,7 +18,6 @@ #include "ash/display/screen_orientation_controller.h" #include "ash/display/screen_orientation_controller_test_api.h" #include "ash/drag_drop/drag_drop_controller.h" -#include "ash/frame/non_client_frame_view_ash.h" #include "ash/public/cpp/app_types.h" #include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/fps_counter.h" @@ -144,7 +143,6 @@ // AshTestBase: void SetUp() override { AshTestBase::SetUp(); - NonClientFrameViewAsh::set_use_empty_minimum_size_for_test(true); aura::Env::GetInstance()->set_throttle_input_on_resize_for_testing(false); shelf_view_test_api_ = std::make_unique<ShelfViewTestAPI>( @@ -161,7 +159,6 @@ false); FpsCounter::SetForceReportZeroAnimationForTest(false); trace_names_.clear(); - NonClientFrameViewAsh::set_use_empty_minimum_size_for_test(false); AshTestBase::TearDown(); } @@ -2522,13 +2519,13 @@ // the window is to be letter or pillar fitted. TEST_F(OverviewSessionTest, Backdrop) { // Add three windows which in overview mode will be considered wide, tall and - // normal. Window |wide|, with size (400, 160) will be resized to (200, 160) - // when the 400x200 is rotated to 200x400, and should be considered a normal + // normal. Window |wide|, with size (400, 160) will be resized to (300, 160) + // when the 400x300 is rotated to 300x400, and should be considered a normal // overview window after display change. - UpdateDisplay("400x200"); + UpdateDisplay("400x300"); std::unique_ptr<aura::Window> wide(CreateTestWindow(gfx::Rect(400, 160))); - std::unique_ptr<aura::Window> tall(CreateTestWindow(gfx::Rect(50, 200))); - std::unique_ptr<aura::Window> normal(CreateTestWindow(gfx::Rect(200, 200))); + std::unique_ptr<aura::Window> tall(CreateTestWindow(gfx::Rect(100, 300))); + std::unique_ptr<aura::Window> normal(CreateTestWindow(gfx::Rect(300, 300))); ToggleOverview(); base::RunLoop().RunUntilIdle();
diff --git a/ash/wm/overview/scoped_overview_transform_window_unittest.cc b/ash/wm/overview/scoped_overview_transform_window_unittest.cc index 963dc3e..9e677d04 100644 --- a/ash/wm/overview/scoped_overview_transform_window_unittest.cc +++ b/ash/wm/overview/scoped_overview_transform_window_unittest.cc
@@ -4,7 +4,6 @@ #include "ash/wm/overview/scoped_overview_transform_window.h" -#include "ash/frame/non_client_frame_view_ash.h" #include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/window_properties.h" #include "ash/test/ash_test_base.h" @@ -212,19 +211,14 @@ // Tests the cases when very wide or tall windows enter overview mode. TEST_F(ScopedOverviewTransformWindowTest, ExtremeWindowBounds) { - NonClientFrameViewAsh::set_use_empty_minimum_size_for_test(true); - // Add three windows which in overview mode will be considered wide, tall and - // normal. Window |wide|, with size (400, 160) will be resized to (200, 160) - // when the 400x200 is rotated to 200x400, and should be considered a normal + // normal. Window |wide|, with size (400, 160) will be resized to (300, 160) + // when the 400x300 is rotated to 300x400, and should be considered a normal // overview window after display change. - UpdateDisplay("400x200"); - std::unique_ptr<aura::Window> wide = - CreateTestWindow(gfx::Rect(10, 10, 400, 160)); - std::unique_ptr<aura::Window> tall = - CreateTestWindow(gfx::Rect(10, 10, 50, 200)); - std::unique_ptr<aura::Window> normal = - CreateTestWindow(gfx::Rect(10, 10, 200, 200)); + UpdateDisplay("400x300"); + std::unique_ptr<aura::Window> wide = CreateTestWindow(gfx::Rect(400, 160)); + std::unique_ptr<aura::Window> tall = CreateTestWindow(gfx::Rect(100, 300)); + std::unique_ptr<aura::Window> normal = CreateTestWindow(gfx::Rect(300, 300)); ScopedOverviewTransformWindow scoped_wide(nullptr, wide.get()); ScopedOverviewTransformWindow scoped_tall(nullptr, tall.get()); @@ -251,8 +245,6 @@ EXPECT_EQ(GridWindowFillMode::kNormal, scoped_wide.type()); EXPECT_EQ(GridWindowFillMode::kPillarBoxed, scoped_tall.type()); EXPECT_EQ(GridWindowFillMode::kNormal, scoped_normal.type()); - - NonClientFrameViewAsh::set_use_empty_minimum_size_for_test(false); } // Tests that transients which should be invisible in overview do not have their
diff --git a/ash/wm/splitview/split_view_controller_unittest.cc b/ash/wm/splitview/split_view_controller_unittest.cc index 71be4014..0d589fd 100644 --- a/ash/wm/splitview/split_view_controller_unittest.cc +++ b/ash/wm/splitview/split_view_controller_unittest.cc
@@ -22,6 +22,7 @@ #include "ash/system/status_area_widget.h" #include "ash/system/status_area_widget_test_helper.h" #include "ash/test/ash_test_base.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "ash/wm/desks/desks_util.h" #include "ash/wm/drag_window_resizer.h" #include "ash/wm/mru_window_tracker.h"
diff --git a/ash/wm/workspace/backdrop_controller.cc b/ash/wm/workspace/backdrop_controller.cc index eb292da..6cbeb55 100644 --- a/ash/wm/workspace/backdrop_controller.cc +++ b/ash/wm/workspace/backdrop_controller.cc
@@ -15,7 +15,7 @@ #include "ash/public/cpp/window_properties.h" #include "ash/screen_util.h" #include "ash/shell.h" -#include "ash/wallpaper/wallpaper_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "ash/wm/always_on_top_controller.h" #include "ash/wm/desks/desks_util.h" #include "ash/wm/overview/overview_controller.h"
diff --git a/ash/wm/workspace/backdrop_controller.h b/ash/wm/workspace/backdrop_controller.h index a2aaf0c..6cc60d1 100644 --- a/ash/wm/workspace/backdrop_controller.h +++ b/ash/wm/workspace/backdrop_controller.h
@@ -10,8 +10,8 @@ #include "ash/accessibility/accessibility_observer.h" #include "ash/ash_export.h" #include "ash/public/cpp/split_view.h" -#include "ash/public/cpp/wallpaper_controller_observer.h" #include "ash/shell_observer.h" +#include "ash/wallpaper/wallpaper_controller_observer.h" #include "ash/wm/overview/overview_observer.h" #include "base/macros.h" #include "ui/gfx/geometry/rect.h"
diff --git a/ash/wm/workspace/workspace_layout_manager_unittest.cc b/ash/wm/workspace/workspace_layout_manager_unittest.cc index f1a5a32b3..ed010e5 100644 --- a/ash/wm/workspace/workspace_layout_manager_unittest.cc +++ b/ash/wm/workspace/workspace_layout_manager_unittest.cc
@@ -147,34 +147,14 @@ } // namespace -// NOTE: many of these tests use NonClientFrameViewAshSizeLock. This is needed -// as the tests assume a minimum size of 0x0. In mash the minimum size, for -// top-level windows, is not 0x0, so without this the tests fails. -// TODO(sky): update the tests so that this isn't necessary. -class NonClientFrameViewAshSizeLock { - public: - NonClientFrameViewAshSizeLock() { - NonClientFrameViewAsh::use_empty_minimum_size_for_test_ = true; - } - ~NonClientFrameViewAshSizeLock() { - NonClientFrameViewAsh::use_empty_minimum_size_for_test_ = false; - } - - private: - DISALLOW_COPY_AND_ASSIGN(NonClientFrameViewAshSizeLock); -}; - using WorkspaceLayoutManagerTest = AshTestBase; // Verifies that a window containing a restore coordinate will be restored to // to the size prior to minimize, keeping the restore rectangle in tact (if // there is one). TEST_F(WorkspaceLayoutManagerTest, RestoreFromMinimizeKeepsRestore) { - // See comment at top of file for why this is needed. - NonClientFrameViewAshSizeLock min_size_lock; - std::unique_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4))); - gfx::Rect bounds(10, 15, 25, 35); - window->SetBounds(bounds); + std::unique_ptr<aura::Window> window( + CreateTestWindow(gfx::Rect(10, 15, 125, 35))); wm::WindowState* window_state = wm::GetWindowState(window.get()); @@ -183,16 +163,16 @@ window_state->Minimize(); window_state->Restore(); EXPECT_EQ("0,0 100x100", window_state->GetRestoreBoundsInScreen().ToString()); - EXPECT_EQ("10,15 25x35", window->bounds().ToString()); + EXPECT_EQ("10,15 125x35", window->bounds().ToString()); UpdateDisplay("400x300,500x400"); - window->SetBoundsInScreen(gfx::Rect(600, 0, 100, 100), GetSecondaryDisplay()); + window->SetBoundsInScreen(gfx::Rect(600, 0, 125, 100), GetSecondaryDisplay()); EXPECT_EQ(Shell::Get()->GetAllRootWindows()[1], window->GetRootWindow()); window_state->Minimize(); // This will not be used for un-minimizing window. window_state->SetRestoreBoundsInScreen(gfx::Rect(0, 0, 100, 100)); window_state->Restore(); - EXPECT_EQ("600,0 100x100", window->GetBoundsInScreen().ToString()); + EXPECT_EQ("600,0 125x100", window->GetBoundsInScreen().ToString()); // Make sure the unminimized window moves inside the display when // 2nd display is disconnected. @@ -235,59 +215,55 @@ } TEST_F(WorkspaceLayoutManagerTest, KeepRestoredWindowInDisplay) { - // See comment at top of file for why this is needed. - NonClientFrameViewAshSizeLock min_size_lock; std::unique_ptr<aura::Window> window( - CreateTestWindow(gfx::Rect(1, 2, 30, 40))); + CreateTestWindow(gfx::Rect(1, 2, 130, 40))); wm::WindowState* window_state = wm::GetWindowState(window.get()); // Maximized -> Normal transition. window_state->Maximize(); - window_state->SetRestoreBoundsInScreen(gfx::Rect(-100, -100, 30, 40)); + window_state->SetRestoreBoundsInScreen(gfx::Rect(-100, -100, 130, 40)); window_state->Restore(); EXPECT_TRUE( Shell::GetPrimaryRootWindow()->bounds().Intersects(window->bounds())); // Y bounds should not be negative. - EXPECT_EQ("-5,0 30x40", window->bounds().ToString()); + EXPECT_GE(window->bounds().y(), 0); // Minimized -> Normal transition. - window->SetBounds(gfx::Rect(-100, -100, 30, 40)); + window->SetBounds(gfx::Rect(-100, -100, 130, 40)); window_state->Minimize(); EXPECT_FALSE( Shell::GetPrimaryRootWindow()->bounds().Intersects(window->bounds())); - EXPECT_EQ("-100,-100 30x40", window->bounds().ToString()); + EXPECT_EQ("-100,-100 130x40", window->bounds().ToString()); window->Show(); EXPECT_TRUE( Shell::GetPrimaryRootWindow()->bounds().Intersects(window->bounds())); // Y bounds should not be negative. - EXPECT_EQ("-5,0 30x40", window->bounds().ToString()); + EXPECT_GE(window->bounds().y(), 0); // Fullscreen -> Normal transition. - window->SetBounds(gfx::Rect(0, 0, 30, 40)); // reset bounds. - ASSERT_EQ("0,0 30x40", window->bounds().ToString()); + window->SetBounds(gfx::Rect(0, 0, 130, 40)); // reset bounds. + ASSERT_EQ("0,0 130x40", window->bounds().ToString()); window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); EXPECT_EQ(window->bounds(), window->GetRootWindow()->bounds()); - window_state->SetRestoreBoundsInScreen(gfx::Rect(-100, -100, 30, 40)); + window_state->SetRestoreBoundsInScreen(gfx::Rect(-100, -100, 130, 40)); window_state->Restore(); EXPECT_TRUE( Shell::GetPrimaryRootWindow()->bounds().Intersects(window->bounds())); // Y bounds should not be negative. - EXPECT_EQ("-5,0 30x40", window->bounds().ToString()); + EXPECT_GE(window->bounds().y(), 0); } TEST_F(WorkspaceLayoutManagerTest, MaximizeInDisplayToBeRestored) { - // See comment at top of file for why this is needed. - NonClientFrameViewAshSizeLock min_size_lock; UpdateDisplay("300x400,400x500"); aura::Window::Windows root_windows = Shell::Get()->GetAllRootWindows(); std::unique_ptr<aura::Window> window( - CreateTestWindow(gfx::Rect(1, 2, 30, 40))); + CreateTestWindow(gfx::Rect(1, 2, 130, 40))); EXPECT_EQ(root_windows[0], window->GetRootWindow()); wm::WindowState* window_state = wm::GetWindowState(window.get()); - window_state->SetRestoreBoundsInScreen(gfx::Rect(400, 0, 30, 40)); + window_state->SetRestoreBoundsInScreen(gfx::Rect(400, 0, 130, 40)); // Maximize the window in 2nd display as the restore bounds // is inside 2nd display. window_state->Maximize(); @@ -298,11 +274,11 @@ window_state->Restore(); EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_EQ("400,0 30x40", window->GetBoundsInScreen().ToString()); + EXPECT_EQ("400,0 130x40", window->GetBoundsInScreen().ToString()); // If the restore bounds intersects with the current display, // don't move. - window_state->SetRestoreBoundsInScreen(gfx::Rect(295, 0, 30, 40)); + window_state->SetRestoreBoundsInScreen(gfx::Rect(295, 0, 130, 40)); window_state->Maximize(); EXPECT_EQ(root_windows[1], window->GetRootWindow()); EXPECT_EQ( @@ -311,13 +287,13 @@ window_state->Restore(); EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_EQ("295,0 30x40", window->GetBoundsInScreen().ToString()); + EXPECT_EQ("295,0 130x40", window->GetBoundsInScreen().ToString()); // Restoring widget state. std::unique_ptr<views::Widget> w1(new views::Widget); views::Widget::InitParams params; params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.delegate = new MaximizeDelegateView(gfx::Rect(400, 0, 30, 40)); + params.delegate = new MaximizeDelegateView(gfx::Rect(400, 0, 130, 40)); params.context = CurrentContext(); w1->Init(params); EXPECT_EQ(root_windows[0], w1->GetNativeWindow()->GetRootWindow()); @@ -329,12 +305,10 @@ w1->GetWindowBoundsInScreen().ToString()); w1->Restore(); EXPECT_EQ(root_windows[1], w1->GetNativeWindow()->GetRootWindow()); - EXPECT_EQ("400,0 30x40", w1->GetWindowBoundsInScreen().ToString()); + EXPECT_EQ("400,0 130x40", w1->GetWindowBoundsInScreen().ToString()); } TEST_F(WorkspaceLayoutManagerTest, FullscreenInDisplayToBeRestored) { - // See comment at top of file for why this is needed. - NonClientFrameViewAshSizeLock min_size_lock; UpdateDisplay("300x400,400x500"); aura::Window::Windows root_windows = Shell::Get()->GetAllRootWindows(); @@ -344,7 +318,7 @@ EXPECT_EQ(root_windows[0], window->GetRootWindow()); wm::WindowState* window_state = wm::GetWindowState(window.get()); - window_state->SetRestoreBoundsInScreen(gfx::Rect(400, 0, 30, 40)); + window_state->SetRestoreBoundsInScreen(gfx::Rect(400, 0, 130, 40)); // Maximize the window in 2nd display as the restore bounds // is inside 2nd display. window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); @@ -353,18 +327,18 @@ window_state->Restore(); EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_EQ("400,0 30x40", window->GetBoundsInScreen().ToString()); + EXPECT_EQ("400,0 130x40", window->GetBoundsInScreen().ToString()); // If the restore bounds intersects with the current display, // don't move. - window_state->SetRestoreBoundsInScreen(gfx::Rect(295, 0, 30, 40)); + window_state->SetRestoreBoundsInScreen(gfx::Rect(295, 0, 130, 40)); window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); EXPECT_EQ(root_windows[1], window->GetRootWindow()); EXPECT_EQ("300,0 400x500", window->GetBoundsInScreen().ToString()); window_state->Restore(); EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_EQ("295,0 30x40", window->GetBoundsInScreen().ToString()); + EXPECT_EQ("295,0 130x40", window->GetBoundsInScreen().ToString()); } // aura::WindowObserver implementation used by @@ -1701,9 +1675,6 @@ TEST_F(WorkspaceLayoutManagerKeyboardTest, ChildWindowFocused) { ScopedStickyKeyboardEnabler sticky_enabler; - // See comment at top of file for why this is needed. - NonClientFrameViewAshSizeLock min_size_lock; - InitKeyboardBounds(); gfx::Rect work_area(GetPrimaryDisplay().work_area()); @@ -1733,15 +1704,10 @@ TEST_F(WorkspaceLayoutManagerKeyboardTest, AdjustWindowForA11yKeyboard) { ScopedStickyKeyboardEnabler sticky_enabler; - // See comment at top of file for why this is needed. - NonClientFrameViewAshSizeLock min_size_lock; InitKeyboardBounds(); gfx::Rect work_area(GetPrimaryDisplay().work_area()); std::unique_ptr<aura::Window> window(CreateToplevelTestWindow(work_area)); - // The additional SetBounds() is needed as the aura-mus case uses Widget, - // which alters the supplied bounds. - window->SetBounds(work_area); int available_height = GetPrimaryDisplay().bounds().height() - keyboard_bounds().height(); @@ -1787,9 +1753,6 @@ InitKeyboardBounds(); std::unique_ptr<aura::Window> window(CreateTestWindow(keyboard_bounds())); - // The additional SetBounds() is needed as the aura-mus case uses Widget, - // which alters the supplied bounds. - window->SetBounds(keyboard_bounds()); wm::GetWindowState(window.get())->set_ignore_keyboard_bounds_change(true); wm::ActivateWindow(window.get());
diff --git a/base/allocator/partition_allocator/partition_alloc_unittest.cc b/base/allocator/partition_allocator/partition_alloc_unittest.cc index 5ebe066..3e4596b 100644 --- a/base/allocator/partition_allocator/partition_alloc_unittest.cc +++ b/base/allocator/partition_allocator/partition_alloc_unittest.cc
@@ -2184,7 +2184,14 @@ generic_allocator.root()->Free(ptr); } -TEST_F(PartitionAllocTest, ZeroFill) { +// TODO(crbug.com/966169): This test is flaky on Fuchsia. +#if defined(OS_FUCHSIA) +#define MAYBE_ZeroFill DISABLED_ZeroFill +#else +#define MAYBE_ZeroFill ZeroFill +#endif // defined(OS_FUCHSIA) + +TEST_F(PartitionAllocTest, MAYBE_ZeroFill) { constexpr static size_t kAllZerosSentinel = std::numeric_limits<size_t>::max(); for (size_t size : kTestSizes) {
diff --git a/base/android/jni_array.cc b/base/android/jni_array.cc index 054853d9..80efbe11d 100644 --- a/base/android/jni_array.cc +++ b/base/android/jni_array.cc
@@ -171,6 +171,25 @@ return ScopedJavaLocalRef<jobjectArray>(env, joa); } +ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfStringArray( + JNIEnv* env, + const std::vector<std::vector<string16>>& vec_outer) { + ScopedJavaLocalRef<jclass> string_array_clazz = + GetClass(env, "[Ljava/lang/String;"); + + jobjectArray joa = + env->NewObjectArray(vec_outer.size(), string_array_clazz.obj(), NULL); + CheckException(env); + + for (size_t i = 0; i < vec_outer.size(); ++i) { + ScopedJavaLocalRef<jobjectArray> inner = + ToJavaArrayOfStrings(env, vec_outer[i]); + env->SetObjectArrayElement(joa, i, inner.obj()); + } + + return ScopedJavaLocalRef<jobjectArray>(env, joa); +} + ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfStrings( JNIEnv* env, const std::vector<string16>& v) { ScopedJavaLocalRef<jclass> string_clazz = GetClass(env, "java/lang/String"); @@ -329,6 +348,23 @@ } } +void Java2dStringArrayTo2dStringVector( + JNIEnv* env, + const JavaRef<jobjectArray>& array, + std::vector<std::vector<string16>>* out) { + DCHECK(out); + size_t len = SafeGetArrayLength(env, array); + out->resize(len); + for (size_t i = 0; i < len; ++i) { + ScopedJavaLocalRef<jobjectArray> strings_array( + env, + static_cast<jobjectArray>(env->GetObjectArrayElement(array.obj(), i))); + + out->at(i).clear(); + AppendJavaStringArrayToStringVector(env, strings_array, &out->at(i)); + } +} + void JavaArrayOfIntArrayToIntVector(JNIEnv* env, const JavaRef<jobjectArray>& array, std::vector<std::vector<int>>* out) {
diff --git a/base/android/jni_array.h b/base/android/jni_array.h index 917f1d0..f7a7273 100644 --- a/base/android/jni_array.h +++ b/base/android/jni_array.h
@@ -78,6 +78,10 @@ BASE_EXPORT ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfStrings( JNIEnv* env, const std::vector<string16>& v); +BASE_EXPORT ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfStringArray( + JNIEnv* env, + const std::vector<std::vector<string16>>& v); + // Converts a Java string array to a native array. BASE_EXPORT void AppendJavaStringArrayToStringVector( JNIEnv* env, @@ -144,6 +148,14 @@ const JavaRef<jobjectArray>& array, std::vector<std::string>* out); +// Assuming |array| is an String[][] (array of String arrays), replaces the +// content of |out| with the corresponding vector of string vectors. No UTF-8 +// conversion is performed. +BASE_EXPORT void Java2dStringArrayTo2dStringVector( + JNIEnv* env, + const JavaRef<jobjectArray>& array, + std::vector<std::vector<string16>>* out); + // Assuming |array| is an int[][] (array of int arrays), replaces the // contents of |out| with the corresponding vectors of ints. BASE_EXPORT void JavaArrayOfIntArrayToIntVector(
diff --git a/base/android/jni_array_unittest.cc b/base/android/jni_array_unittest.cc index 2ddf0ff..024b56f 100644 --- a/base/android/jni_array_unittest.cc +++ b/base/android/jni_array_unittest.cc
@@ -6,12 +6,15 @@ #include <stddef.h> #include <stdint.h> +#include <algorithm> #include <limits> #include "base/android/jni_android.h" +#include "base/android/jni_string.h" #include "base/android/scoped_java_ref.h" #include "base/stl_util.h" +#include "base/strings/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" namespace base { @@ -177,6 +180,21 @@ } } +TEST(JniArray, ArrayOfStringArrayConversion) { + std::vector<std::vector<string16>> kArrays = { + {ASCIIToUTF16("a"), ASCIIToUTF16("f")}, + {ASCIIToUTF16("a"), ASCIIToUTF16("")}, + {}, + {ASCIIToUTF16("")}}; + + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobjectArray> joa = ToJavaArrayOfStringArray(env, kArrays); + + std::vector<std::vector<string16>> out; + Java2dStringArrayTo2dStringVector(env, joa, &out); + ASSERT_TRUE(kArrays == out); +} + TEST(JniArray, FloatConversions) { const float kFloats[] = { 0.0f, 1.0f, -10.0f}; const size_t kLen = base::size(kFloats); @@ -352,6 +370,46 @@ } } +TEST(JniArray, JavaArrayOfStringArrayToVectorOfStringVector) { + const std::vector<std::vector<string16>> kArrays = { + {ASCIIToUTF16("a"), ASCIIToUTF16("f")}, + {ASCIIToUTF16("a"), ASCIIToUTF16("")}, + {}, + {ASCIIToUTF16("")}}; + + JNIEnv* env = AttachCurrentThread(); + + ScopedJavaLocalRef<jobjectArray> array( + env, env->NewObjectArray(kArrays.size(), + env->FindClass("[Ljava/lang/String;"), NULL)); + ASSERT_TRUE(array); + + ScopedJavaLocalRef<jclass> string_clazz(env, + env->FindClass("java/lang/String")); + ASSERT_TRUE(string_clazz); + + for (size_t i = 0; i < kArrays.size(); ++i) { + const std::vector<string16>& child_data = kArrays[i]; + + ScopedJavaLocalRef<jobjectArray> child_array( + env, env->NewObjectArray(child_data.size(), string_clazz.obj(), NULL)); + ASSERT_TRUE(child_array); + + for (size_t j = 0; j < child_data.size(); ++j) { + ScopedJavaLocalRef<jstring> item = + base::android::ConvertUTF16ToJavaString(env, child_data[j]); + env->SetObjectArrayElement(child_array.obj(), j, item.obj()); + ASSERT_FALSE(HasException(env)); + } + env->SetObjectArrayElement(array.obj(), i, child_array.obj()); + } + + std::vector<std::vector<string16>> vec; + Java2dStringArrayTo2dStringVector(env, array, &vec); + + ASSERT_EQ(kArrays, vec); +} + TEST(JniArray, JavaArrayOfIntArrayToIntVector) { const size_t kNumItems = 4; JNIEnv* env = AttachCurrentThread();
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 27fe4aa..a5a53d5 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -422,6 +422,7 @@ "//components/signin/core/browser:signin_enums_javagen", "//components/supervised_user_error_page:enums_srcjar", "//components/ui_metrics:ui_metrics_enums_java", + "//chrome/browser/notifications/scheduler:jni_enums", "//chrome/browser/ui:tab_model_enums_java", "//net:effective_connection_type_java", ":vr_build_config",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index 93cfbd3..3e963fd 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -71,6 +71,7 @@ "java/src/org/chromium/chrome/browser/accessibility/FontSizePrefs.java", "java/src/org/chromium/chrome/browser/appmenu/AppMenu.java", "java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java", + "java/src/org/chromium/chrome/browser/appmenu/AppMenuBlocker.java", "java/src/org/chromium/chrome/browser/appmenu/AppMenuButtonHelper.java", "java/src/org/chromium/chrome/browser/appmenu/AppMenuButtonHelperImpl.java", "java/src/org/chromium/chrome/browser/appmenu/AppMenuCoordinator.java", @@ -292,6 +293,7 @@ "java/src/org/chromium/chrome/browser/contacts_picker/PickerCategoryView.java", "java/src/org/chromium/chrome/browser/contacts_picker/TopView.java", "java/src/org/chromium/chrome/browser/content/ContentUtils.java", + "java/src/org/chromium/chrome/browser/content_capture/ContentCaptureHistoryDeletionObserver.java", "java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuItem.java", "java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java", "java/src/org/chromium/chrome/browser/contextmenu/ContextMenuHelper.java", @@ -692,10 +694,10 @@ "java/src/org/chromium/chrome/browser/gcore/GoogleApiClientHelper.java", "java/src/org/chromium/chrome/browser/gcore/LifecycleHook.java", "java/src/org/chromium/chrome/browser/gesturenav/AndroidUiNavigationGlow.java", - "java/src/org/chromium/chrome/browser/gesturenav/ArrowChipView.java", "java/src/org/chromium/chrome/browser/gesturenav/CompositorNavigationGlow.java", "java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationDelegate.java", "java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationLayout.java", + "java/src/org/chromium/chrome/browser/gesturenav/NavigationBubble.java", "java/src/org/chromium/chrome/browser/gesturenav/NavigationGlow.java", "java/src/org/chromium/chrome/browser/gesturenav/NavigationGlowFactory.java", "java/src/org/chromium/chrome/browser/gesturenav/NavigationHandler.java",
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupUtils.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupUtils.java index e63e811..928efe1 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupUtils.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupUtils.java
@@ -12,7 +12,6 @@ import org.chromium.chrome.browser.feature_engagement.TrackerFactory; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver; import org.chromium.chrome.browser.tasks.tabgroup.TabGroupModelFilter; @@ -132,20 +131,4 @@ return selector.getCurrentModel().indexOf(tabs.get(tabs.size() - 1)); } - - /** - * This method judges whether the current move from {@code curIndex} to {@code newIndex} in - * {@code tabModel} is a move within one TabGroup or not. - * @param tabModel The TabModel that owns the moving tab. - * @param curIndex The current index of the moving tab. - * @param newIndex The new index of the moving tab. - * @return Whether is move happens within one TabGroup or not. - */ - public static boolean isMoveInSameGroup(TabModel tabModel, int curIndex, int newIndex) { - int rootId = tabModel.getTabAt(curIndex).getRootId(); - for (int i = Math.min(newIndex, curIndex); i <= Math.max(newIndex, curIndex); i++) { - if (tabModel.getTabAt(i).getRootId() != rootId) return false; - } - return true; - } }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java index c408b68..3a55f47 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
@@ -233,6 +233,8 @@ private final TabModelObserver mTabModelObserver; + private TabGroupModelFilter.Observer mTabGroupObserver; + /** * Interface for implementing a {@link Runnable} that takes a tabId for a generic action. */ @@ -324,12 +326,69 @@ @Override public void didMoveTab(Tab tab, int newIndex, int curIndex) { + if (mTabModelSelector.getTabModelFilterProvider().getCurrentTabModelFilter() + instanceof TabGroupModelFilter) { + return; + } onTabMoved(tab, newIndex, curIndex); } }; mTabModelSelector.getTabModelFilterProvider().addTabModelFilterObserver(mTabModelObserver); + if (mTabModelSelector.getTabModelFilterProvider().getCurrentTabModelFilter() + instanceof TabGroupModelFilter) { + mTabGroupObserver = new TabGroupModelFilter.Observer() { + @Override + public void didMoveWithinGroup( + Tab movedTab, int tabModelOldIndex, int tabModelNewIndex) { + int curPosition = mModel.indexFromId(movedTab.getId()); + TabModel tabModel = mTabModelSelector.getCurrentModel(); + + if (!isValidMovePosition(curPosition)) return; + + Tab destinationTab = tabModel.getTabAt(tabModelNewIndex > tabModelOldIndex + ? tabModelNewIndex - 1 + : tabModelNewIndex + 1); + + int newPosition = mModel.indexFromId(destinationTab.getId()); + if (!isValidMovePosition(newPosition)) return; + mModel.move(curPosition, newPosition); + } + + @Override + public void didMoveTabGroup( + Tab movedTab, int tabModelOldIndex, int tabModelNewIndex) { + List<Tab> relatedTabs = getRelatedTabsForId(movedTab.getId()); + Tab currentGroupSelectedTab = + TabGroupUtils.getSelectedTabInGroupForTab(mTabModelSelector, movedTab); + TabModel tabModel = mTabModelSelector.getCurrentModel(); + int curPosition = mModel.indexFromId(currentGroupSelectedTab.getId()); + if (!isValidMovePosition(curPosition)) return; + + // Find the tab which was in the destination index before this move. Use that + // tab to figure out the new position. + int destinationTabIndex = tabModelNewIndex > tabModelOldIndex + ? tabModelNewIndex - relatedTabs.size() + : tabModelNewIndex + 1; + Tab destinationTab = tabModel.getTabAt(destinationTabIndex); + Tab destinationGroupSelectedTab = TabGroupUtils.getSelectedTabInGroupForTab( + mTabModelSelector, destinationTab); + int newPosition = mModel.indexFromId(destinationGroupSelectedTab.getId()); + if (!isValidMovePosition(newPosition)) return; + + mModel.move(curPosition, newPosition); + } + }; + + ((TabGroupModelFilter) mTabModelSelector.getTabModelFilterProvider().getTabModelFilter( + false)) + .addTabGroupObserver(mTabGroupObserver); + ((TabGroupModelFilter) mTabModelSelector.getTabModelFilterProvider().getTabModelFilter( + true)) + .addTabGroupObserver(mTabGroupObserver); + } + // TODO(meiliang): follow up with unit tests to test the close signal is sent correctly with // the recommendedNextTab. mTabClosedListener = new TabActionListener() { @@ -424,54 +483,12 @@ } private void onTabMoved(Tab tab, int newIndex, int curIndex) { - List<Tab> relatedTabs = getRelatedTabsForId(tab.getId()); - TabModel tabModel = mTabModelSelector.getCurrentModel(); - // Handle move without groups enabled. if (mTabModelSelector.getTabModelFilterProvider().getCurrentTabModelFilter() instanceof EmptyTabModelFilter) { if (!isValidMovePosition(curIndex) || !isValidMovePosition(newIndex)) return; mModel.move(curIndex, newIndex); - return; } - - // Handle move with groups enabled. - // When move within one group. - if (TabGroupUtils.isMoveInSameGroup(tabModel, curIndex, newIndex)) { - int curPosition = mModel.indexFromId(tab.getId()); - if (!isValidMovePosition(curPosition)) return; - Tab destinationTab = - tabModel.getTabAt(newIndex > curIndex ? newIndex - 1 : newIndex + 1); - int newPosition = mModel.indexFromId(destinationTab.getId()); - if (!isValidMovePosition(newPosition)) return; - mModel.move(curPosition, newPosition); - return; - } - - // When move between groups. - // Only proceed when all members of the group are moved to target index in TabModel. - // Regardless of the size of tab group, one tab(group) only proceeds once here per - // move. - int lastTabInGroupIndex = newIndex - relatedTabs.size() + 1; - if (!relatedTabs.contains(tabModel.getTabAt(lastTabInGroupIndex))) return; - - // Locate current position of the moving tab in TabListModel. - Tab currentGroupSelectedTab = - TabGroupUtils.getSelectedTabInGroupForTab(mTabModelSelector, tab); - int curPosition = mModel.indexFromId(currentGroupSelectedTab.getId()); - if (!isValidMovePosition(curPosition)) return; - - // Find the tab which was in the destination index before this move. Use that tab to - // figure out the new position. - int destinationTabIndex = - newIndex > curIndex ? newIndex - relatedTabs.size() : newIndex + 1; - Tab destinationTab = tabModel.getTabAt(destinationTabIndex); - Tab destinationGroupSelectedTab = - TabGroupUtils.getSelectedTabInGroupForTab(mTabModelSelector, destinationTab); - int newPosition = mModel.indexFromId(destinationGroupSelectedTab.getId()); - if (!isValidMovePosition(newPosition)) return; - - mModel.move(curPosition, newPosition); } private boolean isValidMovePosition(int position) { @@ -613,6 +630,14 @@ mTabModelSelector.getTabModelFilterProvider().removeTabModelFilterObserver( mTabModelObserver); } + if (mTabGroupObserver != null) { + ((TabGroupModelFilter) mTabModelSelector.getTabModelFilterProvider().getTabModelFilter( + false)) + .removeTabGroupObserver(mTabGroupObserver); + ((TabGroupModelFilter) mTabModelSelector.getTabModelFilterProvider().getTabModelFilter( + true)) + .removeTabGroupObserver(mTabGroupObserver); + } if (mComponentCallbacks != null) { ContextUtils.getApplicationContext().unregisterComponentCallbacks(mComponentCallbacks); }
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java index 4631062..954cef6 100644 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java +++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
@@ -100,6 +100,8 @@ ArgumentCaptor<TabObserver> mTabObserverCaptor; @Captor ArgumentCaptor<Callback<Drawable>> mCallbackCaptor; + @Captor + ArgumentCaptor<TabGroupModelFilter.Observer> mTabGroupModelFilterObserverCaptor; private Tab mTab1; private Tab mTab2; @@ -432,7 +434,7 @@ @Test public void tabMovementWithGroup_Forward() { - initAndAssertAllProperties(); + setUpForTabGroupOperation(); // Assume that moveTab in TabModel is finished. doReturn(mTab1).when(mTabModel).getTabAt(POSITION2); @@ -443,7 +445,7 @@ assertThat(mModel.get(1).get(TabProperties.TAB_ID), equalTo(TAB2_ID)); assertThat(mModel.get(1).get(TabProperties.TITLE), equalTo(TAB2_TITLE)); - mTabModelObserverCaptor.getValue().didMoveTab(mTab2, POSITION1, POSITION2); + mTabGroupModelFilterObserverCaptor.getValue().didMoveTabGroup(mTab2, POSITION2, POSITION1); assertThat(mModel.size(), equalTo(2)); assertThat(mModel.get(0).get(TabProperties.TAB_ID), equalTo(TAB2_ID)); @@ -452,7 +454,7 @@ @Test public void tabMovementWithGroup_Backward() { - initAndAssertAllProperties(); + setUpForTabGroupOperation(); // Assume that moveTab in TabModel is finished. doReturn(mTab1).when(mTabModel).getTabAt(POSITION2); @@ -463,7 +465,7 @@ assertThat(mModel.get(1).get(TabProperties.TAB_ID), equalTo(TAB2_ID)); assertThat(mModel.get(1).get(TabProperties.TITLE), equalTo(TAB2_TITLE)); - mTabModelObserverCaptor.getValue().didMoveTab(mTab1, POSITION2, POSITION1); + mTabGroupModelFilterObserverCaptor.getValue().didMoveTabGroup(mTab1, POSITION1, POSITION2); assertThat(mModel.size(), equalTo(2)); assertThat(mModel.get(0).get(TabProperties.TAB_ID), equalTo(TAB2_ID)); @@ -472,7 +474,7 @@ @Test public void tabMovementWithinGroup_Forward() { - initAndAssertAllProperties(); + setUpForTabGroupOperation(); // Assume that moveTab in TabModel is finished. doReturn(mTab1).when(mTabModel).getTabAt(POSITION2); @@ -485,7 +487,8 @@ assertThat(mModel.get(1).get(TabProperties.TAB_ID), equalTo(TAB2_ID)); assertThat(mModel.get(1).get(TabProperties.TITLE), equalTo(TAB2_TITLE)); - mTabModelObserverCaptor.getValue().didMoveTab(mTab2, POSITION1, POSITION2); + mTabGroupModelFilterObserverCaptor.getValue().didMoveWithinGroup( + mTab2, POSITION2, POSITION1); assertThat(mModel.size(), equalTo(2)); assertThat(mModel.get(0).get(TabProperties.TAB_ID), equalTo(TAB2_ID)); @@ -494,7 +497,7 @@ @Test public void tabMovementWithinGroup_Backward() { - initAndAssertAllProperties(); + setUpForTabGroupOperation(); // Assume that moveTab in TabModel is finished. doReturn(mTab1).when(mTabModel).getTabAt(POSITION2); @@ -507,7 +510,8 @@ assertThat(mModel.get(1).get(TabProperties.TAB_ID), equalTo(TAB2_ID)); assertThat(mModel.get(1).get(TabProperties.TITLE), equalTo(TAB2_TITLE)); - mTabModelObserverCaptor.getValue().didMoveTab(mTab1, POSITION2, POSITION1); + mTabGroupModelFilterObserverCaptor.getValue().didMoveWithinGroup( + mTab1, POSITION1, POSITION2); assertThat(mModel.size(), equalTo(2)); assertThat(mModel.get(0).get(TabProperties.TAB_ID), equalTo(TAB2_ID)); @@ -570,4 +574,19 @@ doReturn(position).when(viewHolder).getAdapterPosition(); return viewHolder; } + + private void setUpForTabGroupOperation() { + doReturn(mTabGroupModelFilter).when(mTabModelFilterProvider).getCurrentTabModelFilter(); + doReturn(mTabGroupModelFilter).when(mTabModelFilterProvider).getTabModelFilter(true); + doReturn(mTabGroupModelFilter).when(mTabModelFilterProvider).getTabModelFilter(false); + doNothing() + .when(mTabGroupModelFilter) + .addTabGroupObserver(mTabGroupModelFilterObserverCaptor.capture()); + + mMediator = new TabListMediator(mModel, mTabModelSelector, + mTabContentManager::getTabThumbnailWithCallback, null, mTabListFaviconProvider, + false, null, null, getClass().getSimpleName()); + + initAndAssertAllProperties(); + } }
diff --git a/chrome/android/java/res/layout/navigation_bubble.xml b/chrome/android/java/res/layout/navigation_bubble.xml new file mode 100644 index 0000000..a9ca81d --- /dev/null +++ b/chrome/android/java/res/layout/navigation_bubble.xml
@@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2019 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. + --> + +<org.chromium.chrome.browser.gesturenav.NavigationBubble + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:minHeight="@dimen/navigation_bubble_default_height" + android:gravity="center_vertical" + android:orientation="horizontal"> + + <org.chromium.ui.widget.ChromeImageView + android:id="@+id/navigation_bubble_icon" + android:layout_width="@dimen/navigation_bubble_icon_size" + android:layout_height="@dimen/navigation_bubble_icon_size" + android:layout_marginStart="@dimen/navigation_bubble_icon_leading_margin" /> + <TextView + android:id="@+id/navigation_bubble_text" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:gravity="center" + android:paddingStart="@dimen/navigation_bubble_horizontal_padding" + android:paddingTop="@dimen/navigation_bubble_vertical_padding" + android:paddingEnd="@dimen/navigation_bubble_horizontal_padding" + android:paddingBottom="@dimen/navigation_bubble_vertical_padding" + android:textAppearance="@style/TextAppearance.BlackTitle2" + android:maxLines="1" + android:ellipsize="end" /> +</org.chromium.chrome.browser.gesturenav.NavigationBubble>
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml index bee945a..c152412 100644 --- a/chrome/android/java/res/values/colors.xml +++ b/chrome/android/java/res/values/colors.xml
@@ -181,6 +181,11 @@ <color name="payments_section_edit_background">@color/modern_secondary_color</color> <color name="payments_section_chevron">#B2B2B2</color> + <!-- History Navigation UI colors --> + <color name="navigation_bubble_stroke_color">@color/hairline_stroke_color</color> + <color name="navigation_bubble_background_color">@color/default_bg_color_elev_4</color> + <color name="navigation_bubble_ripple_color">@color/modern_grey_800</color> + <!-- Other colors --> <color name="media_viewer_bg">#000000</color> <color name="image_viewer_bg">#0E0E0E</color>
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml index bd8b03c..1ac2935 100644 --- a/chrome/android/java/res/values/dimens.xml +++ b/chrome/android/java/res/values/dimens.xml
@@ -598,4 +598,11 @@ <dimen name="radio_button_with_description_lateral_padding">16dp</dimen> <dimen name="radio_button_with_description_vertical_padding">10dp</dimen> + <!-- History Navigation UI Item --> + <dimen name="navigation_bubble_border_width">1dp</dimen> + <dimen name="navigation_bubble_default_height">32dp</dimen> + <dimen name="navigation_bubble_vertical_padding">4dp</dimen> + <dimen name="navigation_bubble_horizontal_padding">8dp</dimen> + <dimen name="navigation_bubble_icon_size">20dp</dimen> + <dimen name="navigation_bubble_icon_leading_margin">8dp</dimen> </resources>
diff --git a/chrome/android/java/res_night/values-night/colors.xml b/chrome/android/java/res_night/values-night/colors.xml index 1fbdf9c..0685d50 100644 --- a/chrome/android/java/res_night/values-night/colors.xml +++ b/chrome/android/java/res_night/values-night/colors.xml
@@ -31,4 +31,8 @@ <!-- Photo Picker colors --> <color name="photo_picker_tile_bg_color">@color/modern_grey_800</color> <color name="photo_picker_special_tile_bg_color">@color/modern_grey_800</color> + + <!-- History Navigation UI colors --> + <color name="navigation_bubble_ripple_color">@android:color/white</color> + </resources>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java index 4edabe3..d2e46a9c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -57,6 +57,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.IntentHandler.IntentHandlerDelegate; import org.chromium.chrome.browser.IntentHandler.TabOpenType; +import org.chromium.chrome.browser.appmenu.AppMenuBlocker; import org.chromium.chrome.browser.appmenu.AppMenuDelegate; import org.chromium.chrome.browser.appmenu.AppMenuPropertiesDelegate; import org.chromium.chrome.browser.appmenu.AppMenuPropertiesDelegateImpl; @@ -200,7 +201,8 @@ extends AsyncInitializationActivity implements TabCreatorManager, AccessibilityStateChangeListener, PolicyChangeListener, ContextualSearchTabPromotionDelegate, SnackbarManageable, SceneChangeObserver, - StatusBarColorController.StatusBarColorProvider, AppMenuDelegate { + StatusBarColorController.StatusBarColorProvider, AppMenuDelegate, + AppMenuBlocker { /** * No control container to inflate during initialization. */ @@ -1538,7 +1540,7 @@ @CallSuper @Override - public boolean shouldShowAppMenu() { + public boolean canShowAppMenu() { if (isActivityFinishingOrDestroyed()) return false; @ActivityState @@ -1548,22 +1550,6 @@ return false; } - // TODO(https://crbug.com/956260): Move UI state related logic out of ChromeActivity. - - // Do not show the menu if Contextual Search panel is opened. - if (mContextualSearchManager != null && mContextualSearchManager.isSearchPanelOpened()) { - return false; - } - - if (getEphemeralTabPanel() != null && getEphemeralTabPanel().isPanelOpened()) { - return false; - } - - // Do not show the menu if we are in find in page view. - if (mFindToolbarManager != null && mFindToolbarManager.isShowing() && !isTablet()) { - return false; - } - return true; }
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 352cf81..e128b8a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -2256,7 +2256,7 @@ // App Menu related code ----------------------------------------------------------------------- @Override - public boolean shouldShowAppMenu() { + public boolean canShowAppMenu() { // The popup menu relies on the model created during the full UI initialization, so do not // attempt to show the menu until the UI creation has finished. if (!mUIWithNativeInitialized) return false; @@ -2266,7 +2266,7 @@ Tab tab = getActivityTab(); if (tab != null && TabModalPresenter.isDialogShowing(tab)) return false; - return super.shouldShowAppMenu(); + return super.canShowAppMenu(); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuBlocker.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuBlocker.java new file mode 100644 index 0000000..78797206 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuBlocker.java
@@ -0,0 +1,16 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.appmenu; + +/** + * An interface that may be used to block the app menu from showing (e.g. when other conflicting UI + * is showing). To register, see {@link AppMenuCoordinator#registerAppMenuBlocker(AppMenuBlocker)}. + */ +public interface AppMenuBlocker { + /** + * @return Whether the app menu can be shown. + */ + boolean canShowAppMenu(); +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuCoordinator.java index decad4e..e78a365 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuCoordinator.java
@@ -26,4 +26,15 @@ * @return The {@link AppMenuPropertiesDelegate} associated with this activity. */ AppMenuPropertiesDelegate getAppMenuPropertiesDelegate(); + + /** + * Registers an {@link AppMenuBlocker} used to help determine whether the app menu can be shown. + * @param blocker An {@link AppMenuBlocker} to check before attempting to show the app menu. + */ + void registerAppMenuBlocker(AppMenuBlocker blocker); + + /** + * @param blocker The {@link AppMenuBlocker} to unregister. + */ + void unregisterAppMenuBlocker(AppMenuBlocker blocker); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuCoordinatorImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuCoordinatorImpl.java index f0a1e1f..c7fd9d1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuCoordinatorImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuCoordinatorImpl.java
@@ -118,7 +118,7 @@ @Override public void showAppMenuForKeyboardEvent() { - if (mAppMenuHandler == null || !mAppMenuDelegate.shouldShowAppMenu()) return; + if (mAppMenuHandler == null || !mAppMenuHandler.shouldShowAppMenu()) return; boolean hasPermanentMenuKey = ViewConfiguration.get(mContext).hasPermanentMenuKey(); mAppMenuHandler.showAppMenu( @@ -136,6 +136,16 @@ return mAppMenuPropertiesDelegate; } + @Override + public void registerAppMenuBlocker(AppMenuBlocker blocker) { + mAppMenuHandler.registerAppMenuBlocker(blocker); + } + + @Override + public void unregisterAppMenuBlocker(AppMenuBlocker blocker) { + mAppMenuHandler.unregisterAppMenuBlocker(blocker); + } + // Testing methods @VisibleForTesting
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuDelegate.java index 85469c8..838c17e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuDelegate.java
@@ -23,9 +23,4 @@ * should be using. */ AppMenuPropertiesDelegate createAppMenuPropertiesDelegate(); - - /** - * @return Whether the app menu should be shown. - */ - boolean shouldShowAppMenu(); } \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuHandlerImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuHandlerImpl.java index cdfa8ce..349910e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuHandlerImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuHandlerImpl.java
@@ -31,6 +31,7 @@ import org.chromium.chrome.browser.widget.textbubble.TextBubble; import java.util.ArrayList; +import java.util.List; /** * Object responsible for handling the creation, showing, hiding of the AppMenu and notifying the @@ -42,7 +43,8 @@ private AppMenu mAppMenu; private AppMenuDragHelper mAppMenuDragHelper; private Menu mMenu; - private final ArrayList<AppMenuObserver> mObservers; + private final List<AppMenuBlocker> mBlockers; + private final List<AppMenuObserver> mObservers; private final int mMenuResourceId; private final View mHardwareButtonMenuAnchor; @@ -86,6 +88,7 @@ mAppMenuDelegate = appMenuDelegate; mDelegate = delegate; mDecorView = decorView; + mBlockers = new ArrayList<>(); mObservers = new ArrayList<>(); mMenuResourceId = menuResourceId; mHardwareButtonMenuAnchor = mDecorView.findViewById(R.id.menu_anchor_stub); @@ -163,7 +166,7 @@ // TODO(crbug.com/635567): Fix this properly. @SuppressLint("ResourceType") boolean showAppMenu(View anchorView, boolean startDragging, boolean showFromBottom) { - if (!mAppMenuDelegate.shouldShowAppMenu() || isAppMenuShowing()) return false; + if (!shouldShowAppMenu() || isAppMenuShowing()) return false; TextBubble.dismissBubbles(); boolean isByPermanentButton = false; @@ -343,4 +346,26 @@ void onFooterViewInflated(View view) { if (mDelegate != null) mDelegate.onFooterViewInflated(this, view); } + + /** + * Registers an {@link AppMenuBlocker} used to help determine whether the app menu can be shown. + * @param blocker An {@link AppMenuBlocker} to check before attempting to show the app menu. + */ + void registerAppMenuBlocker(AppMenuBlocker blocker) { + if (!mBlockers.contains(blocker)) mBlockers.add(blocker); + } + + /** + * @param blocker The {@link AppMenuBlocker} to unregister. + */ + void unregisterAppMenuBlocker(AppMenuBlocker blocker) { + mBlockers.remove(blocker); + } + + boolean shouldShowAppMenu() { + for (int i = 0; i < mBlockers.size(); i++) { + if (!mBlockers.get(i).canShowAppMenu()) return false; + } + return true; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/content_capture/ContentCaptureHistoryDeletionObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/content_capture/ContentCaptureHistoryDeletionObserver.java new file mode 100644 index 0000000..ef7e18bd --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/content_capture/ContentCaptureHistoryDeletionObserver.java
@@ -0,0 +1,29 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.content_capture; + +import org.chromium.chrome.browser.history.HistoryDeletionBridge; +import org.chromium.chrome.browser.history.HistoryDeletionInfo; +import org.chromium.components.content_capture.ContentCaptureController; + +/** History deletion observer that calls ContentCapture methods. */ +public class ContentCaptureHistoryDeletionObserver implements HistoryDeletionBridge.Observer { + /** Observer method when a bit of history is deleted. */ + @Override + public void onURLsDeleted(HistoryDeletionInfo historyDeletionInfo) { + ContentCaptureController contentCaptureController = ContentCaptureController.getInstance(); + if (contentCaptureController == null) return; + + if (historyDeletionInfo.isTimeRangeForAllTime() + || (historyDeletionInfo.isTimeRangeValid() + && historyDeletionInfo.getTimeRangeBegin() + != historyDeletionInfo.getTimeRangeEnd())) { + contentCaptureController.clearAllContentCaptureData(); + } else { + contentCaptureController.clearContentCaptureDataForURLs( + historyDeletionInfo.getDeletedURLs()); + } + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/content_capture/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/content_capture/OWNERS new file mode 100644 index 0000000..2d0a24b --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/content_capture/OWNERS
@@ -0,0 +1,4 @@ +tedchoc@chromium.org +wylieb@chomium.org + +file://components/content_capture/OWNERS
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java index d09918b..bb99ba7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -704,10 +704,10 @@ } @Override - public boolean shouldShowAppMenu() { + public boolean canShowAppMenu() { if (getActivityTab() == null || !getToolbarManager().isInitialized()) return false; - return super.shouldShowAppMenu(); + return super.canShowAppMenu(); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/ArrowChipView.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/ArrowChipView.java deleted file mode 100644 index d38eb98..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/ArrowChipView.java +++ /dev/null
@@ -1,74 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.gesturenav; - -import android.content.Context; -import android.support.annotation.StyleRes; -import android.view.View; -import android.view.animation.Animation.AnimationListener; - -import org.chromium.chrome.R; -import org.chromium.ui.widget.ChipView; - -/** - * A widget for arrow and an optional 'close chrome' indicator used for overscroll navigation. - * TODO(jinsukkim): Implement this using a custom view. - */ -public final class ArrowChipView extends ChipView { - private AnimationListener mListener; - - public ArrowChipView(Context context, @StyleRes int style) { - super(context, style); - getPrimaryTextView().setText(context.getResources().getString( - R.string.overscroll_navigation_close_chrome, context.getString(R.string.app_name))); - getPrimaryTextView().setVisibility(View.GONE); - } - - /** - * Sets {@link AnimationListener} used when the widget disappears at the end of - * user gesture. - * @param listener Listener object. - */ - public void setAnimationListener(AnimationListener listener) { - mListener = listener; - } - - /** - * @return {@code true} if the widget is showing the close chrome indicator text. - */ - public boolean isShowingCaption() { - return getPrimaryTextView().getVisibility() == View.VISIBLE; - } - - /** - * Shows or hides the close chrome indicator. - * @param on {@code true} if the indicator should appear. - */ - public void showCaption(boolean on) { - if (on && !isShowingCaption()) { - getPrimaryTextView().setVisibility(View.VISIBLE); - // Measure the width again after the indicator text becomes visible. - measure(0, 0); - } else if (!on && isShowingCaption()) { - getPrimaryTextView().setVisibility(View.GONE); - } - } - - @Override - public void onAnimationStart() { - super.onAnimationStart(); - if (mListener != null) { - mListener.onAnimationStart(getAnimation()); - } - } - - @Override - public void onAnimationEnd() { - super.onAnimationEnd(); - if (mListener != null) { - mListener.onAnimationEnd(getAnimation()); - } - } -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationBubble.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationBubble.java new file mode 100644 index 0000000..3f36639 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationBubble.java
@@ -0,0 +1,128 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +package org.chromium.chrome.browser.gesturenav; + +import android.content.Context; +import android.support.annotation.DrawableRes; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.Animation.AnimationListener; +import android.widget.LinearLayout; +import android.widget.TextView; + +import org.chromium.base.ApiCompatibilityUtils; +import org.chromium.chrome.R; +import org.chromium.ui.widget.ChromeImageView; +import org.chromium.ui.widget.RippleBackgroundHelper; + +/** + * View class for a bubble used in gesture navigation UI that consists of an icon + * and an optional text. + */ +public class NavigationBubble extends LinearLayout { + private final RippleBackgroundHelper mRippleBackgroundHelper; + + private ChromeImageView mIcon; + private TextView mText; + private AnimationListener mListener; + + /** + * Constructor for inflating from XML. + */ + public NavigationBubble(Context context) { + this(context, null); + } + + public NavigationBubble(Context context, AttributeSet attrs) { + super(context, attrs); + + // Reset icon and background. Height is used as corner radius to ensure we have a circle. + mRippleBackgroundHelper = new RippleBackgroundHelper(this, + R.color.navigation_bubble_background_color, R.color.navigation_bubble_ripple_color, + getResources().getDimensionPixelSize(R.dimen.navigation_bubble_default_height), + R.color.navigation_bubble_stroke_color, R.dimen.navigation_bubble_border_width); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + mIcon = findViewById(R.id.navigation_bubble_icon); + mText = findViewById(R.id.navigation_bubble_text); + } + + /** + * Sets {@link AnimationListener} used when the widget disappears at the end of + * user gesture. + * @param listener Listener object. + */ + public void setAnimationListener(AnimationListener listener) { + mListener = listener; + } + + /** + * @return {@code true} if the widget is showing the close chrome indicator text. + */ + public boolean isShowingCaption() { + return getTextView().getVisibility() == View.VISIBLE; + } + + /** + * Shows or hides the close chrome indicator. + * @param on {@code true} if the indicator should appear. + */ + public void showCaption(boolean on) { + if (on && !isShowingCaption()) { + getTextView().setVisibility(View.VISIBLE); + // Measure the width again after the indicator text becomes visible. + measure(0, 0); + } else if (!on && isShowingCaption()) { + getTextView().setVisibility(View.GONE); + } + } + + @Override + public void onAnimationStart() { + super.onAnimationStart(); + if (mListener != null) { + mListener.onAnimationStart(getAnimation()); + } + } + + @Override + public void onAnimationEnd() { + super.onAnimationEnd(); + if (mListener != null) { + mListener.onAnimationEnd(getAnimation()); + } + } + + @Override + protected void drawableStateChanged() { + super.drawableStateChanged(); + if (mRippleBackgroundHelper != null) { + mRippleBackgroundHelper.onDrawableStateChanged(); + } + } + + /** + * Sets the icon at the start of the icon view. + * @param icon The resource id pointing to the icon. + */ + public void setIcon(@DrawableRes int icon) { + mIcon.setVisibility(ViewGroup.VISIBLE); + mIcon.setImageResource(icon); + + // Sets the correct tinting on the icon. + ApiCompatibilityUtils.setImageTintList(mIcon, mText.getTextColors()); + } + + /** + * Returns the {@link TextView} that contains the label of the widget. + * @return A {@link TextView}. + */ + public TextView getTextView() { + return mText; + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/SideSlideLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/SideSlideLayout.java index 5029bc55..a1f71f5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/SideSlideLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/SideSlideLayout.java
@@ -6,6 +6,7 @@ import android.content.Context; import android.support.annotation.IntDef; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.animation.AlphaAnimation; @@ -99,7 +100,7 @@ // True while side gesture is in progress. private boolean mIsBeingDragged; - private ArrowChipView mArrowView; + private NavigationBubble mArrowView; private int mArrowViewWidth; // Start position for animation moving the UI back to original offset. @@ -158,7 +159,11 @@ final float density = getResources().getDisplayMetrics().density; mCircleWidth = (int) (CIRCLE_DIAMETER_DP * density); - mArrowView = new ArrowChipView(getContext(), R.style.AssistiveChip); + LayoutInflater layoutInflater = LayoutInflater.from(getContext()); + mArrowView = (NavigationBubble) layoutInflater.inflate(R.layout.navigation_bubble, null); + mArrowView.getTextView().setText( + getResources().getString(R.string.overscroll_navigation_close_chrome, + getContext().getString(R.string.app_name))); mArrowViewWidth = mCircleWidth; addView(mArrowView); @@ -226,8 +231,7 @@ public void setDirection(boolean forward) { mIsForward = forward; mArrowView.setIcon( - forward ? R.drawable.ic_arrow_forward_blue_24dp : R.drawable.ic_arrow_back_24dp, - true); + forward ? R.drawable.ic_arrow_forward_blue_24dp : R.drawable.ic_arrow_back_24dp); } public void setEnableCloseIndicator(boolean enable) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java index 1d56f507..6d7b883 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java
@@ -44,11 +44,13 @@ import org.chromium.chrome.browser.banners.AppBannerManager; import org.chromium.chrome.browser.bookmarkswidget.BookmarkWidgetProvider; import org.chromium.chrome.browser.contacts_picker.ContactsPickerDialog; +import org.chromium.chrome.browser.content_capture.ContentCaptureHistoryDeletionObserver; import org.chromium.chrome.browser.crash.LogcatExtractionRunnable; import org.chromium.chrome.browser.crash.MinidumpUploadService; import org.chromium.chrome.browser.download.DownloadController; import org.chromium.chrome.browser.download.DownloadManagerService; import org.chromium.chrome.browser.firstrun.ForcedSigninProcessor; +import org.chromium.chrome.browser.history.HistoryDeletionBridge; import org.chromium.chrome.browser.identity.UniqueIdentificationGeneratorFactory; import org.chromium.chrome.browser.identity.UuidBasedUniqueIdentificationGenerator; import org.chromium.chrome.browser.incognito.IncognitoTabLauncher; @@ -265,6 +267,8 @@ }); SearchWidgetProvider.initialize(); + HistoryDeletionBridge.getInstance().addObserver( + new ContentCaptureHistoryDeletionObserver()); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tasks/tabgroup/TabGroupModelFilter.java b/chrome/android/java/src/org/chromium/chrome/browser/tasks/tabgroup/TabGroupModelFilter.java index a31b9f5..bec2314 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tasks/tabgroup/TabGroupModelFilter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tasks/tabgroup/TabGroupModelFilter.java
@@ -9,6 +9,7 @@ import android.support.annotation.NonNull; import org.chromium.base.ContextUtils; +import org.chromium.base.ObserverList; import org.chromium.base.ThreadUtils; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordUserAction; @@ -43,6 +44,29 @@ private static SharedPreferences sPref; /** + * An interface to be notified about changes to a {@link TabGroupModelFilter}. + */ + public interface Observer { + /** + * This method is called after a group is moved. + * + * @param movedTab The tab which has been moved. This is the last tab within the group. + * @param tabModelOldIndex The old index of the {@code movedTab} in the {@link TabModel}. + * @param tabModelNewIndex The new index of the {@code movedTab} in the {@link TabModel}. + */ + void didMoveTabGroup(Tab movedTab, int tabModelOldIndex, int tabModelNewIndex); + + /** + * This method is called after a tab within a group is moved. + * + * @param movedTab The tab which has been moved. + * @param tabModelOldIndex The old index of the {@code movedTab} in the {@link TabModel}. + * @param tabModelNewIndex The new index of the {@code movedTab} in the {@link TabModel}. + */ + void didMoveWithinGroup(Tab movedTab, int tabModelOldIndex, int tabModelNewIndex); + } + + /** * This class is a representation of a group of tabs. It knows the last selected tab within the * group. */ @@ -108,6 +132,7 @@ return ids.get(position - 1); } } + private ObserverList<Observer> mGroupFilterObserver = new ObserverList<>(); private Map<Integer, Integer> mGroupIdToGroupIndexMap = new HashMap<>(); private Map<Integer, TabGroup> mGroupIdToGroupMap = new HashMap<>(); private int mCurrentGroupIndex = TabList.INVALID_TAB_INDEX; @@ -132,6 +157,22 @@ } /** + * This method adds a {@link Observer} to be notified on {@link TabGroupModelFilter} changes. + * @param observer The {@link Observer} to add. + */ + public void addTabGroupObserver(Observer observer) { + mGroupFilterObserver.addObserver(observer); + } + + /** + * This method removes a {@link Observer}. + * @param observer The {@link Observer} to remove. + */ + public void removeTabGroupObserver(Observer observer) { + mGroupFilterObserver.removeObserver(observer); + } + + /** * @return Number of {@link TabGroup}s that has at least two tabs. */ public int getTabGroupCount() { @@ -340,6 +381,38 @@ return mAbsentSelectedTab == null; } + @Override + public void didMoveTab(Tab tab, int newIndex, int curIndex) { + super.didMoveTab(tab, newIndex, curIndex); + + if (isMoveWithinGroup(tab, curIndex, newIndex)) { + for (Observer observer : mGroupFilterObserver) { + observer.didMoveWithinGroup(tab, curIndex, newIndex); + } + } else { + if (!hasFinishedMovingGroup(tab, newIndex)) return; + for (Observer observer : mGroupFilterObserver) { + observer.didMoveTabGroup(tab, curIndex, newIndex); + } + } + } + + private boolean isMoveWithinGroup( + Tab movedTab, int oldIndexInTabModel, int newIndexInTabModel) { + int startIndex = Math.min(oldIndexInTabModel, newIndexInTabModel); + int endIndex = Math.max(oldIndexInTabModel, newIndexInTabModel); + for (int i = startIndex; i <= endIndex; i++) { + if (getTabModel().getTabAt(i).getRootId() != movedTab.getRootId()) return false; + } + return true; + } + + private boolean hasFinishedMovingGroup(Tab movedTab, int newIndexInTabModel) { + TabGroup tabGroup = mGroupIdToGroupMap.get(movedTab.getRootId()); + int offsetIndex = Math.abs(newIndexInTabModel - tabGroup.size() + 1); + return tabGroup.contains(getTabModel().getTabAt(offsetIndex).getId()); + } + // TabList implementation. @Override public boolean isIncognito() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java index 00b0e0cd..91d0c53 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
@@ -1803,7 +1803,7 @@ if (inTabSwitcherMode) { if (mUrlFocusLayoutAnimator != null && mUrlFocusLayoutAnimator.isRunning()) { - mUrlFocusLayoutAnimator.end(); + mUrlFocusLayoutAnimator.cancel(); mUrlFocusLayoutAnimator = null; // After finishing the animation, force a re-layout of the location bar, // so that the final translation position is correct (since onMeasure updates @@ -2106,7 +2106,7 @@ private void triggerUrlFocusAnimation(final boolean hasFocus) { if (mUrlFocusLayoutAnimator != null && mUrlFocusLayoutAnimator.isRunning()) { - mUrlFocusLayoutAnimator.end(); + mUrlFocusLayoutAnimator.cancel(); mUrlFocusLayoutAnimator = null; } if (mExperimentalButtonAnimationRunning) mExperimentalButtonAnimator.end();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java index 2b23ced..a83dcc9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
@@ -9,10 +9,12 @@ import org.chromium.base.VisibleForTesting; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeActivity; +import org.chromium.chrome.browser.appmenu.AppMenuBlocker; import org.chromium.chrome.browser.appmenu.AppMenuCoordinator; import org.chromium.chrome.browser.appmenu.AppMenuCoordinatorFactory; import org.chromium.chrome.browser.lifecycle.Destroyable; import org.chromium.chrome.browser.lifecycle.InflationObserver; +import org.chromium.ui.base.DeviceFormFactor; /** * The root UI coordinator. This class will eventually be responsible for inflating and managing @@ -21,8 +23,9 @@ * The specific things this component will manage and how it will hook into Chrome*Activity are * still being discussed See https://crbug.com/931496. */ -public class RootUiCoordinator - implements Destroyable, InflationObserver, ChromeActivity.MenuOrKeyboardActionHandler { +public class RootUiCoordinator implements Destroyable, InflationObserver, + ChromeActivity.MenuOrKeyboardActionHandler, + AppMenuBlocker { protected ChromeActivity mActivity; protected @Nullable AppMenuCoordinator mAppMenuCoordinator; @@ -41,7 +44,11 @@ public void destroy() { mActivity.unregisterMenuOrKeyboardActionHandler(this); mActivity = null; - if (mAppMenuCoordinator != null) mAppMenuCoordinator.destroy(); + if (mAppMenuCoordinator != null) { + mAppMenuCoordinator.unregisterAppMenuBlocker(this); + mAppMenuCoordinator.unregisterAppMenuBlocker(mActivity); + mAppMenuCoordinator.destroy(); + } } @Override @@ -59,6 +66,8 @@ mActivity.getToolbarManager().onAppMenuInitialized( mAppMenuCoordinator.getAppMenuHandler(), mAppMenuCoordinator.getAppMenuPropertiesDelegate()); + mAppMenuCoordinator.registerAppMenuBlocker(this); + mAppMenuCoordinator.registerAppMenuBlocker(mActivity); } else if (mActivity.getToolbarManager() != null) { mActivity.getToolbarManager().getToolbar().disableMenuButton(); } @@ -78,4 +87,30 @@ public AppMenuCoordinator getAppMenuCoordinatorForTesting() { return mAppMenuCoordinator; } + + @Override + public boolean canShowAppMenu() { + // TODO(https:crbug.com/931496): Eventually the ContextualSearchManager, EphemeralTabPanel, + // and FindToolbarManager will all be owned by this class. + + // Do not show the menu if Contextual Search panel is opened. + if (mActivity.getContextualSearchManager() != null + && mActivity.getContextualSearchManager().isSearchPanelOpened()) { + return false; + } + + if (mActivity.getEphemeralTabPanel() != null + && mActivity.getEphemeralTabPanel().isPanelOpened()) { + return false; + } + + // Do not show the menu if we are in find in page view. + if (mActivity.getFindToolbarManager() != null + && mActivity.getFindToolbarManager().isShowing() + && !DeviceFormFactor.isNonMultiDisplayContextOnTablet(mActivity)) { + return false; + } + + return true; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/usage_stats/SuspendedTab.java b/chrome/android/java/src/org/chromium/chrome/browser/usage_stats/SuspendedTab.java index 8becdfde..2ad329f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/usage_stats/SuspendedTab.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/usage_stats/SuspendedTab.java
@@ -20,6 +20,7 @@ import org.chromium.base.UserData; import org.chromium.base.VisibleForTesting; import org.chromium.chrome.R; +import org.chromium.chrome.browser.infobar.InfoBarContainer; import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; import org.chromium.content_public.browser.WebContents; @@ -71,6 +72,11 @@ webContents.onHide(); } + InfoBarContainer infoBarContainer = InfoBarContainer.get(mTab); + if (infoBarContainer != null) { + infoBarContainer.setHidden(true); + } + if (isViewAttached()) { updateFqdnText(); } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java index e719ec14..7ab5512 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java
@@ -17,6 +17,7 @@ import android.os.Bundle; import android.support.annotation.IntDef; import android.text.TextUtils; +import android.util.Pair; import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ContextUtils; @@ -38,6 +39,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; /** @@ -62,28 +64,39 @@ private static final int PARAM_TEXT_INDEX = 2; private static final int PARAM_URL_INDEX = 3; private String[] mData; + private boolean mIsShareMethodPost; + private boolean mIsShareEncTypeMultipart; + private String[] mFileNames; + private String[][] mFileAccepts; public ShareTarget() { - this(null, null, null, null); + this(null, null, null, null, false, false, null, null); } - public ShareTarget(String action, String paramTitle, String paramText, String paramUrl) { + public ShareTarget(String action, String paramTitle, String paramText, String paramUrl, + boolean isMethodPost, boolean isEncTypeMultipart, String[] fileNames, + String[][] fileAccepts) { mData = new String[4]; mData[ACTION_INDEX] = replaceNullWithEmpty(action); mData[PARAM_TITLE_INDEX] = replaceNullWithEmpty(paramTitle); mData[PARAM_TEXT_INDEX] = replaceNullWithEmpty(paramText); mData[PARAM_URL_INDEX] = replaceNullWithEmpty(paramUrl); + mIsShareMethodPost = isMethodPost; + mIsShareEncTypeMultipart = isEncTypeMultipart; + + mFileNames = fileNames != null ? fileNames : new String[0]; + mFileAccepts = fileAccepts != null ? fileAccepts : new String[0][]; } @Override public boolean equals(Object o) { if (!(o instanceof ShareTarget)) return false; - return Arrays.equals(mData, ((ShareTarget) o).mData); - } - - @Override - public int hashCode() { - return Arrays.hashCode(mData); + ShareTarget shareTarget = (ShareTarget) o; + return Arrays.equals(mData, shareTarget.mData) + && mIsShareMethodPost == shareTarget.mIsShareMethodPost + && mIsShareEncTypeMultipart == shareTarget.mIsShareEncTypeMultipart + && Arrays.equals(mFileNames, shareTarget.mFileNames) + && Arrays.deepEquals(mFileAccepts, shareTarget.mFileAccepts); } public String getAction() { @@ -101,6 +114,22 @@ public String getParamUrl() { return mData[PARAM_URL_INDEX]; } + + public boolean isShareMethodPost() { + return mIsShareMethodPost; + } + + public boolean isShareEncTypeMultipart() { + return mIsShareEncTypeMultipart; + } + + public String[] getFileNames() { + return mFileNames; + } + + public String[][] getFileAccepts() { + return mFileAccepts; + } } public static final String RESOURCE_NAME = "name"; @@ -125,6 +154,7 @@ private String mManifestStartUrl; private @WebApkDistributor int mDistributor; private ShareTarget mShareTarget; + private String mShareTargetActivityName; private Map<String, String> mIconUrlToMurmur2HashMap; private boolean mIsSplashProvidedByWebApk; @@ -292,7 +322,11 @@ int splashIconId = IntentUtils.safeGetInt(bundle, WebApkMetaDataKeys.SPLASH_ID, 0); Bitmap splashIcon = decodeBitmapFromDrawable(res, splashIconId); - ShareTarget shareTarget = extractAndMergeShareTargets(webApkPackageName); + + Pair<String, ShareTarget> shareTargetActivityNameAndData = + extractFirstShareTarget(webApkPackageName); + String shareTargetActivityName = shareTargetActivityNameAndData.first; + ShareTarget shareTarget = shareTargetActivityNameAndData.second; boolean isSplashProvidedByWebApk = (canUseSplashFromContentProvider && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N @@ -302,13 +336,12 @@ new Icon(primaryIcon), new Icon(badgeIcon), new Icon(splashIcon), name, shortName, displayMode, orientation, source, themeColor, backgroundColor, webApkPackageName, shellApkVersion, manifestUrl, manifestStartUrl, distributor, - iconUrlToMurmur2HashMap, shareTarget, forceNavigation, isSplashProvidedByWebApk, - shareData); + iconUrlToMurmur2HashMap, shareTarget, shareTargetActivityName, forceNavigation, + isSplashProvidedByWebApk, shareData); } /** * Construct a {@link WebApkInfo} instance. - * * @param id ID for the WebAPK. * @param url URL that the WebAPK should navigate to when launched. * @param scope Scope for the WebAPK. @@ -331,7 +364,9 @@ * @param distributor The source from where the WebAPK is installed. * @param iconUrlToMurmur2HashMap Map of the WebAPK's icon URLs to Murmur2 hashes of the * icon untransformed bytes. - * @param shareTarget Data about WebAPK's share intent handlers. + * @param shareTarget shareTarget data for {@link shareTargetActivityName} + * @param shareTargetActivityName Name of activity or activity alias in WebAPK which handles + * share intents * @param forceNavigation Whether the WebAPK should navigate to {@link url} if the * WebAPK is already open. * @param isSplashProvidedByWebApk Whether the WebAPK (1) launches an internal activity to @@ -345,7 +380,8 @@ long backgroundColor, String webApkPackageName, int shellApkVersion, String manifestUrl, String manifestStartUrl, @WebApkDistributor int distributor, Map<String, String> iconUrlToMurmur2HashMap, ShareTarget shareTarget, - boolean forceNavigation, boolean isSplashProvidedByWebApk, ShareData shareData) { + String shareTargetActivityName, boolean forceNavigation, + boolean isSplashProvidedByWebApk, ShareData shareData) { if (id == null || url == null || manifestStartUrl == null || webApkPackageName == null) { Log.e(TAG, "Incomplete data provided: " + id + ", " + url + ", " + manifestStartUrl + ", " @@ -363,8 +399,8 @@ return new WebApkInfo(id, url, scope, primaryIcon, badgeIcon, splashIcon, name, shortName, displayMode, orientation, source, themeColor, backgroundColor, webApkPackageName, shellApkVersion, manifestUrl, manifestStartUrl, distributor, - iconUrlToMurmur2HashMap, shareTarget, forceNavigation, isSplashProvidedByWebApk, - shareData); + iconUrlToMurmur2HashMap, shareTarget, shareTargetActivityName, forceNavigation, + isSplashProvidedByWebApk, shareData); } protected WebApkInfo(String id, String url, String scope, Icon primaryIcon, Icon badgeIcon, @@ -373,7 +409,8 @@ String webApkPackageName, int shellApkVersion, String manifestUrl, String manifestStartUrl, @WebApkDistributor int distributor, Map<String, String> iconUrlToMurmur2HashMap, ShareTarget shareTarget, - boolean forceNavigation, boolean isSplashProvidedByWebApk, ShareData shareData) { + String shareTargetActivityName, boolean forceNavigation, + boolean isSplashProvidedByWebApk, ShareData shareData) { super(id, url, scope, primaryIcon, name, shortName, displayMode, orientation, source, themeColor, backgroundColor, null /* splash_screen_url */, false /* isIconGenerated */, false /* isIconAdaptive */, forceNavigation); @@ -387,11 +424,11 @@ mIconUrlToMurmur2HashMap = iconUrlToMurmur2HashMap; mIsSplashProvidedByWebApk = isSplashProvidedByWebApk; mShareData = shareData; - mShareTarget = shareTarget; if (mShareTarget == null) { mShareTarget = new ShareTarget(); } + mShareTargetActivityName = shareTargetActivityName; } protected WebApkInfo() {} @@ -415,6 +452,13 @@ return mShareTarget; } + /** + * Returns name of activity or activity alias in WebAPK which handles share intents. + */ + public String shareTargetActivityName() { + return mShareTargetActivityName; + } + @Override public boolean isForWebApk() { return true; @@ -580,8 +624,11 @@ } } - /** Returns data about the share intent handlers for the given WebAPK. */ - private static ShareTarget extractAndMergeShareTargets(String webApkPackageName) { + /** + * Returns the name of activity or activity alias in WebAPK which handles share intents, and + * the data about the handler. + */ + private static Pair<String, ShareTarget> extractFirstShareTarget(String webApkPackageName) { Intent shareIntent = new Intent(); shareIntent.setAction(Intent.ACTION_SEND); shareIntent.setPackage(webApkPackageName); @@ -596,16 +643,45 @@ continue; } - return new ShareTarget( + String shareTargetActivityName = resolveInfo.activityInfo.name; + + String shareAction = + IntentUtils.safeGetString(shareTargetMetaData, WebApkMetaDataKeys.SHARE_ACTION); + if (TextUtils.isEmpty(shareAction)) { + return new Pair<>(null, new ShareTarget()); + } + + String encodedFileNames = IntentUtils.safeGetString( + shareTargetMetaData, WebApkMetaDataKeys.SHARE_PARAM_NAMES); + String[] fileNames = WebApkShareTargetUtil.decodeJsonStringArray(encodedFileNames); + + String encodedFileAccepts = IntentUtils.safeGetString( + shareTargetMetaData, WebApkMetaDataKeys.SHARE_PARAM_ACCEPTS); + String[][] fileAccepts = WebApkShareTargetUtil.decodeJsonAccepts(encodedFileAccepts); + + String shareMethod = + IntentUtils.safeGetString(shareTargetMetaData, WebApkMetaDataKeys.SHARE_METHOD); + boolean isShareMethodPost = + shareMethod != null && shareMethod.toUpperCase(Locale.ENGLISH).equals("POST"); + + String shareEncType = IntentUtils.safeGetString( + shareTargetMetaData, WebApkMetaDataKeys.SHARE_ENCTYPE); + boolean isShareEncTypeMultipart = shareEncType != null + && shareEncType.toLowerCase(Locale.ENGLISH).equals("multipart/form-data"); + + ShareTarget target = new ShareTarget( IntentUtils.safeGetString(shareTargetMetaData, WebApkMetaDataKeys.SHARE_ACTION), IntentUtils.safeGetString( shareTargetMetaData, WebApkMetaDataKeys.SHARE_PARAM_TITLE), IntentUtils.safeGetString( shareTargetMetaData, WebApkMetaDataKeys.SHARE_PARAM_TEXT), IntentUtils.safeGetString( - shareTargetMetaData, WebApkMetaDataKeys.SHARE_PARAM_URL)); + shareTargetMetaData, WebApkMetaDataKeys.SHARE_PARAM_URL), + isShareMethodPost, isShareEncTypeMultipart, fileNames, fileAccepts); + + return new Pair<>(shareTargetActivityName, target); } - return null; + return new Pair<>(null, new ShareTarget()); } /** Returns the value if it is non-null. Returns an empty string otherwise. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkPostShareTargetNavigator.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkPostShareTargetNavigator.java index 4923cff..e577ec7f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkPostShareTargetNavigator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkPostShareTargetNavigator.java
@@ -12,8 +12,9 @@ public class WebApkPostShareTargetNavigator { public static boolean navigateIfPostShareTarget( WebApkInfo webApkInfo, WebContents webContents) { - WebApkShareTargetUtil.PostData postData = WebApkShareTargetUtil.computePostData( - webApkInfo.webApkPackageName(), webApkInfo.shareData()); + WebApkShareTargetUtil.PostData postData = + WebApkShareTargetUtil.computePostData(webApkInfo.shareTargetActivityName(), + webApkInfo.shareTarget(), webApkInfo.shareData()); if (postData == null) { return false; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkShareTargetUtil.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkShareTargetUtil.java index e8bad23..21983f8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkShareTargetUtil.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkShareTargetUtil.java
@@ -4,13 +4,11 @@ package org.chromium.chrome.browser.webapps; -import android.content.ComponentName; -import android.content.pm.ActivityInfo; -import android.content.pm.PackageManager; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.provider.OpenableColumns; +import android.text.TextUtils; import org.json.JSONArray; import org.json.JSONException; @@ -26,13 +24,15 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; -import java.util.List; +import java.util.Arrays; import java.util.Locale; /** * Computes data for Post Share Target. */ public class WebApkShareTargetUtil { + private static final String TAG = "WebApkShareTargetUtil"; + // A class containing data required to generate a share target post request. protected static class PostData { public boolean isMultipartEncoding; @@ -57,32 +57,6 @@ } } - private static Bundle computeShareTargetMetaData( - String apkPackageName, WebApkInfo.ShareData shareData) { - if (shareData == null) { - return null; - } - ActivityInfo shareActivityInfo; - try { - shareActivityInfo = - ContextUtils.getApplicationContext().getPackageManager().getActivityInfo( - new ComponentName(apkPackageName, shareData.shareActivityClassName), - PackageManager.GET_META_DATA); - } catch (PackageManager.NameNotFoundException e) { - return null; - } - - if (shareActivityInfo == null) { - return null; - } - return shareActivityInfo.metaData; - } - - private static boolean enctypeFromMetaDataIsMultipart(Bundle metaData) { - String enctype = IntentUtils.safeGetString(metaData, WebApkMetaDataKeys.SHARE_ENCTYPE); - return enctype != null && "multipart/form-data".equals(enctype.toLowerCase(Locale.ENGLISH)); - } - private static byte[] readStringFromContentUri(Uri uri) { try (InputStream inputStream = ContextUtils.getApplicationContext().getContentResolver().openInputStream( @@ -114,23 +88,42 @@ return uri.getPath(); } - private static ArrayList<String> decodeJsonStringArray(JSONArray jsonArray) - throws JSONException { - ArrayList<String> originalData = new ArrayList<>(); - for (int i = 0; i < jsonArray.length(); i++) { - originalData.add(jsonArray.getString(i)); + public static String[] decodeJsonStringArray(String encodedJsonArray) { + if (encodedJsonArray == null) { + return null; } - return originalData; + + try { + JSONArray jsonArray = new JSONArray(encodedJsonArray); + String[] originalData = new String[jsonArray.length()]; + for (int i = 0; i < jsonArray.length(); i++) { + originalData[i] = jsonArray.getString(i); + } + return originalData; + } catch (JSONException e) { + } + return null; } - private static ArrayList<ArrayList<String>> decodeJsonAccepts(String string) - throws JSONException { - JSONArray jsonArray = new JSONArray(string); - ArrayList<ArrayList<String>> originalData = new ArrayList<>(); - for (int i = 0; i < jsonArray.length(); i++) { - originalData.add(decodeJsonStringArray(jsonArray.getJSONArray(i))); + public static String[][] decodeJsonAccepts(String encodedAcceptsArray) { + if (encodedAcceptsArray == null) { + return null; } - return originalData; + try { + JSONArray jsonArray = new JSONArray(encodedAcceptsArray); + String[][] originalData = new String[jsonArray.length()][]; + for (int i = 0; i < jsonArray.length(); i++) { + String[] childArr = new String[jsonArray.getJSONArray(i).length()]; + for (int j = 0; j < childArr.length; j++) { + childArr[j] = jsonArray.getJSONArray(i).getString(j); + } + originalData[i] = childArr; + } + return originalData; + } catch (JSONException e) { + } + + return null; } protected static boolean methodFromShareTargetMetaDataIsPost(Bundle metaData) { @@ -138,22 +131,13 @@ return method != null && "POST".equals(method.toUpperCase(Locale.ENGLISH)); } - protected static void addFilesToMultipartPostData(PostData postData, String encodedFileNames, - String encodedFileAccepts, ArrayList<Uri> shareFiles) { - if (encodedFileNames == null || encodedFileAccepts == null || shareFiles == null) { + protected static void addFilesToMultipartPostData(PostData postData, String[] fileNames, + String[][] fileAccepts, ArrayList<Uri> shareFiles) { + if (fileNames == null || fileAccepts == null || shareFiles == null) { return; } - ArrayList<String> names; - ArrayList<ArrayList<String>> accepts; - try { - names = decodeJsonStringArray(new JSONArray(encodedFileNames)); - accepts = decodeJsonAccepts(encodedFileAccepts); - } catch (JSONException e) { - return; - } - - if (names.size() != accepts.size()) { + if (fileNames.length != fileAccepts.length) { return; } @@ -166,13 +150,14 @@ continue; } - for (int i = 0; i < names.size(); i++) { - List<String> mimeTypeList = accepts.get(i); - MimeTypeFilter mimeTypeFilter = new MimeTypeFilter(mimeTypeList, false); + for (int i = 0; i < fileNames.length; i++) { + String[] mimeTypeList = fileAccepts[i]; + MimeTypeFilter mimeTypeFilter = + new MimeTypeFilter(Arrays.asList(mimeTypeList), false); if (mimeTypeFilter.accept(fileUri, fileType)) { byte[] fileContent = readStringFromContentUri(fileUri); if (fileContent != null) { - postData.add(names.get(i), fileContent, fileName, fileType); + postData.add(fileNames[i], fileContent, fileName, fileType); } break; } @@ -181,40 +166,31 @@ } } - protected static PostData computePostData( - String apkPackageName, WebApkInfo.ShareData shareData) { - Bundle shareTargetMetaData = computeShareTargetMetaData(apkPackageName, shareData); - if (shareTargetMetaData == null - || !methodFromShareTargetMetaDataIsPost(shareTargetMetaData)) { + protected static PostData computePostData(String shareTargetActivityName, + WebApkInfo.ShareTarget shareTarget, WebApkInfo.ShareData shareData) { + if (shareTarget == null || !shareTarget.isShareMethodPost() || shareData == null + || !shareData.shareActivityClassName.equals(shareTargetActivityName)) { return null; } - PostData postData = new PostData(enctypeFromMetaDataIsMultipart(shareTargetMetaData)); + PostData postData = new PostData(shareTarget.isShareEncTypeMultipart()); - String shareTitleName = IntentUtils.safeGetString( - shareTargetMetaData, WebApkMetaDataKeys.SHARE_PARAM_TITLE); - if (shareTitleName != null && shareData.subject != null) { - postData.add(shareTitleName, ApiCompatibilityUtils.getBytesUtf8(shareData.subject), "", - "text/plain"); + if (!TextUtils.isEmpty(shareTarget.getParamTitle()) && shareData.subject != null) { + postData.add(shareTarget.getParamTitle(), + ApiCompatibilityUtils.getBytesUtf8(shareData.subject), "", "text/plain"); } - String shareTextName = - IntentUtils.safeGetString(shareTargetMetaData, WebApkMetaDataKeys.SHARE_PARAM_TEXT); - if (shareTextName != null && shareData.text != null) { - postData.add(shareTextName, ApiCompatibilityUtils.getBytesUtf8(shareData.text), "", - "text/plain"); + if (!TextUtils.isEmpty(shareTarget.getParamText()) && shareData.text != null) { + postData.add(shareTarget.getParamText(), + ApiCompatibilityUtils.getBytesUtf8(shareData.text), "", "text/plain"); } if (!postData.isMultipartEncoding) { return postData; } - addFilesToMultipartPostData(postData, - IntentUtils.safeGetString( - shareTargetMetaData, WebApkMetaDataKeys.SHARE_PARAM_NAMES), - IntentUtils.safeGetString( - shareTargetMetaData, WebApkMetaDataKeys.SHARE_PARAM_ACCEPTS), - shareData.files); + addFilesToMultipartPostData(postData, shareTarget.getFileNames(), + shareTarget.getFileAccepts(), shareData.files); return postData; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcher.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcher.java index 75ec95d8..5a87979f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcher.java
@@ -100,7 +100,9 @@ Bitmap primaryIconBitmap, String badgeIconUrl, String badgeIconMurmur2Hash, Bitmap badgeIconBitmap, String[] iconUrls, @WebDisplayMode int displayMode, int orientation, long themeColor, long backgroundColor, String shareAction, - String shareParamsTitle, String shareParamsText, String shareParamsUrl) { + String shareParamsTitle, String shareParamsText, String shareParamsUrl, + boolean isShareMethodPost, boolean isShareEncTypeMultipart, + String[] shareParamsFileNames, String[][] shareParamsAccepts) { HashMap<String, String> iconUrlToMurmur2HashMap = new HashMap<String, String>(); for (String iconUrl : iconUrls) { String murmur2Hash = null; @@ -112,15 +114,19 @@ iconUrlToMurmur2HashMap.put(iconUrl, murmur2Hash); } - WebApkInfo.ShareTarget shareTarget = new WebApkInfo.ShareTarget( - shareAction, shareParamsTitle, shareParamsText, shareParamsUrl); + // When share action is empty, we use a default empty share target + WebApkInfo.ShareTarget shareTarget = TextUtils.isEmpty(shareAction) + ? new WebApkInfo.ShareTarget() + : new WebApkInfo.ShareTarget(shareAction, shareParamsTitle, shareParamsText, + shareParamsUrl, isShareMethodPost, isShareEncTypeMultipart, + shareParamsFileNames, shareParamsAccepts); WebApkInfo info = WebApkInfo.create(mOldInfo.id(), mOldInfo.uri().toString(), scopeUrl, new WebApkInfo.Icon(primaryIconBitmap), new WebApkInfo.Icon(badgeIconBitmap), null, name, shortName, displayMode, orientation, mOldInfo.source(), themeColor, backgroundColor, mOldInfo.webApkPackageName(), mOldInfo.shellApkVersion(), mOldInfo.manifestUrl(), manifestStartUrl, WebApkInfo.WebApkDistributor.BROWSER, - iconUrlToMurmur2HashMap, shareTarget, mOldInfo.shouldForceNavigation(), + iconUrlToMurmur2HashMap, shareTarget, null, mOldInfo.shouldForceNavigation(), mOldInfo.isSplashProvidedByWebApk(), null); mObserver.onGotManifestData(info, primaryIconUrl, badgeIconUrl); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java index b5aeb736..d66d815 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java
@@ -378,8 +378,10 @@ info.displayMode(), info.orientation(), info.themeColor(), info.backgroundColor(), info.shareTarget().getAction(), info.shareTarget().getParamTitle(), info.shareTarget().getParamText(), info.shareTarget().getParamUrl(), - info.manifestUrl(), info.webApkPackageName(), versionCode, isManifestStale, - updateReason, callback); + info.shareTarget().isShareMethodPost(), + info.shareTarget().isShareEncTypeMultipart(), info.shareTarget().getFileNames(), + info.shareTarget().getFileAccepts(), info.manifestUrl(), info.webApkPackageName(), + versionCode, isManifestStale, updateReason, callback); } @NativeMethods @@ -390,7 +392,9 @@ String[] iconHashes, @WebDisplayMode int displayMode, int orientation, long themeColor, long backgroundColor, String shareTargetAction, String shareTargetParamTitle, String shareTargetParamText, - String shareTargetParamUrl, String manifestUrl, String webApkPackage, + String shareTargetParamUrl, boolean shareTargetParamIsMethodPost, + boolean shareTargetParamIsEncTypeMultipart, String[] shareTargetParamFileNames, + Object[] shareTargetParamAccepts, String manifestUrl, String webApkPackage, int webApkVersion, boolean isManifestStale, @WebApkUpdateReason int updateReason, Callback<Boolean> callback); public void updateWebApkFromFile(String updateRequestPath, WebApkUpdateCallback callback);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcherTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcherTest.java index f6a5721..f2c7d63 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcherTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcherTest.java
@@ -105,8 +105,8 @@ WebApkInfo oldInfo = WebApkInfo.create("", "", scopeUrl, null, null, null, null, null, -1, -1, -1, -1, -1, "random.package", -1, manifestUrl, "", WebApkInfo.WebApkDistributor.BROWSER, new HashMap<String, String>(), null, - false /* forceNavigation */, false /* isSplashProvidedByWebApk */, - null /* shareData */); + null /*shareTargetActivityName*/, false /* forceNavigation */, + false /* isSplashProvidedByWebApk */, null /* shareData */); fetcher.start(mTab, oldInfo, observer); }); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java index 4dea71e..a90af0c7 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java
@@ -151,14 +151,17 @@ final TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(waiter, storage); TestThreadUtils.runOnUiThreadBlocking(() -> { - WebApkInfo info = WebApkInfo.create(WEBAPK_ID, "", creationData.scope, null, null, null, - creationData.name, creationData.shortName, creationData.displayMode, - creationData.orientation, 0, creationData.themeColor, - creationData.backgroundColor, "", + WebApkInfo info = WebApkInfo.create( + WEBAPK_ID, "", creationData.scope, null, null, null, creationData.name, + creationData.shortName, creationData.displayMode, creationData.orientation, 0, + creationData.themeColor, creationData.backgroundColor, "", WebApkVersion.REQUEST_UPDATE_FOR_SHELL_APK_VERSION, creationData.manifestUrl, creationData.startUrl, WebApkInfo.WebApkDistributor.BROWSER, - creationData.iconUrlToMurmur2HashMap, null, false /* forceNavigation */, - false /* isSplashProvidedByWebApk */, null /* shareData */); + creationData.iconUrlToMurmur2HashMap, null, null /*shareTargetActivityName*/, + false /* forceNavigation */, false /* isSplashProvidedByWebApk */, + null /* shareData */ + + ); updateManager.updateIfNeeded(mTab, info); }); waiter.waitForCallback(0); @@ -202,4 +205,17 @@ mTestServerRule.getServer(), mTab, WEBAPK_MANIFEST_URL); Assert.assertTrue(checkUpdateNeeded(creationData)); } + + @Test + @MediumTest + @Feature({"WebApk"}) + public void testNoUpdateForPagesWithoutWST() throws Exception { + CreationData creationData = defaultCreationData(); + creationData.startUrl = mTestServerRule.getServer().getURL( + "/chrome/test/data/banners/manifest_test_page.html"); + + WebappTestPage.navigateToServiceWorkerPageWithManifest( + mTestServerRule.getServer(), mTab, WEBAPK_MANIFEST_URL); + Assert.assertFalse(checkUpdateNeeded(creationData)); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappVisibilityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappVisibilityTest.java index 6cb64a8c..0979c1a8 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappVisibilityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappVisibilityTest.java
@@ -132,10 +132,12 @@ ? WebappInfo.create("", webappStartUrlOrScopeUrl, null, null, null, null, displayMode, 0, 0, 0, 0, null, false /* isIconGenerated */, false /* isIconAdaptive */, false /* forceNavigation */) - : WebApkInfo.create("", "", webappStartUrlOrScopeUrl, null, null, null, null, null, - displayMode, 0, 0, 0, 0, "", 0, null, "", - WebApkInfo.WebApkDistributor.BROWSER, null, null, - false /* forceNavigation */, false /* isSplashProvidedByWebApk */, - null /* shareData */); + : WebApkInfo.create( + "", "", webappStartUrlOrScopeUrl, null, null, null, null, null, displayMode, + 0, 0, 0, 0, "", 0, null, "", WebApkInfo.WebApkDistributor.BROWSER, null, + null, null /*shareTargetActivityName*/, false /* forceNavigation */, + false /* isSplashProvidedByWebApk */, null /* shareData */ + + ); } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkShareTargetUtilTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkShareTargetUtilTest.java index cdbc86e..29a96e8 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkShareTargetUtilTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkShareTargetUtilTest.java
@@ -105,21 +105,31 @@ @Test public void testGET() { Bundle shareActivityBundle = new Bundle(); + shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_ACTION, "/share.html"); shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_METHOD, "GET"); shareActivityBundle.putString( WebApkMetaDataKeys.SHARE_ENCTYPE, "application/x-www-form-urlencoded"); registerWebApk(shareActivityBundle); Intent intent = createBasicShareIntent(); - WebApkInfo info = WebApkInfo.create(intent); + WebApkInfo infoWithShareMethodGet = WebApkInfo.create(intent); Assert.assertEquals(null, - WebApkShareTargetUtilShadow.computePostData(WEBAPK_PACKAGE_NAME, info.shareData())); + WebApkShareTargetUtilShadow.computePostData( + WebApkTestHelper.getGeneratedShareTargetActivityClassName(0), + infoWithShareMethodGet.shareTarget(), infoWithShareMethodGet.shareData())); shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_METHOD, "POST"); registerWebApk(shareActivityBundle); + // recreating the WebApkInfo because the shareActivityBundle used for registerWebApk() has + // changed + WebApkInfo infoWithShareMethodPost = WebApkInfo.create(intent); + Assert.assertNotEquals(null, - WebApkShareTargetUtilShadow.computePostData(WEBAPK_PACKAGE_NAME, info.shareData())); + WebApkShareTargetUtilShadow.computePostData( + WebApkTestHelper.getGeneratedShareTargetActivityClassName(0), + infoWithShareMethodPost.shareTarget(), + infoWithShareMethodPost.shareData())); } /** @@ -132,6 +142,8 @@ shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_PARAM_TITLE, "title"); shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_PARAM_TEXT, "text"); shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_METHOD, "POST"); + shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_ACTION, "/share.html"); + shareActivityBundle.putString( WebApkMetaDataKeys.SHARE_ENCTYPE, "application/x-www-form-urlencoded"); registerWebApk(shareActivityBundle); @@ -141,8 +153,9 @@ intent.putExtra(Intent.EXTRA_TEXT, "extra_text"); WebApkInfo info = WebApkInfo.create(intent); - WebApkShareTargetUtilShadow.PostData postData = - WebApkShareTargetUtilShadow.computePostData(WEBAPK_PACKAGE_NAME, info.shareData()); + WebApkShareTargetUtilShadow.PostData postData = WebApkShareTargetUtilShadow.computePostData( + WebApkTestHelper.getGeneratedShareTargetActivityClassName(0), info.shareTarget(), + info.shareData()); assertPostData(postData, new String[] {"title", "text"}, new String[] {"extra_subject", "extra_text"}, new String[] {"", ""}, @@ -150,13 +163,15 @@ } /** - * Test that multipart/form-data with no names/accepts output a null postdata. + * Test that + * multipart/form-data with no names/accepts output a null postdata. */ @Test public void testPostMultipartWithNoNamesNoAccepts() { Bundle shareActivityBundle = new Bundle(); shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_METHOD, "POST"); shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_ENCTYPE, "multipart/form-data"); + shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_ACTION, "/share.html"); // Note that names and accepts are not specified registerWebApk(shareActivityBundle); @@ -167,8 +182,9 @@ WebApkInfo info = WebApkInfo.create(intent); - WebApkShareTargetUtilShadow.PostData postData = - WebApkShareTargetUtilShadow.computePostData(WEBAPK_PACKAGE_NAME, info.shareData()); + WebApkShareTargetUtilShadow.PostData postData = WebApkShareTargetUtilShadow.computePostData( + WebApkTestHelper.getGeneratedShareTargetActivityClassName(0), info.shareTarget(), + info.shareData()); assertPostData( postData, new String[] {}, new String[] {}, new String[] {}, new String[] {}); @@ -185,14 +201,16 @@ shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_ENCTYPE, "multipart/form-data"); shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_PARAM_NAMES, "[\"name\"]"); shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_PARAM_ACCEPTS, "[[\"image/*\"]]"); + shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_ACTION, "/share.html"); registerWebApk(shareActivityBundle); Intent intent = createBasicShareIntent(); // Intent.EXTRA_STREAM is not specified. WebApkInfo info = WebApkInfo.create(intent); - WebApkShareTargetUtilShadow.PostData postData = - WebApkShareTargetUtilShadow.computePostData(WEBAPK_PACKAGE_NAME, info.shareData()); + WebApkShareTargetUtilShadow.PostData postData = WebApkShareTargetUtilShadow.computePostData( + WebApkTestHelper.getGeneratedShareTargetActivityClassName(0), info.shareTarget(), + info.shareData()); assertPostData( postData, new String[] {}, new String[] {}, new String[] {}, new String[] {}); @@ -205,6 +223,7 @@ shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_ENCTYPE, "multipart/form-data"); shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_PARAM_NAMES, "[\"name\"]"); shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_PARAM_ACCEPTS, "[[\"image/*\"]]"); + shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_ACTION, "/share.html"); registerWebApk(shareActivityBundle); Intent intent = createBasicShareIntent(); @@ -214,8 +233,9 @@ WebApkInfo info = WebApkInfo.create(intent); - WebApkShareTargetUtilShadow.PostData postData = - WebApkShareTargetUtilShadow.computePostData(WEBAPK_PACKAGE_NAME, info.shareData()); + WebApkShareTargetUtilShadow.PostData postData = WebApkShareTargetUtilShadow.computePostData( + WebApkTestHelper.getGeneratedShareTargetActivityClassName(0), info.shareTarget(), + info.shareData()); assertPostData(postData, new String[] {"name"}, new String[] {"content"}, new String[] {"filename"}, new String[] {"image/gif"}); @@ -231,6 +251,7 @@ shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_PARAM_TEXT, "share-text"); shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_PARAM_TITLE, "share-title"); shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_PARAM_URL, "share-url"); + shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_ACTION, "/share.html"); registerWebApk(shareActivityBundle); @@ -240,8 +261,9 @@ WebApkInfo info = WebApkInfo.create(intent); - WebApkShareTargetUtilShadow.PostData postData = - WebApkShareTargetUtilShadow.computePostData(WEBAPK_PACKAGE_NAME, info.shareData()); + WebApkShareTargetUtilShadow.PostData postData = WebApkShareTargetUtilShadow.computePostData( + WebApkTestHelper.getGeneratedShareTargetActivityClassName(0), info.shareTarget(), + info.shareData()); assertPostData(postData, new String[] {"share-title", "share-text"}, new String[] {"shared_subject_value", "shared_text_value"}, new String[] {"", ""}, @@ -258,6 +280,7 @@ shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_PARAM_TEXT, "share-text"); shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_PARAM_TITLE, "share-title"); shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_PARAM_URL, "share-url"); + shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_ACTION, "/share.html"); registerWebApk(shareActivityBundle); @@ -267,8 +290,9 @@ WebApkInfo info = WebApkInfo.create(intent); - WebApkShareTargetUtilShadow.PostData postData = - WebApkShareTargetUtilShadow.computePostData(WEBAPK_PACKAGE_NAME, info.shareData()); + WebApkShareTargetUtilShadow.PostData postData = WebApkShareTargetUtilShadow.computePostData( + WebApkTestHelper.getGeneratedShareTargetActivityClassName(0), info.shareTarget(), + info.shareData()); assertPostData(postData, new String[] {"share-title", "share-text"}, new String[] {"shared_subject_value", "shared_text_value"}, new String[] {"", ""}, @@ -285,6 +309,7 @@ shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_PARAM_TEXT, "share-text"); shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_PARAM_TITLE, "share-title"); shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_PARAM_URL, "share-url"); + shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_ACTION, "/share.html"); registerWebApk(shareActivityBundle); @@ -298,8 +323,9 @@ WebApkInfo info = WebApkInfo.create(intent); - WebApkShareTargetUtilShadow.PostData postData = - WebApkShareTargetUtilShadow.computePostData(WEBAPK_PACKAGE_NAME, info.shareData()); + WebApkShareTargetUtilShadow.PostData postData = WebApkShareTargetUtilShadow.computePostData( + WebApkTestHelper.getGeneratedShareTargetActivityClassName(0), info.shareTarget(), + info.shareData()); assertPostData(postData, new String[] {"share-title", "share-text", "name"}, new String[] {"shared_subject_value", "shared_text_value", "content"}, @@ -317,6 +343,7 @@ shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_PARAM_TEXT, "share-text"); shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_PARAM_TITLE, "share-title"); shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_PARAM_URL, "share-url"); + shareActivityBundle.putString(WebApkMetaDataKeys.SHARE_ACTION, "/share.html"); registerWebApk(shareActivityBundle); @@ -330,8 +357,9 @@ WebApkInfo info = WebApkInfo.create(intent); - WebApkShareTargetUtilShadow.PostData postData = - WebApkShareTargetUtilShadow.computePostData(WEBAPK_PACKAGE_NAME, info.shareData()); + WebApkShareTargetUtilShadow.PostData postData = WebApkShareTargetUtilShadow.computePostData( + WebApkTestHelper.getGeneratedShareTargetActivityClassName(0), info.shareTarget(), + info.shareData()); // with invalid name parameter from Android manifest, we ignore the file sharing part. assertPostData(postData, new String[] {"share-title", "share-text"},
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java index e50e7b1..b5bd04f2 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java
@@ -17,6 +17,7 @@ import android.graphics.Color; import android.os.Bundle; +import org.json.JSONArray; import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -46,6 +47,7 @@ import java.io.File; import java.io.FileOutputStream; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -84,6 +86,13 @@ private static final long BACKGROUND_COLOR = 2L; private static final String SHARE_TARGET_ACTION = "/share_action.html"; private static final String SHARE_TARGET_PARAM_TITLE = "share_params_title"; + private static final String SHARE_TARGET_METHOD_GET = "GET"; + private static final String SHARE_TARGET_METHOD_POST = "POST"; + private static final String SHARE_TARGET_ENC_TYPE_MULTIPART = "multipart/form-data"; + private static final String[] SHARE_TARGET_FILE_NAMES = new String[] {"file_1", "file_2"}; + private static final String[][] SHARE_TARGET_ACCEPTS = + new String[][] {new String[] {"file_1_accept_1", "file_1_accept_2"}, + new String[] {"file_2_accept_2", "file_2_accept_2"}}; /** Different name than the one used in {@link defaultManifestData()}. */ private static final String DIFFERENT_NAME = "Different Name"; @@ -117,7 +126,9 @@ String[] iconHashes, @WebDisplayMode int displayMode, int orientation, long themeColor, long backgroundColor, String shareTargetAction, String shareTargetParamTitle, String shareTargetParamText, - String shareTargetParamUrl, String manifestUrl, String webApkPackage, + String shareTargetParamUrl, boolean shareTargetParamIsMethodPost, + boolean shareTargetParamIsEncTypeMultipart, String[] shareTargetParamFileNames, + Object[] shareTargetParamAccepts, String manifestUrl, String webApkPackage, int webApkVersion, boolean isManifestStale, @WebApkUpdateReason int updateReason, Callback<Boolean> callback) {} @@ -205,6 +216,10 @@ public long backgroundColor; public String shareTargetAction; public String shareTargetParamTitle; + public String shareTargetMethod; + public String shareTargetEncType; + public String[] shareTargetFileNames; + public String[][] shareTargetFileAccepts; } private static String getWebApkId(String packageName) { @@ -251,6 +266,30 @@ shareTargetMetaData.putString( WebApkMetaDataKeys.SHARE_PARAM_TITLE, manifestData.shareTargetParamTitle); + shareTargetMetaData.putString( + WebApkMetaDataKeys.SHARE_METHOD, manifestData.shareTargetMethod); + shareTargetMetaData.putString( + WebApkMetaDataKeys.SHARE_ENCTYPE, manifestData.shareTargetEncType); + + shareTargetMetaData.remove(WebApkMetaDataKeys.SHARE_PARAM_NAMES); + if (manifestData.shareTargetFileNames != null) { + JSONArray fileNamesJson = + new JSONArray(Arrays.asList(manifestData.shareTargetFileNames)); + shareTargetMetaData.putString( + WebApkMetaDataKeys.SHARE_PARAM_NAMES, fileNamesJson.toString()); + } + + shareTargetMetaData.remove(WebApkMetaDataKeys.SHARE_PARAM_ACCEPTS); + if (manifestData.shareTargetFileAccepts != null) { + JSONArray acceptJson = new JSONArray(); + + for (String[] acceptArr : manifestData.shareTargetFileAccepts) { + acceptJson.put(new JSONArray(Arrays.asList(acceptArr))); + } + shareTargetMetaData.putString( + WebApkMetaDataKeys.SHARE_PARAM_ACCEPTS, acceptJson.toString()); + } + WebApkTestHelper.registerWebApkWithMetaData( packageName, metaData, new Bundle[] {shareTargetMetaData}); } @@ -276,6 +315,12 @@ manifestData.backgroundColor = BACKGROUND_COLOR; manifestData.shareTargetAction = SHARE_TARGET_ACTION; manifestData.shareTargetParamTitle = SHARE_TARGET_PARAM_TITLE; + + manifestData.shareTargetMethod = SHARE_TARGET_METHOD_GET; + manifestData.shareTargetEncType = SHARE_TARGET_ENC_TYPE_MULTIPART; + manifestData.shareTargetFileNames = SHARE_TARGET_FILE_NAMES.clone(); + manifestData.shareTargetFileAccepts = + Arrays.stream(SHARE_TARGET_ACCEPTS).map(String[] ::clone).toArray(String[][] ::new); return manifestData; } @@ -291,8 +336,15 @@ WEB_MANIFEST_URL, manifestData.startUrl, WebApkInfo.WebApkDistributor.BROWSER, manifestData.iconUrlToMurmur2HashMap, new WebApkInfo.ShareTarget(manifestData.shareTargetAction, - manifestData.shareTargetParamTitle, null, null), - false /* forceNavigation */, false /* isSplashProvidedByWebApk */, null); + manifestData.shareTargetParamTitle, null, null, + manifestData.shareTargetMethod != null + && manifestData.shareTargetMethod.equals(SHARE_TARGET_METHOD_POST), + manifestData.shareTargetEncType != null + && manifestData.shareTargetEncType.equals( + SHARE_TARGET_ENC_TYPE_MULTIPART), + manifestData.shareTargetFileNames, manifestData.shareTargetFileAccepts), + null /* shareTargetActivityName */, false /* forceNavigation */, + false /* isSplashProvidedByWebApk */, null /* shareData */); } /** @@ -749,6 +801,68 @@ assertTrue(checkUpdateNeededForFetchedManifest(oldData, fetchedData)); } + @Test + public void testShareTargetV2ChangedShouldUpgrade() { + ManifestData oldData = defaultManifestData(); + + ManifestData fetchedData1 = defaultManifestData(); + fetchedData1.shareTargetFileNames[0] = "changed"; + assertTrue(checkUpdateNeededForFetchedManifest(oldData, fetchedData1)); + + ManifestData fetchedData2 = defaultManifestData(); + fetchedData2.shareTargetFileAccepts[1] = new String[] {}; + assertTrue(checkUpdateNeededForFetchedManifest(oldData, fetchedData2)); + + ManifestData fetchedData3 = defaultManifestData(); + fetchedData3.shareTargetFileAccepts[1][1] = "changed"; + assertTrue(checkUpdateNeededForFetchedManifest(oldData, fetchedData3)); + } + + @Test + public void testShareTargetV2UpgradeFromV1() { + ManifestData oldNoShareTarget = defaultManifestData(); + oldNoShareTarget.shareTargetAction = null; + oldNoShareTarget.shareTargetParamTitle = null; + oldNoShareTarget.shareTargetMethod = null; + oldNoShareTarget.shareTargetEncType = null; + oldNoShareTarget.shareTargetFileNames = null; + oldNoShareTarget.shareTargetFileAccepts = null; + + ManifestData fetchedNoShareTarget2 = defaultManifestData(); + fetchedNoShareTarget2.shareTargetAction = null; + fetchedNoShareTarget2.shareTargetParamTitle = null; + fetchedNoShareTarget2.shareTargetMethod = null; + fetchedNoShareTarget2.shareTargetEncType = null; + fetchedNoShareTarget2.shareTargetFileNames = null; + fetchedNoShareTarget2.shareTargetFileAccepts = null; + + assertFalse(checkUpdateNeededForFetchedManifest(oldNoShareTarget, fetchedNoShareTarget2)); + + ManifestData oldV1ShareTarget = defaultManifestData(); + oldV1ShareTarget.shareTargetMethod = null; + oldV1ShareTarget.shareTargetEncType = null; + oldV1ShareTarget.shareTargetFileNames = null; + oldV1ShareTarget.shareTargetFileAccepts = null; + + ManifestData fetchedV1ShareTarget = defaultManifestData(); + fetchedV1ShareTarget.shareTargetMethod = null; + fetchedV1ShareTarget.shareTargetEncType = null; + fetchedV1ShareTarget.shareTargetFileNames = null; + fetchedV1ShareTarget.shareTargetFileAccepts = null; + assertFalse(checkUpdateNeededForFetchedManifest(oldV1ShareTarget, fetchedV1ShareTarget)); + + ManifestData oldV2ShareTarget = defaultManifestData(); + ManifestData fetchedV2ShareTarget = defaultManifestData(); + assertFalse(checkUpdateNeededForFetchedManifest(oldV2ShareTarget, fetchedV2ShareTarget)); + + assertTrue(checkUpdateNeededForFetchedManifest(oldNoShareTarget, fetchedV1ShareTarget)); + assertTrue(checkUpdateNeededForFetchedManifest(oldNoShareTarget, fetchedV2ShareTarget)); + assertTrue(checkUpdateNeededForFetchedManifest(oldV1ShareTarget, fetchedV2ShareTarget)); + assertTrue(checkUpdateNeededForFetchedManifest(fetchedV2ShareTarget, fetchedV1ShareTarget)); + assertTrue(checkUpdateNeededForFetchedManifest(fetchedV2ShareTarget, oldNoShareTarget)); + assertTrue(checkUpdateNeededForFetchedManifest(fetchedV1ShareTarget, oldNoShareTarget)); + } + /** * Test that an upgrade is not requested when the Web Manifest did not change and the Web * Manifest scope is empty.
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt index 77a7c15..7d1d321 100644 --- a/chrome/android/profiles/newest.txt +++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-76.0.3805.0_rc-r1-merged.afdo.bz2 \ No newline at end of file +chromeos-chrome-amd64-76.0.3806.0_rc-r1-merged.afdo.bz2 \ No newline at end of file
diff --git a/chrome/app/extensions_strings.grdp b/chrome/app/extensions_strings.grdp index b3a1db4..fd3d828 100644 --- a/chrome/app/extensions_strings.grdp +++ b/chrome/app/extensions_strings.grdp
@@ -295,6 +295,9 @@ <message name="IDS_EXTENSIONS_LOADING_ACTIVITIES" desc="The message shown to the user when the activity log for an extension is currently being fetched from the API."> Fetching activities... </message> + <message name="IDS_MISSING_OR_UNINSTALLED_EXTENSION" desc="The placeholder for the activity log page header if the extension does not exist or is not installed."> + Missing or uninstalled extension + </message> <message name="IDS_EXTENSIONS_NO_ACTIVITIES" desc="The message shown to the user when an extension has no recent activities."> No recent activities </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 9ff87bb..e7c65a9 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -333,8 +333,8 @@ "component_updater/recovery_component_installer.h", "component_updater/recovery_improved_component_installer.cc", "component_updater/recovery_improved_component_installer.h", - "component_updater/sth_set_component_installer.cc", - "component_updater/sth_set_component_installer.h", + "component_updater/sth_set_component_remover.cc", + "component_updater/sth_set_component_remover.h", "component_updater/subresource_filter_component_installer.cc", "component_updater/subresource_filter_component_installer.h", "component_updater/supervised_user_whitelist_installer.cc", @@ -5525,47 +5525,37 @@ } } -static_library("test_support_ui") { - testonly = true +if (!is_android) { + static_library("test_support_ui") { + testonly = true + configs += [ "//build/config:precompiled_headers" ] - # Always include this via the main test support UI target. - visibility = [ "//chrome/test:test_support_ui" ] + # Always include this via the main test support UI target. + visibility = [ "//chrome/test:test_support_ui" ] - sources = [ - "signin/token_revoker_test_utils.cc", - "signin/token_revoker_test_utils.h", - ] - - deps = [ - "//components/metrics:test_support", - "//components/password_manager/core/browser:test_support", - "//components/translate/content/common", - "//skia", - "//testing/gtest", - "//third_party/blink/public:blink_headers", - ] - - public_deps = [ - "//net:test_support", - ] - - configs += [ "//build/config:precompiled_headers" ] - - if (!is_android) { - sources += [ + sources = [ "password_manager/password_manager_test_base.cc", "password_manager/password_manager_test_base.h", + "signin/token_revoker_test_utils.cc", + "signin/token_revoker_test_utils.h", "ui/webui/signin/login_ui_test_utils.cc", "ui/webui/signin/login_ui_test_utils.h", "ui/webui/web_ui_test_handler.cc", "ui/webui/web_ui_test_handler.h", ] - deps += [ + deps = [ ":browser", "//chrome:browser_tests_pak", "//chrome/common:mojo_bindings", "//chrome/test/data:web_ui_test_bindings", + "//components/metrics:test_support", + "//components/password_manager/core/browser:test_support", + "//components/translate/content/common", + ] + + public_deps = [ + "//net:test_support", ] } }
diff --git a/chrome/browser/android/provider/chrome_browser_provider.cc b/chrome/browser/android/provider/chrome_browser_provider.cc index 36e397d7..7f89ab47 100644 --- a/chrome/browser/android/provider/chrome_browser_provider.cc +++ b/chrome/browser/android/provider/chrome_browser_provider.cc
@@ -136,22 +136,6 @@ return env->CallIntMethod(integer_obj.obj(), int_value, NULL); } -std::vector<base::string16> ConvertJStringArrayToString16Array( - JNIEnv* env, - const JavaRef<jobjectArray>& array) { - std::vector<base::string16> results; - if (!array.is_null()) { - jsize len = env->GetArrayLength(array.obj()); - for (int i = 0; i < len; i++) { - ScopedJavaLocalRef<jstring> j_str( - env, - static_cast<jstring>(env->GetObjectArrayElement(array.obj(), i))); - results.push_back(ConvertJavaStringToUTF16(env, j_str)); - } - } - return results; -} - // ------------- Utility methods used by tasks ------------- // // Parse the given url and return a GURL, appending the default scheme @@ -931,8 +915,8 @@ } } - std::vector<base::string16> where_args = - ConvertJStringArrayToString16Array(env, selection_args); + std::vector<base::string16> where_args; + AppendJavaStringArrayToStringVector(env, selection_args, &where_args); std::string where_clause; if (selections) { @@ -976,8 +960,8 @@ date, favicon, title, visits, parent_id, &row, bookmark_model_); - std::vector<base::string16> where_args = - ConvertJStringArrayToString16Array(env, selection_args); + std::vector<base::string16> where_args; + AppendJavaStringArrayToStringVector(env, selection_args, &where_args); std::string where_clause; if (selections) @@ -992,8 +976,8 @@ const JavaParamRef<jobject>& obj, const JavaParamRef<jstring>& selections, const JavaParamRef<jobjectArray>& selection_args) { - std::vector<base::string16> where_args = - ConvertJStringArrayToString16Array(env, selection_args); + std::vector<base::string16> where_args; + AppendJavaStringArrayToStringVector(env, selection_args, &where_args); std::string where_clause; if (selections) @@ -1008,8 +992,8 @@ const JavaParamRef<jobject>& obj, const JavaParamRef<jstring>& selections, const JavaParamRef<jobjectArray>& selection_args) { - std::vector<base::string16> where_args = - ConvertJStringArrayToString16Array(env, selection_args); + std::vector<base::string16> where_args; + AppendJavaStringArrayToStringVector(env, selection_args, &where_args); std::string where_clause; if (selections) @@ -1069,8 +1053,8 @@ } } - std::vector<base::string16> where_args = - ConvertJStringArrayToString16Array(env, selection_args); + std::vector<base::string16> where_args; + AppendJavaStringArrayToStringVector(env, selection_args, &where_args); std::string where_clause; if (selections) { @@ -1107,8 +1091,8 @@ history::SearchRow row; JNI_ChromeBrowserProvider_FillSearchRow(env, obj, search_term, date, &row); - std::vector<base::string16> where_args = ConvertJStringArrayToString16Array( - env, selection_args); + std::vector<base::string16> where_args; + AppendJavaStringArrayToStringVector(env, selection_args, &where_args); std::string where_clause; if (selections) @@ -1125,8 +1109,8 @@ const JavaParamRef<jobject>& obj, const JavaParamRef<jstring>& selections, const JavaParamRef<jobjectArray>& selection_args) { - std::vector<base::string16> where_args = - ConvertJStringArrayToString16Array(env, selection_args); + std::vector<base::string16> where_args; + AppendJavaStringArrayToStringVector(env, selection_args, &where_args); std::string where_clause; if (selections)
diff --git a/chrome/browser/android/webapk/webapk_update_data_fetcher.cc b/chrome/browser/android/webapk/webapk_update_data_fetcher.cc index 13e7609b..08e8682 100644 --- a/chrome/browser/android/webapk/webapk_update_data_fetcher.cc +++ b/chrome/browser/android/webapk/webapk_update_data_fetcher.cc
@@ -227,7 +227,11 @@ ScopedJavaLocalRef<jstring> java_share_params_title; ScopedJavaLocalRef<jstring> java_share_params_text; ScopedJavaLocalRef<jstring> java_share_params_url; - if (info_.share_target.has_value()) { + jboolean java_share_params_is_method_post = false; + jboolean java_share_params_is_enctype_multipart = false; + ScopedJavaLocalRef<jobjectArray> java_share_params_file_names; + ScopedJavaLocalRef<jobjectArray> java_share_params_accepts; + if (info_.share_target.has_value() && info_.share_target->action.is_valid()) { java_share_action = base::android::ConvertUTF8ToJavaString( env, info_.share_target->action.spec()); java_share_params_title = base::android::ConvertUTF16ToJavaString( @@ -236,6 +240,22 @@ env, info_.share_target->params.text); java_share_params_url = base::android::ConvertUTF16ToJavaString( env, info_.share_target->params.url); + + java_share_params_is_method_post = + (info_.share_target->method == ShareTarget::kPost); + java_share_params_is_enctype_multipart = + (info_.share_target->enctype == ShareTarget::kMultipart); + + std::vector<base::string16> file_names; + std::vector<std::vector<base::string16>> accepts; + for (auto& f : info_.share_target->params.files) { + file_names.push_back(f.name); + accepts.push_back(f.accept); + } + java_share_params_file_names = + base::android::ToJavaArrayOfStrings(env, file_names); + java_share_params_accepts = + base::android::ToJavaArrayOfStringArray(env, accepts); } Java_WebApkUpdateDataFetcher_onDataAvailable( @@ -245,5 +265,7 @@ java_icon_urls, info_.display, info_.orientation, OptionalSkColorToJavaColor(info_.theme_color), OptionalSkColorToJavaColor(info_.background_color), java_share_action, - java_share_params_title, java_share_params_text, java_share_params_url); + java_share_params_title, java_share_params_text, java_share_params_url, + java_share_params_is_method_post, java_share_params_is_enctype_multipart, + java_share_params_file_names, java_share_params_accepts); }
diff --git a/chrome/browser/android/webapk/webapk_update_manager.cc b/chrome/browser/android/webapk/webapk_update_manager.cc index cbbf307..9bacd43 100644 --- a/chrome/browser/android/webapk/webapk_update_manager.cc +++ b/chrome/browser/android/webapk/webapk_update_manager.cc
@@ -65,6 +65,10 @@ const JavaParamRef<jstring>& java_share_target_param_title, const JavaParamRef<jstring>& java_share_target_param_text, const JavaParamRef<jstring>& java_share_target_param_url, + const jboolean java_share_target_param_is_method_post, + const jboolean java_share_target_param_is_enctype_multipart, + const JavaParamRef<jobjectArray>& java_share_target_param_file_names, + const JavaParamRef<jobjectArray>& java_share_target_param_accepts, const JavaParamRef<jstring>& java_web_manifest_url, const JavaParamRef<jstring>& java_webapk_package, jint java_webapk_version, @@ -103,6 +107,31 @@ ConvertJavaStringToUTF16(java_share_target_param_text); info.share_target->params.url = ConvertJavaStringToUTF16(java_share_target_param_url); + info.share_target->method = + java_share_target_param_is_method_post == JNI_TRUE ? ShareTarget::kPost + : ShareTarget::kGet; + + info.share_target->enctype = + java_share_target_param_is_enctype_multipart == JNI_TRUE + ? ShareTarget::kMultipart + : ShareTarget::kApplication; + + std::vector<base::string16> fileNames; + base::android::AppendJavaStringArrayToStringVector( + env, java_share_target_param_file_names, &fileNames); + + std::vector<std::vector<base::string16>> accepts; + base::android::Java2dStringArrayTo2dStringVector( + env, java_share_target_param_accepts, &accepts); + + // The length of fileNames and accepts should always be the same, but here + // we just want to be safe. + for (size_t i = 0; i < std::min(fileNames.size(), accepts.size()); ++i) { + ShareTargetParamsFile file; + file.name = fileNames[i]; + file.accept.swap(accepts[i]); + info.share_target->params.files.push_back(file); + } } base::android::AppendJavaStringArrayToStringVector(env, java_icon_urls,
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc index 4c1bbd7b..dac48ab 100644 --- a/chrome/browser/apps/guest_view/web_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -92,6 +92,7 @@ #include "extensions/browser/api/declarative_webrequest/webrequest_constants.h" #include "extensions/browser/api/extensions_api_client.h" #include "extensions/browser/app_window/native_app_window.h" +#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_embedder.h" #include "extensions/browser/guest_view/web_view/web_view_guest.h" #include "extensions/common/extension.h" #include "extensions/common/extensions_client.h" @@ -3341,7 +3342,13 @@ true); TestHelper("testPluginLoadInternalResource", "web_view/shim", NO_TEST_SERVER); + // Sanity check to ensure no GuestView was created. + for (auto* guest_wc : GetEmbedderWebContents()->GetInnerWebContents()) { + EXPECT_FALSE(extensions::MimeHandlerViewEmbedder::Get( + guest_wc->GetMainFrame()->GetFrameTreeNodeId())); + } } + #endif // BUILDFLAG(ENABLE_PLUGINS) class WebViewCaptureTest : public WebViewTest {
diff --git a/chrome/browser/banners/app_banner_manager.cc b/chrome/browser/banners/app_banner_manager.cc index c475b05..464ad92 100644 --- a/chrome/browser/banners/app_banner_manager.cc +++ b/chrome/browser/banners/app_banner_manager.cc
@@ -346,18 +346,31 @@ TrackDisplayEvent(DISPLAY_EVENT_WEB_APP_BANNER_REQUESTED); auto error = data.errors.empty() ? NO_ERROR_DETECTED : data.errors[0]; - SetInstallableWebAppCheckResult(error == NO_ERROR_DETECTED - ? InstallableWebAppCheckResult::kYes - : InstallableWebAppCheckResult::kNo); - if (error != NO_ERROR_DETECTED) { if (error == NO_MATCHING_SERVICE_WORKER) TrackDisplayEvent(DISPLAY_EVENT_LACKS_SERVICE_WORKER); + SetInstallableWebAppCheckResult(InstallableWebAppCheckResult::kNo); Stop(error); return; } + if (CheckIfInstalled()) { + banners::TrackDisplayEvent(banners::DISPLAY_EVENT_INSTALLED_PREVIOUSLY); + SetInstallableWebAppCheckResult(InstallableWebAppCheckResult::kNo); + Stop(ALREADY_INSTALLED); + return; + } + + if (manifest_.prefer_related_applications) { + SetInstallableWebAppCheckResult( + InstallableWebAppCheckResult::kByUserRequest); + Stop(PREFER_RELATED_APPLICATIONS); + return; + } + + SetInstallableWebAppCheckResult(InstallableWebAppCheckResult::kPromotable); + DCHECK(data.has_worker && data.valid_manifest); DCHECK(!data.primary_icon_url.is_empty()); DCHECK(data.primary_icon); @@ -365,11 +378,6 @@ primary_icon_url_ = data.primary_icon_url; primary_icon_ = *data.primary_icon; - if (CheckIfInstalled()) { - banners::TrackDisplayEvent(banners::DISPLAY_EVENT_INSTALLED_PREVIOUSLY); - Stop(ALREADY_INSTALLED); - return; - } // If we triggered the installability check on page load, then it's possible // we don't have enough engagement yet. If that's the case, return here but @@ -449,11 +457,6 @@ return NO_ERROR_DETECTED; } -bool AppBannerManager::IsInstallableWebApp() const { - return installable_web_app_check_result_ == - InstallableWebAppCheckResult::kYes; -} - void AppBannerManager::SetInstallableWebAppCheckResult( InstallableWebAppCheckResult result) { if (installable_web_app_check_result_ == result) @@ -464,15 +467,16 @@ switch (result) { case InstallableWebAppCheckResult::kUnknown: break; - case InstallableWebAppCheckResult::kYes: - last_installable_web_app_scope_ = manifest_.scope; - DCHECK(!last_installable_web_app_scope_.is_empty()); + case InstallableWebAppCheckResult::kPromotable: + last_promotable_web_app_scope_ = manifest_.scope; + DCHECK(!last_promotable_web_app_scope_.is_empty()); install_animation_pending_ = AppBannerSettingsHelper::CanShowInstallTextAnimation( - web_contents(), last_installable_web_app_scope_); + web_contents(), last_promotable_web_app_scope_); break; + case InstallableWebAppCheckResult::kByUserRequest: case InstallableWebAppCheckResult::kNo: - last_installable_web_app_scope_ = GURL(); + last_promotable_web_app_scope_ = GURL(); install_animation_pending_ = false; break; } @@ -641,28 +645,39 @@ base::string16 AppBannerManager::GetInstallableWebAppName( content::WebContents* web_contents) { AppBannerManager* manager = FromWebContents(web_contents); - if (!manager || !manager->IsInstallableWebApp()) + if (!manager) return base::string16(); - return manager->GetAppName(); + switch (manager->installable_web_app_check_result_) { + case InstallableWebAppCheckResult::kUnknown: + case InstallableWebAppCheckResult::kNo: + return base::string16(); + case InstallableWebAppCheckResult::kByUserRequest: + case InstallableWebAppCheckResult::kPromotable: + return manager->GetAppName(); + } } -bool AppBannerManager::IsProbablyInstallableWebApp() const { - if (IsInstallableWebApp()) - return true; - return installable_web_app_check_result_ == - InstallableWebAppCheckResult::kUnknown && - last_installable_web_app_scope_.is_valid() && - base::StartsWith(web_contents()->GetLastCommittedURL().spec(), - last_installable_web_app_scope_.spec(), - base::CompareCase::SENSITIVE); +bool AppBannerManager::IsProbablyPromotableWebApp() const { + switch (installable_web_app_check_result_) { + case InstallableWebAppCheckResult::kUnknown: + return last_promotable_web_app_scope_.is_valid() && + base::StartsWith(web_contents()->GetLastCommittedURL().spec(), + last_promotable_web_app_scope_.spec(), + base::CompareCase::SENSITIVE); + case InstallableWebAppCheckResult::kNo: + case InstallableWebAppCheckResult::kByUserRequest: + return false; + case InstallableWebAppCheckResult::kPromotable: + return true; + } } bool AppBannerManager::MaybeConsumeInstallAnimation() { - DCHECK(IsProbablyInstallableWebApp()); + DCHECK(IsProbablyPromotableWebApp()); if (!install_animation_pending_) return false; AppBannerSettingsHelper::RecordInstallTextAnimationShown( - web_contents(), last_installable_web_app_scope_); + web_contents(), last_promotable_web_app_scope_); install_animation_pending_ = false; return true; }
diff --git a/chrome/browser/banners/app_banner_manager.h b/chrome/browser/banners/app_banner_manager.h index c1d1e1e..b7ae097 100644 --- a/chrome/browser/banners/app_banner_manager.h +++ b/chrome/browser/banners/app_banner_manager.h
@@ -105,9 +105,14 @@ COMPLETE, }; - // Installable describes whether a site satisifes the installablity + // Installable describes to what degree a site satisifes the installablity // requirements. - enum class InstallableWebAppCheckResult { kUnknown, kNo, kYes }; + enum class InstallableWebAppCheckResult { + kUnknown, + kNo, + kByUserRequest, + kPromotable, + }; // Retrieves the platform specific instance of AppBannerManager from // |web_contents|. @@ -131,10 +136,10 @@ static base::string16 GetInstallableWebAppName( content::WebContents* web_contents); - // Returns whether installability checks have passed (e.g. having a service - // worker fetch event) or have passed previously within the current manifest - // scope. - bool IsProbablyInstallableWebApp() const; + // Returns whether installability checks satisfy promotion requirements + // (e.g. having a service worker fetch event) or have passed previously within + // the current manifest scope. + bool IsProbablyPromotableWebApp() const; // Each successful installability check gets to show one animation prompt, // this returns and consumes the animation prompt if it is available. @@ -167,9 +172,7 @@ // GetAppIdentifier() must return a valid value for this method to work. bool CheckIfShouldShowBanner(); - // Called when the current site is eligible to show a banner. Returns true if - // the banner should not be shown because the site is already installed, and - // false if the banner should be shown because the site is not yet installed. + // Returns whether the site is already installed as a web app. bool CheckIfInstalled(); // Return a string identifying this app for metrics. @@ -337,7 +340,6 @@ // Returns a status code based on the current state, to log when terminating. InstallableStatusCode TerminationCode() const; - bool IsInstallableWebApp() const; void SetInstallableWebAppCheckResult(InstallableWebAppCheckResult result); // Fetches the data required to display a banner for the current page. @@ -361,9 +363,9 @@ bool install_animation_pending_; InstallableWebAppCheckResult installable_web_app_check_result_; - // The scope of the most recent installability check if successful otherwise - // invalid. - GURL last_installable_web_app_scope_; + // The scope of the most recent installability check that passes promotability + // requirements, otherwise invalid. + GURL last_promotable_web_app_scope_; base::ObserverList<Observer, true> observer_list_;
diff --git a/chrome/browser/banners/app_banner_manager_browsertest.cc b/chrome/browser/banners/app_banner_manager_browsertest.cc index 9e77b2f..adc08ea9 100644 --- a/chrome/browser/banners/app_banner_manager_browsertest.cc +++ b/chrome/browser/banners/app_banner_manager_browsertest.cc
@@ -468,4 +468,20 @@ SHOWING_WEB_APP_BANNER, 1); } +IN_PROC_BROWSER_TEST_F(AppBannerManagerBrowserTest, PreferRelatedApplications) { + std::unique_ptr<AppBannerManagerTest> manager( + CreateAppBannerManager(browser())); + base::HistogramTester histograms; + + GURL test_url = embedded_test_server()->GetURL( + "/banners/manifest_test_page.html?manifest=" + "manifest_prefer_related_apps_empty.json"); + TriggerBannerFlowWithNavigation(browser(), manager.get(), test_url, + false /* expected_will_show */, + State::COMPLETE); + + histograms.ExpectUniqueSample(banners::kInstallableStatusCodeHistogram, + PREFER_RELATED_APPLICATIONS, 1); +} + } // namespace banners
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index 5abd5845..90dceea 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc
@@ -60,7 +60,7 @@ #include "chrome/browser/component_updater/optimization_hints_component_installer.h" #include "chrome/browser/component_updater/origin_trials_component_installer.h" #include "chrome/browser/component_updater/pepper_flash_component_installer.h" -#include "chrome/browser/component_updater/sth_set_component_installer.h" +#include "chrome/browser/component_updater/sth_set_component_remover.h" #include "chrome/browser/component_updater/subresource_filter_component_installer.h" #include "chrome/browser/component_updater/supervised_user_whitelist_installer.h" #include "chrome/browser/defaults.h" @@ -496,6 +496,15 @@ // The CRLSet component previously resided in a different location: delete // the old file. component_updater::DeleteLegacyCRLSet(path); + +#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) + // Clean up previous STH sets that may have been installed. This is not + // done for: + // Android: Because STH sets were never used + // Chrome OS: On Chrome OS, this cleanup is delayed until user login. + component_updater::DeleteLegacySTHSet(path); +#endif + #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) // CRLSetFetcher attempts to load a CRL set from either the local disk or // network. @@ -504,12 +513,6 @@ component_updater::RegisterCRLSetComponent(cus, path); #endif // !defined(OS_CHROMEOS) && !defined(OS_ANDROID) -#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) - // Registration of the STH set fetcher here is not done for: - // Android: Because the story around CT on Mobile is not finalized yet. - // Chrome OS: On Chrome OS this registration is delayed until user login. - RegisterSTHSetComponent(cus, path); -#endif // !defined(OS_CHROMEOS) && !defined(OS_ANDROID) RegisterOriginTrialsComponent(cus, path); RegisterFileTypePoliciesComponent(cus, path); @@ -1813,15 +1816,14 @@ PostBrowserStart(); -#if defined(OS_ANDROID) - DCHECK(!parameters().ui_task); -#else + // The ui_task can be injected by tests to replace the main message loop. + // In that case we Run() it here, and set a flag to avoid running the main + // message loop later, as the test will do so as needed from the |ui_task|. if (parameters().ui_task) { parameters().ui_task->Run(); delete parameters().ui_task; run_message_loop_ = false; } -#endif #if defined(OS_WIN) // Clean up old user data directory and disk cache directory.
diff --git a/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service.cc b/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service.cc index c360b65..63254a4f 100644 --- a/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service.cc +++ b/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service.cc
@@ -70,6 +70,14 @@ } // namespace +struct ArcWallpaperService::WallpaperIdPair { + // ID of wallpaper image which can be obtaind by + // WallpaperResizer::GetImageId(). + uint32_t image_id; + // ID of wallpaper generated in the container side. + int32_t android_id; +}; + class ArcWallpaperService::DecodeRequest : public ImageDecoder::ImageRequest { public: DecodeRequest(ArcWallpaperService* service, int32_t android_id) @@ -120,15 +128,26 @@ ArcWallpaperService::ArcWallpaperService(content::BrowserContext* context, ArcBridgeService* bridge_service) : arc_bridge_service_(bridge_service), - decode_request_sender_(std::make_unique<DecodeRequestSenderImpl>()) { + decode_request_sender_(std::make_unique<DecodeRequestSenderImpl>()), + observer_binding_(this), + weak_ptr_factory_(this) { arc_bridge_service_->wallpaper()->SetHost(this); + arc_bridge_service_->wallpaper()->AddObserver(this); } ArcWallpaperService::~ArcWallpaperService() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + arc_bridge_service_->wallpaper()->RemoveObserver(this); arc_bridge_service_->wallpaper()->SetHost(nullptr); } +void ArcWallpaperService::OnConnectionReady() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + ash::mojom::WallpaperObserverAssociatedPtrInfo ptr_info; + observer_binding_.Bind(mojo::MakeRequest(&ptr_info)); + WallpaperControllerClient::Get()->AddObserver(std::move(ptr_info)); +} + void ArcWallpaperService::SetWallpaper(const std::vector<uint8_t>& data, int32_t wallpaper_id) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -156,12 +175,35 @@ void ArcWallpaperService::GetWallpaper(GetWallpaperCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - gfx::ImageSkia image = WallpaperControllerClient::Get()->GetWallpaperImage(); - base::PostTaskWithTraitsAndReplyWithResult( - FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, - base::BindOnce(&EncodeImagePng, image), std::move(callback)); + WallpaperControllerClient::Get()->GetWallpaperImage( + base::BindOnce(&ArcWallpaperService::OnGetWallpaperImageCallback, + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } +void ArcWallpaperService::OnWallpaperChanged(uint32_t image_id) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + bool current_wallpaper_notified = false; + for (auto it = id_pairs_.begin(); it != id_pairs_.end();) { + int32_t const android_id = it->android_id; + if (it->image_id == image_id) { + current_wallpaper_notified = true; + it = id_pairs_.erase(it); + NotifyWallpaperChanged(android_id); + } else { + ++it; + } + } + + if (!current_wallpaper_notified) + NotifyWallpaperChanged(-1); +} + +void ArcWallpaperService::OnWallpaperColorsChanged( + const std::vector<SkColor>& prominent_colors) {} + +void ArcWallpaperService::OnWallpaperBlurChanged(bool blurred) {} + void ArcWallpaperService::OnWallpaperDecoded(const gfx::ImageSkia& image, int32_t android_id) { const AccountId account_id = @@ -169,20 +211,11 @@ const std::string wallpaper_files_id = WallpaperControllerClient::Get()->GetFilesId(account_id); - const bool result = WallpaperControllerClient::Get()->SetThirdPartyWallpaper( + WallpaperControllerClient::Get()->SetThirdPartyWallpaper( account_id, wallpaper_files_id, kAndroidWallpaperFilename, - ash::WALLPAPER_LAYOUT_CENTER_CROPPED, image); - - // Notify the Android side whether the request is going through or not. - if (result) - NotifyWallpaperChanged(android_id); - else - NotifyWallpaperChangedAndReset(android_id); - - // TODO(crbug.com/618922): Register the wallpaper to Chrome OS wallpaper - // picker. Currently the new wallpaper does not appear there. The best way - // to make this happen seems to do the same things as wallpaper_api.cc and - // wallpaper_private_api.cc. + ash::WALLPAPER_LAYOUT_CENTER_CROPPED, image, + base::BindOnce(&ArcWallpaperService::OnSetThirdPartyWallpaperCallback, + weak_ptr_factory_.GetWeakPtr(), android_id)); } void ArcWallpaperService::NotifyWallpaperChanged(int android_id) { @@ -203,4 +236,26 @@ NotifyWallpaperChanged(-1); } +void ArcWallpaperService::OnSetThirdPartyWallpaperCallback(int32_t android_id, + bool allowed, + uint32_t image_id) { + if (allowed) + id_pairs_.push_back({image_id, android_id}); + else + NotifyWallpaperChangedAndReset(android_id); + + // TODO(crbug.com/618922): Register the wallpaper to Chrome OS wallpaper + // picker. Currently the new wallpaper does not appear there. The best way + // to make this happen seems to do the same things as wallpaper_api.cc and + // wallpaper_private_api.cc. +} + +void ArcWallpaperService::OnGetWallpaperImageCallback( + GetWallpaperCallback callback, + const gfx::ImageSkia& image) { + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, + base::BindOnce(&EncodeImagePng, image), std::move(callback)); +} + } // namespace arc
diff --git a/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service.h b/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service.h index 6f7e950..c6c8fe7 100644 --- a/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service.h +++ b/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service.h
@@ -10,25 +10,28 @@ #include <memory> #include <vector> +#include "ash/public/interfaces/wallpaper.mojom.h" #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "chrome/browser/image_decoder.h" #include "components/arc/common/wallpaper.mojom.h" +#include "components/arc/session/connection_observer.h" #include "components/keyed_service/core/keyed_service.h" +#include "mojo/public/cpp/bindings/associated_binding.h" namespace content { class BrowserContext; } // namespace content -namespace gfx { -class ImageSkia; -} // namespace gfx - namespace arc { class ArcBridgeService; // Lives on the UI thread. -class ArcWallpaperService : public KeyedService, public mojom::WallpaperHost { +class ArcWallpaperService : public KeyedService, + public ConnectionObserver<mojom::WallpaperInstance>, + public mojom::WallpaperHost, + public ash::mojom::WallpaperObserver { public: // Returns singleton instance for the given BrowserContext, // or nullptr if the browser |context| is not allowed to use ARC. @@ -39,12 +42,21 @@ ArcBridgeService* bridge_service); ~ArcWallpaperService() override; + // ConnectionObserver<mojom::WallpaperInstance> overrides. + void OnConnectionReady() override; + // mojom::WallpaperHost overrides. void SetWallpaper(const std::vector<uint8_t>& data, int32_t wallpaper_id) override; void SetDefaultWallpaper() override; void GetWallpaper(GetWallpaperCallback callback) override; + // ash::mojom::WallpaperObserver overrides. + void OnWallpaperChanged(uint32_t image_id) override; + void OnWallpaperColorsChanged( + const std::vector<SkColor>& prominent_colors) override; + void OnWallpaperBlurChanged(bool blurred) override; + class DecodeRequestSender { public: virtual ~DecodeRequestSender(); @@ -63,6 +75,7 @@ friend class TestApi; class AndroidIdStore; class DecodeRequest; + struct WallpaperIdPair; // Initiates a set wallpaper request to //ash. void OnWallpaperDecoded(const gfx::ImageSkia& image, int32_t android_id); @@ -74,10 +87,27 @@ // -1 to reset wallpaper cache at Android side. void NotifyWallpaperChangedAndReset(int android_id); + // If the wallpaper is allowed to be shown on screen, stores the |image_id| + // in order to track the wallpaper change later, otherwise notify the Android + // side immediately that the request is not going through. + void OnSetThirdPartyWallpaperCallback(int32_t android_id, + bool allowed, + uint32_t image_id); + + // Initiates an encoding image request after getting the wallpaper image. + void OnGetWallpaperImageCallback(GetWallpaperCallback callback, + const gfx::ImageSkia& image); + ArcBridgeService* const arc_bridge_service_; // Owned by ArcServiceManager. std::unique_ptr<DecodeRequest> decode_request_; + std::vector<WallpaperIdPair> id_pairs_; std::unique_ptr<DecodeRequestSender> decode_request_sender_; + // The binding this instance uses to implement ash::mojom::WallpaperObserver. + mojo::AssociatedBinding<ash::mojom::WallpaperObserver> observer_binding_; + + base::WeakPtrFactory<ArcWallpaperService> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(ArcWallpaperService); };
diff --git a/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service_unittest.cc b/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service_unittest.cc index 8b84c4e..7e53975 100644 --- a/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service_unittest.cc +++ b/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service_unittest.cc
@@ -84,7 +84,8 @@ // Wallpaper wallpaper_controller_client_ = std::make_unique<WallpaperControllerClient>(); - wallpaper_controller_client_->InitForTesting(&test_wallpaper_controller_); + wallpaper_controller_client_->InitForTesting( + test_wallpaper_controller_.CreateInterfacePtr()); // Arc services arc_service_manager_.set_browser_context(&testing_profile_); @@ -135,6 +136,7 @@ TEST_F(ArcWallpaperServiceTest, SetDefaultWallpaper) { test_wallpaper_controller_.ClearCounts(); service_->SetDefaultWallpaper(); + wallpaper_controller_client_->FlushForTesting(); EXPECT_EQ(1, test_wallpaper_controller_.set_default_wallpaper_count()); } @@ -143,6 +145,7 @@ std::make_unique<SuccessDecodeRequestSender>()); std::vector<uint8_t> bytes; service_->SetWallpaper(bytes, 10 /*wallpaper_id=*/); + wallpaper_controller_client_->FlushForTesting(); ASSERT_EQ(1u, wallpaper_instance_->changed_ids().size()); EXPECT_EQ(10, wallpaper_instance_->changed_ids()[0]); @@ -150,6 +153,7 @@ base::BindOnce([](std::vector<uint8_t>* out, const std::vector<uint8_t>& bytes) { *out = bytes; }, &bytes)); + wallpaper_controller_client_->FlushForTesting(); content::RunAllTasksUntilIdle(); ASSERT_NE(0u, bytes.size()); } @@ -159,6 +163,7 @@ std::make_unique<FailureDecodeRequestSender>()); std::vector<uint8_t> bytes; service_->SetWallpaper(bytes, 10 /*wallpaper_id=*/); + wallpaper_controller_client_->FlushForTesting(); // For failure case, ArcWallpaperService reports that wallpaper is changed to // requested wallpaper (ID=10), then reports that the wallpaper is changed
diff --git a/chrome/browser/chromeos/customization/customization_wallpaper_downloader_browsertest.cc b/chrome/browser/chromeos/customization/customization_wallpaper_downloader_browsertest.cc index 8017981..19c4370 100644 --- a/chrome/browser/chromeos/customization/customization_wallpaper_downloader_browsertest.cc +++ b/chrome/browser/chromeos/customization/customization_wallpaper_downloader_browsertest.cc
@@ -6,7 +6,7 @@ #include <vector> -#include "ash/public/cpp/wallpaper_controller_observer.h" +#include "ash/public/interfaces/wallpaper.mojom.h" #include "base/bind.h" #include "base/command_line.h" #include "base/macros.h" @@ -20,6 +20,7 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/testing_browser_process.h" #include "chromeos/constants/chromeos_switches.h" +#include "mojo/public/cpp/bindings/associated_binding.h" #include "net/http/http_response_headers.h" #include "net/http/http_status_code.h" #include "net/test/embedded_test_server/http_response.h" @@ -120,22 +121,27 @@ return true; } -class TestWallpaperObserver : public ash::WallpaperControllerObserver { +class TestWallpaperObserver : public ash::mojom::WallpaperObserver { public: - TestWallpaperObserver() { - WallpaperControllerClient::Get()->AddObserver(this); + TestWallpaperObserver() : finished_(false), observer_binding_(this) { + ash::mojom::WallpaperObserverAssociatedPtrInfo ptr_info; + observer_binding_.Bind(mojo::MakeRequest(&ptr_info)); + WallpaperControllerClient::Get()->AddObserver(std::move(ptr_info)); } - ~TestWallpaperObserver() override { - WallpaperControllerClient::Get()->RemoveObserver(this); - } + ~TestWallpaperObserver() override = default; - // ash::WallpaperControllerObserver: - void OnWallpaperChanged() override { + // ash::mojom::WallpaperObserver: + void OnWallpaperChanged(uint32_t image_id) override { finished_ = true; base::RunLoop::QuitCurrentWhenIdleDeprecated(); } + void OnWallpaperColorsChanged( + const std::vector<SkColor>& prominent_colors) override {} + + void OnWallpaperBlurChanged(bool blurred) override {} + // Wait until the wallpaper update is completed. void WaitForWallpaperChanged() { while (!finished_) @@ -145,7 +151,10 @@ void Reset() { finished_ = false; } private: - bool finished_ = false; + bool finished_; + + // The binding this instance uses to implement ash::mojom::WallpaperObserver. + mojo::AssociatedBinding<ash::mojom::WallpaperObserver> observer_binding_; DISALLOW_COPY_AND_ASSIGN(TestWallpaperObserver); }; @@ -254,8 +263,13 @@ // Verify the customized default wallpaper has replaced the built-in default // wallpaper. - gfx::ImageSkia image = WallpaperControllerClient::Get()->GetWallpaperImage(); - EXPECT_TRUE(ImageIsNearColor(image, kCustomizedDefaultWallpaperColor)); + base::RunLoop run_loop; + WallpaperControllerClient::Get()->GetWallpaperImage( + base::BindLambdaForTesting([&run_loop](const gfx::ImageSkia& image) { + run_loop.Quit(); + EXPECT_TRUE(ImageIsNearColor(image, kCustomizedDefaultWallpaperColor)); + })); + run_loop.Run(); EXPECT_EQ(1U, num_attempts()); } @@ -281,8 +295,13 @@ // Verify the customized default wallpaper has replaced the built-in default // wallpaper. - gfx::ImageSkia image = WallpaperControllerClient::Get()->GetWallpaperImage(); - EXPECT_TRUE(ImageIsNearColor(image, kCustomizedDefaultWallpaperColor)); + base::RunLoop run_loop; + WallpaperControllerClient::Get()->GetWallpaperImage( + base::BindLambdaForTesting([&run_loop](const gfx::ImageSkia& image) { + run_loop.Quit(); + EXPECT_TRUE(ImageIsNearColor(image, kCustomizedDefaultWallpaperColor)); + })); + run_loop.Run(); EXPECT_EQ(2U, num_attempts()); }
diff --git a/chrome/browser/chromeos/extensions/wallpaper_private_api.cc b/chrome/browser/chromeos/extensions/wallpaper_private_api.cc index 0e856811..bc5b9ce7 100644 --- a/chrome/browser/chromeos/extensions/wallpaper_private_api.cc +++ b/chrome/browser/chromeos/extensions/wallpaper_private_api.cc
@@ -58,6 +58,8 @@ wallpaper_private::SetCustomWallpaperLayout; namespace get_thumbnail = wallpaper_private::GetThumbnail; namespace save_thumbnail = wallpaper_private::SaveThumbnail; +namespace get_offline_wallpaper_list = + wallpaper_private::GetOfflineWallpaperList; namespace record_wallpaper_uma = wallpaper_private::RecordWallpaperUMA; namespace get_collections_info = wallpaper_private::GetCollectionsInfo; namespace get_images_info = wallpaper_private::GetImagesInfo; @@ -241,12 +243,20 @@ wallpaper_api_util::kCancelWallpaperMessage); dict->SetString("highResolutionSuffix", GetBackdropWallpaperSuffix()); - auto info = WallpaperControllerClient::Get()->GetActiveUserWallpaperInfo(); - dict->SetString("currentWallpaper", info.location); - dict->SetString("currentWallpaperLayout", - wallpaper_api_util::GetLayoutString(info.layout)); + WallpaperControllerClient::Get()->GetActiveUserWallpaperInfo(base::BindOnce( + &WallpaperPrivateGetStringsFunction::OnWallpaperInfoReturned, this, + std::move(dict))); + return RespondLater(); +} - return RespondNow(OneArgument(std::move(dict))); +void WallpaperPrivateGetStringsFunction::OnWallpaperInfoReturned( + std::unique_ptr<base::DictionaryValue> dict, + const std::string& location, + ash::WallpaperLayout layout) { + dict->SetString("currentWallpaper", location); + dict->SetString("currentWallpaperLayout", + wallpaper_api_util::GetLayoutString(layout)); + Respond(OneArgument(std::move(dict))); } ExtensionFunction::ResponseAction @@ -806,12 +816,20 @@ get_current_wallpaper_thumbnail::Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params); - auto image = WallpaperControllerClient::Get()->GetWallpaperImage(); - gfx::Size thumbnail_size(params->thumbnail_width, params->thumbnail_height); + WallpaperControllerClient::Get()->GetWallpaperImage(base::BindOnce( + &WallpaperPrivateGetCurrentWallpaperThumbnailFunction:: + OnWallpaperImageReturned, + this, gfx::Size(params->thumbnail_width, params->thumbnail_height))); + return RespondLater(); +} + +void WallpaperPrivateGetCurrentWallpaperThumbnailFunction:: + OnWallpaperImageReturned(const gfx::Size& thumbnail_size, + const gfx::ImageSkia& image) { image.EnsureRepsForSupportedScales(); scoped_refptr<base::RefCountedBytes> thumbnail_data; GenerateThumbnail(image, thumbnail_size, &thumbnail_data); - return RespondNow(OneArgument(std::make_unique<Value>( + Respond(OneArgument(std::make_unique<Value>( Value::BlobStorage(thumbnail_data->front(), thumbnail_data->front() + thumbnail_data->size())))); }
diff --git a/chrome/browser/chromeos/extensions/wallpaper_private_api.h b/chrome/browser/chromeos/extensions/wallpaper_private_api.h index 5c2a757..50ddaee 100644 --- a/chrome/browser/chromeos/extensions/wallpaper_private_api.h +++ b/chrome/browser/chromeos/extensions/wallpaper_private_api.h
@@ -31,6 +31,12 @@ // ExtensionFunction: ResponseAction Run() override; + + private: + // Responds with the dictionary after getting the wallpaper info. + void OnWallpaperInfoReturned(std::unique_ptr<base::DictionaryValue> dict, + const std::string& location, + ash::WallpaperLayout layout); }; // Check if sync themes setting is enabled. @@ -411,6 +417,10 @@ ResponseAction Run() override; private: + // Responds with the thumbnail data. + void OnWallpaperImageReturned(const gfx::Size& thumbnail_size, + const gfx::ImageSkia& image); + // WallpaperFunctionBase: void OnWallpaperDecoded(const gfx::ImageSkia& wallpaper) override;
diff --git a/chrome/browser/chromeos/extensions/wallpaper_private_api_unittest.cc b/chrome/browser/chromeos/extensions/wallpaper_private_api_unittest.cc index 4f64fe0..5c051c99 100644 --- a/chrome/browser/chromeos/extensions/wallpaper_private_api_unittest.cc +++ b/chrome/browser/chromeos/extensions/wallpaper_private_api_unittest.cc
@@ -71,7 +71,7 @@ ScopedTestingLocalState local_state(TestingBrowserProcess::GetGlobal()); WallpaperControllerClient client; TestWallpaperController test_controller; - client.InitForTesting(&test_controller); + client.InitForTesting(test_controller.CreateInterfacePtr()); fake_user_manager()->AddUser(AccountId::FromUserEmail(kTestAccount)); { @@ -81,6 +81,7 @@ extensions::api_test_utils::RunFunction(function.get(), "[]", nullptr)); } + client.FlushForTesting(); // Expect SetDefaultWallpaper() to be called exactly once. EXPECT_EQ(1, test_controller.set_default_wallpaper_count()); }
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_session_unittest.cc b/chrome/browser/chromeos/login/demo_mode/demo_session_unittest.cc index 338b7919..c2a6cd3 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_session_unittest.cc +++ b/chrome/browser/chromeos/login/demo_mode/demo_session_unittest.cc
@@ -82,7 +82,8 @@ session_manager_ = std::make_unique<session_manager::SessionManager>(); wallpaper_controller_client_ = std::make_unique<WallpaperControllerClient>(); - wallpaper_controller_client_->InitForTesting(&test_wallpaper_controller_); + wallpaper_controller_client_->InitForTesting( + test_wallpaper_controller_.CreateInterfacePtr()); } void TearDown() override { @@ -433,12 +434,14 @@ test_wallpaper_controller_.remove_always_on_top_wallpaper_count()); session_manager_->SetSessionState( session_manager::SessionState::LOGIN_PRIMARY); + wallpaper_controller_client_->FlushForTesting(); EXPECT_EQ(0, test_wallpaper_controller_.show_always_on_top_wallpaper_count()); EXPECT_EQ(0, test_wallpaper_controller_.remove_always_on_top_wallpaper_count()); ASSERT_TRUE(FinishResourcesComponentLoad( base::FilePath(kTestDemoModeResourcesMountPoint))); + wallpaper_controller_client_->FlushForTesting(); EXPECT_EQ(1, test_wallpaper_controller_.show_always_on_top_wallpaper_count()); EXPECT_EQ(0, test_wallpaper_controller_.remove_always_on_top_wallpaper_count()); @@ -457,11 +460,13 @@ profile, new ChromeAppDelegate(true /* keep_alive */), screensaver_app.get()); demo_session->OnAppWindowActivated(app_window); + wallpaper_controller_client_->FlushForTesting(); // The splash screen is not removed until active session starts. EXPECT_EQ(1, test_wallpaper_controller_.show_always_on_top_wallpaper_count()); EXPECT_EQ(0, test_wallpaper_controller_.remove_always_on_top_wallpaper_count()); session_manager_->SetSessionState(session_manager::SessionState::ACTIVE); + wallpaper_controller_client_->FlushForTesting(); EXPECT_EQ(1, test_wallpaper_controller_.show_always_on_top_wallpaper_count()); EXPECT_EQ(1, test_wallpaper_controller_.remove_always_on_top_wallpaper_count()); @@ -484,12 +489,14 @@ test_wallpaper_controller_.remove_always_on_top_wallpaper_count()); session_manager_->SetSessionState( session_manager::SessionState::LOGIN_PRIMARY); + wallpaper_controller_client_->FlushForTesting(); EXPECT_EQ(0, test_wallpaper_controller_.show_always_on_top_wallpaper_count()); EXPECT_EQ(0, test_wallpaper_controller_.remove_always_on_top_wallpaper_count()); ASSERT_TRUE(FinishResourcesComponentLoad( base::FilePath(kTestDemoModeResourcesMountPoint))); + wallpaper_controller_client_->FlushForTesting(); EXPECT_EQ(1, test_wallpaper_controller_.show_always_on_top_wallpaper_count()); EXPECT_EQ(0, test_wallpaper_controller_.remove_always_on_top_wallpaper_count()); @@ -498,6 +505,7 @@ static_cast<base::MockOneShotTimer*>(demo_session->GetTimerForTesting()); ASSERT_TRUE(timer_ptr); timer_ptr->Fire(); + wallpaper_controller_client_->FlushForTesting(); EXPECT_EQ(1, test_wallpaper_controller_.show_always_on_top_wallpaper_count()); EXPECT_EQ(1, test_wallpaper_controller_.remove_always_on_top_wallpaper_count()); @@ -517,11 +525,13 @@ profile, new ChromeAppDelegate(true /* keep_alive */), screensaver_app.get()); demo_session->OnAppWindowActivated(app_window); + wallpaper_controller_client_->FlushForTesting(); EXPECT_EQ(1, test_wallpaper_controller_.show_always_on_top_wallpaper_count()); EXPECT_EQ(1, test_wallpaper_controller_.remove_always_on_top_wallpaper_count()); // Entering active session will not trigger splash screen removal anymore. session_manager_->SetSessionState(session_manager::SessionState::ACTIVE); + wallpaper_controller_client_->FlushForTesting(); EXPECT_EQ(1, test_wallpaper_controller_.show_always_on_top_wallpaper_count()); EXPECT_EQ(1, test_wallpaper_controller_.remove_always_on_top_wallpaper_count());
diff --git a/chrome/browser/chromeos/login/kiosk_browsertest.cc b/chrome/browser/chromeos/login/kiosk_browsertest.cc index dfdedf6..9a1bdbcc 100644 --- a/chrome/browser/chromeos/login/kiosk_browsertest.cc +++ b/chrome/browser/chromeos/login/kiosk_browsertest.cc
@@ -8,8 +8,8 @@ #include "apps/test/app_window_waiter.h" #include "ash/public/cpp/ash_switches.h" #include "ash/public/cpp/keyboard/keyboard_switches.h" -#include "ash/public/cpp/wallpaper_controller_observer.h" #include "ash/public/interfaces/login_screen_test_api.test-mojom-test-utils.h" +#include "ash/public/interfaces/wallpaper.mojom.h" #include "base/bind.h" #include "base/bind_helpers.h" #include "base/json/json_reader.h" @@ -92,6 +92,7 @@ #include "google_apis/gaia/gaia_switches.h" #include "google_apis/gaia/gaia_urls.h" #include "media/audio/test_audio_thread.h" +#include "mojo/public/cpp/bindings/associated_binding.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "services/audio/public/cpp/fake_system_info.h" #include "services/audio/public/cpp/sounds/audio_stream_handler.h" @@ -2476,19 +2477,20 @@ // Specialized test fixture for testing kiosk mode on the // hidden WebUI initialization flow for slow hardware. class KioskHiddenWebUITest : public KioskTest, - public ash::WallpaperControllerObserver { + public ash::mojom::WallpaperObserver { public: - KioskHiddenWebUITest() = default; + KioskHiddenWebUITest() : wallpaper_loaded_(false), observer_binding_(this) {} - // KioskTest: void SetUpOnMainThread() override { LoginDisplayHostWebUI::DisableRestrictiveProxyCheckForTest(); KioskTest::SetUpOnMainThread(); - WallpaperControllerClient::Get()->AddObserver(this); + ash::mojom::WallpaperObserverAssociatedPtrInfo ptr_info; + observer_binding_.Bind(mojo::MakeRequest(&ptr_info)); + WallpaperControllerClient::Get()->AddObserver(std::move(ptr_info)); } + void TearDownOnMainThread() override { - WallpaperControllerClient::Get()->RemoveObserver(this); KioskTest::TearDownOnMainThread(); } @@ -2501,17 +2503,25 @@ bool wallpaper_loaded() const { return wallpaper_loaded_; } - // ash::WallpaperControllerObserver: - void OnWallpaperChanged() override { + // ash::mojom::WallpaperObserver: + void OnWallpaperChanged(uint32_t image_id) override { wallpaper_loaded_ = true; if (runner_.get()) runner_->Quit(); } - private: - bool wallpaper_loaded_ = false; + void OnWallpaperColorsChanged( + const std::vector<SkColor>& prominent_colors) override {} + + void OnWallpaperBlurChanged(bool blurred) override {} + + bool wallpaper_loaded_; scoped_refptr<content::MessageLoopRunner> runner_; + private: + // The binding this instance uses to implement ash::mojom::WallpaperObserver. + mojo::AssociatedBinding<ash::mojom::WallpaperObserver> observer_binding_; + DISALLOW_COPY_AND_ASSIGN(KioskHiddenWebUITest); };
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc index 5f71b564..6b8b4e1 100644 --- a/chrome/browser/chromeos/login/session/user_session_manager.cc +++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -82,7 +82,7 @@ #include "chrome/browser/chromeos/tether/tether_service.h" #include "chrome/browser/chromeos/tpm_firmware_update_notification.h" #include "chrome/browser/component_updater/crl_set_component_installer.h" -#include "chrome/browser/component_updater/sth_set_component_installer.h" +#include "chrome/browser/component_updater/sth_set_component_remover.h" #include "chrome/browser/first_run/first_run.h" #include "chrome/browser/google/google_brand_chromeos.h" #include "chrome/browser/lifetime/application_lifetime.h" @@ -1852,8 +1852,8 @@ const user_manager::User* user) { const std::string username_hash = user->username_hash(); if (!username_hash.empty()) { - base::FilePath path; - path = ProfileHelper::GetProfilePathByUserIdHash(username_hash); + base::FilePath path = + ProfileHelper::GetProfilePathByUserIdHash(username_hash); component_updater::ComponentUpdateService* cus = g_browser_process->component_updater(); if (cus) @@ -1864,13 +1864,10 @@ void UserSessionManager::InitializeCertificateTransparencyComponents( const user_manager::User* user) { const std::string username_hash = user->username_hash(); - component_updater::ComponentUpdateService* cus = - g_browser_process->component_updater(); - if (!username_hash.empty() && cus) { - const base::FilePath path = + if (!username_hash.empty()) { + base::FilePath path = ProfileHelper::GetProfilePathByUserIdHash(username_hash); - // STH set fetcher. - RegisterSTHSetComponent(cus, path); + component_updater::DeleteLegacySTHSet(path); } }
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.h b/chrome/browser/chromeos/login/session/user_session_manager.h index faf0f2c1..7aa0b09 100644 --- a/chrome/browser/chromeos/login/session/user_session_manager.h +++ b/chrome/browser/chromeos/login/session/user_session_manager.h
@@ -209,8 +209,7 @@ // Starts loading CRL set. void InitializeCRLSetFetcher(const user_manager::User* user); - // Starts loading CT-related components, which are the EV Certificates - // whitelist and the STHSet. + // Initializes Certificate Transparency-related components. void InitializeCertificateTransparencyComponents( const user_manager::User* user);
diff --git a/chrome/browser/chromeos/login/signin_partition_manager_unittest.cc b/chrome/browser/chromeos/login/signin_partition_manager_unittest.cc index a1c2a45..8475ec9 100644 --- a/chrome/browser/chromeos/login/signin_partition_manager_unittest.cc +++ b/chrome/browser/chromeos/login/signin_partition_manager_unittest.cc
@@ -103,6 +103,8 @@ } void TearDown() override { + system_network_context_.reset(); + signin_ui_web_contents_.reset(); signin_browser_context_.reset();
diff --git a/chrome/browser/chromeos/login/user_board_view_mojo.cc b/chrome/browser/chromeos/login/user_board_view_mojo.cc index e206b19..fbe1b6a 100644 --- a/chrome/browser/chromeos/login/user_board_view_mojo.cc +++ b/chrome/browser/chromeos/login/user_board_view_mojo.cc
@@ -104,11 +104,7 @@ // warning banner message. // TODO(fukino): Remove ShowWarningMessage and related implementation along // with the migration screen once the transition to ext4 is compilete. - if (!message.empty()) { - LoginScreenClient::Get()->login_screen()->ShowWarningBanner(message); - } else { - LoginScreenClient::Get()->login_screen()->HideWarningBanner(); - } + ash::LoginScreen::Get()->GetModel()->UpdateWarningMessage(message); } void UserBoardViewMojo::ShowUserPodCustomIcon(
diff --git a/chrome/browser/chromeos/login/users/user_manager_unittest.cc b/chrome/browser/chromeos/login/users/user_manager_unittest.cc index 9830a82..9f73e62 100644 --- a/chrome/browser/chromeos/login/users/user_manager_unittest.cc +++ b/chrome/browser/chromeos/login/users/user_manager_unittest.cc
@@ -83,7 +83,8 @@ wallpaper_controller_client_ = std::make_unique<WallpaperControllerClient>(); - wallpaper_controller_client_->InitForTesting(&test_wallpaper_controller_); + wallpaper_controller_client_->InitForTesting( + test_wallpaper_controller_.CreateInterfacePtr()); } void TearDown() override { @@ -217,6 +218,7 @@ EXPECT_EQ(1U, users->size()); EXPECT_EQ((*users)[0]->GetAccountId(), owner_account_id_at_invalid_domain_); // Verify that the wallpaper is removed when user is removed. + wallpaper_controller_client_->FlushForTesting(); EXPECT_EQ(2, test_wallpaper_controller_.remove_user_wallpaper_count()); }
diff --git a/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc b/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc index 3f7ad74..553f95ec 100644 --- a/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc +++ b/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc
@@ -8,7 +8,7 @@ #include <string> #include <vector> -#include "ash/public/cpp/wallpaper_controller_observer.h" +#include "ash/public/interfaces/wallpaper.mojom.h" #include "base/bind.h" #include "base/command_line.h" #include "base/compiler_specific.h" @@ -56,6 +56,7 @@ #include "components/user_manager/user_names.h" #include "content/public/test/browser_test_utils.h" #include "crypto/rsa_private_key.h" +#include "mojo/public/cpp/bindings/associated_binding.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -129,7 +130,7 @@ } // namespace class WallpaperPolicyTest : public LoginManagerTest, - public ash::WallpaperControllerObserver { + public ash::mojom::WallpaperObserver { protected: WallpaperPolicyTest() : LoginManagerTest(true, true), @@ -203,7 +204,9 @@ void SetUpOnMainThread() override { LoginManagerTest::SetUpOnMainThread(); - WallpaperControllerClient::Get()->AddObserver(this); + ash::mojom::WallpaperObserverAssociatedPtrInfo ptr_info; + observer_binding_.Bind(mojo::MakeRequest(&ptr_info)); + WallpaperControllerClient::Get()->AddObserver(std::move(ptr_info)); // Set up policy signing. user_policy_builders_[0] = GetUserPolicyBuilder(testUsers_[0]); @@ -211,30 +214,45 @@ } void TearDownOnMainThread() override { - WallpaperControllerClient::Get()->RemoveObserver(this); LoginManagerTest::TearDownOnMainThread(); } // Obtain wallpaper image and return its average ARGB color. SkColor GetAverageWallpaperColor() { average_color_.reset(); - auto image = WallpaperControllerClient::Get()->GetWallpaperImage(); + WallpaperControllerClient::Get()->GetWallpaperImage( + base::BindOnce(&WallpaperPolicyTest::OnGetWallpaperImageCallback, + weak_ptr_factory_.GetWeakPtr())); + while (!average_color_.has_value()) { + run_loop_.reset(new base::RunLoop); + run_loop_->Run(); + } + return average_color_.value(); + } + + void OnGetWallpaperImageCallback(const gfx::ImageSkia& image) { const gfx::ImageSkiaRep& representation = image.GetRepresentation(1.0f); if (representation.is_null()) { ADD_FAILURE() << "No image representation."; average_color_ = SkColorSetARGB(0, 0, 0, 0); } average_color_ = ComputeAverageColor(representation.GetBitmap()); - return average_color_.value(); + if (run_loop_) + run_loop_->Quit(); } - // ash::WallpaperControllerObserver: - void OnWallpaperChanged() override { + // ash::mojom::WallpaperObserver: + void OnWallpaperChanged(uint32_t image_id) override { ++wallpaper_change_count_; if (run_loop_) run_loop_->Quit(); } + void OnWallpaperColorsChanged( + const std::vector<SkColor>& prominent_colors) override {} + + void OnWallpaperBlurChanged(bool blurred) override {} + // Runs the loop until wallpaper has changed to the expected color. void RunUntilWallpaperChangeToColor(const SkColor& expected_color) { while (expected_color != GetAverageWallpaperColor()) { @@ -317,6 +335,10 @@ &mixin_host_, DeviceStateMixin::State::OOBE_COMPLETED_CLOUD_ENROLLED}; private: + // The binding this instance uses to implement ash::mojom::WallpaperObserver. + mojo::AssociatedBinding<ash::mojom::WallpaperObserver> observer_binding_{ + this}; + // The average ARGB color of the current wallpaper. base::Optional<SkColor> average_color_;
diff --git a/chrome/browser/component_updater/sth_set_component_installer.cc b/chrome/browser/component_updater/sth_set_component_installer.cc deleted file mode 100644 index 2403050..0000000 --- a/chrome/browser/component_updater/sth_set_component_installer.cc +++ /dev/null
@@ -1,242 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/component_updater/sth_set_component_installer.h" - -#include <utility> - -#include "base/bind.h" -#include "base/files/file_enumerator.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/json/json_reader.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/no_destructor.h" -#include "base/path_service.h" -#include "base/sequenced_task_runner.h" -#include "base/strings/string_number_conversions.h" -#include "base/task/post_task.h" -#include "base/threading/scoped_blocking_call.h" -#include "base/threading/sequenced_task_runner_handle.h" -#include "base/values.h" -#include "base/version.h" -#include "components/certificate_transparency/sth_observer.h" -#include "components/component_updater/component_updater_paths.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/network_service_instance.h" -#include "crypto/sha2.h" -#include "net/cert/ct_log_response_parser.h" -#include "net/cert/signed_tree_head.h" -#include "services/network/network_service.h" -#include "services/service_manager/public/cpp/service.h" - -using component_updater::ComponentUpdateService; - -namespace { -const base::FilePath::CharType kSTHsDirName[] = FILE_PATH_LITERAL("sths"); - -network::mojom::NetworkService* g_network_service_for_testing = nullptr; - -base::FilePath& GetInstallDir() { - static base::NoDestructor<base::FilePath> install_dir; - return *install_dir; -} - -base::FilePath GetInstalledPath(const base::FilePath& base) { - return base.Append(FILE_PATH_LITERAL("_platform_specific")) - .Append(FILE_PATH_LITERAL("all")) - .Append(kSTHsDirName); -} - -// Loads the STHs from |sths_path|, which contains a series of files that -// are the in the form "[log_id].sth", where [log_id] is the hex-encoded ID -// of the log, and the contents are JSON STH. Parsed STHs will be posted to -// |callback| on |origin_task_runner|. -void LoadSTHsFromDisk( - const base::FilePath& sths_path, - scoped_refptr<base::SequencedTaskRunner> origin_task_runner, - base::RepeatingCallback<void(const net::ct::SignedTreeHead&)> callback) { - base::FileEnumerator sth_file_enumerator(sths_path, false, - base::FileEnumerator::FILES, - FILE_PATH_LITERAL("*.sth")); - base::FilePath sth_file_path; - - while (!(sth_file_path = sth_file_enumerator.Next()).empty()) { - DVLOG(1) << "Reading STH from file: " << sth_file_path.value(); - - const std::string log_id_hex = - sth_file_path.BaseName().RemoveExtension().MaybeAsASCII(); - if (log_id_hex.empty()) { - DVLOG(1) << "Error extracting log_id from: " - << sth_file_path.BaseName().LossyDisplayName(); - continue; - } - - std::vector<uint8_t> decoding_output; - if (!base::HexStringToBytes(log_id_hex, &decoding_output)) { - DVLOG(1) << "Failed to decode Log ID: " << log_id_hex; - continue; - } - - const std::string log_id( - reinterpret_cast<const char*>(decoding_output.data()), - decoding_output.size()); - - std::string json_sth; - { - base::ScopedBlockingCall scoped_blocking_call( - FROM_HERE, base::BlockingType::MAY_BLOCK); - if (!base::ReadFileToString(sth_file_path, &json_sth)) { - DVLOG(1) << "Failed reading from " << sth_file_path.value(); - continue; - } - } - - DVLOG(1) << "STH: Successfully read: " << json_sth; - - int error_code = 0; - std::string error_message; - std::unique_ptr<base::Value> parsed_json = - base::JSONReader::ReadAndReturnErrorDeprecated( - json_sth, base::JSON_PARSE_RFC, &error_code, &error_message); - - if (!parsed_json || error_code != base::JSONReader::JSON_NO_ERROR) { - DVLOG(1) << "STH loading failed: " << error_message << " for log: " - << base::HexEncode(log_id.data(), log_id.length()); - continue; - } - - DVLOG(1) << "STH parsing success for log: " - << base::HexEncode(log_id.data(), log_id.length()); - - net::ct::SignedTreeHead signed_tree_head; - if (!net::ct::FillSignedTreeHead(*parsed_json, &signed_tree_head)) { - LOG(ERROR) << "Failed to fill in signed tree head."; - continue; - } - - // The log id is not a part of the response, fill in manually. - signed_tree_head.log_id = log_id; - origin_task_runner->PostTask(FROM_HERE, - base::BindOnce(callback, signed_tree_head)); - } -} - -// Indicates that a new STH has been loaded. -void OnSTHLoaded(const net::ct::SignedTreeHead& sth) { - network::mojom::NetworkService* network_service = - g_network_service_for_testing ? g_network_service_for_testing - : content::GetNetworkService(); - network_service->UpdateSignedTreeHead(sth); -} - -} // namespace - -namespace component_updater { - -// The SHA256 of the SubjectPublicKeyInfo used to sign the extension. -// The extension id is: ojjgnpkioondelmggbekfhllhdaimnho -const uint8_t kSthSetPublicKeySHA256[32] = { - 0xe9, 0x96, 0xdf, 0xa8, 0xee, 0xd3, 0x4b, 0xc6, 0x61, 0x4a, 0x57, - 0xbb, 0x73, 0x08, 0xcd, 0x7e, 0x51, 0x9b, 0xcc, 0x69, 0x08, 0x41, - 0xe1, 0x96, 0x9f, 0x7c, 0xb1, 0x73, 0xef, 0x16, 0x80, 0x0a}; - -const char kSTHSetFetcherManifestName[] = "Signed Tree Heads"; - -STHSetComponentInstallerPolicy::STHSetComponentInstallerPolicy() {} - -STHSetComponentInstallerPolicy::~STHSetComponentInstallerPolicy() = default; - -// static -void STHSetComponentInstallerPolicy::ReconfigureAfterNetworkRestart() { - if (!GetInstallDir().empty()) - ConfigureNetworkService(); -} - -void STHSetComponentInstallerPolicy::SetNetworkServiceForTesting( - network::mojom::NetworkService* network_service) { - DCHECK(network_service); - g_network_service_for_testing = network_service; -} - -bool STHSetComponentInstallerPolicy:: - SupportsGroupPolicyEnabledComponentUpdates() const { - return false; -} - -// Public data is delivered via this component, no need for encryption. -bool STHSetComponentInstallerPolicy::RequiresNetworkEncryption() const { - return false; -} - -update_client::CrxInstaller::Result -STHSetComponentInstallerPolicy::OnCustomInstall( - const base::DictionaryValue& manifest, - const base::FilePath& install_dir) { - return update_client::CrxInstaller::Result(0); // Nothing custom here. -} - -void STHSetComponentInstallerPolicy::OnCustomUninstall() {} - -void STHSetComponentInstallerPolicy::ComponentReady( - const base::Version& version, - const base::FilePath& install_dir, - std::unique_ptr<base::DictionaryValue> manifest) { - GetInstallDir() = install_dir; - ConfigureNetworkService(); -} - -// Called during startup and installation before ComponentReady(). -bool STHSetComponentInstallerPolicy::VerifyInstallation( - const base::DictionaryValue& manifest, - const base::FilePath& install_dir) const { - return base::PathExists(GetInstalledPath(install_dir)); -} - -base::FilePath STHSetComponentInstallerPolicy::GetRelativeInstallDir() const { - return base::FilePath(FILE_PATH_LITERAL("CertificateTransparency")); -} - -void STHSetComponentInstallerPolicy::GetHash(std::vector<uint8_t>* hash) const { - hash->assign(std::begin(kSthSetPublicKeySHA256), - std::end(kSthSetPublicKeySHA256)); -} - -std::string STHSetComponentInstallerPolicy::GetName() const { - return kSTHSetFetcherManifestName; -} - -update_client::InstallerAttributes -STHSetComponentInstallerPolicy::GetInstallerAttributes() const { - return update_client::InstallerAttributes(); -} - -std::vector<std::string> STHSetComponentInstallerPolicy::GetMimeTypes() const { - return std::vector<std::string>(); -} - -// static -void STHSetComponentInstallerPolicy::ConfigureNetworkService() { - // Load and parse the STH JSON on a background task runner, then - // dispatch back to the current task runner with all of the successfully - // parsed results. - auto background_runner = base::CreateTaskRunnerWithTraits( - {base::TaskPriority::BEST_EFFORT, base::MayBlock()}); - content::BrowserThread::PostAfterStartupTask( - FROM_HERE, background_runner, - base::BindOnce(&LoadSTHsFromDisk, GetInstalledPath(GetInstallDir()), - base::SequencedTaskRunnerHandle::Get(), - base::BindRepeating(OnSTHLoaded))); -} - -void RegisterSTHSetComponent(ComponentUpdateService* cus, - const base::FilePath& user_data_dir) { - DVLOG(1) << "Registering STH Set fetcher component."; - auto installer = base::MakeRefCounted<ComponentInstaller>( - std::make_unique<STHSetComponentInstallerPolicy>()); - installer->Register(cus, base::Closure()); -} - -} // namespace component_updater
diff --git a/chrome/browser/component_updater/sth_set_component_installer.h b/chrome/browser/component_updater/sth_set_component_installer.h deleted file mode 100644 index 9d3b05c1..0000000 --- a/chrome/browser/component_updater/sth_set_component_installer.h +++ /dev/null
@@ -1,79 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_COMPONENT_UPDATER_STH_SET_COMPONENT_INSTALLER_H_ -#define CHROME_BROWSER_COMPONENT_UPDATER_STH_SET_COMPONENT_INSTALLER_H_ - -#include <stdint.h> - -#include <memory> -#include <string> -#include <vector> - -#include "base/gtest_prod_util.h" -#include "base/memory/weak_ptr.h" -#include "components/component_updater/component_installer.h" - -namespace network { -namespace mojom { -class NetworkService; -} // namespace mojom -} // namespace network - -namespace component_updater { - -class ComponentUpdateService; - -// Component for receiving Signed Tree Heads updates for Certificate -// Transparency logs recognized in Chrome. -// The STHs are in JSON format. -// To identify the log each STH belongs to, the name of the file is -// hex-encoded Log ID of the log that produced this STH. -// -// Notifications of each of the new STHs are sent to the -// certificate_transparency::STHObserver, on the same task runner that this -// object is created, so that it can take appropriate steps, including possible -// persistence. -class STHSetComponentInstallerPolicy : public ComponentInstallerPolicy { - public: - STHSetComponentInstallerPolicy(); - ~STHSetComponentInstallerPolicy() override; - - // Update the STHs after a network process crash. - static void ReconfigureAfterNetworkRestart(); - - private: - friend class STHSetComponentInstallerTest; - void SetNetworkServiceForTesting( - network::mojom::NetworkService* network_service); - - // ComponentInstallerPolicy implementation. - bool SupportsGroupPolicyEnabledComponentUpdates() const override; - bool RequiresNetworkEncryption() const override; - update_client::CrxInstaller::Result OnCustomInstall( - const base::DictionaryValue& manifest, - const base::FilePath& install_dir) override; - void OnCustomUninstall() override; - bool VerifyInstallation(const base::DictionaryValue& manifest, - const base::FilePath& install_dir) const override; - void ComponentReady(const base::Version& version, - const base::FilePath& install_dir, - std::unique_ptr<base::DictionaryValue> manifest) override; - base::FilePath GetRelativeInstallDir() const override; - void GetHash(std::vector<uint8_t>* hash) const override; - std::string GetName() const override; - update_client::InstallerAttributes GetInstallerAttributes() const override; - std::vector<std::string> GetMimeTypes() const override; - - static void ConfigureNetworkService(); - - DISALLOW_COPY_AND_ASSIGN(STHSetComponentInstallerPolicy); -}; - -void RegisterSTHSetComponent(ComponentUpdateService* cus, - const base::FilePath& user_data_dir); - -} // namespace component_updater - -#endif // CHROME_BROWSER_COMPONENT_UPDATER_STH_SET_COMPONENT_INSTALLER_H_
diff --git a/chrome/browser/component_updater/sth_set_component_installer_unittest.cc b/chrome/browser/component_updater/sth_set_component_installer_unittest.cc deleted file mode 100644 index 80911869..0000000 --- a/chrome/browser/component_updater/sth_set_component_installer_unittest.cc +++ /dev/null
@@ -1,196 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/component_updater/sth_set_component_installer.h" - -#include <map> -#include <memory> -#include <string> - -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/files/scoped_temp_dir.h" -#include "base/macros.h" -#include "base/run_loop.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "base/values.h" -#include "base/version.h" -#include "components/certificate_transparency/sth_observer.h" -#include "components/certificate_transparency/sth_reporter.h" -#include "content/public/test/test_browser_thread_bundle.h" -#include "net/cert/signed_tree_head.h" -#include "net/test/ct_test_util.h" -#include "services/data_decoder/public/cpp/testing_json_parser.h" -#include "services/network/network_service.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/platform_test.h" - -namespace component_updater { - -class StoringSTHObserver : public certificate_transparency::STHObserver { - public: - void NewSTHObserved(const net::ct::SignedTreeHead& sth) override { - sths[sth.log_id] = sth; - } - - std::map<std::string, net::ct::SignedTreeHead> sths; -}; - -class STHSetComponentInstallerTest : public PlatformTest { - public: - STHSetComponentInstallerTest() - : network_service_(std::make_unique<network::NetworkService>(nullptr)) { - network_service_->sth_reporter()->RegisterObserver(&observer_); - } - - ~STHSetComponentInstallerTest() override { - network_service_->sth_reporter()->UnregisterObserver(&observer_); - } - - void SetUp() override { - PlatformTest::SetUp(); - - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - - policy_ = std::make_unique<STHSetComponentInstallerPolicy>(); - policy_->SetNetworkServiceForTesting(network_service_.get()); - } - - void SimulateCrash() { - network_service_->sth_reporter()->UnregisterObserver(&observer_); - observer_.sths.clear(); - network_service_.reset(); - network_service_ = std::make_unique<network::NetworkService>(nullptr); - network_service_->sth_reporter()->RegisterObserver(&observer_); - policy_->SetNetworkServiceForTesting(network_service_.get()); - } - - void WriteSTHToFile(const std::string& sth_json, - const base::FilePath& filename) { - ASSERT_EQ(static_cast<int32_t>(sth_json.length()), - base::WriteFile(filename, sth_json.data(), sth_json.length())); - } - - base::FilePath GetSTHsDir() { - return temp_dir_.GetPath() - .Append(FILE_PATH_LITERAL("_platform_specific")) - .Append(FILE_PATH_LITERAL("all")) - .Append(FILE_PATH_LITERAL("sths")); - } - - void CreateSTHsDir(const base::DictionaryValue& manifest, - const base::FilePath& sths_dir) { - ASSERT_FALSE(policy_->VerifyInstallation(manifest, temp_dir_.GetPath())); - ASSERT_TRUE(base::CreateDirectory(sths_dir)); - } - - void LoadSTHs(const base::DictionaryValue& manifest, - const base::FilePath& sths_dir) { - ASSERT_TRUE(policy_->VerifyInstallation(manifest, temp_dir_.GetPath())); - - const base::Version v("1.0"); - policy_->ComponentReady(v, temp_dir_.GetPath(), manifest.CreateDeepCopy()); - // Drain the RunLoop created by the TestBrowserThreadBundle - thread_bundle_.RunUntilIdle(); - } - - protected: - content::TestBrowserThreadBundle thread_bundle_; - - std::unique_ptr<network::NetworkService> network_service_; - StoringSTHObserver observer_; - - base::ScopedTempDir temp_dir_; - std::unique_ptr<STHSetComponentInstallerPolicy> policy_; - data_decoder::TestingJsonParser::ScopedFactoryOverride factory_override_; - - private: - DISALLOW_COPY_AND_ASSIGN(STHSetComponentInstallerTest); -}; - -// Parses valid STH JSON in a file with valid hex encoding of log id. -TEST_F(STHSetComponentInstallerTest, CanLoadAllSTHs) { - const base::DictionaryValue manifest; - const base::FilePath sths_dir(GetSTHsDir()); - CreateSTHsDir(manifest, sths_dir); - - const std::string good_sth_json = net::ct::GetSampleSTHAsJson(); - const base::FilePath first_sth_file = - sths_dir.Append(FILE_PATH_LITERAL("616263.sth")); - WriteSTHToFile(good_sth_json, first_sth_file); - - const base::FilePath second_sth_file = - sths_dir.Append(FILE_PATH_LITERAL("610064.sth")); - WriteSTHToFile(good_sth_json, second_sth_file); - - LoadSTHs(manifest, sths_dir); - - EXPECT_EQ(2u, observer_.sths.size()); - - const std::string first_log_id("abc"); - ASSERT_TRUE(observer_.sths.find(first_log_id) != observer_.sths.end()); - const net::ct::SignedTreeHead& first_sth(observer_.sths[first_log_id]); - EXPECT_EQ(21u, first_sth.tree_size); - - const std::string second_log_id("a\00d", 3); - ASSERT_TRUE(observer_.sths.find(second_log_id) != observer_.sths.end()); -} - -// Does not notify of invalid STH JSON. -TEST_F(STHSetComponentInstallerTest, DoesNotLoadInvalidJSON) { - const base::DictionaryValue manifest; - const base::FilePath sths_dir(GetSTHsDir()); - CreateSTHsDir(manifest, sths_dir); - - const base::FilePath invalid_sth = - sths_dir.Append(FILE_PATH_LITERAL("010101.sth")); - WriteSTHToFile(std::string("{invalid json}"), invalid_sth); - - LoadSTHs(manifest, sths_dir); - EXPECT_EQ(0u, observer_.sths.size()); -} - -// Does not notify of valid JSON but in a file not hex-encoded log id. -TEST_F(STHSetComponentInstallerTest, - DoesNotLoadValidJSONFromFileNotHexEncoded) { - const base::DictionaryValue manifest; - const base::FilePath sths_dir(GetSTHsDir()); - CreateSTHsDir(manifest, sths_dir); - - const base::FilePath not_hex_sth_file = - sths_dir.Append(FILE_PATH_LITERAL("nothex.sth")); - WriteSTHToFile(net::ct::GetSampleSTHAsJson(), not_hex_sth_file); - - LoadSTHs(manifest, sths_dir); - EXPECT_EQ(0u, observer_.sths.size()); -} - -// Tests recovery after network process crashes. -TEST_F(STHSetComponentInstallerTest, ReconfiguresAfterRestart) { - const base::DictionaryValue manifest; - const base::FilePath sths_dir(GetSTHsDir()); - CreateSTHsDir(manifest, sths_dir); - - const std::string good_sth_json = net::ct::GetSampleSTHAsJson(); - const base::FilePath sth_file = - sths_dir.Append(FILE_PATH_LITERAL("616263.sth")); - WriteSTHToFile(good_sth_json, sth_file); - - LoadSTHs(manifest, sths_dir); - - const std::string log_id("abc"); - ASSERT_TRUE(observer_.sths.find(log_id) != observer_.sths.end()); - const net::ct::SignedTreeHead& sth(observer_.sths[log_id]); - EXPECT_EQ(21u, sth.tree_size); - - // Simulate a Network Service crash - SimulateCrash(); - STHSetComponentInstallerPolicy::ReconfigureAfterNetworkRestart(); - thread_bundle_.RunUntilIdle(); - - ASSERT_TRUE(observer_.sths.find(log_id) != observer_.sths.end()); -} - -} // namespace component_updater
diff --git a/chrome/browser/component_updater/sth_set_component_remover.cc b/chrome/browser/component_updater/sth_set_component_remover.cc new file mode 100644 index 0000000..2e3791c --- /dev/null +++ b/chrome/browser/component_updater/sth_set_component_remover.cc
@@ -0,0 +1,51 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/component_updater/sth_set_component_remover.h" + +#include "base/bind.h" +#include "base/files/file_enumerator.h" +#include "base/files/file_util.h" +#include "base/task/post_task.h" +#include "base/version.h" + +namespace component_updater { + +namespace { + +void CleanupOnWorker(const base::FilePath& sth_directory) { + const base::FilePath base_dir = sth_directory.DirName(); + base::FileEnumerator file_enumerator(base_dir, false, + base::FileEnumerator::DIRECTORIES); + for (base::FilePath path = file_enumerator.Next(); !path.value().empty(); + path = file_enumerator.Next()) { + base::Version version(path.BaseName().MaybeAsASCII()); + + // Ignore folders that don't have valid version names. These folders are + // not managed by the component installer, so don't try to remove them. + if (!version.IsValid()) + continue; + + if (!base::DeleteFile(path, true)) { + DLOG(ERROR) << "Couldn't delete " << path.value(); + } + } + + if (base::IsDirectoryEmpty(base_dir)) { + if (!base::DeleteFile(base_dir, false)) { + DLOG(ERROR) << "Couldn't delete " << base_dir.value(); + } + } +} + +} // namespace + +void DeleteLegacySTHSet(const base::FilePath& user_data_dir) { + base::PostTaskWithTraits( + FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()}, + base::BindOnce(&CleanupOnWorker, user_data_dir.Append(FILE_PATH_LITERAL( + "CertificateTransparency")))); +} + +} // namespace component_updater
diff --git a/chrome/browser/component_updater/sth_set_component_remover.h b/chrome/browser/component_updater/sth_set_component_remover.h new file mode 100644 index 0000000..51b028d --- /dev/null +++ b/chrome/browser/component_updater/sth_set_component_remover.h
@@ -0,0 +1,19 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_COMPONENT_UPDATER_STH_SET_COMPONENT_REMOVER_H_ +#define CHROME_BROWSER_COMPONENT_UPDATER_STH_SET_COMPONENT_REMOVER_H_ + +namespace base { +class FilePath; +} // namespace base + +namespace component_updater { + +// TODO(rsleevi): Remove in M86 or later. +void DeleteLegacySTHSet(const base::FilePath& user_data_dir); + +} // namespace component_updater + +#endif // CHROME_BROWSER_COMPONENT_UPDATER_STH_SET_COMPONENT_REMOVER_H_
diff --git a/chrome/browser/download/download_open_prompt.cc b/chrome/browser/download/download_open_prompt.cc index 19f0bc94..aac377f 100644 --- a/chrome/browser/download/download_open_prompt.cc +++ b/chrome/browser/download/download_open_prompt.cc
@@ -4,6 +4,9 @@ #include "chrome/browser/download/download_open_prompt.h" +#include <memory> +#include <utility> + #include "base/callback.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/ui/browser_dialogs.h" @@ -102,10 +105,11 @@ const std::string& extension_name, const base::FilePath& file_path, DownloadOpenPrompt::OpenCallback open_callback) { - DownloadOpenConfirmationDialog* prompt = new DownloadOpenConfirmationDialog( + auto prompt = std::make_unique<DownloadOpenConfirmationDialog>( web_contents, extension_name, file_path, std::move(open_callback)); - TabModalConfirmDialog::Create(prompt, web_contents); - return prompt; + DownloadOpenConfirmationDialog* prompt_observer = prompt.get(); + TabModalConfirmDialog::Create(std::move(prompt), web_contents); + return prompt_observer; } void DownloadOpenPrompt::AcceptConfirmationDialogForTesting(
diff --git a/chrome/browser/extensions/active_tab_unittest.cc b/chrome/browser/extensions/active_tab_unittest.cc index fd6031c..62a4b0c 100644 --- a/chrome/browser/extensions/active_tab_unittest.cc +++ b/chrome/browser/extensions/active_tab_unittest.cc
@@ -544,7 +544,8 @@ TestingBrowserProcess::GetGlobal()); wallpaper_controller_client_ = std::make_unique<WallpaperControllerClient>(); - wallpaper_controller_client_->InitForTesting(&test_wallpaper_controller_); + wallpaper_controller_client_->InitForTesting( + test_wallpaper_controller_.CreateInterfacePtr()); g_browser_process->local_state()->SetString( "PublicAccountPendingDataRemoval", user_email); user_manager::UserManager::Get()->UserLoggedIn(account_id, user_id_hash,
diff --git a/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_api_unittest.cc b/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_api_unittest.cc index 3c29f4d..9cff1e3 100644 --- a/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_api_unittest.cc +++ b/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_api_unittest.cc
@@ -114,6 +114,12 @@ browser()->tab_strip_model()->DetachWebContentsAt(0); browser_window_.reset(); content::BrowserSideNavigationTearDown(); + + // Make sure the NetworkContext owned by SafeBrowsingService is destructed + // before the NetworkService object.. + TestingBrowserProcess::GetGlobal()->safe_browsing_service()->ShutDown(); + TestingBrowserProcess::GetGlobal()->SetSafeBrowsingService(nullptr); + ExtensionServiceTestBase::TearDown(); }
diff --git a/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc b/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc index 3c0e379..b9b3e4f 100644 --- a/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc +++ b/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc
@@ -411,20 +411,8 @@ const GURL& effective_site_url) { const Extension* extension = GetEnabledExtensions(browser_or_resource_context) ->GetExtensionOrAppByURL(effective_site_url); - if (!extension) - return false; - - // Always isolate Chrome Web Store. - if (extension->id() == kWebStoreAppId) - return true; - - // Extensions should be isolated, except for hosted apps. Isolating hosted - // apps is a good idea, but ought to be a separate knob. - if (extension->is_hosted_app()) - return false; - // Isolate all extensions. - return true; + return extension != nullptr; } // static
diff --git a/chrome/browser/extensions/extension_apitest.cc b/chrome/browser/extensions/extension_apitest.cc index 65051af..5c903214 100644 --- a/chrome/browser/extensions/extension_apitest.cc +++ b/chrome/browser/extensions/extension_apitest.cc
@@ -259,6 +259,11 @@ browser_test_flags |= ExtensionBrowserTest::kFlagAllowOldManifestVersions; } + if (flags & kFlagRunAsServiceWorkerBasedExtension) { + browser_test_flags |= + ExtensionBrowserTest::kFlagRunAsServiceWorkerBasedExtension; + } + extension = LoadExtensionWithFlags(extension_path, browser_test_flags); } if (!extension) {
diff --git a/chrome/browser/extensions/extension_apitest.h b/chrome/browser/extensions/extension_apitest.h index 23400bc4..8253bf58 100644 --- a/chrome/browser/extensions/extension_apitest.h +++ b/chrome/browser/extensions/extension_apitest.h
@@ -61,6 +61,10 @@ // Load the extension using //extensions/test/data/ as the root path instead // of loading from //chrome/test/data/extensions/api_test/. kFlagUseRootExtensionsDir = 1 << 7, + + // Load the event page extension as a Service Worker based background + // extension. + kFlagRunAsServiceWorkerBasedExtension = 1 << 8, }; ExtensionApiTest();
diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc index d6e9c59..0c4199a5 100644 --- a/chrome/browser/extensions/extension_browsertest.cc +++ b/chrome/browser/extensions/extension_browsertest.cc
@@ -16,6 +16,7 @@ #include "base/files/scoped_temp_dir.h" #include "base/path_service.h" #include "base/run_loop.h" +#include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" @@ -67,8 +68,12 @@ #include "extensions/browser/notification_types.h" #include "extensions/browser/test_extension_registry_observer.h" #include "extensions/browser/uninstall_reason.h" +#include "extensions/common/constants.h" #include "extensions/common/extension_set.h" +#include "extensions/common/file_test_util.h" +#include "extensions/common/file_util.h" #include "extensions/common/switches.h" +#include "extensions/common/value_builder.h" #include "net/url_request/url_request_file_job.h" #if defined(OS_CHROMEOS) @@ -237,7 +242,12 @@ const Extension* ExtensionBrowserTest::LoadExtensionWithFlags( const base::FilePath& path, int flags) { - return LoadExtensionWithInstallParam(path, flags, std::string()); + base::FilePath extension_path = path; + if (flags & kFlagRunAsServiceWorkerBasedExtension) { + if (!CreateServiceWorkerBasedExtension(path, &extension_path)) + return nullptr; + } + return LoadExtensionWithInstallParam(extension_path, flags, std::string()); } const Extension* ExtensionBrowserTest::LoadExtensionWithInstallParam( @@ -258,6 +268,123 @@ return extension.get(); } +bool ExtensionBrowserTest::CreateServiceWorkerBasedExtension( + const base::FilePath& path, + base::FilePath* out_path) { + base::ScopedAllowBlockingForTesting allow_blocking; + + // This dir will contain all files for the Service Worker based extension. + base::FilePath temp_extension_container; + if (!base::CreateTemporaryDirInDir(temp_dir_.GetPath(), + base::FilePath::StringType(), + &temp_extension_container)) { + ADD_FAILURE() << "Could not create temporary dir for test under " + << temp_dir_.GetPath(); + return false; + } + + // Copy all files from test dir to temp dir. + if (!base::CopyDirectory(path, temp_extension_container, + true /* recursive */)) { + ADD_FAILURE() << path.value() << " could not be copied to " + << temp_extension_container.value(); + return false; + } + + const base::FilePath extension_root = + temp_extension_container.Append(path.BaseName()); + + std::string error; + std::unique_ptr<base::DictionaryValue> manifest_dict = + file_util::LoadManifest(extension_root, &error); + if (!manifest_dict) { + ADD_FAILURE() << path.value() << " could not load manifest: " << error; + return false; + } + + // Retrieve the value of the "background" key and verify that it is + // non-persistent and specifies JS files. + // Persistent background pages or background pages that specify HTML files + // are not supported. + base::Value* background_dict = + manifest_dict->FindKeyOfType("background", base::Value::Type::DICTIONARY); + if (!background_dict) { + ADD_FAILURE() << path.value() + << " 'background' key not found in manifest.json"; + return false; + } + { + base::Value* background_persistent = background_dict->FindKeyOfType( + "persistent", base::Value::Type::BOOLEAN); + if (!background_persistent || background_persistent->GetBool()) { + ADD_FAILURE() << path.value() + << ": Only event pages can be loaded as SW extension."; + return false; + } + } + base::Value* background_scripts_list = + background_dict->FindKeyOfType("scripts", base::Value::Type::LIST); + if (!background_scripts_list) { + ADD_FAILURE() << path.value() + << ": Only event pages with JS script(s) can be loaded " + "as SW extension."; + return false; + } + + // Number of JS scripts must be > 1. + base::Value::ListStorage& scripts_list = background_scripts_list->GetList(); + if (scripts_list.size() < 1) { + ADD_FAILURE() << path.value() + << ": Only event pages with JS script(s) can be loaded " + " as SW extension."; + return false; + } + + // Generate combined script as Service Worker script using importScripts(). + constexpr const char kGeneratedSWFileName[] = "generated_service_worker__.js"; + + std::vector<std::string> script_filenames; + for (const base::Value& script : scripts_list) + script_filenames.push_back(base::StrCat({"'", script.GetString(), "'"})); + + base::FilePath combined_script_filepath = + extension_root.AppendASCII(kGeneratedSWFileName); + // Collision with generated script filename. + if (base::PathExists(combined_script_filepath)) { + ADD_FAILURE() << combined_script_filepath.value() + << " already exists, make sure " << path.value() + << " does not contained file named " << kGeneratedSWFileName; + return false; + } + std::string generated_sw_script_content = base::StringPrintf( + "importScripts(%s);", base::JoinString(script_filenames, ",").c_str()); + if (!file_test_util::WriteFile(combined_script_filepath, + generated_sw_script_content)) { + ADD_FAILURE() << "Could not write combined Service Worker script to: " + << combined_script_filepath.value(); + return false; + } + + // Remove the existing background specification and replace it with a service + // worker. + background_dict->RemoveKey("persistent"); + background_dict->RemoveKey("scripts"); + background_dict->SetStringPath("service_worker", kGeneratedSWFileName); + + // Write out manifest.json. + DictionaryBuilder manifest_builder(*manifest_dict); + std::string manifest_contents = manifest_builder.ToJSON(); + base::FilePath manifest_path = extension_root.Append(kManifestFilename); + if (!file_test_util::WriteFile(manifest_path, manifest_contents)) { + ADD_FAILURE() << "Could not write manifest file to " + << manifest_path.value(); + return false; + } + + *out_path = extension_root; + return true; +} + const Extension* ExtensionBrowserTest::LoadExtensionAsComponentWithManifest( const base::FilePath& path, const base::FilePath::CharType* manifest_relative_path) {
diff --git a/chrome/browser/extensions/extension_browsertest.h b/chrome/browser/extensions/extension_browsertest.h index cd66718..e892d781 100644 --- a/chrome/browser/extensions/extension_browsertest.h +++ b/chrome/browser/extensions/extension_browsertest.h
@@ -62,6 +62,9 @@ // Allow older manifest versions (typically these can't be loaded - we allow // them for testing). kFlagAllowOldManifestVersions = 1 << 3, + + // Load the provided extension as Service Worker based extension. + kFlagRunAsServiceWorkerBasedExtension = 1 << 4, }; ExtensionBrowserTest(); @@ -117,6 +120,16 @@ int flags, const std::string& install_param); + // Converts an extension from |path| to a Service Worker based extension and + // returns true on success. + // If successful, |out_path| contains path of the converted extension. + // + // NOTE: The conversion works only for extensions with background.scripts and + // background.persistent = false; persistent background pages and + // background.page are not supported. + bool CreateServiceWorkerBasedExtension(const base::FilePath& path, + base::FilePath* out_path); + // Loads unpacked extension from |path| with manifest |manifest_relative_path| // and imitates that it is a component extension. // |manifest_relative_path| is relative to |path|.
diff --git a/chrome/browser/extensions/service_worker_apitest.cc b/chrome/browser/extensions/service_worker_apitest.cc index 504187e..99be1aa 100644 --- a/chrome/browser/extensions/service_worker_apitest.cc +++ b/chrome/browser/extensions/service_worker_apitest.cc
@@ -1777,6 +1777,13 @@ EXPECT_FALSE(ProcessManager::Get(profile())->HasServiceWorker(*worker_id)); } +IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, + ChromeRuntimeOpenOptionsPage) { + ASSERT_TRUE(RunExtensionTestWithFlags("runtime/open_options_page", + kFlagRunAsServiceWorkerBasedExtension)) + << message_; +} + // Tests that console messages logged by extension service workers, both via // the typical console.* methods and via our custom bindings console, are // passed through the normal ServiceWorker console messaging and are
diff --git a/chrome/browser/history/top_sites_factory.cc b/chrome/browser/history/top_sites_factory.cc index d83305c..3839498 100644 --- a/chrome/browser/history/top_sites_factory.cc +++ b/chrome/browser/history/top_sites_factory.cc
@@ -25,11 +25,14 @@ #include "chrome/grit/generated_resources.h" #include "chrome/grit/locale_settings.h" #include "chrome/grit/theme_resources.h" +#include "components/grit/components_scaled_resources.h" #include "components/history/core/browser/history_constants.h" #include "components/history/core/browser/top_sites_impl.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "components/ntp_tiles/features.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" +#include "components/strings/grit/components_strings.h" #include "content/public/browser/browser_thread.h" #include "ui/base/l10n/l10n_util.h" #include "url/gurl.h" @@ -53,6 +56,14 @@ #if !defined(OS_ANDROID) // Android does not use prepopulated pages. const RawPrepopulatedPage kRawPrepopulatedPages[] = { +#if defined(GOOGLE_CHROME_BUILD) + { + IDS_NTP_DEFAULT_SEARCH_URL, + IDS_NTP_DEFAULT_SEARCH_TITLE, + IDS_ONBOARDING_WELCOME_SEARCH, + SkColorSetRGB(63, 132, 197), + }, +#endif { IDS_WEBSTORE_URL, IDS_EXTENSION_WEB_STORE_TITLE_SHORT, @@ -73,6 +84,11 @@ const RawPrepopulatedPage& page = kRawPrepopulatedPages[i]; if (hide_web_store_icon && page.url_id == IDS_WEBSTORE_URL) continue; + if (page.url_id == IDS_NTP_DEFAULT_SEARCH_URL && + !base::FeatureList::IsEnabled(ntp_tiles::kDefaultSearchShortcut)) { + continue; + } + prepopulated_pages->push_back(history::PrepopulatedPage( GURL(l10n_util::GetStringUTF8(page.url_id)), l10n_util::GetStringUTF16(page.title_id), page.favicon_id, page.color));
diff --git a/chrome/browser/installable/installable_manager.cc b/chrome/browser/installable/installable_manager.cc index c47554b3..e53ba98 100644 --- a/chrome/browser/installable/installable_manager.cc +++ b/chrome/browser/installable/installable_manager.cc
@@ -577,11 +577,6 @@ return false; } - if (manifest.prefer_related_applications) { - is_valid = false; - valid_manifest_->errors.push_back(PREFER_RELATED_APPLICATIONS); - } - if (!manifest.start_url.is_valid()) { valid_manifest_->errors.push_back(START_URL_NOT_VALID); is_valid = false;
diff --git a/chrome/browser/installable/installable_manager_browsertest.cc b/chrome/browser/installable/installable_manager_browsertest.cc index e78d7d9..53725cf 100644 --- a/chrome/browser/installable/installable_manager_browsertest.cc +++ b/chrome/browser/installable/installable_manager_browsertest.cc
@@ -634,8 +634,7 @@ EXPECT_FALSE(tester->has_worker()); EXPECT_EQ( std::vector<InstallableStatusCode>( - {PREFER_RELATED_APPLICATIONS, START_URL_NOT_VALID, - MANIFEST_MISSING_NAME_OR_SHORT_NAME, + {START_URL_NOT_VALID, MANIFEST_MISSING_NAME_OR_SHORT_NAME, MANIFEST_DISPLAY_NOT_SUPPORTED, MANIFEST_MISSING_SUITABLE_ICON}), tester->errors()); } @@ -1629,8 +1628,7 @@ run_loop.Run(); EXPECT_EQ(std::vector<InstallableStatusCode>( - {PREFER_RELATED_APPLICATIONS, START_URL_NOT_VALID, - MANIFEST_MISSING_NAME_OR_SHORT_NAME, + {START_URL_NOT_VALID, MANIFEST_MISSING_NAME_OR_SHORT_NAME, MANIFEST_DISPLAY_NOT_SUPPORTED, MANIFEST_MISSING_SUITABLE_ICON, NO_URL_FOR_SERVICE_WORKER, NO_ACCEPTABLE_ICON}), tester->errors()); @@ -1652,8 +1650,7 @@ IN_PROC_BROWSER_TEST_F(InstallableManagerBrowserTest, GetAllErrorsWithPlayAppManifest) { EXPECT_EQ(std::vector<std::string>( - {GetErrorMessage(PREFER_RELATED_APPLICATIONS), - GetErrorMessage(START_URL_NOT_VALID), + {GetErrorMessage(START_URL_NOT_VALID), GetErrorMessage(MANIFEST_MISSING_NAME_OR_SHORT_NAME), GetErrorMessage(MANIFEST_DISPLAY_NOT_SUPPORTED), GetErrorMessage(MANIFEST_MISSING_SUITABLE_ICON),
diff --git a/chrome/browser/installable/installable_manager_unittest.cc b/chrome/browser/installable/installable_manager_unittest.cc index de3bfd8..4ae9bbb 100644 --- a/chrome/browser/installable/installable_manager_unittest.cc +++ b/chrome/browser/installable/installable_manager_unittest.cc
@@ -213,11 +213,3 @@ EXPECT_TRUE(IsManifestValid(manifest)); EXPECT_EQ(NO_ERROR_DETECTED, GetErrorCode()); } - -TEST_F(InstallableManagerUnitTest, PreferRelatedApplications) { - blink::Manifest manifest = GetValidManifest(); - - manifest.prefer_related_applications = true; - EXPECT_FALSE(IsManifestValid(manifest)); - EXPECT_EQ(PREFER_RELATED_APPLICATIONS, GetErrorCode()); -}
diff --git a/chrome/browser/io_thread_browsertest.cc b/chrome/browser/io_thread_browsertest.cc index 96a18ef3..43b2941 100644 --- a/chrome/browser/io_thread_browsertest.cc +++ b/chrome/browser/io_thread_browsertest.cc
@@ -20,8 +20,6 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" -#include "components/certificate_transparency/features.h" -#include "components/certificate_transparency/tree_state_tracker.h" #include "components/prefs/pref_service.h" #include "components/variations/variations_associated_data.h" #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/net/system_network_context_manager.cc b/chrome/browser/net/system_network_context_manager.cc index 183a377a..685c3bb 100644 --- a/chrome/browser/net/system_network_context_manager.cc +++ b/chrome/browser/net/system_network_context_manager.cc
@@ -22,7 +22,6 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_content_browser_client.h" #include "chrome/browser/component_updater/crl_set_component_installer.h" -#include "chrome/browser/component_updater/sth_set_component_installer.h" #include "chrome/browser/io_thread.h" #include "chrome/browser/net/chrome_mojo_proxy_resolver_factory.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" @@ -601,10 +600,6 @@ // Asynchronously reapply the most recently received CRLSet (if any). component_updater::CRLSetPolicy::ReconfigureAfterNetworkRestart(); - - // Asynchronously reapply the most recently received STHs (if any). - component_updater::STHSetComponentInstallerPolicy:: - ReconfigureAfterNetworkRestart(); } void SystemNetworkContextManager::DisableQuic() { @@ -691,7 +686,6 @@ network::mojom::CTLogInfoPtr log_info = network::mojom::CTLogInfo::New(); log_info->public_key = std::string(ct_log.log_key, ct_log.log_key_length); log_info->name = ct_log.log_name; - log_info->dns_api_endpoint = ct_log.log_dns_domain; network_context_params->ct_logs.push_back(std::move(log_info)); }
diff --git a/chrome/browser/notifications/scheduler/BUILD.gn b/chrome/browser/notifications/scheduler/BUILD.gn index 0a6d6b9a..d101031 100644 --- a/chrome/browser/notifications/scheduler/BUILD.gn +++ b/chrome/browser/notifications/scheduler/BUILD.gn
@@ -20,7 +20,6 @@ source_set("public") { sources = [ - "internal_types.h", "notification_background_task_scheduler.h", "notification_data.cc", "notification_data.h", @@ -86,7 +85,6 @@ "impression_types.h", "init_aware_scheduler.cc", "init_aware_scheduler.h", - "internal_types.h", "notification_entry.cc", "notification_entry.h", "notification_schedule_service_impl.cc", @@ -143,3 +141,11 @@ "//testing/gtest", ] } + +if (is_android) { + java_cpp_enum("jni_enums") { + sources = [ + "notification_scheduler_types.h", + ] + } +}
diff --git a/chrome/browser/notifications/scheduler/DEPS b/chrome/browser/notifications/scheduler/DEPS new file mode 100644 index 0000000..c80012b5 --- /dev/null +++ b/chrome/browser/notifications/scheduler/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+jni", +]
diff --git a/chrome/browser/notifications/scheduler/background_task_coordinator.h b/chrome/browser/notifications/scheduler/background_task_coordinator.h index 19e622b..0487485 100644 --- a/chrome/browser/notifications/scheduler/background_task_coordinator.h +++ b/chrome/browser/notifications/scheduler/background_task_coordinator.h
@@ -10,7 +10,6 @@ #include <vector> #include "base/macros.h" -#include "chrome/browser/notifications/scheduler/internal_types.h" #include "chrome/browser/notifications/scheduler/notification_scheduler_types.h" namespace base {
diff --git a/chrome/browser/notifications/scheduler/display_decider.h b/chrome/browser/notifications/scheduler/display_decider.h index 72ee364..2e4187c6 100644 --- a/chrome/browser/notifications/scheduler/display_decider.h +++ b/chrome/browser/notifications/scheduler/display_decider.h
@@ -13,7 +13,6 @@ #include "base/callback.h" #include "base/macros.h" -#include "chrome/browser/notifications/scheduler/internal_types.h" #include "chrome/browser/notifications/scheduler/notification_scheduler_types.h" namespace notifications {
diff --git a/chrome/browser/notifications/scheduler/distribution_policy.h b/chrome/browser/notifications/scheduler/distribution_policy.h index 25e1827..762ba338 100644 --- a/chrome/browser/notifications/scheduler/distribution_policy.h +++ b/chrome/browser/notifications/scheduler/distribution_policy.h
@@ -8,7 +8,7 @@ #include <memory> #include "base/macros.h" -#include "chrome/browser/notifications/scheduler/internal_types.h" +#include "chrome/browser/notifications/scheduler/notification_scheduler_types.h" namespace notifications {
diff --git a/chrome/browser/notifications/scheduler/impression_types.h b/chrome/browser/notifications/scheduler/impression_types.h index 85d1e838..607f0dd 100644 --- a/chrome/browser/notifications/scheduler/impression_types.h +++ b/chrome/browser/notifications/scheduler/impression_types.h
@@ -11,7 +11,6 @@ #include "base/optional.h" #include "base/time/time.h" -#include "chrome/browser/notifications/scheduler/internal_types.h" #include "chrome/browser/notifications/scheduler/notification_scheduler_types.h" namespace notifications {
diff --git a/chrome/browser/notifications/scheduler/internal_types.h b/chrome/browser/notifications/scheduler/internal_types.h deleted file mode 100644 index 0a994d6..0000000 --- a/chrome/browser/notifications/scheduler/internal_types.h +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_INTERNAL_TYPES_H_ -#define CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_INTERNAL_TYPES_H_ - -namespace notifications { - -// Enum to describe the time to process scheduled notification data. -enum class SchedulerTaskTime { - // The system is started from normal user launch or other background - // tasks. - kUnknown = 0, - - // Background task runs in the morning. - kMorning = 1, - - // Background task runs in the evening. - kEvening = 2, -}; - -} // namespace notifications - -#endif // CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_INTERNAL_TYPES_H_
diff --git a/chrome/browser/notifications/scheduler/notification_background_task_scheduler.h b/chrome/browser/notifications/scheduler/notification_background_task_scheduler.h index c59b3ad1..3c33cce5 100644 --- a/chrome/browser/notifications/scheduler/notification_background_task_scheduler.h +++ b/chrome/browser/notifications/scheduler/notification_background_task_scheduler.h
@@ -7,7 +7,7 @@ #include "base/macros.h" #include "base/time/time.h" -#include "chrome/browser/notifications/scheduler/internal_types.h" +#include "chrome/browser/notifications/scheduler/notification_scheduler_types.h" namespace notifications {
diff --git a/chrome/browser/notifications/scheduler/notification_scheduler_types.h b/chrome/browser/notifications/scheduler/notification_scheduler_types.h index 12b7546..95decdff 100644 --- a/chrome/browser/notifications/scheduler/notification_scheduler_types.h +++ b/chrome/browser/notifications/scheduler/notification_scheduler_types.h
@@ -7,6 +7,20 @@ namespace notifications { +// Enum to describe the time to process scheduled notification data. +// A Java counterpart will be generated for this enum. +// GENERATED_JAVA_ENUM_PACKAGE: ( +// org.chromium.chrome.browser.notifications.scheduler) +enum class SchedulerTaskTime { + // The system is started from normal user launch or other background + // tasks. + kUnknown = 0, + // Background task runs in the morning. + kMorning = 1, + // Background task runs in the evening. + kEvening = 2, +}; + // The type of a list of clients using the notification scheduler system. enum class SchedulerClientType { // Test only values.
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc index 2e080f6..86d3ae5 100644 --- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc +++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -147,7 +147,7 @@ #include "chrome/browser/extensions/browser_context_keyed_service_factories.h" #include "chrome/browser/extensions/extension_management.h" #include "chrome/browser/ui/web_applications/web_app_metrics_factory.h" -#include "chrome/browser/ui/web_applications/web_app_ui_delegate_impl_factory.h" +#include "chrome/browser/ui/web_applications/web_app_ui_service_factory.h" #include "chrome/browser/web_applications/web_app_provider_factory.h" #include "extensions/browser/api/networking_private/networking_private_delegate_factory.h" #include "extensions/browser/browser_context_keyed_service_factories.h" @@ -400,7 +400,7 @@ #endif #if BUILDFLAG(ENABLE_EXTENSIONS) web_app::WebAppProviderFactory::GetInstance(); - web_app::WebAppUiDelegateImplFactory::GetInstance(); + web_app::WebAppUiServiceFactory::GetInstance(); web_app::WebAppMetricsFactory::GetInstance(); #endif WebDataServiceFactory::GetInstance();
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc index 7d9197c..a77de6f 100644 --- a/chrome/browser/profiles/profile_io_data.cc +++ b/chrome/browser/profiles/profile_io_data.cc
@@ -47,7 +47,6 @@ #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" #include "components/about_handler/about_protocol_handler.h" -#include "components/certificate_transparency/tree_state_tracker.h" #include "components/content_settings/core/browser/content_settings_provider.h" #include "components/content_settings/core/browser/cookie_settings.h" #include "components/content_settings/core/browser/host_content_settings_map.h"
diff --git a/chrome/browser/profiles/profile_manager_unittest.cc b/chrome/browser/profiles/profile_manager_unittest.cc index fb54be05..2e164d3e 100644 --- a/chrome/browser/profiles/profile_manager_unittest.cc +++ b/chrome/browser/profiles/profile_manager_unittest.cc
@@ -153,7 +153,8 @@ cl->AppendSwitch(switches::kTestType); wallpaper_controller_client_ = std::make_unique<WallpaperControllerClient>(); - wallpaper_controller_client_->InitForTesting(&test_wallpaper_controller_); + wallpaper_controller_client_->InitForTesting( + test_wallpaper_controller_.CreateInterfacePtr()); // Have to manually reset the session type in between test runs because // some tests log in users. @@ -599,7 +600,8 @@ wallpaper_controller_client_ = std::make_unique<WallpaperControllerClient>(); - wallpaper_controller_client_->InitForTesting(&test_wallpaper_controller_); + wallpaper_controller_client_->InitForTesting( + test_wallpaper_controller_.CreateInterfacePtr()); // Have to manually reset the session type in between test runs because // RegisterUser() changes it.
diff --git a/chrome/browser/resource_coordinator/tab_activity_watcher.cc b/chrome/browser/resource_coordinator/tab_activity_watcher.cc index 9036c25..e34499b18 100644 --- a/chrome/browser/resource_coordinator/tab_activity_watcher.cc +++ b/chrome/browser/resource_coordinator/tab_activity_watcher.cc
@@ -48,7 +48,14 @@ // incrementally from 1. int64_t NewInt64ForLabelIdOrQueryId() { static int64_t id = 0; - return ++id; + // The id is shifted 13 bits so that the lower bits are reserved for counting + // multiple queries. + // We choose 13 so that the lower bits for counting multiple queries and + // higher bits for labeling queries are both unlikely to overflow. (lower bits + // only overflows when we have more than 8192 queries without labeling events; + // higher bits only overflow when we have more than 100 billion discards. + constexpr int kIdShiftBits = 13; + return (++id) << kIdShiftBits; } } // namespace @@ -103,8 +110,8 @@ // Copy the replaced tab's stats. page_metrics_ = replaced_tab.page_metrics_; - // Record previous ukm_source_id from the |replaced_tab|. - previous_ukm_source_id_ = replaced_tab.ukm_source_id_; + // Recover the ukm_source_id from the |replaced_tab|. + ukm_source_id_ = replaced_tab.ukm_source_id_; // Copy the replaced label_id_. label_id_ = replaced_tab.label_id_; @@ -161,10 +168,12 @@ if (!tab.has_value()) return; - // A new label_id_ is generated for this query. + // Update label_id_: a new label_id is generated for this query if the + // label_id_ is 0; otherwise the old label_id_ is incremented. This allows + // us to better pairing TabMetrics with ForegroundedOrClosed events offline. // The same label_id_ will be logged with ForegroundedOrClosed event later // on so that TabFeatures can be paired with ForegroundedOrClosed. - label_id_ = NewInt64ForLabelIdOrQueryId(); + label_id_ = label_id_ ? label_id_ + 1 : NewInt64ForLabelIdOrQueryId(); TabActivityWatcher::GetInstance()->tab_metrics_logger_->LogTabMetrics( ukm_source_id_, tab.value(), web_contents(), label_id_); @@ -426,11 +435,8 @@ metrics.total_tab_count = mru.total; metrics.label_id = label_id_; - const ukm::SourceId source_id = discarded_since_backgrounded_ - ? previous_ukm_source_id_ - : ukm_source_id_; TabActivityWatcher::GetInstance() - ->tab_metrics_logger_->LogForegroundedOrClosedMetrics(source_id, + ->tab_metrics_logger_->LogForegroundedOrClosedMetrics(ukm_source_id_, metrics); // label_id_ is reset whenever a label is logged. // A new label_id_ is generated when a query happens inside @@ -445,9 +451,6 @@ // Updated when a navigation is finished. ukm::SourceId ukm_source_id_ = 0; - // Recorded when a WebContents is replaced by another. - ukm::SourceId previous_ukm_source_id_ = 0; - // When the tab was created. base::TimeTicks creation_time_;
diff --git a/chrome/browser/resource_coordinator/tab_activity_watcher_browsertest.cc b/chrome/browser/resource_coordinator/tab_activity_watcher_browsertest.cc index d4ac8eb6..a8ebd87 100644 --- a/chrome/browser/resource_coordinator/tab_activity_watcher_browsertest.cc +++ b/chrome/browser/resource_coordinator/tab_activity_watcher_browsertest.cc
@@ -56,6 +56,7 @@ // These parameters don't affect logging. const bool kCheckNavigationSuccess = true; +const int64_t kIdShift = 1 << 13; } // namespace @@ -381,6 +382,11 @@ // Tests discarded tab is recorded correctly. IN_PROC_BROWSER_TEST_F(TabActivityWatcherUkmTest, DiscardedTabGetsPreviousSourceId) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeatureWithParameters( + features::kTabRanker, + {{"number_of_oldest_tabs_to_log_with_TabRanker", "1"}}); + ukm::SourceId ukm_source_id_for_tab_0 = 0; ukm::SourceId ukm_source_id_for_tab_1 = 0; @@ -407,6 +413,31 @@ ->GetTabLifecycleUnitExternal(first_contents) ->DiscardTab(); + // Call LogOldestNTabFeatures should log the oldest tab which is tab@0. + TabActivityWatcher::GetInstance()->LogOldestNTabFeatures(); + { + SCOPED_TRACE(""); + // tab feature of tab@0 should be logged correctly. + UkmMetricMap expected_tab_feature_values = kBasicMetricValues; + expected_tab_feature_values[TabManager_TabMetrics::kMRUIndexName] = 1; + expected_tab_feature_values + [TabManager_TabMetrics::kNumReactivationBeforeName] = 0; + expected_tab_feature_values[TabManager_TabMetrics::kTotalTabCountName] = 2; + expected_tab_feature_values[TabManager_TabMetrics::kWindowTabCountName] = 2; + expected_tab_feature_values[TabManager_TabMetrics::kLabelIdName] = + 2 * kIdShift; + expected_tab_feature_values[TabManager_TabMetrics::kQueryIdName] = + 1 * kIdShift; + expected_tab_feature_values + [TabManager_TabMetrics::kNavigationEntryCountName] = 2; + + ukm_entry_checker_->ExpectNewEntry(kEntryName, test_urls_[0], + expected_tab_feature_values); + ExpectNewEntryWithSourceId(test_urls_[0], kEntryName, 2, + expected_tab_feature_values, + ukm_source_id_for_tab_0); + } + // Switching to first tab logs a forgrounded event for test_urls_[0] // and a backgrounded event for test_urls_[1]. browser()->tab_strip_model()->ActivateTabAt( @@ -417,7 +448,7 @@ kBasicMetricValues); ukm_source_id_for_tab_1 = ExpectNewEntryWithSourceId( - test_urls_[1], kEntryName, 2, kBasicMetricValues); + test_urls_[1], kEntryName, 3, kBasicMetricValues); ExpectNewEntryWithSourceId( test_urls_[0], kFOCEntryName, 1, @@ -520,8 +551,10 @@ [TabManager_TabMetrics::kNumReactivationBeforeName] = 0; expected_tab_feature_values[TabManager_TabMetrics::kTotalTabCountName] = 3; expected_tab_feature_values[TabManager_TabMetrics::kWindowTabCountName] = 3; - expected_tab_feature_values[TabManager_TabMetrics::kLabelIdName] = 2; - expected_tab_feature_values[TabManager_TabMetrics::kQueryIdName] = 1; + expected_tab_feature_values[TabManager_TabMetrics::kLabelIdName] = + 2 * kIdShift; + expected_tab_feature_values[TabManager_TabMetrics::kQueryIdName] = + 1 * kIdShift; ukm_entry_checker_->ExpectNewEntry(kEntryName, test_urls_[1], expected_tab_feature_values); @@ -537,7 +570,8 @@ ukm_entry_checker_->ExpectNewEntry( kFOCEntryName, test_urls_[1], {{TabManager_Background_ForegroundedOrClosed::kIsForegroundedName, 1}, - {TabManager_Background_ForegroundedOrClosed::kLabelIdName, 2}, + {TabManager_Background_ForegroundedOrClosed::kLabelIdName, + 2 * kIdShift}, {TabManager_Background_ForegroundedOrClosed::kIsDiscardedName, 0}}); } @@ -552,8 +586,10 @@ [TabManager_TabMetrics::kNumReactivationBeforeName] = 0; expected_tab_feature_values[TabManager_TabMetrics::kTotalTabCountName] = 3; expected_tab_feature_values[TabManager_TabMetrics::kWindowTabCountName] = 3; - expected_tab_feature_values[TabManager_TabMetrics::kLabelIdName] = 4; - expected_tab_feature_values[TabManager_TabMetrics::kQueryIdName] = 3; + expected_tab_feature_values[TabManager_TabMetrics::kLabelIdName] = + 4 * kIdShift; + expected_tab_feature_values[TabManager_TabMetrics::kQueryIdName] = + 3 * kIdShift; ukm_entry_checker_->ExpectNewEntry(kEntryName, test_urls_[2], expected_tab_feature_values); @@ -568,7 +604,8 @@ ukm_entry_checker_->ExpectNewEntry( kFOCEntryName, test_urls_[2], {{TabManager_Background_ForegroundedOrClosed::kIsForegroundedName, 0}, - {TabManager_Background_ForegroundedOrClosed::kLabelIdName, 4}, + {TabManager_Background_ForegroundedOrClosed::kLabelIdName, + 4 * kIdShift}, {TabManager_Background_ForegroundedOrClosed::kIsDiscardedName, 0}}); // Close Browser should log a ForegroundedOrClosed event for tab@0 with @@ -601,8 +638,8 @@ SCOPED_TRACE(""); UkmMetricMap expected_metrics = kBasicMetricValues; expected_metrics[TabManager_TabMetrics::kNavigationEntryCountName] = 2; - expected_metrics[TabManager_TabMetrics::kLabelIdName] = 2; - expected_metrics[TabManager_TabMetrics::kQueryIdName] = 1; + expected_metrics[TabManager_TabMetrics::kLabelIdName] = 2 * kIdShift; + expected_metrics[TabManager_TabMetrics::kQueryIdName] = 1 * kIdShift; // tab feature of tab@0 should be logged correctly. ukm_entry_checker_->ExpectNewEntry(kEntryName, test_urls_[0], expected_metrics); @@ -623,7 +660,8 @@ UkmMetricMap expected_metrics = { {TabManager_Background_ForegroundedOrClosed::kIsForegroundedName, 1}, {TabManager_Background_ForegroundedOrClosed::kIsDiscardedName, 1}, - {TabManager_Background_ForegroundedOrClosed::kLabelIdName, 2}}; + {TabManager_Background_ForegroundedOrClosed::kLabelIdName, + 2 * kIdShift}}; ukm_entry_checker_->ExpectNewEntry(kFOCEntryName, test_urls_[0], expected_metrics); @@ -635,8 +673,8 @@ SCOPED_TRACE(""); // tab feature of tab@1 should be logged correctly. UkmMetricMap expected_metrics = kBasicMetricValues; - expected_metrics[TabManager_TabMetrics::kLabelIdName] = 4; - expected_metrics[TabManager_TabMetrics::kQueryIdName] = 3; + expected_metrics[TabManager_TabMetrics::kLabelIdName] = 4 * kIdShift; + expected_metrics[TabManager_TabMetrics::kQueryIdName] = 3 * kIdShift; ukm_entry_checker_->ExpectNewEntry(kEntryName, test_urls_[1], expected_metrics); } @@ -654,10 +692,53 @@ UkmMetricMap expected_metrics = { {TabManager_Background_ForegroundedOrClosed::kIsForegroundedName, 0}, {TabManager_Background_ForegroundedOrClosed::kIsDiscardedName, 1}, - {TabManager_Background_ForegroundedOrClosed::kLabelIdName, 4}}; + {TabManager_Background_ForegroundedOrClosed::kLabelIdName, + 4 * kIdShift}}; ukm_entry_checker_->ExpectNewEntry(kFOCEntryName, test_urls_[1], expected_metrics); } } + +// Tests label_id is incremented if the LogOldestNTabFeatures is called second +// times without logging the label first. +IN_PROC_BROWSER_TEST_F(TabActivityWatcherUkmTest, + TabsAlreadyHaveLabelIdGetIncrementalLabelIds) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeatureWithParameters( + features::kTabRanker, + {{"number_of_oldest_tabs_to_log_with_TabRanker", "1"}, + {"disable_background_log_with_TabRanker", "true"}}); + + ui_test_utils::NavigateToURL(browser(), test_urls_[0]); + AddTabAtIndex(1, test_urls_[1], ui::PAGE_TRANSITION_LINK); + // No TabMetrics events are logged till now. + EXPECT_EQ(0u, ukm_entry_checker_->NumEntries(kEntryName)); + + // Log tab_0. + TabActivityWatcher::GetInstance()->LogOldestNTabFeatures(); + { + SCOPED_TRACE(""); + UkmMetricMap expected_metrics = kBasicMetricValues; + expected_metrics[TabManager_TabMetrics::kNavigationEntryCountName] = 2; + expected_metrics[TabManager_TabMetrics::kLabelIdName] = 2 * kIdShift; + expected_metrics[TabManager_TabMetrics::kQueryIdName] = 1 * kIdShift; + // tab feature of tab@0 should be logged correctly. + ukm_entry_checker_->ExpectNewEntry(kEntryName, test_urls_[0], + expected_metrics); + } + + TabActivityWatcher::GetInstance()->LogOldestNTabFeatures(); + { + SCOPED_TRACE(""); + UkmMetricMap expected_metrics = kBasicMetricValues; + expected_metrics[TabManager_TabMetrics::kNavigationEntryCountName] = 2; + expected_metrics[TabManager_TabMetrics::kLabelIdName] = 2 * kIdShift + 1; + expected_metrics[TabManager_TabMetrics::kQueryIdName] = 3 * kIdShift; + // tab feature of tab@0 should be logged correctly. + ukm_entry_checker_->ExpectNewEntry(kEntryName, test_urls_[0], + expected_metrics); + } +} + } // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/tab_activity_watcher_unittest.cc b/chrome/browser/resource_coordinator/tab_activity_watcher_unittest.cc index a312a30..b852f6e 100644 --- a/chrome/browser/resource_coordinator/tab_activity_watcher_unittest.cc +++ b/chrome/browser/resource_coordinator/tab_activity_watcher_unittest.cc
@@ -602,7 +602,9 @@ tab_activity_simulator_.SwitchToTabAt(tab_strip_model, 1); { SCOPED_TRACE(""); - ExpectNewEntry(kTestUrls[1], kBasicMetricValues); + // Replaced tab uses the orig source_id; so the metrics is logged to + // kTestUrls[0]. + ExpectNewEntry(kTestUrls[0], kBasicMetricValues); } tab_strip_model->CloseAllTabs();
diff --git a/chrome/browser/resources/app_management/OWNERS b/chrome/browser/resources/app_management/OWNERS index 90c732ec..54640cb 100644 --- a/chrome/browser/resources/app_management/OWNERS +++ b/chrome/browser/resources/app_management/OWNERS
@@ -1,3 +1,5 @@ calamity@chromium.org dominickn@chromium.org ericwilligers@chromium.org + +# COMPONENT: Platform>Apps>Foundation \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/add_supervision/add_supervision_api_client.js b/chrome/browser/resources/chromeos/add_supervision/add_supervision_api_client.js index bf71b93..4cd2b14 100644 --- a/chrome/browser/resources/chromeos/add_supervision/add_supervision_api_client.js +++ b/chrome/browser/resources/chromeos/add_supervision/add_supervision_api_client.js
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -const METHOD_LIST = ['logOut', 'getInstalledArcApps', 'uninstallArcApps']; +const METHOD_LIST = ['logOut', 'getInstalledArcApps']; /** * Class that implements the client side of the AddSupervision postMessage API.
diff --git a/chrome/browser/resources/chromeos/add_supervision/add_supervision_api_server.js b/chrome/browser/resources/chromeos/add_supervision/add_supervision_api_server.js index 49fcd5ac0..038d09af 100644 --- a/chrome/browser/resources/chromeos/add_supervision/add_supervision_api_server.js +++ b/chrome/browser/resources/chromeos/add_supervision/add_supervision_api_server.js
@@ -5,7 +5,7 @@ /** * The methods to expose to the client. */ -const METHOD_LIST = ['logOut', 'getInstalledArcApps', 'uninstallArcApps']; +const METHOD_LIST = ['logOut', 'getInstalledArcApps']; /** * Class that implements the server side of the AddSupervision postMessage @@ -31,7 +31,6 @@ this.registerMethod('logOut', this.logOut.bind(this)); this.registerMethod( 'getInstalledArcApps', this.getInstalledArcApps.bind(this)); - this.registerMethod('uninstallArcApps', this.uninstallArcApps.bind(this)); } /** @@ -53,14 +52,4 @@ getInstalledArcApps(unused) { return this.proxy_.getInstalledArcApps(); } - - /** - * Uninstall the specified ARC apps. - * @param {!Array<!string>} apps List of app package names to uninstall. - * @return {Promise} a promise whose successful result indicates the apps were - * uninstalled. - */ - uninstallArcApps(apps) { - return this.proxy_.uninstallArcApps(apps); - } }
diff --git a/chrome/browser/resources/chromeos/add_supervision/webview-example.html b/chrome/browser/resources/chromeos/add_supervision/webview-example.html index 400fe30..61d67a43 100644 --- a/chrome/browser/resources/chromeos/add_supervision/webview-example.html +++ b/chrome/browser/resources/chromeos/add_supervision/webview-example.html
@@ -33,19 +33,6 @@ console.error(err); }) }); - - const uninstallArcAppsBtn = document.querySelector('#uninstall_arc_apps'); - - uninstallArcAppsBtn.addEventListener('click', () => { - api.uninstallArcApps( - ['com.netflix.mediaclient', 'com.google.android.videos']) - .then(() => { - console.log('uninstalled arc apps'); - }, (error) => { - console.error(error.message); - }); - }); - }); </script> </head> <body> @@ -58,9 +45,6 @@ <button id="get_arc_apps">Get ARC Apps</button> </div> <div> - <button id="uninstall_arc_apps">Uninstall ARC Apps</button> - </div> - <div> <input type="text" id="arc_apps" minlength="0" maxlength="128" size="128"> </div>
diff --git a/chrome/browser/resources/chromeos/add_supervision/webview-example2.html b/chrome/browser/resources/chromeos/add_supervision/webview-example2.html index b7d7202..6808e97f 100644 --- a/chrome/browser/resources/chromeos/add_supervision/webview-example2.html +++ b/chrome/browser/resources/chromeos/add_supervision/webview-example2.html
@@ -33,19 +33,6 @@ console.error(err); }) }); - - const uninstallArcAppsBtn = document.querySelector('#uninstall_arc_apps'); - - uninstallArcAppsBtn.addEventListener('click', () => { - api.uninstallArcApps( - ['com.netflix.mediaclient', 'com.google.android.videos']) - .then(() => { - console.log('uninstalled arc apps'); - }, (error) => { - console.error(error.message); - }); - }); - }); </script> </head> <body> @@ -58,9 +45,6 @@ <button id="get_arc_apps">Get ARC Apps</button> </div> <div> - <button id="uninstall_arc_apps">Uninstall ARC Apps</button> - </div> - <div> <input type="text" id="arc_apps" minlength="0" maxlength="128" size="128"> </div>
diff --git a/chrome/browser/resources/downloads/item.js b/chrome/browser/resources/downloads/item.js index c318484..19ffb11 100644 --- a/chrome/browser/resources/downloads/item.js +++ b/chrome/browser/resources/downloads/item.js
@@ -475,7 +475,6 @@ }); cr.toastManager.getInstance().showForStringPieces(pieces, true); this.mojoHandler_.remove(this.data.id); - this.fire('restore-focus-after-remove'); }, /** @private */
diff --git a/chrome/browser/resources/downloads/manager.js b/chrome/browser/resources/downloads/manager.js index 084bc8e..f96ceed 100644 --- a/chrome/browser/resources/downloads/manager.js +++ b/chrome/browser/resources/downloads/manager.js
@@ -60,19 +60,12 @@ 'itemsChanged_(items_.*)', ], - listeners: { - 'restore-focus-after-remove': 'onRestoreFocusAfterRemove_', - }, - /** @private {downloads.mojom.PageCallbackRouter} */ mojoEventTarget_: null, /** @private {downloads.mojom.PageHandlerInterface} */ mojoHandler_: null, - /** @private {boolean} */ - restoreFocusAfterRemove_: false, - /** @private {?downloads.SearchService} */ searchService_: null, @@ -265,28 +258,10 @@ type: 'splice', removed: removed, }]); - if (this.restoreFocusAfterRemove_) { - this.restoreFocusAfterRemove_ = false; - const focusIndex = Math.min(this.items_.length - 1, index); - if (focusIndex >= 0) { - setTimeout(() => { - this.$.downloadsList.focusItem(focusIndex); - const item = getDeepActiveElement(); - if (item) { - item.focusOnRemoveButton(); - } - }); - } - } this.onScroll_(); }, /** @private */ - onRestoreFocusAfterRemove_: function() { - this.restoreFocusAfterRemove_ = true; - }, - - /** @private */ onUndoClick_: function() { cr.toastManager.getInstance().hide(); this.mojoHandler_.undo();
diff --git a/chrome/browser/resources/extensions/BUILD.gn b/chrome/browser/resources/extensions/BUILD.gn index 8a3b44b..375e5e5 100644 --- a/chrome/browser/resources/extensions/BUILD.gn +++ b/chrome/browser/resources/extensions/BUILD.gn
@@ -261,6 +261,7 @@ "//ui/webui/resources/cr_elements/cr_view_manager:cr_view_manager", "//ui/webui/resources/js:assert", "//ui/webui/resources/js:cr", + "//ui/webui/resources/js:load_time_data", ] externs_list = [ "$externs_path/developer_private.js" ] }
diff --git a/chrome/browser/resources/extensions/activity_log/activity_log.html b/chrome/browser/resources/extensions/activity_log/activity_log.html index 1f4abb9..ab435e7 100644 --- a/chrome/browser/resources/extensions/activity_log/activity_log.html +++ b/chrome/browser/resources/extensions/activity_log/activity_log.html
@@ -27,10 +27,13 @@ margin-inline-start: 8px; } + #closeButton { + margin-inline-end: 16px; + } + #icon { height: 24px; margin-inline-end: 12px; - margin-inline-start: 16px; width: 24px; } @@ -65,13 +68,15 @@ <cr-icon-button class="icon-arrow-back no-overlap" id="closeButton" aria-label="$i18n{back}" on-click="onCloseButtonTap_"> </cr-icon-button> - <img id="icon" src="[[extensionInfo.iconUrl]]" - alt$="[[appOrExtension( - extensionInfo.type, - '$i18nPolymer{appIcon}', - '$i18nPolymer{extensionIcon}')]]"> + <template is="dom-if" if="[[!extensionInfo.isPlaceholder]]"> + <img id="icon" src="[[extensionInfo.iconUrl]]" + alt$="[[appOrExtension( + extensionInfo.type, + '$i18nPolymer{appIcon}', + '$i18nPolymer{extensionIcon}')]]"> + </template> <div id="activity-log-heading"> - [[i18n('activityLogPageHeading', extensionInfo.name)]] + [[getActivityLogHeading_(extensionInfo)]] </div> </div> <cr-tabs selected="{{selectedSubpage_}}" tab-names="[[tabNames_]]">
diff --git a/chrome/browser/resources/extensions/activity_log/activity_log.js b/chrome/browser/resources/extensions/activity_log/activity_log.js index 4617810..8f29629 100644 --- a/chrome/browser/resources/extensions/activity_log/activity_log.js +++ b/chrome/browser/resources/extensions/activity_log/activity_log.js
@@ -18,6 +18,17 @@ cr.define('extensions', function() { 'use strict'; + /** + * A struct used as a placeholder for chrome.developerPrivate.ExtensionInfo + * for this component if the extensionId from the URL does not correspond to + * installed extension. + * @typedef {{ + * id: string, + * isPlaceholder: boolean, + * }} + */ + let ActivityLogExtensionPlaceholder; + const ActivityLog = Polymer({ is: 'extensions-activity-log', @@ -30,7 +41,8 @@ properties: { /** * The underlying ExtensionInfo for the details being displayed. - * @type {!chrome.developerPrivate.ExtensionInfo} + * @type {!chrome.developerPrivate.ExtensionInfo| + * !extensions.ActivityLogExtensionPlaceholder} */ extensionInfo: Object, @@ -85,6 +97,17 @@ /** * @private + * @return {string} + */ + getActivityLogHeading_: function() { + const headingName = this.extensionInfo.isPlaceholder ? + this.i18n('missingOrUninstalledExtension') : + this.extensionInfo.name; + return this.i18n('activityLogPageHeading', headingName); + }, + + /** + * @private * @return {boolean} */ isHistoryTabSelected_: function() { @@ -123,12 +146,17 @@ /** @private */ onCloseButtonTap_: function() { - extensions.navigation.navigateTo( - {page: Page.DETAILS, extensionId: this.extensionInfo.id}); + if (this.extensionInfo.isPlaceholder) { + extensions.navigation.navigateTo({page: Page.LIST}); + } else { + extensions.navigation.navigateTo( + {page: Page.DETAILS, extensionId: this.extensionInfo.id}); + } }, }); return { ActivityLog: ActivityLog, + ActivityLogExtensionPlaceholder: ActivityLogExtensionPlaceholder, }; });
diff --git a/chrome/browser/resources/extensions/manager.js b/chrome/browser/resources/extensions/manager.js index eda57f21..6095756 100644 --- a/chrome/browser/resources/extensions/manager.js +++ b/chrome/browser/resources/extensions/manager.js
@@ -100,7 +100,8 @@ /** * The item that provides some information about the current extension * for the activity log view subpage. See also errorPageItem_. - * @private {!chrome.developerPrivate.ExtensionInfo|undefined} + * @private {!chrome.developerPrivate.ExtensionInfo|undefined| + * !extensions.ActivityLogExtensionPlaceholder} */ activityLogItem_: Object, @@ -407,6 +408,10 @@ this.errorPageItem_ && this.errorPageItem_.id == item.id && this.currentPage_.page == Page.ERRORS) { this.errorPageItem_ = item; + } else if ( + this.activityLogItem_ && this.activityLogItem_.id == item.id && + this.currentPage_.page == Page.ACTIVITY_LOG) { + this.activityLogItem_ = item; } }, @@ -465,12 +470,24 @@ const fromPage = this.currentPage_ ? this.currentPage_.page : null; const toPage = newPage.page; let data; + let activityLogPlaceholder; if (newPage.extensionId) { data = this.getData_(newPage.extensionId); if (!data) { - // Attempting to view an invalid (removed?) app or extension ID. - extensions.navigation.replaceWith({page: Page.LIST}); - return; + // Allow the user to navigate to the activity log page even if the + // extension ID is not valid. This enables the use case of seeing an + // extension's install-time activities by navigating to an extension's + // activity log page, then installing the extension. + if (this.showActivityLog && toPage == Page.ACTIVITY_LOG) { + activityLogPlaceholder = { + id: newPage.extensionId, + isPlaceholder: true, + }; + } else { + // Attempting to view an invalid (removed?) app or extension ID. + extensions.navigation.replaceWith({page: Page.LIST}); + return; + } } } @@ -487,7 +504,7 @@ return; } - this.activityLogItem_ = assert(data); + this.activityLogItem_ = data ? assert(data) : activityLogPlaceholder; } if (fromPage != toPage) {
diff --git a/chrome/browser/resources/feedback/css/feedback.css b/chrome/browser/resources/feedback/css/feedback.css index 86371f0..cb000bd 100644 --- a/chrome/browser/resources/feedback/css/feedback.css +++ b/chrome/browser/resources/feedback/css/feedback.css
@@ -144,6 +144,10 @@ flex: auto; } +.content #sys-info-container { + margin-inline-end: 130px; +} + .content #privacy-note { color: #969696; font-size: 12px;
diff --git a/chrome/browser/resources/feedback/html/default.html b/chrome/browser/resources/feedback/html/default.html index e04a2cda..4443627 100644 --- a/chrome/browser/resources/feedback/html/default.html +++ b/chrome/browser/resources/feedback/html/default.html
@@ -63,7 +63,7 @@ <img id="screenshot-image"> </div> <!-- System Information --> - <div class="checkbox-field-container"> + <div id="sys-info-container" class="checkbox-field-container"> <input id="sys-info-checkbox" type="checkbox" aria-labelledby="sys-info-label" checked> <label id="sys-info-label" i18n-values=".innerHTML:sys-info"></label> </div>
diff --git a/chrome/browser/resources/print_preview/ui/pages_settings.js b/chrome/browser/resources/print_preview/ui/pages_settings.js index 64f6d0a..f46015b 100644 --- a/chrome/browser/resources/print_preview/ui/pages_settings.js +++ b/chrome/browser/resources/print_preview/ui/pages_settings.js
@@ -38,19 +38,15 @@ is: 'print-preview-pages-settings', behaviors: [ - SettingsBehavior, print_preview.InputBehavior, - print_preview.SelectBehavior + SettingsBehavior, print_preview.InputBehavior, print_preview.SelectBehavior ], properties: { disabled: Boolean, - pageCount: Number, - - /** @private {!Array<number>} */ - allPagesArray_: { - type: Array, - computed: 'computeAllPagesArray_(pageCount)', + pageCount: { + type: Number, + observer: 'onPageCountChange_', }, /** @private {boolean} */ @@ -90,7 +86,7 @@ /** @private {!Array<{to: number, from: number}>} */ rangesToPrint_: { type: Array, - computed: 'computeRangesToPrint_(pagesToPrint_, allPagesArray_)', + computed: 'computeRangesToPrint_(pagesToPrint_)', }, /** @@ -104,7 +100,7 @@ }, observers: [ - 'updatePagesToPrint_(inputString_, allPagesArray_)', + 'updatePagesToPrint_(inputString_)', 'onRangeChange_(errorState_, rangesToPrint_, settings.pages, ' + 'settings.pagesPerSheet.value)', ], @@ -153,8 +149,8 @@ /** @private */ onCollapseChanged_: function() { if (this.customSelected_) { - /** @type {!CrInputElement} */ (this.$.pageSettingsCustomInput) - .inputElement.focus(); + /** @type {!CrInputElement} */ (this.$.pageSettingsCustomInput) + .inputElement.focus(); } }, @@ -168,18 +164,6 @@ }, /** - * @return {!Array<number>} - * @private - */ - computeAllPagesArray_: function() { - const array = new Array(this.pageCount); - for (let i = 0; i < array.length; i++) { - array[i] = i + 1; - } - return array; - }, - - /** * Updates pages to print and error state based on the validity and * current value of the input. * @private @@ -187,7 +171,9 @@ updatePagesToPrint_: function() { if (!this.customSelected_) { this.errorState_ = PagesInputErrorState.NO_ERROR; - this.pagesToPrint_ = this.allPagesArray_ || []; + this.pagesToPrint_ = this.pageCount ? + Array.from(new Array(this.pageCount).fill(0), (_, i) => i + 1) : + []; return; } else if (this.inputString_ === '') { this.errorState_ = PagesInputErrorState.EMPTY; @@ -197,7 +183,7 @@ const pages = []; const added = {}; const ranges = this.inputString_.split(/,|\u3001/); - const maxPage = this.allPagesArray_.length; + const maxPage = this.pageCount; for (const range of ranges) { if (range == '') { this.errorState_ = PagesInputErrorState.INVALID_SYNTAX; @@ -266,14 +252,13 @@ }, /** - * Updates ranges to print. * @return {!Array<{to: number, from: number}>} * @private */ computeRangesToPrint_: function() { if (!this.pagesToPrint_ || this.pagesToPrint_.length == 0 || this.pagesToPrint_[0] == -1 || - this.pagesToPrint_.length == this.allPagesArray_.length) { + this.pagesToPrint_.length == this.pageCount) { return []; } @@ -432,6 +417,28 @@ this.resetString(); } this.updatePagesToPrint_(); - } + }, + + /** + * @param {number} current + * @param {number} previous + * @private + */ + onPageCountChange_: function(current, previous) { + // Reset the custom input to the new "all pages" value if it is equal to the + // full page range and was either set automatically, or would become invalid + // due to the page count change. + const resetCustom = this.customSelected_ && !!this.pagesToPrint_ && + this.pagesToPrint_.length === previous && + (current < previous || !this.restoreLastInput_); + + if (resetCustom) { + this.$$('cr-input').value = this.getAllPagesString_(); + this.inputString_ = this.getAllPagesString_(); + this.resetString(); + } else { + this.updatePagesToPrint_(); + } + }, }); })();
diff --git a/chrome/browser/resources/settings/internet_page/internet_config.js b/chrome/browser/resources/settings/internet_page/internet_config.js index 64452cd..97cca74 100644 --- a/chrome/browser/resources/settings/internet_page/internet_config.js +++ b/chrome/browser/resources/settings/internet_page/internet_config.js
@@ -122,6 +122,12 @@ * @private */ getDialogTitle_: function() { + // If no properties are available yet, wait until they are set as part of + // open(). + if (!this.managedProperties_) { + return ''; + } + const name = /** @type {string} */ ( CrOnc.getActiveValue(this.managedProperties_.Name)); if (name && !this.showConnect) {
diff --git a/chrome/browser/safe_browsing/telemetry/android/android_telemetry_service_unittest.cc b/chrome/browser/safe_browsing/telemetry/android/android_telemetry_service_unittest.cc index b235300..4013bde 100644 --- a/chrome/browser/safe_browsing/telemetry/android/android_telemetry_service_unittest.cc +++ b/chrome/browser/safe_browsing/telemetry/android/android_telemetry_service_unittest.cc
@@ -77,7 +77,13 @@ std::make_unique<AndroidTelemetryService>(sb_service_.get(), profile()); } - void TearDown() override {} + void TearDown() override { + // Make sure the NetworkContext owned by SafeBrowsingService is destructed + // before the NetworkService object.. + browser_process_->safe_browsing_service()->ShutDown(); + browser_process_->SetSafeBrowsingService(nullptr); + base::RunLoop().RunUntilIdle(); + } bool CanSendPing(download::DownloadItem* item) { return telemetry_service_->CanSendPing(item);
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 1f1a5314..3df0378 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -2352,6 +2352,14 @@ "//ui/events:dom_keycode_converter", ] + if (use_dbus) { + sources += [ + "views/status_icons/status_icon_linux_dbus.cc", + "views/status_icons/status_icon_linux_dbus.h", + ] + defines += [ "USE_DBUS" ] + } + if (use_x11) { sources += [ "views/frame/browser_desktop_window_tree_host_x11.cc", @@ -2367,6 +2375,8 @@ "views/javascript_app_modal_dialog_views_x11.h", "views/javascript_app_modal_event_blocker_x11.cc", "views/javascript_app_modal_event_blocker_x11.h", + "views/status_icons/status_icon_linux_x11.cc", + "views/status_icons/status_icon_linux_x11.h", ] configs += [ "//build/config/linux:x11" ] deps += [ @@ -3348,6 +3358,7 @@ "//ash/public/cpp/app_list/vector_icons", "//ash/resources/vector_icons", "//chrome/browser/ui:app_launch_event_logger_proto", + "//chrome/browser/ui/app_list/search/logging:search_ranking_event_proto", "//chrome/browser/ui/app_list/search/search_result_ranker:app_launch_predictor_proto", "//chrome/browser/ui/app_list/search/search_result_ranker:app_list_launch_recorder_proto", "//chrome/browser/ui/app_list/search/search_result_ranker:recurrence_ranker_proto", @@ -3617,10 +3628,10 @@ "web_applications/web_app_metrics.h", "web_applications/web_app_metrics_factory.cc", "web_applications/web_app_metrics_factory.h", - "web_applications/web_app_ui_delegate_impl.cc", - "web_applications/web_app_ui_delegate_impl.h", - "web_applications/web_app_ui_delegate_impl_factory.cc", - "web_applications/web_app_ui_delegate_impl_factory.h", + "web_applications/web_app_ui_service.cc", + "web_applications/web_app_ui_service.h", + "web_applications/web_app_ui_service_factory.cc", + "web_applications/web_app_ui_service_factory.h", "webui/extensions/extension_basic_info.cc", "webui/extensions/extension_basic_info.h", "webui/extensions/extension_icon_source.cc",
diff --git a/chrome/browser/ui/app_list/arc/arc_app_utils.cc b/chrome/browser/ui/app_list/arc/arc_app_utils.cc index fb619871..7e9a91a1 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_utils.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_utils.cc
@@ -639,12 +639,6 @@ return app_info->package_name; } -std::string ArcPackageNameToAppId(const std::string& package_name, - Profile* profile) { - ArcAppListPrefs* arc_prefs = ArcAppListPrefs::Get(profile); - return arc_prefs->GetAppIdByPackageName(package_name); -} - bool IsArcAppSticky(const std::string& app_id, Profile* profile) { ArcAppListPrefs* arc_prefs = ArcAppListPrefs::Get(profile); std::unique_ptr<ArcAppListPrefs::AppInfo> app_info =
diff --git a/chrome/browser/ui/app_list/arc/arc_app_utils.h b/chrome/browser/ui/app_list/arc/arc_app_utils.h index 42babca..b53f570 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_utils.h +++ b/chrome/browser/ui/app_list/arc/arc_app_utils.h
@@ -189,11 +189,6 @@ // be the AppID of an ARC app. std::string AppIdToArcPackageName(const std::string& app_id, Profile* profile); -// Returns the AppID for the specified package_name, which must be the package -// name of an ARC app. -std::string ArcPackageNameToAppId(const std::string& package_name, - Profile* profile); - // Returns true if the ARC app is sticky (not uninstallable). This function // will DCHECK if app_id isn't installed. This functionality should eventually // move to the App Service: (https://crbug.com/948408).
diff --git a/chrome/browser/ui/app_list/search/logging/BUILD.gn b/chrome/browser/ui/app_list/search/logging/BUILD.gn new file mode 100644 index 0000000..d2fbed1 --- /dev/null +++ b/chrome/browser/ui/app_list/search/logging/BUILD.gn
@@ -0,0 +1,11 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/protobuf/proto_library.gni") + +proto_library("search_ranking_event_proto") { + sources = [ + "search_ranking_event.proto", + ] +}
diff --git a/chrome/browser/ui/app_list/search/logging/search_ranking_event.proto b/chrome/browser/ui/app_list/search/logging/search_ranking_event.proto new file mode 100644 index 0000000..791ab28 --- /dev/null +++ b/chrome/browser/ui/app_list/search/logging/search_ranking_event.proto
@@ -0,0 +1,92 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +syntax = "proto2"; + +option optimize_for = LITE_RUNTIME; + +package app_list; + +// Some enums that will be used for both SearchRankingZeroStateEvent and +// SearchRankingQueryEvent. +enum CategoryID { + UNKNOWN_CATEGORY_ID = 0; + ANSWER_CARD = 1; + RECENT_QUERY = 2; + WEB_RESULT = 3; + BOOKMARK = 4; + RECENTLY_VISITED_URL = 5; + DRIVE_FILE = 6; + LOCAL_FILE = 7; +} + +enum FileExtension { + UNKNOWN_FILE_EXTENSION = 0; + DOCS = 1; + SHEETS = 2; + SLIDES = 3; + FORMS = 4; + DRAWINGS = 5; +} + +enum DayOfWeek { + SUN = 0; + MON = 1; + TUE = 2; + WED = 3; + THU = 4; + FRI = 5; + SAT = 6; +} + +enum DeviceMode { + CLAMSHELL = 0; + TABLET = 1; +} + +// SearchRankingZeroStateEvent contains features and related information for the +// Chrome OS Search and Ranking project. These will be used for zero-state +// recommendations. +message SearchRankingZeroStateEvent { + // Contain features about a specific item. + message Features { + // Type of the item. + optional CategoryID category_id = 1; + // Extension of the file. Only available if category_id is DRIVE_FILE or + // LOCAL_FILE. + optional FileExtension file_extension = 2; + // Day of the week. Sunday is 0. + optional DayOfWeek day_of_week = 3; + // Position of the item. Topmost is position 1. + optional int32 position = 4; + // Last usage time as hours since midnight in the local time zone. For + // previous queries, it is the time the user clicked on it on the + // same Chrome device. + optional int32 last_usage_time = 5; + // Time since the item was last used/clicked. This is a duration timestamp + // and will be in seconds. + optional int32 time_since_last_use = 6; + // Number of clicks each hour as bucketed by the hour. + optional int32 num_clicks_each_hour = 7; + // Physical device mode, e.g. TABLET, CLAMSHELL. + optional DeviceMode device_mode = 8; + // Bucketed previous query length + optional int32 query_length = 9; + } + + // Information related to a specific event. + message Event { + // Identifier used to associate all recommended items that were shown to the + // user. + optional int32 event_id = 1; + // Event time as hours since midnight in the local time zone. This is + // absolute timestamp and will be in hours. + optional int32 event_time = 2; + // Whether the item is clicked. + optional bool is_clicked = 3; + } + + optional Features features = 1; + optional Event event = 2; +}
diff --git a/chrome/browser/ui/apps/directory_access_confirmation_dialog.cc b/chrome/browser/ui/apps/directory_access_confirmation_dialog.cc index d5299d6e..b31b1a2 100644 --- a/chrome/browser/ui/apps/directory_access_confirmation_dialog.cc +++ b/chrome/browser/ui/apps/directory_access_confirmation_dialog.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/ui/apps/directory_access_confirmation_dialog.h" +#include <memory> + #include "base/callback.h" #include "chrome/browser/ui/tab_modal_confirm_dialog.h" #include "chrome/browser/ui/tab_modal_confirm_dialog_delegate.h" @@ -93,7 +95,7 @@ const base::Closure& on_accept, const base::Closure& on_cancel) { TabModalConfirmDialog::Create( - new DirectoryAccessConfirmationDialog( + std::make_unique<DirectoryAccessConfirmationDialog>( writable, app_name, web_contents, on_accept, on_cancel), web_contents); }
diff --git a/chrome/browser/ui/ash/assistant/device_actions.cc b/chrome/browser/ui/ash/assistant/device_actions.cc index f9dc5db..006ba96c 100644 --- a/chrome/browser/ui/ash/assistant/device_actions.cc +++ b/chrome/browser/ui/ash/assistant/device_actions.cc
@@ -81,9 +81,43 @@ kPackage, package_name.c_str(), kEndSuffix); } +std::vector<AndroidAppInfoPtr> GetAppsInfo() { + std::vector<AndroidAppInfoPtr> android_apps_info; + auto* prefs = ArcAppListPrefs::Get(ProfileManager::GetActiveUserProfile()); + if (!prefs) { + LOG(ERROR) << "ArcAppListPrefs is not available."; + return android_apps_info; + } + for (const auto& app_id : prefs->GetAppIds()) { + std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = prefs->GetApp(app_id); + if (!app_info) + continue; + AndroidAppInfoPtr app_info_ptr = + chromeos::assistant::mojom::AndroidAppInfo::New(); + app_info_ptr->package_name = app_info->package_name; + auto package = prefs->GetPackage(app_info->package_name); + if (package) + app_info_ptr->version = package->package_version; + app_info_ptr->localized_app_name = app_info->name; + app_info_ptr->intent = app_info->intent_uri; + android_apps_info.push_back(std::move(app_info_ptr)); + } + return android_apps_info; +} + +void NotifyAndroidAppListRefreshed( + mojo::InterfacePtrSet<chromeos::assistant::mojom::AppListEventSubscriber> + subscribers) { + std::vector<AndroidAppInfoPtr> android_apps_info = GetAppsInfo(); + + subscribers.ForAllPtrs([&android_apps_info](auto* ptr) { + ptr->OnAndroidAppListRefreshed(mojo::Clone(android_apps_info)); + }); +} + } // namespace -DeviceActions::DeviceActions() {} +DeviceActions::DeviceActions() : scoped_prefs_observer_(this) {} DeviceActions::~DeviceActions() { bindings_.CloseAllBindings(); @@ -172,9 +206,8 @@ std::move(callback).Run(!!app); } -void DeviceActions::VerifyAndroidApp( - std::vector<chromeos::assistant::mojom::AndroidAppInfoPtr> apps_info, - VerifyAndroidAppCallback callback) { +void DeviceActions::VerifyAndroidApp(std::vector<AndroidAppInfoPtr> apps_info, + VerifyAndroidAppCallback callback) { for (const auto& app_info : apps_info) { app_info->status = GetAndroidAppStatus(app_info->package_name); } @@ -192,3 +225,32 @@ // TODO(updowndota): Launch the intent in current active display. app->LaunchIntent(intent, display::kDefaultDisplayId); } + +void DeviceActions::AddAppListEventSubscriber( + chromeos::assistant::mojom::AppListEventSubscriberPtr subscriber) { + app_list_subscribers_.AddPtr(std::move(subscriber)); + auto* prefs = ArcAppListPrefs::Get(ProfileManager::GetActiveUserProfile()); + if (!prefs) + return; + + if (!scoped_prefs_observer_.IsObserving(prefs)) { + scoped_prefs_observer_.Add(prefs); + } + if (prefs->package_list_initial_refreshed()) { + std::vector<AndroidAppInfoPtr> android_apps_info = GetAppsInfo(); + subscriber->OnAndroidAppListRefreshed(mojo::Clone(android_apps_info)); + } +} + +void DeviceActions::OnPackageListInitialRefreshed() { + NotifyAndroidAppListRefreshed(app_list_subscribers_); +} + +void DeviceActions::OnAppRegistered(const std::string& app_id, + const ArcAppListPrefs::AppInfo& app_info) { + NotifyAndroidAppListRefreshed(app_list_subscribers_); +} + +void DeviceActions::OnAppRemoved(const std::string& id) { + NotifyAndroidAppListRefreshed(app_list_subscribers_); +}
diff --git a/chrome/browser/ui/ash/assistant/device_actions.h b/chrome/browser/ui/ash/assistant/device_actions.h index f6cca958..df934cc 100644 --- a/chrome/browser/ui/ash/assistant/device_actions.h +++ b/chrome/browser/ui/ash/assistant/device_actions.h
@@ -5,10 +5,14 @@ #ifndef CHROME_BROWSER_UI_ASH_ASSISTANT_DEVICE_ACTIONS_H_ #define CHROME_BROWSER_UI_ASH_ASSISTANT_DEVICE_ACTIONS_H_ +#include "base/scoped_observer.h" +#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" #include "chromeos/services/assistant/public/mojom/assistant.mojom.h" #include "mojo/public/cpp/bindings/binding_set.h" +#include "mojo/public/cpp/bindings/interface_ptr_set.h" -class DeviceActions : public chromeos::assistant::mojom::DeviceActions { +class DeviceActions : public chromeos::assistant::mojom::DeviceActions, + public ArcAppListPrefs::Observer { public: DeviceActions(); ~DeviceActions() override; @@ -28,10 +32,21 @@ std::vector<chromeos::assistant::mojom::AndroidAppInfoPtr> apps_info, VerifyAndroidAppCallback callback) override; void LaunchAndroidIntent(const std::string& intent) override; + void AddAppListEventSubscriber( + chromeos::assistant::mojom::AppListEventSubscriberPtr subscriber) + override; private: - mojo::BindingSet<chromeos::assistant::mojom::DeviceActions> bindings_; + // ArcAppListPrefs::Observer overrides. + void OnPackageListInitialRefreshed() override; + void OnAppRegistered(const std::string& app_id, + const ArcAppListPrefs::AppInfo& app_info) override; + void OnAppRemoved(const std::string& id) override; + ScopedObserver<ArcAppListPrefs, DeviceActions> scoped_prefs_observer_; + mojo::BindingSet<chromeos::assistant::mojom::DeviceActions> bindings_; + mojo::InterfacePtrSet<chromeos::assistant::mojom::AppListEventSubscriber> + app_list_subscribers_; DISALLOW_COPY_AND_ASSIGN(DeviceActions); };
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc index 1ed2b24..bd6aa73 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
@@ -1048,7 +1048,8 @@ // Initialize WallpaperControllerClient. wallpaper_controller_client_ = std::make_unique<WallpaperControllerClient>(); - wallpaper_controller_client_->InitForTesting(&test_wallpaper_controller_); + wallpaper_controller_client_->InitForTesting( + test_wallpaper_controller_.CreateInterfacePtr()); // AvatarMenu and multiple profiles works after user logged in. profile_manager()->SetLoggedIn(true);
diff --git a/chrome/browser/ui/ash/multi_user/multi_profile_support_unittest.cc b/chrome/browser/ui/ash/multi_user/multi_profile_support_unittest.cc index 99292b8..4123c2a 100644 --- a/chrome/browser/ui/ash/multi_user/multi_profile_support_unittest.cc +++ b/chrome/browser/ui/ash/multi_user/multi_profile_support_unittest.cc
@@ -278,7 +278,7 @@ user_manager::ScopedUserManager user_manager_enabler_; - std::unique_ptr<::WallpaperControllerClient> wallpaper_controller_client_; + std::unique_ptr<WallpaperControllerClient> wallpaper_controller_client_; TestWallpaperController test_wallpaper_controller_; @@ -315,9 +315,9 @@ AccountId::FromUserEmail("A")); ash::MultiUserWindowManagerImpl::Get()->SetAnimationSpeedForTest( ash::MultiUserWindowManagerImpl::ANIMATION_SPEED_DISABLED); - wallpaper_controller_client_ = - std::make_unique<::WallpaperControllerClient>(); - wallpaper_controller_client_->InitForTesting(&test_wallpaper_controller_); + wallpaper_controller_client_ = std::make_unique<WallpaperControllerClient>(); + wallpaper_controller_client_->InitForTesting( + test_wallpaper_controller_.CreateInterfacePtr()); } void MultiProfileSupportTest::TearDown() {
diff --git a/chrome/browser/ui/ash/test_login_screen.cc b/chrome/browser/ui/ash/test_login_screen.cc index 20d0d602..85de5f39 100644 --- a/chrome/browser/ui/ash/test_login_screen.cc +++ b/chrome/browser/ui/ash/test_login_screen.cc
@@ -46,10 +46,6 @@ const std::string& help_link_text, int32_t help_topic_id) {} -void TestLoginScreen::ShowWarningBanner(const base::string16& message) {} - -void TestLoginScreen::HideWarningBanner() {} - void TestLoginScreen::ClearErrors() {} void TestLoginScreen::SetAuthType(const AccountId& account_id,
diff --git a/chrome/browser/ui/ash/test_login_screen.h b/chrome/browser/ui/ash/test_login_screen.h index e9995927..6e08eee70 100644 --- a/chrome/browser/ui/ash/test_login_screen.h +++ b/chrome/browser/ui/ash/test_login_screen.h
@@ -35,8 +35,6 @@ const std::string& error_text, const std::string& help_link_text, int32_t help_topic_id) override; - void ShowWarningBanner(const base::string16& message) override; - void HideWarningBanner() override; void ClearErrors() override; void SetAuthType(const AccountId& account_id, ::proximity_auth::mojom::AuthType auth_type,
diff --git a/chrome/browser/ui/ash/test_login_screen_model.cc b/chrome/browser/ui/ash/test_login_screen_model.cc index df6cf8a..84e6a06 100644 --- a/chrome/browser/ui/ash/test_login_screen_model.cc +++ b/chrome/browser/ui/ash/test_login_screen_model.cc
@@ -14,6 +14,8 @@ void TestLoginScreenModel::ShowEasyUnlockIcon( const AccountId& account_id, const ash::EasyUnlockIconOptions& icon) {} +void TestLoginScreenModel::UpdateWarningMessage(const base::string16& message) { +} void TestLoginScreenModel::SetFingerprintState(const AccountId& account_id, ash::FingerprintState state) {} void TestLoginScreenModel::SetPublicSessionLocales(
diff --git a/chrome/browser/ui/ash/test_login_screen_model.h b/chrome/browser/ui/ash/test_login_screen_model.h index a3a4730..9104f5b 100644 --- a/chrome/browser/ui/ash/test_login_screen_model.h +++ b/chrome/browser/ui/ash/test_login_screen_model.h
@@ -21,6 +21,7 @@ ash::FingerprintState state) override; void ShowEasyUnlockIcon(const AccountId& user, const ash::EasyUnlockIconOptions& icon) override; + void UpdateWarningMessage(const base::string16& message) override; void SetPublicSessionLocales(const AccountId& account_id, const std::vector<ash::LocaleItem>& locales, const std::string& default_locale,
diff --git a/chrome/browser/ui/ash/test_wallpaper_controller.cc b/chrome/browser/ui/ash/test_wallpaper_controller.cc index 7d38d18..118e8e7 100644 --- a/chrome/browser/ui/ash/test_wallpaper_controller.cc +++ b/chrome/browser/ui/ash/test_wallpaper_controller.cc
@@ -4,24 +4,32 @@ #include "chrome/browser/ui/ash/test_wallpaper_controller.h" -#include "ash/public/cpp/wallpaper_controller_observer.h" +constexpr uint32_t dummy_image_id = 1; -TestWallpaperController::TestWallpaperController() = default; +TestWallpaperController::TestWallpaperController() : binding_(this) {} TestWallpaperController::~TestWallpaperController() = default; void TestWallpaperController::ShowWallpaperImage(const gfx::ImageSkia& image) { current_wallpaper = image; - for (auto& observer : observers_) - observer.OnWallpaperChanged(); + test_observers_.ForAllPtrs([](ash::mojom::WallpaperObserver* observer) { + observer->OnWallpaperChanged(dummy_image_id); + }); } void TestWallpaperController::ClearCounts() { remove_user_wallpaper_count_ = 0; } +ash::mojom::WallpaperControllerPtr +TestWallpaperController::CreateInterfacePtr() { + ash::mojom::WallpaperControllerPtr ptr; + binding_.Bind(mojo::MakeRequest(&ptr)); + return ptr; +} + void TestWallpaperController::Init( - ash::WallpaperControllerClient* client, + ash::mojom::WallpaperControllerClientPtr client, const base::FilePath& user_data_path, const base::FilePath& chromeos_wallpapers_path, const base::FilePath& chromeos_custom_wallpapers_path, @@ -30,7 +38,7 @@ } void TestWallpaperController::SetCustomWallpaper( - const ash::WallpaperUserInfo& user_info, + ash::mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id, const std::string& file_name, ash::WallpaperLayout layout, @@ -40,16 +48,17 @@ } void TestWallpaperController::SetOnlineWallpaperIfExists( - const ash::WallpaperUserInfo& user_info, + ash::mojom::WallpaperUserInfoPtr user_info, const std::string& url, ash::WallpaperLayout layout, bool preview_mode, - SetOnlineWallpaperIfExistsCallback callback) { + ash::mojom::WallpaperController::SetOnlineWallpaperIfExistsCallback + callback) { NOTIMPLEMENTED(); } void TestWallpaperController::SetOnlineWallpaperFromData( - const ash::WallpaperUserInfo& user_info, + ash::mojom::WallpaperUserInfoPtr user_info, const std::string& image_data, const std::string& url, ash::WallpaperLayout layout, @@ -59,7 +68,7 @@ } void TestWallpaperController::SetDefaultWallpaper( - const ash::WallpaperUserInfo& user_info, + ash::mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id, bool show_wallpaper) { ++set_default_wallpaper_count_; @@ -72,7 +81,7 @@ } void TestWallpaperController::SetPolicyWallpaper( - const ash::WallpaperUserInfo& user_info, + ash::mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id, const std::string& data) { NOTIMPLEMENTED(); @@ -83,14 +92,15 @@ NOTIMPLEMENTED(); } -bool TestWallpaperController::SetThirdPartyWallpaper( - const ash::WallpaperUserInfo& user_info, +void TestWallpaperController::SetThirdPartyWallpaper( + ash::mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id, const std::string& file_name, ash::WallpaperLayout layout, - const gfx::ImageSkia& image) { + const gfx::ImageSkia& image, + ash::mojom::WallpaperController::SetThirdPartyWallpaperCallback callback) { + std::move(callback).Run(true /*allowed=*/, dummy_image_id); ShowWallpaperImage(image); - return true; } void TestWallpaperController::ConfirmPreviewWallpaper() { @@ -102,13 +112,13 @@ } void TestWallpaperController::UpdateCustomWallpaperLayout( - const ash::WallpaperUserInfo& user_info, + ash::mojom::WallpaperUserInfoPtr user_info, ash::WallpaperLayout layout) { NOTIMPLEMENTED(); } void TestWallpaperController::ShowUserWallpaper( - const ash::WallpaperUserInfo& user_info) { + ash::mojom::WallpaperUserInfoPtr user_info) { NOTIMPLEMENTED(); } @@ -131,19 +141,19 @@ } void TestWallpaperController::RemoveUserWallpaper( - const ash::WallpaperUserInfo& user_info, + ash::mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id) { ++remove_user_wallpaper_count_; } void TestWallpaperController::RemovePolicyWallpaper( - const ash::WallpaperUserInfo& user_info, + ash::mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id) { NOTIMPLEMENTED(); } void TestWallpaperController::GetOfflineWallpaperList( - GetOfflineWallpaperListCallback callback) { + ash::mojom::WallpaperController::GetOfflineWallpaperListCallback callback) { NOTIMPLEMENTED(); } @@ -167,41 +177,41 @@ } void TestWallpaperController::AddObserver( - ash::WallpaperControllerObserver* observer) { - observers_.AddObserver(observer); + ash::mojom::WallpaperObserverAssociatedPtrInfo observer) { + ash::mojom::WallpaperObserverAssociatedPtr observer_ptr; + observer_ptr.Bind(std::move(observer)); + test_observers_.AddPtr(std::move(observer_ptr)); } -void TestWallpaperController::RemoveObserver( - ash::WallpaperControllerObserver* observer) { - observers_.RemoveObserver(observer); +void TestWallpaperController::GetWallpaperImage( + ash::mojom::WallpaperController::GetWallpaperImageCallback callback) { + std::move(callback).Run(current_wallpaper); } -gfx::ImageSkia TestWallpaperController::GetWallpaperImage() { - return current_wallpaper; -} - -const std::vector<SkColor>& TestWallpaperController::GetWallpaperColors() { +void TestWallpaperController::GetWallpaperColors( + ash::mojom::WallpaperController::GetWallpaperColorsCallback callback) { NOTIMPLEMENTED(); - static std::vector<SkColor> kColors; - return kColors; } -bool TestWallpaperController::IsWallpaperBlurred() { +void TestWallpaperController::IsWallpaperBlurred( + ash::mojom::WallpaperController::IsWallpaperBlurredCallback callback) { NOTIMPLEMENTED(); - return false; } -bool TestWallpaperController::IsActiveUserWallpaperControlledByPolicy() { +void TestWallpaperController::IsActiveUserWallpaperControlledByPolicy( + ash::mojom::WallpaperController:: + IsActiveUserWallpaperControlledByPolicyCallback callback) { NOTIMPLEMENTED(); - return false; } -ash::WallpaperInfo TestWallpaperController::GetActiveUserWallpaperInfo() { +void TestWallpaperController::GetActiveUserWallpaperInfo( + ash::mojom::WallpaperController::GetActiveUserWallpaperInfoCallback + callback) { NOTIMPLEMENTED(); - return {}; } -bool TestWallpaperController::ShouldShowWallpaperSetting() { +void TestWallpaperController::ShouldShowWallpaperSetting( + ash::mojom::WallpaperController::ShouldShowWallpaperSettingCallback + callback) { NOTIMPLEMENTED(); - return false; }
diff --git a/chrome/browser/ui/ash/test_wallpaper_controller.h b/chrome/browser/ui/ash/test_wallpaper_controller.h index 7eb6743..83b97fe0 100644 --- a/chrome/browser/ui/ash/test_wallpaper_controller.h +++ b/chrome/browser/ui/ash/test_wallpaper_controller.h
@@ -5,16 +5,17 @@ #ifndef CHROME_BROWSER_UI_ASH_TEST_WALLPAPER_CONTROLLER_H_ #define CHROME_BROWSER_UI_ASH_TEST_WALLPAPER_CONTROLLER_H_ -#include "ash/public/cpp/wallpaper_controller.h" +#include "ash/public/interfaces/wallpaper.mojom.h" #include "base/macros.h" -#include "base/observer_list.h" -#include "ui/gfx/image/image_skia.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/interface_ptr_set.h" // Simulates WallpaperController in ash. -class TestWallpaperController : public ash::WallpaperController { +class TestWallpaperController : ash::mojom::WallpaperController { public: TestWallpaperController(); - ~TestWallpaperController(); + + ~TestWallpaperController() override; // Simulates showing the wallpaper on screen by updating |current_wallpaper| // and notifying the observers. @@ -36,76 +37,98 @@ return remove_always_on_top_wallpaper_count_; } - // ash::WallpaperController: - void Init(ash::WallpaperControllerClient* client, + // Returns a mojo interface pointer bound to this object. + ash::mojom::WallpaperControllerPtr CreateInterfacePtr(); + + // ash::mojom::WallpaperController: + void Init(ash::mojom::WallpaperControllerClientPtr client, const base::FilePath& user_data_path, const base::FilePath& chromeos_wallpapers_path, const base::FilePath& chromeos_custom_wallpapers_path, const base::FilePath& device_policy_wallpaper_path) override; - void SetCustomWallpaper(const ash::WallpaperUserInfo& user_info, + void SetCustomWallpaper(ash::mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id, const std::string& file_name, ash::WallpaperLayout layout, const gfx::ImageSkia& image, bool preview_mode) override; void SetOnlineWallpaperIfExists( - const ash::WallpaperUserInfo& user_info, + ash::mojom::WallpaperUserInfoPtr user_info, const std::string& url, ash::WallpaperLayout layout, bool preview_mode, - SetOnlineWallpaperIfExistsCallback callback) override; + ash::mojom::WallpaperController::SetOnlineWallpaperIfExistsCallback + callback) override; void SetOnlineWallpaperFromData( - const ash::WallpaperUserInfo& user_info, + ash::mojom::WallpaperUserInfoPtr user_info, const std::string& image_data, const std::string& url, ash::WallpaperLayout layout, bool preview_mode, SetOnlineWallpaperFromDataCallback callback) override; - void SetDefaultWallpaper(const ash::WallpaperUserInfo& user_info, + void SetDefaultWallpaper(ash::mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id, bool show_wallpaper) override; void SetCustomizedDefaultWallpaperPaths( const base::FilePath& customized_default_small_path, const base::FilePath& customized_default_large_path) override; - void SetPolicyWallpaper(const ash::WallpaperUserInfo& user_info, + void SetPolicyWallpaper(ash::mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id, const std::string& data) override; void SetDevicePolicyWallpaperPath( const base::FilePath& device_policy_wallpaper_path) override; - bool SetThirdPartyWallpaper(const ash::WallpaperUserInfo& user_info, - const std::string& wallpaper_files_id, - const std::string& file_name, - ash::WallpaperLayout layout, - const gfx::ImageSkia& image) override; + void SetThirdPartyWallpaper( + ash::mojom::WallpaperUserInfoPtr user_info, + const std::string& wallpaper_files_id, + const std::string& file_name, + ash::WallpaperLayout layout, + const gfx::ImageSkia& image, + ash::mojom::WallpaperController::SetThirdPartyWallpaperCallback callback) + override; void ConfirmPreviewWallpaper() override; void CancelPreviewWallpaper() override; - void UpdateCustomWallpaperLayout(const ash::WallpaperUserInfo& user_info, + void UpdateCustomWallpaperLayout(ash::mojom::WallpaperUserInfoPtr user_info, ash::WallpaperLayout layout) override; - void ShowUserWallpaper(const ash::WallpaperUserInfo& user_info) override; + void ShowUserWallpaper(ash::mojom::WallpaperUserInfoPtr user_info) override; void ShowSigninWallpaper() override; void ShowOneShotWallpaper(const gfx::ImageSkia& image) override; void ShowAlwaysOnTopWallpaper(const base::FilePath& image_path) override; void RemoveAlwaysOnTopWallpaper() override; - void RemoveUserWallpaper(const ash::WallpaperUserInfo& user_info, + void RemoveUserWallpaper(ash::mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id) override; - void RemovePolicyWallpaper(const ash::WallpaperUserInfo& user_info, + void RemovePolicyWallpaper(ash::mojom::WallpaperUserInfoPtr user_info, const std::string& wallpaper_files_id) override; void GetOfflineWallpaperList( - GetOfflineWallpaperListCallback callback) override; + ash::mojom::WallpaperController::GetOfflineWallpaperListCallback callback) + override; void SetAnimationDuration(base::TimeDelta animation_duration) override; void OpenWallpaperPickerIfAllowed() override; void MinimizeInactiveWindows(const std::string& user_id_hash) override; void RestoreMinimizedWindows(const std::string& user_id_hash) override; - void AddObserver(ash::WallpaperControllerObserver* observer) override; - void RemoveObserver(ash::WallpaperControllerObserver* observer) override; - gfx::ImageSkia GetWallpaperImage() override; - const std::vector<SkColor>& GetWallpaperColors() override; - bool IsWallpaperBlurred() override; - bool IsActiveUserWallpaperControlledByPolicy() override; - ash::WallpaperInfo GetActiveUserWallpaperInfo() override; - bool ShouldShowWallpaperSetting() override; + void AddObserver( + ash::mojom::WallpaperObserverAssociatedPtrInfo observer) override; + void GetWallpaperImage( + ash::mojom::WallpaperController::GetWallpaperImageCallback callback) + override; + void GetWallpaperColors( + ash::mojom::WallpaperController::GetWallpaperColorsCallback callback) + override; + void IsWallpaperBlurred( + ash::mojom::WallpaperController::IsWallpaperBlurredCallback callback) + override; + void IsActiveUserWallpaperControlledByPolicy( + ash::mojom::WallpaperController:: + IsActiveUserWallpaperControlledByPolicyCallback callback) override; + void GetActiveUserWallpaperInfo( + ash::mojom::WallpaperController::GetActiveUserWallpaperInfoCallback + callback) override; + void ShouldShowWallpaperSetting( + ash::mojom::WallpaperController::ShouldShowWallpaperSettingCallback + callback) override; private: + mojo::Binding<ash::mojom::WallpaperController> binding_; + bool was_client_set_ = false; int remove_user_wallpaper_count_ = 0; int set_default_wallpaper_count_ = 0; @@ -113,7 +136,8 @@ int show_always_on_top_wallpaper_count_ = 0; int remove_always_on_top_wallpaper_count_ = 0; - base::ObserverList<ash::WallpaperControllerObserver>::Unchecked observers_; + mojo::AssociatedInterfacePtrSet<ash::mojom::WallpaperObserver> + test_observers_; gfx::ImageSkia current_wallpaper;
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client.cc b/chrome/browser/ui/ash/wallpaper_controller_client.cc index fed413b..026caed 100644 --- a/chrome/browser/ui/ash/wallpaper_controller_client.cc +++ b/chrome/browser/ui/ash/wallpaper_controller_client.cc
@@ -4,7 +4,7 @@ #include "chrome/browser/ui/ash/wallpaper_controller_client.h" -#include "ash/public/cpp/wallpaper_user_info.h" +#include "ash/public/interfaces/constants.mojom.h" #include "base/bind.h" #include "base/hash/sha1.h" #include "base/path_service.h" @@ -40,26 +40,27 @@ WallpaperControllerClient* g_wallpaper_controller_client_instance = nullptr; -// Creates a WallpaperUserInfo for the account id. Returns nullptr if user -// manager cannot find the user. -base::Optional<ash::WallpaperUserInfo> AccountIdToWallpaperUserInfo( +// Creates a mojom::WallpaperUserInfo for the account id. Returns nullptr if +// user manager cannot find the user. +ash::mojom::WallpaperUserInfoPtr AccountIdToWallpaperUserInfo( const AccountId& account_id) { if (!account_id.is_valid()) { // |account_id| may be invalid in tests. - return base::nullopt; + return nullptr; } const user_manager::User* user = user_manager::UserManager::Get()->FindUser(account_id); if (!user) - return base::nullopt; + return nullptr; - ash::WallpaperUserInfo wallpaper_user_info; - wallpaper_user_info.account_id = account_id; - wallpaper_user_info.type = user->GetType(); - wallpaper_user_info.is_ephemeral = + ash::mojom::WallpaperUserInfoPtr wallpaper_user_info = + ash::mojom::WallpaperUserInfo::New(); + wallpaper_user_info->account_id = account_id; + wallpaper_user_info->type = user->GetType(); + wallpaper_user_info->is_ephemeral = user_manager::UserManager::Get()->IsUserNonCryptohomeDataEphemeral( account_id); - wallpaper_user_info.has_gaia_account = user->HasGaiaAccount(); + wallpaper_user_info->has_gaia_account = user->HasGaiaAccount(); return wallpaper_user_info; } @@ -133,7 +134,8 @@ } // namespace -WallpaperControllerClient::WallpaperControllerClient() : weak_factory_(this) { +WallpaperControllerClient::WallpaperControllerClient() + : binding_(this), weak_factory_(this) { local_state_ = g_browser_process->local_state(); show_user_names_on_signin_subscription_ = chromeos::CrosSettings::Get()->AddSettingsObserver( @@ -159,14 +161,16 @@ base::BindRepeating( &WallpaperControllerClient::DeviceWallpaperImageFilePathChanged, weak_factory_.GetWeakPtr())); - wallpaper_controller_ = ash::WallpaperController::Get(); - InitController(); + content::ServiceManagerConnection::GetForProcess() + ->GetConnector() + ->BindInterface(ash::mojom::kServiceName, &wallpaper_controller_); + BindAndSetClient(); } void WallpaperControllerClient::InitForTesting( - ash::WallpaperController* controller) { - wallpaper_controller_ = controller; - InitController(); + ash::mojom::WallpaperControllerPtr controller) { + wallpaper_controller_ = std::move(controller); + BindAndSetClient(); } // static @@ -197,10 +201,11 @@ ash::WallpaperLayout layout, const gfx::ImageSkia& image, bool preview_mode) { - auto user_info = AccountIdToWallpaperUserInfo(account_id); + ash::mojom::WallpaperUserInfoPtr user_info = + AccountIdToWallpaperUserInfo(account_id); if (!user_info) return; - wallpaper_controller_->SetCustomWallpaper(user_info.value(), + wallpaper_controller_->SetCustomWallpaper(std::move(user_info), wallpaper_files_id, file_name, layout, image, preview_mode); } @@ -210,12 +215,14 @@ const std::string& url, ash::WallpaperLayout layout, bool preview_mode, - ash::WallpaperController::SetOnlineWallpaperIfExistsCallback callback) { - auto user_info = AccountIdToWallpaperUserInfo(account_id); + ash::mojom::WallpaperController::SetOnlineWallpaperIfExistsCallback + callback) { + ash::mojom::WallpaperUserInfoPtr user_info = + AccountIdToWallpaperUserInfo(account_id); if (!user_info) return; wallpaper_controller_->SetOnlineWallpaperIfExists( - user_info.value(), url, layout, preview_mode, std::move(callback)); + std::move(user_info), url, layout, preview_mode, std::move(callback)); } void WallpaperControllerClient::SetOnlineWallpaperFromData( @@ -224,18 +231,21 @@ const std::string& url, ash::WallpaperLayout layout, bool preview_mode, - ash::WallpaperController::SetOnlineWallpaperFromDataCallback callback) { - auto user_info = AccountIdToWallpaperUserInfo(account_id); + ash::mojom::WallpaperController::SetOnlineWallpaperFromDataCallback + callback) { + ash::mojom::WallpaperUserInfoPtr user_info = + AccountIdToWallpaperUserInfo(account_id); if (!user_info) return; wallpaper_controller_->SetOnlineWallpaperFromData( - user_info.value(), image_data, url, layout, preview_mode, + std::move(user_info), image_data, url, layout, preview_mode, std::move(callback)); } void WallpaperControllerClient::SetDefaultWallpaper(const AccountId& account_id, bool show_wallpaper) { - auto user_info = AccountIdToWallpaperUserInfo(account_id); + ash::mojom::WallpaperUserInfoPtr user_info = + AccountIdToWallpaperUserInfo(account_id); if (!user_info) return; @@ -251,7 +261,7 @@ } wallpaper_controller_->SetDefaultWallpaper( - user_info.value(), GetFilesId(account_id), show_wallpaper); + std::move(user_info), GetFilesId(account_id), show_wallpaper); } void WallpaperControllerClient::SetCustomizedDefaultWallpaperPaths( @@ -267,7 +277,8 @@ if (!data) return; - auto user_info = AccountIdToWallpaperUserInfo(account_id); + ash::mojom::WallpaperUserInfoPtr user_info = + AccountIdToWallpaperUserInfo(account_id); if (!user_info) return; @@ -280,21 +291,24 @@ return; } - wallpaper_controller_->SetPolicyWallpaper(user_info.value(), + wallpaper_controller_->SetPolicyWallpaper(std::move(user_info), GetFilesId(account_id), *data); } -bool WallpaperControllerClient::SetThirdPartyWallpaper( +void WallpaperControllerClient::SetThirdPartyWallpaper( const AccountId& account_id, const std::string& wallpaper_files_id, const std::string& file_name, ash::WallpaperLayout layout, - const gfx::ImageSkia& image) { - auto user_info = AccountIdToWallpaperUserInfo(account_id); + const gfx::ImageSkia& image, + ash::mojom::WallpaperController::SetThirdPartyWallpaperCallback callback) { + ash::mojom::WallpaperUserInfoPtr user_info = + AccountIdToWallpaperUserInfo(account_id); if (!user_info) - return false; - return wallpaper_controller_->SetThirdPartyWallpaper( - user_info.value(), wallpaper_files_id, file_name, layout, image); + return; + wallpaper_controller_->SetThirdPartyWallpaper( + std::move(user_info), wallpaper_files_id, file_name, layout, image, + std::move(callback)); } void WallpaperControllerClient::ConfirmPreviewWallpaper() { @@ -308,17 +322,20 @@ void WallpaperControllerClient::UpdateCustomWallpaperLayout( const AccountId& account_id, ash::WallpaperLayout layout) { - auto user_info = AccountIdToWallpaperUserInfo(account_id); + ash::mojom::WallpaperUserInfoPtr user_info = + AccountIdToWallpaperUserInfo(account_id); if (!user_info) return; - wallpaper_controller_->UpdateCustomWallpaperLayout(user_info.value(), layout); + wallpaper_controller_->UpdateCustomWallpaperLayout(std::move(user_info), + layout); } void WallpaperControllerClient::ShowUserWallpaper(const AccountId& account_id) { - auto user_info = AccountIdToWallpaperUserInfo(account_id); + ash::mojom::WallpaperUserInfoPtr user_info = + AccountIdToWallpaperUserInfo(account_id); if (!user_info) return; - wallpaper_controller_->ShowUserWallpaper(user_info.value()); + wallpaper_controller_->ShowUserWallpaper(std::move(user_info)); } void WallpaperControllerClient::ShowSigninWallpaper() { @@ -336,7 +353,8 @@ void WallpaperControllerClient::RemoveUserWallpaper( const AccountId& account_id) { - auto user_info = AccountIdToWallpaperUserInfo(account_id); + ash::mojom::WallpaperUserInfoPtr user_info = + AccountIdToWallpaperUserInfo(account_id); if (!user_info) return; @@ -351,13 +369,14 @@ return; } - wallpaper_controller_->RemoveUserWallpaper(user_info.value(), + wallpaper_controller_->RemoveUserWallpaper(std::move(user_info), GetFilesId(account_id)); } void WallpaperControllerClient::RemovePolicyWallpaper( const AccountId& account_id) { - auto user_info = AccountIdToWallpaperUserInfo(account_id); + ash::mojom::WallpaperUserInfoPtr user_info = + AccountIdToWallpaperUserInfo(account_id); if (!user_info) return; @@ -372,12 +391,12 @@ return; } - wallpaper_controller_->RemovePolicyWallpaper(user_info.value(), + wallpaper_controller_->RemovePolicyWallpaper(std::move(user_info), GetFilesId(account_id)); } void WallpaperControllerClient::GetOfflineWallpaperList( - ash::WallpaperController::GetOfflineWallpaperListCallback callback) { + ash::mojom::WallpaperController::GetOfflineWallpaperListCallback callback) { wallpaper_controller_->GetOfflineWallpaperList(std::move(callback)); } @@ -401,37 +420,42 @@ } void WallpaperControllerClient::AddObserver( - ash::WallpaperControllerObserver* observer) { - wallpaper_controller_->AddObserver(observer); + ash::mojom::WallpaperObserverAssociatedPtrInfo observer) { + wallpaper_controller_->AddObserver(std::move(observer)); } -void WallpaperControllerClient::RemoveObserver( - ash::WallpaperControllerObserver* observer) { - wallpaper_controller_->RemoveObserver(observer); +void WallpaperControllerClient::GetWallpaperImage( + ash::mojom::WallpaperController::GetWallpaperImageCallback callback) { + wallpaper_controller_->GetWallpaperImage(std::move(callback)); } -gfx::ImageSkia WallpaperControllerClient::GetWallpaperImage() { - return wallpaper_controller_->GetWallpaperImage(); +void WallpaperControllerClient::GetWallpaperColors( + ash::mojom::WallpaperController::GetWallpaperColorsCallback callback) { + wallpaper_controller_->GetWallpaperColors(std::move(callback)); } -const std::vector<SkColor>& WallpaperControllerClient::GetWallpaperColors() { - return wallpaper_controller_->GetWallpaperColors(); +void WallpaperControllerClient::IsWallpaperBlurred( + ash::mojom::WallpaperController::IsWallpaperBlurredCallback callback) { + wallpaper_controller_->IsWallpaperBlurred(std::move(callback)); } -bool WallpaperControllerClient::IsWallpaperBlurred() { - return wallpaper_controller_->IsWallpaperBlurred(); +void WallpaperControllerClient::IsActiveUserWallpaperControlledByPolicy( + ash::mojom::WallpaperController:: + IsActiveUserWallpaperControlledByPolicyCallback callback) { + wallpaper_controller_->IsActiveUserWallpaperControlledByPolicy( + std::move(callback)); } -bool WallpaperControllerClient::IsActiveUserWallpaperControlledByPolicy() { - return wallpaper_controller_->IsActiveUserWallpaperControlledByPolicy(); +void WallpaperControllerClient::GetActiveUserWallpaperInfo( + ash::mojom::WallpaperController::GetActiveUserWallpaperInfoCallback + callback) { + wallpaper_controller_->GetActiveUserWallpaperInfo(std::move(callback)); } -ash::WallpaperInfo WallpaperControllerClient::GetActiveUserWallpaperInfo() { - return wallpaper_controller_->GetActiveUserWallpaperInfo(); -} - -bool WallpaperControllerClient::ShouldShowWallpaperSetting() { - return wallpaper_controller_->ShouldShowWallpaperSetting(); +void WallpaperControllerClient::ShouldShowWallpaperSetting( + ash::mojom::WallpaperController::ShouldShowWallpaperSettingCallback + callback) { + wallpaper_controller_->ShouldShowWallpaperSetting(std::move(callback)); } void WallpaperControllerClient::DeviceWallpaperImageFilePathChanged() { @@ -439,7 +463,14 @@ GetDeviceWallpaperImageFilePath()); } -void WallpaperControllerClient::InitController() { +void WallpaperControllerClient::FlushForTesting() { + wallpaper_controller_.FlushForTesting(); +} + +void WallpaperControllerClient::BindAndSetClient() { + ash::mojom::WallpaperControllerClientPtr client; + binding_.Bind(mojo::MakeRequest(&client)); + // Get the paths of wallpaper directories. base::FilePath user_data_path; CHECK(base::PathService::Get(chrome::DIR_USER_DATA, &user_data_path)); @@ -453,9 +484,9 @@ base::FilePath device_policy_wallpaper_path = GetDeviceWallpaperImageFilePath(); - wallpaper_controller_->Init(this, user_data_path, chromeos_wallpapers_path, - chromeos_custom_wallpapers_path, - device_policy_wallpaper_path); + wallpaper_controller_->Init( + std::move(client), user_data_path, chromeos_wallpapers_path, + chromeos_custom_wallpapers_path, device_policy_wallpaper_path); } void WallpaperControllerClient::ShowWallpaperOnLoginScreen() {
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client.h b/chrome/browser/ui/ash/wallpaper_controller_client.h index 11d72c5..5d515b0 100644 --- a/chrome/browser/ui/ash/wallpaper_controller_client.h +++ b/chrome/browser/ui/ash/wallpaper_controller_client.h
@@ -7,33 +7,32 @@ #include <memory> -#include "ash/public/cpp/wallpaper_controller.h" -#include "ash/public/cpp/wallpaper_controller_client.h" #include "ash/public/cpp/wallpaper_types.h" +#include "ash/public/interfaces/wallpaper.mojom.h" #include "base/macros.h" #include "chrome/browser/chromeos/settings/cros_settings.h" #include "components/prefs/pref_change_registrar.h" +#include "mojo/public/cpp/bindings/binding.h" -class AccountId; - -// Handles chrome-side wallpaper control alongside the ash-side controller. -class WallpaperControllerClient : public ash::WallpaperControllerClient { +// Handles method calls sent from ash to chrome. Also sends messages from chrome +// to ash. +class WallpaperControllerClient : public ash::mojom::WallpaperControllerClient { public: WallpaperControllerClient(); - virtual ~WallpaperControllerClient(); + ~WallpaperControllerClient() override; // Initializes and connects to ash. void Init(); - // Tests can provide a mock interface for the ash controller. - void InitForTesting(ash::WallpaperController* controller); + // Tests can provide a mock mojo interface for the ash controller. + void InitForTesting(ash::mojom::WallpaperControllerPtr controller); static WallpaperControllerClient* Get(); // Returns files identifier for the |account_id|. std::string GetFilesId(const AccountId& account_id) const; - // Wrappers around the ash::WallpaperController interface. + // Wrappers around the ash::mojom::WallpaperController interface. void SetCustomWallpaper(const AccountId& account_id, const std::string& wallpaper_files_id, const std::string& file_name, @@ -45,25 +44,29 @@ const std::string& url, ash::WallpaperLayout layout, bool preview_mode, - ash::WallpaperController::SetOnlineWallpaperIfExistsCallback callback); + ash::mojom::WallpaperController::SetOnlineWallpaperIfExistsCallback + callback); void SetOnlineWallpaperFromData( const AccountId& account_id, const std::string& image_data, const std::string& url, ash::WallpaperLayout layout, bool preview_mode, - ash::WallpaperController::SetOnlineWallpaperFromDataCallback callback); + ash::mojom::WallpaperController::SetOnlineWallpaperFromDataCallback + callback); void SetDefaultWallpaper(const AccountId& account_id, bool show_wallpaper); void SetCustomizedDefaultWallpaperPaths( const base::FilePath& customized_default_small_path, const base::FilePath& customized_default_large_path); void SetPolicyWallpaper(const AccountId& account_id, std::unique_ptr<std::string> data); - bool SetThirdPartyWallpaper(const AccountId& account_id, - const std::string& wallpaper_files_id, - const std::string& file_name, - ash::WallpaperLayout layout, - const gfx::ImageSkia& image); + void SetThirdPartyWallpaper( + const AccountId& account_id, + const std::string& wallpaper_files_id, + const std::string& file_name, + ash::WallpaperLayout layout, + const gfx::ImageSkia& image, + ash::mojom::WallpaperController::SetThirdPartyWallpaperCallback callback); void ConfirmPreviewWallpaper(); void CancelPreviewWallpaper(); void UpdateCustomWallpaperLayout(const AccountId& account_id, @@ -75,30 +78,42 @@ void RemoveUserWallpaper(const AccountId& account_id); void RemovePolicyWallpaper(const AccountId& account_id); void GetOfflineWallpaperList( - ash::WallpaperController::GetOfflineWallpaperListCallback callback); + ash::mojom::WallpaperController::GetOfflineWallpaperListCallback + callback); void SetAnimationDuration(const base::TimeDelta& animation_duration); void OpenWallpaperPickerIfAllowed(); void MinimizeInactiveWindows(const std::string& user_id_hash); void RestoreMinimizedWindows(const std::string& user_id_hash); - void AddObserver(ash::WallpaperControllerObserver* observer); - void RemoveObserver(ash::WallpaperControllerObserver* observer); - gfx::ImageSkia GetWallpaperImage(); - const std::vector<SkColor>& GetWallpaperColors(); - bool IsWallpaperBlurred(); - bool IsActiveUserWallpaperControlledByPolicy(); - ash::WallpaperInfo GetActiveUserWallpaperInfo(); - bool ShouldShowWallpaperSetting(); + void AddObserver(ash::mojom::WallpaperObserverAssociatedPtrInfo observer); + void GetWallpaperImage( + ash::mojom::WallpaperController::GetWallpaperImageCallback callback); + void GetWallpaperColors( + ash::mojom::WallpaperController::GetWallpaperColorsCallback callback); + void IsWallpaperBlurred( + ash::mojom::WallpaperController::IsWallpaperBlurredCallback callback); + void IsActiveUserWallpaperControlledByPolicy( + ash::mojom::WallpaperController:: + IsActiveUserWallpaperControlledByPolicyCallback callback); + void GetActiveUserWallpaperInfo( + ash::mojom::WallpaperController::GetActiveUserWallpaperInfoCallback + callback); + void ShouldShowWallpaperSetting( + ash::mojom::WallpaperController::ShouldShowWallpaperSettingCallback + callback); + + // Flushes the mojo pipe to ash. + void FlushForTesting(); private: - // Initialize the controller for this client and some wallpaper directories. - void InitController(); + // Binds this object to its mojo interface and sets it as the ash client. + void BindAndSetClient(); // Shows the wallpaper of the first user in |UserManager::GetUsers|, or a // default signin wallpaper if there's no user. This ensures the wallpaper is // shown right after boot, regardless of when the login screen is available. void ShowWallpaperOnLoginScreen(); - // ash::WallpaperControllerClient: + // ash::mojom::WallpaperControllerClient: void OpenWallpaperPicker() override; void OnReadyToSetWallpaper() override; void OnFirstWallpaperAnimationFinished() override; @@ -111,7 +126,7 @@ base::FilePath GetDeviceWallpaperImageFilePath(); // WallpaperController interface in ash. - ash::WallpaperController* wallpaper_controller_; + ash::mojom::WallpaperControllerPtr wallpaper_controller_; PrefService* local_state_; @@ -123,6 +138,9 @@ std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> show_user_names_on_signin_subscription_; + // Binds to the client interface. + mojo::Binding<ash::mojom::WallpaperControllerClient> binding_; + base::WeakPtrFactory<WallpaperControllerClient> weak_factory_; DISALLOW_COPY_AND_ASSIGN(WallpaperControllerClient);
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client_unittest.cc b/chrome/browser/ui/ash/wallpaper_controller_client_unittest.cc index 4cfa016..14bea4c 100644 --- a/chrome/browser/ui/ash/wallpaper_controller_client_unittest.cc +++ b/chrome/browser/ui/ash/wallpaper_controller_client_unittest.cc
@@ -30,7 +30,8 @@ TEST_F(WallpaperControllerClientTest, Construction) { WallpaperControllerClient client; TestWallpaperController controller; - client.InitForTesting(&controller); + client.InitForTesting(controller.CreateInterfacePtr()); + client.FlushForTesting(); // Singleton was initialized. EXPECT_EQ(&client, WallpaperControllerClient::Get());
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 5570973..10231fb1 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -1551,8 +1551,8 @@ } void Browser::ShowRepostFormWarningDialog(WebContents* source) { - TabModalConfirmDialog::Create(new RepostFormWarningController(source), - source); + TabModalConfirmDialog::Create( + std::make_unique<RepostFormWarningController>(source), source); } bool Browser::ShouldCreateWebContents(
diff --git a/chrome/browser/ui/browser_command_controller_browsertest.cc b/chrome/browser/ui/browser_command_controller_browsertest.cc index 7978ad48..798aafbf 100644 --- a/chrome/browser/ui/browser_command_controller_browsertest.cc +++ b/chrome/browser/ui/browser_command_controller_browsertest.cc
@@ -66,9 +66,10 @@ // Showing constrained window should disable find. content::WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); - MockTabModalConfirmDialogDelegate* delegate = - new MockTabModalConfirmDialogDelegate(web_contents, NULL); - TabModalConfirmDialog::Create(delegate, web_contents); + auto delegate = std::make_unique<MockTabModalConfirmDialogDelegate>( + web_contents, nullptr); + MockTabModalConfirmDialogDelegate* delegate_ptr = delegate.get(); + TabModalConfirmDialog::Create(std::move(delegate), web_contents); EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_FIND)); // Switching to a new (unblocked) tab should reenable it. @@ -80,7 +81,7 @@ EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_FIND)); // Closing the constrained window should reenable it. - delegate->Cancel(); + delegate_ptr->Cancel(); content::RunAllPendingInMessageLoop(); EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FIND)); }
diff --git a/chrome/browser/ui/search/local_ntp_browsertest.cc b/chrome/browser/ui/search/local_ntp_browsertest.cc index 2a64453..6aab086 100644 --- a/chrome/browser/ui/search/local_ntp_browsertest.cc +++ b/chrome/browser/ui/search/local_ntp_browsertest.cc
@@ -36,6 +36,7 @@ #include "chrome/test/base/ui_test_utils.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/ntp_tiles/constants.h" +#include "components/ntp_tiles/features.h" #include "components/prefs/pref_service.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/interstitial_page.h" @@ -81,6 +82,16 @@ return nullptr; } +bool ContainsDefaultSearchTile(content::RenderFrameHost* iframe) { + int num_search_tiles; + EXPECT_TRUE( + instant_test_utils::GetIntFromJS(iframe, + "document.querySelectorAll(\".md-tile[" + "href='https://google.com/']\").length", + &num_search_tiles)); + return num_search_tiles == 1; +} + class LocalNTPTest : public InProcessBrowserTest { public: LocalNTPTest(const std::vector<base::Feature>& enabled_features, @@ -844,4 +855,41 @@ EXPECT_TRUE(search::IsInstantNTP(active_tab)); } +class LocalNTPNoSearchShortcutTest : public LocalNTPTest { + public: + LocalNTPNoSearchShortcutTest() + : LocalNTPTest({}, {ntp_tiles::kDefaultSearchShortcut}) {} +}; + +IN_PROC_BROWSER_TEST_F(LocalNTPNoSearchShortcutTest, SearchShortcutHidden) { + content::WebContents* active_tab = + local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank")); + + local_ntp_test_utils::NavigateToNTPAndWaitUntilLoaded(browser()); + ASSERT_TRUE(search::IsInstantNTP(active_tab)); + + content::RenderFrameHost* iframe = GetIframe(active_tab, "mv-single"); + + EXPECT_FALSE(ContainsDefaultSearchTile(iframe)); +} + +#if defined(GOOGLE_CHROME_BUILD) +class LocalNTPSearchShortcutTest : public LocalNTPTest { + public: + LocalNTPSearchShortcutTest() + : LocalNTPTest({ntp_tiles::kDefaultSearchShortcut}, {}) {} +}; + +IN_PROC_BROWSER_TEST_F(LocalNTPSearchShortcutTest, SearchShortcutShown) { + content::WebContents* active_tab = + local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank")); + local_ntp_test_utils::NavigateToNTPAndWaitUntilLoaded(browser()); + ASSERT_TRUE(search::IsInstantNTP(active_tab)); + + content::RenderFrameHost* iframe = GetIframe(active_tab, kMostVisitedIframe); + + EXPECT_TRUE(ContainsDefaultSearchTile(iframe)); +} +#endif + } // namespace
diff --git a/chrome/browser/ui/tab_modal_confirm_dialog.h b/chrome/browser/ui/tab_modal_confirm_dialog.h index 9ecc4ba0..cbc0ea2 100644 --- a/chrome/browser/ui/tab_modal_confirm_dialog.h +++ b/chrome/browser/ui/tab_modal_confirm_dialog.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_UI_TAB_MODAL_CONFIRM_DIALOG_H_ #define CHROME_BROWSER_UI_TAB_MODAL_CONFIRM_DIALOG_H_ +#include <memory> + #include "build/build_config.h" #include "chrome/browser/ui/tab_modal_confirm_dialog_delegate.h" @@ -17,8 +19,9 @@ public: // Platform specific factory function. This function will automatically show // the dialog. - static TabModalConfirmDialog* Create(TabModalConfirmDialogDelegate* delegate, - content::WebContents* web_contents); + static TabModalConfirmDialog* Create( + std::unique_ptr<TabModalConfirmDialogDelegate> delegate, + content::WebContents* web_contents); // Accepts the dialog. virtual void AcceptTabModalDialog() = 0;
diff --git a/chrome/browser/ui/tab_modal_confirm_dialog_browsertest.cc b/chrome/browser/ui/tab_modal_confirm_dialog_browsertest.cc index bb56ae9..cb6d14f 100644 --- a/chrome/browser/ui/tab_modal_confirm_dialog_browsertest.cc +++ b/chrome/browser/ui/tab_modal_confirm_dialog_browsertest.cc
@@ -4,6 +4,9 @@ #include "chrome/browser/ui/tab_modal_confirm_dialog_browsertest.h" +#include <memory> +#include <utility> + #include "base/bind.h" #include "base/location.h" #include "base/single_thread_task_runner.h" @@ -57,10 +60,12 @@ closed_count_(0) {} void TabModalConfirmDialogTest::SetUpOnMainThread() { - delegate_ = new MockTabModalConfirmDialogDelegate( + auto delegate = std::make_unique<MockTabModalConfirmDialogDelegate>( browser()->tab_strip_model()->GetActiveWebContents(), this); + delegate_ = delegate.get(); dialog_ = TabModalConfirmDialog::Create( - delegate_, browser()->tab_strip_model()->GetActiveWebContents()); + std::move(delegate), + browser()->tab_strip_model()->GetActiveWebContents()); content::RunAllPendingInMessageLoop(); }
diff --git a/chrome/browser/ui/views/autofill/payments/save_card_bubble_views_browsertest.cc b/chrome/browser/ui/views/autofill/payments/save_card_bubble_views_browsertest.cc index 4c4ff5b..31f6e8e 100644 --- a/chrome/browser/ui/views/autofill/payments/save_card_bubble_views_browsertest.cc +++ b/chrome/browser/ui/views/autofill/payments/save_card_bubble_views_browsertest.cc
@@ -40,6 +40,7 @@ #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/form_data_importer.h" #include "components/autofill/core/browser/payments/credit_card_save_manager.h" +#include "components/autofill/core/browser/payments/credit_card_save_strike_database.h" #include "components/autofill/core/browser/payments/payments_client.h" #include "components/autofill/core/browser/test_autofill_clock.h" #include "components/autofill/core/browser/test_event_waiter.h" @@ -181,14 +182,13 @@ ->set_url_loader_factory_for_testing(test_shared_loader_factory_); // Set up this class as the ObserverForTest implementation. - CreditCardSaveManager* credit_card_save_manager = - ContentAutofillDriver::GetForRenderFrameHost( - GetActiveWebContents()->GetMainFrame()) - ->autofill_manager() - ->client() - ->GetFormDataImporter() - ->credit_card_save_manager_.get(); - credit_card_save_manager->SetEventObserverForTesting(this); + credit_card_save_manager_ = ContentAutofillDriver::GetForRenderFrameHost( + GetActiveWebContents()->GetMainFrame()) + ->autofill_manager() + ->client() + ->GetFormDataImporter() + ->credit_card_save_manager_.get(); + credit_card_save_manager_->SetEventObserverForTesting(this); // Set up this class as the ObserverForTest implementation. AutofillHandler* autofill_handler = @@ -731,6 +731,8 @@ std::unique_ptr<ProfileSyncServiceHarness> harness_; + CreditCardSaveManager* credit_card_save_manager_ = nullptr; + private: std::unique_ptr<autofill::EventWaiter<DialogEvent>> event_waiter_; std::unique_ptr<net::FakeURLFetcherFactory> url_fetcher_factory_; @@ -2587,9 +2589,11 @@ bool controller_observer_set = false; - // Show and ignore the bubble kMaxStrikesToPreventPoppingUpOfferToSavePrompt - // times in order to accrue maximum strikes. - for (int i = 0; i < kMaxStrikesToPreventPoppingUpOfferToSavePrompt; i++) { + // Show and ignore the bubble enough times in order to accrue maximum strikes. + for (int i = 0; + i < credit_card_save_manager_->GetCreditCardSaveStrikeDatabase() + ->GetMaxStrikesLimit(); + ++i) { // Submitting the form and having Payments decline offering to save should // show the local save bubble. // (Must wait for response from Payments before accessing the controller.) @@ -2675,9 +2679,11 @@ // Set up the Payments RPC. SetUploadDetailsRpcPaymentsAccepts(); - // Show and ignore the bubble kMaxStrikesToPreventPoppingUpOfferToSavePrompt - // times in order to accrue maximum strikes. - for (int i = 0; i < kMaxStrikesToPreventPoppingUpOfferToSavePrompt; i++) { + // Show and ignore the bubble enough times in order to accrue maximum strikes. + for (int i = 0; + i < credit_card_save_manager_->GetCreditCardSaveStrikeDatabase() + ->GetMaxStrikesLimit(); + ++i) { // Submitting the form should show the upload save bubble and legal footer. // (Must wait for response from Payments before accessing the controller.) ResetEventWaiterForSequence(
diff --git a/chrome/browser/ui/views/frame/browser_view_browsertest.cc b/chrome/browser/ui/views/frame/browser_view_browsertest.cc index f83f45e6..72d1c68 100644 --- a/chrome/browser/ui/views/frame/browser_view_browsertest.cc +++ b/chrome/browser/ui/views/frame/browser_view_browsertest.cc
@@ -317,12 +317,14 @@ window_title, base::CompareCase::SENSITIVE)); content::WebContents* contents = browser_view()->GetActiveWebContents(); - TestTabModalConfirmDialogDelegate* delegate = - new TestTabModalConfirmDialogDelegate(contents); - TabModalConfirmDialog::Create(delegate, contents); - EXPECT_EQ(browser_view()->GetAccessibleWindowTitle(), delegate->GetTitle()); + auto delegate = std::make_unique<TestTabModalConfirmDialogDelegate>(contents); + TestTabModalConfirmDialogDelegate* delegate_observer = delegate.get(); + TabModalConfirmDialog::Create(std::move(delegate), contents); + EXPECT_EQ(browser_view()->GetAccessibleWindowTitle(), + delegate_observer->GetTitle()); - delegate->Close(); + delegate_observer->Close(); + EXPECT_TRUE(base::StartsWith(browser_view()->GetAccessibleWindowTitle(), window_title, base::CompareCase::SENSITIVE)); } @@ -349,9 +351,8 @@ nullptr); content::WebContents* contents = browser_view()->GetActiveWebContents(); - TestTabModalConfirmDialogDelegate* delegate = - new TestTabModalConfirmDialogDelegate(contents); - TabModalConfirmDialog::Create(delegate, contents); + auto delegate = std::make_unique<TestTabModalConfirmDialogDelegate>(contents); + TabModalConfirmDialog::Create(std::move(delegate), contents); // The tab modal dialog should be in the accessibility tree; everything else // should be hidden. So we expect an "OK" button and no reload button.
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc index 6081e7c6..724a180 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
@@ -615,13 +615,6 @@ }; TEST_P(OmniboxViewViewsClipboardTest, ClipboardCopyOrCutURL) { - // TODO(crbug.com/396477) Make this an interactive ui test so there isn't - // contention for the system clipboard. - // Force use of the system clipboard because this test checks for URL format - // on Linux, which is not supported by test clipboard. - ui::Clipboard::DestroyClipboardForCurrentThread(); - ui::Clipboard::GetForCurrentThread(); - omnibox_view()->SelectAll(false); ASSERT_TRUE(omnibox_view()->IsSelectAll());
diff --git a/chrome/browser/ui/views/page_action/pwa_install_view.cc b/chrome/browser/ui/views/page_action/pwa_install_view.cc index 1aae1525..bdaeae717 100644 --- a/chrome/browser/ui/views/page_action/pwa_install_view.cc +++ b/chrome/browser/ui/views/page_action/pwa_install_view.cc
@@ -35,12 +35,12 @@ if (!manager) return false; - bool is_probably_installable = manager->IsProbablyInstallableWebApp(); + bool is_probably_promotable = manager->IsProbablyPromotableWebApp(); auto* tab_helper = web_app::WebAppTabHelperBase::FromWebContents(web_contents); bool is_installed = tab_helper && tab_helper->HasAssociatedApp(); - bool show_install_button = is_probably_installable && !is_installed; + bool show_install_button = is_probably_promotable && !is_installed; if (show_install_button && manager->MaybeConsumeInstallAnimation()) AnimateIn(base::nullopt);
diff --git a/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc b/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc index d7c881d..4a3779b2 100644 --- a/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc +++ b/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc
@@ -326,3 +326,20 @@ IN_PROC_BROWSER_TEST_F(PwaInstallViewBrowserTest, BouncedInstallIgnored) { TestInstallBounce(base::TimeDelta::FromMinutes(70), 0); } + +// Omnibox install button shouldn't show for a PWA that prefers a related app +// over the web app. +IN_PROC_BROWSER_TEST_F(PwaInstallViewBrowserTest, + SuppressForPreferredRelatedApp) { + NavigateToURL( + https_server_.GetURL("/banners/manifest_test_page.html?manifest=" + "manifest_prefer_related_apps_empty.json")); + ASSERT_TRUE(app_banner_manager_->WaitForInstallableCheck()); + EXPECT_FALSE(pwa_install_view_->GetVisible()); + + // Site should still be considered installable even if it's not promoted in + // the omnibox. + EXPECT_TRUE(base::EqualsASCII( + banners::AppBannerManager::GetInstallableWebAppName(web_contents_), + "Manifest prefer related apps empty")); +}
diff --git a/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.cc b/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.cc new file mode 100644 index 0000000..673aa9b --- /dev/null +++ b/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.cc
@@ -0,0 +1,24 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/status_icons/status_icon_linux_dbus.h" + +#include "base/logging.h" + +StatusIconLinuxDbus::StatusIconLinuxDbus(const gfx::ImageSkia& image, + const base::string16& tool_tip) {} + +StatusIconLinuxDbus::~StatusIconLinuxDbus() = default; + +void StatusIconLinuxDbus::SetImage(const gfx::ImageSkia& image) { + NOTIMPLEMENTED(); +} + +void StatusIconLinuxDbus::SetToolTip(const base::string16& tool_tip) { + NOTIMPLEMENTED(); +} + +void StatusIconLinuxDbus::UpdatePlatformContextMenu(ui::MenuModel* model) { + NOTIMPLEMENTED(); +}
diff --git a/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.h b/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.h new file mode 100644 index 0000000..ea18ea9 --- /dev/null +++ b/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.h
@@ -0,0 +1,28 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_ICON_LINUX_DBUS_H_ +#define CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_ICON_LINUX_DBUS_H_ + +#include "base/macros.h" +#include "ui/views/linux_ui/status_icon_linux.h" + +// A status icon following the StatusNotifierItem specification. +// https://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/StatusNotifierItem/ +class StatusIconLinuxDbus : public views::StatusIconLinux { + public: + StatusIconLinuxDbus(const gfx::ImageSkia& image, + const base::string16& tool_tip); + ~StatusIconLinuxDbus() override; + + // StatusIcon: + void SetImage(const gfx::ImageSkia& image) override; + void SetToolTip(const base::string16& tool_tip) override; + void UpdatePlatformContextMenu(ui::MenuModel* model) override; + + private: + DISALLOW_COPY_AND_ASSIGN(StatusIconLinuxDbus); +}; + +#endif // CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_ICON_LINUX_DBUS_H_
diff --git a/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.cc b/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.cc index 4694a9a..b81d764 100644 --- a/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.cc +++ b/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.cc
@@ -4,12 +4,24 @@ #include "chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.h" +#include "base/feature_list.h" #include "base/memory/ptr_util.h" #include "ui/message_center/public/cpp/notifier_id.h" #include "ui/views/linux_ui/linux_ui.h" +#if defined(USE_DBUS) +#include "chrome/browser/ui/views/status_icons/status_icon_linux_dbus.h" +#endif + +#if defined(USE_X11) +#include "chrome/browser/ui/views/status_icons/status_icon_linux_x11.h" +#endif + namespace { +constexpr base::Feature kEnableDbusAndX11StatusIcons{ + "EnableDbusAndX11StatusIcons", base::FEATURE_DISABLED_BY_DEFAULT}; + // Prefix for app indicator ids const char kAppIndicatorIdPrefix[] = "chrome_app_indicator_"; @@ -58,6 +70,15 @@ StatusIconLinuxWrapper::CreateWrappedStatusIcon( const gfx::ImageSkia& image, const base::string16& tool_tip) { + if (base::FeatureList::IsEnabled(kEnableDbusAndX11StatusIcons)) { +#if defined(USE_DBUS) + return base::WrapUnique(new StatusIconLinuxWrapper( + std::make_unique<StatusIconLinuxDbus>(image, tool_tip))); +#endif + // TODO(thomasanderson): Set up a mechanism for replacing |status_icon_| + // with a StatusIconLinuxX11 in case the system doesn't support DBus status + // icons, which we can only discover asynchronously. + } const views::LinuxUI* linux_ui = views::LinuxUI::instance(); if (linux_ui) { auto status_icon = @@ -72,7 +93,7 @@ void StatusIconLinuxWrapper::UpdatePlatformContextMenu( StatusIconMenuModel* model) { - // If a menu already exists, remove ourself from its oberver list. + // If a menu already exists, remove ourself from its observer list. if (menu_model_) menu_model_->RemoveObserver(this);
diff --git a/chrome/browser/ui/views/status_icons/status_icon_linux_x11.cc b/chrome/browser/ui/views/status_icons/status_icon_linux_x11.cc new file mode 100644 index 0000000..2256e37 --- /dev/null +++ b/chrome/browser/ui/views/status_icons/status_icon_linux_x11.cc
@@ -0,0 +1,24 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/status_icons/status_icon_linux_x11.h" + +#include "base/logging.h" + +StatusIconLinuxX11::StatusIconLinuxX11(const gfx::ImageSkia& image, + const base::string16& tool_tip) {} + +StatusIconLinuxX11::~StatusIconLinuxX11() = default; + +void StatusIconLinuxX11::SetImage(const gfx::ImageSkia& image) { + NOTIMPLEMENTED(); +} + +void StatusIconLinuxX11::SetToolTip(const base::string16& tool_tip) { + NOTIMPLEMENTED(); +} + +void StatusIconLinuxX11::UpdatePlatformContextMenu(ui::MenuModel* model) { + NOTIMPLEMENTED(); +}
diff --git a/chrome/browser/ui/views/status_icons/status_icon_linux_x11.h b/chrome/browser/ui/views/status_icons/status_icon_linux_x11.h new file mode 100644 index 0000000..bab7293f --- /dev/null +++ b/chrome/browser/ui/views/status_icons/status_icon_linux_x11.h
@@ -0,0 +1,28 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_ICON_LINUX_X11_H_ +#define CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_ICON_LINUX_X11_H_ + +#include "base/macros.h" +#include "ui/views/linux_ui/status_icon_linux.h" + +// A status icon that uses the XEmbed protocol. +// https://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html +class StatusIconLinuxX11 : public views::StatusIconLinux { + public: + StatusIconLinuxX11(const gfx::ImageSkia& image, + const base::string16& tool_tip); + ~StatusIconLinuxX11() override; + + // StatusIcon: + void SetImage(const gfx::ImageSkia& image) override; + void SetToolTip(const base::string16& tool_tip) override; + void UpdatePlatformContextMenu(ui::MenuModel* model) override; + + private: + DISALLOW_COPY_AND_ASSIGN(StatusIconLinuxX11); +}; + +#endif // CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_ICON_LINUX_X11_H_
diff --git a/chrome/browser/ui/views/tab_modal_confirm_dialog_views.cc b/chrome/browser/ui/views/tab_modal_confirm_dialog_views.cc index fc16b97c..19470a2 100644 --- a/chrome/browser/ui/views/tab_modal_confirm_dialog_views.cc +++ b/chrome/browser/ui/views/tab_modal_confirm_dialog_views.cc
@@ -4,6 +4,9 @@ #include "chrome/browser/ui/views/tab_modal_confirm_dialog_views.h" +#include <memory> +#include <utility> + #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "chrome/browser/ui/browser_dialogs.h" @@ -21,25 +24,25 @@ // static TabModalConfirmDialog* TabModalConfirmDialog::Create( - TabModalConfirmDialogDelegate* delegate, + std::unique_ptr<TabModalConfirmDialogDelegate> delegate, content::WebContents* web_contents) { - return new TabModalConfirmDialogViews(delegate, web_contents); + return new TabModalConfirmDialogViews(std::move(delegate), web_contents); } ////////////////////////////////////////////////////////////////////////////// // TabModalConfirmDialogViews, constructor & destructor: TabModalConfirmDialogViews::TabModalConfirmDialogViews( - TabModalConfirmDialogDelegate* delegate, + std::unique_ptr<TabModalConfirmDialogDelegate> delegate, content::WebContents* web_contents) - : delegate_(delegate) { - views::MessageBoxView::InitParams init_params(delegate->GetDialogMessage()); + : delegate_(std::move(delegate)) { + views::MessageBoxView::InitParams init_params(delegate_->GetDialogMessage()); init_params.inter_row_vertical_spacing = ChromeLayoutProvider::Get()->GetDistanceMetric( views::DISTANCE_UNRELATED_CONTROL_VERTICAL); message_box_view_ = new views::MessageBoxView(init_params); - base::string16 link_text(delegate->GetLinkText()); + base::string16 link_text(delegate_->GetLinkText()); if (!link_text.empty()) message_box_view_->SetLink(link_text, this);
diff --git a/chrome/browser/ui/views/tab_modal_confirm_dialog_views.h b/chrome/browser/ui/views/tab_modal_confirm_dialog_views.h index e664758..5b6e510 100644 --- a/chrome/browser/ui/views/tab_modal_confirm_dialog_views.h +++ b/chrome/browser/ui/views/tab_modal_confirm_dialog_views.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_UI_VIEWS_TAB_MODAL_CONFIRM_DIALOG_VIEWS_H_ #define CHROME_BROWSER_UI_VIEWS_TAB_MODAL_CONFIRM_DIALOG_VIEWS_H_ +#include <memory> + #include "base/compiler_specific.h" #include "base/macros.h" #include "chrome/browser/ui/tab_modal_confirm_dialog.h" @@ -30,8 +32,9 @@ public views::DialogDelegate, public views::LinkListener { public: - TabModalConfirmDialogViews(TabModalConfirmDialogDelegate* delegate, - content::WebContents* web_contents); + TabModalConfirmDialogViews( + std::unique_ptr<TabModalConfirmDialogDelegate> delegate, + content::WebContents* web_contents); // views::DialogDelegate: base::string16 GetWindowTitle() const override;
diff --git a/chrome/browser/ui/views/tabs/tab_animation.cc b/chrome/browser/ui/views/tabs/tab_animation.cc index c80718c..d4e4e00 100644 --- a/chrome/browser/ui/views/tabs/tab_animation.cc +++ b/chrome/browser/ui/views/tabs/tab_animation.cc
@@ -62,14 +62,6 @@ duration_ = kZeroDuration; } -void TabAnimation::CancelAnimation() { - TabAnimationState current_state = GetCurrentState(); - initial_state_ = current_state; - target_state_ = current_state; - start_time_ = base::TimeTicks::Now(); - duration_ = kZeroDuration; -} - void TabAnimation::NotifyCloseCompleted() { std::move(tab_removed_callback_).Run(); }
diff --git a/chrome/browser/ui/views/tabs/tab_animation.h b/chrome/browser/ui/views/tabs/tab_animation.h index 2f006af..6133e53 100644 --- a/chrome/browser/ui/views/tabs/tab_animation.h +++ b/chrome/browser/ui/views/tabs/tab_animation.h
@@ -34,7 +34,6 @@ void RetargetTo(TabAnimationState target_state); void CompleteAnimation(); - void CancelAnimation(); // Notifies the owner of the animated tab that the close animation // has completed and the tab can be cleaned up.
diff --git a/chrome/browser/ui/views/tabs/tab_animation_unittest.cc b/chrome/browser/ui/views/tabs/tab_animation_unittest.cc index 85c4c8a..ce70460 100644 --- a/chrome/browser/ui/views/tabs/tab_animation_unittest.cc +++ b/chrome/browser/ui/views/tabs/tab_animation_unittest.cc
@@ -95,48 +95,6 @@ PinnednessOf(animation.GetCurrentState())); } -TEST_F(TabAnimationTest, CanceledAnimationStaysAtInitial) { - TabAnimationState initial_state = TabAnimationState::ForIdealTabState( - TabAnimationState::TabOpenness::kOpen, - TabAnimationState::TabPinnedness::kUnpinned, - TabAnimationState::TabActiveness::kInactive, 0); - TabAnimationState target_state = - initial_state.WithPinnedness(TabAnimationState::TabPinnedness::kPinned); - TabAnimation animation = - TabAnimation::ForStaticState(initial_state, base::BindOnce([]() {})); - animation.AnimateTo(target_state); - - animation.CancelAnimation(); - - EXPECT_EQ(kZeroDuration, animation.GetTimeRemaining()); - EXPECT_EQ(base::TimeDelta::FromMilliseconds(0), animation.GetTimeRemaining()); - EXPECT_EQ(PinnednessOf(initial_state), - PinnednessOf(animation.GetCurrentState())); -} - -TEST_F(TabAnimationTest, PartwayFinishedCanceledAnimationStaysPartwayFinished) { - TabAnimationState initial_state = TabAnimationState::ForIdealTabState( - TabAnimationState::TabOpenness::kOpen, - TabAnimationState::TabPinnedness::kUnpinned, - TabAnimationState::TabActiveness::kInactive, 0); - TabAnimationState target_state = - initial_state.WithPinnedness(TabAnimationState::TabPinnedness::kPinned); - TabAnimation animation = - TabAnimation::ForStaticState(initial_state, base::BindOnce([]() {})); - animation.AnimateTo(target_state); - - env_.FastForwardBy(TabAnimation::kAnimationDuration / 2.0); - - animation.CancelAnimation(); - - EXPECT_EQ(kZeroDuration, animation.GetTimeRemaining()); - EXPECT_EQ(base::TimeDelta::FromMilliseconds(0), animation.GetTimeRemaining()); - EXPECT_LT(PinnednessOf(initial_state), - PinnednessOf(animation.GetCurrentState())); - EXPECT_LT(PinnednessOf(animation.GetCurrentState()), - PinnednessOf(target_state)); -} - TEST_F(TabAnimationTest, ReplacedAnimationRestartsDuration) { TabAnimationState initial_state = TabAnimationState::ForIdealTabState( TabAnimationState::TabOpenness::kOpen,
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 5f1a991..8b6453ec 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -2105,6 +2105,10 @@ } void TabStrip::AnimateToIdealBounds() { + // bounds_animator_ and animator_ should not run concurrently. + // bounds_animator_ takes precedence, and can finish what animator_ started. + animator_->CompleteAnimationsWithoutDestroyingTabs(); + for (int i = 0; i < tab_count(); ++i) { // If the tab is being dragged manually, skip it. Tab* tab = tab_at(i);
diff --git a/chrome/browser/ui/views/tabs/tab_strip_animator.cc b/chrome/browser/ui/views/tabs/tab_strip_animator.cc index 9f9f6c4f..39173902 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_animator.cc +++ b/chrome/browser/ui/views/tabs/tab_strip_animator.cc
@@ -97,16 +97,13 @@ } void TabStripAnimator::CompleteAnimations() { - for (size_t i = 0; i < animations_.size(); i++) { - animations_[i].CompleteAnimation(); - } + CompleteAnimationsWithoutDestroyingTabs(); RemoveClosedTabs(); - timer_.Stop(); } -void TabStripAnimator::CancelAnimations() { +void TabStripAnimator::CompleteAnimationsWithoutDestroyingTabs() { for (TabAnimation& animation : animations_) { - animation.CancelAnimation(); + animation.CompleteAnimation(); } timer_.Stop(); }
diff --git a/chrome/browser/ui/views/tabs/tab_strip_animator.h b/chrome/browser/ui/views/tabs/tab_strip_animator.h index 33b9907..ff065f4 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_animator.h +++ b/chrome/browser/ui/views/tabs/tab_strip_animator.h
@@ -58,10 +58,12 @@ void CompleteAnimations(); - // TODO(958173): Temporary method that aborts current animations, leaving - // tabs where they are. Use to hand off animation responsibilities from - // this animator to elsewhere without teleporting tabs. - void CancelAnimations(); + // TODO(958173): Temporary method that completes running animations, + // without invoking the callback to destroy removed tabs. Use to hand + // off animation (and removed tab destruction) responsibilities from + // this animator to elsewhere without teleporting tabs or destroying + // the same tab more than once. + void CompleteAnimationsWithoutDestroyingTabs(); private: void AnimateTabTo(int index, TabAnimationState target_state);
diff --git a/chrome/browser/ui/views/tabs/tab_strip_animator_unittest.cc b/chrome/browser/ui/views/tabs/tab_strip_animator_unittest.cc index cd87784..d158fd5 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_animator_unittest.cc +++ b/chrome/browser/ui/views/tabs/tab_strip_animator_unittest.cc
@@ -160,20 +160,6 @@ EXPECT_EQ(1.0f, OpennessOf(animator_.GetCurrentTabStates()[0])); } -TEST_F(TabStripAnimatorTest, CancelAnimations) { - animator_.InsertTabAt(0, base::BindOnce([]() {}), - TabAnimationState::TabActiveness::kActive, - TabAnimationState::TabPinnedness::kUnpinned); - EXPECT_TRUE(animator_.IsAnimating()); - EXPECT_EQ(1u, animator_.GetCurrentTabStates().size()); - EXPECT_EQ(0.0f, OpennessOf(animator_.GetCurrentTabStates()[0])); - - animator_.CancelAnimations(); - - EXPECT_FALSE(animator_.IsAnimating()); - EXPECT_EQ(0.0f, OpennessOf(animator_.GetCurrentTabStates()[0])); -} - TEST_F(TabStripAnimatorTest, CompleteAnimationsRemovesClosedTabs) { TabClosedDetector second_tab; animator_.InsertTabAtNoAnimation(0, base::BindOnce([]() {}), @@ -200,7 +186,8 @@ EXPECT_TRUE(second_tab.was_closed_); } -TEST_F(TabStripAnimatorTest, CancelAnimationsDoesNotRemoveClosedTabs) { +TEST_F(TabStripAnimatorTest, + CompleteAnimationsWithoutDestroyingTabsDoesNotRemoveClosedTabs) { TabClosedDetector second_tab; animator_.InsertTabAtNoAnimation(0, base::BindOnce([]() {}), TabAnimationState::TabActiveness::kActive, @@ -219,7 +206,7 @@ EXPECT_EQ(1.0f, OpennessOf(animator_.GetCurrentTabStates()[1])); EXPECT_FALSE(second_tab.was_closed_); - animator_.CancelAnimations(); + animator_.CompleteAnimationsWithoutDestroyingTabs(); EXPECT_FALSE(animator_.IsAnimating()); EXPECT_EQ(2u, animator_.GetCurrentTabStates().size());
diff --git a/chrome/browser/ui/web_applications/web_app_ui_delegate_impl_factory.cc b/chrome/browser/ui/web_applications/web_app_ui_delegate_impl_factory.cc deleted file mode 100644 index 61ac027..0000000 --- a/chrome/browser/ui/web_applications/web_app_ui_delegate_impl_factory.cc +++ /dev/null
@@ -1,51 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/web_applications/web_app_ui_delegate_impl_factory.h" - -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/web_applications/web_app_ui_delegate_impl.h" -#include "chrome/browser/web_applications/components/web_app_utils.h" -#include "chrome/browser/web_applications/web_app_provider_factory.h" -#include "components/keyed_service/content/browser_context_dependency_manager.h" - -namespace web_app { - -// static -WebAppUiDelegateImpl* WebAppUiDelegateImplFactory::GetForProfile( - Profile* profile) { - return static_cast<WebAppUiDelegateImpl*>( - WebAppUiDelegateImplFactory::GetInstance()->GetServiceForBrowserContext( - profile, true /* create */)); -} - -// static -WebAppUiDelegateImplFactory* WebAppUiDelegateImplFactory::GetInstance() { - return base::Singleton<WebAppUiDelegateImplFactory>::get(); -} - -WebAppUiDelegateImplFactory::WebAppUiDelegateImplFactory() - : BrowserContextKeyedServiceFactory( - "WebAppUiDelegate", - BrowserContextDependencyManager::GetInstance()) { - DependsOn(WebAppProviderFactory::GetInstance()); -} - -WebAppUiDelegateImplFactory::~WebAppUiDelegateImplFactory() = default; - -KeyedService* WebAppUiDelegateImplFactory::BuildServiceInstanceFor( - content::BrowserContext* context) const { - return new WebAppUiDelegateImpl(Profile::FromBrowserContext(context)); -} - -bool WebAppUiDelegateImplFactory::ServiceIsCreatedWithBrowserContext() const { - return true; -} - -content::BrowserContext* WebAppUiDelegateImplFactory::GetBrowserContextToUse( - content::BrowserContext* context) const { - return GetBrowserContextForWebApps(context); -} - -} // namespace web_app
diff --git a/chrome/browser/ui/web_applications/web_app_ui_delegate_impl_factory.h b/chrome/browser/ui/web_applications/web_app_ui_delegate_impl_factory.h deleted file mode 100644 index 100b4c40..0000000 --- a/chrome/browser/ui/web_applications/web_app_ui_delegate_impl_factory.h +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_WEB_APPLICATIONS_WEB_APP_UI_DELEGATE_IMPL_FACTORY_H_ -#define CHROME_BROWSER_UI_WEB_APPLICATIONS_WEB_APP_UI_DELEGATE_IMPL_FACTORY_H_ - -#include "base/macros.h" -#include "base/memory/singleton.h" -#include "components/keyed_service/content/browser_context_keyed_service_factory.h" - -namespace content { -class BrowserContext; -} - -class Profile; - -namespace web_app { - -class WebAppUiDelegateImpl; - -// Singleton that owns all WebAppUiDelegateImplFactories and associated them -// with Profile. -class WebAppUiDelegateImplFactory : public BrowserContextKeyedServiceFactory { - public: - static WebAppUiDelegateImpl* GetForProfile(Profile* profile); - - static WebAppUiDelegateImplFactory* GetInstance(); - - private: - friend struct base::DefaultSingletonTraits<WebAppUiDelegateImplFactory>; - - WebAppUiDelegateImplFactory(); - ~WebAppUiDelegateImplFactory() override; - - // BrowserContextKeyedServiceFactory - KeyedService* BuildServiceInstanceFor( - content::BrowserContext* context) const override; - bool ServiceIsCreatedWithBrowserContext() const override; - content::BrowserContext* GetBrowserContextToUse( - content::BrowserContext* context) const override; - - DISALLOW_COPY_AND_ASSIGN(WebAppUiDelegateImplFactory); -}; - -} // namespace web_app - -#endif // CHROME_BROWSER_UI_WEB_APPLICATIONS_WEB_APP_UI_DELEGATE_IMPL_FACTORY_H_
diff --git a/chrome/browser/ui/web_applications/web_app_ui_delegate_impl.cc b/chrome/browser/ui/web_applications/web_app_ui_service.cc similarity index 71% rename from chrome/browser/ui/web_applications/web_app_ui_delegate_impl.cc rename to chrome/browser/ui/web_applications/web_app_ui_service.cc index 5ef0980..256a7963 100644 --- a/chrome/browser/ui/web_applications/web_app_ui_delegate_impl.cc +++ b/chrome/browser/ui/web_applications/web_app_ui_service.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/web_applications/web_app_ui_delegate_impl.h" +#include "chrome/browser/ui/web_applications/web_app_ui_service.h" #include <utility> @@ -10,18 +10,17 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/web_applications/app_browser_controller.h" -#include "chrome/browser/ui/web_applications/web_app_ui_delegate_impl_factory.h" +#include "chrome/browser/ui/web_applications/web_app_ui_service_factory.h" #include "chrome/browser/web_applications/web_app_provider.h" namespace web_app { // static -WebAppUiDelegateImpl* WebAppUiDelegateImpl::Get(Profile* profile) { - return WebAppUiDelegateImplFactory::GetForProfile(profile); +WebAppUiService* WebAppUiService::Get(Profile* profile) { + return WebAppUiServiceFactory::GetForProfile(profile); } -WebAppUiDelegateImpl::WebAppUiDelegateImpl(Profile* profile) - : profile_(profile) { +WebAppUiService::WebAppUiService(Profile* profile) : profile_(profile) { for (Browser* browser : *BrowserList::GetInstance()) { base::Optional<AppId> app_id = GetAppIdForBrowser(browser); if (!app_id.has_value()) @@ -34,14 +33,14 @@ WebAppProvider::Get(profile_)->set_ui_delegate(this); } -WebAppUiDelegateImpl::~WebAppUiDelegateImpl() = default; +WebAppUiService::~WebAppUiService() = default; -void WebAppUiDelegateImpl::Shutdown() { +void WebAppUiService::Shutdown() { WebAppProvider::Get(profile_)->set_ui_delegate(nullptr); BrowserList::RemoveObserver(this); } -size_t WebAppUiDelegateImpl::GetNumWindowsForApp(const AppId& app_id) { +size_t WebAppUiService::GetNumWindowsForApp(const AppId& app_id) { auto it = num_windows_for_apps_map_.find(app_id); if (it == num_windows_for_apps_map_.end()) return 0; @@ -49,9 +48,8 @@ return it->second; } -void WebAppUiDelegateImpl::NotifyOnAllAppWindowsClosed( - const AppId& app_id, - base::OnceClosure callback) { +void WebAppUiService::NotifyOnAllAppWindowsClosed(const AppId& app_id, + base::OnceClosure callback) { const size_t num_windows_for_app = GetNumWindowsForApp(app_id); if (num_windows_for_app == 0) { base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, @@ -62,7 +60,7 @@ windows_closed_requests_map_[app_id].push_back(std::move(callback)); } -void WebAppUiDelegateImpl::OnBrowserAdded(Browser* browser) { +void WebAppUiService::OnBrowserAdded(Browser* browser) { base::Optional<AppId> app_id = GetAppIdForBrowser(browser); if (!app_id.has_value()) return; @@ -70,7 +68,7 @@ ++num_windows_for_apps_map_[app_id.value()]; } -void WebAppUiDelegateImpl::OnBrowserRemoved(Browser* browser) { +void WebAppUiService::OnBrowserRemoved(Browser* browser) { base::Optional<AppId> app_id_opt = GetAppIdForBrowser(browser); if (!app_id_opt.has_value()) return; @@ -94,8 +92,7 @@ windows_closed_requests_map_.erase(app_id); } -base::Optional<AppId> WebAppUiDelegateImpl::GetAppIdForBrowser( - Browser* browser) { +base::Optional<AppId> WebAppUiService::GetAppIdForBrowser(Browser* browser) { if (browser->profile() != profile_) return base::nullopt;
diff --git a/chrome/browser/ui/web_applications/web_app_ui_delegate_impl.h b/chrome/browser/ui/web_applications/web_app_ui_service.h similarity index 65% rename from chrome/browser/ui/web_applications/web_app_ui_delegate_impl.h rename to chrome/browser/ui/web_applications/web_app_ui_service.h index 7987502..e175429 100644 --- a/chrome/browser/ui/web_applications/web_app_ui_delegate_impl.h +++ b/chrome/browser/ui/web_applications/web_app_ui_service.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_WEB_APPLICATIONS_WEB_APP_UI_DELEGATE_IMPL_H_ -#define CHROME_BROWSER_UI_WEB_APPLICATIONS_WEB_APP_UI_DELEGATE_IMPL_H_ +#ifndef CHROME_BROWSER_UI_WEB_APPLICATIONS_WEB_APP_UI_SERVICE_H_ +#define CHROME_BROWSER_UI_WEB_APPLICATIONS_WEB_APP_UI_SERVICE_H_ #include <map> #include <vector> @@ -20,14 +20,16 @@ namespace web_app { -class WebAppUiDelegateImpl : public KeyedService, - public BrowserListObserver, - public WebAppUiDelegate { +// This KeyedService is a UI counterpart for WebAppProvider. +// It tracks the open windows for each web app. +class WebAppUiService : public KeyedService, + public BrowserListObserver, + public WebAppUiDelegate { public: - static WebAppUiDelegateImpl* Get(Profile* profile); + static WebAppUiService* Get(Profile* profile); - explicit WebAppUiDelegateImpl(Profile* profile); - ~WebAppUiDelegateImpl() override; + explicit WebAppUiService(Profile* profile); + ~WebAppUiService() override; // KeyedService void Shutdown() override; @@ -49,9 +51,9 @@ std::map<AppId, std::vector<base::OnceClosure>> windows_closed_requests_map_; std::map<AppId, size_t> num_windows_for_apps_map_; - DISALLOW_COPY_AND_ASSIGN(WebAppUiDelegateImpl); + DISALLOW_COPY_AND_ASSIGN(WebAppUiService); }; } // namespace web_app -#endif // CHROME_BROWSER_UI_WEB_APPLICATIONS_WEB_APP_UI_DELEGATE_IMPL_H_ +#endif // CHROME_BROWSER_UI_WEB_APPLICATIONS_WEB_APP_UI_SERVICE_H_
diff --git a/chrome/browser/ui/web_applications/web_app_ui_delegate_impl_browsertest.cc b/chrome/browser/ui/web_applications/web_app_ui_service_browsertest.cc similarity index 68% rename from chrome/browser/ui/web_applications/web_app_ui_delegate_impl_browsertest.cc rename to chrome/browser/ui/web_applications/web_app_ui_service_browsertest.cc index ae7f3df7..f5974b33 100644 --- a/chrome/browser/ui/web_applications/web_app_ui_delegate_impl_browsertest.cc +++ b/chrome/browser/ui/web_applications/web_app_ui_service_browsertest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/web_applications/web_app_ui_delegate_impl.h" +#include "chrome/browser/ui/web_applications/web_app_ui_service.h" #include "base/barrier_closure.h" #include "base/test/bind_test_util.h" @@ -62,7 +62,7 @@ const GURL kFooUrl = GURL("https://foo.example"); const GURL kBarUrl = GURL("https://bar.example"); -class WebAppUiDelegateImplBrowserTest : public InProcessBrowserTest { +class WebAppUiServiceBrowserTest : public InProcessBrowserTest { protected: Profile* profile() { return browser()->profile(); } @@ -78,28 +78,28 @@ return extensions::browsertest_util::LaunchAppBrowser(profile(), app); } - WebAppUiDelegateImpl* ui_delegate() { - return WebAppUiDelegateImpl::Get(profile()); - } + WebAppUiService* ui_service() { return WebAppUiService::Get(profile()); } }; -IN_PROC_BROWSER_TEST_F(WebAppUiDelegateImplBrowserTest, +IN_PROC_BROWSER_TEST_F(WebAppUiServiceBrowserTest, GetNumWindowsForApp_AppWindowsAdded) { // Should not crash. - auto& delegate = WebAppProvider::Get(browser()->profile())->ui_delegate(); - auto* delegate_impl = WebAppUiDelegateImpl::Get(browser()->profile()); - EXPECT_EQ(&delegate, delegate_impl); + auto& ui_delegate = WebAppProvider::Get(browser()->profile())->ui_delegate(); + auto* ui_service = WebAppUiService::Get(browser()->profile()); + EXPECT_EQ(&ui_delegate, ui_service); // Zero apps on start: - EXPECT_EQ(0u, delegate.GetNumWindowsForApp(AppId())); + EXPECT_EQ(0u, ui_service->GetNumWindowsForApp(AppId())); const auto* foo_app = InstallWebApp(kFooUrl); LaunchApp(foo_app); + EXPECT_EQ(1u, ui_service->GetNumWindowsForApp(foo_app->id())); - EXPECT_EQ(1u, delegate.GetNumWindowsForApp(foo_app->id())); + LaunchApp(foo_app); + EXPECT_EQ(2u, ui_service->GetNumWindowsForApp(foo_app->id())); } -IN_PROC_BROWSER_TEST_F(WebAppUiDelegateImplBrowserTest, +IN_PROC_BROWSER_TEST_F(WebAppUiServiceBrowserTest, GetNumWindowsForApp_AppWindowsRemoved) { const auto* foo_app = InstallWebApp(kFooUrl); auto* foo_window1 = LaunchApp(foo_app); @@ -108,21 +108,21 @@ const auto* bar_app = InstallWebApp(kBarUrl); LaunchApp(bar_app); - EXPECT_EQ(2u, ui_delegate()->GetNumWindowsForApp(foo_app->id())); - EXPECT_EQ(1u, ui_delegate()->GetNumWindowsForApp(bar_app->id())); + EXPECT_EQ(2u, ui_service()->GetNumWindowsForApp(foo_app->id())); + EXPECT_EQ(1u, ui_service()->GetNumWindowsForApp(bar_app->id())); CloseAndWait(foo_window1); - EXPECT_EQ(1u, ui_delegate()->GetNumWindowsForApp(foo_app->id())); - EXPECT_EQ(1u, ui_delegate()->GetNumWindowsForApp(bar_app->id())); + EXPECT_EQ(1u, ui_service()->GetNumWindowsForApp(foo_app->id())); + EXPECT_EQ(1u, ui_service()->GetNumWindowsForApp(bar_app->id())); CloseAndWait(foo_window2); - EXPECT_EQ(0u, ui_delegate()->GetNumWindowsForApp(foo_app->id())); - EXPECT_EQ(1u, ui_delegate()->GetNumWindowsForApp(bar_app->id())); + EXPECT_EQ(0u, ui_service()->GetNumWindowsForApp(foo_app->id())); + EXPECT_EQ(1u, ui_service()->GetNumWindowsForApp(bar_app->id())); } -IN_PROC_BROWSER_TEST_F(WebAppUiDelegateImplBrowserTest, +IN_PROC_BROWSER_TEST_F(WebAppUiServiceBrowserTest, NotifyOnAllAppWindowsClosed_NoOpenedWindows) { const auto* foo_app = InstallWebApp(kFooUrl); const auto* bar_app = InstallWebApp(kBarUrl); @@ -130,14 +130,14 @@ base::RunLoop run_loop; // Should return early; no windows for |foo_app|. - ui_delegate()->NotifyOnAllAppWindowsClosed(foo_app->id(), - run_loop.QuitClosure()); + ui_service()->NotifyOnAllAppWindowsClosed(foo_app->id(), + run_loop.QuitClosure()); run_loop.Run(); } // Tests that the callback is correctly called when there is more than one // app window. -IN_PROC_BROWSER_TEST_F(WebAppUiDelegateImplBrowserTest, +IN_PROC_BROWSER_TEST_F(WebAppUiServiceBrowserTest, NotifyOnAllAppWindowsClosed_MultipleOpenedWindows) { const auto* foo_app = InstallWebApp(kFooUrl); const auto* bar_app = InstallWebApp(kBarUrl); @@ -151,11 +151,11 @@ bool callback_ran = false; base::RunLoop run_loop; - ui_delegate()->NotifyOnAllAppWindowsClosed( - foo_app->id(), base::BindLambdaForTesting([&]() { - callback_ran = true; - run_loop.Quit(); - })); + ui_service()->NotifyOnAllAppWindowsClosed(foo_app->id(), + base::BindLambdaForTesting([&]() { + callback_ran = true; + run_loop.Quit(); + })); CloseAndWait(foo_window1); // The callback shouldn't have run yet because there is still one window @@ -173,7 +173,7 @@ // Tests that callbacks are correctly called when there is more than one // request. -IN_PROC_BROWSER_TEST_F(WebAppUiDelegateImplBrowserTest, +IN_PROC_BROWSER_TEST_F(WebAppUiServiceBrowserTest, NotifyOnAllAppWindowsClosed_MultipleRequests) { const auto* foo_app = InstallWebApp(kFooUrl); const auto* bar_app = InstallWebApp(kBarUrl); @@ -187,16 +187,16 @@ base::RunLoop run_loop; auto barrier_closure = base::BarrierClosure(2, run_loop.QuitClosure()); - ui_delegate()->NotifyOnAllAppWindowsClosed(foo_app->id(), - base::BindLambdaForTesting([&]() { - callback_ran1 = true; - barrier_closure.Run(); - })); - ui_delegate()->NotifyOnAllAppWindowsClosed(foo_app->id(), - base::BindLambdaForTesting([&]() { - callback_ran2 = true; - barrier_closure.Run(); - })); + ui_service()->NotifyOnAllAppWindowsClosed(foo_app->id(), + base::BindLambdaForTesting([&]() { + callback_ran1 = true; + barrier_closure.Run(); + })); + ui_service()->NotifyOnAllAppWindowsClosed(foo_app->id(), + base::BindLambdaForTesting([&]() { + callback_ran2 = true; + barrier_closure.Run(); + })); CloseAndWait(foo_window1); // The callback shouldn't have run yet because there is still one window
diff --git a/chrome/browser/ui/web_applications/web_app_ui_service_factory.cc b/chrome/browser/ui/web_applications/web_app_ui_service_factory.cc new file mode 100644 index 0000000..1ef4395 --- /dev/null +++ b/chrome/browser/ui/web_applications/web_app_ui_service_factory.cc
@@ -0,0 +1,50 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/web_applications/web_app_ui_service_factory.h" + +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/web_applications/web_app_ui_service.h" +#include "chrome/browser/web_applications/components/web_app_utils.h" +#include "chrome/browser/web_applications/web_app_provider_factory.h" +#include "components/keyed_service/content/browser_context_dependency_manager.h" + +namespace web_app { + +// static +WebAppUiService* WebAppUiServiceFactory::GetForProfile(Profile* profile) { + return static_cast<WebAppUiService*>( + WebAppUiServiceFactory::GetInstance()->GetServiceForBrowserContext( + profile, true /* create */)); +} + +// static +WebAppUiServiceFactory* WebAppUiServiceFactory::GetInstance() { + return base::Singleton<WebAppUiServiceFactory>::get(); +} + +WebAppUiServiceFactory::WebAppUiServiceFactory() + : BrowserContextKeyedServiceFactory( + "WebAppUiDelegate", + BrowserContextDependencyManager::GetInstance()) { + DependsOn(WebAppProviderFactory::GetInstance()); +} + +WebAppUiServiceFactory::~WebAppUiServiceFactory() = default; + +KeyedService* WebAppUiServiceFactory::BuildServiceInstanceFor( + content::BrowserContext* context) const { + return new WebAppUiService(Profile::FromBrowserContext(context)); +} + +bool WebAppUiServiceFactory::ServiceIsCreatedWithBrowserContext() const { + return true; +} + +content::BrowserContext* WebAppUiServiceFactory::GetBrowserContextToUse( + content::BrowserContext* context) const { + return GetBrowserContextForWebApps(context); +} + +} // namespace web_app
diff --git a/chrome/browser/ui/web_applications/web_app_ui_service_factory.h b/chrome/browser/ui/web_applications/web_app_ui_service_factory.h new file mode 100644 index 0000000..1f5683c9 --- /dev/null +++ b/chrome/browser/ui/web_applications/web_app_ui_service_factory.h
@@ -0,0 +1,48 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEB_APPLICATIONS_WEB_APP_UI_SERVICE_FACTORY_H_ +#define CHROME_BROWSER_UI_WEB_APPLICATIONS_WEB_APP_UI_SERVICE_FACTORY_H_ + +#include "base/macros.h" +#include "base/memory/singleton.h" +#include "components/keyed_service/content/browser_context_keyed_service_factory.h" + +namespace content { +class BrowserContext; +} + +class Profile; + +namespace web_app { + +class WebAppUiService; + +// Singleton that owns all WebAppUiServices and associates them +// with Profile. +class WebAppUiServiceFactory : public BrowserContextKeyedServiceFactory { + public: + static WebAppUiService* GetForProfile(Profile* profile); + + static WebAppUiServiceFactory* GetInstance(); + + private: + friend struct base::DefaultSingletonTraits<WebAppUiServiceFactory>; + + WebAppUiServiceFactory(); + ~WebAppUiServiceFactory() override; + + // BrowserContextKeyedServiceFactory + KeyedService* BuildServiceInstanceFor( + content::BrowserContext* context) const override; + bool ServiceIsCreatedWithBrowserContext() const override; + content::BrowserContext* GetBrowserContextToUse( + content::BrowserContext* context) const override; + + DISALLOW_COPY_AND_ASSIGN(WebAppUiServiceFactory); +}; + +} // namespace web_app + +#endif // CHROME_BROWSER_UI_WEB_APPLICATIONS_WEB_APP_UI_SERVICE_FACTORY_H_
diff --git a/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision.mojom b/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision.mojom index 784434c..7d50324 100644 --- a/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision.mojom +++ b/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision.mojom
@@ -18,9 +18,6 @@ // Returns an array of package names of installed ARC apps. GetInstalledArcApps() => (array<string> package_names); - // Uninstalls the ARC apps specified by the list of package names. - UninstallArcApps(array<string> package_names) => (); - // Returns the oauth token to be passed to the server. GetOAuthToken() => (OAuthTokenFetchStatus status, string oauth_token); };
diff --git a/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.cc b/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.cc index 4e849e51..2bf9775a 100644 --- a/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.cc +++ b/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.cc
@@ -4,7 +4,9 @@ #include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.h" +#include <string> #include <utility> +#include <vector> #include "base/stl_util.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" @@ -60,31 +62,6 @@ std::move(callback).Run(installed_arc_apps); } -void AddSupervisionHandler::UninstallArcApps( - const std::vector<std::string>& package_names, - UninstallArcAppsCallback callback) { - Profile* profile = Profile::FromWebUI(web_ui_); - apps::AppServiceProxy* proxy = - apps::AppServiceProxyFactory::GetForProfile(profile); - - for (const std::string& package_name : package_names) { - proxy->AppRegistryCache().ForOneApp( - arc::ArcPackageNameToAppId(package_name, profile), - [proxy, package_names, profile](const apps::AppUpdate& update) { - // We don't include "sticky" ARC apps because they are - // system-required apps that should not be uninstalled. - // TODO(danan): check for stickyness via the App Service instead - // when that is available. (https://crbug.com/948408). - if (ShouldIncludeAppUpdate(update) && - !arc::IsArcAppSticky(update.AppId(), profile)) { - proxy->Uninstall(update.AppId()); - } - }); - } - - std::move(callback).Run(); -} - void AddSupervisionHandler::GetOAuthToken(GetOAuthTokenCallback callback) { identity::ScopeSet scopes; scopes.insert(GaiaConstants::kKidFamilyOAuth2Scope);
diff --git a/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.h b/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.h index 6f58d04..d07c2886 100644 --- a/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.h +++ b/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.h
@@ -5,9 +5,6 @@ #ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_ADD_SUPERVISION_ADD_SUPERVISION_HANDLER_H_ #define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ADD_SUPERVISION_ADD_SUPERVISION_HANDLER_H_ -#include <string> -#include <vector> - #include "base/callback_forward.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" @@ -37,8 +34,6 @@ // add_supervision::mojom::AddSupervisionHandler overrides: void LogOut(LogOutCallback callback) override; void GetInstalledArcApps(GetInstalledArcAppsCallback callback) override; - void UninstallArcApps(const std::vector<std::string>& apps, - UninstallArcAppsCallback callback) override; void GetOAuthToken(GetOAuthTokenCallback callback) override; private:
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc index 71aabddc..eef88d33 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -233,6 +233,7 @@ proxy_auth_dialog_reload_times_(kMaxGaiaReloadForProxyAuthDialog), gaia_screen_handler_(gaia_screen_handler), histogram_helper_(new ErrorScreensHistogramHelper("Signin")), + observer_binding_(this), weak_factory_(this) { DCHECK(network_state_informer_.get()); DCHECK(error_screen_); @@ -267,12 +268,12 @@ tablet_mode_client->AddObserver(this); OnTabletModeToggled(tablet_mode_client->tablet_mode_enabled()); - WallpaperControllerClient::Get()->AddObserver(this); + ash::mojom::WallpaperObserverAssociatedPtrInfo ptr_info; + observer_binding_.Bind(mojo::MakeRequest(&ptr_info)); + WallpaperControllerClient::Get()->AddObserver(std::move(ptr_info)); } SigninScreenHandler::~SigninScreenHandler() { - if (auto* wallpaper_controller_client = WallpaperControllerClient::Get()) - wallpaper_controller_client->RemoveObserver(this); TabletModeClient::Get()->RemoveObserver(this); OobeUI* oobe_ui = GetOobeUI(); if (oobe_ui && oobe_ui_observer_added_) @@ -827,12 +828,14 @@ } } -void SigninScreenHandler::OnWallpaperColorsChanged() { +void SigninScreenHandler::OnWallpaperChanged(uint32_t image_id) {} + +void SigninScreenHandler::OnWallpaperColorsChanged( + const std::vector<SkColor>& prominent_colors) { // Updates the color of the scrollable container on account picker screen, // based on wallpaper color extraction results. - auto colors = WallpaperControllerClient::Get()->GetWallpaperColors(); SkColor dark_muted_color = - colors[static_cast<int>(ash::ColorProfileType::DARK_MUTED)]; + prominent_colors[static_cast<int>(ash::ColorProfileType::DARK_MUTED)]; if (dark_muted_color == ash::kInvalidWallpaperColor) dark_muted_color = ash::login_constants::kDefaultBaseColor; @@ -848,10 +851,9 @@ color_utils::SkColorToRgbaString(scroll_color)); } -void SigninScreenHandler::OnWallpaperBlurChanged() { - const bool show_pod_background = - !WallpaperControllerClient::Get()->IsWallpaperBlurred(); - CallJS("login.AccountPickerScreen.togglePodBackground", show_pod_background); +void SigninScreenHandler::OnWallpaperBlurChanged(bool blurred) { + CallJS("login.AccountPickerScreen.togglePodBackground", + !blurred /*show_pod_background=*/); } void SigninScreenHandler::ClearAndEnablePassword() { @@ -1207,8 +1209,12 @@ // The wallpaper may have been set before the instance is initialized, so make // sure the colors and blur state are updated. - OnWallpaperColorsChanged(); - OnWallpaperBlurChanged(); + WallpaperControllerClient::Get()->GetWallpaperColors( + base::BindOnce(&SigninScreenHandler::OnWallpaperColorsChanged, + weak_factory_.GetWeakPtr())); + WallpaperControllerClient::Get()->IsWallpaperBlurred( + base::BindOnce(&SigninScreenHandler::OnWallpaperBlurChanged, + weak_factory_.GetWeakPtr())); session_manager::SessionManager* session_manager = session_manager::SessionManager::Get();
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h index 48988d3..c2ab54e 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
@@ -10,7 +10,7 @@ #include <set> #include <string> -#include "ash/public/cpp/wallpaper_controller_observer.h" +#include "ash/public/interfaces/wallpaper.mojom.h" #include "base/callback.h" #include "base/compiler_specific.h" #include "base/macros.h" @@ -32,6 +32,7 @@ #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "content/public/browser/web_ui.h" +#include "mojo/public/cpp/bindings/associated_binding.h" #include "net/base/net_errors.h" #include "ui/base/ime/chromeos/ime_keyboard.h" #include "ui/base/ime/chromeos/input_method_manager.h" @@ -185,7 +186,7 @@ public input_method::ImeKeyboard::Observer, public TabletModeClientObserver, public OobeUI::Observer, - public ash::WallpaperControllerObserver { + public ash::mojom::WallpaperObserver { public: SigninScreenHandler( JSCallsContainer* js_calls_container, @@ -224,9 +225,11 @@ OobeScreenId new_screen) override; void OnDestroyingOobeUI() override {} - // ash::WallpaperControllerObserver implementation: - void OnWallpaperColorsChanged() override; - void OnWallpaperBlurChanged() override; + // ash::mojom::WallpaperObserver implementation: + void OnWallpaperChanged(uint32_t image_id) override; + void OnWallpaperColorsChanged( + const std::vector<SkColor>& prominent_colors) override; + void OnWallpaperBlurChanged(bool blurred) override; void SetFocusPODCallbackForTesting(base::Closure callback); @@ -503,6 +506,9 @@ std::unique_ptr<AccountId> focused_pod_account_id_; + // The binding this instance uses to implement ash::mojom::WallpaperObserver. + mojo::AssociatedBinding<ash::mojom::WallpaperObserver> observer_binding_; + base::WeakPtrFactory<SigninScreenHandler> weak_factory_; DISALLOW_COPY_AND_ASSIGN(SigninScreenHandler);
diff --git a/chrome/browser/ui/webui/extensions/extensions_ui.cc b/chrome/browser/ui/webui/extensions/extensions_ui.cc index 05990cf..f9859030 100644 --- a/chrome/browser/ui/webui/extensions/extensions_ui.cc +++ b/chrome/browser/ui/webui/extensions/extensions_ui.cc
@@ -245,6 +245,7 @@ {"loadErrorErrorLabel", IDS_EXTENSIONS_LOAD_ERROR_ERROR_LABEL}, {"loadErrorRetry", IDS_EXTENSIONS_LOAD_ERROR_RETRY}, {"loadingActivities", IDS_EXTENSIONS_LOADING_ACTIVITIES}, + {"missingOrUninstalledExtension", IDS_MISSING_OR_UNINSTALLED_EXTENSION}, {"noActivities", IDS_EXTENSIONS_NO_ACTIVITIES}, {"noErrorsToShow", IDS_EXTENSIONS_ERROR_NO_ERRORS_CODE_MESSAGE}, {"runtimeHostsDialogInputError",
diff --git a/chrome/browser/ui/webui/settings/appearance_handler.cc b/chrome/browser/ui/webui/settings/appearance_handler.cc index 435767b8b..ae92d56 100644 --- a/chrome/browser/ui/webui/settings/appearance_handler.cc +++ b/chrome/browser/ui/webui/settings/appearance_handler.cc
@@ -71,16 +71,17 @@ #if defined(OS_CHROMEOS) void AppearanceHandler::IsWallpaperSettingVisible(const base::ListValue* args) { CHECK_EQ(args->GetSize(), 1U); - bool result = WallpaperControllerClient::Get()->ShouldShowWallpaperSetting(); - ResolveCallback(args->GetList()[0], result); + WallpaperControllerClient::Get()->ShouldShowWallpaperSetting( + base::Bind(&AppearanceHandler::ResolveCallback, + weak_ptr_factory_.GetWeakPtr(), args->GetList()[0].Clone())); } void AppearanceHandler::IsWallpaperPolicyControlled( const base::ListValue* args) { CHECK_EQ(args->GetSize(), 1U); - bool result = WallpaperControllerClient::Get() - ->IsActiveUserWallpaperControlledByPolicy(); - ResolveCallback(args->GetList()[0], result); + WallpaperControllerClient::Get()->IsActiveUserWallpaperControlledByPolicy( + base::Bind(&AppearanceHandler::ResolveCallback, + weak_ptr_factory_.GetWeakPtr(), args->GetList()[0].Clone())); } void AppearanceHandler::HandleOpenWallpaperManager(
diff --git a/chrome/browser/vr/service/xr_runtime_manager.cc b/chrome/browser/vr/service/xr_runtime_manager.cc index 8729fea..c3eff313 100644 --- a/chrome/browser/vr/service/xr_runtime_manager.cc +++ b/chrome/browser/vr/service/xr_runtime_manager.cc
@@ -52,6 +52,13 @@ base::LazyInstance<base::ObserverList<XRRuntimeManagerObserver>>::Leaky g_xr_runtime_manager_observers; + +// Returns true if any of the AR-related features are enabled. +bool AreArFeaturesEnabled() { + return base::FeatureList::IsEnabled(features::kWebXrHitTest) || + base::FeatureList::IsEnabled(features::kWebXrPlaneDetection); +} + } // namespace XRRuntimeManager::~XRRuntimeManager() { @@ -64,15 +71,17 @@ // Register VRDeviceProviders for the current platform ProviderList providers; + if (AreArFeaturesEnabled()) { #if defined(OS_ANDROID) #if BUILDFLAG(ENABLE_ARCORE) - if (base::FeatureList::IsEnabled(features::kWebXrHitTest)) { providers.emplace_back(device::ArCoreDeviceProviderFactory::Create()); +#endif // BUILDFLAG(ENABLE_ARCORE) +#endif // defined(OS_ANDROID) } -#endif +#if defined(OS_ANDROID) providers.emplace_back(std::make_unique<device::GvrDeviceProvider>()); -#endif +#endif // defined(OS_ANDROID) #if BUILDFLAG(ENABLE_ISOLATED_XR_SERVICE) providers.emplace_back(std::make_unique<vr::IsolatedVRDeviceProvider>());
diff --git a/chrome/browser/vr/service/xr_session_request_consent_manager_impl.cc b/chrome/browser/vr/service/xr_session_request_consent_manager_impl.cc index c194d9e5..d962f66 100644 --- a/chrome/browser/vr/service/xr_session_request_consent_manager_impl.cc +++ b/chrome/browser/vr/service/xr_session_request_consent_manager_impl.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/vr/service/xr_session_request_consent_manager_impl.h" +#include <memory> #include <utility> #include "chrome/browser/ui/tab_modal_confirm_dialog.h" @@ -22,10 +23,10 @@ XRSessionRequestConsentManagerImpl::ShowDialogAndGetConsent( content::WebContents* web_contents, base::OnceCallback<void(bool)> response_callback) { - auto* delegate = new XrSessionRequestConsentDialogDelegate( + auto delegate = std::make_unique<XrSessionRequestConsentDialogDelegate>( web_contents, std::move(response_callback)); delegate->OnShowDialog(); - return TabModalConfirmDialog::Create(delegate, web_contents); + return TabModalConfirmDialog::Create(std::move(delegate), web_contents); } } // namespace vr
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index ac9a6b9..fedf2cf4 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -613,15 +613,18 @@ // necessary here (see https://crbug.com/965747). For now, returning false // should take us to CreatePlugin after HTMLPlugInElement which is called // through HTMLPlugInElement::LoadPlugin code path. - if ((plugin_info->status != chrome::mojom::PluginStatus::kAllowed && - plugin_info->status != - chrome::mojom::PluginStatus::kPlayImportantContent) || - !ChromeExtensionsRendererClient::MaybeCreateMimeHandlerView( - plugin_element, original_url, plugin_info->actual_mime_type, - plugin_info->plugin)) { + if (plugin_info->status != chrome::mojom::PluginStatus::kAllowed && + plugin_info->status != + chrome::mojom::PluginStatus::kPlayImportantContent) { + // We could get here when a MimeHandlerView is loaded inside a <webview> + // which is using permissions API (see WebViewPluginTests). + ChromeExtensionsRendererClient::DidBlockMimeHandlerViewForDisallowedPlugin( + plugin_element); return false; } - return true; + return ChromeExtensionsRendererClient::MaybeCreateMimeHandlerView( + plugin_element, original_url, plugin_info->actual_mime_type, + plugin_info->plugin); #else return false; #endif @@ -821,17 +824,13 @@ const Extension* extension = extensions::RendererExtensionRegistry::Get() ->GetExtensionOrAppByURL(manifest_url); - if (!IsNaClAllowed(app_url, is_nacl_unrestricted, extension, - ¶ms)) { + if (!IsNativeNaClAllowed(app_url, is_nacl_unrestricted, extension)) { WebString error_message; if (is_nacl_mime_type) { error_message = "Only unpacked extensions and apps installed from the Chrome " "Web Store can load NaCl modules without enabling Native " "Client in about:flags."; - } else if (is_pnacl_mime_type) { - error_message = - "Portable Native Client must not be disabled in about:flags."; } frame->AddMessageToConsole(WebConsoleMessage( blink::mojom::ConsoleMessageLevel::kError, error_message)); @@ -1052,12 +1051,10 @@ #if BUILDFLAG(ENABLE_NACL) // static -bool ChromeContentRendererClient::IsNaClAllowed( +bool ChromeContentRendererClient::IsNativeNaClAllowed( const GURL& app_url, bool is_nacl_unrestricted, - const Extension* extension, - WebPluginParams* params) { - // Temporarily allow these whitelisted apps to use NaCl. + const Extension* extension) { bool is_invoked_by_webstore_installed_extension = false; bool is_extension_unrestricted = false; bool is_extension_force_installed = false;
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h index ac59181f..699c3da 100644 --- a/chrome/renderer/chrome_content_renderer_client.h +++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -258,12 +258,11 @@ base::TimeTicks main_entry_time_; #if BUILDFLAG(ENABLE_NACL) - // Determines if a NaCl app is allowed, and modifies params to pass the app's - // permissions to the trusted NaCl plugin. - static bool IsNaClAllowed(const GURL& app_url, - bool is_nacl_unrestricted, - const extensions::Extension* extension, - blink::WebPluginParams* params); + // Determines if a page/app/extension is allowed to run native (non-PNaCl) + // NaCl modules. + static bool IsNativeNaClAllowed(const GURL& app_url, + bool is_nacl_unrestricted, + const extensions::Extension* extension); #endif service_manager::Connector* GetConnector();
diff --git a/chrome/renderer/chrome_content_renderer_client_unittest.cc b/chrome/renderer/chrome_content_renderer_client_unittest.cc index c6e91b4b..31c3966cd 100644 --- a/chrome/renderer/chrome_content_renderer_client_unittest.cc +++ b/chrome/renderer/chrome_content_renderer_client_unittest.cc
@@ -152,103 +152,79 @@ #if BUILDFLAG(ENABLE_NACL) // --enable-nacl allows all NaCl apps. { - WebPluginParams params; - EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed( - GURL(), - kNaClUnrestricted, - CreateExtension(kExtensionNotFromWebStore).get(), - ¶ms)); + EXPECT_TRUE(ChromeContentRendererClient::IsNativeNaClAllowed( + GURL(), kNaClUnrestricted, + CreateExtension(kExtensionNotFromWebStore).get())); } // Unpacked extensions are allowed without --enable-nacl. { - WebPluginParams params; - EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed( - GURL(kExtensionUrl), - kNaClRestricted, + EXPECT_TRUE(ChromeContentRendererClient::IsNativeNaClAllowed( + GURL(kExtensionUrl), kNaClRestricted, CreateExtensionWithLocation(extensions::Manifest::UNPACKED, - kExtensionNotFromWebStore).get(), - ¶ms)); + kExtensionNotFromWebStore) + .get())); } // Component extensions are allowed without --enable-nacl. { - WebPluginParams params; - EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed( - GURL(kExtensionUrl), - kNaClRestricted, + EXPECT_TRUE(ChromeContentRendererClient::IsNativeNaClAllowed( + GURL(kExtensionUrl), kNaClRestricted, CreateExtensionWithLocation(extensions::Manifest::COMPONENT, - kExtensionNotFromWebStore).get(), - ¶ms)); + kExtensionNotFromWebStore) + .get())); } { - WebPluginParams params; - EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed( - GURL(kExtensionUrl), - kNaClRestricted, + EXPECT_TRUE(ChromeContentRendererClient::IsNativeNaClAllowed( + GURL(kExtensionUrl), kNaClRestricted, CreateExtensionWithLocation(extensions::Manifest::EXTERNAL_COMPONENT, - kExtensionNotFromWebStore).get(), - ¶ms)); + kExtensionNotFromWebStore) + .get())); } // Extensions that are force installed by policy are allowed without // --enable-nacl. { - WebPluginParams params; - EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed( - GURL(kExtensionUrl), - kNaClRestricted, + EXPECT_TRUE(ChromeContentRendererClient::IsNativeNaClAllowed( + GURL(kExtensionUrl), kNaClRestricted, CreateExtensionWithLocation(extensions::Manifest::EXTERNAL_POLICY, - kExtensionNotFromWebStore).get(), - ¶ms)); - EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed( - GURL(kExtensionUrl), - kNaClRestricted, + kExtensionNotFromWebStore) + .get())); + EXPECT_TRUE(ChromeContentRendererClient::IsNativeNaClAllowed( + GURL(kExtensionUrl), kNaClRestricted, CreateExtensionWithLocation( extensions::Manifest::EXTERNAL_POLICY_DOWNLOAD, - kExtensionNotFromWebStore).get(), - ¶ms)); + kExtensionNotFromWebStore) + .get())); } // CWS extensions are allowed without --enable-nacl if called from an // extension url. { - WebPluginParams params; - EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed( - GURL(kExtensionUrl), - kNaClRestricted, - CreateExtension(kExtensionFromWebStore).get(), - ¶ms)); + EXPECT_TRUE(ChromeContentRendererClient::IsNativeNaClAllowed( + GURL(kExtensionUrl), kNaClRestricted, + CreateExtension(kExtensionFromWebStore).get())); } // Other URLs (including previously-whitelisted URLs) are blocked // without --enable-nacl. { - WebPluginParams params; - EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed( - GURL("https://plus.google.com.evil.com/foo1"), kNaClRestricted, nullptr, - ¶ms)); - EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed( + EXPECT_FALSE(ChromeContentRendererClient::IsNativeNaClAllowed( + GURL("https://plus.google.com.evil.com/foo1"), kNaClRestricted, + nullptr)); + EXPECT_FALSE(ChromeContentRendererClient::IsNativeNaClAllowed( GURL("https://talkgadget.google.com/hangouts/foo1"), kNaClRestricted, - nullptr, ¶ms)); + nullptr)); } // Non chrome-extension:// URLs belonging to hosted apps are allowed for // webstore installed hosted apps. { - WebPluginParams params; - EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed( - GURL("http://example.com/test.html"), - kNaClRestricted, - CreateHostedApp(kExtensionFromWebStore, - "http://example.com/").get(), - ¶ms)); - EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed( - GURL("http://example.com/test.html"), - kNaClRestricted, - CreateHostedApp(kExtensionNotFromWebStore, - "http://example.com/").get(), - ¶ms)); - EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed( - GURL("http://example.evil.com/test.html"), - kNaClRestricted, - CreateHostedApp(kExtensionNotFromWebStore, - "http://example.com/").get(), - ¶ms)); + EXPECT_TRUE(ChromeContentRendererClient::IsNativeNaClAllowed( + GURL("http://example.com/test.html"), kNaClRestricted, + CreateHostedApp(kExtensionFromWebStore, "http://example.com/").get())); + EXPECT_FALSE(ChromeContentRendererClient::IsNativeNaClAllowed( + GURL("http://example.com/test.html"), kNaClRestricted, + CreateHostedApp(kExtensionNotFromWebStore, "http://example.com/") + .get())); + EXPECT_FALSE(ChromeContentRendererClient::IsNativeNaClAllowed( + GURL("http://example.evil.com/test.html"), kNaClRestricted, + CreateHostedApp(kExtensionNotFromWebStore, "http://example.com/") + .get())); } #endif // BUILDFLAG(ENABLE_NACL) }
diff --git a/chrome/renderer/extensions/chrome_extensions_renderer_client.cc b/chrome/renderer/extensions/chrome_extensions_renderer_client.cc index 486c5a65..2eae139 100644 --- a/chrome/renderer/extensions/chrome_extensions_renderer_client.cc +++ b/chrome/renderer/extensions/chrome_extensions_renderer_client.cc
@@ -319,6 +319,16 @@ } // static +void ChromeExtensionsRendererClient::DidBlockMimeHandlerViewForDisallowedPlugin( + const blink::WebElement& plugin_element) { + extensions::MimeHandlerViewContainerManager::Get( + content::RenderFrame::FromWebFrame( + plugin_element.GetDocument().GetFrame()), + true /* create_if_does_not_exist */) + ->DidBlockMimeHandlerViewForDisallowedPlugin(plugin_element); +} + +// static bool ChromeExtensionsRendererClient::MaybeCreateMimeHandlerView( const blink::WebElement& plugin_element, const GURL& resource_url,
diff --git a/chrome/renderer/extensions/chrome_extensions_renderer_client.h b/chrome/renderer/extensions/chrome_extensions_renderer_client.h index 1612bbe1..13ff1500 100644 --- a/chrome/renderer/extensions/chrome_extensions_renderer_client.h +++ b/chrome/renderer/extensions/chrome_extensions_renderer_client.h
@@ -93,6 +93,8 @@ const content::WebPluginInfo& info, const std::string& mime_type, const GURL& original_url); + static void DidBlockMimeHandlerViewForDisallowedPlugin( + const blink::WebElement& plugin_element); static bool MaybeCreateMimeHandlerView( const blink::WebElement& plugin_element, const GURL& resource_url,
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index ef83da0..2e6cb58 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -445,6 +445,41 @@ } } +if (is_android) { + test("android_browsertests") { + configs += [ "//build/config:precompiled_headers" ] + defines = [ + "HAS_OUT_OF_PROC_TEST_RUNNER", + "CHROME_VERSION_MAJOR=" + chrome_version_major, + ] + use_default_launcher = false + + deps = [ + ":test_support", + ":test_support_ui_android", + "//chrome/android:app_hooks_java", + "//chrome/android:chrome_java", + ] + + sources = [] + } + + static_library("test_support_ui_android") { + configs += [ "//build/config:precompiled_headers" ] + testonly = true + + sources = [ + # TODO(crbug.com/961849): Write an AndroidBrowserTest base class and put + # it here. + ] + public_deps = [] + deps = [ + "//chrome/browser", + "//content/public/browser", + ] + } +} + if (!is_android) { static_library("browser_tests_runner") { testonly = true @@ -466,129 +501,144 @@ } test("browser_tests") { - sources = [ - # TODO(jbudorick): Move tests here from other lists as Android support is - # implemented. See crbug.com/611756 - ] - configs += [ "//build/config:precompiled_headers" ] - - deps = [ - ":browser_tests_runner", - ":test_support", - "//base", - "//chrome/browser/profiling_host:profiling_browsertests", - "//components/cbor", - "//components/nacl/common:buildflags", - "//components/spellcheck:buildflags", - "//components/sync:test_support_model", - "//extensions/buildflags", - "//media:media_buildflags", - "//net:test_support", - "//ppapi/buildflags", - "//printing/buildflags", - "//rlz/buildflags", - "//services/strings", - "//third_party/blink/public:buildflags", - ] - - data_deps = [ - "//testing/buildbot/filters:browser_tests_filters", - "//tools/media_engagement_preload:generator", - ] - - data = [] - defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER", "CHROME_VERSION_MAJOR=" + chrome_version_major, ] - if (is_win) { - data += [ "$root_out_dir/chrome_200_percent.pak" ] - deps += [ "//chrome/app:chrome_dll_resources" ] - } - if (is_chromeos) { - data += [ - # TODO(GYP): figure out which of these things are - # actually needed and also which should be pulled in via - # data or data_deps and through which dependencies. - "//chrome/browser/chromeos/login/test/https_forwarder.py", - "//chrome/browser/resources/chromeos/wallpaper_manager/", - "//chrome/browser/resources/chromeos/zip_archiver/", - "//google_apis/test/", - "//chrome/browser/resources/chromeos/zip_archiver/test/", - "//chromeos/test/data/", - "//ui/file_manager/base/", - "//ui/file_manager/file_manager/", - "//ui/file_manager/gallery/", - "//ui/file_manager/image_loader/", - "//ui/file_manager/integration_tests/", - "//ui/file_manager/video_player", - "//third_party/polymer/v1_0/components-chromium/", - "$root_gen_dir/ui/file_manager/file_manager/", - "$root_out_dir/chromevox_test_data/", - "$root_out_dir/content_shell.pak", - "$root_out_dir/resources/chromeos/", - ] + deps = [ + ":browser_tests_runner", + ":policy_testserver_pyproto", + ":test_support", + ":test_support_ui", + "//base", + "//base:i18n", + "//base/test:test_support", + "//chrome:browser_tests_pak", + "//chrome:packed_resources", + "//chrome:resources", + "//chrome:strings", + "//chrome/browser", + "//chrome/browser/devtools:test_support", + "//chrome/browser/profiling_host:profiling_browsertests", + "//chrome/browser/web_applications:browser_tests", + "//chrome/renderer", + "//chrome/services/removable_storage_writer:lib", + "//components/autofill/content/browser:risk_proto", + "//components/autofill/content/common:mojo_interfaces", + "//components/autofill/content/renderer:test_support", + "//components/captive_portal:test_support", + "//components/cbor", + "//components/data_reduction_proxy/core/browser:test_support", + "//components/dom_distiller/content/browser", + "//components/dom_distiller/content/renderer", + "//components/dom_distiller/core:test_support", + "//components/feature_engagement/test:test_support", + "//components/nacl/common:buildflags", + "//components/offline_items_collection/core/test_support", + "//components/optimization_guide:test_support", + "//components/policy:chrome_settings_proto_generated_compile", + "//components/resources", + "//components/safe_browsing/db:test_database_manager", + "//components/services/quarantine:test_support", + "//components/spellcheck:buildflags", + "//components/strings", + "//components/sync", + "//components/sync:test_support_model", + "//components/translate/core/common", + "//content/public/common:buildflags", + "//content/test:test_support", + "//crypto:platform", + "//crypto:test_support", + "//device/bluetooth:mocks", + "//extensions/buildflags", + "//google_apis:test_support", + "//media:media_buildflags", + "//media:test_support", + "//media/cast:test_support", + "//mojo/public/cpp/system", + "//net", + "//net:test_support", + "//net:test_support", + "//ppapi/buildflags", + "//printing/buildflags", + "//rlz/buildflags", + "//services/device/public/cpp:test_support", + "//services/device/public/mojom", + "//services/network/public/cpp", + "//services/service_manager/public/cpp", + "//services/strings", + "//skia", + "//testing/gmock", + "//testing/gtest", + "//testing/perf", + "//third_party/blink/public:blink_headers", + "//third_party/blink/public:buildflags", + "//third_party/cacheinvalidation", + "//third_party/icu", + "//third_party/leveldatabase", + "//third_party/webrtc_overrides", + "//third_party/widevine/cdm:buildflags", + "//third_party/widevine/cdm:headers", + "//ui/accessibility:test_support", + "//ui/base:test_support", + "//ui/base/clipboard:clipboard_test_support", + "//ui/compositor:test_support", + "//ui/native_theme:test_support", + "//ui/resources", + "//ui/web_dialogs:test_support", + "//v8", + ] - data_deps += [ - "//chrome", - "//ash/keyboard/ui:resources", - "//ui/file_manager:unit_test_data", - ] + # Runtime dependencies + data_deps = [ + "//ppapi:ppapi_tests", + "//ppapi:power_saver_test_plugin", + "//remoting/webapp:browser_test_resources", + "//remoting/webapp:unit_tests", + "//testing/buildbot/filters:browser_tests_filters", + "//third_party/mesa_headers", + "//third_party/widevine/cdm:widevine_test_license_server", + "//tools/media_engagement_preload:generator", + ] - if (use_dbus) { - deps += [ "//dbus:test_support" ] - } + data = [ + "data/", + "//chrome/browser/policy/test/asn1der.py", + "//chrome/browser/policy/test/policy_testserver.py", + "//chrome/common/extensions/docs/examples/apps/calculator/", + "//chrome/third_party/mock4js/", + "//components/test/data/arc/", + "//components/test/data/autofill/", + "//components/test/data/payments/", + "//components/test/data/update_client/", + "//content/test/data/", + "//google_apis/test/", + "//media/test/data/", + "//net/tools/testserver/", + "//ppapi/tests/test_case.html", + "//ppapi/tests/test_case.html.mock-http-headers", + "//ppapi/tests/test_page.css", + "//ppapi/tests/test_page.css.mock-http-headers", + "//testing/test_env.py", + "//third_party/accessibility-audit/axs_testing.js", + "//third_party/chaijs/chai.js", + "//third_party/mocha/mocha.js", + "//third_party/polymer/v1_0/components-chromium/iron-test-helpers/mock-interactions.js", + "//third_party/pywebsocket/src/mod_pywebsocket/", + "//third_party/simplejson/", + "//third_party/tlslite/", + "//ui/webui/resources/", + "$root_out_dir/browser_tests.pak", + "$root_out_dir/test_case.html", + "$root_out_dir/test_case.html.mock-http-headers", + "$root_out_dir/test_page.css", + "$root_out_dir/test_page.css.mock-http-headers", + "$root_out_dir/test_url_loader_data/", + ] - if (enable_nacl) { - data_deps += [ - "//components/nacl/loader:nacl_helper", - "//ppapi/native_client:irt", - ] - - if (enable_nacl_nonsfi) { - data_deps += [ "//components/nacl/loader:helper_nonsfi" ] - } - } - - deps += [ - "//ash:test_support", - "//ash/keyboard/ui:test_support", - "//ash/public/interfaces:test_interfaces", - "//chrome/browser/chromeos:arc_test_support", - "//chrome/browser/chromeos:test_support", - "//chrome/browser/media/router:test_support", - "//chrome/browser/resources/chromeos/chromevox:browser_tests", - "//chrome/browser/resources/chromeos/login:browser_tests", - "//chrome/browser/resources/chromeos/select_to_speak:browser_tests", - "//chrome/browser/resources/chromeos/switch_access:browser_tests", - "//chrome/services/file_util/public/cpp:browser_tests", - "//chromeos:test_support", - "//chromeos/components/drivefs:test_support", - "//chromeos/dbus:test_support", - "//chromeos/dbus/session_manager", - "//components/arc:arc_test_support", - "//components/exo:test_support", - "//components/prefs", - "//components/user_manager:test_support", - "//content/public/common:feature_h264_with_openh264_ffmpeg", - "//mojo/core/embedder", - "//services/audio/public/cpp:test_support", - "//services/identity/public/cpp", - "//services/network/public/mojom", - "//services/preferences/public/cpp", - "//services/preferences/public/mojom", - "//services/service_manager/public/cpp", - "//services/ws/public/cpp/input_devices:test_support", - "//url", - ] - } - - sources += [ - # The list of sources which is only used by chrome browser tests on - # desktop platforms. + sources = [ "../../apps/app_restore_service_browsertest.cc", "../../apps/load_and_launch_browsertest.cc", "../app/chrome_version.rc.version", @@ -1053,7 +1103,7 @@ "../browser/ui/views/webauthn/authenticator_dialog_view_browsertest.cc", "../browser/ui/views/webview_accessibility_browsertest.cc", "../browser/ui/web_applications/bookmark_app_browsertest.cc", - "../browser/ui/web_applications/web_app_ui_delegate_impl_browsertest.cc", + "../browser/ui/web_applications/web_app_ui_service_browsertest.cc", "../browser/ui/webauthn/authenticator_dialog_browsertest.cc", "../browser/ui/webui/bookmarks/bookmarks_browsertest.cc", "../browser/ui/webui/bookmarks/bookmarks_browsertest.h", @@ -1139,72 +1189,76 @@ "v8/wasm_trap_handler_browsertest.cc", ] - deps += [ - ":policy_testserver_pyproto", - ":test_support_ui", - "//base:i18n", - "//base/test:test_support", - "//chrome:browser_tests_pak", - "//chrome:packed_resources", - "//chrome:resources", - "//chrome:strings", - "//chrome/browser", - "//chrome/browser/devtools:test_support", - "//chrome/browser/web_applications:browser_tests", - "//chrome/renderer", - "//chrome/services/removable_storage_writer:lib", - "//components/autofill/content/browser:risk_proto", - "//components/autofill/content/common:mojo_interfaces", - "//components/autofill/content/renderer:test_support", - "//components/captive_portal:test_support", - "//components/data_reduction_proxy/core/browser:test_support", - "//components/dom_distiller/content/browser", - "//components/dom_distiller/content/renderer", - "//components/dom_distiller/core:test_support", - "//components/feature_engagement/test:test_support", - "//components/offline_items_collection/core/test_support", - "//components/optimization_guide:test_support", - "//components/policy:chrome_settings_proto_generated_compile", - "//components/resources", - "//components/safe_browsing/db:test_database_manager", - "//components/services/quarantine:test_support", - "//components/strings", - "//components/sync", - "//components/translate/core/common", - "//content/public/common:buildflags", - "//content/test:test_support", - "//crypto:platform", - "//crypto:test_support", - "//device/bluetooth:mocks", - "//google_apis:test_support", - "//media:test_support", - "//media/cast:test_support", - "//mojo/public/cpp/system", - "//net", - "//net:test_support", - "//services/device/public/cpp:test_support", - "//services/device/public/mojom", - "//services/network/public/cpp", - "//services/service_manager/public/cpp", - "//skia", - "//testing/gmock", - "//testing/gtest", - "//testing/perf", - "//third_party/cacheinvalidation", - "//third_party/icu", - "//third_party/leveldatabase", - "//third_party/webrtc_overrides", - "//third_party/widevine/cdm:buildflags", - "//third_party/widevine/cdm:headers", - "//ui/accessibility:test_support", - "//ui/base:test_support", - "//ui/base/clipboard:clipboard_test_support", - "//ui/compositor:test_support", - "//ui/native_theme:test_support", - "//ui/resources", - "//ui/web_dialogs:test_support", - "//v8", - ] + if (is_win) { + data += [ "$root_out_dir/chrome_200_percent.pak" ] + deps += [ "//chrome/app:chrome_dll_resources" ] + } + + if (is_chromeos) { + data += [ + # TODO(GYP): figure out which of these things are + # actually needed and also which should be pulled in via + # data or data_deps and through which dependencies. + "//chrome/browser/chromeos/login/test/https_forwarder.py", + "//chrome/browser/resources/chromeos/wallpaper_manager/", + "//chrome/browser/resources/chromeos/zip_archiver/", + "//chrome/browser/resources/chromeos/zip_archiver/test/", + "//chromeos/test/data/", + "//ui/file_manager/base/", + "//ui/file_manager/file_manager/", + "//ui/file_manager/gallery/", + "//ui/file_manager/image_loader/", + "//ui/file_manager/integration_tests/", + "//ui/file_manager/video_player", + "//third_party/polymer/v1_0/components-chromium/", + "$root_gen_dir/ui/file_manager/file_manager/", + "$root_out_dir/chromevox_test_data/", + "$root_out_dir/content_shell.pak", + "$root_out_dir/resources/chromeos/", + ] + + data_deps += [ + "//chrome", + "//ash/keyboard/ui:resources", + "//ui/file_manager:unit_test_data", + ] + + if (use_dbus) { + deps += [ "//dbus:test_support" ] + } + + deps += [ + "//ash:test_support", + "//ash/keyboard/ui:test_support", + "//ash/public/interfaces:test_interfaces", + "//chrome/browser/chromeos:arc_test_support", + "//chrome/browser/chromeos:test_support", + "//chrome/browser/media/router:test_support", + "//chrome/browser/resources/chromeos/chromevox:browser_tests", + "//chrome/browser/resources/chromeos/login:browser_tests", + "//chrome/browser/resources/chromeos/select_to_speak:browser_tests", + "//chrome/browser/resources/chromeos/switch_access:browser_tests", + "//chrome/services/file_util/public/cpp:browser_tests", + "//chromeos:test_support", + "//chromeos/components/drivefs:test_support", + "//chromeos/dbus:test_support", + "//chromeos/dbus/session_manager", + "//components/arc:arc_test_support", + "//components/exo:test_support", + "//components/prefs", + "//components/user_manager:test_support", + "//content/public/common:feature_h264_with_openh264_ffmpeg", + "//mojo/core/embedder", + "//services/audio/public/cpp:test_support", + "//services/identity/public/cpp", + "//services/network/public/mojom", + "//services/preferences/public/cpp", + "//services/preferences/public/mojom", + "//services/service_manager/public/cpp", + "//services/ws/public/cpp/input_devices:test_support", + "//url", + ] + } if (include_js_tests) { deps += [ @@ -1217,51 +1271,6 @@ deps += [ ":sync_integration_test_support" ] } - # Runtime dependencies - data_deps += [ - "//ppapi:ppapi_tests", - "//ppapi:power_saver_test_plugin", - "//remoting/webapp:browser_test_resources", - "//remoting/webapp:unit_tests", - "//third_party/mesa_headers", - "//third_party/widevine/cdm:widevine_test_license_server", - ] - - data += [ - "data/", - "//chrome/browser/policy/test/asn1der.py", - "//chrome/browser/policy/test/policy_testserver.py", - "//chrome/common/extensions/docs/examples/apps/calculator/", - "//chrome/third_party/mock4js/", - "//components/test/data/arc/", - "//components/test/data/autofill/", - "//components/test/data/payments/", - "//components/test/data/update_client/", - "//content/test/data/", - "//google_apis/test/", - "//media/test/data/", - "//net/tools/testserver/", - "//ppapi/tests/test_case.html", - "//ppapi/tests/test_case.html.mock-http-headers", - "//ppapi/tests/test_page.css", - "//ppapi/tests/test_page.css.mock-http-headers", - "//testing/test_env.py", - "//third_party/accessibility-audit/axs_testing.js", - "//third_party/chaijs/chai.js", - "//third_party/mocha/mocha.js", - "//third_party/polymer/v1_0/components-chromium/iron-test-helpers/mock-interactions.js", - "//third_party/pywebsocket/src/mod_pywebsocket/", - "//third_party/simplejson/", - "//third_party/tlslite/", - "//ui/webui/resources/", - "$root_out_dir/browser_tests.pak", - "$root_out_dir/test_case.html", - "$root_out_dir/test_case.html.mock-http-headers", - "$root_out_dir/test_page.css", - "$root_out_dir/test_page.css.mock-http-headers", - "$root_out_dir/test_url_loader_data/", - ] - if (!is_mac) { data += [ "$root_out_dir/locales/", @@ -1270,10 +1279,12 @@ "$root_out_dir/resources.pak", ] } + if (enable_captive_portal_detection) { sources += [ "../browser/ssl/captive_portal_blocking_page_browsertest.cc" ] } + if (enable_dice_support) { sources += [ "../browser/signin/dice_browsertest.cc", @@ -1313,7 +1324,14 @@ "//third_party/liblouis/wasm/liblouis_wrapper_browsertest.cc", ] deps += [ "//chrome/browser/chromeos" ] - data_deps += [ "//third_party/liblouis:liblouis_test_data" ] + data_deps += [ + "//third_party/liblouis:liblouis_test_data", + "//components/nacl/loader:nacl_helper", + "//ppapi/native_client:irt", + ] + if (enable_nacl_nonsfi) { + data_deps += [ "//components/nacl/loader:helper_nonsfi" ] + } } else if (is_linux || is_win) { sources += [ "../browser/ui/views/ime/ime_warning_bubble_browsertest.cc", @@ -2665,7 +2683,6 @@ "../browser/component_updater/chrome_component_updater_configurator_unittest.cc", "../browser/component_updater/optimization_hints_component_installer_unittest.cc", "../browser/component_updater/origin_trials_component_installer_unittest.cc", - "../browser/component_updater/sth_set_component_installer_unittest.cc", "../browser/component_updater/subresource_filter_component_installer_unittest.cc", "../browser/component_updater/supervised_user_whitelist_installer_unittest.cc", "../browser/component_updater/sw_reporter_installer_win_unittest.cc", @@ -4923,7 +4940,6 @@ "//extensions/buildflags", "//skia", "//testing/gtest", - "//third_party/blink/public:blink_headers", ] if (enable_plugins) {
diff --git a/chrome/test/base/perf/performance_test.cc b/chrome/test/base/perf/performance_test.cc index 8b7a76d..bacb39d 100644 --- a/chrome/test/base/perf/performance_test.cc +++ b/chrome/test/base/perf/performance_test.cc
@@ -16,13 +16,12 @@ #include "ui/gl/gl_switches.h" #if defined(OS_CHROMEOS) -#include "ash/public/cpp/wallpaper_controller_observer.h" #include "ash/public/cpp/wallpaper_types.h" #include "chrome/browser/ui/ash/wallpaper_controller_client.h" #include "components/user_manager/user_names.h" +#include "mojo/public/cpp/bindings/associated_binding.h" #include "ui/display/display.h" #include "ui/display/screen.h" -#include "ui/gfx/image/image_skia.h" #endif // OS_CHROMEOS static const char kTraceDir[] = "trace-dir"; @@ -31,23 +30,31 @@ #if defined(OS_CHROMEOS) // Watches if the wallpaper has been changed and runs a passed callback if so. -class TestWallpaperObserver : public ash::WallpaperControllerObserver { +class TestWallpaperObserver : public ash::mojom::WallpaperObserver { public: explicit TestWallpaperObserver(base::OnceClosure closure) - : closure_(std::move(closure)) { - WallpaperControllerClient::Get()->AddObserver(this); + : closure_(std::move(closure)), observer_binding_(this) { + ash::mojom::WallpaperObserverAssociatedPtrInfo ptr_info; + observer_binding_.Bind(mojo::MakeRequest(&ptr_info)); + WallpaperControllerClient::Get()->AddObserver(std::move(ptr_info)); } - ~TestWallpaperObserver() override { - WallpaperControllerClient::Get()->RemoveObserver(this); - } + ~TestWallpaperObserver() override = default; - // ash::WallpaperControllerObserver: - void OnWallpaperChanged() override { std::move(closure_).Run(); } + // ash::mojom::WallpaperObserver: + void OnWallpaperChanged(uint32_t image_id) override { + std::move(closure_).Run(); + } + void OnWallpaperColorsChanged( + const std::vector<uint32_t>& prominent_colors) override {} + void OnWallpaperBlurChanged(bool blurred) override {} private: base::OnceClosure closure_; + // The binding this instance uses to implement ash::mojom::WallpaperObserver. + mojo::AssociatedBinding<ash::mojom::WallpaperObserver> observer_binding_; + DISALLOW_COPY_AND_ASSIGN(TestWallpaperObserver); };
diff --git a/chrome/test/data/banners/manifest_prefer_related_apps_empty.json b/chrome/test/data/banners/manifest_prefer_related_apps_empty.json new file mode 100644 index 0000000..1ecc469 --- /dev/null +++ b/chrome/test/data/banners/manifest_prefer_related_apps_empty.json
@@ -0,0 +1,14 @@ +{ + "name": "Manifest prefer related apps empty", + "icons": [ + { + "src": "/banners/image-512px.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "scope": ".", + "start_url": ".", + "display": "standalone", + "prefer_related_applications": true +}
diff --git a/chrome/test/data/extensions/api_test/runtime/open_options_page/manifest.json b/chrome/test/data/extensions/api_test/runtime/open_options_page/manifest.json index 81f6f54..eaa1628 100644 --- a/chrome/test/data/extensions/api_test/runtime/open_options_page/manifest.json +++ b/chrome/test/data/extensions/api_test/runtime/open_options_page/manifest.json
@@ -4,7 +4,8 @@ "manifest_version": 2, "description": "Browser test for chrome.runtime.openOptionsPage, success case.", "background": { - "scripts": ["test.js"] + "scripts": ["test.js"], + "persistent": false }, "options_ui": { "page": "options.html"
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json index ddd9525..06a96eb 100644 --- a/chrome/test/data/policy/policy_test_cases.json +++ b/chrome/test/data/policy/policy_test_cases.json
@@ -4831,7 +4831,7 @@ }, "BrowserSwitcherExternalGreylistUrl": { - "os": ["win", "linux", "mac"], + "os": [], "test_policy": { "BrowserSwitcherExternalGreylistUrl": "file:///C:/src/greylist.xml" },
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn index 90b35b7..b758293 100644 --- a/chrome/test/data/webui/BUILD.gn +++ b/chrome/test/data/webui/BUILD.gn
@@ -108,6 +108,7 @@ "settings/a11y/multidevice_a11y_test.js", "settings/a11y/multidevice_features_a11y_test.js", "settings/a11y/tts_subpage_a11y_test.js", + "settings/chromeos/os_settings_browsertest.js", "sys_internals/sys_internals_browsertest.js", ] } else {
diff --git a/chrome/test/data/webui/extensions/activity_log_test.js b/chrome/test/data/webui/extensions/activity_log_test.js index 21b41cf..b7a0e34f 100644 --- a/chrome/test/data/webui/extensions/activity_log_test.js +++ b/chrome/test/data/webui/extensions/activity_log_test.js
@@ -19,7 +19,8 @@ /** * Backing extension info for the activity log. - * @type {chrome.developerPrivate.ExtensionInfo} + * @type {chrome.developerPrivate.ExtensionInfo| + * extensions.ActivityLogExtensionPlaceholder} */ let extensionInfo; @@ -84,6 +85,22 @@ currentPage, {page: Page.DETAILS, extensionId: EXTENSION_ID}); }); + test( + 'clicking on back button for a placeholder page navigates to list view', + function() { + activityLog.extensionInfo = {id: EXTENSION_ID, isPlaceholder: true}; + + Polymer.dom.flush(); + + let currentPage = null; + extensions.navigation.addListener(newPage => { + currentPage = newPage; + }); + + activityLog.$$('#closeButton').click(); + expectDeepEquals(currentPage, {page: Page.LIST}); + }); + test('tab transitions', async () => { Polymer.dom.flush(); // Default view should be the history view.
diff --git a/chrome/test/data/webui/extensions/manager_test.js b/chrome/test/data/webui/extensions/manager_test.js index 3e09001..94f38ae56f 100644 --- a/chrome/test/data/webui/extensions/manager_test.js +++ b/chrome/test/data/webui/extensions/manager_test.js
@@ -171,8 +171,9 @@ extensions.navigation.navigateTo( {page: Page.ACTIVITY_LOG, extensionId: 'z'.repeat(32)}); Polymer.dom.flush(); - // Should be re-routed to the main page. - assertViewActive('extensions-item-list'); + // Should also be on activity log page. See |changePage_| in manager.js + // for the use case. + assertViewActive('extensions-activity-log'); }); });
diff --git a/chrome/test/data/webui/print_preview/pages_settings_test.js b/chrome/test/data/webui/print_preview/pages_settings_test.js index 8d3770e..5669cbc 100644 --- a/chrome/test/data/webui/print_preview/pages_settings_test.js +++ b/chrome/test/data/webui/print_preview/pages_settings_test.js
@@ -293,6 +293,17 @@ // Input has been cleared. assertEquals('', input.value); validateState([1, 2, 3], [], '', false); + whenBlurred = test_util.eventToPromise('blur', input); + input.blur(); + + await whenBlurred; + assertEquals('1-3', input.value); + + // Change the page count. Since the range was set automatically, this + // should reset it to the new set of all pages. + pagesSection.pageCount = 2; + validateState([1, 2], [], '', false); + assertEquals('1-2', input.value); }); // Verifies that the input is never disabled when the validity of the
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js new file mode 100644 index 0000000..8b0619a --- /dev/null +++ b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
@@ -0,0 +1,70 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** @fileoverview Tests for Chrome OS settings page. */ + +/** @const {string} Path general Chrome browser settings. */ +const BROWSER_SETTINGS_PATH = '../'; + +// Polymer BrowserTest fixture. +GEN_INCLUDE(['//chrome/test/data/webui/polymer_browser_test_base.js']); + +GEN('#include "ash/public/cpp/ash_features.h"'); +GEN('#include "chrome/common/chrome_features.h"'); +GEN('#include "chromeos/constants/chromeos_features.h"'); +/** + * Generic text fixture for CrOS Polymer Settings elements to be overridden by + * individual element tests. + * @constructor + * @extends {PolymerTest} + */ +const OSSettingsBrowserTest = class extends PolymerTest { + /** @override */ + get browsePreload() { + return 'chrome://settings/chromeos/'; + } + + /** @override */ + get featureList() { + return {enabled: ['chromeos::features::kSplitSettings']}; + } + + /** @override */ + get extraLibraries() { + return super.extraLibraries.concat([ + BROWSER_SETTINGS_PATH + 'ensure_lazy_loaded.js', + ]); + } + + /** @override */ + setUp() { + super.setUp(); + settings.ensureLazyLoaded(); + } +}; + +/** + * Test fixture for the Smb Shares page. + * @constructor + * @extends {OSSettingsBrowserTest} + */ +OSSettingsSmbPageTest = class extends OSSettingsBrowserTest { + /** @override */ + get browsePreload() { + return super.browsePreload + 'os_downloads_page/smb_shares_page.html'; + } + + /** @override */ + get extraLibraries() { + return super.extraLibraries.concat([ + BROWSER_SETTINGS_PATH + 'test_util.js', + BROWSER_SETTINGS_PATH + '../test_browser_proxy.js', + 'smb_shares_page_tests.js', + ]); + } +}; + +TEST_F('OSSettingsSmbPageTest', 'All', function() { + mocha.run(); +});
diff --git a/chrome/test/data/webui/settings/smb_shares_page_tests.js b/chrome/test/data/webui/settings/chromeos/smb_shares_page_tests.js similarity index 99% rename from chrome/test/data/webui/settings/smb_shares_page_tests.js rename to chrome/test/data/webui/settings/chromeos/smb_shares_page_tests.js index 0a9e3b86..5fdc0bf2 100644 --- a/chrome/test/data/webui/settings/smb_shares_page_tests.js +++ b/chrome/test/data/webui/settings/chromeos/smb_shares_page_tests.js
@@ -192,5 +192,4 @@ expectEquals(expectedSmbUrl, addDialog.mountUrl_); expectEquals(expectedSmbUrl, addDialog.mountUrl_); }); - });
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js index 1e5f191..9718a9f 100644 --- a/chrome/test/data/webui/settings/cr_settings_browsertest.js +++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -2139,7 +2139,7 @@ extraLibraries: CrSettingsBrowserTest.prototype.extraLibraries.concat([ 'test_util.js', '../test_browser_proxy.js', - 'smb_shares_page_tests.js', + 'chromeos/smb_shares_page_tests.js', ]), };
diff --git a/chrome/updater/BUILD.gn b/chrome/updater/BUILD.gn index 186a2dbd..1d13162 100644 --- a/chrome/updater/BUILD.gn +++ b/chrome/updater/BUILD.gn
@@ -31,6 +31,8 @@ "crash_client.h", "crash_reporter.cc", "crash_reporter.h", + "installer.cc", + "installer.h", "patcher.cc", "patcher.h", "prefs.cc",
diff --git a/chrome/updater/DEPS b/chrome/updater/DEPS index 843c0ac..5aa062e 100644 --- a/chrome/updater/DEPS +++ b/chrome/updater/DEPS
@@ -1,11 +1,12 @@ include_rules = [ "+components/crash/core/common", + "+components/crx_file", "+components/prefs", "+components/services/patch", "+components/services/unzip", "+components/update_client", "+components/version_info", "+courgette", - "+third_party/zlib/google", "+third_party/crashpad", + "+third_party/zlib/google", ]
diff --git a/chrome/updater/installer.cc b/chrome/updater/installer.cc new file mode 100644 index 0000000..8b2807a --- /dev/null +++ b/chrome/updater/installer.cc
@@ -0,0 +1,185 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/updater/installer.h" + +#include <utility> + +#include "base/callback.h" +#include "base/files/file_enumerator.h" +#include "base/files/file_util.h" +#include "base/logging.h" +#include "chrome/updater/updater_constants.h" +#include "chrome/updater/util.h" +#include "components/crx_file/crx_verifier.h" +#include "components/update_client/update_client_errors.h" +#include "components/update_client/utils.h" + +namespace updater { + +namespace { + +// Version "0" corresponds to no installed version. +const char kNullVersion[] = "0.0.0.0"; + +} // namespace + +Installer::InstallInfo::InstallInfo() : version(kNullVersion) {} +Installer::InstallInfo::~InstallInfo() = default; + +Installer::Installer(const std::vector<uint8_t>& pk_hash) + : pk_hash_(pk_hash), + crx_id_(update_client::GetCrxIdFromPublicKeyHash(pk_hash)), + install_info_(std::make_unique<InstallInfo>()) {} + +Installer::~Installer() = default; + +update_client::CrxComponent Installer::MakeCrxComponent() { + update_client::CrxComponent component; + component.installer = scoped_refptr<Installer>(this); + component.requires_network_encryption = false; + component.crx_format_requirement = + crx_file::VerifierFormat::CRX3_WITH_PUBLISHER_PROOF; + component.pk_hash = pk_hash_; + component.name = crx_id_; + component.version = install_info_->version; + component.fingerprint = install_info_->fingerprint; + return component; +} + +void Installer::FindInstallOfApp() { + VLOG(1) << __func__ << " for " << crx_id_; + + base::FilePath root_install_path; + if (!GetProductDataDirectory(&root_install_path)) { + install_info_ = std::make_unique<InstallInfo>(); + return; + } + root_install_path = root_install_path.AppendASCII(crx_id_); + if (!base::PathExists(root_install_path)) { + install_info_ = std::make_unique<InstallInfo>(); + return; + } + + base::Version latest_version(kNullVersion); + base::FilePath latest_path; + std::vector<base::FilePath> older_paths; + base::FileEnumerator file_enumerator(root_install_path, false, + base::FileEnumerator::DIRECTORIES); + for (auto path = file_enumerator.Next(); !path.value().empty(); + path = file_enumerator.Next()) { + const base::Version version(path.BaseName().MaybeAsASCII()); + + // Ignore folders that don't have valid version names. + if (!version.IsValid()) + continue; + + // The |version| not newer than the latest found version is marked for + // removal. |kNullVersion| is also removed. + if (version.CompareTo(latest_version) <= 0) { + older_paths.push_back(path); + continue; + } + + // New valid |version| folder found. + if (!latest_path.empty()) + older_paths.push_back(latest_path); + + latest_version = version; + latest_path = path; + } + + install_info_->version = latest_version; + install_info_->install_dir = latest_path; + install_info_->manifest = update_client::ReadManifest(latest_path); + base::ReadFileToString(latest_path.AppendASCII("manifest.fingerprint"), + &install_info_->fingerprint); + + for (const auto& older_path : older_paths) + base::DeleteFile(older_path, true); +} + +Installer::Result Installer::InstallHelper(const base::FilePath& unpack_path) { + auto local_manifest = update_client::ReadManifest(unpack_path); + if (!local_manifest) + return Result(update_client::InstallError::BAD_MANIFEST); + + std::string version_ascii; + local_manifest->GetStringASCII("version", &version_ascii); + const base::Version manifest_version(version_ascii); + + VLOG(1) << "Installed version=" << install_info_->version.GetString() + << ", installing version=" << manifest_version.GetString(); + + if (!manifest_version.IsValid()) + return Result(update_client::InstallError::INVALID_VERSION); + + if (install_info_->version.CompareTo(manifest_version) > 0) + return Result(update_client::InstallError::VERSION_NOT_UPGRADED); + + base::FilePath root_install_path; + if (!GetProductDataDirectory(&root_install_path)) + return Result(update_client::InstallError::NO_DIR_COMPONENT_USER); + + root_install_path = root_install_path.AppendASCII(crx_id_); + if (!base::CreateDirectory(root_install_path)) { + return Result( + static_cast<int>(update_client::InstallError::CUSTOM_ERROR_BASE) + + kCustomInstallErrorCreateAppInstallDirectory); + } + + const auto versioned_install_path = + root_install_path.AppendASCII(manifest_version.GetString()); + if (base::PathExists(versioned_install_path)) { + if (!base::DeleteFile(versioned_install_path, true)) + return Result(update_client::InstallError::CLEAN_INSTALL_DIR_FAILED); + } + + VLOG(1) << "Install_path=" << versioned_install_path.AsUTF8Unsafe(); + + if (!base::Move(unpack_path, versioned_install_path)) { + PLOG(ERROR) << "Move failed."; + base::DeleteFile(versioned_install_path, true); + return Result(update_client::InstallError::MOVE_FILES_ERROR); + } + + DCHECK(!base::PathExists(unpack_path)); + DCHECK(base::PathExists(versioned_install_path)); + + install_info_->manifest = std::move(local_manifest); + install_info_->version = manifest_version; + install_info_->install_dir = versioned_install_path; + base::ReadFileToString( + versioned_install_path.AppendASCII("manifest.fingerprint"), + &install_info_->fingerprint); + + return Result(update_client::InstallError::NONE); +} + +void Installer::OnUpdateError(int error) { + LOG(ERROR) << "updater error: " << error << " for " << crx_id_; +} + +void Installer::Install(const base::FilePath& unpack_path, + const std::string& public_key, + Callback callback) { + std::unique_ptr<base::DictionaryValue> manifest; + base::Version version; + base::FilePath install_path; + + const auto result = InstallHelper(unpack_path); + base::DeleteFile(unpack_path, true); + std::move(callback).Run(result); +} + +bool Installer::GetInstalledFile(const std::string& file, + base::FilePath* installed_file) { + return false; +} + +bool Installer::Uninstall() { + return false; +} + +} // namespace updater
diff --git a/chrome/updater/installer.h b/chrome/updater/installer.h new file mode 100644 index 0000000..ef97e84 --- /dev/null +++ b/chrome/updater/installer.h
@@ -0,0 +1,74 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_UPDATER_INSTALLER_H_ +#define CHROME_UPDATER_INSTALLER_H_ + +#include <stdint.h> + +#include <memory> +#include <string> +#include <vector> + +#include "base/callback_forward.h" +#include "base/files/file_path.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/values.h" +#include "base/version.h" +#include "components/update_client/update_client.h" + +namespace updater { + +class Installer final : public update_client::CrxInstaller { + public: + struct InstallInfo { + InstallInfo(); + ~InstallInfo(); + + base::FilePath install_dir; + base::Version version; + std::string fingerprint; + std::unique_ptr<base::DictionaryValue> manifest; + + private: + DISALLOW_COPY_AND_ASSIGN(InstallInfo); + }; + + explicit Installer(const std::vector<uint8_t>& pk_hash); + + const std::string crx_id() const { return crx_id_; } + + // Finds the highest version install of the app, and updates the install + // info for this installer instance. + void FindInstallOfApp(); + + // Returns a CrxComponent instance that describes the current install + // state of the app. + update_client::CrxComponent MakeCrxComponent(); + + private: + ~Installer() override; + + // Overrides from update_client::CrxInstaller. + void OnUpdateError(int error) override; + void Install(const base::FilePath& unpack_path, + const std::string& public_key, + Callback callback) override; + bool GetInstalledFile(const std::string& file, + base::FilePath* installed_file) override; + bool Uninstall() override; + + Result InstallHelper(const base::FilePath& unpack_path); + + const std::vector<uint8_t> pk_hash_; + const std::string crx_id_; + std::unique_ptr<InstallInfo> install_info_; + + DISALLOW_COPY_AND_ASSIGN(Installer); +}; + +} // namespace updater + +#endif // CHROME_UPDATER_INSTALLER_H_
diff --git a/chrome/updater/updater.cc b/chrome/updater/updater.cc index ef1a9d4..0aae5e93 100644 --- a/chrome/updater/updater.cc +++ b/chrome/updater/updater.cc
@@ -4,6 +4,8 @@ #include "chrome/updater/updater.h" +#include <stdint.h> + #include <iterator> #include <memory> #include <string> @@ -11,7 +13,7 @@ #include <vector> #include "base/at_exit.h" -#include "base/callback_forward.h" +#include "base/bind.h" #include "base/command_line.h" #include "base/files/file_path.h" #include "base/logging.h" @@ -30,6 +32,7 @@ #include "chrome/updater/configurator.h" #include "chrome/updater/crash_client.h" #include "chrome/updater/crash_reporter.h" +#include "chrome/updater/installer.h" #include "chrome/updater/updater_constants.h" #include "chrome/updater/updater_version.h" #include "chrome/updater/util.h" @@ -68,12 +71,16 @@ // Overrides for update_client::UpdateClient::Observer. void OnEvent(Events event, const std::string& id) override { - update_client::CrxUpdateItem item; - update_client_->GetCrxUpdateState(id, &item); + update_client_->GetCrxUpdateState(id, &crx_update_item_); + } + + const update_client::CrxUpdateItem& crx_update_item() const { + return crx_update_item_; } private: scoped_refptr<update_client::UpdateClient> update_client_; + update_client::CrxUpdateItem crx_update_item_; DISALLOW_COPY_AND_ASSIGN(Observer); }; @@ -100,11 +107,11 @@ "process_type"); crash_key_process_type.Set("updater"); - if (CrashClient::GetInstance()->InitializeCrashReporting()) { + if (CrashClient::GetInstance()->InitializeCrashReporting()) VLOG(1) << "Crash reporting initialized."; - } else { + else VLOG(1) << "Crash reporting is not available."; - } + StartCrashReporter(UPDATER_VERSION_STRING); ThreadPoolStart(); @@ -138,12 +145,16 @@ return *ptr; } + auto installer = base::MakeRefCounted<Installer>( + std::vector<uint8_t>(std::cbegin(mimo_hash), std::cend(mimo_hash))); + installer->FindInstallOfApp(); + const auto component = installer->MakeCrxComponent(); + base::MessageLoopForUI message_loop; base::RunLoop runloop; DCHECK(base::ThreadTaskRunnerHandle::IsSet()); auto config = base::MakeRefCounted<Configurator>(); - { base::ScopedDisallowBlocking no_blocking_allowed; @@ -152,20 +163,17 @@ Observer observer(update_client); update_client->AddObserver(&observer); - const std::vector<std::string> ids = {"mimojjlkmoijpicakmndhoigimigcmbb"}; + const std::vector<std::string> ids = {installer->crx_id()}; update_client->Update( ids, base::BindOnce( - [](const std::vector<std::string>& ids) + [](const update_client::CrxComponent& component, + const std::vector<std::string>& ids) -> std::vector<base::Optional<update_client::CrxComponent>> { - update_client::CrxComponent component; - component.name = "mimo"; - component.pk_hash.assign(std::begin(mimo_hash), - std::end(mimo_hash)); - component.version = base::Version("0.0"); - component.requires_network_encryption = false; + DCHECK_EQ(1u, ids.size()); return {component}; - }), + }, + component), true, base::BindOnce( [](base::OnceClosure closure, update_client::Error error) { @@ -176,6 +184,21 @@ runloop.Run(); + const auto& update_item = observer.crx_update_item(); + switch (update_item.state) { + case update_client::ComponentState::kUpdated: + VLOG(1) << "Update success."; + break; + case update_client::ComponentState::kUpToDate: + VLOG(1) << "No updates."; + break; + case update_client::ComponentState::kUpdateError: + VLOG(1) << "Updater error: " << update_item.error_code << "."; + break; + default: + NOTREACHED(); + break; + } update_client->RemoveObserver(&observer); update_client = nullptr; }
diff --git a/chrome/updater/updater_constants.h b/chrome/updater/updater_constants.h index 4b3704b..235cddd 100644 --- a/chrome/updater/updater_constants.h +++ b/chrome/updater/updater_constants.h
@@ -31,6 +31,11 @@ extern const char kCrashUploadURL[]; extern const char kCrashStagingUploadURL[]; +// Errors. +// +// The install directory for the application could not be created. +const int kCustomInstallErrorCreateAppInstallDirectory = 0; + } // namespace updater #endif // CHROME_UPDATER_UPDATER_CONSTANTS_H_
diff --git a/chromecast/media/DEPS b/chromecast/media/DEPS index 6eced6d..ffba57ad 100644 --- a/chromecast/media/DEPS +++ b/chromecast/media/DEPS
@@ -5,6 +5,8 @@ "+content/public/test/test_browser_thread.h", "+content/public/test/test_browser_thread_bundle.h", "+content/public/test/test_utils.h", + "+content/renderer/media/audio/audio_device_factory.h", + "+content/renderer/media/audio/audio_output_ipc_factory.h", "+media/audio", "+media/base", "+media/cdm",
diff --git a/chromecast/media/audio/BUILD.gn b/chromecast/media/audio/BUILD.gn index 2e000eb..3b68287f 100644 --- a/chromecast/media/audio/BUILD.gn +++ b/chromecast/media/audio/BUILD.gn
@@ -49,6 +49,21 @@ configs += [ "//media/audio:platform_config" ] } +if (is_android) { + cast_source_set("cast_audio_device_factory") { + sources = [ + "cast_audio_device_factory.cc", + "cast_audio_device_factory.h", + ] + + deps = [ + "//base", + "//content/renderer:renderer", + "//media", + ] + } +} + cast_shared_library("libcast_external_audio_pipeline_1.0") { sources = [ "external_audio_pipeline_dummy.cc",
diff --git a/chromecast/media/audio/cast_audio_device_factory.cc b/chromecast/media/audio/cast_audio_device_factory.cc new file mode 100644 index 0000000..33e8f21 --- /dev/null +++ b/chromecast/media/audio/cast_audio_device_factory.cc
@@ -0,0 +1,132 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromecast/media/audio/cast_audio_device_factory.h" + +#include <string> + +#include "content/renderer/media/audio/audio_output_ipc_factory.h" +#include "media/audio/audio_output_device.h" +#include "media/base/audio_capturer_source.h" +#include "media/base/audio_parameters.h" +#include "media/base/audio_renderer_sink.h" +#include "media/base/output_device_info.h" + +namespace chromecast { +namespace media { + +class NonSwitchableAudioRendererSink + : public ::media::SwitchableAudioRendererSink { + public: + explicit NonSwitchableAudioRendererSink( + scoped_refptr<::media::AudioOutputDevice> output_device) + : output_device_(std::move(output_device)) {} + + void Initialize(const ::media::AudioParameters& params, + RenderCallback* callback) override { + output_device_->Initialize(params, callback); + } + + void Start() override { output_device_->Start(); } + + void Stop() override { output_device_->Stop(); } + + void Pause() override { output_device_->Pause(); } + + void Play() override { output_device_->Play(); } + + bool SetVolume(double volume) override { + return output_device_->SetVolume(volume); + } + + ::media::OutputDeviceInfo GetOutputDeviceInfo() override { + return output_device_->GetOutputDeviceInfo(); + } + + void GetOutputDeviceInfoAsync(OutputDeviceInfoCB info_cb) override { + output_device_->GetOutputDeviceInfoAsync(std::move(info_cb)); + } + + bool IsOptimizedForHardwareParameters() override { + return output_device_->IsOptimizedForHardwareParameters(); + } + + bool CurrentThreadIsRenderingThread() override { + return output_device_->CurrentThreadIsRenderingThread(); + } + + void SwitchOutputDevice(const std::string& device_id, + ::media::OutputDeviceStatusCB callback) override { + LOG(ERROR) << __func__ << " is not suported."; + std::move(callback).Run(::media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL); + } + + void Flush() override { output_device_->Flush(); } + + protected: + ~NonSwitchableAudioRendererSink() override = default; + + private: + scoped_refptr<::media::AudioOutputDevice> output_device_; +}; + +scoped_refptr<::media::AudioOutputDevice> NewOutputDevice( + int render_frame_id, + const ::media::AudioSinkParameters& params, + base::TimeDelta auth_timeout) { + auto device = base::MakeRefCounted<::media::AudioOutputDevice>( + content::AudioOutputIPCFactory::get()->CreateAudioOutputIPC( + render_frame_id), + content::AudioOutputIPCFactory::get()->io_task_runner(), params, + auth_timeout); + device->RequestDeviceAuthorization(); + return device; +} + +CastAudioDeviceFactory::CastAudioDeviceFactory() + : content::AudioDeviceFactory() { + DVLOG(1) << "Register CastAudioDeviceFactory"; +} + +CastAudioDeviceFactory::~CastAudioDeviceFactory() { + DVLOG(1) << "Unregister CastAudioDeviceFactory"; +} + +scoped_refptr<::media::AudioRendererSink> +CastAudioDeviceFactory::CreateFinalAudioRendererSink( + int render_frame_id, + const ::media::AudioSinkParameters& params, + base::TimeDelta auth_timeout) { + // Use default implementation. + return nullptr; +} + +scoped_refptr<::media::AudioRendererSink> +CastAudioDeviceFactory::CreateAudioRendererSink( + content::AudioDeviceFactory::SourceType source_type, + int render_frame_id, + const ::media::AudioSinkParameters& params) { + // Use default implementation. + return nullptr; +} + +scoped_refptr<::media::SwitchableAudioRendererSink> +CastAudioDeviceFactory::CreateSwitchableAudioRendererSink( + content::AudioDeviceFactory::SourceType source_type, + int render_frame_id, + const ::media::AudioSinkParameters& params) { + return base::MakeRefCounted<NonSwitchableAudioRendererSink>(NewOutputDevice( + render_frame_id, params, base::TimeDelta::FromSeconds(100))); +} + +scoped_refptr<::media::AudioCapturerSource> +CastAudioDeviceFactory::CreateAudioCapturerSource( + int render_frame_id, + const ::media::AudioSourceParameters& params) { + // Use default implementation. + return nullptr; +} + +} // namespace media +} // namespace chromecast \ No newline at end of file
diff --git a/chromecast/media/audio/cast_audio_device_factory.h b/chromecast/media/audio/cast_audio_device_factory.h new file mode 100644 index 0000000..2be9cdb4 --- /dev/null +++ b/chromecast/media/audio/cast_audio_device_factory.h
@@ -0,0 +1,55 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMECAST_MEDIA_AUDIO_CAST_AUDIO_DEVICE_FACTORY_H_ +#define CHROMECAST_MEDIA_AUDIO_CAST_AUDIO_DEVICE_FACTORY_H_ + +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "content/renderer/media/audio/audio_device_factory.h" +#include "media/audio/audio_sink_parameters.h" + +namespace media { +class AudioCapturerSource; +class AudioRendererSink; +class SwitchableAudioRendererSink; +} // namespace media + +namespace chromecast { +namespace media { + +class CastAudioDeviceFactory : public content::AudioDeviceFactory { + public: + CastAudioDeviceFactory(); + ~CastAudioDeviceFactory() final; + + scoped_refptr<::media::AudioRendererSink> CreateFinalAudioRendererSink( + int render_frame_id, + const ::media::AudioSinkParameters& params, + base::TimeDelta auth_timeout) override; + + scoped_refptr<::media::AudioRendererSink> CreateAudioRendererSink( + content::AudioDeviceFactory::SourceType source_type, + int render_frame_id, + const ::media::AudioSinkParameters& params) override; + + scoped_refptr<::media::SwitchableAudioRendererSink> + CreateSwitchableAudioRendererSink( + content::AudioDeviceFactory::SourceType source_type, + int render_frame_id, + const ::media::AudioSinkParameters& params) override; + + scoped_refptr<::media::AudioCapturerSource> CreateAudioCapturerSource( + int render_frame_id, + const ::media::AudioSourceParameters& params) override; + + private: + DISALLOW_COPY_AND_ASSIGN(CastAudioDeviceFactory); +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_MEDIA_AUDIO_CAST_AUDIO_DEVICE_FACTORY_H_
diff --git a/chromecast/media/audio/cast_audio_manager.cc b/chromecast/media/audio/cast_audio_manager.cc index 6c9e272..25470c0 100644 --- a/chromecast/media/audio/cast_audio_manager.cc +++ b/chromecast/media/audio/cast_audio_manager.cc
@@ -298,5 +298,16 @@ return &mixer_service_connection_factory_; } +#if defined(OS_ANDROID) +::media::AudioOutputStream* CastAudioManager::MakeAudioOutputStreamProxy( + const ::media::AudioParameters& params, + const std::string& device_id) { + // Override to use MakeAudioOutputStream to prevent the audio output stream + // from closing during pause/stop. + return MakeAudioOutputStream(params, device_id, + /*log_callback, not used*/ base::DoNothing()); +} +#endif // defined(OS_ANDROID) + } // namespace media } // namespace chromecast
diff --git a/chromecast/media/audio/cast_audio_manager.h b/chromecast/media/audio/cast_audio_manager.h index fbecbdf..dcac0c3 100644 --- a/chromecast/media/audio/cast_audio_manager.h +++ b/chromecast/media/audio/cast_audio_manager.h
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" +#include "build/build_config.h" #include "chromecast/media/audio/mixer_service/mixer_service_connection_factory.h" #include "media/audio/audio_manager_base.h" #include "services/service_manager/public/cpp/connector.h" @@ -108,6 +109,12 @@ virtual ::media::AudioOutputStream* MakeMixerOutputStream( const ::media::AudioParameters& params); +#if defined(OS_ANDROID) + ::media::AudioOutputStream* MakeAudioOutputStreamProxy( + const ::media::AudioParameters& params, + const std::string& device_id) override; +#endif + private: friend class CastAudioMixer; friend class CastAudioManagerTest;
diff --git a/chromecast/media/audio/cast_audio_output_stream.cc b/chromecast/media/audio/cast_audio_output_stream.cc index 91b9801..420b741 100644 --- a/chromecast/media/audio/cast_audio_output_stream.cc +++ b/chromecast/media/audio/cast_audio_output_stream.cc
@@ -55,6 +55,7 @@ constexpr base::TimeDelta kFadeTime = base::TimeDelta::FromMilliseconds(5); constexpr base::TimeDelta kMixerStartThreshold = base::TimeDelta::FromMilliseconds(60); +constexpr base::TimeDelta kRenderBufferSize = base::TimeDelta::FromSeconds(4); } // namespace namespace chromecast { @@ -105,10 +106,18 @@ chromecast::mojom::MultiroomInfoPtr multiroom_info); void Start(AudioSourceCallback* source_callback); void Stop(base::WaitableEvent* finished); + void Flush(base::WaitableEvent* finished); void Close(base::OnceClosure closure); void SetVolume(double volume); private: + enum class CmaBackendState { + kUinitialized, + kStopped, + kPaused, + kStarted, + }; + void PushBuffer(); // CmaBackend::Decoder::Delegate implementation: @@ -126,6 +135,7 @@ CmaBackendFactory* const cma_backend_factory_; AudioOutputState media_thread_state_; + CmaBackendState cma_backend_state_ = CmaBackendState::kUinitialized; ::media::AudioTimestampHelper timestamp_helper_; const base::TimeDelta buffer_duration_; std::unique_ptr<TaskRunnerImpl> cma_backend_task_runner_; @@ -134,7 +144,8 @@ base::OneShotTimer push_timer_; bool push_in_progress_; bool encountered_error_; - base::TimeTicks next_push_time_; + base::TimeTicks last_push_complete_time_; + base::TimeDelta render_buffer_size_estimate_ = kRenderBufferSize; CmaBackend::AudioDecoder* audio_decoder_; AudioSourceCallback* source_callback_; @@ -154,7 +165,8 @@ cma_backend_factory_(cma_backend_factory), media_thread_state_(kClosed), timestamp_helper_(audio_params_.sample_rate()), - buffer_duration_(audio_params_.GetBufferDuration()) { + buffer_duration_(audio_params_.GetBufferDuration()), + render_buffer_size_estimate_(kRenderBufferSize) { DETACH_FROM_THREAD(media_thread_checker_); DCHECK(audio_task_runner_); DCHECK(cma_backend_factory_); @@ -222,6 +234,7 @@ encountered_error_ = true; return; } + cma_backend_state_ = CmaBackendState::kStopped; audio_bus_ = ::media::AudioBus::Create(audio_params_); timestamp_helper_.SetBaseTimestamp(base::TimeDelta()); @@ -241,11 +254,19 @@ } if (media_thread_state_ == kOpened) { + DCHECK(cma_backend_state_ == CmaBackendState::kPaused || + cma_backend_state_ == CmaBackendState::kStopped); + if (cma_backend_state_ == CmaBackendState::kPaused) { + cma_backend_->Resume(); + } else { + cma_backend_->Start(0); + render_buffer_size_estimate_ = kRenderBufferSize; + } + last_push_complete_time_ = base::TimeTicks::Now(); + cma_backend_state_ = CmaBackendState::kStarted; media_thread_state_ = kStarted; - cma_backend_->Start(0); } - next_push_time_ = base::TimeTicks::Now(); if (!push_in_progress_) { push_in_progress_ = true; PushBuffer(); @@ -256,8 +277,30 @@ DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_); // Prevent further pushes to the audio buffer after stopping. push_timer_.Stop(); - if (cma_backend_ && media_thread_state_ == kStarted) { - cma_backend_->Stop(); + // Don't actually stop the backend. Stop() gets called when the stream is + // paused. We rely on Flush() to stop the backend. + if (cma_backend_) { + cma_backend_->Pause(); + cma_backend_state_ = CmaBackendState::kPaused; + } + push_in_progress_ = false; + media_thread_state_ = kOpened; + source_callback_ = nullptr; + finished->Signal(); +} + +void CastAudioOutputStream::CmaWrapper::Flush(base::WaitableEvent* finished) { + DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_); + // Prevent further pushes to the audio buffer after stopping. + push_timer_.Stop(); + + if (cma_backend_ && + (media_thread_state_ == kStarted || media_thread_state_ == kOpened)) { + if (cma_backend_state_ == CmaBackendState::kPaused || + cma_backend_state_ == CmaBackendState::kStarted) { + cma_backend_->Stop(); + cma_backend_state_ = CmaBackendState::kStopped; + } } push_in_progress_ = false; media_thread_state_ = kOpened; @@ -270,8 +313,9 @@ // Prevent further pushes to the audio buffer after stopping. push_timer_.Stop(); // Only stop the backend if it was started. - if (cma_backend_ && media_thread_state_ == kStarted) { + if (cma_backend_ && cma_backend_state_ != CmaBackendState::kStopped) { cma_backend_->Stop(); + cma_backend_state_ = CmaBackendState::kStopped; } push_in_progress_ = false; media_thread_state_ = kPendingClose; @@ -308,19 +352,21 @@ CmaBackend::AudioDecoder::RenderingDelay rendering_delay = audio_decoder_->GetRenderingDelay(); - base::TimeDelta delay = - base::TimeDelta::FromMicroseconds(rendering_delay.delay_microseconds); - base::TimeTicks delay_timestamp = - base::TimeTicks() + - base::TimeDelta::FromMicroseconds(rendering_delay.timestamp_microseconds); - // The delay must be greater than zero, and if the timestamp is invalid, we - // cannot trust the current delay. - if (rendering_delay.timestamp_microseconds == kInvalidTimestamp || - rendering_delay.delay_microseconds < 0) { + base::TimeDelta delay; + if (rendering_delay.delay_microseconds < 0) { delay = base::TimeDelta(); + } else { + delay = + base::TimeDelta::FromMicroseconds(rendering_delay.delay_microseconds); } + // This isn't actually used by audio_renderer_impl + base::TimeTicks delay_timestamp = base::TimeTicks(); + if (rendering_delay.timestamp_microseconds != kInvalidTimestamp) { + delay_timestamp += base::TimeDelta::FromMicroseconds( + rendering_delay.timestamp_microseconds); + } int frame_count = source_callback_->OnMoreData(delay, delay_timestamp, 0, audio_bus_.get()); DVLOG(3) << "frames_filled=" << frame_count << " with latency=" << delay; @@ -357,9 +403,20 @@ // Schedule next push buffer. const base::TimeTicks now = base::TimeTicks::Now(); - next_push_time_ = std::max(now, next_push_time_ + buffer_duration_); + render_buffer_size_estimate_ -= buffer_duration_; + render_buffer_size_estimate_ += now - last_push_complete_time_; + last_push_complete_time_ = now; - base::TimeDelta delay = next_push_time_ - now; + base::TimeDelta delay; + if (render_buffer_size_estimate_ >= buffer_duration_) { + delay = base::TimeDelta::FromSeconds(0); + } else { + delay = buffer_duration_; + } + + DVLOG(3) << "render_buffer_size_estimate_=" << render_buffer_size_estimate_ + << " delay=" << delay << " buffer_duration_=" << buffer_duration_; + push_timer_.Start(FROM_HERE, delay, this, &CmaWrapper::PushBuffer); push_in_progress_ = true; } @@ -386,6 +443,7 @@ void Stop(); void Close(base::OnceClosure closure); void SetVolume(double volume); + void Flush(); base::SingleThreadTaskRunner* io_task_runner() { return io_task_runner_.get(); @@ -484,6 +542,12 @@ source_callback_ = nullptr; } +void CastAudioOutputStream::MixerServiceWrapper::Flush() { + DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_); + // Nothing to do. + return; +} + void CastAudioOutputStream::MixerServiceWrapper::Close( base::OnceClosure closure) { DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_); @@ -692,7 +756,21 @@ void CastAudioOutputStream::Flush() { DCHECK_CALLED_ON_VALID_THREAD(audio_thread_checker_); DVLOG(2) << this << ": " << __func__; - // TODO(alexleung): Implement in follow-up CL. + + // |cma_wrapper_| and |mixer_service_wrapper_| cannot be both active. + DCHECK(!(cma_wrapper_ && mixer_service_wrapper_)); + + if (cma_wrapper_) { + // Make sure this is not on the same thread as CMA_WRAPPER to prevent + // deadlock. + DCHECK(!audio_manager_->media_task_runner()->BelongsToCurrentThread()); + + base::WaitableEvent finished; + POST_TO_CMA_WRAPPER(Flush, base::Unretained(&finished)); + finished.Wait(); + } else if (mixer_service_wrapper_) { + POST_TO_MIXER_SERVICE_WRAPPER(Flush); + } } void CastAudioOutputStream::SetVolume(double volume) {
diff --git a/chromecast/media/audio/cast_audio_output_stream.h b/chromecast/media/audio/cast_audio_output_stream.h index c471664..4051cedc 100644 --- a/chromecast/media/audio/cast_audio_output_stream.h +++ b/chromecast/media/audio/cast_audio_output_stream.h
@@ -12,6 +12,7 @@ #include "base/single_thread_task_runner.h" #include "base/threading/thread_checker.h" #include "base/timer/timer.h" +#include "build/build_config.h" #include "chromecast/base/task_runner_impl.h" #include "chromecast/common/mojom/multiroom.mojom.h" #include "chromecast/media/cma/backend/cma_backend.h"
diff --git a/chromecast/media/audio/cast_audio_output_stream_unittest.cc b/chromecast/media/audio/cast_audio_output_stream_unittest.cc index 3528131..31a9f05 100644 --- a/chromecast/media/audio/cast_audio_output_stream_unittest.cc +++ b/chromecast/media/audio/cast_audio_output_stream_unittest.cc
@@ -617,6 +617,10 @@ stream->Stop(); RunThreadsUntilIdle(); + EXPECT_EQ(FakeCmaBackend::kStatePaused, cma_backend_->state()); + + stream->Flush(); + RunThreadsUntilIdle(); EXPECT_EQ(FakeCmaBackend::kStateStopped, cma_backend_->state()); stream->Close();
diff --git a/chromecast/renderer/BUILD.gn b/chromecast/renderer/BUILD.gn index 1b6e8ba5..21ee1ccc 100644 --- a/chromecast/renderer/BUILD.gn +++ b/chromecast/renderer/BUILD.gn
@@ -84,6 +84,8 @@ "//chromecast/common/mojom", "//mojo/public/cpp/bindings", ] + } else { + deps += [ "//chromecast/media/audio:cast_audio_device_factory" ] } if (enable_chromecast_extensions) {
diff --git a/chromecast/renderer/cast_content_renderer_client.cc b/chromecast/renderer/cast_content_renderer_client.cc index ad26b8e1..23ee7f4 100644 --- a/chromecast/renderer/cast_content_renderer_client.cc +++ b/chromecast/renderer/cast_content_renderer_client.cc
@@ -7,6 +7,7 @@ #include <utility> #include "base/command_line.h" +#include "base/optional.h" #include "base/strings/string_number_conversions.h" #include "chromecast/base/bitstream_audio_codecs.h" #include "chromecast/base/chromecast_switches.h" @@ -35,6 +36,7 @@ #include "third_party/blink/public/web/web_view.h" #if defined(OS_ANDROID) +#include "chromecast/media/audio/cast_audio_device_factory.h" #include "media/base/android/media_codec_util.h" #else #include "chromecast/renderer/memory_pressure_observer_impl.h" @@ -59,6 +61,18 @@ namespace chromecast { namespace shell { +#if defined(OS_ANDROID) +// Audio renderer algorithm maximum capacity. +constexpr base::TimeDelta kAudioRendererMaxCapacity = + base::TimeDelta::FromSeconds(10); +// Audio renderer algorithm starting capacity. Configure large enough to +// prevent underrun. +constexpr base::TimeDelta kAudioRendererStartingCapacity = + base::TimeDelta::FromMilliseconds(5000); +constexpr base::TimeDelta kAudioRendererStartingCapacityEncrypted = + base::TimeDelta::FromMilliseconds(5500); +#endif // defined(OS_ANDROID) + CastContentRendererClient::CastContentRendererClient() : supported_profiles_(new media::SupportedCodecProfileLevelsMemo()), app_media_capabilities_observer_binding_(this), @@ -71,6 +85,10 @@ // instance, which caches the platform decoder supported state when it is // constructed. ::media::EnablePlatformDecoderSupport(); + + // Registers a custom content::AudioDeviceFactory + cast_audio_device_factory_ = + std::make_unique<media::CastAudioDeviceFactory>(); #endif // OS_ANDROID } @@ -310,7 +328,16 @@ base::Optional<::media::AudioRendererAlgorithmParameters> CastContentRendererClient::GetAudioRendererAlgorithmParameters( ::media::AudioParameters audio_parameters) { +#if defined(OS_ANDROID) + ::media::AudioRendererAlgorithmParameters parameters; + parameters.max_capacity = kAudioRendererMaxCapacity; + parameters.starting_capacity = kAudioRendererStartingCapacity; + parameters.starting_capacity_for_encrypted = + kAudioRendererStartingCapacityEncrypted; + return base::Optional<::media::AudioRendererAlgorithmParameters>(parameters); +#else return base::nullopt; +#endif } } // namespace shell
diff --git a/chromecast/renderer/cast_content_renderer_client.h b/chromecast/renderer/cast_content_renderer_client.h index b45c074..27e5f38 100644 --- a/chromecast/renderer/cast_content_renderer_client.h +++ b/chromecast/renderer/cast_content_renderer_client.h
@@ -32,6 +32,10 @@ namespace media { class MediaCapsObserverImpl; class SupportedCodecProfileLevelsMemo; + +#if defined(OS_ANDROID) +class CastAudioDeviceFactory; +#endif // defined(OS_ANDROID) } namespace shell { @@ -106,6 +110,10 @@ guest_view_container_dispatcher_; #endif +#if defined(OS_ANDROID) + std::unique_ptr<media::CastAudioDeviceFactory> cast_audio_device_factory_; +#endif + int supported_bitstream_audio_codecs_; DISALLOW_COPY_AND_ASSIGN(CastContentRendererClient);
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 520040f..fd4b667 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -12225.0.0 \ No newline at end of file +12233.0.0 \ No newline at end of file
diff --git a/chromeos/network/proxy/ui_proxy_config_service.cc b/chromeos/network/proxy/ui_proxy_config_service.cc index b154b87..c108736d 100644 --- a/chromeos/network/proxy/ui_proxy_config_service.cc +++ b/chromeos/network/proxy/ui_proxy_config_service.cc
@@ -283,13 +283,20 @@ NetworkHandler::Get()->network_state_handler()->DefaultNetwork(); if (!network) return false; + return ProxyModeForNetwork(network) == ProxyPrefs::MODE_FIXED_SERVERS; +} + +ProxyPrefs::ProxyMode UIProxyConfigService::ProxyModeForNetwork( + const NetworkState* network) { + // TODO(919691): Include proxies set by an extension and per-user proxies. onc::ONCSource onc_source = onc::ONC_SOURCE_NONE; std::unique_ptr<ProxyConfigDictionary> proxy_dict = proxy_config::GetProxyConfigForNetwork(nullptr, local_state_prefs_, *network, &onc_source); ProxyPrefs::ProxyMode mode; - return (proxy_dict && proxy_dict->GetMode(&mode) && - mode == ProxyPrefs::MODE_FIXED_SERVERS); + if (!proxy_dict || !proxy_dict->GetMode(&mode)) + return ProxyPrefs::MODE_DIRECT; + return mode; } void UIProxyConfigService::OnPreferenceChanged(const std::string& pref_name) {
diff --git a/chromeos/network/proxy/ui_proxy_config_service.h b/chromeos/network/proxy/ui_proxy_config_service.h index 830d6e43..f5bb6dbd 100644 --- a/chromeos/network/proxy/ui_proxy_config_service.h +++ b/chromeos/network/proxy/ui_proxy_config_service.h
@@ -10,6 +10,7 @@ #include "base/component_export.h" #include "base/macros.h" #include "components/prefs/pref_change_registrar.h" +#include "components/proxy_config/proxy_prefs.h" class PrefService; @@ -19,6 +20,8 @@ namespace chromeos { +class NetworkState; + // This class provides an interface to the UI for getting a network proxy // configuration. // NOTE: This class must be rebuilt with the primary user's profile prefs when @@ -57,6 +60,9 @@ // with mode == MODE_FIXED_SERVERS. bool HasDefaultNetworkProxyConfigured(); + // Returns the ProxyMode for |network| using |local_state_prefs_| + ProxyPrefs::ProxyMode ProxyModeForNetwork(const NetworkState* network); + private: void OnPreferenceChanged(const std::string& pref_name);
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.cc b/chromeos/services/assistant/assistant_manager_service_impl.cc index ac21d8d..00fb5fe4 100644 --- a/chromeos/services/assistant/assistant_manager_service_impl.cc +++ b/chromeos/services/assistant/assistant_manager_service_impl.cc
@@ -148,6 +148,7 @@ service_(service), background_thread_("background thread"), media_controller_observer_binding_(this), + app_list_subscriber_binding_(this), weak_factory_(this) { background_thread_.Start(); platform_api_ = std::make_unique<PlatformApiImpl>( @@ -1030,6 +1031,13 @@ service_->assistant_state()->hotword_enabled().value()) { assistant_settings_manager_->SyncSpeakerIdEnrollmentStatus(); } + + if (base::FeatureList::IsEnabled(assistant::features::kAssistantAppSupport)) { + mojom::AppListEventSubscriberPtr subscriber_ptr; + app_list_subscriber_binding_.Bind(mojo::MakeRequest(&subscriber_ptr)); + service_->device_actions()->AddAppListEventSubscriber( + std::move(subscriber_ptr)); + } } void AssistantManagerServiceImpl::HandleLaunchMediaIntentResponse( @@ -1118,6 +1126,17 @@ service_->assistant_alarm_timer_controller()->OnTimerSoundingFinished(); } +void AssistantManagerServiceImpl::OnAndroidAppListRefreshed( + std::vector<mojom::AndroidAppInfoPtr> apps_info) { + std::vector<action::AndroidAppInfo> android_apps_info; + for (const auto& app_info : apps_info) { + android_apps_info.push_back({app_info->package_name, app_info->version, + app_info->localized_app_name, + app_info->intent}); + } + display_connection_->OnAndroidAppListRefreshed(android_apps_info); +} + void AssistantManagerServiceImpl::UpdateInternalOptions( assistant_client::AssistantManagerInternal* assistant_manager_internal) { // Build user agent string.
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.h b/chromeos/services/assistant/assistant_manager_service_impl.h index 0cf7e09..d774237 100644 --- a/chromeos/services/assistant/assistant_manager_service_impl.h +++ b/chromeos/services/assistant/assistant_manager_service_impl.h
@@ -90,7 +90,8 @@ public assistant_client::AssistantManagerDelegate, public assistant_client::DeviceStateListener, public assistant_client::MediaManager::Listener, - public media_session::mojom::MediaControllerObserver { + public media_session::mojom::MediaControllerObserver, + public mojom::AppListEventSubscriber { public: // |service| owns this class and must outlive this class. AssistantManagerServiceImpl( @@ -184,6 +185,10 @@ void OnTimerSoundingStarted() override; void OnTimerSoundingFinished() override; + // mojom::AppListEventSubscriber overrides: + void OnAndroidAppListRefreshed( + std::vector<mojom::AndroidAppInfoPtr> apps_info) override; + void UpdateInternalOptions( assistant_client::AssistantManagerInternal* assistant_manager_internal); @@ -337,6 +342,8 @@ bool start_finished_ = false; + mojo::Binding<mojom::AppListEventSubscriber> app_list_subscriber_binding_; + base::WeakPtrFactory<AssistantManagerServiceImpl> weak_factory_; DISALLOW_COPY_AND_ASSIGN(AssistantManagerServiceImpl);
diff --git a/chromeos/services/assistant/public/mojom/assistant.mojom b/chromeos/services/assistant/public/mojom/assistant.mojom index 5259a6b..d63927d 100644 --- a/chromeos/services/assistant/public/mojom/assistant.mojom +++ b/chromeos/services/assistant/public/mojom/assistant.mojom
@@ -187,6 +187,15 @@ // Launch Android intent. The intent is encoded as a URI string. // See Intent.toUri(). LaunchAndroidIntent(string intent); + + // Register App list event subscriber. + AddAppListEventSubscriber(AppListEventSubscriber subscriber); +}; + +// Subscribes to App list events. +interface AppListEventSubscriber { + // Called when the android app list changed. + OnAndroidAppListRefreshed(array<AndroidAppInfo> apps_info); }; // Enumeration of possible completions for an Assistant interaction.
diff --git a/chromeos/services/assistant/service_unittest.cc b/chromeos/services/assistant/service_unittest.cc index 0014cd7..abdf27a 100644 --- a/chromeos/services/assistant/service_unittest.cc +++ b/chromeos/services/assistant/service_unittest.cc
@@ -143,6 +143,9 @@ std::vector<chromeos::assistant::mojom::AndroidAppInfoPtr> apps_info, VerifyAndroidAppCallback callback) override {} void LaunchAndroidIntent(const std::string& intent) override {} + void AddAppListEventSubscriber( + chromeos::assistant::mojom::AppListEventSubscriberPtr subscriber) + override {} mojo::Binding<mojom::DeviceActions> binding_;
diff --git a/chromeos/services/network_config/BUILD.gn b/chromeos/services/network_config/BUILD.gn index b7e14024..0df128d 100644 --- a/chromeos/services/network_config/BUILD.gn +++ b/chromeos/services/network_config/BUILD.gn
@@ -19,6 +19,7 @@ "//chromeos/services/network_config/public/mojom", "//components/device_event_log", "//components/onc", + "//components/proxy_config", "//services/service_manager/public/cpp", ] }
diff --git a/chromeos/services/network_config/DEPS b/chromeos/services/network_config/DEPS index 273d26b..dfcefe2 100644 --- a/chromeos/services/network_config/DEPS +++ b/chromeos/services/network_config/DEPS
@@ -1,3 +1,4 @@ include_rules = [ "+components/onc", + "+components/proxy_config", ]
diff --git a/chromeos/services/network_config/cros_network_config.cc b/chromeos/services/network_config/cros_network_config.cc index e18a9a84..59ce8e7 100644 --- a/chromeos/services/network_config/cros_network_config.cc +++ b/chromeos/services/network_config/cros_network_config.cc
@@ -5,10 +5,12 @@ #include "chromeos/services/network_config/cros_network_config.h" #include "chromeos/network/device_state.h" +#include "chromeos/network/network_handler.h" #include "chromeos/network/network_state.h" #include "chromeos/network/network_state_handler.h" #include "chromeos/network/network_type_pattern.h" #include "chromeos/network/onc/onc_translation_tables.h" +#include "chromeos/network/proxy/ui_proxy_config_service.h" #include "chromeos/services/network_config/public/cpp/cros_network_config_util.h" #include "chromeos/services/network_config/public/mojom/cros_network_config_mojom_traits.h" #include "components/device_event_log/device_event_log.h" @@ -143,6 +145,17 @@ result->prohibited_by_policy = network->blocked_by_policy(); result->source = mojom::ONCSource(network->onc_source()); + // NetworkHandler and UIProxyConfigService may not exist in tests. + UIProxyConfigService* ui_proxy_config_service = + NetworkHandler::IsInitialized() + ? NetworkHandler::Get()->ui_proxy_config_service() + : nullptr; + result->proxy_mode = + ui_proxy_config_service + ? mojom::ProxyMode( + ui_proxy_config_service->ProxyModeForNetwork(network)) + : mojom::ProxyMode::kDirect; + const NetworkState::CaptivePortalProviderInfo* captive_portal_provider = network->captive_portal_provider(); if (captive_portal_provider) {
diff --git a/chromeos/services/network_config/cros_network_config_unittest.cc b/chromeos/services/network_config/cros_network_config_unittest.cc index 63ba877..9861b61 100644 --- a/chromeos/services/network_config/cros_network_config_unittest.cc +++ b/chromeos/services/network_config/cros_network_config_unittest.cc
@@ -153,6 +153,7 @@ ASSERT_TRUE(result->vpn); EXPECT_EQ(mojom::VPNType::kL2TPIPsec, result->vpn->type); })); + // TODO(919691): Test ProxyMode once UIProxyConfigService logic is improved. } TEST_F(CrosNetworkConfigTest, GetNetworkStateList) {
diff --git a/chromeos/services/network_config/public/mojom/cros_network_config.mojom b/chromeos/services/network_config/public/mojom/cros_network_config.mojom index 753c864..5691f92 100644 --- a/chromeos/services/network_config/public/mojom/cros_network_config.mojom +++ b/chromeos/services/network_config/public/mojom/cros_network_config.mojom
@@ -46,15 +46,6 @@ kUnavailable, }; -// The ONC source for policy or imported networks. -enum ONCSource { - kUnknown, - kNone, - kUserImport, - kDevicePolicy, - kUserPolicy, -}; - // The network technology type. NOTE: 'All' and 'Wireless' are only used by // FilterType for requesting groups of networks. enum NetworkType { @@ -71,6 +62,28 @@ kWiMAX, }; +// The ONC source for policy or imported networks. +enum ONCSource { + kUnknown, + kNone, + kUserImport, + kDevicePolicy, + kUserPolicy, +}; + +enum ProxyMode { + // Direct connection to the network. + kDirect, + // Try to retrieve a PAC script from http://wpad/wpad.dat. + kAutoDetect, + // Try to retrieve a PAC script from kProxyPacURL. + kPacScript, + // Use a specified list of servers. + kFixedServers, + // Use the system's proxy settings. + kSystem, +}; + // The security type for WiFi Ethernet networks. enum SecurityType { kNone, @@ -189,6 +202,9 @@ string name; // The relative priority of the network. Larger values have higher priority. int32 priority; + // The proxy mode affecting this network. Includes any settings that affect + // this network (i.e. global proxy settings are also considered). + ProxyMode proxy_mode; // True for visible networks that are blocked / disallowed by policy. bool prohibited_by_policy = false; ONCSource source;
diff --git a/chromeos/services/network_config/public/mojom/cros_network_config.typemap b/chromeos/services/network_config/public/mojom/cros_network_config.typemap index ad3154c..2410ad27 100644 --- a/chromeos/services/network_config/public/mojom/cros_network_config.typemap +++ b/chromeos/services/network_config/public/mojom/cros_network_config.typemap
@@ -7,6 +7,7 @@ public_deps = [ "//components/onc", + "//components/proxy_config", ] public_headers = [ "//components/onc/onc_constants.h" ]
diff --git a/chromeos/services/network_config/public/mojom/cros_network_config_mojom_traits.cc b/chromeos/services/network_config/public/mojom/cros_network_config_mojom_traits.cc index 3d8b4a64..89895d0 100644 --- a/chromeos/services/network_config/public/mojom/cros_network_config_mojom_traits.cc +++ b/chromeos/services/network_config/public/mojom/cros_network_config_mojom_traits.cc
@@ -53,4 +53,52 @@ return false; } +chromeos::network_config::mojom::ProxyMode +EnumTraits<chromeos::network_config::mojom::ProxyMode, + ProxyPrefs::ProxyMode>::ToMojom(ProxyPrefs::ProxyMode input) { + switch (input) { + case ProxyPrefs::MODE_DIRECT: + return chromeos::network_config::mojom::ProxyMode::kDirect; + case ProxyPrefs::MODE_AUTO_DETECT: + return chromeos::network_config::mojom::ProxyMode::kAutoDetect; + case ProxyPrefs::MODE_PAC_SCRIPT: + return chromeos::network_config::mojom::ProxyMode::kPacScript; + case ProxyPrefs::MODE_FIXED_SERVERS: + return chromeos::network_config::mojom::ProxyMode::kFixedServers; + case ProxyPrefs::MODE_SYSTEM: + return chromeos::network_config::mojom::ProxyMode::kSystem; + case ProxyPrefs::kModeCount: + break; + } + + NOTREACHED(); + return chromeos::network_config::mojom::ProxyMode::kDirect; +} + +bool EnumTraits<chromeos::network_config::mojom::ProxyMode, + ProxyPrefs::ProxyMode>:: + FromMojom(chromeos::network_config::mojom::ProxyMode input, + ProxyPrefs::ProxyMode* out) { + switch (input) { + case chromeos::network_config::mojom::ProxyMode::kDirect: + *out = ProxyPrefs::MODE_DIRECT; + return true; + case chromeos::network_config::mojom::ProxyMode::kAutoDetect: + *out = ProxyPrefs::MODE_AUTO_DETECT; + return true; + case chromeos::network_config::mojom::ProxyMode::kPacScript: + *out = ProxyPrefs::MODE_PAC_SCRIPT; + return true; + case chromeos::network_config::mojom::ProxyMode::kFixedServers: + *out = ProxyPrefs::MODE_FIXED_SERVERS; + return true; + case chromeos::network_config::mojom::ProxyMode::kSystem: + *out = ProxyPrefs::MODE_SYSTEM; + return true; + } + + NOTREACHED(); + return false; +} + } // namespace mojo
diff --git a/chromeos/services/network_config/public/mojom/cros_network_config_mojom_traits.h b/chromeos/services/network_config/public/mojom/cros_network_config_mojom_traits.h index 0a860c221..0ae9185 100644 --- a/chromeos/services/network_config/public/mojom/cros_network_config_mojom_traits.h +++ b/chromeos/services/network_config/public/mojom/cros_network_config_mojom_traits.h
@@ -7,6 +7,7 @@ #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h" #include "components/onc/onc_constants.h" +#include "components/proxy_config/proxy_prefs.h" #include "mojo/public/cpp/bindings/enum_traits.h" namespace mojo { @@ -20,6 +21,16 @@ onc::ONCSource* out); }; +template <> +class EnumTraits<chromeos::network_config::mojom::ProxyMode, + ProxyPrefs::ProxyMode> { + public: + static chromeos::network_config::mojom::ProxyMode ToMojom( + ProxyPrefs::ProxyMode input); + static bool FromMojom(chromeos::network_config::mojom::ProxyMode input, + ProxyPrefs::ProxyMode* out); +}; + } // namespace mojo #endif // CHROMEOS_SERVICES_NETWORK_CONFIG_PUBLIC_MOJOM_CROS_NETWORK_CONFIG_MOJOM_TRAITS_H_
diff --git a/components/OWNERS b/components/OWNERS index 00c717f..c3e984d 100644 --- a/components/OWNERS +++ b/components/OWNERS
@@ -13,6 +13,7 @@ per-file error_page_strings.grdp=file://components/error_page/OWNERS per-file management_strings.grdp=file://docs/privacy/OWNERS per-file ntp_snippets_strings.grdp=file://components/ntp_snippets/OWNERS +per-file ntp_tiles_strings.grdp=file://components/ntp_tiles/OWNERS per-file omnibox_strings.grdp=file://components/omnibox/OWNERS per-file page_info_strings.grdp=file://chrome/browser/ui/page_info/OWNERS per-file password_manager_strings.grdp=file://components/password_manager/OWNERS
diff --git a/components/arc/intent_helper/arc_intent_helper_bridge.cc b/components/arc/intent_helper/arc_intent_helper_bridge.cc index 251884d..56f860b 100644 --- a/components/arc/intent_helper/arc_intent_helper_bridge.cc +++ b/components/arc/intent_helper/arc_intent_helper_bridge.cc
@@ -8,7 +8,8 @@ #include <utility> #include "ash/public/cpp/new_window_delegate.h" -#include "ash/public/cpp/wallpaper_controller.h" +#include "ash/public/interfaces/constants.mojom.h" +#include "ash/public/interfaces/wallpaper.mojom.h" #include "base/logging.h" #include "base/memory/singleton.h" #include "base/memory/weak_ptr.h" @@ -228,7 +229,11 @@ void ArcIntentHelperBridge::OpenWallpaperPicker() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); RecordOpenType(ArcIntentHelperOpenType::WALLPAPER_PICKER); - ash::WallpaperController::Get()->OpenWallpaperPickerIfAllowed(); + ash::mojom::WallpaperControllerPtr wallpaper_controller_ptr; + content::ServiceManagerConnection::GetForProcess() + ->GetConnector() + ->BindInterface(ash::mojom::kServiceName, &wallpaper_controller_ptr); + wallpaper_controller_ptr->OpenWallpaperPickerIfAllowed(); } void ArcIntentHelperBridge::SetWallpaperDeprecated(
diff --git a/components/autofill/core/browser/payments/credit_card_save_manager.cc b/components/autofill/core/browser/payments/credit_card_save_manager.cc index 3a8e590..72368d45 100644 --- a/components/autofill/core/browser/payments/credit_card_save_manager.cc +++ b/components/autofill/core/browser/payments/credit_card_save_manager.cc
@@ -103,8 +103,10 @@ // Query the Autofill StrikeDatabase on if we should pop up the // offer-to-save prompt for this card. - OnDidGetStrikesForLocalSave(GetCreditCardSaveStrikeDatabase()->GetStrikes( - base::UTF16ToUTF8(local_card_save_candidate_.LastFourDigits()))); + show_save_prompt_ = + !GetCreditCardSaveStrikeDatabase()->IsMaxStrikesLimitReached( + base::UTF16ToUTF8(local_card_save_candidate_.LastFourDigits())); + OfferCardLocalSave(); } void CreditCardSaveManager::AttemptToOfferCardUploadSave( @@ -236,6 +238,12 @@ // All required data is available, start the upload process. if (observer_for_testing_) observer_for_testing_->OnDecideToRequestUploadSave(); + + // Query the Autofill StrikeDatabase on if we should pop up the + // offer-to-save prompt for this card. + show_save_prompt_ = + !GetCreditCardSaveStrikeDatabase()->IsMaxStrikesLimitReached( + base::UTF16ToUTF8(upload_request_.card.LastFourDigits())); payments_client_->GetUploadDetails( send_only_country_in_addresses ? country_only_profiles : upload_request_.profiles, @@ -245,10 +253,6 @@ weak_ptr_factory_.GetWeakPtr()), payments::kUploadCardBillableServiceNumber, payments::PaymentsClient::UploadCardSource::UPSTREAM_CHECKOUT_FLOW); - // Query the Autofill StrikeDatabase on if we should pop up the - // offer-to-save prompt for this card. - OnDidGetStrikesForUploadSave(GetCreditCardSaveStrikeDatabase()->GetStrikes( - base::UTF16ToUTF8(upload_request_.card.LastFourDigits()))); } bool CreditCardSaveManager::IsCreditCardUploadEnabled() { @@ -345,26 +349,6 @@ return local_card_migration_strike_database_.get(); } -void CreditCardSaveManager::OnDidGetStrikesForLocalSave(const int num_strikes) { - show_save_prompt_ = - num_strikes < kMaxStrikesToPreventPoppingUpOfferToSavePrompt; - - OfferCardLocalSave(); -} - -void CreditCardSaveManager::OnDidGetStrikesForUploadSave( - const int num_strikes) { - show_save_prompt_ = - num_strikes < kMaxStrikesToPreventPoppingUpOfferToSavePrompt; - - // Only offer upload once both Payments and the Autofill - // StrikeDatabase have returned their decisions. Use population of - // |upload_request_.context_token| as an indicator of the Payments call - // returning successfully. - if (!upload_request_.context_token.empty()) - OfferCardUploadSave(); -} - void CreditCardSaveManager::OnDidGetUploadDetails( AutofillClient::PaymentsRpcResult result, const base::string16& context_token, @@ -393,13 +377,7 @@ } upload_request_.context_token = context_token; legal_message_ = base::DictionaryValue::From(std::move(legal_message)); - - // Only offer upload once both Payments and the Autofill - // StrikeDatabase have returned their decisions. Use presence of - // |show_save_prompt_| as an indicator of StrikeDatabase retrieving - // its data. - if (show_save_prompt_.has_value()) - OfferCardUploadSave(); + OfferCardUploadSave(); } else { // If the upload details request failed and we *know* we have all possible // information (card number, expiration, cvc, name, and address), fall back
diff --git a/components/autofill/core/browser/payments/credit_card_save_manager.h b/components/autofill/core/browser/payments/credit_card_save_manager.h index f28c34a..0de7ae9 100644 --- a/components/autofill/core/browser/payments/credit_card_save_manager.h +++ b/components/autofill/core/browser/payments/credit_card_save_manager.h
@@ -143,6 +143,10 @@ friend class TestCreditCardSaveManager; friend class SaveCardBubbleViewsFullFormBrowserTest; friend class SaveCardInfobarEGTestHelper; + FRIEND_TEST_ALL_PREFIXES(SaveCardBubbleViewsFullFormBrowserTest, + StrikeDatabase_Local_FullFlowTest); + FRIEND_TEST_ALL_PREFIXES(SaveCardBubbleViewsFullFormBrowserTest, + StrikeDatabase_Upload_FullFlowTest); // Returns the CreditCardSaveStrikeDatabase for |client_|. CreditCardSaveStrikeDatabase* GetCreditCardSaveStrikeDatabase(); @@ -150,14 +154,6 @@ // Returns the GetLocalCardMigrationStrikeDatabase for |client_|. LocalCardMigrationStrikeDatabase* GetLocalCardMigrationStrikeDatabase(); - // Sets |show_save_prompt| and moves forward with offering credit card local - // save. - void OnDidGetStrikesForLocalSave(const int num_strikes); - - // Sets |show_save_prompt| and moves forward with offering credit card upload - // if Payments has also returned a success response. - void OnDidGetStrikesForUploadSave(const int num_strikes); - // Returns the legal message retrieved from Payments. On failure or not // meeting Payments's conditions for upload, |legal_message| will contain // nullptr. |supported_card_bin_ranges| is a list of BIN prefix ranges which
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc index 9d02f4b5..df9e83ea 100644 --- a/components/autofill/core/browser/personal_data_manager.cc +++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -1189,8 +1189,6 @@ type.GetStorableType(), 1, app_locale_, &labels); } - suggestion_selection::PrepareSuggestions(formatter != nullptr, labels, - &unique_suggestions); #if !defined(OS_ANDROID) && !defined(OS_IOS) if (use_improved_label_disambiguation && !unique_suggestions.empty()) { @@ -1199,6 +1197,9 @@ } #endif // #if !defined(OS_ANDROID) && !defined(OS_IOS) + suggestion_selection::PrepareSuggestions(formatter != nullptr, labels, + &unique_suggestions, comparator); + return unique_suggestions; }
diff --git a/components/autofill/core/browser/ui/suggestion_selection.cc b/components/autofill/core/browser/ui/suggestion_selection.cc index 0e5ae85..3d3ef80fa 100644 --- a/components/autofill/core/browser/ui/suggestion_selection.cc +++ b/components/autofill/core/browser/ui/suggestion_selection.cc
@@ -4,6 +4,7 @@ #include "components/autofill/core/browser/ui/suggestion_selection.h" #include <string> +#include <unordered_set> #include <vector> #include "base/strings/string_util.h" @@ -247,18 +248,56 @@ void PrepareSuggestions(bool add_profile_icon, const std::vector<base::string16>& labels, - std::vector<Suggestion>* suggestions) { + std::vector<Suggestion>* suggestions, + const AutofillProfileComparator& comparator) { DCHECK_EQ(suggestions->size(), labels.size()); + // This set is used to determine whether duplicate Suggestions exist. For + // example, a Suggestion with the value "John" and the label "400 Oak Rd" has + // the normalized text "john400oakrd". This text can only be added to the set + // once. + std::unordered_set<base::string16> suggestion_text; + size_t index_to_add_suggestion = 0; + + // Dedupes Suggestions to show in the dropdown once values and labels have + // been created. This is useful when LabelFormatters make Suggestions' labels. + // + // Suppose profile A has the data John, 400 Oak Rd, and (617) 544-7411 and + // profile B has the data John, 400 Oak Rd, (508) 957-5009. If a formatter + // puts only 400 Oak Rd in the label, then there will be two Suggestions with + // the normalized text "john400oakrd", and the Suggestion with the lower + // ranking should be discarded. for (size_t i = 0; i < labels.size(); ++i) { - (*suggestions)[i].additional_label = labels[i]; - (*suggestions)[i].label = labels[i]; + base::string16 label = labels[i]; + + bool text_inserted = + suggestion_text + .insert(comparator.NormalizeForComparison( + (*suggestions)[i].value + label, + autofill::AutofillProfileComparator::DISCARD_WHITESPACE)) + .second; + + if (text_inserted) { + if (index_to_add_suggestion != i) { + (*suggestions)[index_to_add_suggestion] = (*suggestions)[i]; + } + // The given |suggestions| are already sorted from highest to lowest + // ranking. Suggestions with lower indices have a higher ranking and + // should be kept. + (*suggestions)[index_to_add_suggestion].additional_label = labels[i]; + (*suggestions)[index_to_add_suggestion].label = labels[i]; #if !defined(OS_ANDROID) && !defined(OS_IOS) - if (add_profile_icon) { - (*suggestions)[i].icon = "accountBoxIcon"; - } + if (add_profile_icon) { + (*suggestions)[index_to_add_suggestion].icon = "accountBoxIcon"; + } #endif // !defined(OS_ANDROID) && !defined(OS_IOS) + ++index_to_add_suggestion; + } + } + + if (index_to_add_suggestion < suggestions->size()) { + suggestions->resize(index_to_add_suggestion); } }
diff --git a/components/autofill/core/browser/ui/suggestion_selection.h b/components/autofill/core/browser/ui/suggestion_selection.h index 0867fb9c..cac66719 100644 --- a/components/autofill/core/browser/ui/suggestion_selection.h +++ b/components/autofill/core/browser/ui/suggestion_selection.h
@@ -65,12 +65,16 @@ std::vector<AutofillProfile*>* profiles); // Prepares a collection of Suggestions to show to the user. Adds |labels| to -// their corresponding |suggestions|. A label corresponds to the suggestion with -// the same index. Adds an icon on desktop platforms when |add_profile_icon| is -// true. +// their corresponding |suggestions| and removes duplicates, if any. A label +// corresponds to the suggestion with the same index. Adds an icon on desktop +// platforms when |add_profile_icon| is true. +// +// NOTE: |suggestions| are assumed to have already been sorted from most to +// least important. void PrepareSuggestions(bool add_profile_icon, const std::vector<base::string16>& labels, - std::vector<Suggestion>* suggestions); + std::vector<Suggestion>* suggestions, + const AutofillProfileComparator& comparator); } // namespace suggestion_selection } // namespace autofill
diff --git a/components/autofill/core/browser/ui/suggestion_selection_unittest.cc b/components/autofill/core/browser/ui/suggestion_selection_unittest.cc index 2691c07..783cc0c 100644 --- a/components/autofill/core/browser/ui/suggestion_selection_unittest.cc +++ b/components/autofill/core/browser/ui/suggestion_selection_unittest.cc
@@ -519,5 +519,62 @@ } } +TEST_F(SuggestionSelectionTest, + PrepareSuggestions_DiscardDuplicateSuggestions) { + std::vector<Suggestion> suggestions{ + Suggestion(base::ASCIIToUTF16("Jon Snow")), + Suggestion(base::ASCIIToUTF16("Jon Snow")), + Suggestion(base::ASCIIToUTF16("Jon Snow")), + Suggestion(base::ASCIIToUTF16("Jon Snow"))}; + + const std::vector<base::string16> labels{ + base::ASCIIToUTF16("2 Beyond-the-Wall Rd"), + base::ASCIIToUTF16("1 Winterfell Ln"), + base::ASCIIToUTF16("2 Beyond-the-Wall Rd"), + base::ASCIIToUTF16("2 Beyond-the-Wall Rd.")}; + + PrepareSuggestions(/*add_profile_icon=*/false, labels, &suggestions, + comparator_); + + // Suggestions are sorted from highest to lowest rank, so check that + // duplicates with a lower rank are removed. + EXPECT_THAT( + suggestions, + ElementsAre( + AllOf(Field(&Suggestion::value, base::ASCIIToUTF16("Jon Snow")), + Field(&Suggestion::label, + base::ASCIIToUTF16("2 Beyond-the-Wall Rd"))), + AllOf(Field(&Suggestion::value, base::ASCIIToUTF16("Jon Snow")), + Field(&Suggestion::label, + base::ASCIIToUTF16("1 Winterfell Ln"))))); +} + +TEST_F(SuggestionSelectionTest, + PrepareSuggestions_KeepNonDuplicateSuggestions) { + std::vector<Suggestion> suggestions{ + Suggestion(base::ASCIIToUTF16("Sansa")), + Suggestion(base::ASCIIToUTF16("Sansa")), + Suggestion(base::ASCIIToUTF16("Brienne"))}; + + const std::vector<base::string16> labels{ + base::ASCIIToUTF16("1 Winterfell Ln"), base::ASCIIToUTF16(""), + base::ASCIIToUTF16("1 Winterfell Ln")}; + + PrepareSuggestions(/*add_profile_icon=*/false, labels, &suggestions, + comparator_); + + EXPECT_THAT( + suggestions, + ElementsAre( + AllOf( + Field(&Suggestion::value, base::ASCIIToUTF16("Sansa")), + Field(&Suggestion::label, base::ASCIIToUTF16("1 Winterfell Ln"))), + AllOf(Field(&Suggestion::value, base::ASCIIToUTF16("Sansa")), + Field(&Suggestion::label, base::ASCIIToUTF16(""))), + AllOf(Field(&Suggestion::value, base::ASCIIToUTF16("Brienne")), + Field(&Suggestion::label, + base::ASCIIToUTF16("1 Winterfell Ln"))))); +} + } // namespace suggestion_selection } // namespace autofill
diff --git a/components/autofill/core/common/autofill_constants.h b/components/autofill/core/common/autofill_constants.h index 59314c26..5e3b1955 100644 --- a/components/autofill/core/common/autofill_constants.h +++ b/components/autofill/core/common/autofill_constants.h
@@ -36,14 +36,6 @@ IS_PASSWORD_FIELD = 1 << 1 /* input field is a password field */ }; -// Autofill StrikeDatabase: Maximum strikes allowed for the credit card -// save project. If the StrikeDatabase returns this many strikes for a -// given card, it will not show the offer-to-save bubble on Desktop or infobar -// on Android. On Desktop, however, the omnibox icon will still be available. -// TODO(crbug.com/884817): Remove once StrikeDatabase v2 moves this constant to -// its own credit card save policy. -const int kMaxStrikesToPreventPoppingUpOfferToSavePrompt = 3; - // Constants for the soft/hard deletion of Autofill data. constexpr base::TimeDelta kDisusedDataModelTimeDelta = base::TimeDelta::FromDays(180);
diff --git a/components/bookmarks/browser/bookmark_node_data.cc b/components/bookmarks/browser/bookmark_node_data.cc index 6a5b0e8f5..6801c22 100644 --- a/components/bookmarks/browser/bookmark_node_data.cc +++ b/components/bookmarks/browser/bookmark_node_data.cc
@@ -97,13 +97,14 @@ LOG(WARNING) << "children_count failed bounds check"; return false; } + // Note: do not preallocate the children vector. A pickle could be + // constructed to contain N nested Elements. By continually recursing on + // this ReadFromPickle function, the fast-fail logic is subverted. Each + // child would claim it contains M more children. The first (and only) child + // provided would claim M more children. We would allocate N * M Elements + // along the way, while only receiving N Elements. const size_t children_count = base::checked_cast<size_t>(children_count_tmp); - // Restrict vector preallocation to prevent OOM crashes on invalid (or - // malicious) pickles. - if (children_count > kMaxVectorPreallocateSize) - LOG(WARNING) << "children_count exceeds kMaxVectorPreallocateSize"; - children.reserve(std::min(children_count, kMaxVectorPreallocateSize)); for (size_t i = 0; i < children_count; ++i) { children.emplace_back(); if (!children.back().ReadFromPickle(iterator))
diff --git a/components/certificate_transparency/BUILD.gn b/components/certificate_transparency/BUILD.gn index 604177a7..3eedd649 100644 --- a/components/certificate_transparency/BUILD.gn +++ b/components/certificate_transparency/BUILD.gn
@@ -10,20 +10,8 @@ "chrome_require_ct_delegate.h", "ct_known_logs.cc", "ct_known_logs.h", - "features.cc", - "features.h", - "log_dns_client.cc", - "log_dns_client.h", "pref_names.cc", "pref_names.h", - "single_tree_tracker.cc", - "single_tree_tracker.h", - "sth_distributor.cc", - "sth_distributor.h", - "sth_observer.h", - "sth_reporter.h", - "tree_state_tracker.cc", - "tree_state_tracker.h", ] deps = [ @@ -44,12 +32,6 @@ "chrome_ct_policy_enforcer_unittest.cc", "chrome_require_ct_delegate_unittest.cc", "ct_known_logs_unittest.cc", - "log_dns_client_unittest.cc", - "mock_log_dns_traffic.cc", - "mock_log_dns_traffic.h", - "single_tree_tracker_unittest.cc", - "sth_distributor_unittest.cc", - "tree_state_tracker_unittest.cc", ] deps = [ ":certificate_transparency",
diff --git a/components/certificate_transparency/chrome_ct_policy_enforcer.cc b/components/certificate_transparency/chrome_ct_policy_enforcer.cc index 7a2f2f71..43f3ae0 100644 --- a/components/certificate_transparency/chrome_ct_policy_enforcer.cc +++ b/components/certificate_transparency/chrome_ct_policy_enforcer.cc
@@ -16,6 +16,7 @@ #include "base/metrics/histogram_macros.h" #include "base/numerics/safe_conversions.h" #include "base/strings/string_number_conversions.h" +#include "base/time/default_clock.h" #include "base/time/time.h" #include "base/values.h" #include "base/version.h" @@ -109,6 +110,7 @@ std::vector<std::string> operated_by_google_logs) : disqualified_logs_(disqualified_logs), operated_by_google_logs_(operated_by_google_logs), + clock_(base::DefaultClock::GetInstance()), log_list_date_(log_list_date) {} ChromeCTPolicyEnforcer::~ChromeCTPolicyEnforcer() {} @@ -163,7 +165,7 @@ bool ChromeCTPolicyEnforcer::IsLogDataTimely() const { // We consider built-in information to be timely for 10 weeks. - return (base::Time::Now() - log_list_date_).InDays() < 70 /* 10 weeks */; + return (clock_->Now() - log_list_date_).InDays() < 70 /* 10 weeks */; } // Evaluates against the policy specified at
diff --git a/components/certificate_transparency/chrome_ct_policy_enforcer.h b/components/certificate_transparency/chrome_ct_policy_enforcer.h index 989d3e6..053cbacd 100644 --- a/components/certificate_transparency/chrome_ct_policy_enforcer.h +++ b/components/certificate_transparency/chrome_ct_policy_enforcer.h
@@ -9,6 +9,7 @@ #include <utility> #include <vector> +#include "base/time/clock.h" #include "base/time/time.h" #include "net/cert/ct_policy_enforcer.h" @@ -42,6 +43,8 @@ const net::ct::SCTList& verified_scts, const net::NetLogWithSource& net_log) override; + void SetClockForTesting(const base::Clock* clock) { clock_ = clock; } + private: // Returns true if the log identified by |log_id| (the SHA-256 hash of the // log's DER-encoded SPKI) has been disqualified, and sets @@ -68,6 +71,8 @@ // List of SHA-256(SPKI) for logs operated by Google. std::vector<std::string> operated_by_google_logs_; + const base::Clock* clock_; + // The time at which |disqualified_logs_| and |operated_by_google_logs_| were // generated. const base::Time log_list_date_;
diff --git a/components/certificate_transparency/chrome_ct_policy_enforcer_unittest.cc b/components/certificate_transparency/chrome_ct_policy_enforcer_unittest.cc index 49bf2ad..d072578 100644 --- a/components/certificate_transparency/chrome_ct_policy_enforcer_unittest.cc +++ b/components/certificate_transparency/chrome_ct_policy_enforcer_unittest.cc
@@ -9,6 +9,7 @@ #include "base/build_time.h" #include "base/stl_util.h" +#include "base/test/simple_test_clock.h" #include "base/time/time.h" #include "base/version.h" #include "components/certificate_transparency/ct_known_logs.h" @@ -44,9 +45,10 @@ class ChromeCTPolicyEnforcerTest : public ::testing::Test { public: void SetUp() override { - policy_enforcer_.reset( - new ChromeCTPolicyEnforcer(base::GetBuildTime(), GetDisqualifiedLogs(), - GetLogsOperatedByGoogle())); + auto enforcer = std::make_unique<ChromeCTPolicyEnforcer>( + base::GetBuildTime(), GetDisqualifiedLogs(), GetLogsOperatedByGoogle()); + enforcer->SetClockForTesting(&clock_); + policy_enforcer_.reset(enforcer.release()); std::string der_test_cert(net::ct::GetDerEncodedX509Cert()); chain_ = X509Certificate::CreateFromBytes(der_test_cert.data(), @@ -54,6 +56,7 @@ ASSERT_TRUE(chain_.get()); google_log_id_ = std::string(kGoogleAviatorLogID, crypto::kSHA256Length); non_google_log_id_.assign(crypto::kSHA256Length, 1); + clock_.SetNow(base::Time::Now()); } void FillListWithSCTsOfOrigin( @@ -126,6 +129,7 @@ } protected: + base::SimpleTestClock clock_; std::unique_ptr<net::CTPolicyEnforcer> policy_enforcer_; scoped_refptr<X509Certificate> chain_; std::string google_log_id_; @@ -183,6 +187,22 @@ NetLogWithSource())); } +TEST_F(ChromeCTPolicyEnforcerTest, EnforcementDisabledByBinaryAge) { + SCTList scts; + FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, + 2, &scts); + + EXPECT_EQ(CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS, + policy_enforcer_->CheckCompliance(chain_.get(), scts, + NetLogWithSource())); + + clock_.Advance(base::TimeDelta::FromDays(71)); + + EXPECT_EQ(CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY, + policy_enforcer_->CheckCompliance(chain_.get(), scts, + NetLogWithSource())); +} + TEST_F(ChromeCTPolicyEnforcerTest, ConformsToCTPolicyWithEmbeddedSCTs) { // |chain_| is valid for 10 years - over 121 months - so requires 5 SCTs. SCTList scts;
diff --git a/components/certificate_transparency/features.cc b/components/certificate_transparency/features.cc deleted file mode 100644 index 949ef35b..0000000 --- a/components/certificate_transparency/features.cc +++ /dev/null
@@ -1,13 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/certificate_transparency/features.h" - -namespace certificate_transparency { - -// Enables or disables auditing Certificate Transparency logs over DNS. -const base::Feature kCTLogAuditing = {"CertificateTransparencyLogAuditing", - base::FEATURE_DISABLED_BY_DEFAULT}; - -} // namespace certificate_transparency
diff --git a/components/certificate_transparency/features.h b/components/certificate_transparency/features.h deleted file mode 100644 index 835cdab9..0000000 --- a/components/certificate_transparency/features.h +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_CERTIFICATE_TRANSPARENCY_FEATURES_H_ -#define COMPONENTS_CERTIFICATE_TRANSPARENCY_FEATURES_H_ - -#include "base/feature_list.h" - -namespace certificate_transparency { - -extern const base::Feature kCTLogAuditing; - -} // namespace certificate_transparency - -#endif // COMPONENTS_CERTIFICATE_TRANSPARENCY_FEATURES_H_
diff --git a/components/certificate_transparency/log_dns_client.cc b/components/certificate_transparency/log_dns_client.cc deleted file mode 100644 index 695c096..0000000 --- a/components/certificate_transparency/log_dns_client.cc +++ /dev/null
@@ -1,612 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/certificate_transparency/log_dns_client.h" - -#include "base/big_endian.h" -#include "base/bind.h" -#include "base/format_macros.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/metrics/histogram_functions.h" -#include "base/metrics/histogram_macros.h" -#include "base/stl_util.h" -#include "base/strings/strcat.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/time/time.h" -#include "components/base32/base32.h" -#include "crypto/sha2.h" -#include "net/base/completion_once_callback.h" -#include "net/base/sys_addrinfo.h" -#include "net/cert/merkle_audit_proof.h" -#include "net/dns/dns_client.h" -#include "net/dns/dns_config.h" -#include "net/dns/dns_response.h" -#include "net/dns/dns_transaction.h" -#include "net/dns/dns_util.h" -#include "net/dns/public/dns_protocol.h" -#include "net/dns/record_parsed.h" -#include "net/dns/record_rdata.h" - -namespace certificate_transparency { - -namespace { - -void LogQueryDuration(net::Error error, const base::TimeDelta& duration) { - UMA_HISTOGRAM_MEDIUM_TIMES("Net.CertificateTransparency.DnsQueryDuration", - duration); - - if (error == net::OK) { - UMA_HISTOGRAM_MEDIUM_TIMES( - "Net.CertificateTransparency.DnsQueryDuration.Success", duration); - } -} - -void LogQueryResult(const std::string& name, - net::Error error, - const net::DnsResponse* response) { - base::UmaHistogramSparse( - base::StrCat({"Net.CertificateTransparency.DnsQuery", name, "Error"}), - -error); - - if (response) { - base::UmaHistogramSparse( - base::StrCat({"Net.CertificateTransparency.DnsQuery", name, "Rcode"}), - response->rcode()); - } -} - -// Returns an EDNS option that disables the client subnet extension, as -// described in https://tools.ietf.org/html/rfc7871. This is to avoid the -// privacy issues caused by this extension being enabled in recursive resolvers -// used by this DNS client (see the "Privacy Note" in RFC7871). -net::OptRecordRdata::Opt OptToDisableClientSubnetExtension() { - const uint16_t kClientSubnetExtensionCode = 8; - // https://www.iana.org/assignments/address-family-numbers/address-family-numbers.xhtml - const uint16_t kIanaAddressFamilyIpV4 = 1; - - char buf[4]; - base::BigEndianWriter writer(buf, base::size(buf)); - // family - address is empty so the value of this is irrelevant, so long as - // it's valid (see https://tools.ietf.org/html/rfc7871#section-7.1.2). - writer.WriteU16(kIanaAddressFamilyIpV4); - // source prefix length - 0 to disable this extension. - writer.WriteU8(0); - // scope prefix length - must be 0 for queries. - writer.WriteU8(0); - // no address - don't want a client subnet in the query. - - return net::OptRecordRdata::Opt(kClientSubnetExtensionCode, - base::StringPiece(buf, base::size(buf))); -} - -// Parses the DNS response and extracts a single string from the TXT RDATA. -// If the response is malformed, not a TXT record, or contains any number of -// strings other than 1, this returns false and extracts nothing. -// Otherwise, it returns true and the extracted string is assigned to |*txt|. -bool ParseTxtResponse(const net::DnsResponse& response, std::string* txt) { - DCHECK(txt); - - net::DnsRecordParser parser = response.Parser(); - // We don't care about the creation time, since we're going to throw - // |parsed_record| away as soon as we've extracted the payload, so provide - // the "null" time. - auto parsed_record = net::RecordParsed::CreateFrom(&parser, base::Time()); - if (!parsed_record) - return false; - - auto* txt_record = parsed_record->rdata<net::TxtRecordRdata>(); - if (!txt_record) - return false; - - // The draft CT-over-DNS RFC says that there MUST be exactly one string in the - // TXT record. - if (txt_record->texts().size() != 1) - return false; - - *txt = txt_record->texts().front(); - return true; -} - -// Extracts a leaf index value from a DNS response's TXT RDATA. -// Returns true on success, false otherwise. -bool ParseLeafIndex(const net::DnsResponse& response, uint64_t* index) { - DCHECK(index); - - std::string index_str; - if (!ParseTxtResponse(response, &index_str)) - return false; - - return base::StringToUint64(index_str, index); -} - -// Extracts audit proof nodes from a DNS response's TXT RDATA. -// Returns true on success, false otherwise. -// It will fail if there is not a whole number of nodes present > 0. -// There must only be one string in the TXT RDATA. -// The nodes will be appended to |proof->nodes| -bool ParseAuditPath(const net::DnsResponse& response, - net::ct::MerkleAuditProof* proof) { - DCHECK(proof); - - std::string audit_path; - if (!ParseTxtResponse(response, &audit_path)) - return false; - // If empty or not a multiple of the node size, it is considered invalid. - // It's important to consider empty audit paths as invalid, as otherwise an - // infinite loop could occur if the server consistently returned empty - // responses. - if (audit_path.empty() || audit_path.size() % crypto::kSHA256Length != 0) - return false; - - for (size_t i = 0; i < audit_path.size(); i += crypto::kSHA256Length) { - proof->nodes.push_back(audit_path.substr(i, crypto::kSHA256Length)); - } - - return true; -} - -} // namespace - -// Encapsulates the state machine required to get an audit proof from a Merkle -// leaf hash. This requires a DNS request to obtain the leaf index, then a -// series of DNS requests to get the nodes of the proof. -class AuditProofQueryImpl : public LogDnsClient::AuditProofQuery { - public: - // The API contract of LogDnsClient requires that callers make sure the - // AuditProofQuery does not outlive LogDnsClient, so it's safe to leave - // ownership of |dns_client| with LogDnsClient. - AuditProofQueryImpl(net::DnsClient* dns_client, - net::URLRequestContext* url_request_context, - const std::string& domain_for_log, - const net::NetLogWithSource& net_log); - - ~AuditProofQueryImpl() override; - - // Begins the process of getting an audit proof for the CT log entry with a - // leaf hash of |leaf_hash|. If |lookup_securely| is true, only secure DNS - // lookups will be performed, otherwise only insecure DNS lookups will be - // performed. The proof will be for a tree of size |tree_size|. If the proof - // cannot be obtained synchronously, net::ERR_IO_PENDING will be returned and - // |callback| will be invoked when the operation has completed asynchronously. - // If the operation is cancelled (by deleting the AuditProofQueryImpl), - // |cancellation_callback| will be invoked. - net::Error Start(std::string leaf_hash, - bool lookup_securely, - uint64_t tree_size, - net::CompletionOnceCallback callback, - base::OnceClosure cancellation_callback); - - // Returns the proof that is being obtained by this query. - // It is only guaranteed to be populated once either Start() returns net::OK - // or the completion callback is invoked with net::OK. - const net::ct::MerkleAuditProof& GetProof() const override; - - private: - enum class State { - NONE, - REQUEST_LEAF_INDEX, - REQUEST_LEAF_INDEX_COMPLETE, - REQUEST_AUDIT_PROOF_NODES, - REQUEST_AUDIT_PROOF_NODES_COMPLETE, - }; - - net::Error DoLoop(net::Error result); - - // When a DnsTransaction completes, store the response and resume the state - // machine. It is safe to store a pointer to |response| because |transaction| - // is kept alive in |current_dns_transaction_|. - void OnDnsTransactionComplete(net::DnsTransaction* transaction, - int net_error, - const net::DnsResponse* response, - bool secure); - - // Requests the leaf index for the CT log entry with |leaf_hash_|. - net::Error RequestLeafIndex(); - - // Stores the received leaf index in |proof_->leaf_index|. - // If successful, the audit proof nodes will be requested next. - net::Error RequestLeafIndexComplete(net::Error result); - - // Requests the next batch of audit proof nodes from a CT log. - // The index of the first node required is determined by looking at how many - // nodes are already in |proof_->nodes|. - // The CT log may return up to 7 nodes - this is the maximum allowed by the - // CT-over-DNS draft RFC, as a TXT RDATA string can have a maximum length of - // 255 bytes and each node is 32 bytes long (a SHA-256 hash). - // - // The performance of this could be improved by sending all of the expected - // requests up front. Each response can contain a maximum of 7 audit path - // nodes, so for an audit proof of size 20, it could send 3 queries (for nodes - // 0-6, 7-13 and 14-19) immediately. Currently, it sends only the first and - // then, based on the number of nodes received, sends the next query. - // The complexity of the code would increase though, as it would need to - // detect gaps in the audit proof caused by the server not responding with the - // anticipated number of nodes. It would also undermine LogDnsClient's ability - // to rate-limit DNS requests. - net::Error RequestAuditProofNodes(); - - // Appends the received audit proof nodes to |proof_->nodes|. - // If any nodes are missing, another request will follow this one. - net::Error RequestAuditProofNodesComplete(net::Error result); - - // Sends a TXT record request for the domain |qname|. - // Returns true if the request could be started. - // OnDnsTransactionComplete() will be invoked with the result of the request. - bool StartDnsTransaction(const std::string& qname); - - // The next state that this query will enter. - State next_state_; - // The DNS domain of the CT log that is being queried. - std::string domain_for_log_; - // The Merkle leaf hash of the CT log entry an audit proof is required for. - std::string leaf_hash_; - // Whether the DNS request should be sent securely or insecurely. - bool lookup_securely_; - // The audit proof to populate. - net::ct::MerkleAuditProof proof_; - // The callback to invoke when the query is complete. - net::CompletionOnceCallback callback_; - // The callback to invoke when the query is cancelled. - base::OnceClosure cancellation_callback_; - // The DnsClient to use for sending DNS requests to the CT log. - net::DnsClient* dns_client_; - // The URLRequestContext to use for sending DoH requests to the CT log. - net::URLRequestContext* url_request_context_; - // The most recent DNS request. Null if no DNS requests have been made. - std::unique_ptr<net::DnsTransaction> current_dns_transaction_; - // The most recent DNS response. Only valid so long as the corresponding DNS - // request is stored in |current_dns_transaction_|. - const net::DnsResponse* last_dns_response_; - // The NetLog that DNS transactions will log to. - net::NetLogWithSource net_log_; - // The time that Start() was last called. Used to measure query duration. - base::TimeTicks start_time_; - // Produces WeakPtrs to |this| for binding callbacks. - base::WeakPtrFactory<AuditProofQueryImpl> weak_ptr_factory_; -}; - -AuditProofQueryImpl::AuditProofQueryImpl( - net::DnsClient* dns_client, - net::URLRequestContext* url_request_context, - const std::string& domain_for_log, - const net::NetLogWithSource& net_log) - : next_state_(State::NONE), - domain_for_log_(domain_for_log), - dns_client_(dns_client), - url_request_context_(url_request_context), - last_dns_response_(nullptr), - net_log_(net_log), - weak_ptr_factory_(this) { - DCHECK(dns_client_); - DCHECK(!domain_for_log_.empty()); -} - -AuditProofQueryImpl::~AuditProofQueryImpl() { - if (next_state_ != State::NONE) - std::move(cancellation_callback_).Run(); -} - -// |leaf_hash| is not a const-ref to allow callers to std::move that string into -// the method, avoiding the need to make a copy. -net::Error AuditProofQueryImpl::Start(std::string leaf_hash, - bool lookup_securely, - uint64_t tree_size, - net::CompletionOnceCallback callback, - base::OnceClosure cancellation_callback) { - // It should not already be in progress. - DCHECK_EQ(State::NONE, next_state_); - start_time_ = base::TimeTicks::Now(); - proof_.tree_size = tree_size; - leaf_hash_ = std::move(leaf_hash); - lookup_securely_ = lookup_securely; - callback_ = std::move(callback); - cancellation_callback_ = std::move(cancellation_callback); - // The first step in the query is to request the leaf index corresponding to - // |leaf_hash| from the CT log. - next_state_ = State::REQUEST_LEAF_INDEX; - // Begin the state machine. - return DoLoop(net::OK); -} - -const net::ct::MerkleAuditProof& AuditProofQueryImpl::GetProof() const { - return proof_; -} - -net::Error AuditProofQueryImpl::DoLoop(net::Error result) { - CHECK_NE(State::NONE, next_state_); - State state; - do { - state = next_state_; - next_state_ = State::NONE; - switch (state) { - case State::REQUEST_LEAF_INDEX: - result = RequestLeafIndex(); - break; - case State::REQUEST_LEAF_INDEX_COMPLETE: - result = RequestLeafIndexComplete(result); - if (result == net::OK) - LogQueryResult("LeafIndex", net::OK, last_dns_response_); - break; - case State::REQUEST_AUDIT_PROOF_NODES: - result = RequestAuditProofNodes(); - break; - case State::REQUEST_AUDIT_PROOF_NODES_COMPLETE: - result = RequestAuditProofNodesComplete(result); - break; - case State::NONE: - NOTREACHED(); - break; - } - } while (result != net::ERR_IO_PENDING && next_state_ != State::NONE); - - if (result != net::ERR_IO_PENDING) { - // If the query is complete, log some metrics. - LogQueryDuration(result, base::TimeTicks::Now() - start_time_); - switch (state) { - case State::REQUEST_LEAF_INDEX: - case State::REQUEST_LEAF_INDEX_COMPLETE: - // An error must have occurred if the query completed in this state. - LogQueryResult("LeafIndex", result, last_dns_response_); - break; - case State::REQUEST_AUDIT_PROOF_NODES: - case State::REQUEST_AUDIT_PROOF_NODES_COMPLETE: - // The query may have completed successfully. - LogQueryResult("AuditProof", result, last_dns_response_); - break; - case State::NONE: - NOTREACHED(); - break; - } - } - - return result; -} - -void AuditProofQueryImpl::OnDnsTransactionComplete( - net::DnsTransaction* transaction, - int net_error, - const net::DnsResponse* response, - bool secure) { - DCHECK_EQ(current_dns_transaction_.get(), transaction); - last_dns_response_ = response; - net::Error result = DoLoop(static_cast<net::Error>(net_error)); - - // If DoLoop() indicates that I/O is pending, don't invoke the completion - // callback. OnDnsTransactionComplete() will be invoked again once the I/O - // is complete, and can invoke the completion callback then if appropriate. - if (result != net::ERR_IO_PENDING) { - // The callback may delete this query (now that it has finished), so copy - // |callback_| before running it so that it is not deleted along with the - // query, mid-callback-execution (which would result in a crash). - std::move(callback_).Run(result); - } -} - -net::Error AuditProofQueryImpl::RequestLeafIndex() { - std::string encoded_leaf_hash = base32::Base32Encode( - leaf_hash_, base32::Base32EncodePolicy::OMIT_PADDING); - DCHECK_EQ(encoded_leaf_hash.size(), 52u); - - std::string qname = base::StringPrintf( - "%s.hash.%s.", encoded_leaf_hash.c_str(), domain_for_log_.c_str()); - - if (!StartDnsTransaction(qname)) { - return net::ERR_NAME_RESOLUTION_FAILED; - } - - next_state_ = State::REQUEST_LEAF_INDEX_COMPLETE; - return net::ERR_IO_PENDING; -} - -// Stores the received leaf index in |proof_->leaf_index|. -// If successful, the audit proof nodes will be requested next. -net::Error AuditProofQueryImpl::RequestLeafIndexComplete(net::Error result) { - if (result != net::OK) { - return result; - } - - DCHECK(last_dns_response_); - if (!ParseLeafIndex(*last_dns_response_, &proof_.leaf_index)) { - return net::ERR_DNS_MALFORMED_RESPONSE; - } - - // Reject leaf index if it is out-of-range. - // This indicates either: - // a) the wrong tree_size was provided. - // b) the wrong leaf hash was provided. - // c) there is a bug server-side. - // The first two are more likely, so return ERR_INVALID_ARGUMENT. - if (proof_.leaf_index >= proof_.tree_size) { - return net::ERR_INVALID_ARGUMENT; - } - - next_state_ = State::REQUEST_AUDIT_PROOF_NODES; - return net::OK; -} - -net::Error AuditProofQueryImpl::RequestAuditProofNodes() { - // Test pre-conditions (should be guaranteed by DNS response validation). - if (proof_.leaf_index >= proof_.tree_size || - proof_.nodes.size() >= net::ct::CalculateAuditPathLength( - proof_.leaf_index, proof_.tree_size)) { - return net::ERR_UNEXPECTED; - } - - std::string qname = base::StringPrintf( - "%zu.%" PRIu64 ".%" PRIu64 ".tree.%s.", proof_.nodes.size(), - proof_.leaf_index, proof_.tree_size, domain_for_log_.c_str()); - - if (!StartDnsTransaction(qname)) { - return net::ERR_NAME_RESOLUTION_FAILED; - } - - next_state_ = State::REQUEST_AUDIT_PROOF_NODES_COMPLETE; - return net::ERR_IO_PENDING; -} - -net::Error AuditProofQueryImpl::RequestAuditProofNodesComplete( - net::Error result) { - if (result != net::OK) { - return result; - } - - const uint64_t audit_path_length = - net::ct::CalculateAuditPathLength(proof_.leaf_index, proof_.tree_size); - - // The calculated |audit_path_length| can't ever be greater than 64, so - // deriving the amount of memory to reserve from the untrusted |leaf_index| - // is safe. - proof_.nodes.reserve(audit_path_length); - - DCHECK(last_dns_response_); - if (!ParseAuditPath(*last_dns_response_, &proof_)) { - return net::ERR_DNS_MALFORMED_RESPONSE; - } - - // Keep requesting more proof nodes until all of them are received. - if (proof_.nodes.size() < audit_path_length) { - next_state_ = State::REQUEST_AUDIT_PROOF_NODES; - } - - return net::OK; -} - -bool AuditProofQueryImpl::StartDnsTransaction(const std::string& qname) { - net::DnsTransactionFactory* factory = dns_client_->GetTransactionFactory(); - if (!factory) { - return false; - } - - last_dns_response_ = nullptr; - DCHECK(url_request_context_); - current_dns_transaction_ = factory->CreateTransaction( - qname, net::dns_protocol::kTypeTXT, - base::BindOnce(&AuditProofQueryImpl::OnDnsTransactionComplete, - weak_ptr_factory_.GetWeakPtr()), - net_log_, - lookup_securely_ ? net::SecureDnsMode::SECURE : net::SecureDnsMode::OFF, - url_request_context_); - - current_dns_transaction_->Start(); - return true; -} - -LogDnsClient::LogDnsClient(std::unique_ptr<net::DnsClient> dns_client, - net::URLRequestContext* url_request_context, - const net::NetLogWithSource& net_log, - size_t max_in_flight_queries) - : dns_client_(std::move(dns_client)), - url_request_context_(url_request_context), - net_log_(net_log), - in_flight_queries_(0), - max_in_flight_queries_(max_in_flight_queries) { - CHECK(dns_client_); - net::NetworkChangeNotifier::AddDNSObserver(this); - UpdateDnsConfig(); -} - -LogDnsClient::~LogDnsClient() { - net::NetworkChangeNotifier::RemoveDNSObserver(this); -} - -void LogDnsClient::OnDNSChanged() { - UpdateDnsConfig(); -} - -void LogDnsClient::OnInitialDNSConfigRead() { - UpdateDnsConfig(); -} - -void LogDnsClient::NotifyWhenNotThrottled(base::OnceClosure callback) { - DCHECK(HasMaxQueriesInFlight()); - not_throttled_callbacks_.emplace_back(std::move(callback)); -} - -// |leaf_hash| is not a const-ref to allow callers to std::move that string into -// the method, avoiding LogDnsClient::AuditProofQuery having to make a copy. -net::Error LogDnsClient::QueryAuditProof( - base::StringPiece domain_for_log, - std::string leaf_hash, - bool lookup_securely, - uint64_t tree_size, - std::unique_ptr<AuditProofQuery>* out_query, - net::CompletionOnceCallback callback) { - DCHECK(out_query); - - if (domain_for_log.empty() || leaf_hash.size() != crypto::kSHA256Length) { - return net::ERR_INVALID_ARGUMENT; - } - - if (HasMaxQueriesInFlight()) { - return net::ERR_TEMPORARILY_THROTTLED; - } - - auto* query = new AuditProofQueryImpl(dns_client_.get(), url_request_context_, - domain_for_log.as_string(), net_log_); - out_query->reset(query); - - ++in_flight_queries_; - - return query->Start( - std::move(leaf_hash), lookup_securely, tree_size, - base::BindOnce(&LogDnsClient::QueryAuditProofComplete, - base::Unretained(this), std::move(callback)), - base::BindOnce(&LogDnsClient::QueryAuditProofCancelled, - base::Unretained(this))); -} - -void LogDnsClient::QueryAuditProofComplete( - net::CompletionOnceCallback completion_callback, - int net_error) { - --in_flight_queries_; - - // Move the "not throttled" callbacks to a local variable, just in case one of - // the callbacks deletes this LogDnsClient. - std::list<base::OnceClosure> not_throttled_callbacks = - std::move(not_throttled_callbacks_); - - std::move(completion_callback).Run(net_error); - - // Notify interested parties that the next query will not be throttled. - for (auto& callback : not_throttled_callbacks) { - std::move(callback).Run(); - } -} - -void LogDnsClient::QueryAuditProofCancelled() { - --in_flight_queries_; - - // Move not_throttled_callbacks_ to a local variable, just in case one of the - // callbacks deletes this LogDnsClient. - std::list<base::OnceClosure> not_throttled_callbacks = - std::move(not_throttled_callbacks_); - - // Notify interested parties that the next query will not be throttled. - for (auto& callback : not_throttled_callbacks) { - std::move(callback).Run(); - } -} - -bool LogDnsClient::HasMaxQueriesInFlight() const { - return max_in_flight_queries_ != 0 && - in_flight_queries_ >= max_in_flight_queries_; -} - -void LogDnsClient::UpdateDnsConfig() { - net::DnsConfig config; - net::NetworkChangeNotifier::GetDnsConfig(&config); - if (config.IsValid()) - dns_client_->SetConfig(config); - - net::DnsTransactionFactory* factory = dns_client_->GetTransactionFactory(); - if (factory) { - factory->AddEDNSOption(OptToDisableClientSubnetExtension()); - } -} - -} // namespace certificate_transparency
diff --git a/components/certificate_transparency/log_dns_client.h b/components/certificate_transparency/log_dns_client.h deleted file mode 100644 index 091e9873..0000000 --- a/components/certificate_transparency/log_dns_client.h +++ /dev/null
@@ -1,143 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_CERTIFICATE_TRANSPARENCY_LOG_DNS_CLIENT_H_ -#define COMPONENTS_CERTIFICATE_TRANSPARENCY_LOG_DNS_CLIENT_H_ - -#include <stdint.h> - -#include <list> - -#include "base/callback.h" -#include "base/macros.h" -#include "base/single_thread_task_runner.h" -#include "base/strings/string_piece.h" -#include "net/base/completion_once_callback.h" -#include "net/base/net_errors.h" -#include "net/base/network_change_notifier.h" -#include "net/log/net_log_with_source.h" -#include "net/url_request/url_request_context.h" - -namespace net { -class DnsClient; -namespace ct { -struct MerkleAuditProof; -} // namespace ct -} // namespace net - -namespace certificate_transparency { - -// Queries Certificate Transparency (CT) log servers via DNS. -// All queries are performed asynchronously. -// For more information, see -// https://github.com/google/certificate-transparency-rfcs/blob/master/dns/draft-ct-over-dns.md. -// It must be created and deleted on the same thread. It is not thread-safe. -class LogDnsClient : public net::NetworkChangeNotifier::DNSObserver { - public: - class AuditProofQuery { - public: - virtual ~AuditProofQuery() = default; - virtual const net::ct::MerkleAuditProof& GetProof() const = 0; - }; - - // Creates a log client that will take ownership of |dns_client| and use it - // to perform DNS queries. Queries will be logged to |net_log|. - // The |dns_client| does not need to be configured first - this will be done - // automatically as needed. - // A limit can be set on the number of concurrent DNS queries by providing a - // positive value for |max_concurrent_queries|. Queries that would exceed this - // limit will fail with net::TEMPORARILY_THROTTLED. Setting this to 0 will - // disable this limit. - LogDnsClient(std::unique_ptr<net::DnsClient> dns_client, - net::URLRequestContext* url_request_context, - const net::NetLogWithSource& net_log, - size_t max_concurrent_queries); - // Must be deleted on the same thread that it was created on. - ~LogDnsClient() override; - - // Called by NetworkChangeNotifier when the DNS config changes. - // The DnsClient's config will be updated in response. - void OnDNSChanged() override; - - // Called by NetworkChangeNotifier when the DNS config is first read. - // The DnsClient's config will be updated in response. - void OnInitialDNSConfigRead() override; - - // Registers a callback to be invoked when the number of concurrent queries - // falls below the limit defined by |max_concurrent_queries| (passed to the - // constructor of LogDnsClient). This callback will fire once and then be - // unregistered. Should only be used if QueryAuditProof() returns - // net::ERR_TEMPORARILY_THROTTLED. - // The callback will be run on the same thread that created the LogDnsClient. - void NotifyWhenNotThrottled(base::OnceClosure callback); - - // Queries a CT log to retrieve an audit proof for the leaf with |leaf_hash|. - // The log is identified by |domain_for_log|, which is the DNS name used as a - // suffix for all queries. - // The |leaf_hash| is the SHA-256 Merkle leaf hash (see RFC6962, section 2.1). - // The size of the CT log tree, for which the proof is requested, must be - // provided in |tree_size|. - // The field |lookup_securely| specifies whether DNS lookups should be - // performed securely or insecurely. This value should be set according to - // whether the hostname lookup was resolved securely or not in order to - // help achieve resolver consistency between the hostname and proof lookups. - // A handle to the query will be placed in |out_query|. The audit proof can be - // obtained from that once the query completes. Deleting this handle before - // the query completes will cancel it. It must not outlive the LogDnsClient. - // If the proof cannot be obtained synchronously, this method will return - // net::ERR_IO_PENDING and invoke |callback| once the query is complete. - // The callback will be run on the same thread that created the LogDnsClient. - // Returns: - // - net::OK if the query was successful. - // - net::ERR_IO_PENDING if the query was successfully started and is - // continuing asynchronously. - // - net::ERR_TEMPORARILY_THROTTLED if the maximum number of concurrent - // queries are already in progress. Try again later. - // - net::ERR_NAME_RESOLUTION_FAILED if DNS queries are not possible. - // Check that the DnsConfig returned by NetworkChangeNotifier is valid. - // - net::ERR_INVALID_ARGUMENT if an argument is invalid, e.g. |leaf_hash| is - // not a SHA-256 hash. - net::Error QueryAuditProof(base::StringPiece domain_for_log, - std::string leaf_hash, - bool lookup_securely, - uint64_t tree_size, - std::unique_ptr<AuditProofQuery>* out_query, - net::CompletionOnceCallback callback); - - private: - // Invoked when an audit proof query completes. - // |callback| is the user-provided callback that should be notified. - // |net_error| is a net::Error indicating success or failure. - void QueryAuditProofComplete(net::CompletionOnceCallback callback, - int net_error); - - // Invoked when an audit proof query is cancelled. - void QueryAuditProofCancelled(); - - // Returns true if the maximum number of queries are currently in-flight. - // If the maximum number of in-flight queries is set to 0, this will always - // return false. - bool HasMaxQueriesInFlight() const; - - // Updates the |dns_client_| config using NetworkChangeNotifier. - void UpdateDnsConfig(); - - // Used to perform DNS queries. - std::unique_ptr<net::DnsClient> dns_client_; - // Used to perform DoH queries. - net::URLRequestContext* url_request_context_; - // Passed to the DNS client for logging. - net::NetLogWithSource net_log_; - // The number of queries that are currently in-flight. - size_t in_flight_queries_; - // The maximum number of queries that can be in-flight at one time. - size_t max_in_flight_queries_; - // Callbacks to invoke when the number of in-flight queries is at its limit. - std::list<base::OnceClosure> not_throttled_callbacks_; - - DISALLOW_COPY_AND_ASSIGN(LogDnsClient); -}; - -} // namespace certificate_transparency -#endif // COMPONENTS_CERTIFICATE_TRANSPARENCY_LOG_DNS_CLIENT_H_
diff --git a/components/certificate_transparency/log_dns_client_unittest.cc b/components/certificate_transparency/log_dns_client_unittest.cc deleted file mode 100644 index 10d4a96f..0000000 --- a/components/certificate_transparency/log_dns_client_unittest.cc +++ /dev/null
@@ -1,1101 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/certificate_transparency/log_dns_client.h" - -#include <memory> -#include <numeric> -#include <string> -#include <utility> -#include <vector> - -#include "base/format_macros.h" -#include "base/run_loop.h" -#include "base/stl_util.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" -#include "base/test/metrics/histogram_tester.h" -#include "base/test/scoped_task_environment.h" -#include "base/test/test_timeouts.h" -#include "components/certificate_transparency/mock_log_dns_traffic.h" -#include "crypto/sha2.h" -#include "net/base/net_errors.h" -#include "net/cert/merkle_audit_proof.h" -#include "net/cert/signed_certificate_timestamp.h" -#include "net/dns/dns_client.h" -#include "net/dns/dns_config.h" -#include "net/dns/dns_test_util.h" -#include "net/dns/public/dns_protocol.h" -#include "net/log/net_log.h" -#include "net/test/gtest_util.h" -#include "net/url_request/url_request_filter.h" -#include "net/url_request/url_request_test_util.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace certificate_transparency { -namespace { - -using net::test::IsError; -using net::test::IsOk; -using ::testing::AllOf; -using ::testing::Eq; -using ::testing::IsEmpty; -using ::testing::Le; -using ::testing::Not; -using ::testing::NotNull; - -// Histogram names. -const char kLeafIndexErrorHistogram[] = - "Net.CertificateTransparency.DnsQueryLeafIndexError"; -const char kLeafIndexRcodeHistogram[] = - "Net.CertificateTransparency.DnsQueryLeafIndexRcode"; -const char kAuditProofErrorHistogram[] = - "Net.CertificateTransparency.DnsQueryAuditProofError"; -const char kAuditProofRcodeHistogram[] = - "Net.CertificateTransparency.DnsQueryAuditProofRcode"; - -// Sample Merkle leaf hashes. -const char* const kLeafHashes[] = { - "\x1f\x25\xe1\xca\xba\x4f\xf9\xb8\x27\x24\x83\x0f\xca\x60\xe4\xc2\xbe\xa8" - "\xc3\xa9\x44\x1c\x27\xb0\xb4\x3e\x6a\x96\x94\xc7\xb8\x04", - "\x2c\x26\xb4\x6b\x68\xff\xc6\x8f\xf9\x9b\x45\x3c\x1d\x30\x41\x34\x13\x42" - "\x2d\x70\x64\x83\xbf\xa0\xf9\x8a\x5e\x88\x62\x66\xe7\xae", - "\xfc\xde\x2b\x2e\xdb\xa5\x6b\xf4\x08\x60\x1f\xb7\x21\xfe\x9b\x5c\x33\x8d" - "\x10\xee\x42\x9e\xa0\x4f\xae\x55\x11\xb6\x8f\xbf\x8f\xb9", -}; - -// DNS query names for looking up the leaf index associated with each hash in -// |kLeafHashes|. Assumes the log domain is "ct.test". -const char* const kLeafIndexQnames[] = { - "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", - "FQTLI23I77DI76M3IU6B2MCBGQJUELLQMSB37IHZRJPIQYTG46XA.hash.ct.test.", - "7TPCWLW3UVV7ICDAD63SD7U3LQZY2EHOIKPKAT5OKUI3ND57R64Q.hash.ct.test.", -}; - -// Leaf indices and tree sizes for use with |kLeafHashes|. -const uint64_t kLeafIndices[] = {0, 1, 2}; -const uint64_t kTreeSizes[] = {100, 10000, 1000000}; - -// Only 7 audit proof nodes can fit into a DNS response, because they are sent -// in a TXT RDATA string, which has a maximum size of 255 bytes, and each node -// is a SHA-256 hash (32 bytes), i.e. (255 / 32) == 7. -// This means audit proofs consisting of more than 7 nodes require multiple DNS -// requests to retrieve. -const size_t kMaxProofNodesPerDnsResponse = 7; - -// Returns an example Merkle audit proof containing |length| nodes. -// The proof cannot be used for cryptographic purposes; it is merely a -// placeholder. -std::vector<std::string> GetSampleAuditProof(size_t length) { - std::vector<std::string> audit_proof(length); - // Makes each node of the audit proof different, so that tests are able to - // confirm that the audit proof is reconstructed in the correct order. - for (size_t i = 0; i < length; ++i) { - std::string node(crypto::kSHA256Length, '\0'); - // Each node is 32 bytes, with each byte having a different value. - for (size_t j = 0; j < crypto::kSHA256Length; ++j) { - node[j] = static_cast<char>((-127 + i + j) % 128); - } - audit_proof[i].assign(std::move(node)); - } - - return audit_proof; -} - -} // namespace - -class LogDnsClientTest : public ::testing::TestWithParam<net::IoMode> { - void SetUp() override { - net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance(); - filter->AddHostnameInterceptor( - "https", "mock.http", - std::make_unique<MockLogDnsTraffic::DohJobInterceptor>()); - } - - void TearDown() override { - net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance(); - filter->ClearHandlers(); - } - - protected: - LogDnsClientTest() - : network_change_notifier_(net::NetworkChangeNotifier::CreateMock()) { - mock_dns_.SetSocketReadMode(GetParam()); - mock_dns_.InitializeDnsConfig(); - } - - std::unique_ptr<LogDnsClient> CreateLogDnsClient( - size_t max_concurrent_queries) { - return std::make_unique<LogDnsClient>( - mock_dns_.CreateDnsClient(), new net::TestURLRequestContext(), - net::NetLogWithSource(), max_concurrent_queries); - } - - std::unique_ptr<LogDnsClient> CreateRuleBasedLogDnsClient( - net::MockDnsClientRuleList rules) { - return std::make_unique<LogDnsClient>( - std::make_unique<net::MockDnsClient>(net::DnsConfig(), - std::move(rules)), - new net::TestURLRequestContext(), net::NetLogWithSource(), 0); - } - - // Convenience function for calling QueryAuditProof synchronously. - template <typename... Types> - net::Error QueryAuditProof(Types&&... args) { - std::unique_ptr<LogDnsClient> log_client = CreateLogDnsClient(0); - net::TestCompletionCallback callback; - const net::Error result = log_client->QueryAuditProof( - std::forward<Types>(args)..., callback.callback()); - - return result != net::ERR_IO_PENDING - ? result - : static_cast<net::Error>(callback.WaitForResult()); - } - - // This will be the NetworkChangeNotifier singleton for the duration of the - // test. It is accessed statically by LogDnsClient. - std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_; - // Queues and handles asynchronous DNS tasks. Indirectly used by LogDnsClient, - // the underlying net::DnsClient, and NetworkChangeNotifier. - base::test::ScopedTaskEnvironment task_environment_{ - base::test::ScopedTaskEnvironment::MainThreadType::IO}; - // Allows mock DNS sockets to be setup. - MockLogDnsTraffic mock_dns_; - // Tests that histograms are populated as expected. - base::HistogramTester histograms_; -}; - -TEST_P(LogDnsClientTest, QueryAuditProofReportsThatLogDomainDoesNotExist) { - ASSERT_TRUE(mock_dns_.ExpectRequestAndErrorResponse( - kLeafIndexQnames[0], net::dns_protocol::kRcodeNXDOMAIN)); - - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT( - QueryAuditProof("ct.test", kLeafHashes[0], false /* lookup_securely */, - kTreeSizes[0], &query), - IsError(net::ERR_NAME_NOT_RESOLVED)); - histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, - -net::ERR_NAME_NOT_RESOLVED, 1); - histograms_.ExpectUniqueSample(kLeafIndexRcodeHistogram, - net::dns_protocol::kRcodeNXDOMAIN, 1); - histograms_.ExpectTotalCount(kAuditProofErrorHistogram, 0); - histograms_.ExpectTotalCount(kAuditProofRcodeHistogram, 0); -} - -TEST_P(LogDnsClientTest, - QueryAuditProofReportsServerFailuresDuringLeafIndexRequests) { - ASSERT_TRUE(mock_dns_.ExpectRequestAndErrorResponse( - kLeafIndexQnames[0], net::dns_protocol::kRcodeSERVFAIL)); - - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT( - QueryAuditProof("ct.test", kLeafHashes[0], false /* lookup_securely */, - kTreeSizes[0], &query), - IsError(net::ERR_DNS_SERVER_FAILED)); - histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, - -net::ERR_DNS_SERVER_FAILED, 1); - histograms_.ExpectUniqueSample(kLeafIndexRcodeHistogram, - net::dns_protocol::kRcodeSERVFAIL, 1); - histograms_.ExpectTotalCount(kAuditProofErrorHistogram, 0); - histograms_.ExpectTotalCount(kAuditProofRcodeHistogram, 0); -} - -TEST_P(LogDnsClientTest, - QueryAuditProofReportsServerRefusalsDuringLeafIndexRequests) { - ASSERT_TRUE(mock_dns_.ExpectRequestAndErrorResponse( - kLeafIndexQnames[0], net::dns_protocol::kRcodeREFUSED)); - - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT( - QueryAuditProof("ct.test", kLeafHashes[0], false /* lookup_securely */, - kTreeSizes[0], &query), - IsError(net::ERR_DNS_SERVER_FAILED)); - histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, - -net::ERR_DNS_SERVER_FAILED, 1); - histograms_.ExpectUniqueSample(kLeafIndexRcodeHistogram, - net::dns_protocol::kRcodeREFUSED, 1); - histograms_.ExpectTotalCount(kAuditProofErrorHistogram, 0); - histograms_.ExpectTotalCount(kAuditProofRcodeHistogram, 0); -} - -TEST_P(LogDnsClientTest, QueryAuditProofReportsMalformedLeafIndexResponse) { - const struct { - std::string name; - std::vector<base::StringPiece> txt_strings; - } tests[] = {{"contains no strings", {}}, - {"contains more than one string", {"123456", "7"}}, - {"is not numeric", {"foo"}}, - {"is floating point", {"123456.0"}}, - {"is empty"}, - {"has non-numeric prefix", {"foo123456"}}, - {"has non-numeric suffix", {"123456foo"}}}; - - for (auto test : tests) { - SCOPED_TRACE(test.name); - base::HistogramTester histograms; - - ASSERT_TRUE(mock_dns_.ExpectRequestAndResponse(kLeafIndexQnames[0], - test.txt_strings)); - - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT( - QueryAuditProof("ct.test", kLeafHashes[0], false /* lookup_securely */, - kTreeSizes[0], &query), - IsError(net::ERR_DNS_MALFORMED_RESPONSE)); - histograms.ExpectUniqueSample(kLeafIndexErrorHistogram, - -net::ERR_DNS_MALFORMED_RESPONSE, 1); - histograms.ExpectUniqueSample(kLeafIndexRcodeHistogram, - net::dns_protocol::kRcodeNOERROR, 1); - histograms_.ExpectTotalCount(kAuditProofErrorHistogram, 0); - histograms_.ExpectTotalCount(kAuditProofRcodeHistogram, 0); - } -} - -TEST_P(LogDnsClientTest, QueryAuditProofReportsInvalidArgIfLogDomainIsEmpty) { - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("", kLeafHashes[0], false /* lookup_securely */, - kTreeSizes[0], &query), - IsError(net::ERR_INVALID_ARGUMENT)); -} - -TEST_P(LogDnsClientTest, QueryAuditProofReportsInvalidArgIfLeafHashIsInvalid) { - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", "foo", false /* lookup_securely */, - kTreeSizes[0], &query), - IsError(net::ERR_INVALID_ARGUMENT)); -} - -TEST_P(LogDnsClientTest, QueryAuditProofReportsInvalidArgIfLeafHashIsEmpty) { - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", "", false /* lookup_securely */, - kTreeSizes[0], &query), - IsError(net::ERR_INVALID_ARGUMENT)); -} - -TEST_P(LogDnsClientTest, - QueryAuditProofReportsSocketErrorsDuringLeafIndexRequests) { - ASSERT_TRUE(mock_dns_.ExpectRequestAndSocketError( - kLeafIndexQnames[0], net::ERR_CONNECTION_REFUSED)); - - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT( - QueryAuditProof("ct.test", kLeafHashes[0], false /* lookup_securely */, - kTreeSizes[0], &query), - IsError(net::ERR_CONNECTION_REFUSED)); - histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, - -net::ERR_CONNECTION_REFUSED, 1); - histograms_.ExpectTotalCount(kLeafIndexRcodeHistogram, 0); - histograms_.ExpectTotalCount(kAuditProofErrorHistogram, 0); - histograms_.ExpectTotalCount(kAuditProofRcodeHistogram, 0); -} - -TEST_P(LogDnsClientTest, - QueryAuditProofReportsTimeoutsDuringLeafIndexRequests) { - ASSERT_TRUE(mock_dns_.ExpectRequestAndTimeout(kLeafIndexQnames[0])); - - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT( - QueryAuditProof("ct.test", kLeafHashes[0], false /* lookup_securely */, - kTreeSizes[0], &query), - IsError(net::ERR_DNS_TIMED_OUT)); - histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, - -net::ERR_DNS_TIMED_OUT, 1); - histograms_.ExpectTotalCount(kLeafIndexRcodeHistogram, 0); - histograms_.ExpectTotalCount(kAuditProofErrorHistogram, 0); - histograms_.ExpectTotalCount(kAuditProofRcodeHistogram, 0); -} - -TEST_P(LogDnsClientTest, QueryAuditProof) { - const std::vector<std::string> audit_proof = GetSampleAuditProof(20); - - // Expect a leaf index query first, to map the leaf hash to a leaf index. - ASSERT_TRUE( - mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456)); - - // It takes a number of DNS requests to retrieve the entire |audit_proof| - // (see |kMaxProofNodesPerDnsResponse|). - for (size_t nodes_begin = 0; nodes_begin < audit_proof.size(); - nodes_begin += kMaxProofNodesPerDnsResponse) { - const size_t nodes_end = std::min( - nodes_begin + kMaxProofNodesPerDnsResponse, audit_proof.size()); - - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - base::StringPrintf("%zu.123456.999999.tree.ct.test.", nodes_begin), - audit_proof.begin() + nodes_begin, audit_proof.begin() + nodes_end)); - } - - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], - false /* lookup_securely */, 999999, &query), - IsOk()); - const net::ct::MerkleAuditProof& proof = query->GetProof(); - EXPECT_THAT(proof.leaf_index, Eq(123456u)); - EXPECT_THAT(proof.tree_size, Eq(999999u)); - EXPECT_THAT(proof.nodes, Eq(audit_proof)); - - histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::OK, 1); - histograms_.ExpectUniqueSample(kLeafIndexRcodeHistogram, - net::dns_protocol::kRcodeNOERROR, 1); - histograms_.ExpectUniqueSample(kAuditProofErrorHistogram, -net::OK, 1); - histograms_.ExpectUniqueSample(kAuditProofRcodeHistogram, - net::dns_protocol::kRcodeNOERROR, 1); -} - -TEST_P(LogDnsClientTest, QueryAuditProofHandlesResponsesWithShortAuditPaths) { - const std::vector<std::string> audit_proof = GetSampleAuditProof(20); - - // Expect a leaf index query first, to map the leaf hash to a leaf index. - ASSERT_TRUE( - mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456)); - - // Make some of the responses contain fewer proof nodes than they can hold. - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - "0.123456.999999.tree.ct.test.", audit_proof.begin(), - audit_proof.begin() + 1)); - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - "1.123456.999999.tree.ct.test.", audit_proof.begin() + 1, - audit_proof.begin() + 3)); - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - "3.123456.999999.tree.ct.test.", audit_proof.begin() + 3, - audit_proof.begin() + 6)); - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - "6.123456.999999.tree.ct.test.", audit_proof.begin() + 6, - audit_proof.begin() + 10)); - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - "10.123456.999999.tree.ct.test.", audit_proof.begin() + 10, - audit_proof.begin() + 13)); - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - "13.123456.999999.tree.ct.test.", audit_proof.begin() + 13, - audit_proof.end())); - - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], - false /* lookup_securely */, 999999, &query), - IsOk()); - const net::ct::MerkleAuditProof& proof = query->GetProof(); - EXPECT_THAT(proof.leaf_index, Eq(123456u)); - EXPECT_THAT(proof.tree_size, Eq(999999u)); - EXPECT_THAT(proof.nodes, Eq(audit_proof)); - - histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::OK, 1); - histograms_.ExpectUniqueSample(kLeafIndexRcodeHistogram, - net::dns_protocol::kRcodeNOERROR, 1); - histograms_.ExpectUniqueSample(kAuditProofErrorHistogram, -net::OK, 1); - histograms_.ExpectUniqueSample(kAuditProofRcodeHistogram, - net::dns_protocol::kRcodeNOERROR, 1); -} - -TEST_P(LogDnsClientTest, - QueryAuditProofReportsThatAuditProofQnameDoesNotExist) { - ASSERT_TRUE( - mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456)); - ASSERT_TRUE(mock_dns_.ExpectRequestAndErrorResponse( - "0.123456.999999.tree.ct.test.", net::dns_protocol::kRcodeNXDOMAIN)); - - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], - false /* lookup_securely */, 999999, &query), - IsError(net::ERR_NAME_NOT_RESOLVED)); - - histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::OK, 1); - histograms_.ExpectUniqueSample(kLeafIndexRcodeHistogram, - net::dns_protocol::kRcodeNOERROR, 1); - histograms_.ExpectUniqueSample(kAuditProofErrorHistogram, - -net::ERR_NAME_NOT_RESOLVED, 1); - histograms_.ExpectUniqueSample(kAuditProofRcodeHistogram, - net::dns_protocol::kRcodeNXDOMAIN, 1); -} - -TEST_P(LogDnsClientTest, - QueryAuditProofReportsServerFailuresDuringAuditProofRequests) { - ASSERT_TRUE( - mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456)); - ASSERT_TRUE(mock_dns_.ExpectRequestAndErrorResponse( - "0.123456.999999.tree.ct.test.", net::dns_protocol::kRcodeSERVFAIL)); - - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], - false /* lookup_securely */, 999999, &query), - IsError(net::ERR_DNS_SERVER_FAILED)); - - histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::OK, 1); - histograms_.ExpectUniqueSample(kLeafIndexRcodeHistogram, - net::dns_protocol::kRcodeNOERROR, 1); - histograms_.ExpectUniqueSample(kAuditProofErrorHistogram, - -net::ERR_DNS_SERVER_FAILED, 1); - histograms_.ExpectUniqueSample(kAuditProofRcodeHistogram, - net::dns_protocol::kRcodeSERVFAIL, 1); -} - -TEST_P(LogDnsClientTest, - QueryAuditProofReportsServerRefusalsDuringAuditProofRequests) { - ASSERT_TRUE( - mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456)); - ASSERT_TRUE(mock_dns_.ExpectRequestAndErrorResponse( - "0.123456.999999.tree.ct.test.", net::dns_protocol::kRcodeREFUSED)); - - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], - false /* lookup_securely */, 999999, &query), - IsError(net::ERR_DNS_SERVER_FAILED)); - - histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::OK, 1); - histograms_.ExpectUniqueSample(kLeafIndexRcodeHistogram, - net::dns_protocol::kRcodeNOERROR, 1); - histograms_.ExpectUniqueSample(kAuditProofErrorHistogram, - -net::ERR_DNS_SERVER_FAILED, 1); - histograms_.ExpectUniqueSample(kAuditProofRcodeHistogram, - net::dns_protocol::kRcodeREFUSED, 1); -} - -TEST_P( - LogDnsClientTest, - QueryAuditProofReportsResponseMalformedIfProofNodesResponseContainsNoStrings) { - // Expect a leaf index query first, to map the leaf hash to a leaf index. - ASSERT_TRUE( - mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456)); - - ASSERT_TRUE(mock_dns_.ExpectRequestAndResponse( - "0.123456.999999.tree.ct.test.", std::vector<base::StringPiece>())); - - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], - false /* lookup_securely */, 999999, &query), - IsError(net::ERR_DNS_MALFORMED_RESPONSE)); - - histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::OK, 1); - histograms_.ExpectUniqueSample(kLeafIndexRcodeHistogram, - net::dns_protocol::kRcodeNOERROR, 1); - histograms_.ExpectUniqueSample(kAuditProofErrorHistogram, - -net::ERR_DNS_MALFORMED_RESPONSE, 1); - histograms_.ExpectUniqueSample(kAuditProofRcodeHistogram, - net::dns_protocol::kRcodeNOERROR, 1); -} - -TEST_P( - LogDnsClientTest, - QueryAuditProofReportsResponseMalformedIfProofNodesResponseContainsMoreThanOneString) { - // The CT-over-DNS draft RFC states that the response will contain "exactly - // one character-string." - const std::vector<std::string> audit_proof = GetSampleAuditProof(10); - - std::string first_chunk_of_proof = std::accumulate( - audit_proof.begin(), audit_proof.begin() + 7, std::string()); - std::string second_chunk_of_proof = std::accumulate( - audit_proof.begin() + 7, audit_proof.end(), std::string()); - - // Expect a leaf index query first, to map the leaf hash to a leaf index. - ASSERT_TRUE( - mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456)); - - ASSERT_TRUE(mock_dns_.ExpectRequestAndResponse( - "0.123456.999999.tree.ct.test.", - {first_chunk_of_proof, second_chunk_of_proof})); - - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], - false /* lookup_securely */, 999999, &query), - IsError(net::ERR_DNS_MALFORMED_RESPONSE)); - - histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::OK, 1); - histograms_.ExpectUniqueSample(kLeafIndexRcodeHistogram, - net::dns_protocol::kRcodeNOERROR, 1); - histograms_.ExpectUniqueSample(kAuditProofErrorHistogram, - -net::ERR_DNS_MALFORMED_RESPONSE, 1); - histograms_.ExpectUniqueSample(kAuditProofRcodeHistogram, - net::dns_protocol::kRcodeNOERROR, 1); -} - -TEST_P(LogDnsClientTest, - QueryAuditProofReportsResponseMalformedIfNodeTooShort) { - // node is shorter than a SHA-256 hash (31 vs 32 bytes) - const std::vector<std::string> audit_proof(1, std::string(31, 'a')); - - ASSERT_TRUE( - mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456)); - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - "0.123456.999999.tree.ct.test.", audit_proof.begin(), audit_proof.end())); - - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], - false /* lookup_securely */, 999999, &query), - IsError(net::ERR_DNS_MALFORMED_RESPONSE)); - - histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::OK, 1); - histograms_.ExpectUniqueSample(kLeafIndexRcodeHistogram, - net::dns_protocol::kRcodeNOERROR, 1); - histograms_.ExpectUniqueSample(kAuditProofErrorHistogram, - -net::ERR_DNS_MALFORMED_RESPONSE, 1); - histograms_.ExpectUniqueSample(kAuditProofRcodeHistogram, - net::dns_protocol::kRcodeNOERROR, 1); -} - -TEST_P(LogDnsClientTest, QueryAuditProofReportsResponseMalformedIfNodeTooLong) { - // node is longer than a SHA-256 hash (33 vs 32 bytes) - const std::vector<std::string> audit_proof(1, std::string(33, 'a')); - - ASSERT_TRUE( - mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456)); - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - "0.123456.999999.tree.ct.test.", audit_proof.begin(), audit_proof.end())); - - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], - false /* lookup_securely */, 999999, &query), - IsError(net::ERR_DNS_MALFORMED_RESPONSE)); - - histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::OK, 1); - histograms_.ExpectUniqueSample(kLeafIndexRcodeHistogram, - net::dns_protocol::kRcodeNOERROR, 1); - histograms_.ExpectUniqueSample(kAuditProofErrorHistogram, - -net::ERR_DNS_MALFORMED_RESPONSE, 1); - histograms_.ExpectUniqueSample(kAuditProofRcodeHistogram, - net::dns_protocol::kRcodeNOERROR, 1); -} - -TEST_P(LogDnsClientTest, QueryAuditProofReportsResponseMalformedIfEmpty) { - const std::vector<std::string> audit_proof; - - ASSERT_TRUE( - mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456)); - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - "0.123456.999999.tree.ct.test.", audit_proof.begin(), audit_proof.end())); - - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], - false /* lookup_securely */, 999999, &query), - IsError(net::ERR_DNS_MALFORMED_RESPONSE)); - - histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::OK, 1); - histograms_.ExpectUniqueSample(kLeafIndexRcodeHistogram, - net::dns_protocol::kRcodeNOERROR, 1); - histograms_.ExpectUniqueSample(kAuditProofErrorHistogram, - -net::ERR_DNS_MALFORMED_RESPONSE, 1); - histograms_.ExpectUniqueSample(kAuditProofRcodeHistogram, - net::dns_protocol::kRcodeNOERROR, 1); -} - -TEST_P(LogDnsClientTest, - QueryAuditProofReportsInvalidArgIfLeafIndexEqualToTreeSize) { - ASSERT_TRUE( - mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456)); - - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], - false /* lookup_securely */, 123456, &query), - IsError(net::ERR_INVALID_ARGUMENT)); -} - -TEST_P(LogDnsClientTest, - QueryAuditProofReportsInvalidArgIfLeafIndexGreaterThanTreeSize) { - ASSERT_TRUE( - mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 999999)); - - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], - false /* lookup_securely */, 123456, &query), - IsError(net::ERR_INVALID_ARGUMENT)); -} - -TEST_P(LogDnsClientTest, - QueryAuditProofReportsSocketErrorsDuringAuditProofRequests) { - ASSERT_TRUE( - mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456)); - ASSERT_TRUE(mock_dns_.ExpectRequestAndSocketError( - "0.123456.999999.tree.ct.test.", net::ERR_CONNECTION_REFUSED)); - - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], - false /* lookup_securely */, 999999, &query), - IsError(net::ERR_CONNECTION_REFUSED)); - - histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::OK, 1); - histograms_.ExpectUniqueSample(kLeafIndexRcodeHistogram, - net::dns_protocol::kRcodeNOERROR, 1); - histograms_.ExpectUniqueSample(kAuditProofErrorHistogram, - -net::ERR_CONNECTION_REFUSED, 1); - histograms_.ExpectTotalCount(kAuditProofRcodeHistogram, 0); -} - -TEST_P(LogDnsClientTest, - QueryAuditProofReportsTimeoutsDuringAuditProofRequests) { - ASSERT_TRUE( - mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456)); - ASSERT_TRUE( - mock_dns_.ExpectRequestAndTimeout("0.123456.999999.tree.ct.test.")); - - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], - false /* lookup_securely */, 999999, &query), - IsError(net::ERR_DNS_TIMED_OUT)); - - histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::OK, 1); - histograms_.ExpectUniqueSample(kLeafIndexRcodeHistogram, - net::dns_protocol::kRcodeNOERROR, 1); - histograms_.ExpectUniqueSample(kAuditProofErrorHistogram, - -net::ERR_DNS_TIMED_OUT, 1); - histograms_.ExpectTotalCount(kAuditProofRcodeHistogram, 0); -} - -TEST_P(LogDnsClientTest, AdoptsLatestDnsConfigIfValid) { - std::unique_ptr<net::DnsClient> tmp = mock_dns_.CreateDnsClient(); - net::DnsClient* dns_client = tmp.get(); - LogDnsClient log_client(std::move(tmp), new net::TestURLRequestContext(), - net::NetLogWithSource(), 0); - - // Get the current DNS config, modify it and broadcast the update. - net::DnsConfig config(*dns_client->GetConfig()); - ASSERT_NE(123, config.attempts); - config.attempts = 123; - mock_dns_.SetDnsConfig(config); - - // Let the DNS config change propogate. - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(123, dns_client->GetConfig()->attempts); -} - -TEST_P(LogDnsClientTest, IgnoresLatestDnsConfigIfInvalid) { - std::unique_ptr<net::DnsClient> tmp = mock_dns_.CreateDnsClient(); - net::DnsClient* dns_client = tmp.get(); - LogDnsClient log_client(std::move(tmp), new net::TestURLRequestContext(), - net::NetLogWithSource(), 0); - - // Get the current DNS config, modify it and broadcast the update. - net::DnsConfig config(*dns_client->GetConfig()); - ASSERT_THAT(config.nameservers, Not(IsEmpty())); - config.nameservers.clear(); // Makes config invalid - mock_dns_.SetDnsConfig(config); - - // Let the DNS config change propogate. - base::RunLoop().RunUntilIdle(); - EXPECT_THAT(dns_client->GetConfig()->nameservers, Not(IsEmpty())); -} - -// Test that changes to the DNS config after starting a query are adopted and -// that the query is not disrupted. -TEST_P(LogDnsClientTest, AdoptsLatestDnsConfigMidQuery) { - const std::vector<std::string> audit_proof = GetSampleAuditProof(20); - - // Expect a leaf index query first, to map the leaf hash to a leaf index. - ASSERT_TRUE( - mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456)); - - // It takes a number of DNS requests to retrieve the entire |audit_proof| - // (see |kMaxProofNodesPerDnsResponse|). - for (size_t nodes_begin = 0; nodes_begin < audit_proof.size(); - nodes_begin += kMaxProofNodesPerDnsResponse) { - const size_t nodes_end = std::min( - nodes_begin + kMaxProofNodesPerDnsResponse, audit_proof.size()); - - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - base::StringPrintf("%zu.123456.999999.tree.ct.test.", nodes_begin), - audit_proof.begin() + nodes_begin, audit_proof.begin() + nodes_end)); - } - - std::unique_ptr<net::DnsClient> tmp = mock_dns_.CreateDnsClient(); - net::DnsClient* dns_client = tmp.get(); - LogDnsClient log_client(std::move(tmp), new net::TestURLRequestContext(), - net::NetLogWithSource(), 0); - - // Start query. - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - net::TestCompletionCallback callback; - ASSERT_THAT(log_client.QueryAuditProof("ct.test", kLeafHashes[0], - false /* lookup_securely */, 999999, - &query, callback.callback()), - IsError(net::ERR_IO_PENDING)); - - // Get the current DNS config, modify it and publish the update. - // The new config is distributed asynchronously via NetworkChangeNotifier. - net::DnsConfig config(*dns_client->GetConfig()); - ASSERT_NE(123, config.attempts); - config.attempts = 123; - mock_dns_.SetDnsConfig(config); - // The new config is distributed asynchronously via NetworkChangeNotifier. - // Config change shouldn't have taken effect yet. - ASSERT_NE(123, dns_client->GetConfig()->attempts); - - // Wait for the query to complete, then check that it was successful. - // The DNS config should be updated during this time. - ASSERT_THAT(callback.WaitForResult(), IsOk()); - const net::ct::MerkleAuditProof& proof = query->GetProof(); - EXPECT_THAT(proof.leaf_index, Eq(123456u)); - EXPECT_THAT(proof.tree_size, Eq(999999u)); - EXPECT_THAT(proof.nodes, Eq(audit_proof)); - - // Check that the DNS config change was adopted. - ASSERT_EQ(123, dns_client->GetConfig()->attempts); -} - -TEST_P(LogDnsClientTest, CanPerformQueriesInParallel) { - // Check that 3 queries can be performed in parallel. - constexpr size_t kNumOfParallelQueries = 3; - ASSERT_THAT(kNumOfParallelQueries, - AllOf(Le(base::size(kLeafIndexQnames)), - Le(base::size(kLeafIndices)), Le(base::size(kTreeSizes)))) - << "Not enough test data for this many parallel queries"; - - std::unique_ptr<LogDnsClient> log_client = - CreateLogDnsClient(kNumOfParallelQueries); - net::TestCompletionCallback callbacks[kNumOfParallelQueries]; - - // Expect multiple leaf index requests. - for (size_t i = 0; i < kNumOfParallelQueries; ++i) { - ASSERT_TRUE(mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[i], - kLeafIndices[i])); - } - - // Make each query require one more audit proof request than the last, by - // increasing the number of nodes in the audit proof by - // kMaxProofNodesPerDnsResponse for each query. This helps to test that - // parallel queries do not intefere with each other, e.g. one query causing - // another to end prematurely. - std::vector<std::string> audit_proofs[kNumOfParallelQueries]; - for (size_t query_i = 0; query_i < kNumOfParallelQueries; ++query_i) { - const size_t dns_requests_required = query_i + 1; - audit_proofs[query_i] = GetSampleAuditProof(dns_requests_required * - kMaxProofNodesPerDnsResponse); - } - // The most DNS requests that are made by any of the above N queries is N. - const size_t kMaxDnsRequestsPerQuery = kNumOfParallelQueries; - - // Setup expectations for up to N DNS requests per query performed. - // All of the queries will be started at the same time, so expect the DNS - // requests and responses to be interleaved. - // NB: - // Ideally, the tests wouldn't require that the DNS requests sent by the - // parallel queries are interleaved. However, the mock socket framework does - // not provide a way to express this. - for (size_t dns_req_i = 0; dns_req_i < kMaxDnsRequestsPerQuery; ++dns_req_i) { - for (size_t query_i = 0; query_i < kNumOfParallelQueries; ++query_i) { - const std::vector<std::string>& proof = audit_proofs[query_i]; - // Closed-open range of |proof| nodes that are expected in this response. - const size_t start_node = dns_req_i * 7; - const size_t end_node = - std::min(start_node + kMaxProofNodesPerDnsResponse, proof.size()); - - // If there are any nodes left, expect another request and response. - if (start_node < end_node) { - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - base::StringPrintf("%zu.%" PRIu64 ".%" PRIu64 ".tree.ct.test.", - start_node, kLeafIndices[query_i], - kTreeSizes[query_i]), - proof.begin() + start_node, proof.begin() + end_node)); - } - } - } - - std::unique_ptr<LogDnsClient::AuditProofQuery> queries[kNumOfParallelQueries]; - - // Start the queries. - for (size_t i = 0; i < kNumOfParallelQueries; ++i) { - ASSERT_THAT(log_client->QueryAuditProof( - "ct.test", kLeafHashes[i], false /* lookup_securely */, - kTreeSizes[i], &queries[i], callbacks[i].callback()), - IsError(net::ERR_IO_PENDING)) - << "query #" << i; - } - - // Wait for each query to complete and check its results. - for (size_t i = 0; i < kNumOfParallelQueries; ++i) { - net::TestCompletionCallback& callback = callbacks[i]; - - SCOPED_TRACE(testing::Message() << "callbacks[" << i << "]"); - EXPECT_THAT(callback.WaitForResult(), IsOk()); - const net::ct::MerkleAuditProof& proof = queries[i]->GetProof(); - EXPECT_THAT(proof.leaf_index, Eq(kLeafIndices[i])); - EXPECT_THAT(proof.tree_size, Eq(kTreeSizes[i])); - EXPECT_THAT(proof.nodes, Eq(audit_proofs[i])); - } - - histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::OK, 3); - histograms_.ExpectUniqueSample(kLeafIndexRcodeHistogram, - net::dns_protocol::kRcodeNOERROR, 3); - histograms_.ExpectUniqueSample(kAuditProofErrorHistogram, -net::OK, 3); - histograms_.ExpectUniqueSample(kAuditProofRcodeHistogram, - net::dns_protocol::kRcodeNOERROR, 3); -} - -TEST_P(LogDnsClientTest, CanBeThrottledToOneQueryAtATime) { - // Check that queries can be rate-limited to one at a time. - // The second query, initiated while the first is in progress, should fail. - const std::vector<std::string> audit_proof = GetSampleAuditProof(20); - - // Expect the first query to send leaf index and audit proof requests, but the - // second should not due to throttling. - ASSERT_TRUE( - mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456)); - - // It takes a number of DNS requests to retrieve the entire |audit_proof| - // (see |kMaxProofNodesPerDnsResponse|). - for (size_t nodes_begin = 0; nodes_begin < audit_proof.size(); - nodes_begin += kMaxProofNodesPerDnsResponse) { - const size_t nodes_end = std::min( - nodes_begin + kMaxProofNodesPerDnsResponse, audit_proof.size()); - - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - base::StringPrintf("%zu.123456.999999.tree.ct.test.", nodes_begin), - audit_proof.begin() + nodes_begin, audit_proof.begin() + nodes_end)); - } - - const size_t kMaxConcurrentQueries = 1; - std::unique_ptr<LogDnsClient> log_client = - CreateLogDnsClient(kMaxConcurrentQueries); - - // Try to start the queries. - std::unique_ptr<LogDnsClient::AuditProofQuery> query1; - net::TestCompletionCallback callback1; - ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[0], - false /* lookup_securely */, 999999, - &query1, callback1.callback()), - IsError(net::ERR_IO_PENDING)); - - std::unique_ptr<LogDnsClient::AuditProofQuery> query2; - net::TestCompletionCallback callback2; - ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[1], - false /* lookup_securely */, 999999, - &query2, callback2.callback()), - IsError(net::ERR_TEMPORARILY_THROTTLED)); - - // Check that the first query succeeded. - EXPECT_THAT(callback1.WaitForResult(), IsOk()); - const net::ct::MerkleAuditProof& proof1 = query1->GetProof(); - EXPECT_THAT(proof1.leaf_index, Eq(123456u)); - EXPECT_THAT(proof1.tree_size, Eq(999999u)); - EXPECT_THAT(proof1.nodes, Eq(audit_proof)); - - // Try a third query, which should succeed now that the first is finished. - ASSERT_TRUE( - mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[2], 666)); - for (size_t nodes_begin = 0; nodes_begin < audit_proof.size(); - nodes_begin += kMaxProofNodesPerDnsResponse) { - const size_t nodes_end = std::min( - nodes_begin + kMaxProofNodesPerDnsResponse, audit_proof.size()); - - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - base::StringPrintf("%zu.666.999999.tree.ct.test.", nodes_begin), - audit_proof.begin() + nodes_begin, audit_proof.begin() + nodes_end)); - } - - std::unique_ptr<LogDnsClient::AuditProofQuery> query3; - net::TestCompletionCallback callback3; - ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[2], - false /* lookup_securely */, 999999, - &query3, callback3.callback()), - IsError(net::ERR_IO_PENDING)); - - // Check that the third query succeeded. - EXPECT_THAT(callback3.WaitForResult(), IsOk()); - const net::ct::MerkleAuditProof& proof3 = query3->GetProof(); - EXPECT_THAT(proof3.leaf_index, Eq(666u)); - EXPECT_THAT(proof3.tree_size, Eq(999999u)); - EXPECT_THAT(proof3.nodes, Eq(audit_proof)); - - histograms_.ExpectUniqueSample(kLeafIndexErrorHistogram, -net::OK, 2); - histograms_.ExpectUniqueSample(kLeafIndexRcodeHistogram, - net::dns_protocol::kRcodeNOERROR, 2); - histograms_.ExpectUniqueSample(kAuditProofErrorHistogram, -net::OK, 2); - histograms_.ExpectUniqueSample(kAuditProofRcodeHistogram, - net::dns_protocol::kRcodeNOERROR, 2); -} - -TEST_P(LogDnsClientTest, NotifiesWhenNoLongerThrottled) { - const std::vector<std::string> audit_proof = GetSampleAuditProof(20); - - ASSERT_TRUE( - mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456)); - for (size_t nodes_begin = 0; nodes_begin < audit_proof.size(); - nodes_begin += kMaxProofNodesPerDnsResponse) { - const size_t nodes_end = std::min( - nodes_begin + kMaxProofNodesPerDnsResponse, audit_proof.size()); - - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - base::StringPrintf("%zu.123456.999999.tree.ct.test.", nodes_begin), - audit_proof.begin() + nodes_begin, audit_proof.begin() + nodes_end)); - } - - const size_t kMaxConcurrentQueries = 1; - std::unique_ptr<LogDnsClient> log_client = - CreateLogDnsClient(kMaxConcurrentQueries); - - // Start a query. - std::unique_ptr<LogDnsClient::AuditProofQuery> query1; - net::TestCompletionCallback query_callback1; - ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[0], - false /* lookup_securely */, 999999, - &query1, query_callback1.callback()), - IsError(net::ERR_IO_PENDING)); - - net::TestClosure not_throttled_callback; - log_client->NotifyWhenNotThrottled(not_throttled_callback.closure()); - - ASSERT_THAT(query_callback1.WaitForResult(), IsOk()); - not_throttled_callback.WaitForResult(); - - // Start another query to check |not_throttled_callback| doesn't fire again. - ASSERT_TRUE( - mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[1], 666)); - for (size_t nodes_begin = 0; nodes_begin < audit_proof.size(); - nodes_begin += kMaxProofNodesPerDnsResponse) { - const size_t nodes_end = std::min( - nodes_begin + kMaxProofNodesPerDnsResponse, audit_proof.size()); - - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - base::StringPrintf("%zu.666.999999.tree.ct.test.", nodes_begin), - audit_proof.begin() + nodes_begin, audit_proof.begin() + nodes_end)); - } - - std::unique_ptr<LogDnsClient::AuditProofQuery> query2; - net::TestCompletionCallback query_callback2; - ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[1], - false /* lookup_securely */, 999999, - &query2, query_callback2.callback()), - IsError(net::ERR_IO_PENDING)); - - // Give the query a chance to run. - ASSERT_THAT(query_callback2.WaitForResult(), IsOk()); - // Give |not_throttled_callback| a chance to run - it shouldn't though. - base::RunLoop().RunUntilIdle(); - ASSERT_FALSE(not_throttled_callback.have_result()); -} - -TEST_P(LogDnsClientTest, CanCancelQueries) { - const size_t kMaxConcurrentQueries = 1; - std::unique_ptr<LogDnsClient> log_client = - CreateLogDnsClient(kMaxConcurrentQueries); - - // Expect the first request of the query to be sent, but not the rest because - // it'll be cancelled before it gets that far. - ASSERT_TRUE( - mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456)); - - // Start query. - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - net::TestCompletionCallback callback; - ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[0], - false /* lookup_securely */, 999999, - &query, callback.callback()), - IsError(net::ERR_IO_PENDING)); - - // Cancel the query. - query.reset(); - - // Give |callback| a chance to run - it shouldn't though. - base::RunLoop().RunUntilIdle(); - ASSERT_FALSE(callback.have_result()); - - histograms_.ExpectTotalCount(kLeafIndexErrorHistogram, 0); - histograms_.ExpectTotalCount(kLeafIndexRcodeHistogram, 0); - histograms_.ExpectTotalCount(kAuditProofErrorHistogram, 0); - histograms_.ExpectTotalCount(kAuditProofRcodeHistogram, 0); -} - -TEST_P(LogDnsClientTest, SecureDnsMode_Secure) { - const std::vector<std::string> audit_proof = GetSampleAuditProof(20); - - net::MockDnsClientRuleList rules; - // Make leaf index queries for kLeafIndexQnames[0] successful only when - // lookup_securely is true. - rules.emplace_back( - kLeafIndexQnames[0], net::dns_protocol::kTypeTXT, - net::SecureDnsMode::SECURE, - net::MockDnsClientRule::CreateSecureResult(net::BuildTestDnsTextResponse( - kLeafIndexQnames[0], - std::vector<std::vector<std::string>>({{"123456"}}))), - false /* delay */); - - // Add successful audit proof queries for lookup_securely true. - for (size_t nodes_begin = 0; nodes_begin < audit_proof.size(); - nodes_begin += kMaxProofNodesPerDnsResponse) { - const size_t nodes_end = std::min( - nodes_begin + kMaxProofNodesPerDnsResponse, audit_proof.size()); - rules.emplace_back( - base::StringPrintf("%zu.123456.999999.tree.ct.test.", nodes_begin), - net::dns_protocol::kTypeTXT, net::SecureDnsMode::SECURE, - net::MockDnsClientRule::CreateSecureResult( - net::BuildTestDnsTextResponse( - base::StringPrintf("%zu.123456.999999.tree.ct.test.", - nodes_begin), - {{std::accumulate(audit_proof.begin() + nodes_begin, - audit_proof.begin() + nodes_end, - std::string())}})), - false /* delay */ - ); - } - - std::unique_ptr<LogDnsClient> log_client = - CreateRuleBasedLogDnsClient(std::move(rules)); - - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - net::TestCompletionCallback callback1; - ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[0], - false /* lookup_securely */, 999999, - &query, callback1.callback()), - IsError(net::ERR_IO_PENDING)); - EXPECT_THAT(callback1.WaitForResult(), IsError(net::ERR_NAME_NOT_RESOLVED)); - - net::TestCompletionCallback callback2; - ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[0], - true /* lookup_securely */, 999999, - &query, callback2.callback()), - IsError(net::ERR_IO_PENDING)); - EXPECT_THAT(callback2.WaitForResult(), IsOk()); -} - -TEST_P(LogDnsClientTest, SecureDnsMode_Insecure) { - const std::vector<std::string> audit_proof = GetSampleAuditProof(20); - - net::MockDnsClientRuleList rules; - // Make leaf index queries for kLeafIndexQnames[0] successful only when - // lookup_securely is false. - rules.emplace_back( - kLeafIndexQnames[0], net::dns_protocol::kTypeTXT, net::SecureDnsMode::OFF, - net::MockDnsClientRule::Result(net::BuildTestDnsTextResponse( - kLeafIndexQnames[0], - std::vector<std::vector<std::string>>({{"123456"}}))), - false /* delay */); - - // Add successful audit proof queries for lookup_securely false. - for (size_t nodes_begin = 0; nodes_begin < audit_proof.size(); - nodes_begin += kMaxProofNodesPerDnsResponse) { - const size_t nodes_end = std::min( - nodes_begin + kMaxProofNodesPerDnsResponse, audit_proof.size()); - rules.emplace_back( - base::StringPrintf("%zu.123456.999999.tree.ct.test.", nodes_begin), - net::dns_protocol::kTypeTXT, net::SecureDnsMode::OFF, - net::MockDnsClientRule::Result(net::BuildTestDnsTextResponse( - base::StringPrintf("%zu.123456.999999.tree.ct.test.", nodes_begin), - {{std::accumulate(audit_proof.begin() + nodes_begin, - audit_proof.begin() + nodes_end, - std::string())}})), - false /* delay */ - ); - } - - std::unique_ptr<LogDnsClient> log_client = - CreateRuleBasedLogDnsClient(std::move(rules)); - - std::unique_ptr<LogDnsClient::AuditProofQuery> query; - net::TestCompletionCallback callback1; - ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[0], - false /* lookup_securely */, 999999, - &query, callback1.callback()), - IsError(net::ERR_IO_PENDING)); - EXPECT_THAT(callback1.WaitForResult(), IsOk()); - - net::TestCompletionCallback callback2; - ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[0], - true /* lookup_securely */, 999999, - &query, callback2.callback()), - IsError(net::ERR_IO_PENDING)); - EXPECT_THAT(callback2.WaitForResult(), IsError(net::ERR_NAME_NOT_RESOLVED)); -} - -INSTANTIATE_TEST_SUITE_P(ReadMode, - LogDnsClientTest, - ::testing::Values(net::IoMode::ASYNC, - net::IoMode::SYNCHRONOUS)); - -} // namespace certificate_transparency
diff --git a/components/certificate_transparency/mock_log_dns_traffic.cc b/components/certificate_transparency/mock_log_dns_traffic.cc deleted file mode 100644 index 3d0c0ea..0000000 --- a/components/certificate_transparency/mock_log_dns_traffic.cc +++ /dev/null
@@ -1,351 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/certificate_transparency/mock_log_dns_traffic.h" - -#include <algorithm> -#include <numeric> -#include <vector> - -#include "base/big_endian.h" -#include "base/bind.h" -#include "base/containers/span.h" -#include "base/numerics/safe_conversions.h" -#include "base/strings/string_number_conversions.h" -#include "base/sys_byteorder.h" -#include "base/test/test_timeouts.h" -#include "net/dns/dns_client.h" -#include "net/dns/dns_config.h" -#include "net/dns/dns_query.h" -#include "net/dns/dns_util.h" -#include "net/dns/public/dns_protocol.h" -#include "net/dns/record_rdata.h" -#include "net/socket/socket_test_util.h" -#include "net/url_request/url_request_error_job.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace certificate_transparency { - -namespace { - -// This is used for the last mock socket response as a sentinel to prevent -// trying to read more data than expected. -const net::MockRead kNoMoreData(net::SYNCHRONOUS, net::ERR_UNEXPECTED, 2); - -// Necessary to expose SetDnsConfig for testing. -class DnsChangeNotifier : public net::NetworkChangeNotifier { - public: - static void SetDnsConfig(const net::DnsConfig& config) { - net::NetworkChangeNotifier::SetDnsConfig(config); - } -}; - -std::vector<char> AsVector(const net::IOBufferWithSize& buf) { - return std::vector<char>(buf.data(), buf.data() + buf.size()); -} - -// Always return min, to simplify testing. -// This should result in the DNS query ID always being 0. -int FakeRandInt(int min, int max) { - return min; -} - -std::unique_ptr<net::DnsQuery> CreateDnsTxtQuery(base::StringPiece qname) { - std::string encoded_qname; - if (!net::DNSDomainFromDot(qname, &encoded_qname)) { - // qname is an invalid domain name. - return nullptr; - } - - // Expect EDNS option that disables client subnet extension: - // https://tools.ietf.org/html/rfc7871 - const uint16_t kClientSubnetExtensionCode = 8; - net::OptRecordRdata opt_rdata; - opt_rdata.AddOpt(net::OptRecordRdata::Opt( - kClientSubnetExtensionCode, base::StringPiece("\x00\x01\x00\x00", 4))); - - const uint16_t kQueryId = 0; - return std::make_unique<net::DnsQuery>( - kQueryId, encoded_qname, net::dns_protocol::kTypeTXT, &opt_rdata); -} - -bool CreateDnsTxtResponse(const net::DnsQuery& query, - base::StringPiece answer, - std::vector<char>* response) { - *response = AsVector(*query.io_buffer()); - - // Modify the header. - net::dns_protocol::Header* header = - reinterpret_cast<net::dns_protocol::Header*>(response->data()); - header->ancount = base::HostToNet16(1); - header->flags |= base::HostToNet16(net::dns_protocol::kFlagResponse); - - // The qname is at the start of the query section (just after the header). - const uint8_t qname_ptr = sizeof(*header); - - // The answers section starts after the header and question section. - const size_t answers_section_offset = - sizeof(*header) + query.question().size(); - - // DNS answers section: - // 2 bytes - qname pointer - // 2 bytes - record type - // 2 bytes - record class - // 4 bytes - time-to-live - // 2 bytes - size of answer (N) - // N bytes - answer - // Total = 12 + N bytes - const size_t answers_section_size = 12 + answer.size(); - constexpr uint32_t ttl = 86400; // seconds - - // Make space for the answers section. - response->insert(response->begin() + answers_section_offset, - answers_section_size, 0); - - // Write the answers section. - base::BigEndianWriter writer(response->data() + answers_section_offset, - answers_section_size); - if (!writer.WriteU8(net::dns_protocol::kLabelPointer) || - !writer.WriteU8(qname_ptr) || - !writer.WriteU16(net::dns_protocol::kTypeTXT) || - !writer.WriteU16(net::dns_protocol::kClassIN) || !writer.WriteU32(ttl) || - !writer.WriteU16(answer.size()) || - !writer.WriteBytes(answer.data(), answer.size())) { - return false; - } - - if (writer.remaining() != 0) { - // Less than the expected amount of data was written. - return false; - } - - return true; -} - -bool CreateDnsErrorResponse(const net::DnsQuery& query, - uint8_t rcode, - std::vector<char>* response) { - *response = AsVector(*query.io_buffer()); - - // Modify the header - net::dns_protocol::Header* header = - reinterpret_cast<net::dns_protocol::Header*>(response->data()); - header->ancount = base::HostToNet16(1); - header->flags |= base::HostToNet16(net::dns_protocol::kFlagResponse | rcode); - return true; -} - -} // namespace - -net::URLRequestJob* MockLogDnsTraffic::DohJobInterceptor::MaybeInterceptRequest( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const { - return new net::URLRequestErrorJob(request, network_delegate, - net::ERR_NOT_IMPLEMENTED); -} - -// A container for all of the data needed for simulating a socket. -// This is useful because Mock{Read,Write}, SequencedSocketData and -// MockClientSocketFactory all do not take ownership of or copy their arguments, -// so it is necessary to manage the lifetime of those arguments. Wrapping all -// of that up in a single class simplifies this. -class MockLogDnsTraffic::MockSocketData { - public: - // A socket that expects one write and one read operation. - MockSocketData(const std::vector<char>& write, const std::vector<char>& read) - : expected_write_payload_(write), - expected_read_payload_(read), - expected_write_(net::SYNCHRONOUS, - expected_write_payload_.data(), - expected_write_payload_.size(), - 0), - expected_reads_{net::MockRead(net::ASYNC, - expected_read_payload_.data(), - expected_read_payload_.size(), - 1), - kNoMoreData}, - socket_data_(expected_reads_, base::make_span(&expected_write_, 1)) {} - - // A socket that expects one write and a read error. - MockSocketData(const std::vector<char>& write, net::Error error) - : expected_write_payload_(write), - expected_write_(net::SYNCHRONOUS, - expected_write_payload_.data(), - expected_write_payload_.size(), - 0), - expected_reads_{net::MockRead(net::ASYNC, error, 1), kNoMoreData}, - socket_data_(expected_reads_, base::make_span(&expected_write_, 1)) {} - - // A socket that expects one write and no response. - explicit MockSocketData(const std::vector<char>& write) - : expected_write_payload_(write), - expected_write_(net::SYNCHRONOUS, - expected_write_payload_.data(), - expected_write_payload_.size(), - 0), - expected_reads_{net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING, 1), - kNoMoreData}, - socket_data_(expected_reads_, base::make_span(&expected_write_, 1)) {} - - ~MockSocketData() {} - - void SetWriteMode(net::IoMode mode) { expected_write_.mode = mode; } - void SetReadMode(net::IoMode mode) { expected_reads_[0].mode = mode; } - - void AddToFactory(net::MockClientSocketFactory* socket_factory) { - socket_factory->AddSocketDataProvider(&socket_data_); - } - - private: - // This class only supports one write and one read, so just need to store one - // payload each. - const std::vector<char> expected_write_payload_; - const std::vector<char> expected_read_payload_; - - // Encapsulates the data that is expected to be written to a socket. - net::MockWrite expected_write_; - - // Encapsulates the data/error that should be returned when reading from a - // socket. The second "expected" read is a sentinel (see |kNoMoreData|). - net::MockRead expected_reads_[2]; - - // Holds pointers to |expected_write_| and |expected_reads_|. This is what is - // added to net::MockClientSocketFactory to prepare a mock socket. - net::SequencedSocketData socket_data_; - - DISALLOW_COPY_AND_ASSIGN(MockSocketData); -}; - -MockLogDnsTraffic::MockLogDnsTraffic() : socket_read_mode_(net::ASYNC) {} - -MockLogDnsTraffic::~MockLogDnsTraffic() {} - -bool MockLogDnsTraffic::ExpectRequestAndErrorResponse(base::StringPiece qname, - uint8_t rcode) { - std::unique_ptr<net::DnsQuery> query = CreateDnsTxtQuery(qname); - if (!query) { - return false; - } - - std::vector<char> response; - if (!CreateDnsErrorResponse(*query, rcode, &response)) { - return false; - } - - EmplaceMockSocketData(AsVector(*query->io_buffer()), response); - return true; -} - -bool MockLogDnsTraffic::ExpectRequestAndSocketError(base::StringPiece qname, - net::Error error) { - std::unique_ptr<net::DnsQuery> query = CreateDnsTxtQuery(qname); - if (!query) { - return false; - } - - EmplaceMockSocketData(AsVector(*query->io_buffer()), error); - return true; -} - -bool MockLogDnsTraffic::ExpectRequestAndTimeout(base::StringPiece qname) { - std::unique_ptr<net::DnsQuery> query = CreateDnsTxtQuery(qname); - if (!query) { - return false; - } - - EmplaceMockSocketData(AsVector(*query->io_buffer())); - - // Speed up timeout tests. - SetDnsTimeout(TestTimeouts::tiny_timeout()); - - return true; -} - -bool MockLogDnsTraffic::ExpectRequestAndResponse( - base::StringPiece qname, - const std::vector<base::StringPiece>& txt_strings) { - std::string answer; - for (base::StringPiece str : txt_strings) { - // The size of the string must precede it. The size must fit into 1 byte. - answer.insert(answer.end(), base::checked_cast<uint8_t>(str.size())); - str.AppendToString(&answer); - } - - std::unique_ptr<net::DnsQuery> query = CreateDnsTxtQuery(qname); - if (!query) { - return false; - } - - std::vector<char> response; - if (!CreateDnsTxtResponse(*query, answer, &response)) { - return false; - } - - EmplaceMockSocketData(AsVector(*query->io_buffer()), response); - return true; -} - -bool MockLogDnsTraffic::ExpectLeafIndexRequestAndResponse( - base::StringPiece qname, - uint64_t leaf_index) { - return ExpectRequestAndResponse(qname, {base::NumberToString(leaf_index)}); -} - -bool MockLogDnsTraffic::ExpectAuditProofRequestAndResponse( - base::StringPiece qname, - std::vector<std::string>::const_iterator audit_path_start, - std::vector<std::string>::const_iterator audit_path_end) { - // Join nodes in the audit path into a single string. - std::string proof = - std::accumulate(audit_path_start, audit_path_end, std::string()); - - return ExpectRequestAndResponse(qname, {proof}); -} - -void MockLogDnsTraffic::InitializeDnsConfig() { - net::DnsConfig dns_config; - // Use an invalid nameserver address. This prevents the tests accidentally - // sending real DNS queries. The mock sockets don't care that the address - // is invalid. - dns_config.nameservers.push_back(net::IPEndPoint()); - // Add a DoH server. - dns_config.dns_over_https_servers.push_back( - {"https://mock.http/dns-query{?dns}", true /* use_post */}); - // Don't attempt retransmissions - just fail. - dns_config.attempts = 1; - // This ensures timeouts are long enough for memory tests. - dns_config.timeout = TestTimeouts::action_timeout(); - // Simplify testing - don't require random numbers for the source port. - // This means our FakeRandInt function should only be called to get query - // IDs. - dns_config.randomize_ports = false; - - DnsChangeNotifier::SetDnsConfig(dns_config); -} - -void MockLogDnsTraffic::SetDnsConfig(const net::DnsConfig& config) { - DnsChangeNotifier::SetDnsConfig(config); -} - -std::unique_ptr<net::DnsClient> MockLogDnsTraffic::CreateDnsClient() { - return net::DnsClient::CreateClientForTesting(nullptr, &socket_factory_, - base::Bind(&FakeRandInt)); -} - -template <typename... Args> -void MockLogDnsTraffic::EmplaceMockSocketData(Args&&... args) { - mock_socket_data_.emplace_back( - new MockSocketData(std::forward<Args>(args)...)); - mock_socket_data_.back()->SetReadMode(socket_read_mode_); - mock_socket_data_.back()->AddToFactory(&socket_factory_); -} - -void MockLogDnsTraffic::SetDnsTimeout(const base::TimeDelta& timeout) { - net::DnsConfig dns_config; - DnsChangeNotifier::GetDnsConfig(&dns_config); - dns_config.timeout = timeout; - DnsChangeNotifier::SetDnsConfig(dns_config); -} - -} // namespace certificate_transparency
diff --git a/components/certificate_transparency/mock_log_dns_traffic.h b/components/certificate_transparency/mock_log_dns_traffic.h deleted file mode 100644 index d6cefb1d..0000000 --- a/components/certificate_transparency/mock_log_dns_traffic.h +++ /dev/null
@@ -1,167 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_CERTIFICATE_TRANSPARENCY_MOCK_LOG_DNS_TRAFFIC_H_ -#define COMPONENTS_CERTIFICATE_TRANSPARENCY_MOCK_LOG_DNS_TRAFFIC_H_ - -#include <stdint.h> - -#include <memory> -#include <string> -#include <vector> - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "base/strings/string_piece.h" -#include "net/dns/dns_client.h" -#include "net/socket/socket_test_util.h" -#include "net/url_request/url_request.h" -#include "net/url_request/url_request_interceptor.h" - -namespace net { -struct DnsConfig; -} - -namespace certificate_transparency { - -// Mocks DNS requests and responses for a Certificate Transparency (CT) log. -// This is implemented using mock sockets. Call the CreateDnsClient() method to -// get a net::DnsClient wired up to these mock sockets. -// The Expect*() methods must be called from within a GTest test case. -// -// Example Usage: -// // net::DnsClient requires an I/O message loop for async operations. -// base::MessageLoopForIO message_loop; -// -// // Create a mock NetworkChangeNotifier to propagate DNS config. -// std::unique_ptr<net::NetworkChangeNotifier> net_change_notifier( -// net::NetworkChangeNotifier::CreateMock()); -// -// MockLogDnsTraffic mock_dns; -// mock_dns.InitializeDnsConfig(); -// // Use the Expect* methods to define expected DNS requests and responses. -// mock_dns.ExpectLeafIndexRequestAndResponse( -// "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", -// "123456"); -// -// LogDnsClient log_client(mock_dns.CreateDnsClient(), ...); -// log_client.QueryAuditProof("ct.test", ..., base::BindOnce(...)); -class MockLogDnsTraffic { - public: - MockLogDnsTraffic(); - ~MockLogDnsTraffic(); - - // Expect a CT DNS request for the domain |qname|. - // Such a request will receive a DNS response indicating that the error - // specified by |rcode| occurred. See RFC1035, Section 4.1.1 for |rcode| - // values. - // Returns false if any of the arguments are invalid. - WARN_UNUSED_RESULT - bool ExpectRequestAndErrorResponse(base::StringPiece qname, uint8_t rcode); - - // Expect a CT DNS request for the domain |qname|. - // Such a request will trigger a socket error of type |error|. - // Returns false if any of the arguments are invalid. - WARN_UNUSED_RESULT - bool ExpectRequestAndSocketError(base::StringPiece qname, net::Error error); - - // Expect a CT DNS request for the domain |qname|. - // Such a request will timeout. - // This will reduce the DNS timeout to minimize test duration. - // Returns false if |qname| is invalid. - WARN_UNUSED_RESULT - bool ExpectRequestAndTimeout(base::StringPiece qname); - - // Expect a CT DNS request for the domain |qname|. - // Such a request will receive a DNS TXT response containing |txt_strings|. - // Returns false if any of the arguments are invalid. - WARN_UNUSED_RESULT - bool ExpectRequestAndResponse( - base::StringPiece qname, - const std::vector<base::StringPiece>& txt_strings); - - // Expect a CT DNS request for the domain |qname|. - // Such a request will receive a DNS response containing |leaf_index|. - // A description of such a request and response can be seen here: - // https://github.com/google/certificate-transparency-rfcs/blob/c8844de6bd0b5d3d16bac79865e6edef533d760b/dns/draft-ct-over-dns.md#hash-query-hashquery - // Returns false if any of the arguments are invalid. - WARN_UNUSED_RESULT - bool ExpectLeafIndexRequestAndResponse(base::StringPiece qname, - uint64_t leaf_index); - - // Expect a CT DNS request for the domain |qname|. - // Such a request will receive a DNS response containing the inclusion proof - // nodes between |audit_path_start| and |audit_path_end|. - // A description of such a request and response can be seen here: - // https://github.com/google/certificate-transparency-rfcs/blob/c8844de6bd0b5d3d16bac79865e6edef533d760b/dns/draft-ct-over-dns.md#tree-query-treequery - // Returns false if any of the arguments are invalid. - WARN_UNUSED_RESULT - bool ExpectAuditProofRequestAndResponse( - base::StringPiece qname, - std::vector<std::string>::const_iterator audit_path_start, - std::vector<std::string>::const_iterator audit_path_end); - - // Sets the initial DNS config appropriate for testing. - // Requires that net::NetworkChangeNotifier is initialized first. - // The DNS config is propogated to NetworkChangeNotifier::DNSObservers - // asynchronously. - void InitializeDnsConfig(); - - // Sets the DNS config to |config|. - // Requires that net::NetworkChangeNotifier is initialized first. - // The DNS config is propogated to NetworkChangeNotifier::DNSObservers - // asynchronously. - void SetDnsConfig(const net::DnsConfig& config); - - // Creates a DNS client that uses mock sockets. - // It is this DNS client that the expectations will be tested against. - std::unique_ptr<net::DnsClient> CreateDnsClient(); - - private: - // Allows tests to change socket read mode. Only the LogDnsClient tests should - // need to do so, to ensure consistent behaviour regardless of mode. - friend class LogDnsClientTest; - friend class SingleTreeTrackerTest; - - class DohJobInterceptor : public net::URLRequestInterceptor { - public: - DohJobInterceptor() {} - - net::URLRequestJob* MaybeInterceptRequest( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const override; - }; - - class MockSocketData; - - // Sets whether mock reads should complete synchronously or asynchronously. - // By default, they complete asynchronously. - void SetSocketReadMode(net::IoMode read_mode) { - socket_read_mode_ = read_mode; - } - - // Constructs MockSocketData from |args| and adds it to |socket_factory_|. - template <typename... Args> - void EmplaceMockSocketData(Args&&... args); - - // Sets the timeout used for DNS queries. - // Requires that net::NetworkChangeNotifier is initialized first. - // The new timeout is propogated to NetworkChangeNotifier::DNSObservers - // asynchronously. - void SetDnsTimeout(const base::TimeDelta& timeout); - - // One MockSocketData for each socket that is created. This corresponds to one - // for each DNS request sent. - std::vector<std::unique_ptr<MockSocketData>> mock_socket_data_; - // Provides as many mock sockets as there are entries in |mock_socket_data_|. - net::MockClientSocketFactory socket_factory_; - // Controls whether mock socket reads are asynchronous. - net::IoMode socket_read_mode_; - - DISALLOW_COPY_AND_ASSIGN(MockLogDnsTraffic); -}; - -} // namespace certificate_transparency - -#endif // COMPONENTS_CERTIFICATE_TRANSPARENCY_MOCK_LOG_DNS_TRAFFIC_H_
diff --git a/components/certificate_transparency/single_tree_tracker.cc b/components/certificate_transparency/single_tree_tracker.cc deleted file mode 100644 index 09815d0f..0000000 --- a/components/certificate_transparency/single_tree_tracker.cc +++ /dev/null
@@ -1,548 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/certificate_transparency/single_tree_tracker.h" - -#include <algorithm> -#include <iterator> -#include <list> -#include <utility> - -#include "base/bind.h" -#include "base/metrics/histogram_macros.h" -#include "base/strings/string_number_conversions.h" -#include "base/values.h" -#include "components/certificate_transparency/log_dns_client.h" -#include "crypto/sha2.h" -#include "net/base/hash_value.h" -#include "net/base/net_errors.h" -#include "net/cert/ct_log_verifier.h" -#include "net/cert/merkle_audit_proof.h" -#include "net/cert/merkle_tree_leaf.h" -#include "net/cert/signed_certificate_timestamp.h" -#include "net/cert/x509_certificate.h" -#include "net/dns/host_resolver.h" -#include "net/log/net_log.h" - -using net::SHA256HashValue; -using net::ct::MerkleAuditProof; -using net::ct::MerkleTreeLeaf; -using net::ct::SignedCertificateTimestamp; -using net::ct::SignedTreeHead; - -// Overview of the process for auditing CT log entries -// -// In this file, obsered CT log entries are audited for inclusion in the CT log. -// A pre-requirement for auditing a log entry is having a Signed Tree Head (STH) -// from that log that is 24 hours (MMD period) after the timestamp in the SCT. -// Log entries observed while the client has no STH from that log or an STH that -// is too old start in the PENDING_NEWER_STH state. -// -// Once a fresh-enough STH is obtained, all entries that can be audited using -// this STH move to the PENDING_INCLUSION_PROOF_REQUEST state. -// -// Requests for the entry index and inclusion proof are obtained using a -// LogDnsClient instance - when an inclusion proof for an entry has been -// successfully requested (e.g. it has not been throttled), it moves to the -// INCLUSION_PROOF_REQUESTED state. -// -// Once the inclusion check is done, the entry is removed from -// |pending_entries_|. If the inclusion check has been successful, the entry -// is added to |checked_entries_|. - -namespace certificate_transparency { - -namespace { - -// Measure how often clients encounter very new SCTs, by measuring whether an -// SCT can be checked for inclusion upon first observation. -void LogCanBeCheckedForInclusionToUMA( - SCTCanBeCheckedForInclusion can_be_checked) { - UMA_HISTOGRAM_ENUMERATION("Net.CertificateTransparency.CanInclusionCheckSCT", - can_be_checked, SCT_CAN_BE_CHECKED_MAX); -} - -// Enum indicating the outcome of an inclusion check for a particular log -// entry. -// -// Note: The numeric values are used within a histogram and should not change -// or be re-assigned. -enum LogEntryInclusionCheckResult { - // Inclusion check succeeded: Proof obtained and validated successfully. - GOT_VALID_INCLUSION_PROOF = 0, - - // Could not get an inclusion proof. - FAILED_GETTING_INCLUSION_PROOF = 1, - - // An inclusion proof was obtained but it is invalid. - GOT_INVALID_INCLUSION_PROOF = 2, - - // The SCT could not be audited because the client's DNS configuration - // is faulty. - DNS_QUERY_NOT_POSSIBLE = 3, - - LOG_ENTRY_INCLUSION_CHECK_RESULT_MAX -}; - -void LogInclusionCheckResult(LogEntryInclusionCheckResult result) { - UMA_HISTOGRAM_ENUMERATION("Net.CertificateTransparency.InclusionCheckResult", - result, LOG_ENTRY_INCLUSION_CHECK_RESULT_MAX); -} - -// Calculate the leaf hash of the the entry in the log represented by -// the given |cert| and |sct|. If leaf hash calculation succeeds returns -// true, false otherwise. -bool GetLogEntryLeafHash(const net::X509Certificate* cert, - const SignedCertificateTimestamp* sct, - SHA256HashValue* leaf_hash) { - MerkleTreeLeaf leaf; - if (!GetMerkleTreeLeaf(cert, sct, &leaf)) - return false; - - std::string leaf_hash_str; - if (!HashMerkleTreeLeaf(leaf, &leaf_hash_str)) - return false; - - memcpy(leaf_hash->data, leaf_hash_str.data(), crypto::kSHA256Length); - return true; -} - -// Audit state of a log entry. -enum AuditState { - // Entry cannot be audited because a newer STH is needed. - PENDING_NEWER_STH, - // A leaf index has been obtained and the entry is now pending request - // of an inclusion proof. - PENDING_INCLUSION_PROOF_REQUEST, - // An inclusion proof for this entry has been requested from the log. - INCLUSION_PROOF_REQUESTED -}; - -// Maximal size of the checked entries cache. -size_t kCheckedEntriesCacheSize = 100; - -// Maximal size of the pending entries queue. -size_t kPendingEntriesQueueSize = 100; - -// Maximum Merge Delay - logs can have individual MMD, but all known logs -// currently have 24 hours MMD and Chrome's CT policy requires an MMD -// that's no greater than that. For simplicity, use 24 hours for all logs. -constexpr base::TimeDelta kMaximumMergeDelay = base::TimeDelta::FromHours(24); - -// The log MUST incorporate the a certificate in the tree within the Maximum -// Merge Delay, so an entry can be audited once the timestamp from the SCT + -// MMD has passed. -// Returns true if the timestamp from the STH is newer than SCT timestamp + MMD. -bool IsSCTReadyForAudit(base::Time sth_timestamp, base::Time sct_timestamp) { - return sct_timestamp + kMaximumMergeDelay < sth_timestamp; -} - -base::Value NetLogEntryAuditingEventCallback( - const SHA256HashValue* log_entry, - base::StringPiece log_id, - bool success, - net::NetLogCaptureMode capture_mode) { - base::DictionaryValue dict; - - dict.SetString("log_entry", - base::HexEncode(log_entry->data, crypto::kSHA256Length)); - dict.SetString("log_id", base::HexEncode(log_id.data(), log_id.size())); - dict.SetBoolean("success", success); - - return std::move(dict); -} - -} // namespace - -// The entry that is being audited. -struct SingleTreeTracker::EntryToAudit { - base::Time sct_timestamp; - SHA256HashValue leaf_hash; - bool lookup_securely; - - explicit EntryToAudit(base::Time timestamp, bool lookup_securely) - : sct_timestamp(timestamp), lookup_securely(lookup_securely) {} -}; - -// State of a log entry: its audit state and information necessary to -// validate an inclusion proof. Gets updated as the entry transitions -// between the different audit states. -struct SingleTreeTracker::EntryAuditState { - // Current phase of inclusion check. - AuditState state; - - // The audit proof query performed by LogDnsClient. - // It is null unless a query has been started. - std::unique_ptr<LogDnsClient::AuditProofQuery> audit_proof_query; - - // The root hash of the tree for which an inclusion proof was requested. - // The root hash is needed after the inclusion proof is fetched for validating - // the inclusion proof (each inclusion proof is valid for one particular leaf, - // denoted by the leaf index, in exactly one particular tree, denoted by the - // tree size in the proof). - // To avoid having to re-fetch the inclusion proof if a newer STH is provided - // to the SingleTreeTracker, the size of the original tree for which the - // inclusion proof was requested is stored in |proof| and the root hash - // in |root_hash|. - std::string root_hash; - - explicit EntryAuditState(AuditState state) : state(state) {} -}; - -class SingleTreeTracker::NetworkObserver - : public net::NetworkChangeNotifier::NetworkChangeObserver { - public: - explicit NetworkObserver(SingleTreeTracker* parent) : parent_(parent) { - net::NetworkChangeNotifier::AddNetworkChangeObserver(this); - } - - ~NetworkObserver() override { - net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); - } - - // net::NetworkChangeNotifier::NetworkChangeObserver implementation. - void OnNetworkChanged( - net::NetworkChangeNotifier::ConnectionType type) override { - parent_->ResetPendingQueue(); - } - - private: - SingleTreeTracker* parent_; -}; - -// Orders entries by the SCT timestamp. In case of tie, which is very unlikely -// as it requires two SCTs issued from a log at exactly the same time, order -// by leaf hash. There should never be multiple entries that are identical -// apart from the |lookup_securely| field, so this field can be excluded from -// the comparator. -bool SingleTreeTracker::OrderByTimestamp::operator()( - const EntryToAudit& lhs, - const EntryToAudit& rhs) const { - return std::tie(lhs.sct_timestamp, lhs.leaf_hash) < - std::tie(rhs.sct_timestamp, rhs.leaf_hash); -} - -SingleTreeTracker::SingleTreeTracker( - scoped_refptr<const net::CTLogVerifier> ct_log, - LogDnsClient* dns_client, - net::HostResolver* host_resolver, - net::NetLog* net_log) - : ct_log_(std::move(ct_log)), - checked_entries_(kCheckedEntriesCacheSize), - dns_client_(dns_client), - host_resolver_(host_resolver), - net_log_(net::NetLogWithSource::Make( - net_log, - net::NetLogSourceType::CT_TREE_STATE_TRACKER)), - network_observer_(new NetworkObserver(this)), - weak_factory_(this) { - memory_pressure_listener_.reset(new base::MemoryPressureListener(base::Bind( - &SingleTreeTracker::OnMemoryPressure, base::Unretained(this)))); -} - -SingleTreeTracker::~SingleTreeTracker() { - ResetPendingQueue(); -} - -void SingleTreeTracker::OnSCTVerified(base::StringPiece hostname, - net::X509Certificate* cert, - const SignedCertificateTimestamp* sct) { - DCHECK_EQ(ct_log_->key_id(), sct->log_id); - - // Check that a DNS lookup for hostname has already occurred (i.e. the DNS - // resolver already knows that the user has been accessing that host). If not, - // the DNS resolver may not know that the user has been accessing that host, - // but performing an inclusion check would reveal that information so abort to - // preserve the user's privacy. - // - // It's ok to do this now, even though the inclusion check may not happen for - // some time, because SingleTreeTracker will discard the SCT if the network - // changes. - bool secure; - if (!WasLookedUpOverDNS(hostname, &secure)) { - LogCanBeCheckedForInclusionToUMA(NOT_AUDITED_NO_DNS_LOOKUP); - return; - } - - EntryToAudit entry(sct->timestamp, secure /* lookup_securely */); - if (!GetLogEntryLeafHash(cert, sct, &entry.leaf_hash)) { - LogCanBeCheckedForInclusionToUMA(NOT_AUDITED_INVALID_LEAF_HASH); - return; - } - - // Avoid queueing multiple instances of the same entry, ignoring the value of - // the |lookup_securely| field. - switch (GetAuditedEntryInclusionStatus(entry, nullptr)) { - case SCT_NOT_OBSERVED: - // No need to record UMA, will be done below. - break; - case SCT_INCLUDED_IN_LOG: - LogCanBeCheckedForInclusionToUMA(NOT_AUDITED_ALREADY_CHECKED); - return; - default: - // Already pending, either due to a newer STH or in the queue. - LogCanBeCheckedForInclusionToUMA(NOT_AUDITED_ALREADY_PENDING_CHECK); - return; - } - - if (pending_entries_.size() >= kPendingEntriesQueueSize) { - // Queue is full - cannot audit SCT. - LogCanBeCheckedForInclusionToUMA(NOT_AUDITED_QUEUE_FULL); - return; - } - - // If there isn't a valid STH or the STH is not fresh enough to check - // inclusion against, store the SCT for future checking and return. - if (verified_sth_.timestamp.is_null() || - !IsSCTReadyForAudit(verified_sth_.timestamp, entry.sct_timestamp)) { - pending_entries_.insert( - std::make_pair(std::move(entry), EntryAuditState(PENDING_NEWER_STH))); - - if (verified_sth_.timestamp.is_null()) { - LogCanBeCheckedForInclusionToUMA(VALID_STH_REQUIRED); - } else { - LogCanBeCheckedForInclusionToUMA(NEWER_STH_REQUIRED); - } - - return; - } - - LogCanBeCheckedForInclusionToUMA(CAN_BE_CHECKED); - pending_entries_.insert(std::make_pair( - std::move(entry), EntryAuditState(PENDING_INCLUSION_PROOF_REQUEST))); - - ProcessPendingEntries(); -} - -void SingleTreeTracker::NewSTHObserved(const SignedTreeHead& sth) { - DCHECK_EQ(ct_log_->key_id(), sth.log_id); - - if (!ct_log_->VerifySignedTreeHead(sth)) { - // Sanity check the STH; the caller should have done this - // already, but being paranoid here. - // NOTE(eranm): Right now there's no way to get rid of this check here - // as this is the first object in the chain that has an instance of - // a CTLogVerifier to verify the STH. - return; - } - - // In order to avoid updating |verified_sth_| to an older STH in case - // an older STH is observed, check that either the observed STH is for - // a larger tree size or that it is for the same tree size but has - // a newer timestamp. - const bool sths_for_same_tree = verified_sth_.tree_size == sth.tree_size; - const bool received_sth_is_for_larger_tree = - (verified_sth_.tree_size < sth.tree_size); - const bool received_sth_is_newer = (sth.timestamp > verified_sth_.timestamp); - - if (!verified_sth_.timestamp.is_null() && !received_sth_is_for_larger_tree && - !(sths_for_same_tree && received_sth_is_newer)) { - // Observed an old STH - do nothing. - return; - } - - verified_sth_ = sth; - - // Find the first entry in the PENDING_NEWER_STH state - entries - // before that should be pending leaf index / inclusion proof, no - // reason to inspect them. - auto auditable_entries_begin = std::find_if( - pending_entries_.begin(), pending_entries_.end(), - [](std::pair<const EntryToAudit&, const EntryAuditState&> value) { - return value.second.state == PENDING_NEWER_STH; - }); - - // Find where to stop - this is the first entry whose timestamp + MMD - // is greater than the STH's timestamp. - auto auditable_entries_end = std::lower_bound( - auditable_entries_begin, pending_entries_.end(), sth.timestamp, - [](std::pair<const EntryToAudit&, const EntryAuditState&> value, - base::Time sth_timestamp) { - return IsSCTReadyForAudit(sth_timestamp, value.first.sct_timestamp); - }); - - // Update the state of all entries that can now be checked for inclusion. - for (auto curr_entry = auditable_entries_begin; - curr_entry != auditable_entries_end; ++curr_entry) { - DCHECK_EQ(curr_entry->second.state, PENDING_NEWER_STH); - curr_entry->second.state = PENDING_INCLUSION_PROOF_REQUEST; - } - - if (auditable_entries_begin == auditable_entries_end) - return; - - ProcessPendingEntries(); -} - -void SingleTreeTracker::ResetPendingQueue() { - // Move entries out of pending_entries_ prior to deleting them, in case any - // have inclusion checks in progress. Cancelling those checks would invoke the - // cancellation callback (ProcessPendingEntries()), which would attempt to - // access pending_entries_ while it was in the process of being deleted. - std::map<EntryToAudit, EntryAuditState, OrderByTimestamp> pending_entries; - pending_entries_.swap(pending_entries); -} - -SingleTreeTracker::SCTInclusionStatus -SingleTreeTracker::GetLogEntryInclusionStatusForTesting( - net::X509Certificate* cert, - const SignedCertificateTimestamp* sct, - bool* pending_lookup_securely) { - EntryToAudit entry(sct->timestamp, false /* lookup_securely */); - if (!GetLogEntryLeafHash(cert, sct, &entry.leaf_hash)) - return SCT_NOT_OBSERVED; - return GetAuditedEntryInclusionStatus(entry, pending_lookup_securely); -} - -void SingleTreeTracker::ProcessPendingEntries() { - for (auto it = pending_entries_.begin(); it != pending_entries_.end(); ++it) { - if (it->second.state != PENDING_INCLUSION_PROOF_REQUEST) { - continue; - } - - it->second.root_hash = - std::string(verified_sth_.sha256_root_hash, crypto::kSHA256Length); - - std::string leaf_hash( - reinterpret_cast<const char*>(it->first.leaf_hash.data), - crypto::kSHA256Length); - net::Error result = dns_client_->QueryAuditProof( - ct_log_->dns_domain(), leaf_hash, it->first.lookup_securely, - verified_sth_.tree_size, &(it->second.audit_proof_query), - base::BindOnce(&SingleTreeTracker::OnAuditProofObtained, - base::Unretained(this), it->first)); - // Handling proofs returned synchronously is not implemeted. - DCHECK_NE(result, net::OK); - if (result == net::ERR_IO_PENDING) { - // Successfully requested an inclusion proof - change entry state - // and continue to the next one. - it->second.state = INCLUSION_PROOF_REQUESTED; - } else if (result == net::ERR_TEMPORARILY_THROTTLED) { - // Need to use a weak pointer here, as this callback could be triggered - // when the SingleTreeTracker is deleted (and pending queries are - // cancelled). - dns_client_->NotifyWhenNotThrottled( - base::BindOnce(&SingleTreeTracker::ProcessPendingEntries, - weak_factory_.GetWeakPtr())); - // Exit the loop since all subsequent calls to QueryAuditProof - // will be throttled. - break; - } else if (result == net::ERR_NAME_RESOLUTION_FAILED) { - LogInclusionCheckResult(DNS_QUERY_NOT_POSSIBLE); - LogAuditResultToNetLog(it->first, false); - // Lookup failed due to bad DNS configuration, erase the entry and - // continue to the next one. - it = pending_entries_.erase(it); - // Break here if it's the last entry to avoid |it| being incremented - // by the for loop. - if (it == pending_entries_.end()) - break; - } else { - // BUG: an invalid argument was provided or an unexpected error - // was returned from LogDnsClient. - DCHECK_EQ(result, net::ERR_INVALID_ARGUMENT); - NOTREACHED(); - } - } -} - -SingleTreeTracker::SCTInclusionStatus -SingleTreeTracker::GetAuditedEntryInclusionStatus( - const EntryToAudit& entry, - bool* pending_lookup_securely) { - const auto checked_entries_iterator = checked_entries_.Get(entry.leaf_hash); - if (checked_entries_iterator != checked_entries_.end()) { - return SCT_INCLUDED_IN_LOG; - } - - auto pending_iterator = pending_entries_.find(entry); - if (pending_iterator == pending_entries_.end()) { - return SCT_NOT_OBSERVED; - } - // Found match in |pending_entries_|, so set |pending_lookup_securely|. - if (pending_lookup_securely) - *pending_lookup_securely = pending_iterator->first.lookup_securely; - switch (pending_iterator->second.state) { - case PENDING_NEWER_STH: - return SCT_PENDING_NEWER_STH; - case PENDING_INCLUSION_PROOF_REQUEST: - case INCLUSION_PROOF_REQUESTED: - return SCT_PENDING_INCLUSION_CHECK; - } - - NOTREACHED(); - return SCT_NOT_OBSERVED; -} - -void SingleTreeTracker::OnAuditProofObtained(const EntryToAudit& entry, - int net_error) { - auto it = pending_entries_.find(entry); - // The entry may not be present if it was evacuated due to low memory - // pressure. - if (it == pending_entries_.end()) - return; - - DCHECK_EQ(it->second.state, INCLUSION_PROOF_REQUESTED); - - if (net_error != net::OK) { - // TODO(eranm): Should failures be cached? For now, they are not. - LogInclusionCheckResult(FAILED_GETTING_INCLUSION_PROOF); - LogAuditResultToNetLog(entry, false); - pending_entries_.erase(it); - return; - } - - std::string leaf_hash(reinterpret_cast<const char*>(entry.leaf_hash.data), - crypto::kSHA256Length); - - bool verified = - ct_log_->VerifyAuditProof(it->second.audit_proof_query->GetProof(), - it->second.root_hash, leaf_hash); - LogAuditResultToNetLog(entry, verified); - - if (!verified) { - LogInclusionCheckResult(GOT_INVALID_INCLUSION_PROOF); - } else { - LogInclusionCheckResult(GOT_VALID_INCLUSION_PROOF); - checked_entries_.Put(entry.leaf_hash, EntryAuditResult()); - } - - pending_entries_.erase(it); -} - -void SingleTreeTracker::OnMemoryPressure( - base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { - switch (memory_pressure_level) { - case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: - break; - case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL: - ResetPendingQueue(); - // Fall through to clearing the other cache. - FALLTHROUGH; - case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: - checked_entries_.Clear(); - break; - } -} - -void SingleTreeTracker::LogAuditResultToNetLog(const EntryToAudit& entry, - bool success) { - net::NetLogParametersCallback net_log_callback = - base::Bind(&NetLogEntryAuditingEventCallback, &entry.leaf_hash, - ct_log_->key_id(), success); - - net_log_.AddEvent(net::NetLogEventType::CT_LOG_ENTRY_AUDITED, - net_log_callback); -} - -bool SingleTreeTracker::WasLookedUpOverDNS(base::StringPiece hostname, - bool* secure) const { - net::HostCache::Entry::Source source; - net::HostCache::EntryStaleness staleness; - return host_resolver_->HasCached(hostname, &source, &staleness, secure) && - source == net::HostCache::Entry::SOURCE_DNS && - staleness.network_changes == 0; -} - -} // namespace certificate_transparency
diff --git a/components/certificate_transparency/single_tree_tracker.h b/components/certificate_transparency/single_tree_tracker.h deleted file mode 100644 index 1beffdb2..0000000 --- a/components/certificate_transparency/single_tree_tracker.h +++ /dev/null
@@ -1,255 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_CERTIFICATE_TRANSPARENCY_SINGLE_TREE_TRACKER_H_ -#define COMPONENTS_CERTIFICATE_TRANSPARENCY_SINGLE_TREE_TRACKER_H_ - -#include <map> -#include <memory> -#include <string> - -#include "base/containers/mru_cache.h" -#include "base/memory/memory_pressure_monitor.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "net/base/hash_value.h" -#include "net/base/network_change_notifier.h" -#include "net/cert/signed_tree_head.h" -#include "net/dns/host_cache.h" -#include "net/log/net_log_with_source.h" - -namespace net { - -class CTLogVerifier; -class HostResolver; -class X509Certificate; - -namespace ct { - -struct MerkleAuditProof; -struct SignedCertificateTimestamp; - -} // namespace ct - -} // namespace net - -namespace certificate_transparency { - -class LogDnsClient; - -// Enum indicating whether an SCT can be checked for inclusion and if not, -// the reason it cannot. -// -// Note: The numeric values are used within a histogram and should not change -// or be re-assigned. -enum SCTCanBeCheckedForInclusion { - // If the SingleTreeTracker does not have a valid STH, then a valid STH is - // first required to evaluate whether the SCT can be checked for inclusion - // or not. - VALID_STH_REQUIRED = 0, - - // If the STH does not cover the SCT (the timestamp in the SCT is greater than - // MMD + timestamp in the STH), then a newer STH is needed. - NEWER_STH_REQUIRED = 1, - - // When an SCT is observed, if the SingleTreeTracker instance has a valid STH - // and the STH covers the SCT (the timestamp in the SCT is less than MMD + - // timestamp in the STH), then it can be checked for inclusion. - CAN_BE_CHECKED = 2, - - // This SCT was not audited because the queue of pending entries was - // full. - NOT_AUDITED_QUEUE_FULL = 3, - - // This SCT was not audited because no DNS lookup was done when first - // visiting the website that supplied it. It could compromise the user's - // privacy to do an inclusion check over DNS in this scenario. - NOT_AUDITED_NO_DNS_LOOKUP = 4, - - // This SCT was not audited, because it was recently checked and the cached - // inclusion result can be used. - NOT_AUDITED_ALREADY_CHECKED = 5, - - // This SCT is already pending an audit check, and thus can be - // de-duplicated. - NOT_AUDITED_ALREADY_PENDING_CHECK = 6, - - // This SCT was not audited, as an Entry Leaf Hash could not be calculated. - NOT_AUDITED_INVALID_LEAF_HASH = 7, - - SCT_CAN_BE_CHECKED_MAX -}; - -// Tracks the state of an individual Certificate Transparency Log's Merkle Tree. -// A CT Log constantly issues Signed Tree Heads, for which every older STH must -// be incorporated into the current/newer STH. As new certificates are logged, -// new SCTs are produced, and eventually, those SCTs are incorporated into the -// log and a new STH is produced, with there being an inclusion proof between -// the SCTs and the new STH, and a consistency proof between the old STH and the -// new STH. -// This class receives STHs provided by/observed by the embedder, with the -// assumption that STHs have been checked for consistency already. As SCTs are -// observed, their status is checked against the latest STH to ensure they were -// properly logged. If an SCT is newer than the latest STH, then this class -// verifies that when an STH is observed that should have incorporated those -// SCTs, the SCTs (and their corresponding entries) are present in the log. -// -// To accomplish this, this class needs to be notified of when new SCTs are -// observed and when new STHs are observed. Once both SCTs and at least one -// STH have been provided, the status for a given SCT can be queried by -// calling GetLogEntryInclusionCheck. -class SingleTreeTracker { - public: - enum SCTInclusionStatus { - // SCT was not observed by this class and is not currently pending - // inclusion check. As there's no evidence the SCT this status relates - // to is verified (it was never observed via OnSCTVerified), nothing - // is done with it. - SCT_NOT_OBSERVED, - - // SCT was observed but the STH known to this class is not old - // enough to check for inclusion, so a newer STH is needed first. - SCT_PENDING_NEWER_STH, - - // SCT is known and there's a new-enough STH to check inclusion against. - // It's in the process of being checked for inclusion. - SCT_PENDING_INCLUSION_CHECK, - - // Inclusion check succeeded. - SCT_INCLUDED_IN_LOG, - }; - - // Tracks new STHs and SCTs received that were issued by |ct_log|. - // The |dns_client| will be used to obtain inclusion proofs for these SCTs, - // where possible. It is not optional. - // The |host_resolver| will be used to ensure that DNS requests performed to - // obtain inclusion proofs do not compromise the user's privacy. It is not - // optional. It is assumed that it caches DNS lookups. - SingleTreeTracker(scoped_refptr<const net::CTLogVerifier> ct_log, - LogDnsClient* dns_client, - net::HostResolver* host_resolver, - net::NetLog* net_log); - ~SingleTreeTracker(); - - // Enqueues |sct| for later inclusion checking of the given |cert|, so long as - // both of the following are true: - // a) The latest STH known for this log is older than |sct.timestamp| + - // Maximum Merge Delay. - // b) The |hostname| for which this certificate was issued has previously been - // resolved to an IP address using a DNS lookup, and the network has not - // changed since. This ensures that performing an inclusion check over DNS - // will not leak information to the DNS resolver. - // Should only be called with SCTs issued by the log this instance tracks. - // Hostname may be an IP literal, but a DNS lookup will not have been - // performed in this case so inclusion checking will not be performed. - // TODO(eranm): Make sure not to perform any synchronous, blocking operation - // here as this callback is invoked during certificate validation. - void OnSCTVerified(base::StringPiece hostname, - net::X509Certificate* cert, - const net::ct::SignedCertificateTimestamp* sct); - - // After verification of the signature over the |sth|, uses this - // STH for future inclusion checks. - // Must only be called for STHs issued by the log this instance tracks. - void NewSTHObserved(const net::ct::SignedTreeHead& sth); - - // Returns the status of a given log entry that is assembled from |cert| and - // |sct|. If |cert| and |sct| were not previously observed, |sct| is not an - // SCT for |cert| or |sct| is not for this log, and SCT_NOT_OBSERVED will be - // returned. If the assembled entry is pending, |pending_lookup_securely| will - // be set to the value of the pending match's |lookup_securely| field. - SCTInclusionStatus GetLogEntryInclusionStatusForTesting( - net::X509Certificate* cert, - const net::ct::SignedCertificateTimestamp* sct, - bool* pending_lookup_securely = nullptr); - - private: - struct EntryToAudit; - struct EntryAuditState; - struct EntryAuditResult {}; - class NetworkObserver; - friend class NetworkObserver; - - // Less-than comparator that sorts EntryToAudits based on the SCT timestamp, - // with smaller (older) SCTs appearing less than larger (newer) SCTs. - struct OrderByTimestamp { - bool operator()(const EntryToAudit& lhs, const EntryToAudit& rhs) const; - }; - - // Requests an inclusion proof for each of the entries in |pending_entries_| - // until throttled by the LogDnsClient. - void ProcessPendingEntries(); - - // Returns the inclusion status of the given |entry|, similar to - // GetLogEntryInclusionStatus(). The |entry| is an internal representation of - // a certificate + SCT combination, and the |lookup_securely| value in |entry| - // is ignored. If |entry| has a pending status, |pending_lookup_securely| will - // be set to the value fo the pending match's |lookup_securely| field. - SCTInclusionStatus GetAuditedEntryInclusionStatus( - const EntryToAudit& entry, - bool* pending_lookup_securely); - - // Processes the result of obtaining an audit proof for |entry|. - // * If an audit proof was successfully obtained and validated, - // updates |checked_entries_| so that future calls to - // GetLogEntryInclusionStatus() will indicate the entry's - // inclusion. - // * If there was a failure to obtain or validate an inclusion - // proof, removes |entry| from the queue of entries to validate. - // Future calls to GetLogEntryInclusionStatus() will indicate the entry - // has not been observed. - void OnAuditProofObtained(const EntryToAudit& entry, int net_error); - - // Discards all entries pending inclusion check on network change. - // That is done to prevent the client looking up inclusion proofs for - // certificates received from one network, on another network, thus - // leaking state between networks. - void ResetPendingQueue(); - - // Clears entries to reduce memory overhead. - void OnMemoryPressure( - base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level); - - void LogAuditResultToNetLog(const EntryToAudit& entry, bool success); - - // Returns true if |hostname| has previously been looked up using DNS, and the - // network has not changed since. - bool WasLookedUpOverDNS(base::StringPiece hostname, bool* secure) const; - - // Holds the latest STH fetched and verified for this log. - net::ct::SignedTreeHead verified_sth_; - - // The log being tracked. - scoped_refptr<const net::CTLogVerifier> ct_log_; - - // Log entries waiting to be checked for inclusion, or being checked for - // inclusion, and their state. - std::map<EntryToAudit, EntryAuditState, OrderByTimestamp> pending_entries_; - - // A cache of leaf hashes identifying entries which were checked for - // inclusion (the key is the Leaf Hash of the log entry). - // NOTE: The current implementation does not cache failures, so the presence - // of an entry in |checked_entries_| indicates success. - // To extend support for caching failures, a success indicator should be - // added to the EntryAuditResult struct. - base::MRUCache<net::SHA256HashValue, EntryAuditResult> checked_entries_; - - LogDnsClient* dns_client_; - - net::HostResolver* host_resolver_; - - std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; - - net::NetLogWithSource net_log_; - - std::unique_ptr<NetworkObserver> network_observer_; - - base::WeakPtrFactory<SingleTreeTracker> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(SingleTreeTracker); -}; - -} // namespace certificate_transparency - -#endif // COMPONENTS_CERTIFICATE_TRANSPARENCY_SINGLE_TREE_TRACKER_H_
diff --git a/components/certificate_transparency/single_tree_tracker_unittest.cc b/components/certificate_transparency/single_tree_tracker_unittest.cc deleted file mode 100644 index 247d456..0000000 --- a/components/certificate_transparency/single_tree_tracker_unittest.cc +++ /dev/null
@@ -1,1049 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/certificate_transparency/single_tree_tracker.h" - -#include <string> -#include <utility> - -#include <memory> - -#include "base/memory/ptr_util.h" -#include "base/run_loop.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" -#include "base/test/metrics/histogram_tester.h" -#include "base/test/scoped_task_environment.h" -#include "components/base32/base32.h" -#include "components/certificate_transparency/log_dns_client.h" -#include "components/certificate_transparency/mock_log_dns_traffic.h" -#include "crypto/sha2.h" -#include "net/base/network_change_notifier.h" -#include "net/cert/ct_log_verifier.h" -#include "net/cert/ct_serialization.h" -#include "net/cert/merkle_tree_leaf.h" -#include "net/cert/signed_certificate_timestamp.h" -#include "net/cert/signed_tree_head.h" -#include "net/cert/x509_certificate.h" -#include "net/dns/dns_client.h" -#include "net/dns/mock_host_resolver.h" -#include "net/log/net_log.h" -#include "net/log/test_net_log.h" -#include "net/log/test_net_log_util.h" -#include "net/test/ct_test_util.h" -#include "net/url_request/url_request_filter.h" -#include "net/url_request/url_request_test_util.h" -#include "testing/gtest/include/gtest/gtest.h" - -using net::ct::SignedCertificateTimestamp; -using net::ct::SignedTreeHead; -using net::ct::GetSampleSignedTreeHead; -using net::ct::GetTestPublicKeyId; -using net::ct::GetTestPublicKey; -using net::ct::kSthRootHashLength; -using net::ct::GetX509CertSCT; - -namespace certificate_transparency { - -namespace { - -const char kHostname[] = "example.test"; -const char kCanCheckForInclusionHistogramName[] = - "Net.CertificateTransparency.CanInclusionCheckSCT"; -const char kInclusionCheckResultHistogramName[] = - "Net.CertificateTransparency.InclusionCheckResult"; - -const char kDNSRequestSuffix[] = "dns.example.com"; - -// These tests use a 0 time-to-live for HostCache entries, so all entries will -// be stale. This is fine because SingleTreeTracker considers stale entries to -// still be evidence that a DNS lookup was performed for a given hostname. -// Ignoring stale entries could be exploited, as an attacker could set their -// website's DNS record to have a very short TTL in order to avoid having -// inclusion checks performed on the SCTs they provide. -constexpr base::TimeDelta kZeroTTL; - -constexpr base::TimeDelta kMoreThanMMD = base::TimeDelta::FromHours(25); - -bool GetOldSignedTreeHead(SignedTreeHead* sth) { - sth->version = SignedTreeHead::V1; - sth->timestamp = base::Time::UnixEpoch() + - base::TimeDelta::FromMilliseconds(INT64_C(1348589665525)); - sth->tree_size = 12u; - - const uint8_t kOldSTHRootHash[] = { - 0x18, 0x04, 0x1b, 0xd4, 0x66, 0x50, 0x83, 0x00, 0x1f, 0xba, 0x8c, - 0x54, 0x11, 0xd2, 0xd7, 0x48, 0xe8, 0xab, 0xbf, 0xdc, 0xdf, 0xd9, - 0x21, 0x8c, 0xb0, 0x2b, 0x68, 0xa7, 0x8e, 0x7d, 0x4c, 0x23}; - memcpy(sth->sha256_root_hash, kOldSTHRootHash, kSthRootHashLength); - - sth->log_id = GetTestPublicKeyId(); - - const uint8_t kOldSTHSignatureData[] = { - 0x04, 0x03, 0x00, 0x47, 0x30, 0x45, 0x02, 0x20, 0x15, 0x7b, 0x23, - 0x42, 0xa2, 0x5f, 0x88, 0xc9, 0x0b, 0x30, 0xa6, 0xb4, 0x49, 0x50, - 0xb3, 0xab, 0xf5, 0x25, 0xfe, 0x27, 0xf0, 0x3f, 0x9a, 0xbf, 0xc1, - 0x16, 0x5a, 0x7a, 0xc0, 0x62, 0x2b, 0xbb, 0x02, 0x21, 0x00, 0xe6, - 0x57, 0xa3, 0xfe, 0xfc, 0x5a, 0x82, 0x9b, 0x29, 0x46, 0x15, 0x1d, - 0xbc, 0xfd, 0x9e, 0x87, 0x7f, 0xd0, 0x00, 0x5d, 0x62, 0x4f, 0x9a, - 0x1a, 0x9f, 0x20, 0x79, 0xd0, 0xc1, 0x34, 0x2e, 0x08}; - base::StringPiece sp(reinterpret_cast<const char*>(kOldSTHSignatureData), - sizeof(kOldSTHSignatureData)); - return DecodeDigitallySigned(&sp, &(sth->signature)) && sp.empty(); -} - -scoped_refptr<SignedCertificateTimestamp> GetSCT() { - scoped_refptr<SignedCertificateTimestamp> sct; - - // TODO(eranm): Move setting of the origin field to ct_test_util.cc - GetX509CertSCT(&sct); - sct->origin = SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE; - return sct; -} - -std::string LeafHash(const net::X509Certificate* cert, - const SignedCertificateTimestamp* sct) { - net::ct::MerkleTreeLeaf leaf; - if (!GetMerkleTreeLeaf(cert, sct, &leaf)) - return std::string(); - - std::string leaf_hash; - if (!HashMerkleTreeLeaf(leaf, &leaf_hash)) - return std::string(); - - return leaf_hash; -} - -std::string Base32LeafHash(const net::X509Certificate* cert, - const SignedCertificateTimestamp* sct) { - std::string leaf_hash = LeafHash(cert, sct); - if (leaf_hash.empty()) - return std::string(); - - return base32::Base32Encode(leaf_hash, - base32::Base32EncodePolicy::OMIT_PADDING); -} - -// Fills in |sth| for a tree of size 2, where the root hash is a hash of -// the test SCT (from GetX509CertSCT) and another entry, -// whose hash is '0a' 32 times. -bool GetSignedTreeHeadForTreeOfSize2(SignedTreeHead* sth) { - sth->version = SignedTreeHead::V1; - // Timestamp is after the timestamp of the test SCT (GetX509CertSCT) - // to indicate it can be audited using this STH. - sth->timestamp = base::Time::UnixEpoch() + - base::TimeDelta::FromMilliseconds(INT64_C(1365354256089)); - sth->tree_size = 2; - // Root hash is: - // HASH (0x01 || HASH(log entry made of test SCT) || HASH(0x0a * 32)) - // The proof provided by FillVectorWithValidAuditProofForTreeOfSize2 would - // validate with this root hash for the log entry made of the test SCT + - // cert. - const uint8_t kRootHash[] = {0x16, 0x80, 0xbd, 0x5a, 0x1b, 0xc1, 0xb6, 0xcf, - 0x1b, 0x7e, 0x77, 0x41, 0xeb, 0xed, 0x86, 0x8b, - 0x73, 0x81, 0x87, 0xf5, 0xab, 0x93, 0x6d, 0xb2, - 0x0a, 0x79, 0x0d, 0x9e, 0x40, 0x55, 0xc3, 0xe6}; - memcpy(sth->sha256_root_hash, reinterpret_cast<const char*>(kRootHash), - kSthRootHashLength); - - sth->log_id = GetTestPublicKeyId(); - - // valid signature over the STH, using the test log key at: - // https://github.com/google/certificate-transparency/blob/master/test/testdata/ct-server-key.pem - const uint8_t kTreeHeadSignatureData[] = { - 0x04, 0x03, 0x00, 0x46, 0x30, 0x44, 0x02, 0x20, 0x25, 0xa1, 0x9d, - 0x7b, 0xf6, 0xe6, 0xfc, 0x47, 0xa7, 0x2d, 0xef, 0x6b, 0xf4, 0x84, - 0x71, 0xb7, 0x7b, 0x7e, 0xd4, 0x4c, 0x7a, 0x5c, 0x4f, 0x9a, 0xb7, - 0x04, 0x71, 0x6e, 0xd0, 0xa8, 0x0f, 0x53, 0x02, 0x20, 0x27, 0xe5, - 0xed, 0x7d, 0xc3, 0x5d, 0x4c, 0xf0, 0x67, 0x35, 0x5d, 0x8a, 0x10, - 0xae, 0x25, 0x87, 0x1a, 0xef, 0xea, 0xd2, 0xf7, 0xe3, 0x73, 0x2f, - 0x07, 0xb3, 0x4b, 0xea, 0x5b, 0xdd, 0x81, 0x2d}; - - base::StringPiece sp(reinterpret_cast<const char*>(kTreeHeadSignatureData), - sizeof(kTreeHeadSignatureData)); - return DecodeDigitallySigned(&sp, &sth->signature); -} - -void FillVectorWithValidAuditProofForTreeOfSize2( - std::vector<std::string>* out_proof) { - std::string node(crypto::kSHA256Length, '\0'); - for (size_t i = 0; i < crypto::kSHA256Length; ++i) { - node[i] = static_cast<char>(0x0a); - } - out_proof->push_back(node); -} - -void AddCacheEntry(net::HostCache* cache, - const std::string& hostname, - bool secure, - net::HostCache::Entry::Source source, - base::TimeDelta ttl) { - auto key = net::HostCache::Key(hostname, net::ADDRESS_FAMILY_UNSPECIFIED, 0); - key.secure = secure; - cache->Set(key, net::HostCache::Entry(net::OK, net::AddressList(), source), - base::TimeTicks::Now(), ttl); -} - -} // namespace - -class SingleTreeTrackerTest : public ::testing::Test { - void SetUp() override { - log_ = net::CTLogVerifier::Create(GetTestPublicKey(), "testlog", - kDNSRequestSuffix); - - ASSERT_TRUE(log_); - ASSERT_EQ(log_->key_id(), GetTestPublicKeyId()); - - const std::string der_test_cert(net::ct::GetDerEncodedX509Cert()); - chain_ = net::X509Certificate::CreateFromBytes(der_test_cert.data(), - der_test_cert.length()); - ASSERT_TRUE(chain_.get()); - GetX509CertSCT(&cert_sct_); - cert_sct_->origin = SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE; - - net_change_notifier_ = - base::WrapUnique(net::NetworkChangeNotifier::CreateMock()); - mock_dns_.InitializeDnsConfig(); - - net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance(); - filter->AddHostnameInterceptor( - "https", "mock.http", - std::make_unique<MockLogDnsTraffic::DohJobInterceptor>()); - } - - void TearDown() override { - net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance(); - filter->ClearHandlers(); - } - - protected: - void CreateTreeTracker() { - log_dns_client_ = std::make_unique<LogDnsClient>( - mock_dns_.CreateDnsClient(), new net::TestURLRequestContext(), - net_log_with_source_, 1); - - tree_tracker_ = std::make_unique<SingleTreeTracker>( - log_, log_dns_client_.get(), &host_resolver_, &net_log_); - } - - void CreateTreeTrackerWithDefaultDnsExpectation() { - // Default to throttling requests as it means observed log entries will - // be frozen in a pending state, simplifying testing of the - // SingleTreeTracker. - ASSERT_TRUE(ExpectLeafIndexRequestAndThrottle(chain_, cert_sct_)); - CreateTreeTracker(); - } - - // Configured the |mock_dns_| to expect a request for the leaf index - // and have th mock DNS client throttle it. - bool ExpectLeafIndexRequestAndThrottle( - const scoped_refptr<net::X509Certificate>& chain, - const scoped_refptr<SignedCertificateTimestamp>& sct) { - return mock_dns_.ExpectRequestAndSocketError( - Base32LeafHash(chain.get(), sct.get()) + ".hash." + kDNSRequestSuffix, - net::Error::ERR_TEMPORARILY_THROTTLED); - } - - bool MatchAuditingResultInNetLog(net::TestNetLog& net_log, - std::string expected_leaf_hash, - bool expected_success) { - net::TestNetLogEntry::List entries; - - net_log.GetEntries(&entries); - if (entries.size() == 0) - return false; - - size_t pos = net::ExpectLogContainsSomewhere( - entries, 0, net::NetLogEventType::CT_LOG_ENTRY_AUDITED, - net::NetLogEventPhase::NONE); - - const net::TestNetLogEntry& logged_entry = entries[pos]; - - std::string logged_log_id, logged_leaf_hash; - if (!logged_entry.GetStringValue("log_id", &logged_log_id) || - !logged_entry.GetStringValue("log_entry", &logged_leaf_hash)) - return false; - - if (base::HexEncode(GetTestPublicKeyId().data(), - GetTestPublicKeyId().size()) != logged_log_id) - return false; - - if (base::HexEncode(expected_leaf_hash.data(), expected_leaf_hash.size()) != - logged_leaf_hash) - return false; - - bool logged_success; - if (!logged_entry.GetBooleanValue("success", &logged_success)) - return false; - - return logged_success == expected_success; - } - - base::test::ScopedTaskEnvironment task_environment_{ - base::test::ScopedTaskEnvironment::MainThreadType::IO}; - MockLogDnsTraffic mock_dns_; - scoped_refptr<const net::CTLogVerifier> log_; - std::unique_ptr<net::NetworkChangeNotifier> net_change_notifier_; - std::unique_ptr<LogDnsClient> log_dns_client_; - net::MockCachingHostResolver host_resolver_; - std::unique_ptr<SingleTreeTracker> tree_tracker_; - scoped_refptr<net::X509Certificate> chain_; - scoped_refptr<SignedCertificateTimestamp> cert_sct_; - net::TestNetLog net_log_; - net::NetLogWithSource net_log_with_source_; -}; - -// Test that an SCT is discarded if the HostResolver cache does not indicate -// that the hostname lookup was done using DNS. To perform an inclusion check -// in this case could compromise privacy, as the DNS resolver would learn that -// the user had visited that host. -TEST_F(SingleTreeTrackerTest, DiscardsSCTWhenHostnameNotLookedUpUsingDNS) { - CreateTreeTrackerWithDefaultDnsExpectation(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, - net::HostCache::Entry::SOURCE_UNKNOWN, kZeroTTL); - - base::HistogramTester histograms; - // Provide an STH to the tree_tracker_. - SignedTreeHead sth; - GetSampleSignedTreeHead(&sth); - tree_tracker_->NewSTHObserved(sth); - - // Make sure the SCT status is the same as if there's no STH for this log. - EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - - tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); - - // The status for this SCT should still be 'not observed'. - EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - - // Exactly one value should be logged, indicating that the SCT could not be - // checked for inclusion because of no prior DNS lookup for this hostname. - histograms.ExpectUniqueSample(kCanCheckForInclusionHistogramName, 4, 1); - - // Nothing should be logged in the result histogram or net log since an - // inclusion check wasn't performed. - histograms.ExpectTotalCount(kInclusionCheckResultHistogramName, 0); - EXPECT_EQ(0u, net_log_.GetSize()); -} - -// Test that an SCT is discarded if the hostname it was obtained from is an IP -// literal. To perform an inclusion check in this case could compromise privacy, -// as the DNS resolver would learn that the user had visited that host. -TEST_F(SingleTreeTrackerTest, DiscardsSCTWhenHostnameIsIPLiteral) { - CreateTreeTrackerWithDefaultDnsExpectation(); - - base::HistogramTester histograms; - // Provide an STH to the tree_tracker_. - SignedTreeHead sth; - GetSampleSignedTreeHead(&sth); - tree_tracker_->NewSTHObserved(sth); - - // Make sure the SCT status is the same as if there's no STH for this log. - EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - - tree_tracker_->OnSCTVerified("::1", chain_.get(), cert_sct_.get()); - - // The status for this SCT should still be 'not observed'. - EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - - // Exactly one value should be logged, indicating that the SCT could not be - // checked for inclusion because of no prior DNS lookup for this hostname - // (because it's an IP literal). - histograms.ExpectUniqueSample(kCanCheckForInclusionHistogramName, 4, 1); - - // Nothing should be logged in the result histogram or net log since an - // inclusion check wasn't performed. - histograms.ExpectTotalCount(kInclusionCheckResultHistogramName, 0); - EXPECT_EQ(0u, net_log_.GetSize()); -} - -// Test that an SCT is discarded if the network has changed since the hostname -// lookup was performed. To perform an inclusion check in this case could -// compromise privacy, as the current DNS resolver would learn that the user had -// visited that host (it would not already know this already because the -// hostname lookup was performed on a different network, using a different DNS -// resolver). -TEST_F(SingleTreeTrackerTest, - DiscardsSCTWhenHostnameLookedUpUsingDNSOnDiffNetwork) { - CreateTreeTrackerWithDefaultDnsExpectation(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, - net::HostCache::Entry::SOURCE_DNS, kZeroTTL); - - // Simulate network change. - host_resolver_.GetHostCache()->Invalidate(); - - base::HistogramTester histograms; - // Provide an STH to the tree_tracker_. - SignedTreeHead sth; - GetSampleSignedTreeHead(&sth); - tree_tracker_->NewSTHObserved(sth); - - // Make sure the SCT status is the same as if there's no STH for this log. - EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - - tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); - - // The status for this SCT should still be 'not observed'. - EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - - // Exactly one value should be logged, indicating that the SCT could not be - // checked for inclusion because of no prior DNS lookup for this hostname on - // the current network. - histograms.ExpectUniqueSample(kCanCheckForInclusionHistogramName, 4, 1); - - // Nothing should be logged in the result histogram or net log since an - // inclusion check wasn't performed. - histograms.ExpectTotalCount(kInclusionCheckResultHistogramName, 0); - EXPECT_EQ(0u, net_log_.GetSize()); -} - -TEST_F(SingleTreeTrackerTest, EntriesIndistinguishedBySecurity) { - CreateTreeTrackerWithDefaultDnsExpectation(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, - net::HostCache::Entry::SOURCE_DNS, kZeroTTL); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, true /* secure */, - net::HostCache::Entry::SOURCE_DNS, kZeroTTL); - - base::HistogramTester histograms; - // Provide an STH to the tree_tracker_. - SignedTreeHead sth; - GetSampleSignedTreeHead(&sth); - tree_tracker_->NewSTHObserved(sth); - - // Make sure the SCT status is the same as if there's no STH for this log. - EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - - tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); - - // The status for this SCT should be 'pending inclusion check' with - // |pending_lookup_securely| set to true since the cache check will return the - // secure key. - bool pending_lookup_securely; - EXPECT_EQ(SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get(), &pending_lookup_securely)); - EXPECT_TRUE(pending_lookup_securely); - - // Exactly one value should be logged, indicating the SCT can be checked for - // inclusion, as |tree_tracker_| did have a valid STH when it was notified - // of a new SCT. - histograms.ExpectUniqueSample(kCanCheckForInclusionHistogramName, 2, 1); - - // Simulate network change. - host_resolver_.GetHostCache()->Invalidate(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, - net::HostCache::Entry::SOURCE_DNS, kZeroTTL); - - tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); - - // The status for this SCT should still be 'pending inclusion check' with - // |pending_lookup_securely| set to true. - EXPECT_EQ(SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get(), &pending_lookup_securely)); - EXPECT_TRUE(pending_lookup_securely); - - // Another value should be logged, indicating that there is already a - // pending audit check for this SCT. - histograms.ExpectBucketCount(kCanCheckForInclusionHistogramName, 6, 1); - // Nothing should be logged in the result histogram or net log since an - // inclusion check wasn't performed. - histograms.ExpectTotalCount(kInclusionCheckResultHistogramName, 0); - EXPECT_EQ(0u, net_log_.GetSize()); -} - -// Test that an SCT is classified as pending for a newer STH if the -// SingleTreeTracker has not seen any STHs so far. -TEST_F(SingleTreeTrackerTest, CorrectlyClassifiesUnobservedSCTNoSTH) { - CreateTreeTrackerWithDefaultDnsExpectation(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, - net::HostCache::Entry::SOURCE_DNS, kZeroTTL); - - base::HistogramTester histograms; - // First make sure the SCT has not been observed at all. - EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - - tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); - - // Since no STH was provided to the tree_tracker_ the status should be that - // the SCT is pending a newer STH. - EXPECT_EQ(SingleTreeTracker::SCT_PENDING_NEWER_STH, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - - // Expect logging of a value indicating a valid STH is required. - histograms.ExpectUniqueSample(kCanCheckForInclusionHistogramName, 0, 1); - EXPECT_EQ(0u, net_log_.GetSize()); -} - -// Test that an SCT is classified as pending an inclusion check if the -// SingleTreeTracker has a fresh-enough STH to check inclusion against. -TEST_F(SingleTreeTrackerTest, CorrectlyClassifiesUnobservedSCTWithRecentSTH) { - CreateTreeTrackerWithDefaultDnsExpectation(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, - net::HostCache::Entry::SOURCE_DNS, kZeroTTL); - - base::HistogramTester histograms; - // Provide an STH to the tree_tracker_. - SignedTreeHead sth; - GetSampleSignedTreeHead(&sth); - tree_tracker_->NewSTHObserved(sth); - - // Make sure the SCT status is the same as if there's no STH for - // this log. - EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - - tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); - - // The status for this SCT should be 'pending inclusion check' since the STH - // provided at the beginning of the test is newer than the SCT. - EXPECT_EQ(SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - - // Exactly one value should be logged, indicating the SCT can be checked for - // inclusion, as |tree_tracker_| did have a valid STH when it was notified - // of a new SCT. - histograms.ExpectUniqueSample(kCanCheckForInclusionHistogramName, 2, 1); - // Nothing should be logged in the result histogram since inclusion check - // didn't finish. - histograms.ExpectTotalCount(kInclusionCheckResultHistogramName, 0); - EXPECT_EQ(0u, net_log_.GetSize()); -} - -// Test that the SingleTreeTracker correctly queues verified SCTs for inclusion -// checking such that, upon receiving a fresh STH, it changes the SCT's status -// from pending newer STH to pending inclusion check. -TEST_F(SingleTreeTrackerTest, CorrectlyUpdatesSCTStatusOnNewSTH) { - CreateTreeTrackerWithDefaultDnsExpectation(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, - net::HostCache::Entry::SOURCE_DNS, kZeroTTL); - - base::HistogramTester histograms; - // Report an observed SCT and make sure it's in the pending newer STH - // state. - tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); - EXPECT_EQ(SingleTreeTracker::SCT_PENDING_NEWER_STH, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - histograms.ExpectTotalCount(kCanCheckForInclusionHistogramName, 1); - - // Provide with a fresh STH - SignedTreeHead sth; - GetSampleSignedTreeHead(&sth); - tree_tracker_->NewSTHObserved(sth); - - // Test that its status has changed. - EXPECT_EQ(SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - // Check that no additional UMA was logged for this case as the histogram is - // only supposed to measure the state of newly-observed SCTs, not pending - // ones. - histograms.ExpectTotalCount(kCanCheckForInclusionHistogramName, 1); - EXPECT_EQ(0u, net_log_.GetSize()); -} - -// Test that the SingleTreeTracker does not change an SCT's status if an STH -// from the log it was issued by is observed, but that STH is too old to check -// inclusion against. -TEST_F(SingleTreeTrackerTest, DoesNotUpdatesSCTStatusOnOldSTH) { - CreateTreeTrackerWithDefaultDnsExpectation(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, - net::HostCache::Entry::SOURCE_DNS, kZeroTTL); - - // Notify of an SCT and make sure it's in the 'pending newer STH' state. - tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); - EXPECT_EQ(SingleTreeTracker::SCT_PENDING_NEWER_STH, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - - // Provide an old STH for the same log. - SignedTreeHead sth; - GetOldSignedTreeHead(&sth); - tree_tracker_->NewSTHObserved(sth); - - // Make sure the SCT's state hasn't changed. - EXPECT_EQ(SingleTreeTracker::SCT_PENDING_NEWER_STH, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - EXPECT_EQ(0u, net_log_.GetSize()); -} - -// Test that the SingleTreeTracker correctly logs that an SCT is pending a new -// STH, when it has a valid STH, but the observed SCT is not covered by the -// STH. -TEST_F(SingleTreeTrackerTest, LogsUMAForNewSCTAndOldSTH) { - CreateTreeTrackerWithDefaultDnsExpectation(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, - net::HostCache::Entry::SOURCE_DNS, kZeroTTL); - - base::HistogramTester histograms; - // Provide an old STH for the same log. - SignedTreeHead sth; - GetOldSignedTreeHead(&sth); - tree_tracker_->NewSTHObserved(sth); - - histograms.ExpectTotalCount(kCanCheckForInclusionHistogramName, 0); - - // Notify of an SCT and make sure it's in the 'pending newer STH' state. - tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); - - // Exactly one value should be logged, indicating the SCT cannot be checked - // for inclusion as the STH is too old. - histograms.ExpectUniqueSample(kCanCheckForInclusionHistogramName, 1, 1); - EXPECT_EQ(0u, net_log_.GetSize()); -} - -// Test that an entry transitions to the "not found" state if the LogDnsClient -// fails to get a leaf index. -TEST_F(SingleTreeTrackerTest, TestEntryNotPendingAfterLeafIndexFetchFailure) { - ASSERT_TRUE(mock_dns_.ExpectRequestAndSocketError( - Base32LeafHash(chain_.get(), cert_sct_.get()) + ".hash." + - kDNSRequestSuffix, - net::Error::ERR_FAILED)); - - CreateTreeTracker(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, - net::HostCache::Entry::SOURCE_DNS, kZeroTTL); - - tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); - EXPECT_EQ(SingleTreeTracker::SCT_PENDING_NEWER_STH, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - - // Provide with a fresh STH - SignedTreeHead sth; - GetSampleSignedTreeHead(&sth); - tree_tracker_->NewSTHObserved(sth); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - // There should have been one NetLog event, logged with failure. - EXPECT_TRUE(MatchAuditingResultInNetLog( - net_log_, LeafHash(chain_.get(), cert_sct_.get()), false)); -} - -// Test that an entry transitions to the "not found" state if the LogDnsClient -// succeeds to get a leaf index but fails to get an inclusion proof. -TEST_F(SingleTreeTrackerTest, TestEntryNotPendingAfterInclusionCheckFailure) { - // Return 12 as the index of this leaf. - ASSERT_TRUE(mock_dns_.ExpectLeafIndexRequestAndResponse( - Base32LeafHash(chain_.get(), cert_sct_.get()) + ".hash." + - kDNSRequestSuffix, - 12)); - // Expect a request for an inclusion proof for leaf #12 in a tree of size - // 21, which is the size of the tree in the STH returned by - // GetSampleSignedTreeHead. - ASSERT_TRUE(mock_dns_.ExpectRequestAndSocketError( - std::string("0.12.21.tree.") + kDNSRequestSuffix, - net::Error::ERR_FAILED)); - - CreateTreeTracker(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, - net::HostCache::Entry::SOURCE_DNS, kZeroTTL); - - tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); - EXPECT_EQ(SingleTreeTracker::SCT_PENDING_NEWER_STH, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - - // Provide with a fresh STH - SignedTreeHead sth; - GetSampleSignedTreeHead(&sth); - tree_tracker_->NewSTHObserved(sth); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - // There should have been one NetLog event, logged with failure. - EXPECT_TRUE(MatchAuditingResultInNetLog( - net_log_, LeafHash(chain_.get(), cert_sct_.get()), false)); -} - -// Test that an entry transitions to the "included" state if the LogDnsClient -// succeeds to get a leaf index and an inclusion proof. -TEST_F(SingleTreeTrackerTest, TestEntryIncludedAfterInclusionCheckSuccess) { - std::vector<std::string> audit_proof; - FillVectorWithValidAuditProofForTreeOfSize2(&audit_proof); - - // Return 0 as the index for this leaf, so the proof provided - // later on would verify. - ASSERT_TRUE(mock_dns_.ExpectLeafIndexRequestAndResponse( - Base32LeafHash(chain_.get(), cert_sct_.get()) + ".hash." + - kDNSRequestSuffix, - 0)); - // The STH (later on) is for a tree of size 2 and the entry has index 0 - // in the tree, so expect an inclusion proof for entry 0 in a tree - // of size 2 (0.0.2). - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - std::string("0.0.2.tree.") + kDNSRequestSuffix, audit_proof.begin(), - audit_proof.begin() + 1)); - - CreateTreeTracker(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, - net::HostCache::Entry::SOURCE_DNS, kZeroTTL); - - tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); - EXPECT_EQ(SingleTreeTracker::SCT_PENDING_NEWER_STH, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - - // Provide with a fresh STH, which is for a tree of size 2. - SignedTreeHead sth; - ASSERT_TRUE(GetSignedTreeHeadForTreeOfSize2(&sth)); - ASSERT_TRUE(log_->VerifySignedTreeHead(sth)); - - tree_tracker_->NewSTHObserved(sth); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(SingleTreeTracker::SCT_INCLUDED_IN_LOG, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - // There should have been one NetLog event, with success logged. - EXPECT_TRUE(MatchAuditingResultInNetLog( - net_log_, LeafHash(chain_.get(), cert_sct_.get()), true)); -} - -// Tests that inclusion checks are aborted and SCTs discarded if under critical -// memory pressure. -TEST_F(SingleTreeTrackerTest, - TestInclusionCheckCancelledIfUnderMemoryPressure) { - CreateTreeTracker(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, - net::HostCache::Entry::SOURCE_DNS, kZeroTTL); - - tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); - EXPECT_EQ(SingleTreeTracker::SCT_PENDING_NEWER_STH, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - - // Provide with a fresh STH, which is for a tree of size 2. - SignedTreeHead sth; - ASSERT_TRUE(GetSignedTreeHeadForTreeOfSize2(&sth)); - ASSERT_TRUE(log_->VerifySignedTreeHead(sth)); - - // Make the first event that is processed a critical memory pressure - // notification. This should be handled before the response to the first DNS - // request, so no requests after the first one should be sent (the leaf index - // request). - base::MemoryPressureListener::NotifyMemoryPressure( - base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL); - - ASSERT_TRUE(mock_dns_.ExpectLeafIndexRequestAndResponse( - Base32LeafHash(chain_.get(), cert_sct_.get()) + ".hash." + - kDNSRequestSuffix, - 0)); - - tree_tracker_->NewSTHObserved(sth); - base::RunLoop().RunUntilIdle(); - - // Expect the SCT to have been discarded. - EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); -} - -// Test that pending entries transition states correctly according to the -// STHs provided: -// * Start without an STH. -// * Add a collection of entries with mixed timestamps (i.e. SCTs not added -// in the order of their timestamps). -// * Provide an STH that covers some of the entries, test these are audited. -// * Provide another STH that covers more of the entries, test that the entries -// already audited are not audited again and that those that need to be -// audited are audited, while those that are not covered by that STH are -// not audited. -TEST_F(SingleTreeTrackerTest, TestMultipleEntriesTransitionStateCorrectly) { - SignedTreeHead old_sth; - GetOldSignedTreeHead(&old_sth); - - SignedTreeHead new_sth; - GetSampleSignedTreeHead(&new_sth); - - base::TimeDelta kLessThanMMD = base::TimeDelta::FromHours(23); - - // Assert the gap between the two timestamps is big enough so that - // all assumptions below on which SCT can be audited with the - // new STH are true. - ASSERT_LT(old_sth.timestamp + (kMoreThanMMD * 2), new_sth.timestamp); - - // Oldest SCT - auditable by the old and new STHs. - scoped_refptr<SignedCertificateTimestamp> oldest_sct(GetSCT()); - oldest_sct->timestamp = old_sth.timestamp - kMoreThanMMD; - - // SCT that's older than the old STH's timestamp but by less than the MMD, - // so not auditable by old STH. - scoped_refptr<SignedCertificateTimestamp> not_auditable_by_old_sth_sct( - GetSCT()); - not_auditable_by_old_sth_sct->timestamp = old_sth.timestamp - kLessThanMMD; - - // SCT that's newer than the old STH's timestamp so is only auditable by - // the new STH. - scoped_refptr<SignedCertificateTimestamp> newer_than_old_sth_sct(GetSCT()); - newer_than_old_sth_sct->timestamp = old_sth.timestamp + kLessThanMMD; - - // SCT that's older than the new STH's timestamp but by less than the MMD, - // so isn't auditable by the new STH. - scoped_refptr<SignedCertificateTimestamp> not_auditable_by_new_sth_sct( - GetSCT()); - not_auditable_by_new_sth_sct->timestamp = new_sth.timestamp - kLessThanMMD; - - // SCT that's newer than the new STH's timestamp so isn't auditable by the - // the new STH. - scoped_refptr<SignedCertificateTimestamp> newer_than_new_sth_sct(GetSCT()); - newer_than_new_sth_sct->timestamp = new_sth.timestamp + kLessThanMMD; - - // Set up DNS expectations based on inclusion proof request order. - ASSERT_TRUE(ExpectLeafIndexRequestAndThrottle(chain_, oldest_sct)); - ASSERT_TRUE( - ExpectLeafIndexRequestAndThrottle(chain_, not_auditable_by_old_sth_sct)); - ASSERT_TRUE( - ExpectLeafIndexRequestAndThrottle(chain_, newer_than_old_sth_sct)); - CreateTreeTracker(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, - net::HostCache::Entry::SOURCE_DNS, kZeroTTL); - - // Add SCTs in mixed order. - tree_tracker_->OnSCTVerified(kHostname, chain_.get(), - newer_than_new_sth_sct.get()); - tree_tracker_->OnSCTVerified(kHostname, chain_.get(), oldest_sct.get()); - tree_tracker_->OnSCTVerified(kHostname, chain_.get(), - not_auditable_by_new_sth_sct.get()); - tree_tracker_->OnSCTVerified(kHostname, chain_.get(), - newer_than_old_sth_sct.get()); - tree_tracker_->OnSCTVerified(kHostname, chain_.get(), - not_auditable_by_old_sth_sct.get()); - - // Ensure all are in the PENDING_NEWER_STH state. - for (const auto& sct : - {oldest_sct, not_auditable_by_old_sth_sct, newer_than_old_sth_sct, - not_auditable_by_new_sth_sct, newer_than_new_sth_sct}) { - ASSERT_EQ(SingleTreeTracker::SCT_PENDING_NEWER_STH, - tree_tracker_->GetLogEntryInclusionStatusForTesting(chain_.get(), - sct.get())) - << "SCT age: " << sct->timestamp; - } - - // Provide the old STH, ensure only the oldest one is auditable. - tree_tracker_->NewSTHObserved(old_sth); - // Ensure all but the oldest are in the PENDING_NEWER_STH state. - ASSERT_EQ(SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), oldest_sct.get())); - - for (const auto& sct : - {not_auditable_by_old_sth_sct, newer_than_old_sth_sct, - not_auditable_by_new_sth_sct, newer_than_new_sth_sct}) { - ASSERT_EQ(SingleTreeTracker::SCT_PENDING_NEWER_STH, - tree_tracker_->GetLogEntryInclusionStatusForTesting(chain_.get(), - sct.get())) - << "SCT age: " << sct->timestamp; - } - - // Provide the newer one, ensure two more are auditable but the - // rest aren't. - tree_tracker_->NewSTHObserved(new_sth); - - for (const auto& sct : - {not_auditable_by_old_sth_sct, newer_than_old_sth_sct}) { - ASSERT_EQ(SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, - tree_tracker_->GetLogEntryInclusionStatusForTesting(chain_.get(), - sct.get())) - << "SCT age: " << sct->timestamp; - } - - for (const auto& sct : - {not_auditable_by_new_sth_sct, newer_than_new_sth_sct}) { - ASSERT_EQ(SingleTreeTracker::SCT_PENDING_NEWER_STH, - tree_tracker_->GetLogEntryInclusionStatusForTesting(chain_.get(), - sct.get())) - << "SCT age: " << sct->timestamp; - } -} - -// Test that if a request for an entry is throttled, it remains in a -// pending state. - -// Test that if several entries are throttled, when the LogDnsClient notifies -// of un-throttling all entries are handled. -TEST_F(SingleTreeTrackerTest, TestThrottledEntryGetsHandledAfterUnthrottling) { - std::vector<std::string> audit_proof; - FillVectorWithValidAuditProofForTreeOfSize2(&audit_proof); - - ASSERT_TRUE(mock_dns_.ExpectLeafIndexRequestAndResponse( - Base32LeafHash(chain_.get(), cert_sct_.get()) + ".hash." + - kDNSRequestSuffix, - 0)); - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - std::string("0.0.2.tree.") + kDNSRequestSuffix, audit_proof.begin(), - audit_proof.begin() + 1)); - - scoped_refptr<SignedCertificateTimestamp> second_sct(GetSCT()); - second_sct->timestamp -= base::TimeDelta::FromHours(1); - - // Process request for |second_sct| - ASSERT_TRUE(mock_dns_.ExpectLeafIndexRequestAndResponse( - Base32LeafHash(chain_.get(), second_sct.get()) + ".hash." + - kDNSRequestSuffix, - 1)); - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - std::string("0.1.2.tree.") + kDNSRequestSuffix, audit_proof.begin(), - audit_proof.begin() + 1)); - - CreateTreeTracker(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, - net::HostCache::Entry::SOURCE_DNS, kZeroTTL); - - SignedTreeHead sth; - ASSERT_TRUE(GetSignedTreeHeadForTreeOfSize2(&sth)); - tree_tracker_->NewSTHObserved(sth); - - tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); - tree_tracker_->OnSCTVerified(kHostname, chain_.get(), second_sct.get()); - - // Both entries should be in the pending state, the first because the - // LogDnsClient did not invoke the callback yet, the second one because - // the LogDnsClient is "busy" with the first entry and so would throttle. - ASSERT_EQ(SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - ASSERT_EQ(SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), second_sct.get())); - - // Process pending DNS queries so later assertions are on handling - // of the entries based on replies received. - base::RunLoop().RunUntilIdle(); - - // Check that the first sct is included in the log. - ASSERT_EQ(SingleTreeTracker::SCT_INCLUDED_IN_LOG, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - - // Check that the second SCT got an invalid proof and is not included, rather - // than being in the pending state. - ASSERT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), second_sct.get())); -} - -// Test that proof fetching failure due to DNS config errors is handled -// correctly: -// (1) Entry removed from pending queue. -// (2) UMA logged -TEST_F(SingleTreeTrackerTest, - TestProofLookupDueToBadDNSConfigHandledCorrectly) { - base::HistogramTester histograms; - // Provide an STH to the tree_tracker_. - SignedTreeHead sth; - GetSampleSignedTreeHead(&sth); - - // Clear existing DNS configuration, so that the DnsClient created - // by the MockLogDnsTraffic has no valid DnsConfig. - net_change_notifier_.reset(); - net_change_notifier_ = - base::WrapUnique(net::NetworkChangeNotifier::CreateMock()); - CreateTreeTracker(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, - net::HostCache::Entry::SOURCE_DNS, kZeroTTL); - - tree_tracker_->NewSTHObserved(sth); - tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); - - // Make sure the SCT status indicates the entry has been removed from - // the SingleTreeTracker's internal queue as the DNS lookup failed - // synchronously. - EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatusForTesting( - chain_.get(), cert_sct_.get())); - - // Exactly one value should be logged, indicating the SCT can be checked for - // inclusion, as |tree_tracker_| did have a valid STH when it was notified - // of a new SCT. - histograms.ExpectUniqueSample(kCanCheckForInclusionHistogramName, 2, 1); - // Failure due to DNS configuration should be logged in the result histogram. - histograms.ExpectUniqueSample(kInclusionCheckResultHistogramName, 3, 1); -} - -// Test that entries are no longer pending after a network state -// change. -TEST_F(SingleTreeTrackerTest, DiscardsPendingEntriesAfterNetworkChange) { - // Setup expectations for 2 SCTs to pass inclusion checking. - // However, the first should be cancelled half way through (when the network - // change occurs) and the second should be throttled (and then cancelled) so, - // by the end of test, neither should actually have passed the checks. - std::vector<std::string> audit_proof; - FillVectorWithValidAuditProofForTreeOfSize2(&audit_proof); - - ASSERT_TRUE(mock_dns_.ExpectLeafIndexRequestAndResponse( - Base32LeafHash(chain_.get(), cert_sct_.get()) + ".hash." + - kDNSRequestSuffix, - 0)); - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - std::string("0.0.2.tree.") + kDNSRequestSuffix, audit_proof.begin(), - audit_proof.begin() + 1)); - - scoped_refptr<SignedCertificateTimestamp> second_sct(GetSCT()); - second_sct->timestamp -= base::TimeDelta::FromHours(1); - - ASSERT_TRUE(mock_dns_.ExpectLeafIndexRequestAndResponse( - Base32LeafHash(chain_.get(), second_sct.get()) + ".hash." + - kDNSRequestSuffix, - 1)); - ASSERT_TRUE(mock_dns_.ExpectAuditProofRequestAndResponse( - std::string("0.1.2.tree.") + kDNSRequestSuffix, audit_proof.begin(), - audit_proof.begin() + 1)); - - CreateTreeTracker(); - AddCacheEntry(host_resolver_.GetHostCache(), kHostname, false /* secure */, - net::HostCache::Entry::SOURCE_DNS, kZeroTTL); - - // Provide an STH to the tree_tracker_. - SignedTreeHead sth; - GetSignedTreeHeadForTreeOfSize2(&sth); - tree_tracker_->NewSTHObserved(sth); - - tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); - tree_tracker_->OnSCTVerified(kHostname, chain_.get(), second_sct.get()); - - for (auto sct : {cert_sct_, second_sct}) { - EXPECT_EQ(SingleTreeTracker::SCT_PENDING_INCLUSION_CHECK, - tree_tracker_->GetLogEntryInclusionStatusForTesting(chain_.get(), - sct.get())); - } - - net_change_notifier_->NotifyObserversOfNetworkChangeForTests( - net::NetworkChangeNotifier::CONNECTION_UNKNOWN); - base::RunLoop().RunUntilIdle(); - - for (auto sct : {cert_sct_, second_sct}) { - EXPECT_EQ(SingleTreeTracker::SCT_NOT_OBSERVED, - tree_tracker_->GetLogEntryInclusionStatusForTesting(chain_.get(), - sct.get())); - } -} - -} // namespace certificate_transparency
diff --git a/components/certificate_transparency/sth_distributor.cc b/components/certificate_transparency/sth_distributor.cc deleted file mode 100644 index 3382095..0000000 --- a/components/certificate_transparency/sth_distributor.cc +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/certificate_transparency/sth_distributor.h" - -#include "base/metrics/histogram_macros.h" -#include "base/time/time.h" -#include "net/cert/signed_tree_head.h" - -namespace { -const uint8_t kPilotLogID[] = {0xa4, 0xb9, 0x09, 0x90, 0xb4, 0x18, 0x58, 0x14, - 0x87, 0xbb, 0x13, 0xa2, 0xcc, 0x67, 0x70, 0x0a, - 0x3c, 0x35, 0x98, 0x04, 0xf9, 0x1b, 0xdf, 0xb8, - 0xe3, 0x77, 0xcd, 0x0e, 0xc8, 0x0d, 0xdc, 0x10}; -} - -namespace certificate_transparency { - -STHDistributor::STHDistributor() - : observer_list_(base::ObserverListPolicy::EXISTING_ONLY) {} - -STHDistributor::~STHDistributor() = default; - -void STHDistributor::NewSTHObserved(const net::ct::SignedTreeHead& sth) { - auto it = std::find_if(observed_sths_.begin(), observed_sths_.end(), - [&sth](const net::ct::SignedTreeHead& other) { - return sth.log_id == other.log_id; - }); - - if (it == observed_sths_.end()) - observed_sths_.push_back(sth); - else - *it = sth; - - for (auto& observer : observer_list_) - observer.NewSTHObserved(sth); - - if (sth.log_id.compare(0, sth.log_id.size(), - reinterpret_cast<const char*>(kPilotLogID), - sizeof(kPilotLogID)) != 0) - return; - - const base::TimeDelta sth_age = base::Time::Now() - sth.timestamp; - UMA_HISTOGRAM_CUSTOM_TIMES("Net.CertificateTransparency.PilotSTHAge", sth_age, - base::TimeDelta::FromHours(1), - base::TimeDelta::FromDays(4), 100); -} - -void STHDistributor::RegisterObserver(STHObserver* observer) { - observer_list_.AddObserver(observer); - // Make a local copy, because notifying the |observer| of a - // new STH may result in this class being notified of a - // (different) new STH, thus invalidating the iterator. - std::vector<net::ct::SignedTreeHead> local_sths(observed_sths_); - - for (const auto& sth : local_sths) - observer->NewSTHObserved(sth); -} - -void STHDistributor::UnregisterObserver(STHObserver* observer) { - observer_list_.RemoveObserver(observer); -} - -} // namespace certificate_transparency
diff --git a/components/certificate_transparency/sth_distributor.h b/components/certificate_transparency/sth_distributor.h deleted file mode 100644 index db96a5d..0000000 --- a/components/certificate_transparency/sth_distributor.h +++ /dev/null
@@ -1,56 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_CERTIFICATE_TRANSPARENCY_STH_DISTRIBUTOR_H_ -#define COMPONENTS_CERTIFICATE_TRANSPARENCY_STH_DISTRIBUTOR_H_ - -#include <vector> - -#include "base/observer_list.h" -#include "components/certificate_transparency/sth_observer.h" -#include "components/certificate_transparency/sth_reporter.h" -#include "net/base/net_export.h" - -namespace net { -namespace ct { -struct SignedTreeHead; -} // namespace ct -} // namespace net - -namespace certificate_transparency { - -// A proxy for delegating new STH notifications to all registered -// observers. -// For each |observer| registered with RegisterObserver, the -// NewSTHObserved method will be called whenever the STHDistributor's -// NewSTHObserved method is invoked. -class STHDistributor : public STHObserver, public STHReporter { - public: - STHDistributor(); - ~STHDistributor() override; - - // STHObserver implementation. - void NewSTHObserved(const net::ct::SignedTreeHead& sth) override; - - // STHReporter implementation - // Registers |observer| for new STH notifications. On registration, - // the |observer| will be notified of the latest STH for each log tha the - // STHDistributor has observed. - void RegisterObserver(STHObserver* observer) override; - - // Unregisters |observer|, which must have been previously - // registered via RegisterObserver() - void UnregisterObserver(STHObserver* observer) override; - - private: - // STHs from logs, one for each log. - std::vector<net::ct::SignedTreeHead> observed_sths_; - - // The observers for new STH notifications. - base::ObserverList<STHObserver, true>::Unchecked observer_list_; -}; - -} // namespace certificate_transparency - -#endif // COMPONENTS_CERTIFICATE_TRANSPARENCY_STH_DISTRIBUTOR_H_
diff --git a/components/certificate_transparency/sth_distributor_unittest.cc b/components/certificate_transparency/sth_distributor_unittest.cc deleted file mode 100644 index d4ade2e..0000000 --- a/components/certificate_transparency/sth_distributor_unittest.cc +++ /dev/null
@@ -1,133 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/certificate_transparency/sth_distributor.h" - -#include <map> -#include <string> - -#include "base/test/metrics/histogram_tester.h" -#include "components/certificate_transparency/sth_observer.h" -#include "crypto/sha2.h" -#include "net/cert/signed_tree_head.h" -#include "net/test/ct_test_util.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace certificate_transparency { - -namespace { - -// An STHObserver implementation that simply stores all -// observed STHs, keyed by log ID. -class StoringSTHObserver : public STHObserver { - public: - void NewSTHObserved(const net::ct::SignedTreeHead& sth) override { - sths[sth.log_id] = sth; - } - - std::map<std::string, net::ct::SignedTreeHead> sths; -}; - -class STHDistributorTest : public ::testing::Test { - public: - STHDistributorTest() = default; - - void SetUp() override { - ASSERT_TRUE(GetSampleSignedTreeHead(&sample_sth_)); - sample_sth_.log_id = net::ct::GetTestPublicKeyId(); - } - - protected: - STHDistributor distributor_; - net::ct::SignedTreeHead sample_sth_; -}; - -// Test that when a new observer is registered, the STHDistributor notifies it -// of all the observed STHs it received so far. -// This test makes sure that all observed STHs are reported to the observer. -TEST_F(STHDistributorTest, NotifiesOfExistingSTHs) { - // Create an STH that differs from the |sample_sth_| by belonging to a - // different log. - const std::string other_log = "another log"; - net::ct::SignedTreeHead second_sth(sample_sth_); - second_sth.log_id = other_log; - - // Notify |distributor_| of both STHs. - distributor_.NewSTHObserved(sample_sth_); - distributor_.NewSTHObserved(second_sth); - - StoringSTHObserver observer; - distributor_.RegisterObserver(&observer); - - // Check that two STHs from different logs received prior to observer - // registration were reported to the observer once registered. - EXPECT_EQ(2u, observer.sths.size()); - EXPECT_EQ(1u, observer.sths.count(other_log)); - distributor_.UnregisterObserver(&observer); -} - -// Test that histograms are properly recorded for the STH age when an STH -// from Google's Pilot log is observed. -TEST_F(STHDistributorTest, LogsUMAForPilotSTH) { - const char kPilotSTHAgeHistogram[] = - "Net.CertificateTransparency.PilotSTHAge"; - base::HistogramTester histograms; - histograms.ExpectTotalCount(kPilotSTHAgeHistogram, 0); - - const uint8_t kPilotLogID[] = { - 0xa4, 0xb9, 0x09, 0x90, 0xb4, 0x18, 0x58, 0x14, 0x87, 0xbb, 0x13, - 0xa2, 0xcc, 0x67, 0x70, 0x0a, 0x3c, 0x35, 0x98, 0x04, 0xf9, 0x1b, - 0xdf, 0xb8, 0xe3, 0x77, 0xcd, 0x0e, 0xc8, 0x0d, 0xdc, 0x10}; - sample_sth_.log_id = std::string(reinterpret_cast<const char*>(kPilotLogID), - crypto::kSHA256Length); - - distributor_.NewSTHObserved(sample_sth_); - histograms.ExpectTotalCount(kPilotSTHAgeHistogram, 1); -} - -// Test that the STHDistributor updates, rather than accumulates, STHs -// coming from the same log. -// This is tested by notifying the STHDistributor of an STH, modifying that -// STH, notifying the STHDistributor of the modified STH, then registering -// an observer which should get notified only once, with the modified STH. -TEST_F(STHDistributorTest, UpdatesObservedSTHData) { - // Observe an initial STH - StoringSTHObserver observer; - distributor_.RegisterObserver(&observer); - - distributor_.NewSTHObserved(sample_sth_); - - EXPECT_EQ(1u, observer.sths.size()); - EXPECT_EQ(sample_sth_, observer.sths[net::ct::GetTestPublicKeyId()]); - - // Observe a new STH. "new" simply means that it is a more recently observed - // SignedTreeHead for the given log ID, not necessarily that it's newer - // chronologically (the timestamp) or the log state (the tree size). - // To make sure the more recently observed SignedTreeHead is returned, just - // modify some fields. - net::ct::SignedTreeHead new_sth = sample_sth_; - new_sth.tree_size++; - new_sth.timestamp -= base::TimeDelta::FromSeconds(3); - - distributor_.NewSTHObserved(new_sth); - // The STH should have been broadcast to existing observers. - EXPECT_EQ(1u, observer.sths.size()); - EXPECT_NE(sample_sth_, observer.sths[net::ct::GetTestPublicKeyId()]); - EXPECT_EQ(new_sth, observer.sths[net::ct::GetTestPublicKeyId()]); - - // Registering a new observer should only receive the most recently observed - // STH. - StoringSTHObserver new_observer; - distributor_.RegisterObserver(&new_observer); - EXPECT_EQ(1u, new_observer.sths.size()); - EXPECT_NE(sample_sth_, new_observer.sths[net::ct::GetTestPublicKeyId()]); - EXPECT_EQ(new_sth, new_observer.sths[net::ct::GetTestPublicKeyId()]); - - distributor_.UnregisterObserver(&new_observer); - distributor_.UnregisterObserver(&observer); -} - -} // namespace - -} // namespace certificate_transparency
diff --git a/components/certificate_transparency/sth_observer.h b/components/certificate_transparency/sth_observer.h deleted file mode 100644 index 62742ea5..0000000 --- a/components/certificate_transparency/sth_observer.h +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_CERTIFICATE_TRANSPARENCY_STH_OBSERVER_H_ -#define COMPONENTS_CERTIFICATE_TRANSPARENCY_STH_OBSERVER_H_ - -#include <set> - -namespace net { -namespace ct { -struct SignedTreeHead; -} // namespace ct -} // namespace net - -namespace certificate_transparency { - -// Interface for receiving notifications of new STHs observed. -class STHObserver { - public: - virtual ~STHObserver() {} - - // Called with a new |sth| when one is observed. - virtual void NewSTHObserved(const net::ct::SignedTreeHead& sth) = 0; -}; - -} // namespace certificate_transparency - -#endif // COMPONENTS_CERTIFICATE_TRANSPARENCY_STH_OBSERVER_H_
diff --git a/components/certificate_transparency/sth_reporter.h b/components/certificate_transparency/sth_reporter.h deleted file mode 100644 index c4eea96..0000000 --- a/components/certificate_transparency/sth_reporter.h +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_CERTIFICATE_TRANSPARENCY_STH_REPORTER_H_ -#define COMPONENTS_CERTIFICATE_TRANSPARENCY_STH_REPORTER_H_ - -#include <set> - -namespace certificate_transparency { - -class STHObserver; - -// Interface for registering/unregistering observers. -class STHReporter { - public: - virtual ~STHReporter() {} - - virtual void RegisterObserver(STHObserver* observer) = 0; - virtual void UnregisterObserver(STHObserver* observer) = 0; -}; - -} // namespace certificate_transparency - -#endif // COMPONENTS_CERTIFICATE_TRANSPARENCY_STH_REPORTER_H_
diff --git a/components/certificate_transparency/tree_state_tracker.cc b/components/certificate_transparency/tree_state_tracker.cc deleted file mode 100644 index 3b87858..0000000 --- a/components/certificate_transparency/tree_state_tracker.cc +++ /dev/null
@@ -1,76 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/certificate_transparency/tree_state_tracker.h" - -#include <memory> -#include <utility> - -#include "base/feature_list.h" -#include "components/certificate_transparency/features.h" -#include "components/certificate_transparency/log_dns_client.h" -#include "components/certificate_transparency/single_tree_tracker.h" -#include "net/base/network_change_notifier.h" -#include "net/cert/ct_log_verifier.h" -#include "net/cert/signed_certificate_timestamp.h" -#include "net/cert/signed_tree_head.h" -#include "net/cert/x509_certificate.h" -#include "net/dns/dns_client.h" -#include "net/log/net_log.h" - -using net::X509Certificate; -using net::CTLogVerifier; -using net::ct::SignedCertificateTimestamp; -using net::ct::SignedTreeHead; - -namespace { -const size_t kMaxConcurrentDnsQueries = 1; -} - -namespace certificate_transparency { - -TreeStateTracker::TreeStateTracker( - std::vector<scoped_refptr<const CTLogVerifier>> ct_logs, - net::HostResolver* host_resolver, - net::URLRequestContext* url_request_context, - net::NetLog* net_log) { - std::unique_ptr<net::DnsClient> dns_client = - net::DnsClient::CreateClient(net_log); - dns_client_ = std::make_unique<LogDnsClient>( - std::move(dns_client), url_request_context, - net::NetLogWithSource::Make(net_log, - net::NetLogSourceType::CT_TREE_STATE_TRACKER), - kMaxConcurrentDnsQueries); - - for (const auto& log : ct_logs) { - tree_trackers_[log->key_id()].reset( - new SingleTreeTracker(log, dns_client_.get(), host_resolver, net_log)); - } -} - -TreeStateTracker::~TreeStateTracker() {} - -void TreeStateTracker::OnSCTVerified(base::StringPiece hostname, - X509Certificate* cert, - const SignedCertificateTimestamp* sct) { - auto it = tree_trackers_.find(sct->log_id); - // Ignore if the SCT is from an unknown log. - if (it == tree_trackers_.end()) - return; - - it->second->OnSCTVerified(hostname, cert, sct); -} - -void TreeStateTracker::NewSTHObserved(const SignedTreeHead& sth) { - auto it = tree_trackers_.find(sth.log_id); - // Is the STH from a known log? Since STHs can be provided from external - // sources for logs not yet recognized by this client, return, rather than - // DCHECK. - if (it == tree_trackers_.end()) - return; - - it->second->NewSTHObserved(sth); -} - -} // namespace certificate_transparency
diff --git a/components/certificate_transparency/tree_state_tracker.h b/components/certificate_transparency/tree_state_tracker.h deleted file mode 100644 index 97a22ad..0000000 --- a/components/certificate_transparency/tree_state_tracker.h +++ /dev/null
@@ -1,79 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_CERTIFICATE_TRANSPARENCY_TREE_STATE_TRACKER_H_ -#define COMPONENTS_CERTIFICATE_TRANSPARENCY_TREE_STATE_TRACKER_H_ - -#include <map> -#include <memory> -#include <string> -#include <vector> - -#include "base/memory/ref_counted.h" -#include "components/certificate_transparency/sth_observer.h" -#include "net/cert/ct_verifier.h" -#include "net/url_request/url_request_context.h" - -namespace net { -class NetLog; -class CTLogVerifier; -class HostResolver; -class X509Certificate; - -namespace ct { -struct SignedCertificateTimestamp; -struct SignedTreeHead; -} // namespace ct - -} // namespace net - -namespace certificate_transparency { -class LogDnsClient; -class SingleTreeTracker; - -// This class receives notifications of new Signed Tree Heads (STHs) and -// verified Signed Certificate Timestamps (SCTs) and delegates them to -// the SingleTreeTracker tracking the CT log they relate to. -// TODO(eranm): Export the inclusion check status of SCTs+Certs so it can -// be used in the DevTools Security panel, for example. See -// https://crbug.com/506227#c22. -class TreeStateTracker : public net::CTVerifier::Observer, public STHObserver { - public: - // Tracks the state of the logs provided in |ct_logs|. An instance of this - // class only tracks the logs provided in the constructor. The implementation - // is based on the assumption that the list of recognized logs does not change - // during the object's life time. - // Observed STHs from logs not in this list will be simply ignored. - TreeStateTracker(std::vector<scoped_refptr<const net::CTLogVerifier>> ct_logs, - net::HostResolver* host_resolver, - net::URLRequestContext* url_request_context, - net::NetLog* net_log); - ~TreeStateTracker() override; - - // net::ct::CTVerifier::Observer implementation. - // Delegates to the tree tracker corresponding to the log that issued the SCT. - void OnSCTVerified(base::StringPiece hostname, - net::X509Certificate* cert, - const net::ct::SignedCertificateTimestamp* sct) override; - - // STHObserver implementation. - // Delegates to the tree tracker corresponding to the log that issued the STH. - void NewSTHObserved(const net::ct::SignedTreeHead& sth) override; - - private: - // A Log DNS client for fetching inclusion proof and leaf indices from - // DNS front-end of CT logs. - // Shared between all SingleTreeTrackers, for rate-limiting across all - // trackers. Must be deleted after the tree trackers. - std::unique_ptr<LogDnsClient> dns_client_; - - // Holds the SingleTreeTracker for each log - std::map<std::string, std::unique_ptr<SingleTreeTracker>> tree_trackers_; - - DISALLOW_COPY_AND_ASSIGN(TreeStateTracker); -}; - -} // namespace certificate_transparency - -#endif // COMPONENTS_CERTIFICATE_TRANSPARENCY_TREE_STATE_TRACKER_H_
diff --git a/components/certificate_transparency/tree_state_tracker_unittest.cc b/components/certificate_transparency/tree_state_tracker_unittest.cc deleted file mode 100644 index 4dac773..0000000 --- a/components/certificate_transparency/tree_state_tracker_unittest.cc +++ /dev/null
@@ -1,113 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/certificate_transparency/tree_state_tracker.h" - -#include <memory> -#include <string> -#include <utility> - -#include "base/run_loop.h" -#include "base/strings/string_number_conversions.h" -#include "base/test/scoped_feature_list.h" -#include "base/test/scoped_task_environment.h" -#include "components/certificate_transparency/features.h" -#include "net/base/net_errors.h" -#include "net/cert/ct_log_verifier.h" -#include "net/cert/ct_serialization.h" -#include "net/cert/merkle_tree_leaf.h" -#include "net/cert/signed_certificate_timestamp.h" -#include "net/cert/signed_tree_head.h" -#include "net/cert/x509_certificate.h" -#include "net/dns/mock_host_resolver.h" -#include "net/log/net_log.h" -#include "net/log/test_net_log.h" -#include "net/test/ct_test_util.h" -#include "net/url_request/url_request_test_util.h" -#include "testing/gtest/include/gtest/gtest.h" - -using net::ct::SignedCertificateTimestamp; -using net::ct::SignedTreeHead; -using net::ct::GetSampleSignedTreeHead; -using net::ct::GetTestPublicKeyId; -using net::ct::GetTestPublicKey; -using net::ct::kSthRootHashLength; -using net::ct::GetX509CertSCT; - -constexpr char kHostname[] = "example.test"; -constexpr base::TimeDelta kZeroTTL; - -namespace certificate_transparency { - -class TreeStateTrackerTest : public ::testing::Test { - void SetUp() override { - log_ = net::CTLogVerifier::Create(GetTestPublicKey(), "testlog", - "unresolvable.invalid"); - - ASSERT_TRUE(log_); - ASSERT_EQ(log_->key_id(), GetTestPublicKeyId()); - - const std::string der_test_cert(net::ct::GetDerEncodedX509Cert()); - chain_ = net::X509Certificate::CreateFromBytes(der_test_cert.data(), - der_test_cert.length()); - ASSERT_TRUE(chain_.get()); - GetX509CertSCT(&cert_sct_); - cert_sct_->origin = SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE; - } - - protected: - base::test::ScopedTaskEnvironment task_environment_{ - base::test::ScopedTaskEnvironment::MainThreadType::IO}; - scoped_refptr<const net::CTLogVerifier> log_; - net::MockCachingHostResolver host_resolver_; - std::unique_ptr<TreeStateTracker> tree_tracker_; - scoped_refptr<net::X509Certificate> chain_; - scoped_refptr<SignedCertificateTimestamp> cert_sct_; - net::TestNetLog net_log_; -}; - -// Test that a new STH & SCT are delegated correctly to a -// SingleTreeTracker instance created by the TreeStateTracker. -// This is verified by looking for a single event on the net_log_ -// passed into the TreeStateTracker c'tor. -TEST_F(TreeStateTrackerTest, TestDelegatesCorrectly) { - std::vector<scoped_refptr<const net::CTLogVerifier>> verifiers; - verifiers.push_back(log_); - - base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature(kCTLogAuditing); - - tree_tracker_ = std::make_unique<TreeStateTracker>( - verifiers, &host_resolver_, new net::TestURLRequestContext(), &net_log_); - - // Add a cache entry for kHostname that indicates it was looked up over DNS. - // SingleTreeTracker requires this before it will request an inclusion proof, - // as otherwise it would reveal to the DNS resolver which server a user - // visited. If the server was already looked up via DNS though, that that - // information is already known to the DNS resolver so there is then no harm. - host_resolver_.GetHostCache()->Set( - net::HostCache::Key(kHostname, net::ADDRESS_FAMILY_UNSPECIFIED, 0), - net::HostCache::Entry(net::OK, net::AddressList(), - net::HostCache::Entry::SOURCE_DNS), - base::TimeTicks::Now(), kZeroTTL); - - SignedTreeHead sth; - GetSampleSignedTreeHead(&sth); - ASSERT_EQ(log_->key_id(), sth.log_id); - tree_tracker_->NewSTHObserved(sth); - - ASSERT_EQ(log_->key_id(), cert_sct_->log_id); - tree_tracker_->OnSCTVerified(kHostname, chain_.get(), cert_sct_.get()); - base::RunLoop().RunUntilIdle(); - - net::ct::MerkleTreeLeaf leaf; - ASSERT_TRUE(GetMerkleTreeLeaf(chain_.get(), cert_sct_.get(), &leaf)); - - std::string leaf_hash; - ASSERT_TRUE(HashMerkleTreeLeaf(leaf, &leaf_hash)); - // There should be one NetLog event. - EXPECT_EQ(1u, net_log_.GetSize()); -} - -} // namespace certificate_transparency
diff --git a/components/component_updater/component_installer.cc b/components/component_updater/component_installer.cc index 7f30edc8..2cf32b9c 100644 --- a/components/component_updater/component_installer.cc +++ b/components/component_updater/component_installer.cc
@@ -176,13 +176,6 @@ current_version_ = version; current_install_dir_ = install_path; - // Invoke |ComponentReady| on the main thread, then after this task has - // completed, post a task to call the lamda below using the task scheduler. - // The task scheduler PostTaskAndReply call requires the caller to run on - // a sequence. This code is not running on a sequence, therefore, there - // are two tasks posted to the main thread runner, to ensure that - // the |callback| is invoked by the task scheduler after |ComponentReady| has - // returned. main_task_runner_->PostTask( FROM_HERE, base::BindOnce(&ComponentInstaller::ComponentReady, this, std::move(manifest)));
diff --git a/components/components_strings.grd b/components/components_strings.grd index b334ee32..f35232385 100644 --- a/components/components_strings.grd +++ b/components/components_strings.grd
@@ -208,6 +208,7 @@ <part file="login_dialog_strings.grdp" /> <part file="new_or_sad_tab_strings.grdp" /> <part file="ntp_snippets_strings.grdp" /> + <part file="ntp_tiles_strings.grdp" /> <part file="omnibox_strings.grdp" /> <part file="page_info_strings.grdp" /> <part file="password_manager_strings.grdp" />
diff --git a/components/content_capture/android/java/src/org/chromium/components/content_capture/ContentCaptureController.java b/components/content_capture/android/java/src/org/chromium/components/content_capture/ContentCaptureController.java index 8de95c9..118b4fb 100644 --- a/components/content_capture/android/java/src/org/chromium/components/content_capture/ContentCaptureController.java +++ b/components/content_capture/android/java/src/org/chromium/components/content_capture/ContentCaptureController.java
@@ -34,6 +34,16 @@ public abstract boolean shouldStartCapture(); /** + * Clear all ContentCapture data associated with Chrome. + */ + public void clearAllContentCaptureData() {} + + /** + * Clear ContentCapture data for specific URLs. + */ + public void clearContentCaptureDataForURLs(String[] urlsToDelete) {} + + /** * Invoked by native side to pull the whitelist, the subclass should implement this and set * the whitelist by call setWhiteList. */
diff --git a/components/cronet/android/cronet_url_request_context_adapter.cc b/components/cronet/android/cronet_url_request_context_adapter.cc index 083de9c2..5845e48 100644 --- a/components/cronet/android/cronet_url_request_context_adapter.cc +++ b/components/cronet/android/cronet_url_request_context_adapter.cc
@@ -306,10 +306,7 @@ jinclude_subdomains, base::Time::UnixEpoch() + base::TimeDelta::FromMilliseconds(jexpiration_time))); - size_t hash_count = env->GetArrayLength(jhashes); - for (size_t i = 0; i < hash_count; ++i) { - ScopedJavaLocalRef<jbyteArray> bytes_array( - env, static_cast<jbyteArray>(env->GetObjectArrayElement(jhashes, i))); + for (auto bytes_array : jhashes.ReadElements<jbyteArray>()) { static_assert(std::is_pod<net::SHA256HashValue>::value, "net::SHA256HashValue is not POD"); static_assert(sizeof(net::SHA256HashValue) * CHAR_BIT == 256,
diff --git a/components/cronet/stale_host_resolver.cc b/components/cronet/stale_host_resolver.cc index e2ccbaa1..68d1ea7 100644 --- a/components/cronet/stale_host_resolver.cc +++ b/components/cronet/stale_host_resolver.cc
@@ -455,14 +455,6 @@ optional_parameters.value_or(ResolveHostParameters()), tick_clock_); } -bool StaleHostResolver::HasCached(base::StringPiece hostname, - net::HostCache::Entry::Source* source_out, - net::HostCache::EntryStaleness* stale_out, - bool* secure_out) const { - return inner_resolver_->HasCached(hostname, source_out, stale_out, - secure_out); -} - net::HostCache* StaleHostResolver::GetHostCache() { return inner_resolver_->GetHostCache(); }
diff --git a/components/cronet/stale_host_resolver.h b/components/cronet/stale_host_resolver.h index fa122002..568e1949 100644 --- a/components/cronet/stale_host_resolver.h +++ b/components/cronet/stale_host_resolver.h
@@ -85,10 +85,6 @@ // The remaining public methods pass through to the inner resolver: net::HostCache* GetHostCache() override; - bool HasCached(base::StringPiece hostname, - net::HostCache::Entry::Source* source_out, - net::HostCache::EntryStaleness* stale_out, - bool* secure_out) const override; std::unique_ptr<base::Value> GetDnsConfigAsValue() const override; void SetRequestContext(net::URLRequestContext* request_context) override;
diff --git a/components/download/internal/common/android/download_collection_bridge.cc b/components/download/internal/common/android/download_collection_bridge.cc index c1c5601..ae075552 100644 --- a/components/download/internal/common/android/download_collection_bridge.cc +++ b/components/download/internal/common/android/download_collection_bridge.cc
@@ -154,10 +154,7 @@ std::move(cb).Run(std::move(result)); return; } - jsize count = env->GetArrayLength(jdisplay_infos.obj()); - for (jsize i = 0; i < count; ++i) { - base::android::ScopedJavaLocalRef<jobject> jdisplay_info( - env, env->GetObjectArrayElement(jdisplay_infos.obj(), i)); + for (auto jdisplay_info : jdisplay_infos.ReadElements<jobject>()) { ScopedJavaLocalRef<jstring> juri = Java_DisplayNameInfo_getDownloadUri(env, jdisplay_info); ScopedJavaLocalRef<jstring> jdisplay_name =
diff --git a/components/download/internal/common/download_file_impl.cc b/components/download/internal/common/download_file_impl.cc index b56fb8f..13f52e03 100644 --- a/components/download/internal/common/download_file_impl.cc +++ b/components/download/internal/common/download_file_impl.cc
@@ -4,6 +4,7 @@ #include "components/download/public/common/download_file_impl.h" +#include <algorithm> #include <string> #include <utility> @@ -58,13 +59,24 @@ DownloadFileImpl::SourceStream::SourceStream( int64_t offset, int64_t length, + int64_t starting_file_write_offset, std::unique_ptr<InputStream> stream) : offset_(offset), length_(length), + starting_file_write_offset_(starting_file_write_offset), + bytes_read_(0), bytes_written_(0), finished_(false), index_(0u), - input_stream_(std::move(stream)) {} + input_stream_(std::move(stream)) { + CHECK_LE(offset_, starting_file_write_offset_); + CHECK_GE(offset_, 0); + DCHECK(length <= 0 || length >= starting_file_write_offset - offset) + << "Not enough for content validation. offset = " << offset + << ", length = " << length + << " , starting_file_write_offset = " << starting_file_write_offset + << "."; +} DownloadFileImpl::SourceStream::~SourceStream() = default; @@ -72,19 +84,25 @@ input_stream_->Initialize(); } -void DownloadFileImpl::SourceStream::OnWriteBytesToDisk(int64_t bytes_write) { - bytes_written_ += bytes_write; +void DownloadFileImpl::SourceStream::OnBytesConsumed(int64_t bytes_read, + int64_t bytes_written) { + CHECK_GE(bytes_read, bytes_written); + bytes_read_ += bytes_read; + bytes_written_ += bytes_written; } void DownloadFileImpl::SourceStream::TruncateLengthWithWrittenDataBlock( - int64_t offset, + int64_t received_slice_offset, int64_t bytes_written) { DCHECK_GT(bytes_written, 0); if (length_ == kNoBytesToWrite) return; - if (offset <= offset_) { - if (offset + bytes_written > offset_) { + if (received_slice_offset <= starting_file_write_offset_) { + // If validation has completed, mark the stream as finished if the file + // write position already has data. + if (received_slice_offset + bytes_written > starting_file_write_offset_ && + GetRemainingBytesToValidate() == 0) { length_ = kNoBytesToWrite; finished_ = true; } @@ -92,8 +110,12 @@ } if (length_ == DownloadSaveInfo::kLengthFullContent || - length_ > offset - offset_) { - length_ = offset - offset_; + (length_ > received_slice_offset - offset_ && + length_ > starting_file_write_offset_ - offset_)) { + // Stream length should always include the validation data, unless the + // response is too short. + length_ = + std::max(received_slice_offset, starting_file_write_offset_) - offset_; } } @@ -123,6 +145,11 @@ return input_stream_->Read(data, length); } +size_t DownloadFileImpl::SourceStream::GetRemainingBytesToValidate() { + int64_t bytes_remaining = starting_file_write_offset_ - offset_ - bytes_read_; + return bytes_remaining < 0 ? 0 : bytes_remaining; +} + DownloadFileImpl::DownloadFileImpl( std::unique_ptr<DownloadSaveInfo> save_info, const base::FilePath& default_download_directory, @@ -149,7 +176,8 @@ download_id); source_streams_[save_info_->offset] = std::make_unique<SourceStream>( - save_info_->offset, save_info_->length, std::move(stream)); + save_info_->offset, save_info_->length, + save_info_->GetStartingFileWriteOffset(), std::move(stream)); DETACH_FROM_SEQUENCE(sequence_checker_); } @@ -184,7 +212,7 @@ bytes_so_far += received_slice.received_bytes; } } else { - bytes_so_far = save_info_->offset; + bytes_so_far = save_info_->GetStartingFileWriteOffset(); } int64_t bytes_wasted = 0; DownloadInterruptReason reason = file_.Initialize( @@ -227,7 +255,7 @@ } DCHECK(source_streams_.find(offset) == source_streams_.end()); source_streams_[offset] = - std::make_unique<SourceStream>(offset, length, std::move(stream)); + std::make_unique<SourceStream>(offset, length, offset, std::move(stream)); OnSourceStreamAdded(source_streams_[offset].get()); } @@ -244,46 +272,73 @@ RegisterAndActivateStream(source_stream); } -DownloadInterruptReason DownloadFileImpl::WriteDataToFile(int64_t offset, - const char* data, - size_t data_len) { +DownloadInterruptReason DownloadFileImpl::ValidateAndWriteDataToFile( + int64_t offset, + const char* data, + size_t bytes_to_validate, + size_t bytes_to_write) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - WillWriteToDisk(data_len); - return file_.WriteDataToFile(offset, data, data_len); + // Check if some of the data is for validation purpose. + if (bytes_to_validate > 0 && + !file_.ValidateDataInFile(offset, data, bytes_to_validate)) { + return DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH; + } + // If there is no data to write, just return DOWNLOAD_INTERRUPT_REASON_NONE + // and read the next chunk. + if (bytes_to_write <= 0) + return DOWNLOAD_INTERRUPT_REASON_NONE; + // Write the remaining data to disk. + WillWriteToDisk(bytes_to_write); + return file_.WriteDataToFile(offset + bytes_to_validate, + data + bytes_to_validate, bytes_to_write); } bool DownloadFileImpl::CalculateBytesToWrite(SourceStream* source_stream, size_t bytes_available_to_write, + size_t* bytes_to_validate, size_t* bytes_to_write) { + *bytes_to_validate = 0; if (source_stream->length() == kNoBytesToWrite) { *bytes_to_write = 0; return true; } + // First calculate the number of bytes to validate. + *bytes_to_write = bytes_available_to_write; + size_t remaining_bytes_to_validate = + source_stream->GetRemainingBytesToValidate(); + if (remaining_bytes_to_validate > 0) { + *bytes_to_validate = + std::min(remaining_bytes_to_validate, bytes_available_to_write); + *bytes_to_write -= *bytes_to_validate; + } + if (source_stream->length() != DownloadSaveInfo::kLengthFullContent && + source_stream->bytes_read() + + static_cast<int64_t>(bytes_available_to_write) > + source_stream->length()) { + // Total bytes to consume is capped by the length of the stream. + int64_t bytes_to_consume = + source_stream->length() - source_stream->bytes_read(); + // The validation data should always be streamed. + DCHECK_GE(bytes_to_consume, static_cast<int64_t>(*bytes_to_validate)); + *bytes_to_write = bytes_to_consume - *bytes_to_validate; + return true; + } + // If a new slice finds that its target position has already been written, - // terminate the stream. - if (source_stream->bytes_written() == 0) { + // terminate the stream if there are no bytes to validate. + if (source_stream->bytes_written() == 0 && *bytes_to_write > 0) { for (const auto& received_slice : received_slices_) { - if (received_slice.offset <= source_stream->offset() && + if (received_slice.offset <= + source_stream->starting_file_write_offset() && received_slice.offset + received_slice.received_bytes > - source_stream->offset()) { + source_stream->starting_file_write_offset()) { *bytes_to_write = 0; return true; } } } - if (source_stream->length() != DownloadSaveInfo::kLengthFullContent && - source_stream->bytes_written() + - static_cast<int64_t>(bytes_available_to_write) > - source_stream->length()) { - // Write a partial buffer as the incoming data exceeds the length limit. - *bytes_to_write = source_stream->length() - source_stream->bytes_written(); - return true; - } - - *bytes_to_write = bytes_available_to_write; return false; } @@ -361,8 +416,9 @@ DownloadInterruptReason reason = source_stream->GetCompletionStatus(); if (source_stream->length() == DownloadSaveInfo::kLengthFullContent && !received_slices_.empty() && - (source_stream->offset() == received_slices_.back().offset + - received_slices_.back().received_bytes) && + (source_stream->starting_file_write_offset() == + received_slices_.back().offset + + received_slices_.back().received_bytes) && reason == DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE) { // We are probably reaching the end of the stream, don't treat this // as an error. @@ -508,6 +564,7 @@ size_t incoming_data_size = 0; size_t total_incoming_data_size = 0; size_t num_buffers = 0; + size_t bytes_to_validate = 0; size_t bytes_to_write = 0; bool should_terminate = false; InputStream::StreamState state(InputStream::EMPTY); @@ -524,24 +581,26 @@ break; case InputStream::HAS_DATA: { ++num_buffers; - should_terminate = CalculateBytesToWrite( - source_stream, incoming_data_size, &bytes_to_write); + should_terminate = + CalculateBytesToWrite(source_stream, incoming_data_size, + &bytes_to_validate, &bytes_to_write); DCHECK_GE(incoming_data_size, bytes_to_write); - reason = WriteDataToFile( - source_stream->offset() + source_stream->bytes_written(), - incoming_data->data(), bytes_to_write); + reason = ValidateAndWriteDataToFile( + source_stream->offset() + source_stream->bytes_read(), + incoming_data->data(), bytes_to_validate, bytes_to_write); bytes_seen_ += bytes_to_write; - total_incoming_data_size += bytes_to_write; + total_incoming_data_size += incoming_data_size; if (reason == DOWNLOAD_INTERRUPT_REASON_NONE) { int64_t prev_bytes_written = source_stream->bytes_written(); - source_stream->OnWriteBytesToDisk(bytes_to_write); + source_stream->OnBytesConsumed(incoming_data_size, bytes_to_write); if (!IsSparseFile()) break; // If the write operation creates a new slice, add it to the // |received_slices_| and update all the entries in // |source_streams_|. if (bytes_to_write > 0 && prev_bytes_written == 0) { - AddNewSlice(source_stream->offset(), bytes_to_write); + AddNewSlice(source_stream->starting_file_write_offset(), + bytes_to_write); } else { received_slices_[source_stream->index()].received_bytes += bytes_to_write; @@ -611,7 +670,7 @@ } SetPotentialFileLength(source_stream->offset() + - source_stream->bytes_written()); + source_stream->bytes_read()); } num_active_streams_--; @@ -698,10 +757,10 @@ // Update the index of exising SourceStreams. for (auto& stream : source_streams_) { SourceStream* source_stream = stream.second.get(); - if (source_stream->offset() > offset) { + if (source_stream->starting_file_write_offset() > offset) { if (slice_added && source_stream->bytes_written() > 0) source_stream->set_index(source_stream->index() + 1); - } else if (source_stream->offset() == offset) { + } else if (source_stream->starting_file_write_offset() == offset) { source_stream->set_index(index); } else { source_stream->TruncateLengthWithWrittenDataBlock(offset, length); @@ -736,26 +795,29 @@ source_stream->set_finished(true); num_active_streams_--; - // If previous stream has already written data at the starting offset of - // the error stream. The download can complete. - bool can_recover_from_error = (source_stream->length() == kNoBytesToWrite); + bool can_recover_from_error = false; + if (reason != DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH) { + // If previous stream has already written data at the starting offset of + // the error stream. The download can complete. + can_recover_from_error = (source_stream->length() == kNoBytesToWrite); - // See if the previous stream can download the full content. - // If the current stream has written some data, length of all preceding - // streams will be truncated. - if (IsSparseFile() && !can_recover_from_error) { - SourceStream* preceding_neighbor = FindPrecedingNeighbor(source_stream); - while (preceding_neighbor) { - if (CanRecoverFromError(source_stream, preceding_neighbor)) { - can_recover_from_error = true; - break; + // See if the previous stream can download the full content. + // If the current stream has written some data, length of all preceding + // streams will be truncated. + if (IsSparseFile() && !can_recover_from_error) { + SourceStream* preceding_neighbor = FindPrecedingNeighbor(source_stream); + while (preceding_neighbor) { + if (CanRecoverFromError(source_stream, preceding_neighbor)) { + can_recover_from_error = true; + break; + } + + // If the neighbor cannot recover the error and it has already created + // a slice, just interrupt the download. + if (preceding_neighbor->bytes_written() > 0) + break; + preceding_neighbor = FindPrecedingNeighbor(preceding_neighbor); } - - // If the neighbor cannot recover the error and it has already created - // a slice, just interrupt the download. - if (preceding_neighbor->bytes_written() > 0) - break; - preceding_neighbor = FindPrecedingNeighbor(preceding_neighbor); } } @@ -784,8 +846,9 @@ int64_t max_preceding_offset = 0; SourceStream* ret = nullptr; for (auto& stream : source_streams_) { - int64_t offset = stream.second->offset(); - if (offset < source_stream->offset() && offset >= max_preceding_offset) { + int64_t offset = stream.second->starting_file_write_offset(); + if (offset < source_stream->starting_file_write_offset() && + offset >= max_preceding_offset) { ret = stream.second.get(); max_preceding_offset = offset; } @@ -805,6 +868,9 @@ DVLOG(1) << "Total source stream count = " << source_streams_.size(); for (const auto& stream : source_streams_) { DVLOG(1) << "Source stream, offset = " << stream.second->offset() + << " , bytes_read = " << stream.second->bytes_read() + << " , starting_file_write_offset = " + << stream.second->starting_file_write_offset() << " , bytes_written = " << stream.second->bytes_written() << " , is_finished = " << stream.second->is_finished() << " , length = " << stream.second->length()
diff --git a/components/download/internal/common/download_file_unittest.cc b/components/download/internal/common/download_file_unittest.cc index fb89b4c5..a3d72dc 100644 --- a/components/download/internal/common/download_file_unittest.cc +++ b/components/download/internal/common/download_file_unittest.cc
@@ -192,15 +192,22 @@ closure.Run(); } - bool CreateDownloadFile(int offset, bool calculate_hash) { - return CreateDownloadFile(offset, 0, calculate_hash, - DownloadItem::ReceivedSlices()); + bool CreateDownloadFile(bool calculate_hash) { + return CreateDownloadFile(0, calculate_hash, DownloadItem::ReceivedSlices(), + -1); } - bool CreateDownloadFile(int offset, - int length, + bool CreateDownloadFile(int length, bool calculate_hash, const DownloadItem::ReceivedSlices& received_slices) { + return CreateDownloadFile(length, calculate_hash, + DownloadItem::ReceivedSlices(), -1); + } + + bool CreateDownloadFile(int length, + bool calculate_hash, + const DownloadItem::ReceivedSlices& received_slices, + int file_offset) { // There can be only one. DCHECK(!download_file_); @@ -213,8 +220,23 @@ .RetiresOnSaturation(); std::unique_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo()); - save_info->offset = offset; + // Fill the file by repeatedly copying |kTestData1| if |file_offset| is + // positive. + if (file_offset > 0) { + base::CreateTemporaryFileInDir(download_dir_.GetPath(), + &save_info->file_path); + int len = file_offset; + int data_len = strlen(kTestData1); + while (len > 0) { + int bytes_to_write = len > data_len ? data_len : len; + base::AppendToFile(save_info->file_path, kTestData1, bytes_to_write); + len -= bytes_to_write; + } + } + + save_info->offset = 0; save_info->length = length; + save_info->file_offset = file_offset; download_file_.reset(new TestDownloadFileImpl( std::move(save_info), download_dir_.GetPath(), @@ -462,6 +484,9 @@ int64_t bytes_; int64_t bytes_per_sec_; + // Keep track of what data should be saved to the disk file. + std::string expected_data_; + private: void SetRenameResult(const base::Closure& closure, DownloadInterruptReason* reason_p, @@ -476,9 +501,6 @@ } base::test::ScopedTaskEnvironment scoped_task_environment_; - - // Keep track of what data should be saved to the disk file. - std::string expected_data_; }; // DownloadFile::RenameAndAnnotate and DownloadFile::RenameAndUniquify have a @@ -531,7 +553,7 @@ // Rename the file before any data is downloaded, after some has, after it all // has, and after it's closed. TEST_P(DownloadFileTestWithRename, RenameFileFinal) { - ASSERT_TRUE(CreateDownloadFile(0, true)); + ASSERT_TRUE(CreateDownloadFile(true)); base::FilePath initial_path(download_file_->FullPath()); EXPECT_TRUE(base::PathExists(initial_path)); base::FilePath path_1(initial_path.InsertBeforeExtensionASCII("_1")); @@ -601,7 +623,7 @@ // the above test because it only applies to RenameAndAnnotate(). // RenameAndUniquify() doesn't overwrite by design. TEST_F(DownloadFileTest, RenameOverwrites) { - ASSERT_TRUE(CreateDownloadFile(0, true)); + ASSERT_TRUE(CreateDownloadFile(true)); base::FilePath initial_path(download_file_->FullPath()); EXPECT_TRUE(base::PathExists(initial_path)); base::FilePath path_1(initial_path.InsertBeforeExtensionASCII("_1")); @@ -631,7 +653,7 @@ // DownloadFileTestWithRename test because this only applies to // RenameAndUniquify(). TEST_F(DownloadFileTest, RenameUniquifies) { - ASSERT_TRUE(CreateDownloadFile(0, true)); + ASSERT_TRUE(CreateDownloadFile(true)); base::FilePath initial_path(download_file_->FullPath()); EXPECT_TRUE(base::PathExists(initial_path)); base::FilePath path_1(initial_path.InsertBeforeExtensionASCII("_1")); @@ -654,7 +676,7 @@ // Test that RenameAndUniquify doesn't try to uniquify in the case where the // target filename is the same as the current filename. TEST_F(DownloadFileTest, RenameRecognizesSelfConflict) { - ASSERT_TRUE(CreateDownloadFile(0, true)); + ASSERT_TRUE(CreateDownloadFile(true)); base::FilePath initial_path(download_file_->FullPath()); EXPECT_TRUE(base::PathExists(initial_path)); @@ -671,7 +693,7 @@ // Test to make sure we get the proper error on failure. TEST_P(DownloadFileTestWithRename, RenameError) { - ASSERT_TRUE(CreateDownloadFile(0, true)); + ASSERT_TRUE(CreateDownloadFile(true)); base::FilePath initial_path(download_file_->FullPath()); // Create a subdirectory. @@ -726,7 +748,7 @@ // base::MessageLoopCurrent::Get(). Each RunLoop processes that queue until it // sees a QuitClosure() targeted at itself, at which point it stops processing. TEST_P(DownloadFileTestWithRename, RenameWithErrorRetry) { - ASSERT_TRUE(CreateDownloadFile(0, true)); + ASSERT_TRUE(CreateDownloadFile(true)); base::FilePath initial_path(download_file_->FullPath()); // Create a subdirectory. @@ -797,7 +819,7 @@ // Various tests of the StreamActive method. TEST_F(DownloadFileTest, StreamEmptySuccess) { - ASSERT_TRUE(CreateDownloadFile(0, true)); + ASSERT_TRUE(CreateDownloadFile(true)); base::FilePath initial_path(download_file_->FullPath()); EXPECT_TRUE(base::PathExists(initial_path)); @@ -813,7 +835,7 @@ } TEST_F(DownloadFileTest, StreamEmptyError) { - ASSERT_TRUE(CreateDownloadFile(0, true)); + ASSERT_TRUE(CreateDownloadFile(true)); base::FilePath initial_path(download_file_->FullPath()); EXPECT_TRUE(base::PathExists(initial_path)); @@ -842,7 +864,7 @@ } TEST_F(DownloadFileTest, StreamNonEmptySuccess) { - ASSERT_TRUE(CreateDownloadFile(0, true)); + ASSERT_TRUE(CreateDownloadFile(true)); base::FilePath initial_path(download_file_->FullPath()); EXPECT_TRUE(base::PathExists(initial_path)); @@ -858,7 +880,7 @@ } TEST_F(DownloadFileTest, StreamNonEmptyError) { - ASSERT_TRUE(CreateDownloadFile(0, true)); + ASSERT_TRUE(CreateDownloadFile(true)); base::FilePath initial_path(download_file_->FullPath()); EXPECT_TRUE(base::PathExists(initial_path)); @@ -888,6 +910,58 @@ DestroyDownloadFile(0); } +// Tests that if file content validation succeeds, all the remaining data will +// be writing to the file. +TEST_F(DownloadFileTest, FileContentValidationSuccess) { + int stream_length = strlen(kTestData1) * 2; + + ASSERT_TRUE(CreateDownloadFile( + stream_length /* length */, true /* calculate_hash */, + DownloadItem::ReceivedSlices(), strlen(kTestData1) - 1)); + base::FilePath initial_path(download_file_->FullPath()); + EXPECT_TRUE(base::PathExists(initial_path)); + + const char* chunks1[] = {kTestData1, kTestData1}; + ::testing::Sequence s1; + SetupDataAppend(chunks1, 2 /* num_chunks */, input_stream_, s1); + SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, input_stream_, s1); + EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _)); + sink_callback_.Run(MOJO_RESULT_OK); + VerifyStreamAndSize(); + base::RunLoop().RunUntilIdle(); + DestroyDownloadFile(0); +} + +// Tests that if file content validation fails, an error will occur and no data +// will be written. +TEST_F(DownloadFileTest, FileContentValidationFail) { + int file_length = strlen(kTestData2) - 1; + int stream_length = strlen(kTestData1) + strlen(kTestData2); + + ASSERT_TRUE(CreateDownloadFile(stream_length /* length */, + true /* calculate_hash */, + DownloadItem::ReceivedSlices(), file_length)); + base::FilePath initial_path(download_file_->FullPath()); + EXPECT_TRUE(base::PathExists(initial_path)); + std::string file_content = std::string(kTestData1, 0, file_length); + expected_data_ = file_content; + VerifyStreamAndSize(); + + const char* chunks1[] = {kTestData2, kTestData1}; + ::testing::Sequence s1; + // Only 1 chunk will be read, and it will generate an error after + // failing the validation. + SetupDataAppend(chunks1, 1 /* num_chunks */, input_stream_, s1); + EXPECT_CALL(*input_stream_, ClearDataReadyCallback()); + EXPECT_CALL(*(observer_.get()), + MockDestinationError(DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH, + file_length, _)); + sink_callback_.Run(MOJO_RESULT_OK); + base::RunLoop().RunUntilIdle(); + expected_data_ = file_content; + DestroyDownloadFile(0); +} + // Tests for concurrent streams handling, used for parallel download. // // Activate both streams at the same time. @@ -895,7 +969,7 @@ int64_t stream_0_length = GetBuffersLength(kTestData6, 2); int64_t stream_1_length = GetBuffersLength(kTestData7, 2); - ASSERT_TRUE(CreateDownloadFile(0, stream_0_length, true, + ASSERT_TRUE(CreateDownloadFile(stream_0_length, true, DownloadItem::ReceivedSlices())); PrepareStream(&input_stream_, 0, false, true, kTestData6, 2); @@ -934,7 +1008,7 @@ // "Range:50-". int64_t stream_2_length = GetBuffersLength(kTestData6, 2); - ASSERT_TRUE(CreateDownloadFile(0, stream_0_length, true, + ASSERT_TRUE(CreateDownloadFile(stream_0_length, true, DownloadItem::ReceivedSlices())); PrepareStream(&input_stream_, 0, false, true, kTestData6, 2); @@ -986,7 +1060,7 @@ TEST_F(DownloadFileTest, MultipleStreamsFirstStreamWriteAllData) { int64_t stream_0_length = GetBuffersLength(kTestData8, 4); - ASSERT_TRUE(CreateDownloadFile(0, DownloadSaveInfo::kLengthFullContent, true, + ASSERT_TRUE(CreateDownloadFile(DownloadSaveInfo::kLengthFullContent, true, DownloadItem::ReceivedSlices())); PrepareStream(&input_stream_, 0, false, true, kTestData8, 4); @@ -1019,7 +1093,7 @@ TEST_F(DownloadFileTest, SecondStreamStartingOffsetAlreadyWritten) { int64_t stream_0_length = GetBuffersLength(kTestData6, 2); - ASSERT_TRUE(CreateDownloadFile(0, stream_0_length, true, + ASSERT_TRUE(CreateDownloadFile(stream_0_length, true, DownloadItem::ReceivedSlices())); Sequence seq;
diff --git a/components/download/internal/common/parallel_download_utils.cc b/components/download/internal/common/parallel_download_utils.cc index bc7266f..5aa3ad6 100644 --- a/components/download/internal/common/parallel_download_utils.cc +++ b/components/download/internal/common/parallel_download_utils.cc
@@ -102,7 +102,7 @@ // the error stream. if (error_stream->length() > 0) { return error_stream->offset() + error_stream->length() <= - preceding_neighbor->offset() + preceding_neighbor->bytes_written(); + preceding_neighbor->offset() + preceding_neighbor->bytes_read(); } return false;
diff --git a/components/download/internal/common/parallel_download_utils_unittest.cc b/components/download/internal/common/parallel_download_utils_unittest.cc index af8aab7..b0c8462 100644 --- a/components/download/internal/common/parallel_download_utils_unittest.cc +++ b/components/download/internal/common/parallel_download_utils_unittest.cc
@@ -43,7 +43,8 @@ EXPECT_CALL(*input_stream_, GetCompletionStatus()) .WillRepeatedly(Return(DOWNLOAD_INTERRUPT_REASON_NONE)); return std::make_unique<DownloadFileImpl::SourceStream>( - offset, length, std::unique_ptr<MockInputStream>(input_stream_)); + offset, length, offset, + std::unique_ptr<MockInputStream>(input_stream_)); } protected: @@ -166,7 +167,7 @@ EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); // Even if it has written some data. - preceding_stream->OnWriteBytesToDisk(1000u); + preceding_stream->OnBytesConsumed(1000u, 1000u); EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); // Now capped the length of preceding stream with different values. @@ -177,14 +178,15 @@ preceding_stream->set_finished(false); EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); preceding_stream->set_finished(true); - preceding_stream->OnWriteBytesToDisk(kErrorStreamOffset - preceding_offset); + int64_t bytes_consumed = kErrorStreamOffset - preceding_offset; + preceding_stream->OnBytesConsumed(bytes_consumed, bytes_consumed); EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); // Inject an error results in failure, even if data written exceeds the first // byte of error stream. EXPECT_CALL(*input_stream_, GetCompletionStatus()) .WillRepeatedly(Return(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE)); - preceding_stream->OnWriteBytesToDisk(1000u); + preceding_stream->OnBytesConsumed(1000u, 1000u); EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); // Make preceding stream can reach the first byte of error stream. @@ -194,9 +196,9 @@ preceding_stream->set_finished(false); EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); preceding_stream->set_finished(true); - preceding_stream->OnWriteBytesToDisk(kErrorStreamOffset - preceding_offset); + preceding_stream->OnBytesConsumed(bytes_consumed, bytes_consumed); EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); - preceding_stream->OnWriteBytesToDisk(1); + preceding_stream->OnBytesConsumed(1, 1); EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); // Preceding stream that never download data won't recover the error stream. @@ -229,11 +231,13 @@ // Since the preceding stream can never reach the starting offset, for an // unfinished stream, we rely on length instead of bytes written. EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); - preceding_stream->OnWriteBytesToDisk(kErrorStreamOffset - preceding_offset); + int64_t bytes_consumed = kErrorStreamOffset - preceding_offset; + preceding_stream->OnBytesConsumed(bytes_consumed, bytes_consumed); EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); - preceding_stream->OnWriteBytesToDisk(kErrorStreamLength - 1); + preceding_stream->OnBytesConsumed(kErrorStreamLength - 1, + kErrorStreamLength - 1); EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); - preceding_stream->OnWriteBytesToDisk(1); + preceding_stream->OnBytesConsumed(1, 1); // Create preceding stream that can reach the upper bound of error stream. // Since it's unfinished, it potentially can take over error stream's work @@ -248,11 +252,12 @@ // Finished preceding stream only checks data written. preceding_stream = CreateSourceStream(preceding_offset, 1); preceding_stream->set_finished(true); - preceding_stream->OnWriteBytesToDisk(kErrorStreamOffset - preceding_offset); + preceding_stream->OnBytesConsumed(bytes_consumed, bytes_consumed); EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); - preceding_stream->OnWriteBytesToDisk(kErrorStreamLength - 1); + preceding_stream->OnBytesConsumed(kErrorStreamLength - 1, + kErrorStreamLength - 1); EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); - preceding_stream->OnWriteBytesToDisk(1); + preceding_stream->OnBytesConsumed(1, 1); EXPECT_TRUE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); // Even if inject an error, since data written has cover the upper bound of
diff --git a/components/download/public/common/download_file_impl.h b/components/download/public/common/download_file_impl.h index 8c350fb4..c3dee68 100644 --- a/components/download/public/common/download_file_impl.h +++ b/components/download/public/common/download_file_impl.h
@@ -99,17 +99,19 @@ public: SourceStream(int64_t offset, int64_t length, + int64_t starting_file_write_offset, std::unique_ptr<InputStream> stream); ~SourceStream(); void Initialize(); - // Called after successfully writing a buffer to disk. - void OnWriteBytesToDisk(int64_t bytes_write); + // Called after successfully reading and writing a buffer from stream. + void OnBytesConsumed(int64_t bytes_read, int64_t bytes_written); // Given a data block that is already written, truncate the length of this - // object to avoid overwriting that block. - void TruncateLengthWithWrittenDataBlock(int64_t offset, + // object to avoid overwriting that block. Data used for validation purpose + // will not be truncated. + void TruncateLengthWithWrittenDataBlock(int64_t received_slice_offset, int64_t bytes_written); // Registers the callback that will be called when data is ready. @@ -136,8 +138,15 @@ InputStream::StreamState Read(scoped_refptr<net::IOBuffer>* data, size_t* length); + // Returning the remaining bytes to validate. + size_t GetRemainingBytesToValidate(); + int64_t offset() const { return offset_; } int64_t length() const { return length_; } + int64_t starting_file_write_offset() const { + return starting_file_write_offset_; + } + int64_t bytes_read() const { return bytes_read_; } int64_t bytes_written() const { return bytes_written_; } bool is_finished() const { return finished_; } void set_finished(bool finish) { finished_ = finish; } @@ -145,15 +154,24 @@ void set_index(size_t index) { index_ = index; } private: - // Starting position for the stream to write to disk. + // Starting position of the stream, this is from the network response. int64_t offset_; // The maximum length to write to the disk. If set to 0, keep writing until // the stream depletes. int64_t length_; - // Number of bytes written to disk from the stream. - // Next write position is (|offset_| + |bytes_written_|). + // All the data received before this offset are used for validation purpose + // and will not be written to disk. This value should always be no less than + // |offset_|. + int64_t starting_file_write_offset_; + + // Number of bytes read from the stream. + // Next read position is (|offset_| + |bytes_read_|). + int64_t bytes_read_; + + // Number of bytes written to the disk. This does not include the bytes used + // for validation. int64_t bytes_written_; // If all the data read from the stream has been successfully written to @@ -172,11 +190,13 @@ protected: // For test class overrides. - // Write data from the offset to the file. - // On OS level, it will seek to the |offset| and write from there. - virtual DownloadInterruptReason WriteDataToFile(int64_t offset, - const char* data, - size_t data_len); + // Validate the first |bytes_to_validate| bytes and write the next + // |bytes_to_write| bytes of data from the offset to the file. + virtual DownloadInterruptReason ValidateAndWriteDataToFile( + int64_t offset, + const char* data, + size_t bytes_to_validate, + size_t bytes_to_write); virtual base::TimeDelta GetRetryDelayForFailedRename(int attempt_number); @@ -232,13 +252,14 @@ void WillWriteToDisk(size_t data_len); // For a given SourceStream object and the bytes available to write, determine - // the actual number of bytes it can write to the disk. For parallel - // downloading, if the first disk IO writes to a location that is already - // written by another stream, the current stream should stop writing. Returns - // true if the stream can write no more data and should be finished, returns - // false otherwise. + // the number of bytes to validate and the number of bytes it can write to the + // disk. For parallel downloading, if the first disk IO writes to a location + // that is already written by another stream, the current stream should stop + // writing. Returns true if the stream can write no more data and should be + // finished, returns false otherwise. bool CalculateBytesToWrite(SourceStream* source_stream, size_t bytes_available_to_write, + size_t* bytes_to_validate, size_t* bytes_to_write); // Called when a new SourceStream object is added.
diff --git a/components/download/public/common/download_save_info.cc b/components/download/public/common/download_save_info.cc index 2b25b62..c66a6003f 100644 --- a/components/download/public/common/download_save_info.cc +++ b/components/download/public/common/download_save_info.cc
@@ -15,4 +15,8 @@ DownloadSaveInfo::DownloadSaveInfo(DownloadSaveInfo&& that) = default; +int64_t DownloadSaveInfo::GetStartingFileWriteOffset() { + return file_offset >= 0 ? file_offset : offset; +} + } // namespace download
diff --git a/components/download/public/common/download_save_info.h b/components/download/public/common/download_save_info.h index a1e00c8..9f249c7 100644 --- a/components/download/public/common/download_save_info.h +++ b/components/download/public/common/download_save_info.h
@@ -30,6 +30,8 @@ ~DownloadSaveInfo(); DownloadSaveInfo(DownloadSaveInfo&& that); + int64_t GetStartingFileWriteOffset(); + // If non-empty, contains the full target path of the download that has been // determined prior to download initiation. This is considered to be a trusted // path. @@ -42,9 +44,18 @@ // If valid, contains the source data stream for the file contents. base::File file; - // The file offset at which to start the download. + // The offset sent to the server when requesting the download. During + // resumption, |offset| could be smaller than the downloaded content length. + // This is because download may request some data to validate whether the + // content has changed. int64_t offset = 0; + // The file offset to start writing to disk. If this value is negative, + // download stream will be writing to the disk starting at |offset|. + // Otherwise, this value will be used. Data received before |file_offset| are + // used for validation purpose. + int64_t file_offset = -1; + // The number of the bytes to download from |offset|. // Ask to retrieve segment of the download file when length is greater than 0. // Request the rest of the file starting from |offset|, when length is
diff --git a/components/ntp_tiles/features.cc b/components/ntp_tiles/features.cc index a5baa53..0ea51f07 100644 --- a/components/ntp_tiles/features.cc +++ b/components/ntp_tiles/features.cc
@@ -20,4 +20,7 @@ const base::Feature kUsePopularSitesSuggestions{ "UsePopularSitesSuggestions", base::FEATURE_ENABLED_BY_DEFAULT}; +const base::Feature kDefaultSearchShortcut{"DefaultSearchShortcut", + base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace ntp_tiles
diff --git a/components/ntp_tiles/features.h b/components/ntp_tiles/features.h index d9e819607..39dc61d 100644 --- a/components/ntp_tiles/features.h +++ b/components/ntp_tiles/features.h
@@ -26,6 +26,9 @@ // If this feature is enabled, we enable popular sites in the suggestions UI. extern const base::Feature kUsePopularSitesSuggestions; +// If enabled, show a Google search shortcut on the NTP by default. +extern const base::Feature kDefaultSearchShortcut; + } // namespace ntp_tiles #endif // COMPONENTS_NTP_TILES_FEATURES_H_
diff --git a/components/ntp_tiles_strings.grdp b/components/ntp_tiles_strings.grdp new file mode 100644 index 0000000..6500dc8d --- /dev/null +++ b/components/ntp_tiles_strings.grdp
@@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <if expr="not is_android"> + <!-- The title for the Google Search shortcut. --> + <message name="IDS_NTP_DEFAULT_SEARCH_TITLE" translateable="false" desc="The label for the default Search shortcut on the New Tab Page."> + Google + </message> + + <!-- The URL for the Google Search shortcut. --> + <message name="IDS_NTP_DEFAULT_SEARCH_URL" translateable="false"> + https://www.google.com + </message> + </if> +</grit-part>
diff --git a/components/policy/core/browser/android/policy_converter.cc b/components/policy/core/browser/android/policy_converter.cc index 9d41ad0..63e5eb3c 100644 --- a/components/policy/core/browser/android/policy_converter.cc +++ b/components/policy/core/browser/android/policy_converter.cc
@@ -90,13 +90,12 @@ JNIEnv* env, const JavaRef<jobjectArray>& array) { DCHECK(!array.is_null()); - int length = static_cast<int>(env->GetArrayLength(array.obj())); - DCHECK_GE(length, 0) << "Invalid array length: " << length; + base::android::JavaObjectArrayReader<jstring> array_reader(array); + DCHECK_GE(array_reader.size(), 0) + << "Invalid array length: " << array_reader.size(); std::unique_ptr<base::ListValue> list_value(new base::ListValue()); - for (int i = 0; i < length; ++i) { - base::android::ScopedJavaLocalRef<jstring> j_str( - env, static_cast<jstring>(env->GetObjectArrayElement(array.obj(), i))); + for (auto j_str : array_reader) { list_value->AppendString(ConvertJavaStringToUTF8(env, j_str)); }
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index adb967a..96d7269 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -14895,7 +14895,7 @@ 'dynamic_refresh': True, 'per_profile': True, }, - 'supported_on': ['chrome.*:76-'], + 'supported_on': ['chrome.*:77-'], 'caption': '''URL of an XML file that contains URLs that should never trigger a browser switch.''', 'tags': [], 'desc': '''This policy is a URL, that points to an XML file in the same format as Internet Explorer's <ph name="IEEM_SITELIST_POLICY">SiteList</ph> policy. This loads rules from an XML file, without sharing those rules with Internet Explorer.
diff --git a/components/sync/test/fake_server/android/fake_server_helper_android.cc b/components/sync/test/fake_server/android/fake_server_helper_android.cc index b09ccd9..88625c8 100644 --- a/components/sync/test/fake_server/android/fake_server_helper_android.cc +++ b/components/sync/test/fake_server/android/fake_server_helper_android.cc
@@ -91,9 +91,7 @@ jlong fake_server, const JavaParamRef<jobjectArray>& url_array) { std::multiset<std::string> tab_urls; - for (int i = 0; i < env->GetArrayLength(url_array); i++) { - base::android::ScopedJavaLocalRef<jstring> j_string( - env, static_cast<jstring>(env->GetObjectArrayElement(url_array, i))); + for (auto j_string : url_array.ReadElements<jstring>()) { tab_urls.insert(base::android::ConvertJavaStringToUTF8(env, j_string)); } fake_server::SessionsHierarchy expected_sessions;
diff --git a/components/update_client/utils.cc b/components/update_client/utils.cc index ded9add..4952c37 100644 --- a/components/update_client/utils.cc +++ b/components/update_client/utils.cc
@@ -52,8 +52,12 @@ } std::string GetCrxComponentID(const CrxComponent& component) { - const std::string result = crx_file::id_util::GenerateIdFromHash( - &component.pk_hash[0], component.pk_hash.size()); + return GetCrxIdFromPublicKeyHash(component.pk_hash); +} + +std::string GetCrxIdFromPublicKeyHash(const std::vector<uint8_t>& pk_hash) { + const std::string result = + crx_file::id_util::GenerateIdFromHash(&pk_hash[0], pk_hash.size()); DCHECK(crx_file::id_util::IdIsValid(result)); return result; }
diff --git a/components/update_client/utils.h b/components/update_client/utils.h index 50e891f..14567e6 100644 --- a/components/update_client/utils.h +++ b/components/update_client/utils.h
@@ -46,6 +46,9 @@ // format similar with the format of an extension id. std::string GetCrxComponentID(const CrxComponent& component); +// Returns a CRX id from a public key hash. +std::string GetCrxIdFromPublicKeyHash(const std::vector<uint8_t>& pk_hash); + // Returns true if the actual SHA-256 hash of the |filepath| matches the // |expected_hash|. bool VerifyFileHash256(const base::FilePath& filepath,
diff --git a/components/update_client/utils_unittest.cc b/components/update_client/utils_unittest.cc index e2670e9..71a8b886 100644 --- a/components/update_client/utils_unittest.cc +++ b/components/update_client/utils_unittest.cc
@@ -2,10 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "components/update_client/utils.h" + +#include <iterator> + #include "base/files/file_path.h" #include "base/path_service.h" #include "components/update_client/updater_state.h" -#include "components/update_client/utils.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -79,6 +82,16 @@ GetCrxComponentID(component)); } +TEST(UpdateClientUtils, GetCrxIdFromPublicKeyHash) { + static const uint8_t kHash[16] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + }; + + EXPECT_EQ(std::string("abcdefghijklmnopabcdefghijklmnop"), + GetCrxIdFromPublicKeyHash({std::cbegin(kHash), std::cend(kHash)})); +} + // Tests that the name of an InstallerAttribute matches ^[-_=a-zA-Z0-9]{1,256}$ TEST(UpdateClientUtils, IsValidInstallerAttributeName) { // Test the length boundaries.
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index fd4ee39..74760af8 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -1346,7 +1346,8 @@ "net/view_blob_internals_job_factory.h", "network_service_client.cc", "network_service_client.h", - "network_service_instance.cc", + "network_service_instance_impl.cc", + "network_service_instance_impl.h", "notification_service_impl.cc", "notification_service_impl.h", "notifications/blink_notification_service_impl.cc",
diff --git a/content/browser/android/app_web_message_port.cc b/content/browser/android/app_web_message_port.cc index 3711219..a1537873 100644 --- a/content/browser/android/app_web_message_port.cc +++ b/content/browser/android/app_web_message_port.cc
@@ -22,10 +22,7 @@ const base::android::JavaRef<jobjectArray>& jports) { std::vector<blink::MessagePortChannel> channels; if (!jports.is_null()) { - jsize num_ports = env->GetArrayLength(jports.obj()); - for (jsize i = 0; i < num_ports; ++i) { - base::android::ScopedJavaLocalRef<jobject> jport( - env, env->GetObjectArrayElement(jports.obj(), i)); + for (auto jport : jports.ReadElements<jobject>()) { jint native_port = Java_AppWebMessagePort_releaseNativeHandle(env, jport); channels.push_back(blink::MessagePortChannel( mojo::ScopedMessagePipeHandle(mojo::MessagePipeHandle(native_port))));
diff --git a/content/browser/android/content_feature_list.cc b/content/browser/android/content_feature_list.cc index c182bc1..d7e21b9 100644 --- a/content/browser/android/content_feature_list.cc +++ b/content/browser/android/content_feature_list.cc
@@ -24,7 +24,6 @@ const base::Feature* kFeaturesExposedToJava[] = { &features::kBackgroundMediaRendererHasModerateBinding, &kEnhancedSelectionInsertionHandle, - &features::kServiceWorkerForegroundPriority, &kServiceGroupImportance, };
diff --git a/content/browser/android/java/gin_java_bound_object.cc b/content/browser/android/java/gin_java_bound_object.cc index b762a9c..ce1cc16 100644 --- a/content/browser/android/java/gin_java_bound_object.cc +++ b/content/browser/android/java/gin_java_bound_object.cc
@@ -11,6 +11,7 @@ #include "jni/Object_jni.h" using base::android::AttachCurrentThread; +using base::android::JavaObjectArrayReader; using base::android::ScopedJavaLocalRef; namespace content { @@ -134,16 +135,11 @@ return; } - ScopedJavaLocalRef<jobjectArray> methods(GetClassMethods(env, clazz)); - size_t num_methods = env->GetArrayLength(methods.obj()); + JavaObjectArrayReader<jobject> methods(GetClassMethods(env, clazz)); // Java objects always have public methods. - DCHECK(num_methods); + DCHECK_GT(methods.size(), 0); - for (size_t i = 0; i < num_methods; ++i) { - ScopedJavaLocalRef<jobject> java_method( - env, - env->GetObjectArrayElement(methods.obj(), i)); - + for (auto java_method : methods) { if (!safe_annotation_clazz_.is_null()) { if (!IsAnnotationPresent(env, java_method, safe_annotation_clazz_)) continue;
diff --git a/content/browser/child_process_launcher.cc b/content/browser/child_process_launcher.cc index e3086c3..84da2e4 100644 --- a/content/browser/child_process_launcher.cc +++ b/content/browser/child_process_launcher.cc
@@ -188,9 +188,7 @@ bool ChildProcessLauncherPriority::is_background() const { return !visible && !has_media_stream && !boost_for_pending_views && - !(has_foreground_service_worker && - base::FeatureList::IsEnabled( - features::kServiceWorkerForegroundPriority)); + !has_foreground_service_worker; } bool ChildProcessLauncherPriority::operator==(
diff --git a/content/browser/indexed_db/indexed_db_database.cc b/content/browser/indexed_db/indexed_db_database.cc index 1362688..6fade13d 100644 --- a/content/browser/indexed_db/indexed_db_database.cc +++ b/content/browser/indexed_db/indexed_db_database.cc
@@ -233,7 +233,7 @@ // Requested version is higher than current version - upgrade needed. DCHECK_GT(new_version, old_version); - if (db_->connections_.empty()) { + if (db_->HasNoConnections()) { std::vector<ScopesLockManager::ScopeLockRequest> lock_requests = { {kDatabaseRangeLockLevel, GetDatabaseLockRange(db_->metadata_.id), ScopesLockManager::LockType::kExclusive}}; @@ -251,8 +251,7 @@ // "versionchange" event was ignored. DCHECK_NE(pending_->data_loss_info.status, blink::mojom::IDBDataLoss::Total); - for (const auto* connection : db_->connections_) - connection->callbacks()->OnVersionChange(old_version, new_version); + db_->SendVersionChangeToAllConnections(old_version, new_version); // When all connections have closed the upgrade can proceed. } @@ -278,7 +277,7 @@ return; } - if (!db_->connections_.empty()) + if (!db_->HasNoConnections()) return; std::vector<ScopesLockManager::ScopeLockRequest> lock_requests = { @@ -375,7 +374,7 @@ weak_factory_(this) {} void Perform() override { - if (db_->connections_.empty()) { + if (db_->HasNoConnections()) { // No connections, so delete immediately. DoDelete(); return; @@ -385,8 +384,7 @@ // close_pending set. const int64_t old_version = db_->metadata_.version; const int64_t new_version = IndexedDBDatabaseMetadata::NO_VERSION; - for (const auto* connection : db_->connections_) - connection->callbacks()->OnVersionChange(old_version, new_version); + db_->SendVersionChangeToAllConnections(old_version, new_version); } void OnVersionChangeIgnored() const override { @@ -394,7 +392,7 @@ } void OnConnectionClosed(IndexedDBConnection* connection) override { - if (!db_->connections_.empty()) + if (!db_->HasNoConnections()) return; DoDelete(); @@ -599,6 +597,18 @@ active_request_->OnVersionChangeIgnored(); } +bool IndexedDBDatabase::HasNoConnections() const { + return force_closing_ || connections_.empty(); +} + +void IndexedDBDatabase::SendVersionChangeToAllConnections(int64_t old_version, + int64_t new_version) { + if (force_closing_) + return; + for (const auto* connection : connections_) + connection->callbacks()->OnVersionChange(old_version, new_version); +} + void IndexedDBDatabase::ConnectionClosed(IndexedDBConnection* connection) { if (force_closing_) return; @@ -1991,7 +2001,8 @@ // connections to close, or the actual upgrade transaction from an active // request. Notify the active request if it's the latter. if (active_request_ && - mode == blink::mojom::IDBTransactionMode::VersionChange) { + mode == blink::mojom::IDBTransactionMode::VersionChange && + !force_closing_) { active_request_->UpgradeTransactionFinished(committed); } }
diff --git a/content/browser/indexed_db/indexed_db_database.h b/content/browser/indexed_db/indexed_db_database.h index fe819f7..ced3908a3 100644 --- a/content/browser/indexed_db/indexed_db_database.h +++ b/content/browser/indexed_db/indexed_db_database.h
@@ -366,6 +366,11 @@ // pending connection. void VersionChangeIgnored(); + bool HasNoConnections() const; + + void SendVersionChangeToAllConnections(int64_t old_version, + int64_t new_version); + // This can only be called when the given connection is closed and no longer // has any transaction objects. void ConnectionClosed(IndexedDBConnection* connection);
diff --git a/content/browser/network_service_instance.cc b/content/browser/network_service_instance_impl.cc similarity index 89% rename from content/browser/network_service_instance.cc rename to content/browser/network_service_instance_impl.cc index cfeea7a..25a7cf7 100644 --- a/content/browser/network_service_instance.cc +++ b/content/browser/network_service_instance_impl.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/public/browser/network_service_instance.h" +#include "content/browser/network_service_instance_impl.h" #include <map> #include <memory> @@ -17,12 +17,14 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" +#include "base/threading/sequence_local_storage_slot.h" #include "build/build_config.h" #include "content/browser/browser_main_loop.h" #include "content/browser/network_service_client.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/content_browser_client.h" +#include "content/public/browser/network_service_instance.h" #include "content/public/common/network_service_util.h" #include "content/public/common/service_manager_connection.h" #include "content/public/common/service_names.mojom.h" @@ -45,9 +47,16 @@ constexpr char kKrb5ConfEnvName[] = "KRB5_CONFIG"; #endif +bool g_force_create_network_service_directly = false; network::mojom::NetworkServicePtr* g_network_service_ptr = nullptr; network::NetworkConnectionTracker* g_network_connection_tracker; -network::NetworkService* g_network_service; + +std::unique_ptr<network::NetworkService>& GetLocalNetworkService() { + static base::NoDestructor< + base::SequenceLocalStorageSlot<std::unique_ptr<network::NetworkService>>> + service; + return service->Get(); +} network::mojom::NetworkServiceParamsPtr CreateNetworkServiceParams() { network::mojom::NetworkServiceParamsPtr network_service_params = @@ -80,14 +89,14 @@ } void CreateNetworkServiceOnIO(network::mojom::NetworkServiceRequest request) { - if (g_network_service) { + if (GetLocalNetworkService()) { // GetNetworkServiceImpl() was already called and created the object, so // just bind it. - g_network_service->Bind(std::move(request)); + GetLocalNetworkService()->Bind(std::move(request)); return; } - g_network_service = new network::NetworkService( + GetLocalNetworkService() = std::make_unique<network::NetworkService>( nullptr, std::move(request), GetContentClient()->browser()->GetNetLog()); } @@ -112,10 +121,12 @@ } // namespace network::mojom::NetworkService* GetNetworkService() { - service_manager::Connector* connector = - base::FeatureList::IsEnabled(network::features::kNetworkService) - ? ServiceManagerConnection::GetForProcess()->GetConnector() - : nullptr; + service_manager::Connector* connector = nullptr; + if (base::FeatureList::IsEnabled(network::features::kNetworkService) && + ServiceManagerConnection::GetForProcess() && // null in unit tests. + !g_force_create_network_service_directly) { + connector = ServiceManagerConnection::GetForProcess()->GetConnector(); + } return GetNetworkServiceFromConnector(connector); } @@ -145,13 +156,12 @@ auto request = mojo::MakeRequest(g_network_service_ptr); auto leaked_pipe = request.PassMessagePipe().release(); } else { - if (is_network_service_enabled) { + if (is_network_service_enabled && connector) { connector->BindInterface(mojom::kNetworkServiceName, g_network_service_ptr); g_network_service_ptr->set_connection_error_handler( base::BindOnce(&OnNetworkServiceCrash)); } else { - DCHECK(!g_network_service_ptr->is_bound()); base::PostTaskWithTraits( FROM_HERE, {BrowserThread::IO}, base::BindOnce(CreateNetworkServiceOnIO, @@ -237,12 +247,12 @@ network::NetworkService* GetNetworkServiceImpl() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService)); - if (!g_network_service) { - g_network_service = new network::NetworkService( + if (!GetLocalNetworkService()) { + GetLocalNetworkService() = std::make_unique<network::NetworkService>( nullptr, nullptr, GetContentClient()->browser()->GetNetLog()); } - return g_network_service; + return GetLocalNetworkService().get(); } #if defined(OS_CHROMEOS) @@ -311,4 +321,13 @@ return instance->get(); } +void ForceCreateNetworkServiceDirectlyForTesting() { + g_force_create_network_service_directly = true; +} + +void ResetNetworkServiceForTesting() { + delete g_network_service_ptr; + g_network_service_ptr = nullptr; +} + } // namespace content
diff --git a/content/browser/network_service_instance_impl.h b/content/browser/network_service_instance_impl.h new file mode 100644 index 0000000..641d081 --- /dev/null +++ b/content/browser/network_service_instance_impl.h
@@ -0,0 +1,31 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_NETWORK_SERVICE_INSTANCE_IMPL_H_ +#define CONTENT_BROWSER_NETWORK_SERVICE_INSTANCE_IMPL_H_ + +#include "base/callback.h" +#include "base/callback_list.h" +#include "content/common/content_export.h" + +namespace content { + +// Creates the network::NetworkService object on the IO thread directly instead +// of trying to go through the ServiceManager. +CONTENT_EXPORT void ForceCreateNetworkServiceDirectlyForTesting(); + +// Resets the interface ptr to the network service. +CONTENT_EXPORT void ResetNetworkServiceForTesting(); + +// Registers |handler| to run (on UI thread) after NetworkServicePtr encounters +// an error. Note that there are no ordering guarantees wrt error handlers for +// other interfaces (e.g. NetworkContextPtr and/or URLLoaderFactoryPtr). +// +// Can only be called on the UI thread. No-op if NetworkService is disabled. +CONTENT_EXPORT std::unique_ptr<base::CallbackList<void()>::Subscription> +RegisterNetworkServiceCrashHandler(base::RepeatingClosure handler); + +} // namespace content + +#endif // CONTENT_BROWSER_NETWORK_SERVICE_INSTANCE_IMPL_H_
diff --git a/content/browser/network_service_restart_browsertest.cc b/content/browser/network_service_restart_browsertest.cc index 1eb5cfc..2aca979f 100644 --- a/content/browser/network_service_restart_browsertest.cc +++ b/content/browser/network_service_restart_browsertest.cc
@@ -12,6 +12,7 @@ #include "build/build_config.h" #include "content/browser/frame_host/render_frame_host_impl.h" #include "content/browser/frame_host/render_frame_message_filter.h" +#include "content/browser/network_service_instance_impl.h" #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/service_worker/embedded_worker_instance.h" #include "content/browser/service_worker/embedded_worker_status.h"
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 9f1a283..2b50b23 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -109,6 +109,7 @@ #include "content/browser/media/midi_host.h" #include "content/browser/mime_registry_impl.h" #include "content/browser/navigation_subresource_loader_params.h" +#include "content/browser/network_service_instance_impl.h" #include "content/browser/payments/payment_manager.h" #include "content/browser/permissions/permission_service_context.h" #include "content/browser/permissions/permission_service_impl.h"
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc index f747a13..c0094df7 100644 --- a/content/browser/service_worker/embedded_worker_instance.cc +++ b/content/browser/service_worker/embedded_worker_instance.cc
@@ -35,7 +35,6 @@ #include "content/public/browser/content_browser_client.h" #include "content/public/common/child_process_host.h" #include "content/public/common/content_client.h" -#include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" #include "ipc/ipc_message.h" #include "mojo/public/cpp/bindings/strong_binding.h" @@ -278,8 +277,6 @@ void NotifyForegroundServiceWorkerOnUIThread(bool added, int process_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - DCHECK( - base::FeatureList::IsEnabled(features::kServiceWorkerForegroundPriority)); RenderProcessHost* rph = RenderProcessHost::FromID(process_id); if (!rph) @@ -1190,8 +1187,6 @@ void EmbeddedWorkerInstance::NotifyForegroundServiceWorkerAdded() { DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK( - base::FeatureList::IsEnabled(features::kServiceWorkerForegroundPriority)); if (!process_handle_ || foreground_notified_) return; @@ -1205,9 +1200,6 @@ void EmbeddedWorkerInstance::NotifyForegroundServiceWorkerRemoved() { DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK( - !foreground_notified_ || - base::FeatureList::IsEnabled(features::kServiceWorkerForegroundPriority)); if (!process_handle_ || !foreground_notified_) return;
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc index d8d548a..89450d2 100644 --- a/content/browser/service_worker/service_worker_version.cc +++ b/content/browser/service_worker/service_worker_version.cc
@@ -37,7 +37,6 @@ #include "content/public/browser/content_browser_client.h" #include "content/public/browser/page_navigator.h" #include "content/public/common/content_client.h" -#include "content/public/common/content_features.h" #include "content/public/common/result_codes.h" #include "net/http/http_response_headers.h" #include "net/http/http_response_info.h" @@ -2114,8 +2113,6 @@ bool ServiceWorkerVersion::ShouldRequireForegroundPriority( int worker_process_id) const { DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (!base::FeatureList::IsEnabled(features::kServiceWorkerForegroundPriority)) - return false; // Currently FetchEvents are the only type of event we need to really process // at foreground priority. If the service worker does not have a FetchEvent
diff --git a/content/browser/service_worker/service_worker_version_unittest.cc b/content/browser/service_worker/service_worker_version_unittest.cc index af701dc..cf29f82 100644 --- a/content/browser/service_worker/service_worker_version_unittest.cc +++ b/content/browser/service_worker/service_worker_version_unittest.cc
@@ -28,7 +28,6 @@ #include "content/browser/service_worker/service_worker_registration.h" #include "content/browser/service_worker/service_worker_test_utils.h" #include "content/common/service_worker/service_worker_utils.h" -#include "content/public/common/content_features.h" #include "content/public/test/mock_render_process_host.h" #include "content/public/test/test_browser_thread_bundle.h" #include "content/public/test/test_service.mojom.h" @@ -1192,9 +1191,6 @@ TEST_F(ServiceWorkerVersionTest, ForegroundServiceWorkerCountUpdatedByControllee) { - base::test::ScopedFeatureList scoped_list; - scoped_list.InitAndEnableFeature(features::kServiceWorkerForegroundPriority); - // Start the worker before we have a controllee. base::Optional<blink::ServiceWorkerStatusCode> status; base::RunLoop run_loop; @@ -1230,9 +1226,6 @@ TEST_F(ServiceWorkerVersionTest, ForegroundServiceWorkerCountNotUpdatedBySameProcessControllee) { - base::test::ScopedFeatureList scoped_list; - scoped_list.InitAndEnableFeature(features::kServiceWorkerForegroundPriority); - // Start the worker before we have a controllee. base::Optional<blink::ServiceWorkerStatusCode> status; base::RunLoop run_loop; @@ -1258,9 +1251,6 @@ TEST_F(ServiceWorkerVersionTest, ForegroundServiceWorkerCountUpdatedByControlleeProcessIdChange) { - base::test::ScopedFeatureList scoped_list; - scoped_list.InitAndEnableFeature(features::kServiceWorkerForegroundPriority); - // Start the worker before we have a controllee. base::Optional<blink::ServiceWorkerStatusCode> status; base::RunLoop run_loop; @@ -1313,9 +1303,6 @@ TEST_F(ServiceWorkerVersionTest, ForegroundServiceWorkerCountUpdatedByWorkerStatus) { - base::test::ScopedFeatureList scoped_list; - scoped_list.InitAndEnableFeature(features::kServiceWorkerForegroundPriority); - // Add a controllee in a different process from the service worker. auto remote_endpoint = ActivateWithControllee(); @@ -1358,9 +1345,6 @@ TEST_F(ServiceWorkerVersionNoFetchHandlerTest, ForegroundServiceWorkerCountNotUpdated) { - base::test::ScopedFeatureList scoped_list; - scoped_list.InitAndEnableFeature(features::kServiceWorkerForegroundPriority); - // Start the worker before we have a controllee. base::Optional<blink::ServiceWorkerStatusCode> status; base::RunLoop run_loop;
diff --git a/content/browser/web_package/signed_exchange_handler_unittest.cc b/content/browser/web_package/signed_exchange_handler_unittest.cc index b2423f8..b1bf2628c 100644 --- a/content/browser/web_package/signed_exchange_handler_unittest.cc +++ b/content/browser/web_package/signed_exchange_handler_unittest.cc
@@ -152,8 +152,6 @@ base::StringPiece sct_list_from_tls_extension, net::SignedCertificateTimestampAndStatusList* output_scts, const net::NetLogWithSource& net_log)); - MOCK_METHOD1(SetObserver, void(CTVerifier::Observer*)); - MOCK_CONST_METHOD0(GetObserver, CTVerifier::Observer*()); }; class MockCTPolicyEnforcer : public net::CTPolicyEnforcer {
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java index 3d30bd0..c5e7ff9 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java
@@ -501,9 +501,6 @@ boolean mediaRendererHasModerate = ContentFeatureList.isEnabled( ContentFeatureList.BACKGROUND_MEDIA_RENDERER_HAS_MODERATE_BINDING); - boolean serviceWorkerForegroundPriority = - ContentFeatureList.isEnabled(ContentFeatureList.SERVICE_WORKER_FOREGROUND_PRIORITY); - @ChildProcessImportance int newEffectiveImportance; if ((visible && frameDepth == 0) || importance == ChildProcessImportance.IMPORTANT @@ -511,8 +508,7 @@ newEffectiveImportance = ChildProcessImportance.IMPORTANT; } else if ((visible && frameDepth > 0 && intersectsViewport) || boostForPendingViews || importance == ChildProcessImportance.MODERATE - || (hasMediaStream && mediaRendererHasModerate) - || (hasForegroundServiceWorker && serviceWorkerForegroundPriority)) { + || (hasMediaStream && mediaRendererHasModerate) || hasForegroundServiceWorker) { newEffectiveImportance = ChildProcessImportance.MODERATE; } else { newEffectiveImportance = ChildProcessImportance.NORMAL;
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentFeatureList.java b/content/public/android/java/src/org/chromium/content/browser/ContentFeatureList.java index 1d908e2..a217470 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentFeatureList.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentFeatureList.java
@@ -38,8 +38,5 @@ public static final String SERVICE_GROUP_IMPORTANCE = "ServiceGroupImportance"; - public static final String SERVICE_WORKER_FOREGROUND_PRIORITY = - "ServiceWorkerForegroundPriority"; - private static native boolean nativeIsEnabled(String featureName); }
diff --git a/content/public/browser/network_service_instance.h b/content/public/browser/network_service_instance.h index b79141e..905385e6 100644 --- a/content/public/browser/network_service_instance.h +++ b/content/public/browser/network_service_instance.h
@@ -50,14 +50,6 @@ CONTENT_EXPORT network::mojom::NetworkService* GetNetworkServiceFromConnector( service_manager::Connector* connector); -// Registers |handler| to run (on UI thread) after NetworkServicePtr encounters -// an error. Note that there are no ordering guarantees wrt error handlers for -// other interfaces (e.g. NetworkContextPtr and/or URLLoaderFactoryPtr). -// -// Can only be called on the UI thread. No-op if NetworkService is disabled. -CONTENT_EXPORT std::unique_ptr<base::CallbackList<void()>::Subscription> -RegisterNetworkServiceCrashHandler(base::RepeatingClosure handler); - // When network service is disabled, returns the in-process NetworkService // pointer which is used to ease transition to network service. // Must only be called on the IO thread. Must not be called if the network
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 5c9ae72..6a4f0b7 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -406,11 +406,6 @@ "SendBeaconThrowForBlobWithNonSimpleType", base::FEATURE_DISABLED_BY_DEFAULT}; -// Keep processes with service workers controlling clients from other -// processes at foreground priority. (crbug.com/928904) -const base::Feature kServiceWorkerForegroundPriority{ - "ServiceWorkerForegroundPriority", base::FEATURE_ENABLED_BY_DEFAULT}; - // Enables long running message dispatch for service workers. // This is a temporary addition only to be used for the Android Messages // integration with ChromeOS (http://crbug.com/823256).
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index 062664e1..9637f71 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -99,7 +99,6 @@ CONTENT_EXPORT extern const base::Feature kScrollAnchorSerialization; CONTENT_EXPORT extern const base::Feature kSendBeaconThrowForBlobWithNonSimpleType; -CONTENT_EXPORT extern const base::Feature kServiceWorkerForegroundPriority; CONTENT_EXPORT extern const base::Feature kServiceWorkerLongRunningMessage; CONTENT_EXPORT extern const base::Feature kServiceWorkerPaymentApps; CONTENT_EXPORT extern const base::Feature kSharedArrayBuffer;
diff --git a/content/public/test/test_file_error_injector.cc b/content/public/test/test_file_error_injector.cc index d8669a2..f26dd9fa 100644 --- a/content/public/test/test_file_error_injector.cc +++ b/content/public/test/test_file_error_injector.cc
@@ -52,9 +52,11 @@ bool is_parallelizable) override; // DownloadFile interface. - download::DownloadInterruptReason WriteDataToFile(int64_t offset, - const char* data, - size_t data_len) override; + download::DownloadInterruptReason ValidateAndWriteDataToFile( + int64_t offset, + const char* data, + size_t bytes_to_validate, + size_t bytes_to_write) override; download::DownloadInterruptReason HandleStreamCompletionStatus( SourceStream* source_stream) override; @@ -174,13 +176,15 @@ received_slices, is_parallelizable); } -download::DownloadInterruptReason DownloadFileWithError::WriteDataToFile( - int64_t offset, - const char* data, - size_t data_len) { +download::DownloadInterruptReason +DownloadFileWithError::ValidateAndWriteDataToFile(int64_t offset, + const char* data, + size_t bytes_to_validate, + size_t bytes_to_write) { return ShouldReturnError( TestFileErrorInjector::FILE_OPERATION_WRITE, - download::DownloadFileImpl::WriteDataToFile(offset, data, data_len)); + download::DownloadFileImpl::ValidateAndWriteDataToFile( + offset, data, bytes_to_validate, bytes_to_write)); } download::DownloadInterruptReason
diff --git a/content/public/test/unittest_test_suite.cc b/content/public/test/unittest_test_suite.cc index 60a4718..c949988 100644 --- a/content/public/test/unittest_test_suite.cc +++ b/content/public/test/unittest_test_suite.cc
@@ -11,7 +11,9 @@ #include "base/rand_util.h" #include "base/test/test_suite.h" #include "build/build_config.h" +#include "content/browser/network_service_instance_impl.h" #include "content/test/test_blink_web_unit_test_support.h" +#include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/web/blink.h" #if defined(USE_AURA) @@ -28,6 +30,31 @@ namespace content { +namespace { + +// The global NetworkService object could be created in some tests due to +// various StoragePartition calls. Since it has a mojo pipe that is bound using +// the current thread, which goes away between tests, we need to destruct it to +// avoid calls being dropped silently. +class ResetNetworkServiceBetweenTests : public testing::EmptyTestEventListener { + public: + ResetNetworkServiceBetweenTests() = default; + + void OnTestEnd(const testing::TestInfo& test_info) override { + // If the network::NetworkService object was instantiated during a unit test + // it will be deleted because network_service_instance.cc has it in a + // SequenceLocalStorageSlot. However we want to synchronously destruct the + // InterfacePtr pointing to it to avoid it getting the connection error + // later and have other tests use the InterfacePtr that is invalid. + ResetNetworkServiceForTesting(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ResetNetworkServiceBetweenTests); +}; + +} // namespace + UnitTestTestSuite::UnitTestTestSuite(base::TestSuite* test_suite) : test_suite_(test_suite) { base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); @@ -36,6 +63,12 @@ std::string disabled = command_line->GetSwitchValueASCII(switches::kDisableFeatures); + ForceCreateNetworkServiceDirectlyForTesting(); + + testing::TestEventListeners& listeners = + testing::UnitTest::GetInstance()->listeners(); + listeners.Append(new ResetNetworkServiceBetweenTests); + // Unit tests don't currently work with the Network Service enabled. // base::TestSuite will reset the FeatureList, so modify the underlying // CommandLine object to disable the network service when it's parsed again.
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index 3de2f96..8e55869 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -28,6 +28,7 @@ "//content/app:*", "//content/public/renderer:renderer_sources", "//content/renderer:audio_decoder_fuzzer", + "//chromecast/media/audio:*", ] sources = [
diff --git a/extensions/browser/extension_protocols.cc b/extensions/browser/extension_protocols.cc index 0065675..3e1a04a 100644 --- a/extensions/browser/extension_protocols.cc +++ b/extensions/browser/extension_protocols.cc
@@ -521,8 +521,9 @@ } bool IsBackgroundPageURL(const GURL& url) { - std::string path = url.path(); - return path.size() > 1 && path.substr(1) == kGeneratedBackgroundPageFilename; + base::StringPiece path_piece = url.path_piece(); + return path_piece.size() > 1 && + path_piece.substr(1) == kGeneratedBackgroundPageFilename; } class ExtensionProtocolHandler
diff --git a/extensions/browser/guest_view/extensions_guest_view_message_filter.cc b/extensions/browser/guest_view/extensions_guest_view_message_filter.cc index 3d9b309..77aac8f 100644 --- a/extensions/browser/guest_view/extensions_guest_view_message_filter.cc +++ b/extensions/browser/guest_view/extensions_guest_view_message_filter.cc
@@ -24,6 +24,7 @@ #include "extensions/browser/extension_registry.h" #include "extensions/browser/guest_view/mime_handler_view/mime_handler_stream_manager.h" #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_constants.h" +#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_embedder.h" #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h" #include "extensions/browser/guest_view/web_view/web_view_content_script_manager.h" #include "extensions/browser/guest_view/web_view/web_view_guest.h" @@ -126,6 +127,22 @@ false)); } +void ExtensionsGuestViewMessageFilter::ReadyToCreateMimeHandlerView( + int32_t render_frame_id, + bool success) { + if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) { + base::PostTaskWithTraits( + FROM_HERE, {content::BrowserThread::UI}, + base::BindOnce( + &ExtensionsGuestViewMessageFilter::ReadyToCreateMimeHandlerView, + this, render_frame_id, success)); + return; + } + auto* rfh = + content::RenderFrameHost::FromID(render_process_id_, render_frame_id); + if (auto* mhve = MimeHandlerViewEmbedder::Get(rfh->GetFrameTreeNodeId())) + mhve->ReadyToCreateMimeHandlerView(success); +} void ExtensionsGuestViewMessageFilter::CreateMimeHandlerViewGuestOnUIThread( int render_frame_id, const std::string& view_id,
diff --git a/extensions/browser/guest_view/extensions_guest_view_message_filter.h b/extensions/browser/guest_view/extensions_guest_view_message_filter.h index 6eb5c30..86b62e68 100644 --- a/extensions/browser/guest_view/extensions_guest_view_message_filter.h +++ b/extensions/browser/guest_view/extensions_guest_view_message_filter.h
@@ -82,6 +82,8 @@ int32_t element_instance_id, const gfx::Size& element_size, mime_handler::BeforeUnloadControlPtr before_unload_control) override; + void ReadyToCreateMimeHandlerView(int32_t render_frame_id, + bool success) override; void CreateMimeHandlerViewGuestOnUIThread( int32_t render_frame_id,
diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_embedder.cc b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_embedder.cc index 3a33caa..22ef239c 100644 --- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_embedder.cc +++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_embedder.cc
@@ -33,6 +33,17 @@ } } // namespace +// static +MimeHandlerViewEmbedder* MimeHandlerViewEmbedder::Get( + int32_t frame_tree_node_id) { + const auto& map = *GetMimeHandlerViewEmbeddersMap(); + auto it = map.find(frame_tree_node_id); + if (it == map.cend()) + return nullptr; + return it->second.get(); +} + +// static void MimeHandlerViewEmbedder::Create(int32_t frame_tree_node_id, const GURL& resource_url, const std::string& mime_type, @@ -96,6 +107,13 @@ render_frame_host_->GetLastCommittedURL() != resource_url_) { return; } + if (!ready_to_create_mime_handler_view_) { + // Renderer notifies the browser about creating MimeHandlerView right after + // HTMLPlugInElement::RequestObject, which is before the plugin element is + // navigated. + GetMimeHandlerViewEmbeddersMap()->erase(frame_tree_node_id_); + return; + } outer_contents_frame_tree_node_id_ = render_frame_host->GetFrameTreeNodeId(); element_instance_id_ = render_frame_host->GetRoutingID(); // This suggests that a same-origin child frame is created under the @@ -185,4 +203,12 @@ } return container_manager_.get(); } + +void MimeHandlerViewEmbedder::ReadyToCreateMimeHandlerView( + bool ready_to_create_mime_handler_view) { + ready_to_create_mime_handler_view_ = ready_to_create_mime_handler_view; + if (!ready_to_create_mime_handler_view_) + GetMimeHandlerViewEmbeddersMap()->erase(frame_tree_node_id_); +} + } // namespace extensions
diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_embedder.h b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_embedder.h index 7dd20a2..0e276e4 100644 --- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_embedder.h +++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_embedder.h
@@ -32,6 +32,10 @@ //. - the embedder or the <iframe> are removed from DOM. class MimeHandlerViewEmbedder : public content::WebContentsObserver { public: + // Returns the instances associated with an ongoing navigation in a frame + // identified by |frame_tree_node_id|. + static MimeHandlerViewEmbedder* Get(int32_t frame_tree_node_id); + static void Create(int32_t frame_tree_node_id, const GURL& resource_url, const std::string& mime_type, @@ -46,6 +50,8 @@ void DidStartNavigation(content::NavigationHandle* handle) override; void ReadyToCommitNavigation(content::NavigationHandle* handle) override; + void ReadyToCreateMimeHandlerView(bool result); + private: MimeHandlerViewEmbedder(int32_t frame_tree_node_id, const GURL& resource_url, @@ -82,6 +88,8 @@ const std::string internal_id_; + bool ready_to_create_mime_handler_view_ = false; + base::WeakPtrFactory<MimeHandlerViewEmbedder> weak_factory_; DISALLOW_COPY_AND_ASSIGN(MimeHandlerViewEmbedder);
diff --git a/extensions/common/BUILD.gn b/extensions/common/BUILD.gn index feb42c8..93439e9a 100644 --- a/extensions/common/BUILD.gn +++ b/extensions/common/BUILD.gn
@@ -383,6 +383,8 @@ sources = [ "api/declarative_net_request/test_utils.cc", "api/declarative_net_request/test_utils.h", + "file_test_util.cc", + "file_test_util.h", ] deps = [
diff --git a/extensions/common/file_test_util.cc b/extensions/common/file_test_util.cc new file mode 100644 index 0000000..f15c5f4 --- /dev/null +++ b/extensions/common/file_test_util.cc
@@ -0,0 +1,17 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "extensions/common/file_test_util.h" +#include "base/files/file_util.h" + +namespace extensions { +namespace file_test_util { + +bool WriteFile(const base::FilePath& path, base::StringPiece content) { + return base::WriteFile(path, content.data(), content.size()) == + static_cast<int>(content.size()); +} + +} // namespace file_test_util +} // namespace extensions
diff --git a/extensions/common/file_test_util.h b/extensions/common/file_test_util.h new file mode 100644 index 0000000..ecab05df --- /dev/null +++ b/extensions/common/file_test_util.h
@@ -0,0 +1,23 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef EXTENSIONS_COMMON_FILE_TEST_UTIL_H_ +#define EXTENSIONS_COMMON_FILE_TEST_UTIL_H_ + +#include "base/strings/string_piece.h" + +namespace base { +class FilePath; +} + +namespace extensions { +namespace file_test_util { + +// Writes |content| to |path|. Returns true if writing was successful, +// verifying the number of bytes written equals the size of |content|. +bool WriteFile(const base::FilePath& path, base::StringPiece content); + +} // namespace file_test_util +} // namespace extensions + +#endif // EXTENSIONS_COMMON_FILE_TEST_UTIL_H_
diff --git a/extensions/common/mojo/guest_view.mojom b/extensions/common/mojo/guest_view.mojom index 19eae09..d348369 100644 --- a/extensions/common/mojo/guest_view.mojom +++ b/extensions/common/mojo/guest_view.mojom
@@ -30,6 +30,13 @@ int32 element_instance_id, gfx.mojom.Size element_size, extensions.mime_handler.BeforeUnloadControl? before_unload_control); + + // Notifies the browser whether or not now is a good time to start loading the + // MimeHandlerView. |routing_id| identifies the embedder frame. If |success| + // is false, then MimeHandlerViewEmbedder should destroy itself. When + // |success| is true the MimeHandlerViewEmbedder should proceed with attaching + // the GuestView. + ReadyToCreateMimeHandlerView(int32 routing_id, bool success); }; // An interface implemented by the renderer which is used for creating a
diff --git a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_base.cc b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_base.cc index c0b7c84..4e85f0f 100644 --- a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_base.cc +++ b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_base.cc
@@ -146,6 +146,11 @@ } // static +mojom::GuestView* MimeHandlerViewContainerBase::GuestView() { + return GetGuestView(); +} + +// static std::vector<MimeHandlerViewContainerBase*> MimeHandlerViewContainerBase::FromRenderFrame( content::RenderFrame* render_frame) {
diff --git a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_base.h b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_base.h index 1f14dc8..e18ea6b 100644 --- a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_base.h +++ b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_base.h
@@ -46,6 +46,8 @@ ~MimeHandlerViewContainerBase() override; + static mojom::GuestView* GuestView(); + // TODO(ekaramad): Remove this and make MimeHandlerViewContainerManager of // |render_frame| hold on to the list of MimeHandlerViewContainerBase. static std::vector<MimeHandlerViewContainerBase*> FromRenderFrame(
diff --git a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.cc b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.cc index 439870d..d06093d4 100644 --- a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.cc +++ b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.cc
@@ -109,6 +109,18 @@ return true; } +void MimeHandlerViewContainerManager:: + DidBlockMimeHandlerViewForDisallowedPlugin( + const blink::WebElement& plugin_element) { + if (IsManagedByContainerManager(plugin_element)) { + // This is the one injected by HTML string. Return true so that the + // HTMLPlugInElement creates a child frame to be used as the outer + // WebContents frame. + MimeHandlerViewContainerBase::GuestView()->ReadyToCreateMimeHandlerView( + render_frame()->GetRoutingID(), false); + } +} + v8::Local<v8::Object> MimeHandlerViewContainerManager::GetScriptableObject( const blink::WebElement& plugin_element, v8::Isolate* isolate) { @@ -295,6 +307,8 @@ base::ToUpperASCII(plugin_element.GetAttribute("internalid").Utf8()) == internal_id_) { plugin_element_ = plugin_element; + MimeHandlerViewContainerBase::GuestView()->ReadyToCreateMimeHandlerView( + render_frame()->GetRoutingID(), true); } return plugin_element_ == plugin_element; }
diff --git a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.h b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.h index ebfca295..12abbee 100644 --- a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.h +++ b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.h
@@ -66,6 +66,10 @@ const GURL& resource_url, const std::string& mime_type, const content::WebPluginInfo& plugin_info); + // Called to notify about a failed plugin load; this could happen if a + // <webview> with permissions API tries to load a plugin. + void DidBlockMimeHandlerViewForDisallowedPlugin( + const blink::WebElement& plugin_element); // A wrapper for custom postMessage scripts. There should already be a // MimeHandlerViewFrameContainer for |plugin_element|. v8::Local<v8::Object> GetScriptableObject(
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn index 59f5892..034cbfc 100644 --- a/gpu/BUILD.gn +++ b/gpu/BUILD.gn
@@ -197,8 +197,7 @@ ] } -# Disabled on mac due to build failure (crbug.com/967098). -if (!is_android && !is_fuchsia && !is_mac) { +if (!is_android && !is_fuchsia) { proto_library("gl_lpm_fuzzer_proto") { sources = [ "command_buffer/tests/lpm/gl_lpm_fuzzer.proto", @@ -246,6 +245,10 @@ defines = [ "GL_GLEXT_PROTOTYPES" ] + if (is_mac) { + libs = [ "IOSurface.framework" ] + } + deps = [ ":gl_lpm_fuzzer_proto", ":gl_lpm_shader_to_string",
diff --git a/gpu/config/software_rendering_list.json b/gpu/config/software_rendering_list.json index 0042a34..03e2515 100644 --- a/gpu/config/software_rendering_list.json +++ b/gpu/config/software_rendering_list.json
@@ -287,7 +287,6 @@ }, "vendor_id": "0x10de", "gl_vendor": "(?i)nouveau.*", - "driver_vendor": "Mesa", "features": [ "all" ]
diff --git a/gpu/ipc/service/gpu_init.cc b/gpu/ipc/service/gpu_init.cc index 4b413dd..89b8bd0 100644 --- a/gpu/ipc/service/gpu_init.cc +++ b/gpu/ipc/service/gpu_init.cc
@@ -71,6 +71,16 @@ return success; } +#if defined(OS_WIN) +OverlaySupport FlagsToOverlaySupport(UINT flags) { + if (flags & DXGI_OVERLAY_SUPPORT_FLAG_SCALING) + return OverlaySupport::kScaling; + if (flags & DXGI_OVERLAY_SUPPORT_FLAG_DIRECT) + return OverlaySupport::kDirect; + return OverlaySupport::kNone; +} +#endif // OS_WIN + void InitializePlatformOverlaySettings(GPUInfo* gpu_info) { #if defined(OS_WIN) // This has to be called after a context is created, active GPU is identified, @@ -84,19 +94,12 @@ gl::DirectCompositionSurfaceWin::IsDirectCompositionSupported(); gpu_info->supports_overlays = gl::DirectCompositionSurfaceWin::AreOverlaysSupported(); - bool supports_scaling = false; - if (gl::DirectCompositionSurfaceWin::SupportsOverlayFormat( - DXGI_FORMAT_YUY2, &supports_scaling)) { - gpu_info->yuy2_overlay_support = supports_scaling - ? gpu::OverlaySupport::kScaling - : gpu::OverlaySupport::kDirect; - } - if (gl::DirectCompositionSurfaceWin::SupportsOverlayFormat( - DXGI_FORMAT_NV12, &supports_scaling)) { - gpu_info->nv12_overlay_support = supports_scaling - ? gpu::OverlaySupport::kScaling - : gpu::OverlaySupport::kDirect; - } + gpu_info->nv12_overlay_support = FlagsToOverlaySupport( + gl::DirectCompositionSurfaceWin::GetOverlaySupportFlags( + DXGI_FORMAT_NV12)); + gpu_info->yuy2_overlay_support = FlagsToOverlaySupport( + gl::DirectCompositionSurfaceWin::GetOverlaySupportFlags( + DXGI_FORMAT_YUY2)); } #elif defined(OS_ANDROID) if (gpu_info->gpu.vendor_string == "Qualcomm")
diff --git a/ios/chrome/browser/metrics/BUILD.gn b/ios/chrome/browser/metrics/BUILD.gn index 59965713..75424c4c1 100644 --- a/ios/chrome/browser/metrics/BUILD.gn +++ b/ios/chrome/browser/metrics/BUILD.gn
@@ -18,6 +18,16 @@ ] } +source_set("features") { + sources = [ + "features.cc", + "features.h", + ] + deps = [ + "//base", + ] +} + source_set("metrics") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ @@ -47,6 +57,7 @@ ":ukm_url_recorder", ] deps = [ + ":features", "//base", "//components/browser_sync", "//components/crash/core/common",
diff --git a/ios/chrome/browser/metrics/features.cc b/ios/chrome/browser/metrics/features.cc new file mode 100644 index 0000000..d26584cb --- /dev/null +++ b/ios/chrome/browser/metrics/features.cc
@@ -0,0 +1,8 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/metrics/features.h" + +const base::Feature kLogLoadStartedInDidStartNavigation{ + "LogLoadStartedInDidStartNavigation", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/ios/chrome/browser/metrics/features.h b/ios/chrome/browser/metrics/features.h new file mode 100644 index 0000000..e542485a --- /dev/null +++ b/ios/chrome/browser/metrics/features.h
@@ -0,0 +1,13 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_METRICS_FEATURES_H_ +#define IOS_CHROME_BROWSER_METRICS_FEATURES_H_ + +#include "base/feature_list.h" + +// Feature flag to move -LogLoadStarted() to WebStateDidStartNavigation(). +extern const base::Feature kLogLoadStartedInDidStartNavigation; + +#endif // IOS_CHROME_BROWSER_METRICS_FEATURES_H_
diff --git a/ios/chrome/browser/metrics/ios_chrome_stability_metrics_provider.mm b/ios/chrome/browser/metrics/ios_chrome_stability_metrics_provider.mm index 4e51527..d0852a4 100644 --- a/ios/chrome/browser/metrics/ios_chrome_stability_metrics_provider.mm +++ b/ios/chrome/browser/metrics/ios_chrome_stability_metrics_provider.mm
@@ -4,8 +4,10 @@ #include "ios/chrome/browser/metrics/ios_chrome_stability_metrics_provider.h" +#include "base/feature_list.h" #include "base/metrics/histogram_macros.h" #include "ios/chrome/browser/chrome_url_constants.h" +#include "ios/chrome/browser/metrics/features.h" #import "ios/web/public/web_state/navigation_context.h" #import "ios/web/public/web_state/web_state.h" @@ -63,7 +65,8 @@ return; UMA_HISTOGRAM_BOOLEAN(kPageLoadCountLoadingStartedMetric, true); - helper_.LogLoadStarted(); + if (!base::FeatureList::IsEnabled(kLogLoadStartedInDidStartNavigation)) + helper_.LogLoadStarted(); } void IOSChromeStabilityMetricsProvider::WebStateDidStartNavigation( @@ -79,7 +82,8 @@ } else if (navigation_context->IsSameDocument()) { type = PageLoadCountNavigationType::SAME_DOCUMENT_WEB_NAVIGATION; } else { - // TODO(crbug.com/786547): Move helper_.LogLoadStarted() here. + if (base::FeatureList::IsEnabled(kLogLoadStartedInDidStartNavigation)) + helper_.LogLoadStarted(); } UMA_HISTOGRAM_ENUMERATION(kPageLoadCountMetric, type, PageLoadCountNavigationType::COUNT);
diff --git a/ios/chrome/browser/ui/overlays/BUILD.gn b/ios/chrome/browser/ui/overlays/BUILD.gn new file mode 100644 index 0000000..61faa328 --- /dev/null +++ b/ios/chrome/browser/ui/overlays/BUILD.gn
@@ -0,0 +1,79 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("overlays") { + public = [ + "overlay_container_coordinator.h", + "overlay_coordinator_factory.h", + ] + sources = [ + "overlay_container_coordinator.mm", + "overlay_coordinator_factory.mm", + "overlay_presenter_ui_delegate_impl.h", + "overlay_presenter_ui_delegate_impl.mm", + "overlay_request_ui_state.h", + "overlay_request_ui_state.mm", + ] + + configs += [ "//build/config/compiler:enable_arc" ] + + friend = [ ":unit_tests" ] + + deps = [ + ":container_ui", + ":coordinators", + "//base", + "//ios/chrome/browser/main", + "//ios/chrome/browser/overlays", + "//ios/chrome/browser/ui/coordinators:chrome_coordinators", + "//ios/chrome/common/ui_util", + ] +} + +source_set("container_ui") { + sources = [ + "overlay_container_view_controller.h", + "overlay_container_view_controller.mm", + ] + + configs += [ "//build/config/compiler:enable_arc" ] + + deps = [ + "//base", + ] +} + +source_set("coordinators") { + sources = [ + "overlay_request_coordinator.h", + "overlay_request_coordinator.mm", + "overlay_ui_dismissal_delegate.h", + ] + + configs += [ "//build/config/compiler:enable_arc" ] + + deps = [ + "//base", + "//ios/chrome/browser/ui/coordinators:chrome_coordinators", + ] +} + +source_set("unit_tests") { + testonly = true + sources = [ + "overlay_request_ui_state_unittest.mm", + ] + + configs += [ "//build/config/compiler:enable_arc" ] + + deps = [ + ":coordinators", + ":overlays", + "//base/test:test_support", + "//ios/chrome/browser/overlays", + "//ios/chrome/browser/overlays/test", + "//ios/chrome/browser/ui/overlays/test", + "//testing/gtest", + ] +}
diff --git a/ios/chrome/browser/ui/overlays/overlay_container_coordinator.h b/ios/chrome/browser/ui/overlays/overlay_container_coordinator.h new file mode 100644 index 0000000..33664b2 --- /dev/null +++ b/ios/chrome/browser/ui/overlays/overlay_container_coordinator.h
@@ -0,0 +1,38 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_CONTAINER_COORDINATOR_H_ +#define IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_CONTAINER_COORDINATOR_H_ + +#import <UIKit/UIKit.h> + +#include "ios/chrome/browser/overlays/public/overlay_modality.h" +#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h" + +// Coordinator that manages displaying of UI for OverlayRequests. An instance +// of this coordinator should be created for each Browser at every +// OverlayModality. +@interface OverlayContainerCoordinator : ChromeCoordinator + +// Initializer for an overlay container that presents overlay for |browser| at +// |modality|. +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + browser:(Browser*)browser + modality:(OverlayModality)modality + NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + browserState: + (ios::ChromeBrowserState*)browserState + NS_UNAVAILABLE; +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + browser:(Browser*)browser NS_UNAVAILABLE; + +// The view controller whose presentation context is used to present overlays +// for the OverlayPresenter corresponding with the container's Browser and +// OverlayModality. +@property(nonatomic, readonly) UIViewController* viewController; + +@end + +#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_CONTAINER_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/overlays/overlay_container_coordinator.mm b/ios/chrome/browser/ui/overlays/overlay_container_coordinator.mm new file mode 100644 index 0000000..e3695f5 --- /dev/null +++ b/ios/chrome/browser/ui/overlays/overlay_container_coordinator.mm
@@ -0,0 +1,89 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/overlays/overlay_container_coordinator.h" + +#include <map> +#include <memory> + +#include "base/logging.h" +#import "ios/chrome/browser/main/browser.h" +#import "ios/chrome/browser/ui/overlays/overlay_container_view_controller.h" +#import "ios/chrome/browser/ui/overlays/overlay_presenter_ui_delegate_impl.h" +#import "ios/chrome/common/ui_util/constraints_ui_util.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface OverlayContainerCoordinator () < + OverlayContainerViewControllerDelegate> +// Whether the coordinator is started. +@property(nonatomic, assign, getter=isStarted) BOOL started; +// The UI delegate that is used to drive presentation for this container. +@property(nonatomic, readonly) OverlayPresenterUIDelegateImpl* UIDelegate; +@end + +@implementation OverlayContainerCoordinator + +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + browser:(Browser*)browser + modality:(OverlayModality)modality { + if (self = [super initWithBaseViewController:viewController + browser:browser]) { + OverlayPresenterUIDelegateImpl::Container::CreateForUserData(browser, + browser); + _UIDelegate = + OverlayPresenterUIDelegateImpl::Container::FromUserData(browser) + ->UIDelegateForModality(modality); + DCHECK(_UIDelegate); + } + return self; +} + +#pragma mark - ChromeCoordinator + +- (void)start { + if (self.started) + return; + self.started = YES; + // Create the container view controller and add it to the base view + // controller. + OverlayContainerViewController* viewController = + [[OverlayContainerViewController alloc] init]; + viewController.definesPresentationContext = YES; + viewController.delegate = self; + _viewController = viewController; + UIView* containerView = _viewController.view; + containerView.translatesAutoresizingMaskIntoConstraints = NO; + [self.baseViewController addChildViewController:_viewController]; + [self.baseViewController.view addSubview:containerView]; + AddSameConstraints(containerView, self.baseViewController.view); + [_viewController didMoveToParentViewController:self.baseViewController]; +} + +- (void)stop { + if (!self.started) + return; + self.started = NO; + self.UIDelegate->SetCoordinator(nil); + // Remove the container view and reset the view controller. + [_viewController willMoveToParentViewController:nil]; + [_viewController.view removeFromSuperview]; + [_viewController removeFromParentViewController]; + _viewController = nil; +} + +#pragma mark - OverlayContainerViewControllerDelegate + +- (void)containerViewController: + (OverlayContainerViewController*)containerViewController + didMoveToWindow:(UIWindow*)window { + // UIViewController presentation no-ops when attempted on window-less parent + // view controllers. Wait to set UI delegate's coordinator until the + // container is added to a window. + self.UIDelegate->SetCoordinator(window ? self : nil); +} + +@end
diff --git a/ios/chrome/browser/ui/overlays/overlay_container_view_controller.h b/ios/chrome/browser/ui/overlays/overlay_container_view_controller.h new file mode 100644 index 0000000..cf1ee12a --- /dev/null +++ b/ios/chrome/browser/ui/overlays/overlay_container_view_controller.h
@@ -0,0 +1,29 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_CONTAINER_VIEW_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_CONTAINER_VIEW_CONTROLLER_H_ + +#import <UIKit/UIKit.h> + +@protocol OverlayContainerViewControllerDelegate; + +// View controller used to show overlay UI. +@interface OverlayContainerViewController : UIViewController +@property(nonatomic, weak) id<OverlayContainerViewControllerDelegate> delegate; +@end + +// Delegate protocol for the container view. +@protocol OverlayContainerViewControllerDelegate <NSObject> + +// Called when |containerViewController|'s view moves to a new window. Overlay +// presentation should not be attempted until the container is added to +// a window. +- (void)containerViewController: + (OverlayContainerViewController*)containerViewController + didMoveToWindow:(UIWindow*)window; + +@end + +#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_CONTAINER_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/overlays/overlay_container_view_controller.mm b/ios/chrome/browser/ui/overlays/overlay_container_view_controller.mm new file mode 100644 index 0000000..75ab844 --- /dev/null +++ b/ios/chrome/browser/ui/overlays/overlay_container_view_controller.mm
@@ -0,0 +1,41 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/overlays/overlay_container_view_controller.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface OverlayContainerView : UIView +// The owning view controller. +@property(nonatomic, weak) OverlayContainerViewController* viewController; +@end + +@implementation OverlayContainerView + +- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event { + // Allow touches to go to subviews, but ignore touches that are routed to the + // container view itself. + UIView* hitView = [super hitTest:point withEvent:event]; + return hitView == self ? nil : hitView; +} + +- (void)didMoveToWindow { + [super didMoveToWindow]; + [self.viewController.delegate containerViewController:self.viewController + didMoveToWindow:self.window]; +} + +@end + +@implementation OverlayContainerViewController + +- (void)loadView { + OverlayContainerView* containerView = [[OverlayContainerView alloc] init]; + containerView.viewController = self; + self.view = containerView; +} + +@end
diff --git a/ios/chrome/browser/ui/overlays/overlay_coordinator_factory.h b/ios/chrome/browser/ui/overlays/overlay_coordinator_factory.h new file mode 100644 index 0000000..ccc7285 --- /dev/null +++ b/ios/chrome/browser/ui/overlays/overlay_coordinator_factory.h
@@ -0,0 +1,37 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_COORDINATOR_FACTORY_H_ +#define IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_COORDINATOR_FACTORY_H_ + +#import <UIKit/UIKit.h> + +#include "ios/chrome/browser/overlays/public/overlay_modality.h" + +class Browser; +class OverlayUIDismissalDelegate; +@class OverlayRequestCoordinator; +class OverlayRequest; + +// Factory object provided to OverlayContainerCoordinators that supply overlay +// coordinators for a request. +@interface OverlayRequestCoordinatorFactory : NSObject + +// Returns a coordinator factory for |browser| at |modality|. ++ (instancetype)factoryForBrowser:(Browser*)browser + modality:(OverlayModality)modality; + +// OverlayRequestCoordinatorFactory must be fetched using +// |+factoryForBrowser:modality:|. +- (instancetype)init NS_UNAVAILABLE; + +// Creates a coordinator to show |request|'s overlay UI. +- (OverlayRequestCoordinator*) + newCoordinatorForRequest:(OverlayRequest*)request + dismissalDelegate:(OverlayUIDismissalDelegate*)dismissalDelegate + baseViewController:(UIViewController*)baseViewController; + +@end + +#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_COORDINATOR_FACTORY_H_
diff --git a/ios/chrome/browser/ui/overlays/overlay_coordinator_factory.mm b/ios/chrome/browser/ui/overlays/overlay_coordinator_factory.mm new file mode 100644 index 0000000..6014c1c --- /dev/null +++ b/ios/chrome/browser/ui/overlays/overlay_coordinator_factory.mm
@@ -0,0 +1,73 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/overlays/overlay_coordinator_factory.h" + +#include "base/logging.h" +#import "ios/chrome/browser/ui/overlays/overlay_request_coordinator.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface OverlayRequestCoordinatorFactory () +// The Browser passed on initialization. +@property(nonatomic, readonly) Browser* browser; +// The OverlayRequestCoordinator subclasses that are supported at the modality +// associated with this coordinator factory. +@property(nonatomic, readonly) + NSArray<Class>* supportedOverlayRequestCoordinatorClasses; +// Initializer used by |+factoryForBrowser:modality:|. +- (instancetype)initWithBrowser:(Browser*)browser + supportedOverlayRequestCoordinatorClasses: + (NSArray<Class>*)supportedOverlayClasses NS_DESIGNATED_INITIALIZER; +@end + +@implementation OverlayRequestCoordinatorFactory + ++ (instancetype)factoryForBrowser:(Browser*)browser + modality:(OverlayModality)modality { + DCHECK(browser); + NSArray<Class>* supportedCoordinatorClasses = @[]; + switch (modality) { + case OverlayModality::kWebContentArea: + // TODO(crbug.com/941745): Reset |supportedCoordinatorClasses| to contain + // OverlayRequestCoordinator classes once implemented. + break; + } + return [[self alloc] initWithBrowser:browser + supportedOverlayRequestCoordinatorClasses:supportedCoordinatorClasses]; +} + +- (instancetype)initWithBrowser:(Browser*)browser + supportedOverlayRequestCoordinatorClasses: + (NSArray<Class>*)supportedOverlayClasses { + if (self = [super init]) { + _browser = browser; + DCHECK(_browser); + _supportedOverlayRequestCoordinatorClasses = supportedOverlayClasses; + DCHECK(_supportedOverlayRequestCoordinatorClasses.count); + } + return self; +} + +- (OverlayRequestCoordinator*) + newCoordinatorForRequest:(OverlayRequest*)request + dismissalDelegate:(OverlayUIDismissalDelegate*)dismissalDelegate + baseViewController:(UIViewController*)baseViewController { + for (Class coordinatorClass in self + .supportedOverlayRequestCoordinatorClasses) { + if ([coordinatorClass supportsRequest:request]) { + return [[coordinatorClass alloc] + initWithBaseViewController:baseViewController + browser:self.browser + request:request + dismissalDelegate:dismissalDelegate]; + } + } + NOTREACHED() << "Received unsupported request type."; + return nil; +} + +@end
diff --git a/ios/chrome/browser/ui/overlays/overlay_presenter_ui_delegate_impl.h b/ios/chrome/browser/ui/overlays/overlay_presenter_ui_delegate_impl.h new file mode 100644 index 0000000..f73ce9b --- /dev/null +++ b/ios/chrome/browser/ui/overlays/overlay_presenter_ui_delegate_impl.h
@@ -0,0 +1,137 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_PRESENTER_UI_DELEGATE_IMPL_H_ +#define IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_PRESENTER_UI_DELEGATE_IMPL_H_ + +#include "base/memory/weak_ptr.h" +#import "ios/chrome/browser/main/browser_observer.h" +#import "ios/chrome/browser/overlays/public/overlay_presenter.h" +#import "ios/chrome/browser/overlays/public/overlay_user_data.h" +#import "ios/chrome/browser/ui/overlays/overlay_request_coordinator.h" +#import "ios/chrome/browser/ui/overlays/overlay_request_ui_state.h" +#import "ios/chrome/browser/ui/overlays/overlay_ui_dismissal_delegate.h" + +@class OverlayRequestCoordinatorFactory; +@class OverlayContainerCoordinator; + +// Implementation of OverlayPresenter::UIDelegate. An instance of this class +// exists for every OverlayModality for each Browser. This delegate is scoped +// to the Browser because it needs to store state even when a Browser's UI is +// not on screen. When a Browser's UI is shown, the OverlayContainerCoordinator +// for each of its OverlayModalities will supply itself to the delegate, which +// will then present the UI using the container coordinator's presentation +// context. +class OverlayPresenterUIDelegateImpl : public OverlayPresenter::UIDelegate { + public: + ~OverlayPresenterUIDelegateImpl() override; + + // Container that stores the UI delegate for each modality. Usage example: + // + // OverlayPresenterUIDelegateImpl::Container::FromUserData(browser)-> + // UIDelegateForModality(OverlayModality::kWebContentArea); + class Container : public OverlayUserData<Container> { + public: + ~Container() override; + + // Returns the OverlayPresenterUIDelegateImpl for |modality|. + OverlayPresenterUIDelegateImpl* UIDelegateForModality( + OverlayModality modality); + + private: + OVERLAY_USER_DATA_SETUP(Container); + explicit Container(Browser* browser); + + Browser* browser_ = nullptr; + std::map<OverlayModality, std::unique_ptr<OverlayPresenterUIDelegateImpl>> + ui_delegates_; + }; + + // The OverlayContainerCoordinator is used to present the overlay UI at the + // correct modality in the app. Should only be set when the coordinator's + // presentation context is able to present. + OverlayContainerCoordinator* coordinator() const { return coordinator_; } + void SetCoordinator(OverlayContainerCoordinator* coordinator); + + // OverlayPresenter::UIDelegate: + void ShowOverlayUI(OverlayPresenter* presenter, + OverlayRequest* request, + OverlayDismissalCallback dismissal_callback) override; + void HideOverlayUI(OverlayPresenter* presenter, + OverlayRequest* request) override; + void CancelOverlayUI(OverlayPresenter* presenter, + OverlayRequest* request) override; + + private: + OverlayPresenterUIDelegateImpl(Browser* browser, OverlayModality modality); + + // Setter for |request_|. Setting to a new value will attempt to + // present the UI for |request|. + void SetRequest(OverlayRequest* request); + + // Returns the UI state for |request|. + OverlayRequestUIState* GetRequestUIState(OverlayRequest* request); + + // Shows the UI for the presented request using the container coordinator. + void ShowUIForPresentedRequest(); + + // Dismisses the UI for the presented request for |reason|. + void DismissPresentedUI(OverlayDismissalReason reason); + + // Called when the UI for |request_| has finished being dismissed. + void OverlayUIWasDismissed(); + + // Notifies the state for |request_| that its UI has finished being dismissed. + void NotifyStateOfDismissal(); + + // Helper object that detaches the UI delegate for Browser shudown. + class BrowserShutdownHelper : public BrowserObserver { + public: + BrowserShutdownHelper(Browser* browser, OverlayPresenter* presenter); + ~BrowserShutdownHelper() override; + + // BrowserObserver: + void BrowserDestroyed(Browser* browser) override; + + private: + // The presenter whose delegate needs to be reset. + OverlayPresenter* presenter_ = nullptr; + }; + + // Helper object that listens for UI dismissal events. + class OverlayDismissalHelper : public OverlayUIDismissalDelegate { + public: + OverlayDismissalHelper(OverlayPresenterUIDelegateImpl* ui_delegate); + ~OverlayDismissalHelper() override; + + // OverlayUIDismissalDelegate: + void OverlayUIDidFinishDismissal(OverlayRequest* request) override; + + private: + OverlayPresenterUIDelegateImpl* ui_delegate_ = nullptr; + }; + + // The presenter whose UI is being handled by this delegate. + OverlayPresenter* presenter_ = nullptr; + // The cleanup helper. + BrowserShutdownHelper shutdown_helper_; + // The UI dismissal helper. + OverlayDismissalHelper ui_dismissal_helper_; + // The coordinator factory that provides the UI for the overlays at this + // modality. + OverlayRequestCoordinatorFactory* coordinator_factory_ = nil; + // The coordinator responsible for presenting the UI delegate's UI. + OverlayContainerCoordinator* coordinator_ = nil; + // The request that is currently presented by |presenter_|. The UI for this + // request might not yet be visible if no OverlayContainerCoordinator has been + // provided. When a new request is presented, the UI state for the request + // will be added to |states_|. + OverlayRequest* request_ = nullptr; + // Map storing the UI state for each OverlayRequest. + std::map<OverlayRequest*, std::unique_ptr<OverlayRequestUIState>> states_; + // Weak pointer factory. + base::WeakPtrFactory<OverlayPresenterUIDelegateImpl> weak_factory_; +}; + +#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_PRESENTER_UI_DELEGATE_IMPL_H_
diff --git a/ios/chrome/browser/ui/overlays/overlay_presenter_ui_delegate_impl.mm b/ios/chrome/browser/ui/overlays/overlay_presenter_ui_delegate_impl.mm new file mode 100644 index 0000000..db08334 --- /dev/null +++ b/ios/chrome/browser/ui/overlays/overlay_presenter_ui_delegate_impl.mm
@@ -0,0 +1,256 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/overlays/overlay_presenter_ui_delegate_impl.h" + +#include "base/bind.h" +#include "base/callback.h" +#import "ios/chrome/browser/main/browser.h" +#import "ios/chrome/browser/ui/overlays/overlay_container_coordinator.h" +#import "ios/chrome/browser/ui/overlays/overlay_coordinator_factory.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +#pragma mark - OverlayPresenterUIDelegateImpl::Container + +OVERLAY_USER_DATA_SETUP_IMPL(OverlayPresenterUIDelegateImpl::Container); + +OverlayPresenterUIDelegateImpl::Container::Container(Browser* browser) + : browser_(browser) { + DCHECK(browser_); +} + +OverlayPresenterUIDelegateImpl::Container::~Container() = default; + +OverlayPresenterUIDelegateImpl* +OverlayPresenterUIDelegateImpl::Container::UIDelegateForModality( + OverlayModality modality) { + auto& ui_delegate = ui_delegates_[modality]; + if (!ui_delegate) { + ui_delegate = base::WrapUnique( + new OverlayPresenterUIDelegateImpl(browser_, modality)); + } + return ui_delegate.get(); +} + +#pragma mark - OverlayPresenterUIDelegateImpl + +OverlayPresenterUIDelegateImpl::OverlayPresenterUIDelegateImpl( + Browser* browser, + OverlayModality modality) + : presenter_(OverlayPresenter::FromBrowser(browser, modality)), + shutdown_helper_(browser, presenter_), + ui_dismissal_helper_(this), + coordinator_factory_([OverlayRequestCoordinatorFactory + factoryForBrowser:browser + modality:modality]), + weak_factory_(this) { + DCHECK(presenter_); + DCHECK(coordinator_factory_); + presenter_->SetUIDelegate(this); +} + +OverlayPresenterUIDelegateImpl::~OverlayPresenterUIDelegateImpl() = default; + +#pragma mark Public + +void OverlayPresenterUIDelegateImpl::SetCoordinator( + OverlayContainerCoordinator* coordinator) { + if (coordinator_ == coordinator) + return; + if (coordinator_ && request_) + DismissPresentedUI(OverlayDismissalReason::kHiding); + + coordinator_ = coordinator; + + // The new coordinator should be started before provided to the UI delegate. + DCHECK(!coordinator_ || coordinator_.viewController); + + ShowUIForPresentedRequest(); +} + +#pragma mark OverlayPresenter::UIDelegate + +void OverlayPresenterUIDelegateImpl::ShowOverlayUI( + OverlayPresenter* presenter, + OverlayRequest* request, + OverlayDismissalCallback dismissal_callback) { + DCHECK_EQ(presenter_, presenter); + // Create the UI state for |request| if necessary. + if (!GetRequestUIState(request)) + states_[request] = std::make_unique<OverlayRequestUIState>(request); + // Present the overlay UI and update the UI state. + GetRequestUIState(request)->OverlayPresentionRequested( + std::move(dismissal_callback)); + SetRequest(request); +} + +void OverlayPresenterUIDelegateImpl::HideOverlayUI(OverlayPresenter* presenter, + OverlayRequest* request) { + DCHECK_EQ(presenter_, presenter); + DCHECK_EQ(request_, request); + + OverlayRequestUIState* state = GetRequestUIState(request_); + DCHECK(state->has_callback()); + + if (coordinator_) { + // If the request's UI is presented by the coordinator, dismiss it. The + // presented request will be reset when the dismissal animation finishes. + DismissPresentedUI(OverlayDismissalReason::kHiding); + } else { + // Simulate dismissal if there is no container coordinator. + state->set_dismissal_reason(OverlayDismissalReason::kHiding); + NotifyStateOfDismissal(); + } +} + +void OverlayPresenterUIDelegateImpl::CancelOverlayUI( + OverlayPresenter* presenter, + OverlayRequest* request) { + DCHECK_EQ(presenter_, presenter); + // If the coordinator is not presenting the overlay UI for |state|, it can + // be deleted immediately. + OverlayRequestUIState* state = GetRequestUIState(request); + DCHECK(state); + if (!state->has_callback() || !coordinator_) { + states_.erase(request); + return; + } + + DismissPresentedUI(OverlayDismissalReason::kCancellation); +} + +#pragma mark Accesors + +void OverlayPresenterUIDelegateImpl::SetRequest(OverlayRequest* request) { + if (request_ == request) + return; + if (request_) { + OverlayRequestUIState* state = GetRequestUIState(request_); + // The presented request should only be reset when the previously presented + // request's UI has finished being dismissed. + DCHECK(state); + DCHECK(!state->has_callback()); + DCHECK(!state->coordinator().viewController.view.superview); + // If the overlay was dismissed for user interaction or cancellation, then + // the state can be destroyed, since the UI for the previously presented + // request will never be shown again. + OverlayDismissalReason reason = state->dismissal_reason(); + if (reason == OverlayDismissalReason::kUserInteraction || + reason == OverlayDismissalReason::kCancellation) { + states_.erase(request_); + } + } + + request_ = request; + + // The UI state should be created before resetting the presented request. + DCHECK(!request_ || GetRequestUIState(request_)); + + ShowUIForPresentedRequest(); +} + +OverlayRequestUIState* OverlayPresenterUIDelegateImpl::GetRequestUIState( + OverlayRequest* request) { + return request ? states_[request].get() : nullptr; +} + +#pragma mark Presentation and Dismissal helpers + +void OverlayPresenterUIDelegateImpl::ShowUIForPresentedRequest() { + OverlayRequestUIState* state = GetRequestUIState(request_); + if (!state || !coordinator_) + return; + + // Create the coordinator if necessary. + UIViewController* container_view_controller = coordinator_.viewController; + OverlayRequestCoordinator* overlay_coordinator = state->coordinator(); + if (!overlay_coordinator || + overlay_coordinator.baseViewController != container_view_controller) { + overlay_coordinator = [coordinator_factory_ + newCoordinatorForRequest:request_ + dismissalDelegate:&ui_dismissal_helper_ + baseViewController:container_view_controller]; + state->OverlayUIWillBePresented(overlay_coordinator); + } + + [overlay_coordinator startAnimated:!state->has_ui_been_presented()]; + state->OverlayUIWasPresented(); +} + +void OverlayPresenterUIDelegateImpl::DismissPresentedUI( + OverlayDismissalReason reason) { + OverlayRequestUIState* state = GetRequestUIState(request_); + DCHECK(state); + DCHECK(coordinator_); + DCHECK(state->coordinator()); + + state->set_dismissal_reason(reason); + [state->coordinator() + stopAnimated:reason == OverlayDismissalReason::kUserInteraction]; +} + +void OverlayPresenterUIDelegateImpl::OverlayUIWasDismissed() { + DCHECK(request_); + // Overlays are dismissed without animation when the container coordinator is + // reset, but the state should not be notified of these dismissals since the + // same UI will be presented again once a new container coordinator is + // provided. + if (!coordinator_) + return; + NotifyStateOfDismissal(); +} + +void OverlayPresenterUIDelegateImpl::NotifyStateOfDismissal() { + DCHECK(request_); + DCHECK(GetRequestUIState(request_)->has_callback()); + // If there is another request in the active WebState's OverlayRequestQueue, + // executing the state's dismissal callback will trigger the presentation of + // the next request. If the presented request remains unchanged after calling + // the dismissal callback, reset it to nullptr since the UI is no longer + // presented. + OverlayRequest* previously_presented_request = request_; + GetRequestUIState(request_)->OverlayUIWasDismissed(); + if (request_ == previously_presented_request) + SetRequest(nullptr); +} + +#pragma mark BrowserShutdownHelper + +OverlayPresenterUIDelegateImpl::BrowserShutdownHelper::BrowserShutdownHelper( + Browser* browser, + OverlayPresenter* presenter) + : presenter_(presenter) { + DCHECK(presenter_); + browser->AddObserver(this); +} + +OverlayPresenterUIDelegateImpl::BrowserShutdownHelper:: + ~BrowserShutdownHelper() = default; + +void OverlayPresenterUIDelegateImpl::BrowserShutdownHelper::BrowserDestroyed( + Browser* browser) { + presenter_->SetUIDelegate(nullptr); + browser->RemoveObserver(this); +} + +#pragma mark OverlayDismissalHelper + +OverlayPresenterUIDelegateImpl::OverlayDismissalHelper::OverlayDismissalHelper( + OverlayPresenterUIDelegateImpl* ui_delegate) + : ui_delegate_(ui_delegate) { + DCHECK(ui_delegate_); +} + +OverlayPresenterUIDelegateImpl::OverlayDismissalHelper:: + ~OverlayDismissalHelper() = default; + +void OverlayPresenterUIDelegateImpl::OverlayDismissalHelper:: + OverlayUIDidFinishDismissal(OverlayRequest* request) { + DCHECK(request); + DCHECK_EQ(ui_delegate_->request_, request); + ui_delegate_->OverlayUIWasDismissed(); +}
diff --git a/ios/chrome/browser/ui/overlays/overlay_request_coordinator.h b/ios/chrome/browser/ui/overlays/overlay_request_coordinator.h new file mode 100644 index 0000000..02bd7f34 --- /dev/null +++ b/ios/chrome/browser/ui/overlays/overlay_request_coordinator.h
@@ -0,0 +1,54 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_REQUEST_COORDINATOR_H_ +#define IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_REQUEST_COORDINATOR_H_ + +#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h" + +class OverlayUIDismissalDelegate; +class OverlayRequest; + +// Coordinator superclass used to present UI for an OverlayRequest. +@interface OverlayRequestCoordinator : ChromeCoordinator + +// Returns whether this overlay coordinator type supports |request|. ++ (BOOL)supportsRequest:(OverlayRequest*)request; + +// Initializer for a coordinator for |request|. +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + browser:(Browser*)browser + request:(OverlayRequest*)request + dismissalDelegate: + (OverlayUIDismissalDelegate*)dismissalDelegate + NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + browserState: + (ios::ChromeBrowserState*)browserState + NS_UNAVAILABLE; +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + browser:(Browser*)browser NS_UNAVAILABLE; + +// The OverlayUIDismissalDelegate passed on initialization. Used to communicate +// when the overlay UI is finished being dismissed, which may occur after +// |-stop| even if the overlay is stopped without animation. This notifies +// OverlayPresenter that the presentation context is clear to show the next +// requested overlay. +@property(nonatomic, readonly) OverlayUIDismissalDelegate* dismissalDelegate; + +// The request used to configure the overlay UI. +@property(nonatomic, readonly) OverlayRequest* request; + +// The view controller that displays the UI for |request|. +@property(nonatomic, readonly) UIViewController* viewController; + +// OverlayRequestCoordinator's |-start| and |-stop| need to support versions +// both with and without animation, as hidden overlays should be shown without +// animation for subsequent presentations. +- (void)startAnimated:(BOOL)animated; +- (void)stopAnimated:(BOOL)animated; + +@end + +#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_REQUEST_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/overlays/overlay_request_coordinator.mm b/ios/chrome/browser/ui/overlays/overlay_request_coordinator.mm new file mode 100644 index 0000000..0bde829 --- /dev/null +++ b/ios/chrome/browser/ui/overlays/overlay_request_coordinator.mm
@@ -0,0 +1,56 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/overlays/overlay_request_coordinator.h" + +#include "base/logging.h" +#import "ios/chrome/browser/ui/overlays/overlay_ui_dismissal_delegate.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@implementation OverlayRequestCoordinator + ++ (BOOL)supportsRequest:(OverlayRequest*)request { + return NO; +} + +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + browser:(Browser*)browser + request:(OverlayRequest*)request + dismissalDelegate: + (OverlayUIDismissalDelegate*)dismissalDelegate { + DCHECK([[self class] supportsRequest:request]); + self = [super initWithBaseViewController:viewController browser:browser]; + if (self) { + _request = request; + DCHECK(_request); + _dismissalDelegate = dismissalDelegate; + DCHECK(_dismissalDelegate); + } + return self; +} + +#pragma mark - Public + +- (void)startAnimated:(BOOL)animated { + NOTREACHED() << "Subclasses must implement."; +} + +- (void)stopAnimated:(BOOL)animated { + NOTREACHED() << "Subclasses must implement."; +} + +#pragma mark - ChromeCoordinator + +- (void)start { + [self startAnimated:YES]; +} + +- (void)stop { + [self stopAnimated:YES]; +} + +@end
diff --git a/ios/chrome/browser/ui/overlays/overlay_request_ui_state.h b/ios/chrome/browser/ui/overlays/overlay_request_ui_state.h new file mode 100644 index 0000000..1e4a2a8 --- /dev/null +++ b/ios/chrome/browser/ui/overlays/overlay_request_ui_state.h
@@ -0,0 +1,56 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_REQUEST_UI_STATE_H_ +#define IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_REQUEST_UI_STATE_H_ + +#import <Foundation/Foundation.h> + +#include "ios/chrome/browser/overlays/public/overlay_dismissal_callback.h" + +@class OverlayRequestCoordinator; +class OverlayRequest; + +// Container holding information about the state of overlay UI for a given +// request. +class OverlayRequestUIState { + public: + explicit OverlayRequestUIState(OverlayRequest* request); + ~OverlayRequestUIState(); + + // Called when the OverlayPresenter requests the presentation of |request_|. + // This may or may not correspond with an OverlayUIWasPresented() if the + // hierarchy is not ready for presentation (i.e. overlay presentation for a + // Browser whose UI is not currently on-screen). + void OverlayPresentionRequested(OverlayDismissalCallback callback); + + // Notifies the state that the UI is about to be presented using + // |coordinator|. + void OverlayUIWillBePresented(OverlayRequestCoordinator* coordinator); + + // Notifies the state that the UI was presented. + void OverlayUIWasPresented(); + + // Notifies the state the the UI was dismissed. + void OverlayUIWasDismissed(); + + // Accessors. + OverlayRequestCoordinator* coordinator() const { return coordinator_; } + bool has_ui_been_presented() const { return has_ui_been_presented_; } + bool has_callback() const { return !dismissal_callback_.is_null(); } + OverlayDismissalReason dismissal_reason() const { return dismissal_reason_; } + void set_dismissal_reason(OverlayDismissalReason dismissal_reason) { + dismissal_reason_ = dismissal_reason; + } + + private: + OverlayRequest* request_ = nullptr; + OverlayRequestCoordinator* coordinator_ = nil; + bool has_ui_been_presented_ = false; + OverlayDismissalReason dismissal_reason_ = + OverlayDismissalReason::kUserInteraction; + OverlayDismissalCallback dismissal_callback_; +}; + +#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_REQUEST_UI_STATE_H_
diff --git a/ios/chrome/browser/ui/overlays/overlay_request_ui_state.mm b/ios/chrome/browser/ui/overlays/overlay_request_ui_state.mm new file mode 100644 index 0000000..5073250 --- /dev/null +++ b/ios/chrome/browser/ui/overlays/overlay_request_ui_state.mm
@@ -0,0 +1,49 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/overlays/overlay_request_ui_state.h" + +#import "ios/chrome/browser/ui/overlays/overlay_request_coordinator.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +OverlayRequestUIState::OverlayRequestUIState(OverlayRequest* request) + : request_(request) { + DCHECK(request_); +} + +OverlayRequestUIState::~OverlayRequestUIState() { + if (has_callback()) { + set_dismissal_reason(OverlayDismissalReason::kCancellation); + OverlayUIWasDismissed(); + } +} + +void OverlayRequestUIState::OverlayPresentionRequested( + OverlayDismissalCallback callback) { + DCHECK(dismissal_callback_.is_null()); + dismissal_callback_ = std::move(callback); + // The default dismissal reason is kUserInteraction. This is to avoid + // additional bookkeeping for overlays dismissed by user interaction. + // Overlays explicitly dismissed by OverlayPresenter set the reason to kHide + // or kCancellation before dismissal. + dismissal_reason_ = OverlayDismissalReason::kUserInteraction; +} + +void OverlayRequestUIState::OverlayUIWillBePresented( + OverlayRequestCoordinator* coordinator) { + DCHECK(coordinator); + coordinator_ = coordinator; +} + +void OverlayRequestUIState::OverlayUIWasPresented() { + has_ui_been_presented_ = true; +} + +void OverlayRequestUIState::OverlayUIWasDismissed() { + DCHECK(has_callback()); + std::move(dismissal_callback_).Run(dismissal_reason_); +}
diff --git a/ios/chrome/browser/ui/overlays/overlay_request_ui_state_unittest.mm b/ios/chrome/browser/ui/overlays/overlay_request_ui_state_unittest.mm new file mode 100644 index 0000000..cbc9a1c --- /dev/null +++ b/ios/chrome/browser/ui/overlays/overlay_request_ui_state_unittest.mm
@@ -0,0 +1,85 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/overlays/overlay_request_ui_state.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "base/callback_helpers.h" +#include "ios/chrome/browser/overlays/public/overlay_request.h" +#include "ios/chrome/browser/overlays/test/fake_overlay_user_data.h" +#import "ios/chrome/browser/ui/overlays/test/fake_overlay_request_coordinator.h" +#include "ios/chrome/browser/ui/overlays/test/fake_overlay_ui_dismissal_delegate.h" +#include "testing/platform_test.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +// Test fixture for OverlayRequestUIState. +class OverlayRequestUIStateTest : public PlatformTest { + public: + OverlayRequestUIStateTest() + : PlatformTest(), + request_( + OverlayRequest::CreateWithConfig<FakeOverlayUserData>(nullptr)), + state_(request_.get()) {} + + OverlayRequest* request() { return request_.get(); } + OverlayRequestUIState& state() { return state_; } + + private: + std::unique_ptr<OverlayRequest> request_; + OverlayRequestUIState state_; +}; + +// Tests that OverlayPresentionRequested() passes the callback to the state and +// resets the default dismissal reason to kUserInteraction. +TEST_F(OverlayRequestUIStateTest, OverlayPresentionRequested) { + ASSERT_FALSE(state().has_callback()); + state().OverlayPresentionRequested(base::BindOnce(^(OverlayDismissalReason){ + })); + EXPECT_TRUE(state().has_callback()); + EXPECT_EQ(OverlayDismissalReason::kUserInteraction, + state().dismissal_reason()); +} + +// Tests that OverlayUIWillBePresented() stores the coordinator in the state. +TEST_F(OverlayRequestUIStateTest, OverlayUIWillBePresented) { + FakeDismissalDelegate dismissal_delegate; + FakeOverlayRequestCoordinator* coordinator = + [[FakeOverlayRequestCoordinator alloc] + initWithBaseViewController:nil + browser:nullptr + request:request() + dismissalDelegate:&dismissal_delegate]; + state().OverlayUIWillBePresented(coordinator); + EXPECT_EQ(coordinator, state().coordinator()); +} + +// Tests that OverlayUIWasPresented() correctly updates has_ui_been_presented(). +TEST_F(OverlayRequestUIStateTest, OverlayUIWasPresented) { + ASSERT_FALSE(state().has_ui_been_presented()); + state().OverlayUIWasPresented(); + EXPECT_TRUE(state().has_ui_been_presented()); +} + +// Tests that OverlayUIWasDismissed() executes the dismissal callback. +TEST_F(OverlayRequestUIStateTest, OverlayUIWasDismissed) { + __block bool dismissal_callback_executed = false; + state().OverlayPresentionRequested(base::BindOnce(^(OverlayDismissalReason) { + dismissal_callback_executed = true; + })); + FakeDismissalDelegate dismissal_delegate; + FakeOverlayRequestCoordinator* coordinator = + [[FakeOverlayRequestCoordinator alloc] + initWithBaseViewController:nil + browser:nullptr + request:request() + dismissalDelegate:&dismissal_delegate]; + state().OverlayUIWillBePresented(coordinator); + state().OverlayUIWasPresented(); + state().OverlayUIWasDismissed(); + EXPECT_TRUE(dismissal_callback_executed); +}
diff --git a/ios/chrome/browser/ui/overlays/overlay_ui_dismissal_delegate.h b/ios/chrome/browser/ui/overlays/overlay_ui_dismissal_delegate.h new file mode 100644 index 0000000..ad84fa3 --- /dev/null +++ b/ios/chrome/browser/ui/overlays/overlay_ui_dismissal_delegate.h
@@ -0,0 +1,21 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_UI_DISMISSAL_DELEGATE_H_ +#define IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_UI_DISMISSAL_DELEGATE_H_ + +class OverlayRequest; + +// Delegate class used to communicate dismissal events back to OverlayPresenter. +class OverlayUIDismissalDelegate { + public: + OverlayUIDismissalDelegate() = default; + virtual ~OverlayUIDismissalDelegate() = default; + + // Called to notify the delegate that the UI for |request|'s UI is finished + // being dismissed. + virtual void OverlayUIDidFinishDismissal(OverlayRequest* request) = 0; +}; + +#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_UI_DISMISSAL_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/overlays/test/BUILD.gn b/ios/chrome/browser/ui/overlays/test/BUILD.gn new file mode 100644 index 0000000..d5c019f5 --- /dev/null +++ b/ios/chrome/browser/ui/overlays/test/BUILD.gn
@@ -0,0 +1,21 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("test") { + testonly = true + sources = [ + "fake_overlay_request_coordinator.h", + "fake_overlay_request_coordinator.mm", + "fake_overlay_ui_dismissal_delegate.cc", + "fake_overlay_ui_dismissal_delegate.h", + ] + + configs += [ "//build/config/compiler:enable_arc" ] + + deps = [ + "//base", + "//ios/chrome/browser/ui/overlays:coordinators", + "//testing/gtest", + ] +}
diff --git a/ios/chrome/browser/ui/overlays/test/fake_overlay_request_coordinator.h b/ios/chrome/browser/ui/overlays/test/fake_overlay_request_coordinator.h new file mode 100644 index 0000000..4ba13b5 --- /dev/null +++ b/ios/chrome/browser/ui/overlays/test/fake_overlay_request_coordinator.h
@@ -0,0 +1,14 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_OVERLAYS_TEST_FAKE_OVERLAY_REQUEST_COORDINATOR_H_ +#define IOS_CHROME_BROWSER_UI_OVERLAYS_TEST_FAKE_OVERLAY_REQUEST_COORDINATOR_H_ + +#import "ios/chrome/browser/ui/overlays/overlay_request_coordinator.h" + +// Fake version of OverlayRequestCoordinator that supports all OverlayRequests. +@interface FakeOverlayRequestCoordinator : OverlayRequestCoordinator +@end + +#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_TEST_FAKE_OVERLAY_REQUEST_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/overlays/test/fake_overlay_request_coordinator.mm b/ios/chrome/browser/ui/overlays/test/fake_overlay_request_coordinator.mm new file mode 100644 index 0000000..9f7842d --- /dev/null +++ b/ios/chrome/browser/ui/overlays/test/fake_overlay_request_coordinator.mm
@@ -0,0 +1,23 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/overlays/test/fake_overlay_request_coordinator.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@implementation FakeOverlayRequestCoordinator + ++ (BOOL)supportsRequest:(OverlayRequest*)request { + return YES; +} + +- (void)startAnimated:(BOOL)animated { +} + +- (void)stopAnimated:(BOOL)animated { +} + +@end
diff --git a/ios/chrome/browser/ui/overlays/test/fake_overlay_ui_dismissal_delegate.cc b/ios/chrome/browser/ui/overlays/test/fake_overlay_ui_dismissal_delegate.cc new file mode 100644 index 0000000..88ee77f --- /dev/null +++ b/ios/chrome/browser/ui/overlays/test/fake_overlay_ui_dismissal_delegate.cc
@@ -0,0 +1,17 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/ui/overlays/test/fake_overlay_ui_dismissal_delegate.h" + +FakeDismissalDelegate::FakeDismissalDelegate() = default; +FakeDismissalDelegate::~FakeDismissalDelegate() = default; + +bool FakeDismissalDelegate::HasUIBeenDismissed(OverlayRequest* request) const { + return dismissed_requests_.find(request) != dismissed_requests_.end(); +} + +void FakeDismissalDelegate::OverlayUIDidFinishDismissal( + OverlayRequest* request) { + dismissed_requests_.insert(request); +}
diff --git a/ios/chrome/browser/ui/overlays/test/fake_overlay_ui_dismissal_delegate.h b/ios/chrome/browser/ui/overlays/test/fake_overlay_ui_dismissal_delegate.h new file mode 100644 index 0000000..0334c4c9 --- /dev/null +++ b/ios/chrome/browser/ui/overlays/test/fake_overlay_ui_dismissal_delegate.h
@@ -0,0 +1,28 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_OVERLAYS_TEST_FAKE_OVERLAY_UI_DISMISSAL_DELEGATE_H_ +#define IOS_CHROME_BROWSER_UI_OVERLAYS_TEST_FAKE_OVERLAY_UI_DISMISSAL_DELEGATE_H_ + +#import "ios/chrome/browser/ui/overlays/overlay_ui_dismissal_delegate.h" + +#include <set> + +// Fake implementation of OverlayUIDismissalDelegate. +class FakeDismissalDelegate : public OverlayUIDismissalDelegate { + public: + FakeDismissalDelegate(); + ~FakeDismissalDelegate() override; + + // Whether the overlay UI for |request| has been dismissed. + bool HasUIBeenDismissed(OverlayRequest* request) const; + + // OverlayUIDismissalDelegate: + void OverlayUIDidFinishDismissal(OverlayRequest* request) override; + + private: + std::set<OverlayRequest*> dismissed_requests_; +}; + +#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_TEST_FAKE_OVERLAY_UI_DISMISSAL_DELEGATE_H_
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn index 4d0ac98..f7d3439 100644 --- a/ios/chrome/test/BUILD.gn +++ b/ios/chrome/test/BUILD.gn
@@ -224,6 +224,7 @@ "//ios/chrome/browser/ui/omnibox:unit_tests", "//ios/chrome/browser/ui/omnibox/popup:unit_tests", "//ios/chrome/browser/ui/open_in:unit_tests", + "//ios/chrome/browser/ui/overlays:unit_tests", "//ios/chrome/browser/ui/payments:unit_tests", "//ios/chrome/browser/ui/payments/cells:unit_tests", "//ios/chrome/browser/ui/popup_menu:unit_tests",
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey.h b/ios/chrome/test/earl_grey/chrome_earl_grey.h index ba3d819..7e39db1 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey.h +++ b/ios/chrome/test/earl_grey/chrome_earl_grey.h
@@ -112,6 +112,15 @@ #pragma mark - Sync Utilities +// Clears fake sync server data. +- (void)clearSyncServerData; + +// Starts the sync server. The server should not be running when calling this. +- (void)startSync; + +// Stops the sync server. The server should be running when calling this. +- (void)stopSync; + // Clears the autofill profile for the given |GUID|. - (void)clearAutofillProfileWithGUID:(const std::string&)GUID; @@ -284,15 +293,6 @@ #pragma mark - Sync Utilities -// Clears fake sync server data. -- (void)clearSyncServerData; - -// Starts the sync server. The server should not be running when calling this. -- (void)startSync; - -// Stops the sync server. The server should be running when calling this. -- (void)stopSync; - // Verifies that |count| entities of the given |type| and |name| exist on the // sync FakeServer. Folders are not included in this count. Returns nil on // success, or else an NSError indicating why the operation failed.
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey.mm b/ios/chrome/test/earl_grey/chrome_earl_grey.mm index ee6c16d..bb9fa43 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey.mm +++ b/ios/chrome/test/earl_grey/chrome_earl_grey.mm
@@ -240,6 +240,18 @@ #pragma mark - Sync Utilities +- (void)clearSyncServerData { + [ChromeEarlGreyAppInterface clearSyncServerData]; +} + +- (void)startSync { + [ChromeEarlGreyAppInterface startSync]; +} + +- (void)stopSync { + [ChromeEarlGreyAppInterface stopSync]; +} + - (void)clearAutofillProfileWithGUID:(const std::string&)GUID { NSString* nsGUID = base::SysUTF8ToNSString(GUID); [ChromeEarlGreyAppInterface clearAutofillProfileWithGUID:nsGUID]; @@ -501,18 +513,6 @@ #pragma mark - Sync Utilities -- (void)clearSyncServerData { - chrome_test_util::ClearSyncServerData(); -} - -- (void)startSync { - chrome_test_util::StartSync(); -} - -- (void)stopSync { - chrome_test_util::StopSync(); -} - - (NSError*)waitForSyncServerEntitiesWithType:(syncer::ModelType)type name:(const std::string&)name count:(size_t)count
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h index 40bb71f..2f65ed4 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h +++ b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h
@@ -116,6 +116,15 @@ #pragma mark - Sync Utilities (EG2) +// Clears fake sync server data. ++ (void)clearSyncServerData; + +// Starts the sync server. The server should not be running when calling this. ++ (void)startSync; + +// Stops the sync server. The server should be running when calling this. ++ (void)stopSync; + // Waits for sync to be initialized or not. // Returns nil on success, or else an NSError indicating why the // operation failed.
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm index fc9a1c8..e63c1fc 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm +++ b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm
@@ -187,6 +187,18 @@ #pragma mark - Sync Utilities (EG2) ++ (void)clearSyncServerData { + chrome_test_util::ClearSyncServerData(); +} + ++ (void)startSync { + chrome_test_util::StartSync(); +} + ++ (void)stopSync { + chrome_test_util::StopSync(); +} + + (NSError*)waitForSyncInitialized:(BOOL)isInitialized syncTimeout:(NSTimeInterval)timeout { bool success = WaitUntilConditionOrTimeout(timeout, ^{
diff --git a/ios/chrome/test/earl_grey2/smoke_egtest.mm b/ios/chrome/test/earl_grey2/smoke_egtest.mm index 68c5799..119525f 100644 --- a/ios/chrome/test/earl_grey2/smoke_egtest.mm +++ b/ios/chrome/test/earl_grey2/smoke_egtest.mm
@@ -164,4 +164,11 @@ waitForSufficientlyVisibleElementWithMatcher:chrome_test_util::Omnibox()]; } +// Tests sync server converted helpers in chrome_earl_grey.h. +- (void)testSyncServerHelpers { + [ChromeEarlGrey startSync]; + [ChromeEarlGrey stopSync]; + [ChromeEarlGrey clearSyncServerData]; +} + @end
diff --git a/ios/web/navigation/navigation_manager_impl.mm b/ios/web/navigation/navigation_manager_impl.mm index 1e79b66..7f94806e 100644 --- a/ios/web/navigation/navigation_manager_impl.mm +++ b/ios/web/navigation/navigation_manager_impl.mm
@@ -240,6 +240,15 @@ } void NavigationManagerImpl::GoToIndex(int index) { + // Silently return if still on a restore URL. This state should only last a + // few moments, but may be triggered when a user mashes the back or forward + // button quickly. + if (web::GetWebClient()->IsSlimNavigationManagerEnabled()) { + NavigationItemImpl* item = GetLastCommittedItemInCurrentOrRestoredSession(); + if (item && wk_navigation_util::IsRestoreSessionUrl(item->GetURL())) { + return; + } + } GoToIndex(index, NavigationInitiationType::BROWSER_INITIATED, /*has_user_gesture=*/true); }
diff --git a/ios/web/navigation/navigation_manager_impl_unittest.mm b/ios/web/navigation/navigation_manager_impl_unittest.mm index 420cb2a..884d83b 100644 --- a/ios/web/navigation/navigation_manager_impl_unittest.mm +++ b/ios/web/navigation/navigation_manager_impl_unittest.mm
@@ -2657,6 +2657,7 @@ // Call CommitPendingItem() with a valid pending item. auto item = std::make_unique<web::NavigationItemImpl>(); + item->SetURL(GURL("http://www.url.com/new")); item->SetNavigationInitiationType( web::NavigationInitiationType::BROWSER_INITIATED); navigation_manager()->CommitPendingItem(std::move(item));
diff --git a/ios/web/navigation/wk_based_navigation_manager_impl.mm b/ios/web/navigation/wk_based_navigation_manager_impl.mm index 27df334..82fab52 100644 --- a/ios/web/navigation/wk_based_navigation_manager_impl.mm +++ b/ios/web/navigation/wk_based_navigation_manager_impl.mm
@@ -298,8 +298,30 @@ empty_window_open_item_ = std::move(item); } else { empty_window_open_item_.reset(); - SetNavigationItemInWKItem(proxy.backForwardList.currentItem, - std::move(item)); + + const GURL item_url(item->GetURL()); + WKBackForwardList* back_forward_list = proxy.backForwardList; + if (item_url == net::GURLWithNSURL(back_forward_list.currentItem.URL)) { + SetNavigationItemInWKItem(back_forward_list.currentItem, std::move(item)); + } else { + // Sometimes |currentItem.URL| is not updated correctly while the webView + // URL is correctly updated. This is a bug in WKWebView. Check to see if + // the next or previous item matches, and update that item instead. If + // nothing matches, still update the the currentItem. + if (item_url == net::GURLWithNSURL(back_forward_list.backItem.URL)) { + SetNavigationItemInWKItem(back_forward_list.backItem, std::move(item)); + } else if (item_url == + net::GURLWithNSURL(back_forward_list.forwardItem.URL)) { + SetNavigationItemInWKItem(back_forward_list.forwardItem, + std::move(item)); + } else { + // Otherwise default here. This can happen when restoring an NTP, since + // |back_forward_list.currentItem.URL| doesn't get updated when going + // from a file:// scheme to about:// scheme. + SetNavigationItemInWKItem(back_forward_list.currentItem, + std::move(item)); + } + } } pending_item_index_ = -1;
diff --git a/media/BUILD.gn b/media/BUILD.gn index 125c6d6..d53a0e5 100644 --- a/media/BUILD.gn +++ b/media/BUILD.gn
@@ -315,18 +315,6 @@ } } -fuzzer_test("media_vp8_parser_fuzzer") { - sources = [ - "filters/vp8_parser_fuzzertest.cc", - ] - deps = [ - ":test_support", - "//base", - ] - libfuzzer_options = [ "max_len = 400000" ] - dict = "test/vp8.dict" -} - fuzzer_test("media_vp9_parser_fuzzer") { sources = [ "filters/vp9_parser_fuzzertest.cc",
diff --git a/media/filters/BUILD.gn b/media/filters/BUILD.gn index eec20a7..d08e594 100644 --- a/media/filters/BUILD.gn +++ b/media/filters/BUILD.gn
@@ -65,10 +65,6 @@ "video_cadence_estimator.h", "video_renderer_algorithm.cc", "video_renderer_algorithm.h", - "vp8_bool_decoder.cc", - "vp8_bool_decoder.h", - "vp8_parser.cc", - "vp8_parser.h", "vp9_bool_decoder.cc", "vp9_bool_decoder.h", "vp9_compressed_header_parser.cc", @@ -289,8 +285,6 @@ "video_cadence_estimator_unittest.cc", "video_decoder_stream_unittest.cc", "video_renderer_algorithm_unittest.cc", - "vp8_bool_decoder_unittest.cc", - "vp8_parser_unittest.cc", "vp9_parser_unittest.cc", "vp9_raw_bits_reader_unittest.cc", ]
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn index 3441103..ef0101f 100644 --- a/media/gpu/BUILD.gn +++ b/media/gpu/BUILD.gn
@@ -276,6 +276,7 @@ ":buildflags", "//base", "//media", + "//media/parsers", "//ui/gfx:buffer_types", "//ui/gfx:memory_buffer", "//ui/gfx/geometry", @@ -482,6 +483,7 @@ "//base/test:test_support", "//media:test_support", "//media/gpu", + "//media/parsers", "//mojo/core/embedder", "//testing/gtest", "//third_party/ffmpeg",
diff --git a/media/gpu/v4l2/v4l2_vp8_accelerator.cc b/media/gpu/v4l2/v4l2_vp8_accelerator.cc index 314bc49..90a4a38d 100644 --- a/media/gpu/v4l2/v4l2_vp8_accelerator.cc +++ b/media/gpu/v4l2/v4l2_vp8_accelerator.cc
@@ -11,12 +11,12 @@ #include "base/logging.h" #include "base/numerics/safe_conversions.h" #include "base/stl_util.h" -#include "media/filters/vp8_parser.h" #include "media/gpu/macros.h" #include "media/gpu/v4l2/v4l2_decode_surface.h" #include "media/gpu/v4l2/v4l2_decode_surface_handler.h" #include "media/gpu/v4l2/v4l2_device.h" #include "media/gpu/vp8_picture.h" +#include "media/parsers/vp8_parser.h" namespace media { namespace {
diff --git a/media/gpu/vaapi/vaapi_vp8_accelerator.h b/media/gpu/vaapi/vaapi_vp8_accelerator.h index a02b3604..a3bb9f0 100644 --- a/media/gpu/vaapi/vaapi_vp8_accelerator.h +++ b/media/gpu/vaapi/vaapi_vp8_accelerator.h
@@ -6,8 +6,8 @@ #define MEDIA_GPU_VAAPI_VAAPI_VP8_ACCELERATOR_H_ #include "base/sequence_checker.h" -#include "media/filters/vp8_parser.h" #include "media/gpu/vp8_decoder.h" +#include "media/parsers/vp8_parser.h" namespace media {
diff --git a/media/gpu/vaapi/vp8_encoder.h b/media/gpu/vaapi/vp8_encoder.h index 5fb94b3f..9395461c 100644 --- a/media/gpu/vaapi/vp8_encoder.h +++ b/media/gpu/vaapi/vp8_encoder.h
@@ -11,10 +11,10 @@ #include "base/macros.h" #include "base/sequence_checker.h" #include "media/base/video_bitrate_allocation.h" -#include "media/filters/vp8_parser.h" #include "media/gpu/vaapi/accelerated_video_encoder.h" #include "media/gpu/vp8_picture.h" #include "media/gpu/vp8_reference_frame_vector.h" +#include "media/parsers/vp8_parser.h" namespace media {
diff --git a/media/gpu/video_encode_accelerator_unittest.cc b/media/gpu/video_encode_accelerator_unittest.cc index 4a22f31..bc1c9c3 100644 --- a/media/gpu/video_encode_accelerator_unittest.cc +++ b/media/gpu/video_encode_accelerator_unittest.cc
@@ -54,7 +54,6 @@ #include "media/filters/ffmpeg_video_decoder.h" #include "media/filters/in_memory_url_protocol.h" #include "media/filters/ivf_parser.h" -#include "media/filters/vp8_parser.h" #include "media/filters/vp9_parser.h" #include "media/filters/vpx_video_decoder.h" #include "media/gpu/buildflags.h" @@ -63,6 +62,7 @@ #include "media/gpu/h264_dpb.h" #include "media/gpu/test/video_accelerator_unittest_helpers.h" #include "media/gpu/test/video_frame_helpers.h" +#include "media/parsers/vp8_parser.h" #include "media/video/fake_video_encode_accelerator.h" #include "media/video/h264_level_limits.h" #include "media/video/h264_parser.h"
diff --git a/media/gpu/vp8_decoder.h b/media/gpu/vp8_decoder.h index 8f53609f..ecc77310 100644 --- a/media/gpu/vp8_decoder.h +++ b/media/gpu/vp8_decoder.h
@@ -12,10 +12,10 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "media/filters/vp8_parser.h" #include "media/gpu/accelerated_video_decoder.h" #include "media/gpu/vp8_picture.h" #include "media/gpu/vp8_reference_frame_vector.h" +#include "media/parsers/vp8_parser.h" namespace media {
diff --git a/media/gpu/vp8_picture.h b/media/gpu/vp8_picture.h index 1e02ded..2db7510 100644 --- a/media/gpu/vp8_picture.h +++ b/media/gpu/vp8_picture.h
@@ -6,8 +6,8 @@ #define MEDIA_GPU_VP8_PICTURE_H_ #include "base/macros.h" -#include "media/filters/vp8_parser.h" #include "media/gpu/codec_picture.h" +#include "media/parsers/vp8_parser.h" namespace media {
diff --git a/media/gpu/vp8_reference_frame_vector.h b/media/gpu/vp8_reference_frame_vector.h index cdb7c564..6f0604fe 100644 --- a/media/gpu/vp8_reference_frame_vector.h +++ b/media/gpu/vp8_reference_frame_vector.h
@@ -9,7 +9,7 @@ #include "base/memory/scoped_refptr.h" #include "base/sequence_checker.h" -#include "media/filters/vp8_parser.h" +#include "media/parsers/vp8_parser.h" namespace media {
diff --git a/media/gpu/windows/dxva_video_decode_accelerator_win.cc b/media/gpu/windows/dxva_video_decode_accelerator_win.cc index 5e16596..4490f8e 100644 --- a/media/gpu/windows/dxva_video_decode_accelerator_win.cc +++ b/media/gpu/windows/dxva_video_decode_accelerator_win.cc
@@ -90,12 +90,6 @@ const wchar_t kMSVP9DecoderDLLName[] = L"MSVP9DEC.dll"; -const CLSID MEDIASUBTYPE_VP80 = { - 0x30385056, - 0x0000, - 0x0010, - {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; - const CLSID MEDIASUBTYPE_VP90 = { 0x30395056, 0x0000, @@ -347,8 +341,8 @@ namespace media { static const VideoCodecProfile kSupportedProfiles[] = { - H264PROFILE_BASELINE, H264PROFILE_MAIN, H264PROFILE_HIGH, - VP8PROFILE_ANY, VP9PROFILE_PROFILE0, VP9PROFILE_PROFILE2}; + H264PROFILE_BASELINE, H264PROFILE_MAIN, H264PROFILE_HIGH, + VP9PROFILE_PROFILE0, VP9PROFILE_PROFILE2}; CreateDXGIDeviceManager DXVAVideoDecodeAccelerator::create_dxgi_device_manager_ = NULL; @@ -773,7 +767,7 @@ break; } } - RETURN_ON_FAILURE(profile_supported, "Unsupported h.264, vp8, or vp9 profile", + RETURN_ON_FAILURE(profile_supported, "Unsupported h.264 or vp9 profile", false); if (config.profile == VP9PROFILE_PROFILE2 || @@ -1443,8 +1437,9 @@ // 1920 x 1088. We use 1088 to account for 16x16 macroblocks. ResolutionPair max_h264_resolutions(gfx::Size(1920, 1088), gfx::Size()); - // VPX has no default resolutions since it may not even be supported. - ResolutionPair max_vpx_resolutions; + // VP9 has no default resolutions since it may not even be supported. + ResolutionPair max_vp9_profile0_resolutions; + ResolutionPair max_vp9_profile2_resolutions; if (base::win::GetVersion() > base::win::Version::WIN7) { // To detect if a driver supports the desired resolutions, we try and create @@ -1464,31 +1459,44 @@ {gfx::Size(2560, 1440), gfx::Size(3840, 2160), gfx::Size(4096, 2160), gfx::Size(4096, 2304)}); - // Despite the name this is the GUID for VP8/VP9. if (preferences.enable_accelerated_vpx_decode && !workarounds.disable_accelerated_vpx_decode) { - max_vpx_resolutions = GetMaxResolutionsForGUIDs( - max_vpx_resolutions.first, video_device.Get(), + max_vp9_profile0_resolutions = GetMaxResolutionsForGUIDs( + max_vp9_profile0_resolutions.first, video_device.Get(), {D3D11_DECODER_PROFILE_VP9_VLD_PROFILE0}, {gfx::Size(4096, 2160), gfx::Size(4096, 2304), gfx::Size(7680, 4320), gfx::Size(8192, 4320), gfx::Size(8192, 8192)}); + max_vp9_profile2_resolutions = GetMaxResolutionsForGUIDs( + max_vp9_profile2_resolutions.first, video_device.Get(), + {D3D11_DECODER_PROFILE_VP9_VLD_10BIT_PROFILE2}, + {gfx::Size(4096, 2160), gfx::Size(4096, 2304), + gfx::Size(7680, 4320), gfx::Size(8192, 4320), + gfx::Size(8192, 8192)}); } } } } for (const auto& supported_profile : kSupportedProfiles) { - const bool kIsVPX = supported_profile >= VP8PROFILE_MIN && - supported_profile <= VP9PROFILE_MAX; - - // Skip adding VPX profiles if it's not supported or disabled. - if (kIsVPX && max_vpx_resolutions.first.IsEmpty()) - continue; - - const bool kIsH264 = supported_profile >= H264PROFILE_MIN && + const bool is_h264 = supported_profile >= H264PROFILE_MIN && supported_profile <= H264PROFILE_MAX; - DCHECK(kIsH264 || kIsVPX); + const bool is_vp9 = supported_profile >= VP9PROFILE_MIN && + supported_profile <= VP9PROFILE_MAX; + DCHECK(is_h264 || is_vp9); + + ResolutionPair max_resolutions; + if (is_h264) { + max_resolutions = max_h264_resolutions; + } else if (supported_profile == VP9PROFILE_PROFILE0) { + max_resolutions = max_vp9_profile0_resolutions; + } else if (supported_profile == VP9PROFILE_PROFILE2) { + max_resolutions = max_vp9_profile2_resolutions; + } + + // Skip adding VP9 profiles if it's not supported or disabled. + if (is_vp9 && max_resolutions.first.IsEmpty()) + continue; // Windows Media Foundation H.264 decoding does not support decoding videos // with any dimension smaller than 48 pixels: @@ -1496,25 +1504,23 @@ // // TODO(dalecurtis): These values are too low. We should only be using // hardware decode for videos above ~360p, see http://crbug.com/684792. - const gfx::Size kMinResolution = - kIsH264 ? gfx::Size(48, 48) : gfx::Size(16, 16); + const gfx::Size min_resolution = + is_h264 ? gfx::Size(48, 48) : gfx::Size(16, 16); { SupportedProfile profile; profile.profile = supported_profile; - profile.min_resolution = kMinResolution; - profile.max_resolution = - kIsH264 ? max_h264_resolutions.first : max_vpx_resolutions.first; + profile.min_resolution = min_resolution; + profile.max_resolution = max_resolutions.first; profiles.push_back(profile); } - const gfx::Size kPortraitMax = - kIsH264 ? max_h264_resolutions.second : max_vpx_resolutions.second; - if (!kPortraitMax.IsEmpty()) { + const gfx::Size portrait_max_resolution = max_resolutions.second; + if (!portrait_max_resolution.IsEmpty()) { SupportedProfile profile; profile.profile = supported_profile; - profile.min_resolution = kMinResolution; - profile.max_resolution = kPortraitMax; + profile.min_resolution = min_resolution; + profile.max_resolution = portrait_max_resolution; profiles.push_back(profile); } } @@ -1566,13 +1572,10 @@ codec_ = kCodecH264; clsid = __uuidof(CMSH264DecoderMFT); } else if (enable_accelerated_vpx_decode_ && - (profile == VP8PROFILE_ANY || profile == VP9PROFILE_PROFILE0 || - profile == VP9PROFILE_PROFILE1 || - profile == VP9PROFILE_PROFILE2 || - profile == VP9PROFILE_PROFILE3)) { - if (profile != VP8PROFILE_ANY && - (enable_accelerated_vpx_decode_ & - gpu::GpuPreferences::VPX_VENDOR_MICROSOFT)) { + (profile >= VP9PROFILE_PROFILE0 && + profile <= VP9PROFILE_PROFILE3)) { + if (enable_accelerated_vpx_decode_ & + gpu::GpuPreferences::VPX_VENDOR_MICROSOFT) { codec_ = kCodecVP9; clsid = CLSID_MSVPxDecoder; decoder_dll = ::LoadLibrary(kMSVP9DecoderDLLName); @@ -1580,18 +1583,18 @@ using_ms_vp9_mft_ = true; } - int program_files_key = base::DIR_PROGRAM_FILES; - if (base::win::OSInfo::GetInstance()->wow64_status() == - base::win::OSInfo::WOW64_ENABLED) { - program_files_key = base::DIR_PROGRAM_FILES6432; - } - // Avoid loading AMD VP9 decoder on Windows ARM64. #if defined(ARCH_CPU_X86_FAMILY) // AMD if (!decoder_dll && enable_accelerated_vpx_decode_ & gpu::GpuPreferences::VPX_VENDOR_AMD && profile == VP9PROFILE_PROFILE0) { + int program_files_key = base::DIR_PROGRAM_FILES; + if (base::win::OSInfo::GetInstance()->wow64_status() == + base::win::OSInfo::WOW64_ENABLED) { + program_files_key = base::DIR_PROGRAM_FILES6432; + } + base::FilePath dll_path; if (base::PathService::Get(program_files_key, &dll_path)) { codec_ = media::kCodecVP9; @@ -1784,8 +1787,6 @@ if (codec_ == kCodecH264) { hr = media_type->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264); - } else if (codec_ == kCodecVP8) { - hr = media_type->SetGUID(MF_MT_SUBTYPE, MEDIASUBTYPE_VP80); } else if (codec_ == kCodecVP9) { hr = media_type->SetGUID(MF_MT_SUBTYPE, MEDIASUBTYPE_VP90); } else {
diff --git a/media/parsers/BUILD.gn b/media/parsers/BUILD.gn index 4b2fab19..f4999d65 100644 --- a/media/parsers/BUILD.gn +++ b/media/parsers/BUILD.gn
@@ -9,6 +9,12 @@ "jpeg_parser.cc", "jpeg_parser.h", "media_parsers_export.h", + "vp8_bool_decoder.cc", + "vp8_bool_decoder.h", + "vp8_parser.cc", + "vp8_parser.h", + "webp_parser.cc", + "webp_parser.h", ] defines = [ "IS_MEDIA_PARSER_IMPL" ] deps = [ @@ -26,6 +32,9 @@ testonly = true sources = [ "jpeg_parser_unittest.cc", + "vp8_bool_decoder_unittest.cc", + "vp8_parser_unittest.cc", + "webp_parser_unittest.cc", ] deps = [ ":parsers", @@ -46,3 +55,16 @@ seed_corpus = "//media/test/data" dict = "//media/test/jpeg.dict" } + +fuzzer_test("media_vp8_parser_fuzzer") { + sources = [ + "vp8_parser_fuzzertest.cc", + ] + deps = [ + ":parsers", + "//base", + "//media:test_support", + ] + libfuzzer_options = [ "max_len = 400000" ] + dict = "//media/test/vp8.dict" +}
diff --git a/media/parsers/jpeg_parser.h b/media/parsers/jpeg_parser.h index faab7e92..bd054f5 100644 --- a/media/parsers/jpeg_parser.h +++ b/media/parsers/jpeg_parser.h
@@ -1,7 +1,7 @@ // Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// + #ifndef MEDIA_PARSERS_JPEG_PARSER_H_ #define MEDIA_PARSERS_JPEG_PARSER_H_
diff --git a/media/filters/vp8_bool_decoder.cc b/media/parsers/vp8_bool_decoder.cc similarity index 99% rename from media/filters/vp8_bool_decoder.cc rename to media/parsers/vp8_bool_decoder.cc index 7ec4859..4f156ad 100644 --- a/media/filters/vp8_bool_decoder.cc +++ b/media/parsers/vp8_bool_decoder.cc
@@ -40,12 +40,13 @@ // project. (http://www.webmproject.org/code) // It is used to decode bits from a vp8 stream. +#include "media/parsers/vp8_bool_decoder.h" + #include <limits.h> #include <algorithm> #include "base/numerics/safe_conversions.h" -#include "media/filters/vp8_bool_decoder.h" namespace media {
diff --git a/media/filters/vp8_bool_decoder.h b/media/parsers/vp8_bool_decoder.h similarity index 95% rename from media/filters/vp8_bool_decoder.h rename to media/parsers/vp8_bool_decoder.h index 16a98bd..0f407cfb 100644 --- a/media/filters/vp8_bool_decoder.h +++ b/media/parsers/vp8_bool_decoder.h
@@ -40,8 +40,8 @@ // project. (http://www.webmproject.org/code) // It is used to decode bits from a vp8 stream. -#ifndef MEDIA_FILTERS_VP8_BOOL_DECODER_H_ -#define MEDIA_FILTERS_VP8_BOOL_DECODER_H_ +#ifndef MEDIA_PARSERS_VP8_BOOL_DECODER_H_ +#define MEDIA_PARSERS_VP8_BOOL_DECODER_H_ #include <stddef.h> #include <stdint.h> @@ -49,13 +49,13 @@ #include "base/logging.h" #include "base/macros.h" -#include "media/base/media_export.h" +#include "media/parsers/media_parsers_export.h" namespace media { // A class to decode the VP8's boolean entropy coded stream. It's a variant of // arithmetic coding. See RFC 6386 - Chapter 7. Boolean Entropy Decoder. -class MEDIA_EXPORT Vp8BoolDecoder { +class MEDIA_PARSERS_EXPORT Vp8BoolDecoder { public: Vp8BoolDecoder(); @@ -132,4 +132,4 @@ } // namespace media -#endif // MEDIA_FILTERS_VP8_BOOL_DECODER_H_ +#endif // MEDIA_PARSERS_VP8_BOOL_DECODER_H_
diff --git a/media/filters/vp8_bool_decoder_unittest.cc b/media/parsers/vp8_bool_decoder_unittest.cc similarity index 98% rename from media/filters/vp8_bool_decoder_unittest.cc rename to media/parsers/vp8_bool_decoder_unittest.cc index f1f020b0..87968f4f 100644 --- a/media/filters/vp8_bool_decoder_unittest.cc +++ b/media/parsers/vp8_bool_decoder_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "media/filters/vp8_bool_decoder.h" +#include "media/parsers/vp8_bool_decoder.h" #include <stddef.h> #include <stdint.h>
diff --git a/media/filters/vp8_parser.cc b/media/parsers/vp8_parser.cc similarity index 99% rename from media/filters/vp8_parser.cc rename to media/parsers/vp8_parser.cc index cfdcce2..04345b5 100644 --- a/media/filters/vp8_parser.cc +++ b/media/parsers/vp8_parser.cc
@@ -5,8 +5,9 @@ // This file contains an implementation of a VP8 raw stream parser, // as defined in RFC 6386. +#include "media/parsers/vp8_parser.h" + #include "base/logging.h" -#include "media/filters/vp8_parser.h" namespace media {
diff --git a/media/filters/vp8_parser.h b/media/parsers/vp8_parser.h similarity index 92% rename from media/filters/vp8_parser.h rename to media/parsers/vp8_parser.h index c1a95cc..11585bc 100644 --- a/media/filters/vp8_parser.h +++ b/media/parsers/vp8_parser.h
@@ -5,15 +5,15 @@ // This file contains an implementation of a VP8 raw stream parser, // as defined in RFC 6386. -#ifndef MEDIA_FILTERS_VP8_PARSER_H_ -#define MEDIA_FILTERS_VP8_PARSER_H_ +#ifndef MEDIA_PARSERS_VP8_PARSER_H_ +#define MEDIA_PARSERS_VP8_PARSER_H_ #include <stddef.h> #include <stdint.h> #include "base/macros.h" -#include "media/base/media_export.h" -#include "media/filters/vp8_bool_decoder.h" +#include "media/parsers/media_parsers_export.h" +#include "media/parsers/vp8_bool_decoder.h" namespace media { @@ -23,7 +23,7 @@ // Member of Vp8FrameHeader and will be 0-initialized // in Vp8FrameHeader's constructor. -struct MEDIA_EXPORT Vp8SegmentationHeader { +struct Vp8SegmentationHeader { enum SegmentFeatureMode { FEATURE_MODE_DELTA = 0, FEATURE_MODE_ABSOLUTE = 1 }; bool segmentation_enabled; @@ -41,7 +41,7 @@ // Member of Vp8FrameHeader and will be 0-initialized // in Vp8FrameHeader's constructor. -struct MEDIA_EXPORT Vp8LoopFilterHeader { +struct Vp8LoopFilterHeader { enum Type { LOOP_FILTER_TYPE_NORMAL = 0, LOOP_FILTER_TYPE_SIMPLE = 1 }; Type type; uint8_t level; @@ -55,7 +55,7 @@ // Member of Vp8FrameHeader and will be 0-initialized // in Vp8FrameHeader's constructor. -struct MEDIA_EXPORT Vp8QuantizationHeader { +struct Vp8QuantizationHeader { uint8_t y_ac_qi; int8_t y_dc_delta; int8_t y2_dc_delta; @@ -96,7 +96,7 @@ VP8_FRAME_ALTREF = 2, }; -struct MEDIA_EXPORT Vp8FrameHeader { +struct MEDIA_PARSERS_EXPORT Vp8FrameHeader { Vp8FrameHeader(); enum FrameType { KEYFRAME = 0, INTERFRAME = 1 }; @@ -164,7 +164,7 @@ }; // A parser for raw VP8 streams as specified in RFC 6386. -class MEDIA_EXPORT Vp8Parser { +class MEDIA_PARSERS_EXPORT Vp8Parser { public: Vp8Parser(); ~Vp8Parser(); @@ -205,4 +205,4 @@ } // namespace media -#endif // MEDIA_FILTERS_VP8_PARSER_H_ +#endif // MEDIA_PARSERS_VP8_PARSER_H_
diff --git a/media/filters/vp8_parser_fuzzertest.cc b/media/parsers/vp8_parser_fuzzertest.cc similarity index 95% rename from media/filters/vp8_parser_fuzzertest.cc rename to media/parsers/vp8_parser_fuzzertest.cc index 1d3f972..75cc6bb 100644 --- a/media/filters/vp8_parser_fuzzertest.cc +++ b/media/parsers/vp8_parser_fuzzertest.cc
@@ -7,7 +7,7 @@ #include "base/numerics/safe_conversions.h" #include "media/filters/ivf_parser.h" -#include "media/filters/vp8_parser.h" +#include "media/parsers/vp8_parser.h" // Entry point for LibFuzzer. extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
diff --git a/media/filters/vp8_parser_unittest.cc b/media/parsers/vp8_parser_unittest.cc similarity index 97% rename from media/filters/vp8_parser_unittest.cc rename to media/parsers/vp8_parser_unittest.cc index 966a0b8..cbe4ff0 100644 --- a/media/filters/vp8_parser_unittest.cc +++ b/media/parsers/vp8_parser_unittest.cc
@@ -9,7 +9,7 @@ #include "base/logging.h" #include "media/base/test_data_util.h" #include "media/filters/ivf_parser.h" -#include "media/filters/vp8_parser.h" +#include "media/parsers/vp8_parser.h" #include "testing/gtest/include/gtest/gtest.h" namespace media {
diff --git a/media/parsers/webp_parser.cc b/media/parsers/webp_parser.cc new file mode 100644 index 0000000..b0348037 --- /dev/null +++ b/media/parsers/webp_parser.cc
@@ -0,0 +1,131 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/parsers/webp_parser.h" + +#include <limits.h> +#include <stddef.h> +#include <string.h> + +#include "base/bits.h" +#include "base/logging.h" +#include "base/numerics/safe_conversions.h" +#include "build/build_config.h" +#include "media/parsers/vp8_parser.h" + +#if !defined(ARCH_CPU_LITTLE_ENDIAN) +#error Big-Endian architecture not supported. +#endif + +namespace media { + +namespace { + +// The byte position storing the size of the file. +constexpr size_t kFileSizeBytePosition = 4u; + +// The byte position in which the WebP image data begins. +constexpr size_t kWebPFileBeginBytePosition = 8u; + +// The byte position storing the size of the VP8 frame. +constexpr size_t kVp8FrameSizePosition = 16u; + +// The 12 bytes that include the FourCC "WEBPVP8 " plus the VP8 chunk size info. +constexpr size_t kWebPFileHeaderByteSize = 12u; + +// A valid WebP image header and VP8 chunk header require 20 bytes. +// The VP8 Key Frame's payload also begins at byte 20. +constexpr size_t kWebPFileAndVp8ChunkHeaderSizeInBytes = 20u; + +// The max WebP file size is (2^32 - 10) per the WebP spec: +// https://developers.google.com/speed/webp/docs/riff_container#webp_file_header +constexpr uint32_t kMaxWebPFileSize = (1ull << 32) - 10u; + +constexpr size_t kSizeOfUint32t = sizeof(uint32_t); + +} // namespace + +bool IsLossyWebPImage(base::span<const uint8_t> encoded_data) { + if (encoded_data.size() < kWebPFileAndVp8ChunkHeaderSizeInBytes) + return false; + + DCHECK(encoded_data.data()); + + return !memcmp(encoded_data.data(), "RIFF", 4) && + !memcmp(encoded_data.data() + kWebPFileBeginBytePosition, "WEBPVP8 ", + 8); +} + +std::unique_ptr<Vp8FrameHeader> ParseWebPImage( + base::span<const uint8_t> encoded_data) { + if (!IsLossyWebPImage(encoded_data)) + return nullptr; + + static_assert(CHAR_BIT == 8, "Size of a char is not 8 bits."); + static_assert(kSizeOfUint32t == 4u, "Size of uint32_t is not 4 bytes."); + + // Try to acquire the WebP file size. IsLossyWebPImage() has ensured + // that we have enough data to read the file size. + DCHECK_GE(encoded_data.size(), kFileSizeBytePosition + kSizeOfUint32t); + + // No need to worry about endianness because we assert little-endianness. + const uint32_t file_size = *reinterpret_cast<const uint32_t*>( + encoded_data.data() + kFileSizeBytePosition); + + // Check that |file_size| is even, per the WebP spec: + // https://developers.google.com/speed/webp/docs/riff_container#webp_file_header + if (file_size % 2 != 0) + return nullptr; + + // Check that |file_size| <= 2^32 - 10, per the WebP spec: + // https://developers.google.com/speed/webp/docs/riff_container#webp_file_header + if (file_size > kMaxWebPFileSize) + return nullptr; + + // Check that the file size in the header matches the encoded data's size. + if (base::strict_cast<size_t>(file_size) != + encoded_data.size() - kWebPFileBeginBytePosition) { + return nullptr; + } + + // Try to acquire the VP8 key frame size and validate that it fits within the + // encoded data's size. + DCHECK_GE(encoded_data.size(), kVp8FrameSizePosition + kSizeOfUint32t); + + const uint32_t vp8_frame_size = *reinterpret_cast<const uint32_t*>( + encoded_data.data() + kVp8FrameSizePosition); + + // Check that the VP8 frame size is bounded by the WebP size. + if (base::strict_cast<size_t>(file_size) - kWebPFileHeaderByteSize < + base::strict_cast<size_t>(vp8_frame_size)) { + return nullptr; + } + + // Check that the size of the encoded data is consistent. + const size_t vp8_padded_frame_size = + base::bits::Align(base::strict_cast<size_t>(vp8_frame_size), 2u); + if (encoded_data.size() - kWebPFileAndVp8ChunkHeaderSizeInBytes != + vp8_padded_frame_size) { + return nullptr; + } + + // Check that the last byte is 0 if |vp8_frame_size| is odd per WebP specs: + // https://developers.google.com/speed/webp/docs/riff_container#riff_file_format + if (vp8_frame_size % 2 && + encoded_data.data()[encoded_data.size() - 1] != 0u) { + return nullptr; + } + + // Attempt to parse the VP8 frame. + Vp8Parser vp8_parser; + auto result = std::make_unique<Vp8FrameHeader>(); + if (vp8_parser.ParseFrame( + encoded_data.data() + kWebPFileAndVp8ChunkHeaderSizeInBytes, + base::strict_cast<size_t>(vp8_frame_size), result.get())) { + return result; + } + return nullptr; +} + +} // namespace media
diff --git a/media/parsers/webp_parser.h b/media/parsers/webp_parser.h new file mode 100644 index 0000000..436d6c7 --- /dev/null +++ b/media/parsers/webp_parser.h
@@ -0,0 +1,38 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_PARSERS_WEBP_PARSER_H_ +#define MEDIA_PARSERS_WEBP_PARSER_H_ + +#include <stdint.h> +#include <memory> + +#include "base/containers/span.h" +#include "media/parsers/media_parsers_export.h" + +namespace media { + +struct Vp8FrameHeader; + +// A lightweight WebP file header parser to extract feature and size +// information. It validates that a given data stream encodes a simple lossy +// WebP image and populates a Vp8FrameHeader upon successful parsing. +// For more information, see the WebP Container Specification: +// https://developers.google.com/speed/webp/docs/riff_container + +// Returns true if |encoded_data| claims to encode a simple (non-extended) lossy +// WebP image. Returns false otherwise. +MEDIA_PARSERS_EXPORT +bool IsLossyWebPImage(base::span<const uint8_t> encoded_data); + +// Parses a simple (non-extended) lossy WebP image and returns a Vp8FrameHeader +// containing the parsed VP8 frame contained by the image. Returns nullptr on +// failure. +MEDIA_PARSERS_EXPORT +std::unique_ptr<Vp8FrameHeader> ParseWebPImage( + base::span<const uint8_t> encoded_data); + +} // namespace media + +#endif // MEDIA_PARSERS_WEBP_PARSER_H_
diff --git a/media/parsers/webp_parser_unittest.cc b/media/parsers/webp_parser_unittest.cc new file mode 100644 index 0000000..4c9d997 --- /dev/null +++ b/media/parsers/webp_parser_unittest.cc
@@ -0,0 +1,327 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stddef.h> +#include <stdint.h> + +#include <memory> + +#include "base/base_paths.h" +#include "base/containers/span.h" +#include "base/files/file_path.h" +#include "base/files/memory_mapped_file.h" +#include "base/path_service.h" +#include "media/parsers/vp8_parser.h" +#include "media/parsers/webp_parser.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace media { + +namespace { + +constexpr size_t kWebPFileAndVp8ChunkHeaderSizeInBytes = 20u; +// clang-format off +constexpr uint8_t kLossyWebPFileHeader[] = { + 'R', 'I', 'F', 'F', + 0x0c, 0x00, 0x00, 0x00, // == 12 (little endian) + 'W', 'E', 'B', 'P', + 'V', 'P', '8', ' ', + 0x00, 0x00, 0x00, 0x00 // == 0 +}; +constexpr base::span<const uint8_t> kLossyWebPEncodedData( + kLossyWebPFileHeader, + kWebPFileAndVp8ChunkHeaderSizeInBytes); +constexpr base::span<const uint8_t> kInvalidWebPEncodedDataSize( + kLossyWebPFileHeader, + kWebPFileAndVp8ChunkHeaderSizeInBytes - 5u); + +constexpr uint8_t kLosslessWebPFileHeader[] = { + 'R', 'I', 'F', 'F', + 0x0c, 0x00, 0x00, 0x00, + 'W', 'E', 'B', 'P', + 'V', 'P', '8', 'L', + 0x00, 0x00, 0x00, 0x00 +}; +constexpr base::span<const uint8_t> kLosslessWebPEncodedData( + kLosslessWebPFileHeader, + kWebPFileAndVp8ChunkHeaderSizeInBytes); + +constexpr uint8_t kExtendedWebPFileHeader[] = { + 'R', 'I', 'F', 'F', + 0x0c, 0x00, 0x00, 0x00, + 'W', 'E', 'B', 'P', + 'V', 'P', '8', 'X', + 0x00, 0x00, 0x00, 0x00 +}; +constexpr base::span<const uint8_t> kExtendedWebPEncodedData( + kExtendedWebPFileHeader, + kWebPFileAndVp8ChunkHeaderSizeInBytes); + +constexpr uint8_t kUnknownWebPFileHeader[] = { + 'R', 'I', 'F', 'F', + 0x0c, 0x00, 0x00, 0x00, + 'W', 'E', 'B', 'P', + 'V', 'P', '8', '~', + 0x00, 0x00, 0x00, 0x00 +}; +constexpr base::span<const uint8_t> kUnknownWebPEncodedData( + kUnknownWebPFileHeader, + kWebPFileAndVp8ChunkHeaderSizeInBytes); + +constexpr uint8_t kInvalidRiffWebPFileHeader[] = { + 'X', 'I', 'F', 'F', + 0x0c, 0x00, 0x00, 0x00, + 'W', 'E', 'B', 'P', + 'V', 'P', '8', ' ', + 0x00, 0x00, 0x00, 0x00 +}; +constexpr base::span<const uint8_t> kInvalidRiffWebPEncodedData( + kInvalidRiffWebPFileHeader, + kWebPFileAndVp8ChunkHeaderSizeInBytes); + +constexpr uint8_t kInvalidOddFileSizeInWebPFileHeader[] = { + 'R', 'I', 'F', 'F', + 0x0d, 0x00, 0x00, 0x00, // == 13 (Invalid: should be even) + 'W', 'E', 'B', 'P', + 'V', 'P', '8', ' ', + 0x00, 0x00, 0x00, 0x00, + 0x00 +}; +constexpr base::span<const uint8_t> kInvalidOddFileSizeInHeaderWebPEncodedData( + kInvalidOddFileSizeInWebPFileHeader, + kWebPFileAndVp8ChunkHeaderSizeInBytes + 1u); // Match the reported size + +constexpr uint8_t kInvalidLargerThanLimitFileSizeInWebPFileHeader[] = { + 'R', 'I', 'F', 'F', + 0xfe, 0xff, 0xff, 0xff, // == 2^32 - 2 (Invalid: should be <= 2^32 - 10) + 'W', 'E', 'B', 'P', + 'V', 'P', '8', ' ', + 0x00, 0x00, 0x00, 0x00 +}; +constexpr base::span<const uint8_t> +kInvalidLargerThanLimitFileSizeInHeaderWebPEncodedData( + kInvalidLargerThanLimitFileSizeInWebPFileHeader, + kWebPFileAndVp8ChunkHeaderSizeInBytes); + +constexpr uint8_t kInvalidLargerFileSizeInWebPFileHeader[] = { + 'R', 'I', 'F', 'F', + 0x10, 0x00, 0x00, 0x00, // == 16 (Invalid: should be 12) + 'W', 'E', 'B', 'P', + 'V', 'P', '8', ' ', + 0x00, 0x00, 0x00, 0x00 +}; +constexpr base::span<const uint8_t> +kInvalidLargerFileSizeInHeaderWebPEncodedData( + kInvalidLargerFileSizeInWebPFileHeader, + kWebPFileAndVp8ChunkHeaderSizeInBytes); + +constexpr uint8_t kInvalidKeyFrameSizeInWebPFileHeader[] = { + 'R', 'I', 'F', 'F', + 0x0c, 0x00, 0x00, 0x00, // == 12 + 'W', 'E', 'B', 'P', + 'V', 'P', '8', ' ', + 0xc8, 0x00, 0x00, 0x00 // == 200 (Invalid: should be 0) +}; +constexpr base::span<const uint8_t> kInvalidKeyFrameSizeInWebPEncodedData( + kInvalidKeyFrameSizeInWebPFileHeader, + kWebPFileAndVp8ChunkHeaderSizeInBytes); + +constexpr uint8_t kMismatchingOddVp8FrameSizeAndDataSize[] = { + 'R', 'I', 'F', 'F', + 0x12, 0x00, 0x00, 0x00, // == 18 + 'W', 'E', 'B', 'P', + 'V', 'P', '8', ' ', + 0x03, 0x00, 0x00, 0x00, // == 3 + 0x11, 0xa0, 0x23, 0x00, // Valid padding byte + 0xfa, 0xcc // Should not exist. +}; +constexpr base::span<const uint8_t> +kMismatchingOddVp8FrameSizeAndDataSizeEncodedData( + kMismatchingOddVp8FrameSizeAndDataSize, + kWebPFileAndVp8ChunkHeaderSizeInBytes + 6u); + +constexpr uint8_t kMismatchingEvenVp8FrameSizeAndDataSize[] = { + 'R', 'I', 'F', 'F', + 0x12, 0x00, 0x00, 0x00, // == 18 + 'W', 'E', 'B', 'P', + 'V', 'P', '8', ' ', + 0x04, 0x00, 0x00, 0x00, // == 4 + 0x11, 0xa0, 0x23, 0x12, + 0xfc, 0xcd // Should not exist. +}; +constexpr base::span<const uint8_t> +kMismatchingEvenVp8FrameSizeAndDataSizeEncodedData( + kMismatchingEvenVp8FrameSizeAndDataSize, + kWebPFileAndVp8ChunkHeaderSizeInBytes + 6u); + +constexpr uint8_t kInvalidPaddingByteInVp8DataChunk[] = { + 'R', 'I', 'F', 'F', + 0x10, 0x00, 0x00, 0x00, // == 16 + 'W', 'E', 'B', 'P', + 'V', 'P', '8', ' ', + 0x03, 0x00, 0x00, 0x00, // == 3 + 0x11, 0xa0, 0x23, 0xff // Invalid: last byte should be 0 +}; +constexpr base::span<const uint8_t> +kInvalidPaddingByteInVp8DataChunkEncodedData( + kInvalidPaddingByteInVp8DataChunk, + kWebPFileAndVp8ChunkHeaderSizeInBytes + 4u); +// clang-format on + +} // namespace + +TEST(WebPParserTest, WebPImageFileValidator) { + // Verify that only lossy WebP formats pass. + ASSERT_TRUE(IsLossyWebPImage(kLossyWebPEncodedData)); + + // Verify that lossless, extended, and unknown WebP formats fail. + ASSERT_FALSE(IsLossyWebPImage(kLosslessWebPEncodedData)); + ASSERT_FALSE(IsLossyWebPImage(kExtendedWebPEncodedData)); + ASSERT_FALSE(IsLossyWebPImage(kUnknownWebPEncodedData)); + + // Verify that invalid WebP file headers and sizes fail. + ASSERT_FALSE(IsLossyWebPImage(kInvalidRiffWebPEncodedData)); + ASSERT_FALSE(IsLossyWebPImage(kInvalidWebPEncodedDataSize)); +} + +TEST(WebPParserTest, ParseLossyWebP) { + base::FilePath data_dir; + ASSERT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &data_dir)); + + base::FilePath file_path = data_dir.AppendASCII("media") + .AppendASCII("test") + .AppendASCII("data") + .AppendASCII("red_green_gradient_lossy.webp"); + + base::MemoryMappedFile stream; + ASSERT_TRUE(stream.Initialize(file_path)) + << "Couldn't open stream file: " << file_path.MaybeAsASCII(); + + std::unique_ptr<Vp8FrameHeader> result = + ParseWebPImage(base::span<const uint8_t>(stream.data(), stream.length())); + ASSERT_TRUE(result); + + ASSERT_TRUE(result->IsKeyframe()); + ASSERT_TRUE(result->data); + + // Original image is 3000x3000. + ASSERT_EQ(3000u, result->width); + ASSERT_EQ(3000u, result->height); +} + +TEST(WebPParserTest, ParseLosslessWebP) { + base::FilePath data_dir; + ASSERT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &data_dir)); + + base::FilePath file_path = + data_dir.AppendASCII("media") + .AppendASCII("test") + .AppendASCII("data") + .AppendASCII("yellow_pink_gradient_lossless.webp"); + + base::MemoryMappedFile stream; + ASSERT_TRUE(stream.Initialize(file_path)) + << "Couldn't open stream file: " << file_path.MaybeAsASCII(); + + // Should fail because WebP parser does not parse lossless webp images. + std::unique_ptr<Vp8FrameHeader> result = + ParseWebPImage(base::span<const uint8_t>(stream.data(), stream.length())); + ASSERT_FALSE(result); +} + +TEST(WebPParserTest, ParseExtendedWebP) { + base::FilePath data_dir; + ASSERT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &data_dir)); + + base::FilePath file_path = data_dir.AppendASCII("media") + .AppendASCII("test") + .AppendASCII("data") + .AppendASCII("bouncy_ball.webp"); + + base::MemoryMappedFile stream; + ASSERT_TRUE(stream.Initialize(file_path)) + << "Couldn't open stream file: " << file_path.MaybeAsASCII(); + + // Should fail because WebP parser does not parse extended webp images. + std::unique_ptr<Vp8FrameHeader> result = + ParseWebPImage(base::span<const uint8_t>(stream.data(), stream.length())); + ASSERT_FALSE(result); +} + +TEST(WebPParserTest, ParseWebPWithUnknownFormat) { + // Should fail when the specifier byte at position 16 holds anything but ' '. + std::unique_ptr<Vp8FrameHeader> result = + ParseWebPImage(kUnknownWebPEncodedData); + ASSERT_FALSE(result); +} + +TEST(WebPParserTest, ParseWebPWithInvalidHeaders) { + // Should fail because the header is an invalid WebP container. + std::unique_ptr<Vp8FrameHeader> result = + ParseWebPImage(kInvalidRiffWebPEncodedData); + ASSERT_FALSE(result); + + // Should fail because the header has an invalid size. + result = ParseWebPImage(kInvalidWebPEncodedDataSize); + ASSERT_FALSE(result); +} + +TEST(WebPParserTest, ParseWebPWithInvalidOddSizeInHeader) { + // Should fail because the size reported in the header is odd. + std::unique_ptr<Vp8FrameHeader> result = + ParseWebPImage(kInvalidOddFileSizeInHeaderWebPEncodedData); + ASSERT_FALSE(result); +} + +TEST(WebPParserTest, ParseWebPWithInvalidLargerThanLimitSizeInHeader) { + // Should fail because the size reported in the header is larger than + // 2^32 - 10 per the WebP spec. + std::unique_ptr<Vp8FrameHeader> result = + ParseWebPImage(kInvalidLargerThanLimitFileSizeInHeaderWebPEncodedData); + ASSERT_FALSE(result); +} + +TEST(WebPParserTest, ParseWebPWithInvalidFileSizeInHeader) { + // Should fail because the size reported in the header does not match the + // actual data size. + std::unique_ptr<Vp8FrameHeader> result = + ParseWebPImage(kInvalidLargerFileSizeInHeaderWebPEncodedData); + ASSERT_FALSE(result); +} + +TEST(WebPParserTest, ParseWebPWithEmptyVp8KeyFrameAndIncorrectKeyFrameSize) { + // Should fail because the reported VP8 key frame size is larger than the + // the existing data. + std::unique_ptr<Vp8FrameHeader> result = + ParseWebPImage(kInvalidKeyFrameSizeInWebPEncodedData); + ASSERT_FALSE(result); +} + +TEST(WebPParserTest, ParseWebPWithMismatchingVp8FrameAndDataSize) { + // Should fail because the reported VP8 key frame size (even or odd) does not + // match the encoded data's size. + std::unique_ptr<Vp8FrameHeader> result = + ParseWebPImage(kMismatchingOddVp8FrameSizeAndDataSizeEncodedData); + ASSERT_FALSE(result); + + result = ParseWebPImage(kMismatchingEvenVp8FrameSizeAndDataSizeEncodedData); + ASSERT_FALSE(result); +} + +TEST(WebPParserTest, ParseWebPWithInvalidPaddingByteInVp8DataChunk) { + // Should fail because the reported VP8 key frame size is odd and the added + // padding byte is not 0. + std::unique_ptr<Vp8FrameHeader> result = + ParseWebPImage(kInvalidPaddingByteInVp8DataChunkEncodedData); + ASSERT_FALSE(result); +} + +TEST(WebPParserTest, ParseWebPWithEmptyVp8KeyFrame) { + // Should fail because the VP8 parser is passed a data chunk of size 0. + std::unique_ptr<Vp8FrameHeader> result = + ParseWebPImage(kLossyWebPEncodedData); + ASSERT_FALSE(result); +} + +} // namespace media
diff --git a/media/test/data/README.md b/media/test/data/README.md index 7e6305a5..daac16e 100644 --- a/media/test/data/README.md +++ b/media/test/data/README.md
@@ -817,6 +817,17 @@ ffmpeg -i red.webm -i a500hz.webm -map 0 -map 1 red-a500hz.webm ``` +### WebP Test Files + +#### bouncy_ball.webp +An animated (extended) WebP encoded image of 450x450. Created by gildekel@ using Gimp. + +#### red_green_gradient_lossy.webp +A lossy WebP encoded image of 3000x3000. Created by gildekel@ using Gimp. + +#### yellow_pink_gradient_lossless.webp +A lossless WebP encoded image of 3000x3000. Created by gildekel@ using Gimp. + ### JPEG Test Files #### pixel-1280x720.jpg
diff --git a/media/test/data/bouncy_ball.webp b/media/test/data/bouncy_ball.webp new file mode 100644 index 0000000..dfa9399b --- /dev/null +++ b/media/test/data/bouncy_ball.webp Binary files differ
diff --git a/media/test/data/red_green_gradient_lossy.webp b/media/test/data/red_green_gradient_lossy.webp new file mode 100644 index 0000000..45417528 --- /dev/null +++ b/media/test/data/red_green_gradient_lossy.webp Binary files differ
diff --git a/media/test/data/yellow_pink_gradient_lossless.webp b/media/test/data/yellow_pink_gradient_lossless.webp new file mode 100644 index 0000000..4b6b98c --- /dev/null +++ b/media/test/data/yellow_pink_gradient_lossless.webp Binary files differ
diff --git a/net/cert/ct_log_verifier.cc b/net/cert/ct_log_verifier.cc index f82649a..e255cae 100644 --- a/net/cert/ct_log_verifier.cc +++ b/net/cert/ct_log_verifier.cc
@@ -59,23 +59,19 @@ // static scoped_refptr<const CTLogVerifier> CTLogVerifier::Create( const base::StringPiece& public_key, - std::string description, - std::string dns_domain) { + std::string description) { scoped_refptr<CTLogVerifier> result( - new CTLogVerifier(std::move(description), std::move(dns_domain))); + new CTLogVerifier(std::move(description))); if (!result->Init(public_key)) return nullptr; return result; } -CTLogVerifier::CTLogVerifier(std::string description, std::string dns_domain) +CTLogVerifier::CTLogVerifier(std::string description) : description_(std::move(description)), - dns_domain_(std::move(dns_domain)), hash_algorithm_(ct::DigitallySigned::HASH_ALGO_NONE), signature_algorithm_(ct::DigitallySigned::SIG_ALGO_ANONYMOUS), - public_key_(nullptr) { - DCHECK(!dns_domain_.empty()); -} + public_key_(nullptr) {} bool CTLogVerifier::Verify(const ct::SignedEntryData& entry, const ct::SignedCertificateTimestamp& sct) const {
diff --git a/net/cert/ct_log_verifier.h b/net/cert/ct_log_verifier.h index 395c381..fcc51189 100644 --- a/net/cert/ct_log_verifier.h +++ b/net/cert/ct_log_verifier.h
@@ -35,21 +35,15 @@ // using |public_key|, which is a DER-encoded SubjectPublicKeyInfo. // If |public_key| refers to an unsupported public key, returns NULL. // |description| is a textual description of the log. - // |dns_domain| is the DNS name of the log's DNS API endpoint, if one exists. static scoped_refptr<const CTLogVerifier> Create( const base::StringPiece& public_key, - std::string description, - std::string dns_domain); + std::string description); // Returns the log's key ID (RFC6962, Section 3.2) const std::string& key_id() const { return key_id_; } // Returns the log's human-readable description. const std::string& description() const { return description_; } - // Returns the log's DNS domain for CT over DNS queries, as described in - // https://github.com/google/certificate-transparency-rfcs/blob/master/dns/draft-ct-over-dns.md. - const std::string& dns_domain() const { return dns_domain_; } - // Verifies that |sct| is valid for |entry| and was signed by this log. bool Verify(const ct::SignedEntryData& entry, const ct::SignedCertificateTimestamp& sct) const; @@ -78,7 +72,7 @@ FRIEND_TEST_ALL_PREFIXES(CTLogVerifierTest, VerifySignature); friend class base::RefCountedThreadSafe<CTLogVerifier>; - CTLogVerifier(std::string description, std::string dns_domain); + explicit CTLogVerifier(std::string description); ~CTLogVerifier(); // Performs crypto-library specific initialization. @@ -96,7 +90,6 @@ std::string key_id_; std::string description_; - std::string dns_domain_; ct::DigitallySigned::HashAlgorithm hash_algorithm_; ct::DigitallySigned::SignatureAlgorithm signature_algorithm_;
diff --git a/net/cert/ct_log_verifier_unittest.cc b/net/cert/ct_log_verifier_unittest.cc index fb95e22c..dcdc6ced 100644 --- a/net/cert/ct_log_verifier_unittest.cc +++ b/net/cert/ct_log_verifier_unittest.cc
@@ -204,12 +204,10 @@ class CTLogVerifierTest : public ::testing::Test { public: void SetUp() override { - log_ = CTLogVerifier::Create(ct::GetTestPublicKey(), "testlog", - "ct.example.com"); + log_ = CTLogVerifier::Create(ct::GetTestPublicKey(), "testlog"); ASSERT_TRUE(log_); EXPECT_EQ(ct::GetTestPublicKeyId(), log_->key_id()); - EXPECT_EQ("ct.example.com", log_->dns_domain()); } protected: @@ -467,7 +465,7 @@ key += "extra"; scoped_refptr<const CTLogVerifier> log = - CTLogVerifier::Create(key, "testlog", "ct.example.com"); + CTLogVerifier::Create(key, "testlog"); EXPECT_FALSE(log); }
diff --git a/net/cert/ct_objects_extractor_unittest.cc b/net/cert/ct_objects_extractor_unittest.cc index ce1a7284..57028a3 100644 --- a/net/cert/ct_objects_extractor_unittest.cc +++ b/net/cert/ct_objects_extractor_unittest.cc
@@ -32,8 +32,7 @@ der_test_cert.length()); ASSERT_TRUE(test_cert_); - log_ = CTLogVerifier::Create(ct::GetTestPublicKey(), "testlog", - "dns.example.com"); + log_ = CTLogVerifier::Create(ct::GetTestPublicKey(), "testlog"); ASSERT_TRUE(log_); }
diff --git a/net/cert/ct_verifier.h b/net/cert/ct_verifier.h index 0368044..63c0923b 100644 --- a/net/cert/ct_verifier.h +++ b/net/cert/ct_verifier.h
@@ -17,24 +17,6 @@ // Interface for verifying Signed Certificate Timestamps over a certificate. class NET_EXPORT CTVerifier { public: - class NET_EXPORT Observer { - public: - // Called for each Signed Certificate Timestamp from a known log that vas - // verified successfully (i.e. the signature verifies). |sct| is the - // Signed Certificate Timestamp, |cert| is the certificate it applies to and - // |hostname| is the server that presented the certificate (DNS name or IP - // address literal). The certificate is needed to calculate the hash of the - // log entry, necessary for checking inclusion in the log. - // Note: The observer (whose implementation is expected to exist outside - // net/) may store the observed |cert| and |sct|. - virtual void OnSCTVerified(base::StringPiece hostname, - X509Certificate* cert, - const ct::SignedCertificateTimestamp* sct) = 0; - - protected: - virtual ~Observer() {} - }; - virtual ~CTVerifier() {} // Verifies SCTs embedded in the certificate itself, SCTs embedded in a @@ -56,16 +38,6 @@ base::StringPiece sct_list_from_tls_extension, SignedCertificateTimestampAndStatusList* output_scts, const NetLogWithSource& net_log) = 0; - - // Registers |observer| to receive notifications of validated SCTs. Does not - // take ownership of the observer as the observer may be performing - // URLRequests which have to be cancelled before this object is destroyed. - // Setting |observer| to nullptr has the effect of stopping all notifications. - virtual void SetObserver(Observer* observer) = 0; - - // Gets the Observer, if any, that is currently receiving notifications of - // validated SCTs. - virtual Observer* GetObserver() const = 0; }; } // namespace net
diff --git a/net/cert/do_nothing_ct_verifier.cc b/net/cert/do_nothing_ct_verifier.cc index 63b9c0a..596c8e7 100644 --- a/net/cert/do_nothing_ct_verifier.cc +++ b/net/cert/do_nothing_ct_verifier.cc
@@ -21,10 +21,4 @@ output_scts->clear(); } -void DoNothingCTVerifier::SetObserver(Observer* observer) {} - -CTVerifier::Observer* DoNothingCTVerifier::GetObserver() const { - return nullptr; -} - } // namespace net
diff --git a/net/cert/do_nothing_ct_verifier.h b/net/cert/do_nothing_ct_verifier.h index 1aad260..64eacf32 100644 --- a/net/cert/do_nothing_ct_verifier.h +++ b/net/cert/do_nothing_ct_verifier.h
@@ -57,9 +57,6 @@ SignedCertificateTimestampAndStatusList* output_scts, const NetLogWithSource& net_log) override; - void SetObserver(Observer* observer) override; - Observer* GetObserver() const override; - private: DISALLOW_COPY_AND_ASSIGN(DoNothingCTVerifier); };
diff --git a/net/cert/multi_log_ct_verifier.cc b/net/cert/multi_log_ct_verifier.cc index eb9b1483..cd473fb 100644 --- a/net/cert/multi_log_ct_verifier.cc +++ b/net/cert/multi_log_ct_verifier.cc
@@ -54,8 +54,7 @@ } // namespace -MultiLogCTVerifier::MultiLogCTVerifier() : observer_(nullptr) { -} +MultiLogCTVerifier::MultiLogCTVerifier() {} MultiLogCTVerifier::~MultiLogCTVerifier() = default; @@ -67,14 +66,6 @@ } } -void MultiLogCTVerifier::SetObserver(Observer* observer) { - observer_ = observer; -} - -CTVerifier::Observer* MultiLogCTVerifier::GetObserver() const { - return observer_; -} - void MultiLogCTVerifier::Verify( base::StringPiece hostname, X509Certificate* cert, @@ -213,8 +204,6 @@ } AddSCTAndLogStatus(sct, ct::SCT_STATUS_OK, output_scts); - if (observer_) - observer_->OnSCTVerified(hostname, cert, sct.get()); return true; }
diff --git a/net/cert/multi_log_ct_verifier.h b/net/cert/multi_log_ct_verifier.h index af389d6..0d603eb 100644 --- a/net/cert/multi_log_ct_verifier.h +++ b/net/cert/multi_log_ct_verifier.h
@@ -42,9 +42,6 @@ SignedCertificateTimestampAndStatusList* output_scts, const NetLogWithSource& net_log) override; - void SetObserver(Observer* observer) override; - Observer* GetObserver() const override; - private: // Verify a list of SCTs from |encoded_sct_list| over |expected_entry|, // placing the verification results in |output_scts|. The SCTs in the list @@ -68,8 +65,6 @@ // of RFC6962. std::map<std::string, scoped_refptr<const CTLogVerifier>> logs_; - Observer* observer_; - DISALLOW_COPY_AND_ASSIGN(MultiLogCTVerifier); };
diff --git a/net/cert/multi_log_ct_verifier_unittest.cc b/net/cert/multi_log_ct_verifier_unittest.cc index e3e43f1..d935767 100644 --- a/net/cert/multi_log_ct_verifier_unittest.cc +++ b/net/cert/multi_log_ct_verifier_unittest.cc
@@ -41,19 +41,11 @@ const char kHostname[] = "example.com"; const char kLogDescription[] = "somelog"; -class MockSCTObserver : public CTVerifier::Observer { - public: - MOCK_METHOD3(OnSCTVerified, - void(base::StringPiece hostname, - X509Certificate* cert, - const ct::SignedCertificateTimestamp* sct)); -}; - class MultiLogCTVerifierTest : public ::testing::Test { public: void SetUp() override { - scoped_refptr<const CTLogVerifier> log(CTLogVerifier::Create( - ct::GetTestPublicKey(), kLogDescription, "dns.example.com")); + scoped_refptr<const CTLogVerifier> log( + CTLogVerifier::Create(ct::GetTestPublicKey(), kLogDescription)); ASSERT_TRUE(log); log_verifiers_.push_back(log); @@ -251,32 +243,6 @@ EXPECT_EQ(old_embedded_count + 1, NumEmbeddedSCTsInHistogram()); } -TEST_F(MultiLogCTVerifierTest, NotifiesOfValidSCT) { - MockSCTObserver observer; - verifier_->SetObserver(&observer); - - EXPECT_CALL(observer, OnSCTVerified(base::StringPiece(kHostname), - embedded_sct_chain_.get(), _)); - ASSERT_TRUE(VerifySinglePrecertificateChain(embedded_sct_chain_)); -} - -TEST_F(MultiLogCTVerifierTest, StopsNotifyingCorrectly) { - MockSCTObserver observer; - verifier_->SetObserver(&observer); - - EXPECT_CALL(observer, OnSCTVerified(base::StringPiece(kHostname), - embedded_sct_chain_.get(), _)) - .Times(1); - ASSERT_TRUE(VerifySinglePrecertificateChain(embedded_sct_chain_)); - Mock::VerifyAndClearExpectations(&observer); - - EXPECT_CALL(observer, OnSCTVerified(base::StringPiece(kHostname), - embedded_sct_chain_.get(), _)) - .Times(0); - verifier_->SetObserver(nullptr); - ASSERT_TRUE(VerifySinglePrecertificateChain(embedded_sct_chain_)); -} - } // namespace } // namespace net
diff --git a/net/dns/context_host_resolver.cc b/net/dns/context_host_resolver.cc index 9423f1d..34ce64e 100644 --- a/net/dns/context_host_resolver.cc +++ b/net/dns/context_host_resolver.cc
@@ -135,20 +135,6 @@ return host_cache_.get(); } -bool ContextHostResolver::HasCached(base::StringPiece hostname, - HostCache::Entry::Source* source_out, - HostCache::EntryStaleness* stale_out, - bool* secure_out) const { - if (!host_cache_) - return false; - - const HostCache::Key* key = - host_cache_->GetMatchingKey(hostname, source_out, stale_out); - if (key && secure_out != nullptr) - *secure_out = key->secure; - return !!key; -} - std::unique_ptr<base::Value> ContextHostResolver::GetDnsConfigAsValue() const { return manager_->GetDnsConfigAsValue(); }
diff --git a/net/dns/context_host_resolver.h b/net/dns/context_host_resolver.h index e6b5cf5..722bdcb7 100644 --- a/net/dns/context_host_resolver.h +++ b/net/dns/context_host_resolver.h
@@ -52,10 +52,6 @@ const HostPortPair& host, DnsQueryType query_type) override; HostCache* GetHostCache() override; - bool HasCached(base::StringPiece hostname, - HostCache::Entry::Source* source_out, - HostCache::EntryStaleness* stale_out, - bool* secure_out) const override; std::unique_ptr<base::Value> GetDnsConfigAsValue() const override; void SetRequestContext(URLRequestContext* request_context) override; HostResolverManager* GetManagerForTesting() override;
diff --git a/net/dns/host_resolver.h b/net/dns/host_resolver.h index 69a5d4f8..418a0e95 100644 --- a/net/dns/host_resolver.h +++ b/net/dns/host_resolver.h
@@ -277,18 +277,6 @@ // Used primarily to clear the cache and for getting debug information. virtual HostCache* GetHostCache(); - // Checks whether this HostResolver has cached a resolution for the given - // hostname (or IP address literal). If so, returns true and writes the source - // of the resolution (e.g. DNS, HOSTS file, etc.) to |source_out|, the - // staleness of the resolution to |stale_out|, and whether the result was - // retrieved securely or not to |secure_out| (if they are not null). It tries - // using two common address_family and host_resolver_flag combinations when - // checking the cache; this means false negatives are possible, but unlikely. - virtual bool HasCached(base::StringPiece hostname, - HostCache::Entry::Source* source_out, - HostCache::EntryStaleness* stale_out, - bool* secure_out) const = 0; - // Returns the current DNS configuration |this| is using, as a Value, or // nullptr if it's configured to always use the system host resolver. virtual std::unique_ptr<base::Value> GetDnsConfigAsValue() const;
diff --git a/net/dns/mapped_host_resolver.cc b/net/dns/mapped_host_resolver.cc index 182958a..af5525ab 100644 --- a/net/dns/mapped_host_resolver.cc +++ b/net/dns/mapped_host_resolver.cc
@@ -75,13 +75,6 @@ return impl_->GetHostCache(); } -bool MappedHostResolver::HasCached(base::StringPiece hostname, - HostCache::Entry::Source* source_out, - HostCache::EntryStaleness* stale_out, - bool* secure_out) const { - return impl_->HasCached(hostname, source_out, stale_out, secure_out); -} - std::unique_ptr<base::Value> MappedHostResolver::GetDnsConfigAsValue() const { return impl_->GetDnsConfigAsValue(); }
diff --git a/net/dns/mapped_host_resolver.h b/net/dns/mapped_host_resolver.h index ca8c9f0..ced94f2 100644 --- a/net/dns/mapped_host_resolver.h +++ b/net/dns/mapped_host_resolver.h
@@ -54,10 +54,6 @@ const base::Optional<ResolveHostParameters>& optional_parameters) override; HostCache* GetHostCache() override; - bool HasCached(base::StringPiece hostname, - HostCache::Entry::Source* source_out, - HostCache::EntryStaleness* stale_out, - bool* secure_out) const override; std::unique_ptr<base::Value> GetDnsConfigAsValue() const override; void SetRequestContext(URLRequestContext* request_context) override; HostResolverManager* GetManagerForTesting() override;
diff --git a/net/dns/mock_host_resolver.cc b/net/dns/mock_host_resolver.cc index b019d3f..f91f86a 100644 --- a/net/dns/mock_host_resolver.cc +++ b/net/dns/mock_host_resolver.cc
@@ -290,20 +290,6 @@ return cache_.get(); } -bool MockHostResolverBase::HasCached(base::StringPiece hostname, - HostCache::Entry::Source* source_out, - HostCache::EntryStaleness* stale_out, - bool* secure_out) const { - if (!cache_) - return false; - - const HostCache::Key* key = - cache_->GetMatchingKey(hostname, source_out, stale_out); - if (key && secure_out != nullptr) - *secure_out = key->secure; - return !!key; -} - int MockHostResolverBase::LoadIntoCache( const HostPortPair& host, const base::Optional<ResolveHostParameters>& optional_parameters) { @@ -956,13 +942,6 @@ is_local_only); } -bool HangingHostResolver::HasCached(base::StringPiece hostname, - HostCache::Entry::Source* source_out, - HostCache::EntryStaleness* stale_out, - bool* secure_out) const { - return false; -} - //----------------------------------------------------------------------------- ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc() = default;
diff --git a/net/dns/mock_host_resolver.h b/net/dns/mock_host_resolver.h index c653bcf89..8215f76 100644 --- a/net/dns/mock_host_resolver.h +++ b/net/dns/mock_host_resolver.h
@@ -121,10 +121,6 @@ const HostPortPair& host, DnsQueryType query_type) override; HostCache* GetHostCache() override; - bool HasCached(base::StringPiece hostname, - HostCache::Entry::Source* source_out, - HostCache::EntryStaleness* stale_out, - bool* secure_out) const override; void SetRequestContext(URLRequestContext* request_context) override {} // Preloads the cache with what would currently be the result of a request @@ -447,10 +443,6 @@ const NetLogWithSource& net_log, const base::Optional<ResolveHostParameters>& optional_parameters) override; - bool HasCached(base::StringPiece hostname, - HostCache::Entry::Source* source_out, - HostCache::EntryStaleness* stale_out, - bool* secure_out) const override; // Use to detect cancellations since there's otherwise no externally-visible // differentiation between a cancelled and a hung task.
diff --git a/net/http/http_auth_cache.cc b/net/http/http_auth_cache.cc index 8c399be6..6a36b9fb 100644 --- a/net/http/http_auth_cache.cc +++ b/net/http/http_auth_cache.cc
@@ -45,9 +45,7 @@ // Debug helper to check that |origin| arguments are properly formed. void CheckOriginIsValid(const GURL& origin) { DCHECK(origin.is_valid()); - // Note that the scheme may be FTP when we're using a HTTP proxy. - DCHECK(origin.SchemeIsHTTPOrHTTPS() || origin.SchemeIs("ftp") || - origin.SchemeIsWSOrWSS()); + DCHECK(origin.SchemeIsHTTPOrHTTPS() || origin.SchemeIsWSOrWSS()); DCHECK(origin.GetOrigin() == origin); }
diff --git a/net/http/http_stream_factory_job.cc b/net/http/http_stream_factory_job.cc index ababbde0..e176dfd 100644 --- a/net/http/http_stream_factory_job.cc +++ b/net/http/http_stream_factory_job.cc
@@ -1084,11 +1084,9 @@ if (!using_spdy_) { DCHECK(!expect_spdy_); - // We may get ftp scheme when fetching ftp resources through proxy. bool using_proxy = (proxy_info_.is_http() || proxy_info_.is_https() || proxy_info_.is_quic()) && - (request_info_.url.SchemeIs(url::kHttpScheme) || - request_info_.url.SchemeIs(url::kFtpScheme)); + request_info_.url.SchemeIs(url::kHttpScheme); if (is_websocket_) { DCHECK_NE(job_type_, PRECONNECT); DCHECK(delegate_->websocket_handshake_stream_create_helper());
diff --git a/net/http/http_util.cc b/net/http/http_util.cc index 3c315672..e6331a7 100644 --- a/net/http/http_util.cc +++ b/net/http/http_util.cc
@@ -83,9 +83,8 @@ // static std::string HttpUtil::SpecForRequest(const GURL& url) { - // We may get ftp scheme when fetching ftp resources through proxy. - DCHECK(url.is_valid() && (url.SchemeIsHTTPOrHTTPS() || url.SchemeIs("ftp") || - url.SchemeIsWSOrWSS())); + DCHECK(url.is_valid() && + (url.SchemeIsHTTPOrHTTPS() || url.SchemeIsWSOrWSS())); return SimplifyUrlForRequest(url).spec(); }
diff --git a/net/http/http_util_unittest.cc b/net/http/http_util_unittest.cc index 74674f81..d8d316ca 100644 --- a/net/http/http_util_unittest.cc +++ b/net/http/http_util_unittest.cc
@@ -734,13 +734,6 @@ } } -// Test SpecForRequest() for "ftp" scheme. -TEST(HttpUtilTest, SpecForRequestForUrlWithFtpScheme) { - GURL ftp_url("ftp://user:pass@google.com/pub/chromium/"); - EXPECT_EQ("ftp://google.com/pub/chromium/", - HttpUtil::SpecForRequest(ftp_url)); -} - TEST(HttpUtilTest, GenerateAcceptLanguageHeader) { std::string header = HttpUtil::GenerateAcceptLanguageHeader(""); EXPECT_TRUE(header.empty());
diff --git a/net/quic/crypto/proof_verifier_chromium_test.cc b/net/quic/crypto/proof_verifier_chromium_test.cc index f1c498f..591f37eb 100644 --- a/net/quic/crypto/proof_verifier_chromium_test.cc +++ b/net/quic/crypto/proof_verifier_chromium_test.cc
@@ -123,8 +123,8 @@ .WillRepeatedly( Return(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS)); - scoped_refptr<const CTLogVerifier> log(CTLogVerifier::Create( - ct::GetTestPublicKey(), kLogDescription, "dns.example.com")); + scoped_refptr<const CTLogVerifier> log( + CTLogVerifier::Create(ct::GetTestPublicKey(), kLogDescription)); ASSERT_TRUE(log); log_verifiers_.push_back(log);
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc index bbc13ab8..f07bdcd 100644 --- a/net/socket/ssl_client_socket_unittest.cc +++ b/net/socket/ssl_client_socket_unittest.cc
@@ -766,8 +766,6 @@ base::StringPiece, SignedCertificateTimestampAndStatusList*, const NetLogWithSource&)); - MOCK_METHOD1(SetObserver, void(CTVerifier::Observer*)); - MOCK_CONST_METHOD0(GetObserver, CTVerifier::Observer*()); }; // A mock CTPolicyEnforcer that returns a custom verification result.
diff --git a/services/device/usb/usb_configuration_android.cc b/services/device/usb/usb_configuration_android.cc index 2b99d72..9274d9c2 100644 --- a/services/device/usb/usb_configuration_android.cc +++ b/services/device/usb/usb_configuration_android.cc
@@ -24,13 +24,10 @@ Java_ChromeUsbConfiguration_isRemoteWakeup(env, wrapper), Java_ChromeUsbConfiguration_getMaxPower(env, wrapper)); - ScopedJavaLocalRef<jobjectArray> interfaces = - Java_ChromeUsbConfiguration_getInterfaces(env, wrapper); - jsize count = env->GetArrayLength(interfaces.obj()); - config.interfaces.reserve(count); - for (jsize i = 0; i < count; ++i) { - ScopedJavaLocalRef<jobject> interface( - env, env->GetObjectArrayElement(interfaces.obj(), i)); + base::android::JavaObjectArrayReader<jobject> interfaces( + Java_ChromeUsbConfiguration_getInterfaces(env, wrapper)); + config.interfaces.reserve(interfaces.size()); + for (auto interface : interfaces) { config.interfaces.push_back(UsbInterfaceAndroid::Convert(env, interface)); }
diff --git a/services/device/usb/usb_device_android.cc b/services/device/usb/usb_device_android.cc index 25fe940..de98b43fc 100644 --- a/services/device/usb/usb_device_android.cc +++ b/services/device/usb/usb_device_android.cc
@@ -18,6 +18,7 @@ #include "services/device/usb/webusb_descriptors.h" using base::android::ConvertJavaStringToUTF16; +using base::android::JavaObjectArrayReader; using base::android::JavaRef; using base::android::ScopedJavaLocalRef; @@ -131,13 +132,10 @@ j_object_(wrapper) { if (base::android::BuildInfo::GetInstance()->sdk_int() >= base::android::SDK_VERSION_LOLLIPOP) { - ScopedJavaLocalRef<jobjectArray> configurations = - Java_ChromeUsbDevice_getConfigurations(env, j_object_); - jsize count = env->GetArrayLength(configurations.obj()); - descriptor_.configurations.reserve(count); - for (jsize i = 0; i < count; ++i) { - ScopedJavaLocalRef<jobject> config( - env, env->GetObjectArrayElement(configurations.obj(), i)); + JavaObjectArrayReader<jobject> configurations( + Java_ChromeUsbDevice_getConfigurations(env, j_object_)); + descriptor_.configurations.reserve(configurations.size()); + for (auto config : configurations) { descriptor_.configurations.push_back( UsbConfigurationAndroid::Convert(env, config)); } @@ -149,13 +147,10 @@ false, // Remote wakeup, rbitrary default. 0); // Maximum power, aitrary default. - ScopedJavaLocalRef<jobjectArray> interfaces = - Java_ChromeUsbDevice_getInterfaces(env, wrapper); - jsize count = env->GetArrayLength(interfaces.obj()); - config.interfaces.reserve(count); - for (jsize i = 0; i < count; ++i) { - ScopedJavaLocalRef<jobject> interface( - env, env->GetObjectArrayElement(interfaces.obj(), i)); + JavaObjectArrayReader<jobject> interfaces( + Java_ChromeUsbDevice_getInterfaces(env, wrapper)); + config.interfaces.reserve(interfaces.size()); + for (auto interface : interfaces) { config.interfaces.push_back(UsbInterfaceAndroid::Convert(env, interface)); } descriptor_.configurations.push_back(config);
diff --git a/services/device/usb/usb_interface_android.cc b/services/device/usb/usb_interface_android.cc index 6e2f347..7cd8ab00 100644 --- a/services/device/usb/usb_interface_android.cc +++ b/services/device/usb/usb_interface_android.cc
@@ -33,13 +33,10 @@ Java_ChromeUsbInterface_getInterfaceSubclass(env, wrapper), Java_ChromeUsbInterface_getInterfaceProtocol(env, wrapper)); - ScopedJavaLocalRef<jobjectArray> endpoints = - Java_ChromeUsbInterface_getEndpoints(env, wrapper); - jsize count = env->GetArrayLength(endpoints.obj()); - interface.endpoints.reserve(count); - for (jsize i = 0; i < count; ++i) { - ScopedJavaLocalRef<jobject> endpoint( - env, env->GetObjectArrayElement(endpoints.obj(), i)); + base::android::JavaObjectArrayReader<jobject> endpoints( + Java_ChromeUsbInterface_getEndpoints(env, wrapper)); + interface.endpoints.reserve(endpoints.size()); + for (auto endpoint : endpoints) { interface.endpoints.push_back(UsbEndpointAndroid::Convert(env, endpoint)); }
diff --git a/services/device/usb/usb_service_android.cc b/services/device/usb/usb_service_android.cc index 7a57ca8d..8881282 100644 --- a/services/device/usb/usb_service_android.cc +++ b/services/device/usb/usb_service_android.cc
@@ -26,10 +26,7 @@ Java_ChromeUsbService_create(env, reinterpret_cast<jlong>(this))); ScopedJavaLocalRef<jobjectArray> devices = Java_ChromeUsbService_getDevices(env, j_object_); - jsize length = env->GetArrayLength(devices.obj()); - for (jsize i = 0; i < length; ++i) { - ScopedJavaLocalRef<jobject> usb_device( - env, env->GetObjectArrayElement(devices.obj(), i)); + for (auto usb_device : devices.ReadElements<jobject>()) { scoped_refptr<UsbDeviceAndroid> device = UsbDeviceAndroid::Create(env, weak_factory_.GetWeakPtr(), usb_device); AddDevice(device);
diff --git a/services/network/BUILD.gn b/services/network/BUILD.gn index e895fb2..1157afba 100644 --- a/services/network/BUILD.gn +++ b/services/network/BUILD.gn
@@ -392,10 +392,7 @@ ] if (is_ct_supported) { - sources += [ - "expect_ct_reporter_unittest.cc", - "network_context_cert_transparency_unittest.cc", - ] + sources += [ "expect_ct_reporter_unittest.cc" ] deps += [ "//components/certificate_transparency" ] } }
diff --git a/services/network/network_context.cc b/services/network/network_context.cc index 85c9073..6082e82 100644 --- a/services/network/network_context.cc +++ b/services/network/network_context.cc
@@ -93,10 +93,6 @@ #include "components/certificate_transparency/chrome_ct_policy_enforcer.h" #include "components/certificate_transparency/chrome_require_ct_delegate.h" #include "components/certificate_transparency/ct_known_logs.h" -#include "components/certificate_transparency/features.h" -#include "components/certificate_transparency/sth_distributor.h" -#include "components/certificate_transparency/sth_reporter.h" -#include "components/certificate_transparency/tree_state_tracker.h" #include "net/cert/ct_log_verifier.h" #include "net/cert/multi_log_ct_verifier.h" #include "services/network/expect_ct_reporter.h" @@ -648,19 +644,6 @@ } #endif // BUILDFLAG(IS_CT_SUPPORTED) } - -#if BUILDFLAG(IS_CT_SUPPORTED) - if (url_request_context_ && - url_request_context_->cert_transparency_verifier()) { - url_request_context_->cert_transparency_verifier()->SetObserver(nullptr); - } - - if (network_service_ && network_service_->sth_reporter() && - ct_tree_tracker_) { - network_service_->sth_reporter()->UnregisterObserver( - ct_tree_tracker_.get()); - } -#endif // BUILDFLAG(IS_CT_SUPPORTED) } void NetworkContext::SetCertVerifierForTesting( @@ -1930,8 +1913,7 @@ if (!params_->ct_logs.empty()) { for (const auto& log : params_->ct_logs) { scoped_refptr<const net::CTLogVerifier> log_verifier = - net::CTLogVerifier::Create(log->public_key, log->name, - log->dns_api_endpoint); + net::CTLogVerifier::Create(log->public_key, log->name); if (!log_verifier) { // TODO: Signal bad configuration (such as bad key). continue; @@ -2014,16 +1996,6 @@ expect_ct_reporter_.get()); } - if (base::FeatureList::IsEnabled(certificate_transparency::kCTLogAuditing) && - network_service_ && !ct_logs.empty()) { - net::URLRequestContext* context = result.url_request_context.get(); - ct_tree_tracker_ = - std::make_unique<certificate_transparency::TreeStateTracker>( - ct_logs, context->host_resolver(), context, net_log); - context->cert_transparency_verifier()->SetObserver(ct_tree_tracker_.get()); - network_service_->sth_reporter()->RegisterObserver(ct_tree_tracker_.get()); - } - if (params_->enforce_chrome_ct_policy) { require_ct_delegate_ = std::make_unique<certificate_transparency::ChromeRequireCTDelegate>();
diff --git a/services/network/network_context.h b/services/network/network_context.h index 46183aee..05309f98 100644 --- a/services/network/network_context.h +++ b/services/network/network_context.h
@@ -66,7 +66,6 @@ namespace certificate_transparency { class ChromeRequireCTDelegate; -class TreeStateTracker; } // namespace certificate_transparency namespace domain_reliability { @@ -550,7 +549,6 @@ std::queue<SetExpectCTTestReportCallback> outstanding_set_expect_ct_callbacks_; - std::unique_ptr<certificate_transparency::TreeStateTracker> ct_tree_tracker_; #endif // BUILDFLAG(IS_CT_SUPPORTED) #if defined(OS_CHROMEOS)
diff --git a/services/network/network_context_cert_transparency_unittest.cc b/services/network/network_context_cert_transparency_unittest.cc deleted file mode 100644 index 868b466c..0000000 --- a/services/network/network_context_cert_transparency_unittest.cc +++ /dev/null
@@ -1,439 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <memory> - -#include "base/base64.h" -#include "base/bind.h" -#include "base/callback_helpers.h" -#include "base/memory/ref_counted.h" -#include "base/stl_util.h" -#include "base/strings/string_piece.h" -#include "base/test/gtest_util.h" -#include "base/test/metrics/histogram_tester.h" -#include "base/test/scoped_feature_list.h" -#include "base/test/scoped_task_environment.h" -#include "components/certificate_transparency/features.h" -#include "components/certificate_transparency/single_tree_tracker.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "net/base/address_list.h" -#include "net/base/ip_address.h" -#include "net/base/ip_endpoint.h" -#include "net/cert/cert_verify_result.h" -#include "net/cert/ct_policy_status.h" -#include "net/cert/ct_serialization.h" -#include "net/cert/ct_verifier.h" -#include "net/cert/mock_cert_verifier.h" -#include "net/cert/signed_certificate_timestamp.h" -#include "net/cert/signed_tree_head.h" -#include "net/cert/x509_certificate.h" -#include "net/dns/host_cache.h" -#include "net/dns/host_resolver.h" -#include "net/proxy_resolution/proxy_config_with_annotation.h" -#include "net/test/cert_test_util.h" -#include "net/test/ct_test_util.h" -#include "net/test/embedded_test_server/embedded_test_server.h" -#include "net/test/test_data_directory.h" -#include "net/traffic_annotation/network_traffic_annotation_test_helper.h" -#include "net/url_request/url_request_context.h" -#include "services/network/network_context.h" -#include "services/network/network_service.h" -#include "services/network/public/cpp/features.h" -#include "services/network/public/mojom/ct_log_info.mojom.h" -#include "services/network/public/mojom/network_service.mojom.h" -#include "services/network/public/mojom/proxy_config.mojom.h" -#include "services/network/test/test_url_loader_client.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace network { - -namespace { - -mojom::NetworkContextParamsPtr CreateContextParams() { - mojom::NetworkContextParamsPtr params = mojom::NetworkContextParams::New(); - - // Use a fixed proxy config, to avoid dependencies on local network - // configuration. - params->initial_proxy_config = net::ProxyConfigWithAnnotation::CreateDirect(); - - // Configure Certificate Transparency for the context. - // TODO(robpercival): https://crbug.com/839612 - Use test logs for - // integration tests rather than production logs. - const char kPilotKey[] = - "\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86" - "\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x7d\xa8\x4b\x12\x29\x80\xa3" - "\x3d\xad\xd3\x5a\x77\xb8\xcc\xe2\x88\xb3\xa5\xfd\xf1\xd3\x0c\xcd\x18" - "\x0c\xe8\x41\x46\xe8\x81\x01\x1b\x15\xe1\x4b\xf1\x1b\x62\xdd\x36\x0a" - "\x08\x18\xba\xed\x0b\x35\x84\xd0\x9e\x40\x3c\x2d\x9e\x9b\x82\x65\xbd" - "\x1f\x04\x10\x41\x4c\xa0"; - const char kAviatorKey[] = - "\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86" - "\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xd7\xf4\xcc\x69\xb2\xe4\x0e" - "\x90\xa3\x8a\xea\x5a\x70\x09\x4f\xef\x13\x62\xd0\x8d\x49\x60\xff\x1b" - "\x40\x50\x07\x0c\x6d\x71\x86\xda\x25\x49\x8d\x65\xe1\x08\x0d\x47\x34" - "\x6b\xbd\x27\xbc\x96\x21\x3e\x34\xf5\x87\x76\x31\xb1\x7f\x1d\xc9\x85" - "\x3b\x0d\xf7\x1f\x3f\xe9"; - const char kDigiCertKey[] = - "\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86" - "\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x02\x46\xc5\xbe\x1b\xbb\x82" - "\x40\x16\xe8\xc1\xd2\xac\x19\x69\x13\x59\xf8\xf8\x70\x85\x46\x40\xb9" - "\x38\xb0\x23\x82\xa8\x64\x4c\x7f\xbf\xbb\x34\x9f\x4a\x5f\x28\x8a\xcf" - "\x19\xc4\x00\xf6\x36\x06\x93\x65\xed\x4c\xf5\xa9\x21\x62\x5a\xd8\x91" - "\xeb\x38\x24\x40\xac\xe8"; - params->ct_logs.push_back(network::mojom::CTLogInfo::New( - std::string(kPilotKey, base::size(kPilotKey) - 1), "Google 'Pilot' Log", - "pilot.ct.invalid")); - params->ct_logs.push_back(network::mojom::CTLogInfo::New( - std::string(kAviatorKey, base::size(kAviatorKey) - 1), - "Google 'Aviator' Log", "aviator.ct.invalid")); - params->ct_logs.push_back(network::mojom::CTLogInfo::New( - std::string(kDigiCertKey, base::size(kDigiCertKey) - 1), - "DigiCert Log Server", "digicert.ct.invalid")); - - return params; -} - -// TODO(robpercival): https://crbug.com/839612 - Make it easier to use a test -// cert that is not so tightly-coupled to production logs and STHs. -scoped_refptr<net::X509Certificate> GetCTCertForTesting() { - base::ScopedAllowBlockingForTesting allow_blocking_for_loading_cert; - return net::CreateCertificateChainFromFile( - net::GetTestCertsDirectory(), "comodo-chain.pem", - net::X509Certificate::FORMAT_PEM_CERT_SEQUENCE); -} - -// The number of valid SCTs in |GetCTCertForTesting| from logs configured in -// |CreateContextParams()|. -const size_t kNumSCTs = 3; - -// Decodes a base64-encoded "DigitallySigned" TLS struct into |*sig_out|. -// See https://tools.ietf.org/html/rfc5246#section-4.7. -// |sig_out| must not be null. -bool DecodeDigitallySigned(base::StringPiece base64_data, - net::ct::DigitallySigned* sig_out) { - std::string data; - if (!base::Base64Decode(base64_data, &data)) - return false; - - base::StringPiece data_ptr = data; - if (!net::ct::DecodeDigitallySigned(&data_ptr, sig_out)) - return false; - - return true; -} - -// Populates |*sth_out| with the given information. -// |sth_out| must not be null. -bool BuildSignedTreeHead(base::Time timestamp, - uint64_t tree_size, - base::StringPiece root_hash_base64, - base::StringPiece signature_base64, - base::StringPiece log_id_base64, - net::ct::SignedTreeHead* sth_out) { - sth_out->version = net::ct::SignedTreeHead::V1; - sth_out->timestamp = timestamp; - sth_out->tree_size = tree_size; - - std::string root_hash; - if (!base::Base64Decode(root_hash_base64, &root_hash)) { - return false; - } - root_hash.copy(sth_out->sha256_root_hash, net::ct::kSthRootHashLength); - - return DecodeDigitallySigned(signature_base64, &sth_out->signature) && - base::Base64Decode(log_id_base64, &sth_out->log_id); -} - -TEST(NetworkContextCertTransparencyAuditingDisabledTest, - SCTsAreNotCheckedForInclusion) { - base::test::ScopedTaskEnvironment scoped_task_environment( - base::test::ScopedTaskEnvironment::MainThreadType::IO); - - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndDisableFeature( - certificate_transparency::kCTLogAuditing); - - std::unique_ptr<NetworkService> network_service = - NetworkService::CreateForTesting(); - - // Override the CertVerifier, so that a 'real' cert can be simulated being - // returned by the net::TestServer. This should be done before creating the - // context. - net::MockCertVerifier mock_cert_verifier; - NetworkContext::SetCertVerifierForTesting(&mock_cert_verifier); - base::ScopedClosureRunner cleanup(base::BindOnce( - [] { NetworkContext::SetCertVerifierForTesting(nullptr); })); - - mojom::NetworkContextParamsPtr context_params = CreateContextParams(); - mojom::NetworkContextPtr network_context_ptr; - std::unique_ptr<NetworkContext> network_context = - std::make_unique<NetworkContext>(network_service.get(), - mojo::MakeRequest(&network_context_ptr), - std::move(context_params)); - - // Certificate Transparency should be configured, but there should be - // nothing listening for SCTs (such as the NetworkContext's ct_tree_tracker_). - ASSERT_TRUE( - network_context->url_request_context()->cert_transparency_verifier()); - EXPECT_FALSE(network_context->url_request_context() - ->cert_transparency_verifier() - ->GetObserver()); - - // Provide an STH from Google's Pilot log that can be used to prove - // inclusion for an SCT later in the test. - net::ct::SignedTreeHead pilot_sth; - ASSERT_TRUE(BuildSignedTreeHead( - base::Time::FromJsTime(1512419914170), 181871752, - "bvgljSy3Yg32Y6J8qL5WmUA3jn2WnOrEFDqxD0AxUvs=", - "BAMARjBEAiAwEXve2RBk3XkUR+6nACSETTgzKFaEeginxuj5U9BI/" - "wIgBPuQS5ACxsro6TtpY4bQyE6WlMdcSMiMd/SSGraOBOg=", - "pLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BA=", &pilot_sth)); - network_service->UpdateSignedTreeHead(pilot_sth); - - // Provide an STH from Google's Aviator log that is not recent enough to - // prove inclusion for an SCT later in the test. - net::ct::SignedTreeHead aviator_sth; - ASSERT_TRUE(BuildSignedTreeHead( - base::Time::FromJsTime(1442652106945), 8502329, - "bfG+gWZcHl9fqtNo0Z/uggs8E5YqGOtJQ0Z5zVZDRxI=", - "BAMARjBEAiA6elcNQoShmKLHj/" - "IA649UIbaQtWJEpj0Eot0q7G6fEgIgYChb7U6Reuvt0nO5PionH+3UciOxKV3Cy8/" - "eq59lSYY=", - "aPaY+B9kgr46jO65KB1M/HFRXWeT1ETRCmesu09P+8Q=", &aviator_sth)); - network_service->UpdateSignedTreeHead(aviator_sth); - - // Start a test server on "localhost" and configure connections to it to - // simulate using a real certificate. - net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); - ASSERT_TRUE(https_server.Start()); - - // Configure "localhost" to be treated as if it went through DNS. This - // modifies the HostCache directly to simulate it being cached, rather than - // indirecting through a scoped HostResolverProc, as queries that use - // HostResolverProcs are treated as SOURCE_UNKNOWN, rather than SOURCE_DNS. - net::AddressList address_list; - ASSERT_TRUE(https_server.GetAddressList(&address_list)); - - net::HostCache* host_cache = - network_context->url_request_context()->host_resolver()->GetHostCache(); - ASSERT_TRUE(host_cache); - host_cache->Set( - net::HostCache::Key("localhost", net::ADDRESS_FAMILY_UNSPECIFIED, 0), - net::HostCache::Entry(net::OK, address_list, - net::HostCache::Entry::SOURCE_DNS), - base::TimeTicks::Now(), base::TimeDelta()); - - // This certificate contains 3 SCTs and fulfills the Chrome CT policy. - // Simulate it being trusted by a known root, as otherwise CT is skipped for - // private roots. - net::CertVerifyResult verify_result; - verify_result.is_issued_by_known_root = true; - verify_result.cert_status = 0; - verify_result.verified_cert = GetCTCertForTesting(); - ASSERT_TRUE(verify_result.verified_cert); - mock_cert_verifier.AddResultForCert(https_server.GetCertificate(), - verify_result, net::OK); - - ResourceRequest request; - request.url = https_server.GetURL("localhost", "/"); - request.method = "GET"; - request.request_initiator = url::Origin(); - - mojom::URLLoaderFactoryPtr loader_factory; - auto url_loader_factory_params = - network::mojom::URLLoaderFactoryParams::New(); - url_loader_factory_params->process_id = network::mojom::kBrowserProcessId; - url_loader_factory_params->is_corb_enabled = false; - network_context->CreateURLLoaderFactory(mojo::MakeRequest(&loader_factory), - std::move(url_loader_factory_params)); - - base::HistogramTester histograms; - mojom::URLLoaderPtr loader; - TestURLLoaderClient client; - int options = mojom::kURLLoadOptionSendSSLInfoWithResponse | - mojom::kURLLoadOptionSendSSLInfoForCertificateError; - loader_factory->CreateLoaderAndStart( - mojo::MakeRequest(&loader), 0 /* routing_id */, 0 /* request_id */, - options, request, client.CreateInterfacePtr(), - net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS)); - - client.RunUntilComplete(); - EXPECT_TRUE(client.has_received_response()); - EXPECT_TRUE(client.has_received_completion()); - - // Expect a successful connection. - EXPECT_EQ(net::OK, client.completion_status().error_code); - - // Expect 3 SCTs in this connection. - ASSERT_TRUE(client.ssl_info().has_value()); - ASSERT_EQ(kNumSCTs, client.ssl_info()->signed_certificate_timestamps.size()); - - // Expect that all SCTs were embedded in the certificate. - size_t embedded_scts = 0; - for (const auto& sct : client.ssl_info()->signed_certificate_timestamps) { - if (sct.sct->origin == net::ct::SignedCertificateTimestamp::SCT_EMBEDDED) - ++embedded_scts; - } - ASSERT_EQ(kNumSCTs, embedded_scts); - - // No SCTs should be eligible for inclusion checking, as inclusion checking - // is disabled. - histograms.ExpectTotalCount( - "Net.CertificateTransparency.CanInclusionCheckSCT", 0); -} - -TEST(NetworkContextCertTransparencyAuditingEnabledTest, - SCTsAreCheckedForInclusion) { - base::test::ScopedTaskEnvironment scoped_task_environment( - base::test::ScopedTaskEnvironment::MainThreadType::IO); - - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature( - certificate_transparency::kCTLogAuditing); - - std::unique_ptr<NetworkService> network_service = - NetworkService::CreateForTesting(); - - // Override the CertVerifier, so that a 'real' cert can be simulated being - // returned by the net::TestServer. This should be done before creating the - // context. - net::MockCertVerifier mock_cert_verifier; - NetworkContext::SetCertVerifierForTesting(&mock_cert_verifier); - base::ScopedClosureRunner cleanup(base::BindOnce( - [] { NetworkContext::SetCertVerifierForTesting(nullptr); })); - - mojom::NetworkContextParamsPtr context_params = CreateContextParams(); - mojom::NetworkContextPtr network_context_ptr; - std::unique_ptr<NetworkContext> network_context = - std::make_unique<NetworkContext>(network_service.get(), - mojo::MakeRequest(&network_context_ptr), - std::move(context_params)); - - // Certificate Transparency should be configured, but there should be - // nothing listening for SCTs (such as the NetworkContext's ct_tree_tracker_). - ASSERT_TRUE( - network_context->url_request_context()->cert_transparency_verifier()); - EXPECT_TRUE(network_context->url_request_context() - ->cert_transparency_verifier() - ->GetObserver()); - - // Provide an STH from Google's Pilot log that can be used to prove - // inclusion for an SCT later in the test. - net::ct::SignedTreeHead pilot_sth; - ASSERT_TRUE(BuildSignedTreeHead( - base::Time::FromJsTime(1512419914170), 181871752, - "bvgljSy3Yg32Y6J8qL5WmUA3jn2WnOrEFDqxD0AxUvs=", - "BAMARjBEAiAwEXve2RBk3XkUR+6nACSETTgzKFaEeginxuj5U9BI/" - "wIgBPuQS5ACxsro6TtpY4bQyE6WlMdcSMiMd/SSGraOBOg=", - "pLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BA=", &pilot_sth)); - network_service->UpdateSignedTreeHead(pilot_sth); - - // Provide an STH from Google's Aviator log that is not recent enough to - // prove inclusion for an SCT later in the test. - net::ct::SignedTreeHead aviator_sth; - ASSERT_TRUE(BuildSignedTreeHead( - base::Time::FromJsTime(1442652106945), 8502329, - "bfG+gWZcHl9fqtNo0Z/uggs8E5YqGOtJQ0Z5zVZDRxI=", - "BAMARjBEAiA6elcNQoShmKLHj/" - "IA649UIbaQtWJEpj0Eot0q7G6fEgIgYChb7U6Reuvt0nO5PionH+3UciOxKV3Cy8/" - "eq59lSYY=", - "aPaY+B9kgr46jO65KB1M/HFRXWeT1ETRCmesu09P+8Q=", &aviator_sth)); - network_service->UpdateSignedTreeHead(aviator_sth); - - // Start a test server on "localhost" and configure connections to it to - // simulate using a real certificate. - net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); - ASSERT_TRUE(https_server.Start()); - - // Configure "localhost" to be treated as if it went through DNS. This - // modifies the HostCache directly to simulate it being cached, rather than - // indirecting through a scoped HostResolverProc, as queries that use - // HostResolverProcs are treated as SOURCE_UNKNOWN, rather than SOURCE_DNS. - net::AddressList address_list; - ASSERT_TRUE(https_server.GetAddressList(&address_list)); - - net::HostCache* host_cache = - network_context->url_request_context()->host_resolver()->GetHostCache(); - ASSERT_TRUE(host_cache); - host_cache->Set( - net::HostCache::Key("localhost", net::ADDRESS_FAMILY_UNSPECIFIED, 0), - net::HostCache::Entry(net::OK, address_list, - net::HostCache::Entry::SOURCE_DNS), - base::TimeTicks::Now(), base::TimeDelta()); - - // This certificate contains 3 SCTs and fulfills the Chrome CT policy. - // Simulate it being trusted by a known root, as otherwise CT is skipped for - // private roots. - net::CertVerifyResult verify_result; - verify_result.is_issued_by_known_root = true; - verify_result.cert_status = 0; - verify_result.verified_cert = GetCTCertForTesting(); - ASSERT_TRUE(verify_result.verified_cert); - mock_cert_verifier.AddResultForCert(https_server.GetCertificate(), - verify_result, net::OK); - - base::HistogramTester histograms; - - ResourceRequest request; - request.url = https_server.GetURL("localhost", "/"); - request.method = "GET"; - request.request_initiator = url::Origin(); - - mojom::URLLoaderFactoryPtr loader_factory; - auto url_loader_factory_params = - network::mojom::URLLoaderFactoryParams::New(); - url_loader_factory_params->process_id = network::mojom::kBrowserProcessId; - url_loader_factory_params->is_corb_enabled = false; - network_context->CreateURLLoaderFactory(mojo::MakeRequest(&loader_factory), - std::move(url_loader_factory_params)); - - mojom::URLLoaderPtr loader; - TestURLLoaderClient client; - int options = mojom::kURLLoadOptionSendSSLInfoWithResponse | - mojom::kURLLoadOptionSendSSLInfoForCertificateError; - loader_factory->CreateLoaderAndStart( - mojo::MakeRequest(&loader), 0 /* routing_id */, 0 /* request_id */, - options, request, client.CreateInterfacePtr(), - net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS)); - - client.RunUntilComplete(); - EXPECT_TRUE(client.has_received_response()); - EXPECT_TRUE(client.has_received_completion()); - - // Expect a successful connection. - EXPECT_EQ(net::OK, client.completion_status().error_code); - - // Expect 3 SCTs in this connection. - ASSERT_TRUE(client.ssl_info().has_value()); - ASSERT_EQ(kNumSCTs, client.ssl_info()->signed_certificate_timestamps.size()); - - // Expect that all SCTs were embedded in the certificate. - size_t embedded_scts = 0; - for (const auto& sct : client.ssl_info()->signed_certificate_timestamps) { - if (sct.sct->origin == net::ct::SignedCertificateTimestamp::SCT_EMBEDDED) - ++embedded_scts; - } - ASSERT_EQ(kNumSCTs, embedded_scts); - - // The Pilot SCT should be eligible for inclusion checking, because a recent - // enough Pilot STH is available. - histograms.ExpectBucketCount( - "Net.CertificateTransparency.CanInclusionCheckSCT", - certificate_transparency::CAN_BE_CHECKED, 1); - // The Aviator SCT should not be eligible for inclusion checking, because - // there is not a recent enough Aviator STH available. - histograms.ExpectBucketCount( - "Net.CertificateTransparency.CanInclusionCheckSCT", - certificate_transparency::NEWER_STH_REQUIRED, 1); - // The DigiCert SCT should not be eligible for inclusion checking, because - // there is no DigiCert STH available. - histograms.ExpectBucketCount( - "Net.CertificateTransparency.CanInclusionCheckSCT", - certificate_transparency::VALID_STH_REQUIRED, 1); -} - -} // namespace - -} // namespace network
diff --git a/services/network/network_service.cc b/services/network/network_service.cc index 2448249a..652ccfc 100644 --- a/services/network/network_service.cc +++ b/services/network/network_service.cc
@@ -54,10 +54,6 @@ #include "services/network/url_loader.h" #include "services/network/url_request_context_builder_mojo.h" -#if BUILDFLAG(IS_CT_SUPPORTED) -#include "components/certificate_transparency/sth_distributor.h" -#endif // BUILDFLAG(IS_CT_SUPPORTED) - #if defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL) #include "crypto/openssl_util.h" #include "third_party/boringssl/src/include/openssl/cpu.h" @@ -326,10 +322,6 @@ http_auth_cache_copier_ = std::make_unique<HttpAuthCacheCopier>(); -#if BUILDFLAG(IS_CT_SUPPORTED) - sth_distributor_ = - std::make_unique<certificate_transparency::STHDistributor>(); -#endif // BUILDFLAG(IS_CT_SUPPORTED) crl_set_distributor_ = std::make_unique<CRLSetDistributor>(); } @@ -598,12 +590,6 @@ std::move(callback))); } -#if BUILDFLAG(IS_CT_SUPPORTED) -void NetworkService::UpdateSignedTreeHead(const net::ct::SignedTreeHead& sth) { - sth_distributor_->NewSTHObserved(sth); -} -#endif // BUILDFLAG(IS_CT_SUPPORTED) - void NetworkService::UpdateCRLSet(base::span<const uint8_t> crl_set) { crl_set_distributor_->OnNewCRLSet(crl_set); } @@ -687,12 +673,6 @@ MaybeStartUpdateLoadInfoTimer(); } -#if BUILDFLAG(IS_CT_SUPPORTED) -certificate_transparency::STHReporter* NetworkService::sth_reporter() { - return sth_distributor_.get(); -} -#endif // BUILDFLAG(IS_CT_SUPPORTED) - void NetworkService::OnBindInterface( const service_manager::BindSourceInfo& source_info, const std::string& interface_name,
diff --git a/services/network/network_service.h b/services/network/network_service.h index 233b74c5..1c61321 100644 --- a/services/network/network_service.h +++ b/services/network/network_service.h
@@ -49,13 +49,6 @@ class URLRequestContext; } // namespace net -#if BUILDFLAG(IS_CT_SUPPORTED) -namespace certificate_transparency { -class STHDistributor; -class STHReporter; -} // namespace certificate_transparency -#endif // BUILDFLAG(IS_CT_SUPPORTED) - namespace network { class CRLSetDistributor; @@ -177,9 +170,6 @@ void GetNetworkList( uint32_t policy, mojom::NetworkService::GetNetworkListCallback callback) override; -#if BUILDFLAG(IS_CT_SUPPORTED) - void UpdateSignedTreeHead(const net::ct::SignedTreeHead& sth) override; -#endif // !BUILDFLAG(IS_CT_SUPPORTED) void UpdateCRLSet(base::span<const uint8_t> crl_set) override; void OnCertDBChanged() override; #if defined(OS_LINUX) && !defined(OS_CHROMEOS) @@ -231,10 +221,6 @@ return http_auth_cache_copier_.get(); } -#if BUILDFLAG(IS_CT_SUPPORTED) - certificate_transparency::STHReporter* sth_reporter(); -#endif // BUILDFLAG(IS_CT_SUPPORTED) - CRLSetDistributor* crl_set_distributor() { return crl_set_distributor_.get(); } @@ -346,9 +332,6 @@ bool os_crypt_config_set_ = false; -#if BUILDFLAG(IS_CT_SUPPORTED) - std::unique_ptr<certificate_transparency::STHDistributor> sth_distributor_; -#endif // BUILDFLAG(IS_CT_SUPPORTED) std::unique_ptr<CRLSetDistributor> crl_set_distributor_; // A timer that periodically calls UpdateLoadInfo while there are pending
diff --git a/services/network/public/cpp/BUILD.gn b/services/network/public/cpp/BUILD.gn index a618fea..d27d3c4 100644 --- a/services/network/public/cpp/BUILD.gn +++ b/services/network/public/cpp/BUILD.gn
@@ -201,10 +201,6 @@ "url_request_mojom_traits_unittest.cc", ] - if (is_ct_supported) { - sources += [ "signed_tree_head_mojom_traits_unittest.cc" ] - } - if (!is_ios) { sources += [ "server/http_server_unittest.cc" ] }
diff --git a/services/network/public/cpp/signed_tree_head.typemap b/services/network/public/cpp/signed_tree_head.typemap deleted file mode 100644 index 92dbaee..0000000 --- a/services/network/public/cpp/signed_tree_head.typemap +++ /dev/null
@@ -1,18 +0,0 @@ -# Copyright 2018 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//services/network/public/mojom/signed_tree_head.mojom" -public_headers = [ "//net/cert/signed_tree_head.h" ] -traits_headers = - [ "//services/network/public/cpp/signed_tree_head_mojom_traits.h" ] -sources = [ - "//services/network/public/cpp/signed_tree_head_mojom_traits.cc", -] -type_mappings = [ - "network.mojom.SignedTreeHead=net::ct::SignedTreeHead", - "network.mojom.SignedTreeHeadVersion=net::ct::SignedTreeHead::Version", -] -public_deps = [ - "//net", -]
diff --git a/services/network/public/cpp/signed_tree_head_mojom_traits.cc b/services/network/public/cpp/signed_tree_head_mojom_traits.cc deleted file mode 100644 index 9195950..0000000 --- a/services/network/public/cpp/signed_tree_head_mojom_traits.cc +++ /dev/null
@@ -1,42 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/network/public/cpp/signed_tree_head_mojom_traits.h" - -#include <memory> -#include <vector> - -#include "mojo/public/cpp/base/time_mojom_traits.h" -#include "services/network/public/cpp/digitally_signed_mojom_traits.h" - -namespace mojo { - -// static -bool StructTraits< - network::mojom::SignedTreeHeadDataView, - net::ct::SignedTreeHead>::Read(network::mojom::SignedTreeHeadDataView data, - net::ct::SignedTreeHead* out) { - std::vector<uint8_t> sha256_root_hash; - if (!data.ReadVersion(&out->version) || - !data.ReadTimestamp(&out->timestamp) || - !data.ReadSignature(&out->signature) || !data.ReadLogId(&out->log_id) || - !data.ReadSha256RootHash(&sha256_root_hash)) { - return false; - } - if (out->log_id.empty()) { - return false; - } - - out->tree_size = data.tree_size(); - - // The Mojo bindings should have validated the size constraint as part of - // ReadSha256RootHash(). - DCHECK_EQ(sha256_root_hash.size(), sizeof(out->sha256_root_hash)); - memcpy(out->sha256_root_hash, sha256_root_hash.data(), - sizeof(out->sha256_root_hash)); - - return true; -} - -} // namespace mojo
diff --git a/services/network/public/cpp/signed_tree_head_mojom_traits.h b/services/network/public/cpp/signed_tree_head_mojom_traits.h deleted file mode 100644 index f38cf4c7..0000000 --- a/services/network/public/cpp/signed_tree_head_mojom_traits.h +++ /dev/null
@@ -1,75 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_NETWORK_PUBLIC_CPP_SIGNED_TREE_HEAD_MOJOM_TRAITS_H_ -#define SERVICES_NETWORK_PUBLIC_CPP_SIGNED_TREE_HEAD_MOJOM_TRAITS_H_ - -#include "base/containers/span.h" -#include "base/strings/string_piece.h" -#include "base/time/time.h" -#include "mojo/public/cpp/bindings/enum_traits.h" -#include "mojo/public/cpp/bindings/struct_traits.h" -#include "net/cert/signed_tree_head.h" -#include "services/network/public/mojom/digitally_signed.mojom.h" -#include "services/network/public/mojom/signed_tree_head.mojom.h" - -namespace mojo { - -template <> -struct EnumTraits<network::mojom::SignedTreeHeadVersion, - net::ct::SignedTreeHead::Version> { - static network::mojom::SignedTreeHeadVersion ToMojom( - net::ct::SignedTreeHead::Version input) { - switch (input) { - case net::ct::SignedTreeHead::V1: - return network::mojom::SignedTreeHeadVersion::V1; - } - NOTREACHED(); - return network::mojom::SignedTreeHeadVersion::kMaxValue; - } - - static bool FromMojom(network::mojom::SignedTreeHeadVersion input, - net::ct::SignedTreeHead::Version* output) { - switch (input) { - case network::mojom::SignedTreeHeadVersion::V1: - *output = net::ct::SignedTreeHead::V1; - return true; - } - NOTREACHED(); - return false; - } -}; - -template <> -struct StructTraits<network::mojom::SignedTreeHeadDataView, - net::ct::SignedTreeHead> { - static net::ct::SignedTreeHead::Version version( - const net::ct::SignedTreeHead& sth) { - return sth.version; - } - static base::Time timestamp(const net::ct::SignedTreeHead& sth) { - return sth.timestamp; - } - static uint64_t tree_size(const net::ct::SignedTreeHead& sth) { - return sth.tree_size; - } - static base::span<const uint8_t> sha256_root_hash( - const net::ct::SignedTreeHead& sth) { - return base::as_bytes(base::make_span(sth.sha256_root_hash)); - } - static const net::ct::DigitallySigned& signature( - const net::ct::SignedTreeHead& sth) { - return sth.signature; - } - static base::StringPiece log_id(const net::ct::SignedTreeHead& sth) { - return sth.log_id; - } - - static bool Read(network::mojom::SignedTreeHeadDataView obj, - net::ct::SignedTreeHead* out); -}; - -} // namespace mojo - -#endif // SERVICES_NETWORK_PUBLIC_CPP_SIGNED_TREE_HEAD_MOJOM_TRAITS_H_
diff --git a/services/network/public/cpp/signed_tree_head_mojom_traits_unittest.cc b/services/network/public/cpp/signed_tree_head_mojom_traits_unittest.cc deleted file mode 100644 index 3742b832..0000000 --- a/services/network/public/cpp/signed_tree_head_mojom_traits_unittest.cc +++ /dev/null
@@ -1,64 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/network/public/cpp/signed_tree_head_mojom_traits.h" - -#include "base/time/time.h" -#include "mojo/public/cpp/base/time_mojom_traits.h" -#include "mojo/public/cpp/test_support/test_utils.h" -#include "net/cert/signed_certificate_timestamp.h" -#include "net/cert/signed_tree_head.h" -#include "net/test/ct_test_util.h" -#include "services/network/public/cpp/digitally_signed_mojom_traits.h" -#include "services/network/public/mojom/signed_tree_head.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace network { -namespace { - -TEST(SignedTreeHeadTraitsTest, Roundtrips) { - net::ct::SignedTreeHead original; - net::ct::SignedTreeHead copied; - - // First try with a populated STH. - ASSERT_TRUE(net::ct::GetSampleSignedTreeHead(&original)); - EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::SignedTreeHead>( - &original, &copied)); - EXPECT_EQ(original, copied); - - // Then try an STH for an empty tree. - ASSERT_TRUE(net::ct::GetSampleEmptySignedTreeHead(&original)); - EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::SignedTreeHead>( - &original, &copied)); - EXPECT_EQ(original, copied); - - // Then try a syntactically-valid but semantically-bad STH. - ASSERT_TRUE(net::ct::GetBadEmptySignedTreeHead(&original)); - EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::SignedTreeHead>( - &original, &copied)); - EXPECT_EQ(original, copied); -} - -TEST(SignedTreeHeadTraitsTest, RequiresLogId) { - net::ct::SignedTreeHead original; - ASSERT_TRUE(net::ct::GetSampleSignedTreeHead(&original)); - original.log_id.clear(); - - net::ct::SignedTreeHead copied; - EXPECT_FALSE(mojo::test::SerializeAndDeserialize<mojom::SignedTreeHead>( - &original, &copied)); -} - -TEST(SignedTreeHeadTraitsTest, RequiresValidDigitallySigned) { - net::ct::SignedTreeHead original; - ASSERT_TRUE(net::ct::GetSampleSignedTreeHead(&original)); - original.signature.signature_data.clear(); - - net::ct::SignedTreeHead copied; - EXPECT_FALSE(mojo::test::SerializeAndDeserialize<mojom::SignedTreeHead>( - &original, &copied)); -} - -} // namespace -} // namespace network
diff --git a/services/network/public/cpp/typemaps.gni b/services/network/public/cpp/typemaps.gni index 06a2827..b0677ef 100644 --- a/services/network/public/cpp/typemaps.gni +++ b/services/network/public/cpp/typemaps.gni
@@ -28,7 +28,3 @@ "//services/network/public/cpp/url_request_redirect_info.typemap", "//services/network/public/cpp/url_response_head.typemap", ] - -if (is_ct_supported) { - typemaps += [ "//services/network/public/cpp/signed_tree_head.typemap" ] -}
diff --git a/services/network/public/mojom/BUILD.gn b/services/network/public/mojom/BUILD.gn index d07b01290..036bcc4 100644 --- a/services/network/public/mojom/BUILD.gn +++ b/services/network/public/mojom/BUILD.gn
@@ -126,10 +126,7 @@ if (is_ct_supported) { enabled_features += [ "is_ct_supported" ] - sources += [ - "ct_log_info.mojom", - "signed_tree_head.mojom", - ] + sources += [ "ct_log_info.mojom" ] } if (!is_ios) {
diff --git a/services/network/public/mojom/ct_log_info.mojom b/services/network/public/mojom/ct_log_info.mojom index f4c26f7..294892a 100644 --- a/services/network/public/mojom/ct_log_info.mojom +++ b/services/network/public/mojom/ct_log_info.mojom
@@ -14,9 +14,4 @@ // The human-readable, log-supplied log name. Note that this will not be // translated. string name; - - // The DNS API endpoint for the log. - // This will be used as the parent domain for all queries about the log. - // See https://github.com/google/certificate-transparency-rfcs/blob/master/dns/draft-ct-over-dns.md - string dns_api_endpoint; };
diff --git a/services/network/public/mojom/network_service.mojom b/services/network/public/mojom/network_service.mojom index 60c8ab74..53be8c9 100644 --- a/services/network/public/mojom/network_service.mojom +++ b/services/network/public/mojom/network_service.mojom
@@ -24,9 +24,6 @@ import "url/mojom/origin.mojom"; import "url/mojom/url.mojom"; -[EnableIf=is_ct_supported] -import "services/network/public/mojom/signed_tree_head.mojom"; - [EnableIf=is_android] import "mojo/public/mojom/base/application_state.mojom"; @@ -338,12 +335,6 @@ // network interfaces. Corresponds to enum net::HostAddressSelectionPolicy. GetNetworkList(uint32 policy) => (array<NetworkInterface>? networks); - // Updates Signed Tree Heads (STH) used in the handling of Certificate - // Transparency. Broadcast to each NetworkContext using the NetworkService. - // NetworkContextes ignore STHs from unrecognized logs. - [EnableIf=is_ct_supported] - UpdateSignedTreeHead(SignedTreeHead signed_tree_head); - // Updates the CRLSet used in the verification of certificates. CRLSets that // cannot be parsed using net::CRLSet::Parse will be ignored, as will older // CRLSets (where older is determined by the sequence number). All Network
diff --git a/services/network/public/mojom/signed_tree_head.mojom b/services/network/public/mojom/signed_tree_head.mojom deleted file mode 100644 index 6296dc6..0000000 --- a/services/network/public/mojom/signed_tree_head.mojom +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -module network.mojom; - -import "mojo/public/mojom/base/time.mojom"; -import "services/network/public/mojom/digitally_signed.mojom"; - -// Mirror of net::ct::SignedTreeHead::Version -enum SignedTreeHeadVersion { - // The Version enum in RFC 6962, Section 3.2. - V1 = 0, -}; - -// Mirror of net::ct::SignedTreeHead. -// These fields are defined in Section 3.5 and Section 4.3 of RFC 6962. -struct SignedTreeHead { - SignedTreeHeadVersion version; - mojo_base.mojom.Time timestamp; - uint64 tree_size; - array<uint8, 32> sha256_root_hash; - DigitallySigned signature; - - // Added in RFC6962-bis, Appendix A, but useful with RFC 6962 to track - // which log a given STH is associated with. - string log_id; -};
diff --git a/testing/buildbot/chromium.dawn.json b/testing/buildbot/chromium.dawn.json index b51fc85..fc1a665a 100644 --- a/testing/buildbot/chromium.dawn.json +++ b/testing/buildbot/chromium.dawn.json
@@ -272,8 +272,7 @@ "os": "Ubuntu", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" }, @@ -296,8 +295,7 @@ "os": "Ubuntu", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" } @@ -322,8 +320,7 @@ "os": "Ubuntu-14.04", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" }, @@ -346,8 +343,7 @@ "os": "Ubuntu-14.04", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" } @@ -626,8 +622,7 @@ "os": "Mac-10.13.6", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" }, @@ -651,8 +646,7 @@ "os": "Mac-10.13.6", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" } @@ -677,8 +671,7 @@ "os": "Mac-10.13.6", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" }, @@ -701,8 +694,7 @@ "os": "Mac-10.13.6", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" } @@ -979,8 +971,7 @@ "os": "Windows-10", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" }, @@ -1003,8 +994,7 @@ "os": "Windows-10", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" } @@ -1029,8 +1019,7 @@ "os": "Windows-10", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" }, @@ -1053,8 +1042,7 @@ "os": "Windows-10", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" } @@ -1327,8 +1315,7 @@ "os": "Windows-10", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" }, @@ -1351,8 +1338,7 @@ "os": "Windows-10", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" } @@ -1377,8 +1363,7 @@ "os": "Windows-10", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" }, @@ -1401,8 +1386,7 @@ "os": "Windows-10", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" }
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index ec19ee0..b8ec7942 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -7136,8 +7136,7 @@ "os": "Ubuntu", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" }, @@ -7160,8 +7159,7 @@ "os": "Ubuntu", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" } @@ -7186,8 +7184,7 @@ "os": "Ubuntu-14.04", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" }, @@ -7210,8 +7207,7 @@ "os": "Ubuntu-14.04", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" } @@ -7235,8 +7231,7 @@ "gpu": "8086:0a2e", "os": "Mac-10.12.6" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" }, @@ -7258,8 +7253,7 @@ "gpu": "8086:0a2e", "os": "Mac-10.12.6" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" } @@ -7285,8 +7279,7 @@ "os": "Mac-10.13.6", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" }, @@ -7310,8 +7303,7 @@ "os": "Mac-10.13.6", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" } @@ -7337,8 +7329,7 @@ "os": "Mac-10.13.6", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" }, @@ -7362,8 +7353,7 @@ "os": "Mac-10.13.6", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" } @@ -7388,8 +7378,7 @@ "os": "Windows-10", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" }, @@ -7412,8 +7401,7 @@ "os": "Windows-10", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" } @@ -7438,8 +7426,7 @@ "os": "Windows-10", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" }, @@ -7462,8 +7449,7 @@ "os": "Windows-10", "pool": "Chrome-GPU" } - ], - "shards": 4 + ] }, "test": "dawn_end2end_tests" } @@ -26254,8 +26240,7 @@ "pool": "Chrome-GPU" } ], - "expiration": 21600, - "shards": 4 + "expiration": 21600 }, "test": "dawn_end2end_tests" }, @@ -26279,8 +26264,7 @@ "pool": "Chrome-GPU" } ], - "expiration": 21600, - "shards": 4 + "expiration": 21600 }, "test": "dawn_end2end_tests" },
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 409464e..2ed7c72 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -3154,9 +3154,6 @@ # Dawn test retries deliberately disabled to prevent flakiness. '--test-launcher-retry-limit=0' ], - 'swarming': { - 'shards': 4, - }, }, 'dawn_end2end_wire_tests': { 'desktop_args': [ @@ -3165,9 +3162,6 @@ '--test-launcher-retry-limit=0', '--use-wire', ], - 'swarming': { - 'shards': 4, - }, 'test': 'dawn_end2end_tests', }, },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index be3bd6f..8f8c400 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -493,6 +493,21 @@ ] } ], + "AppListLaunchRecorder": [ + { + "platforms": [ + "chromeos" + ], + "experiments": [ + { + "name": "AppListLaunchRecorder", + "enable_features": [ + "EnableAppListLaunchRecording" + ] + } + ] + } + ], "AppleScriptExecuteJavaScript": [ { "platforms": [ @@ -1418,24 +1433,6 @@ ] } ], - "CertificateTransparencyLogAuditing": [ - { - "platforms": [ - "chromeos", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "CertificateTransparencyLogAuditing" - ] - } - ] - } - ], "ChromeCleanupDistribution": [ { "platforms": [ @@ -4045,6 +4042,21 @@ ] } ], + "PrefetchSRPAndroid": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "Enabled_threshold_1_holdback_20190521", + "enable_features": [ + "GWSPrefetchHoldback" + ] + } + ] + } + ], "PreloadMetadataLazyLoad": [ { "platforms": [
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.cc b/third_party/blink/renderer/core/html/html_frame_owner_element.cc index 726df7a..56b20ab6 100644 --- a/third_party/blink/renderer/core/html/html_frame_owner_element.cc +++ b/third_party/blink/renderer/core/html/html_frame_owner_element.cc
@@ -402,14 +402,18 @@ UpdateContainerPolicy(); KURL url_to_request = url.IsNull() ? BlankURL() : url; + ResourceRequest request(url_to_request); + request.SetReferrerPolicy(ReferrerPolicyAttribute()); + if (ContentFrame()) { // TODO(sclittle): Support lazily loading frame navigations. - FrameLoadRequest request(&GetDocument(), ResourceRequest(url_to_request)); - request.SetClientRedirectReason(ClientNavigationReason::kFrameNavigation); + FrameLoadRequest frame_load_request(&GetDocument(), request); + frame_load_request.SetClientRedirectReason( + ClientNavigationReason::kFrameNavigation); WebFrameLoadType frame_load_type = WebFrameLoadType::kStandard; if (replace_current_item) frame_load_type = WebFrameLoadType::kReplaceCurrentItem; - ContentFrame()->Navigate(request, frame_load_type); + ContentFrame()->Navigate(frame_load_request, frame_load_type); return true; } @@ -426,10 +430,6 @@ if (!child_frame) return false; - ResourceRequest request(url_to_request); - network::mojom::ReferrerPolicy policy = ReferrerPolicyAttribute(); - request.SetReferrerPolicy(policy); - WebFrameLoadType child_load_type = WebFrameLoadType::kReplaceCurrentItem; if (!GetDocument().LoadEventFinished() && GetDocument().Loader()->LoadType() ==
diff --git a/third_party/blink/renderer/core/html/html_rt_element.h b/third_party/blink/renderer/core/html/html_rt_element.h index 3b2fe46..04a6891 100644 --- a/third_party/blink/renderer/core/html/html_rt_element.h +++ b/third_party/blink/renderer/core/html/html_rt_element.h
@@ -17,6 +17,7 @@ private: LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override; + bool TypeShouldForceLegacyLayout() const final { return true; } }; } // namespace blink
diff --git a/third_party/blink/renderer/core/html/parser/background_html_parser.cc b/third_party/blink/renderer/core/html/parser/background_html_parser.cc index f9e285f..1eaf3d4 100644 --- a/third_party/blink/renderer/core/html/parser/background_html_parser.cc +++ b/third_party/blink/renderer/core/html/parser/background_html_parser.cc
@@ -273,7 +273,7 @@ chunk.get(), TRACE_EVENT_FLAG_FLOW_OUT); chunk->preloads.swap(pending_preloads_); - if (viewport_description_.set) + if (viewport_description_.has_value()) chunk->viewport = viewport_description_; chunk->xss_infos.swap(pending_xss_infos_); chunk->tokenizer_state = tokenizer_->GetState();
diff --git a/third_party/blink/renderer/core/html/parser/background_html_parser.h b/third_party/blink/renderer/core/html/parser/background_html_parser.h index 474f5717..76b01e4 100644 --- a/third_party/blink/renderer/core/html/parser/background_html_parser.h +++ b/third_party/blink/renderer/core/html/parser/background_html_parser.h
@@ -30,6 +30,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "base/optional.h" #include "base/single_thread_task_runner.h" #include "third_party/blink/renderer/core/dom/document_encoding_data.h" #include "third_party/blink/renderer/core/html/parser/background_html_input_stream.h" @@ -40,6 +41,7 @@ #include "third_party/blink/renderer/core/html/parser/html_tree_builder_simulator.h" #include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h" #include "third_party/blink/renderer/core/html/parser/xss_auditor_delegate.h" +#include "third_party/blink/renderer/core/page/viewport_description.h" namespace blink { @@ -116,7 +118,7 @@ CompactHTMLTokenStream pending_tokens_; PreloadRequestStream pending_preloads_; - ViewportDescriptionWrapper viewport_description_; + base::Optional<ViewportDescription> viewport_description_; XSSInfoStream pending_xss_infos_; std::unique_ptr<XSSAuditor> xss_auditor_;
diff --git a/third_party/blink/renderer/core/html/parser/html_document_parser.cc b/third_party/blink/renderer/core/html/parser/html_document_parser.cc index c8ab1dd..5cce22f 100644 --- a/third_party/blink/renderer/core/html/parser/html_document_parser.cc +++ b/third_party/blink/renderer/core/html/parser/html_document_parser.cc
@@ -326,7 +326,7 @@ // Note that on commit, the loader dispatched preloads for all the non-media // links. GetDocument()->Loader()->DispatchLinkHeaderPreloads( - &chunk->viewport, PreloadHelper::kOnlyLoadMedia); + chunk->viewport, PreloadHelper::kOnlyLoadMedia); tried_loading_link_headers_ = true; if (GetDocument()->Loader()->GetPrefetchedSignedExchangeManager()) { // Link header preloads for prefetched signed exchanges won't be started
diff --git a/third_party/blink/renderer/core/html/parser/html_document_parser.h b/third_party/blink/renderer/core/html/parser/html_document_parser.h index c935616..df11f78d 100644 --- a/third_party/blink/renderer/core/html/parser/html_document_parser.h +++ b/third_party/blink/renderer/core/html/parser/html_document_parser.h
@@ -46,6 +46,7 @@ #include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h" #include "third_party/blink/renderer/core/html/parser/xss_auditor.h" #include "third_party/blink/renderer/core/html/parser/xss_auditor_delegate.h" +#include "third_party/blink/renderer/core/page/viewport_description.h" #include "third_party/blink/renderer/core/script/html_parser_script_runner_host.h" #include "third_party/blink/renderer/platform/wtf/deque.h" #include "third_party/blink/renderer/platform/wtf/text/text_position.h" @@ -112,7 +113,7 @@ public: CompactHTMLTokenStream tokens; PreloadRequestStream preloads; - ViewportDescriptionWrapper viewport; + base::Optional<ViewportDescription> viewport; XSSInfoStream xss_infos; HTMLTokenizer::State tokenizer_state; HTMLTreeBuilderSimulator::State tree_builder_state;
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc b/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc index d23aebb..bcfa14c7 100644 --- a/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc +++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
@@ -758,7 +758,7 @@ void TokenPreloadScanner::Scan(const HTMLToken& token, const SegmentedString& source, PreloadRequestStream& requests, - ViewportDescriptionWrapper* viewport, + base::Optional<ViewportDescription>* viewport, bool* is_csp_meta_tag) { ScanCommon(token, source, requests, viewport, is_csp_meta_tag); } @@ -766,7 +766,7 @@ void TokenPreloadScanner::Scan(const CompactHTMLToken& token, const SegmentedString& source, PreloadRequestStream& requests, - ViewportDescriptionWrapper* viewport, + base::Optional<ViewportDescription>* viewport, bool* is_csp_meta_tag) { ScanCommon(token, source, requests, viewport, is_csp_meta_tag); } @@ -775,17 +775,15 @@ const String& attribute_value, const CachedDocumentParameters* document_parameters, MediaValuesCached* media_values, - ViewportDescriptionWrapper* viewport) { + base::Optional<ViewportDescription>* viewport) { if (!document_parameters->viewport_meta_enabled) return; ViewportDescription description(ViewportDescription::kViewportMeta); HTMLMetaElement::GetViewportDescriptionFromContentAttribute( attribute_value, description, nullptr, document_parameters->viewport_meta_zero_values_quirk); - if (viewport) { - viewport->description = description; - viewport->set = true; - } + if (viewport) + *viewport = description; FloatSize initial_viewport(media_values->DeviceWidth(), media_values->DeviceHeight()); PageScaleConstraints constraints = description.Resolve( @@ -814,7 +812,7 @@ CachedDocumentParameters* document_parameters, MediaValuesCached* media_values, CSSPreloadScanner* css_scanner, - ViewportDescriptionWrapper* viewport) { + base::Optional<ViewportDescription>* viewport) { const typename Token::Attribute* name_attribute = token.GetAttributeItem(kNameAttr); if (!name_attribute) @@ -840,11 +838,12 @@ } template <typename Token> -void TokenPreloadScanner::ScanCommon(const Token& token, - const SegmentedString& source, - PreloadRequestStream& requests, - ViewportDescriptionWrapper* viewport, - bool* is_csp_meta_tag) { +void TokenPreloadScanner::ScanCommon( + const Token& token, + const SegmentedString& source, + PreloadRequestStream& requests, + base::Optional<ViewportDescription>* viewport, + bool* is_csp_meta_tag) { if (!document_parameters_->do_html_preload_scanning) return; @@ -992,7 +991,7 @@ PreloadRequestStream HTMLPreloadScanner::Scan( const KURL& starting_base_element_url, - ViewportDescriptionWrapper* viewport, + base::Optional<ViewportDescription>* viewport, bool& has_csp_meta_tag) { // HTMLTokenizer::updateStateFor only works on the main thread. DCHECK(IsMainThread());
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner.h b/third_party/blink/renderer/core/html/parser/html_preload_scanner.h index e480e1d..45f6493 100644 --- a/third_party/blink/renderer/core/html/parser/html_preload_scanner.h +++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner.h
@@ -32,6 +32,7 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" +#include "base/optional.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/css/media_values_cached.h" #include "third_party/blink/renderer/core/html/parser/compact_html_token.h" @@ -50,12 +51,6 @@ class HTMLTokenizer; class SegmentedString; -struct ViewportDescriptionWrapper { - ViewportDescription description; - bool set; - ViewportDescriptionWrapper() : set(false) {} -}; - struct CORE_EXPORT CachedDocumentParameters { USING_FAST_MALLOC(CachedDocumentParameters); @@ -88,12 +83,12 @@ void Scan(const HTMLToken&, const SegmentedString&, PreloadRequestStream& requests, - ViewportDescriptionWrapper*, + base::Optional<ViewportDescription>*, bool* is_csp_meta_tag); void Scan(const CompactHTMLToken&, const SegmentedString&, PreloadRequestStream& requests, - ViewportDescriptionWrapper*, + base::Optional<ViewportDescription>*, bool* is_csp_meta_tag); void SetPredictedBaseElementURL(const KURL& url) { @@ -112,7 +107,7 @@ inline void ScanCommon(const Token&, const SegmentedString&, PreloadRequestStream& requests, - ViewportDescriptionWrapper*, + base::Optional<ViewportDescription>*, bool* is_csp_meta_tag); template <typename Token> @@ -181,7 +176,7 @@ void AppendToEnd(const SegmentedString&); PreloadRequestStream Scan(const KURL& document_base_element_url, - ViewportDescriptionWrapper*, + base::Optional<ViewportDescription>*, bool& has_csp_meta_tag); private:
diff --git a/third_party/blink/renderer/core/inspector/inspector_highlight.cc b/third_party/blink/renderer/core/inspector/inspector_highlight.cc index 082edae..dc240d0 100644 --- a/third_party/blink/renderer/core/inspector/inspector_highlight.cc +++ b/third_party/blink/renderer/core/inspector/inspector_highlight.cc
@@ -322,8 +322,7 @@ LayoutObject* layout_object = text_node->GetLayoutObject(); if (!layout_object || !layout_object->IsText()) return text_info; - PhysicalRect bounding_box = - ToLayoutText(layout_object)->PhysicalVisualOverflowRect(); + LayoutRect bounding_box = ToLayoutText(layout_object)->VisualOverflowRect(); text_info->setString("nodeWidth", bounding_box.Width().ToString()); text_info->setString("nodeHeight", bounding_box.Height().ToString()); text_info->setString("tagName", "#text"); @@ -846,7 +845,8 @@ if (layout_object->IsText()) { LayoutText* layout_text = ToLayoutText(layout_object); - PhysicalRect text_rect = layout_text->PhysicalVisualOverflowRect(); + PhysicalRect text_rect = + layout_text->FlipForWritingMode(layout_text->VisualOverflowRect()); content_box = text_rect; padding_box = text_rect; border_box = text_rect;
diff --git a/third_party/blink/renderer/core/layout/layout_box.h b/third_party/blink/renderer/core/layout/layout_box.h index e72f5b6..193728f4 100644 --- a/third_party/blink/renderer/core/layout/layout_box.h +++ b/third_party/blink/renderer/core/layout/layout_box.h
@@ -506,8 +506,8 @@ return LayoutSize(LayoutOverflowRect().MaxX(), LayoutOverflowRect().MaxY()); } - LayoutRect VisualOverflowRect() const; - PhysicalRect PhysicalVisualOverflowRect() const final { + LayoutRect VisualOverflowRect() const override; + PhysicalRect PhysicalVisualOverflowRect() const { return FlipForWritingMode(VisualOverflowRect()); } LayoutUnit LogicalLeftVisualOverflow() const {
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object.h b/third_party/blink/renderer/core/layout/layout_box_model_object.h index 23e65eb6..6aaea9d 100644 --- a/third_party/blink/renderer/core/layout/layout_box_model_object.h +++ b/third_party/blink/renderer/core/layout/layout_box_model_object.h
@@ -177,7 +177,7 @@ // border boxes. virtual IntRect BorderBoundingBox() const = 0; - virtual PhysicalRect PhysicalVisualOverflowRect() const = 0; + virtual LayoutRect VisualOverflowRect() const = 0; bool UsesCompositedScrolling() const;
diff --git a/third_party/blink/renderer/core/layout/layout_inline.cc b/third_party/blink/renderer/core/layout/layout_inline.cc index 17b2b0e..94e5ede 100644 --- a/third_party/blink/renderer/core/layout/layout_inline.cc +++ b/third_party/blink/renderer/core/layout/layout_inline.cc
@@ -1242,16 +1242,11 @@ return nullptr; } -PhysicalRect LayoutInline::CulledInlineVisualOverflowBoundingBox() const { - PhysicalRect result; - CollectCulledLineBoxRects( - [&result](const PhysicalRect& r) { result.UniteIfNonZero(r); }); - if (!FirstChild()) - return result; - +LayoutRect LayoutInline::CulledInlineVisualOverflowBoundingBox() const { + LayoutRect result; + CollectCulledLineBoxRectsInFlippedBlocksDirection( + [&result](const LayoutRect& r) { result.UniteIfNonZero(r); }, this); bool is_horizontal = StyleRef().IsHorizontalWritingMode(); - const LayoutBlock* block_for_flipping = - UNLIKELY(HasFlippedBlocksWritingMode()) ? ContainingBlock() : nullptr; for (LayoutObject* curr = FirstChild(); curr; curr = curr->NextSibling()) { if (curr->IsFloatingOrOutOfFlowPositioned()) continue; @@ -1264,31 +1259,29 @@ curr_box->LogicalVisualOverflowRectForPropagation(); if (is_horizontal) { logical_rect.MoveBy(curr_box->Location()); - result.UniteIfNonZero(PhysicalRect(logical_rect)); + result.UniteIfNonZero(logical_rect); } else { logical_rect.MoveBy(curr_box->Location()); - result.UniteIfNonZero(FlipForWritingMode( - logical_rect.TransposedRect(), block_for_flipping)); + result.UniteIfNonZero(logical_rect.TransposedRect()); } } } else if (curr->IsLayoutInline()) { // If the child doesn't need line boxes either, then we can recur. LayoutInline* curr_inline = ToLayoutInline(curr); - if (!curr_inline->AlwaysCreateLineBoxes()) { + if (!curr_inline->AlwaysCreateLineBoxes()) result.UniteIfNonZero( curr_inline->CulledInlineVisualOverflowBoundingBox()); - } else if (!curr_inline->HasSelfPaintingLayer()) { - result.UniteIfNonZero(curr_inline->PhysicalVisualOverflowRect()); - } + else if (!curr_inline->HasSelfPaintingLayer()) + result.UniteIfNonZero(curr_inline->VisualOverflowRect()); } else if (curr->IsText()) { LayoutText* curr_text = ToLayoutText(curr); - result.UniteIfNonZero(curr_text->PhysicalVisualOverflowRect()); + result.UniteIfNonZero(curr_text->VisualOverflowRect()); } } return result; } -PhysicalRect LayoutInline::LinesVisualOverflowBoundingBox() const { +LayoutRect LayoutInline::LinesVisualOverflowBoundingBox() const { if (IsInLayoutNGInlineFormattingContext()) { PhysicalRect result; NGPaintFragment::InlineFragmentsIncludingCulledFor( @@ -1300,14 +1293,14 @@ result->Unite(child_rect); }, &result); - return result; + return FlipForWritingMode(result); } if (!AlwaysCreateLineBoxes()) return CulledInlineVisualOverflowBoundingBox(); if (!FirstLineBox() || !LastLineBox()) - return PhysicalRect(); + return LayoutRect(); // Return the width of the minimal left side and the maximal right side. LayoutUnit logical_left_side = LayoutUnit::Max(); @@ -1333,13 +1326,13 @@ logical_height); if (!StyleRef().IsHorizontalWritingMode()) rect = rect.TransposedRect(); - return FlipForWritingMode(rect); + return rect; } PhysicalRect LayoutInline::VisualRectInDocument(VisualRectFlags flags) const { PhysicalRect rect; if (!Continuation()) { - rect = PhysicalVisualOverflowRect(); + rect = FlipForWritingMode(VisualOverflowRect()); } else { // Should also cover continuations. rect = UnionRect(OutlineRects(PhysicalOffset(), @@ -1361,11 +1354,11 @@ // VisualOverflowRect() is in "physical coordinates with flipped blocks // direction", while all "VisualRect"s are in pure physical coordinates. - return PhysicalVisualOverflowRect(); + return FlipForWritingMode(VisualOverflowRect()); } -PhysicalRect LayoutInline::PhysicalVisualOverflowRect() const { - PhysicalRect overflow_rect = LinesVisualOverflowBoundingBox(); +LayoutRect LayoutInline::VisualOverflowRect() const { + LayoutRect overflow_rect = LinesVisualOverflowBoundingBox(); LayoutUnit outline_outset(StyleRef().OutlineOutsetExtent()); if (outline_outset) { Vector<PhysicalRect> rects; @@ -1385,7 +1378,7 @@ OutlineRectsShouldIncludeBlockVisualOverflow()); } if (!rects.IsEmpty()) { - PhysicalRect outline_rect = UnionRectEvenIfEmpty(rects); + LayoutRect outline_rect = FlipForWritingMode(UnionRectEvenIfEmpty(rects)); outline_rect.Inflate(outline_outset); overflow_rect.Unite(outline_rect); }
diff --git a/third_party/blink/renderer/core/layout/layout_inline.h b/third_party/blink/renderer/core/layout/layout_inline.h index bae52a7..5d1c691 100644 --- a/third_party/blink/renderer/core/layout/layout_inline.h +++ b/third_party/blink/renderer/core/layout/layout_inline.h
@@ -147,7 +147,7 @@ FloatRect LocalBoundingBoxRectForAccessibility() const final; PhysicalRect PhysicalLinesBoundingBox() const; - PhysicalRect PhysicalVisualOverflowRect() const final; + LayoutRect VisualOverflowRect() const final; PhysicalRect ReferenceBoxForClipPath() const; InlineFlowBox* CreateAndAppendInlineFlowBox(); @@ -287,13 +287,13 @@ bool ComputeInitialShouldCreateBoxFragment() const; bool ComputeInitialShouldCreateBoxFragment(const ComputedStyle& style) const; - PhysicalRect CulledInlineVisualOverflowBoundingBox() const; + LayoutRect CulledInlineVisualOverflowBoundingBox() const; InlineBox* CulledInlineFirstLineBox() const; InlineBox* CulledInlineLastLineBox() const; - // For PhysicalVisualOverflowRect() only, to get bounding box of visual - // overflow of line boxes. - PhysicalRect LinesVisualOverflowBoundingBox() const; + // For visualOverflowRect() only, to get bounding box of visual overflow of + // line boxes. + LayoutRect LinesVisualOverflowBoundingBox() const; // PhysicalRectCollector should be like a function: // void (const PhysicalRect&).
diff --git a/third_party/blink/renderer/core/layout/layout_text.cc b/third_party/blink/renderer/core/layout/layout_text.cc index 00166c6..1356d385 100644 --- a/third_party/blink/renderer/core/layout/layout_text.cc +++ b/third_party/blink/renderer/core/layout/layout_text.cc
@@ -1971,13 +1971,13 @@ return result; } -PhysicalRect LayoutText::PhysicalVisualOverflowRect() const { - if (base::Optional<PhysicalRect> rect = +LayoutRect LayoutText::VisualOverflowRect() const { + if (base::Optional<PhysicalRect> physical_rect = NGPaintFragment::LocalVisualRectFor(*this)) - return *rect; + return FlipForWritingMode(*physical_rect); if (!FirstTextBox()) - return PhysicalRect(); + return LayoutRect(); // Return the width of the minimal left side and the maximal right side. LayoutUnit logical_left_side = LayoutUnit::Max(); @@ -2017,11 +2017,16 @@ logical_height); if (!StyleRef().IsHorizontalWritingMode()) rect = rect.TransposedRect(); - return FlipForWritingMode(rect); + return rect; } PhysicalRect LayoutText::LocalVisualRectIgnoringVisibility() const { - return UnionRect(PhysicalVisualOverflowRect(), LocalSelectionVisualRect()); + PhysicalRect rect; + if (const auto& r = NGPaintFragment::LocalVisualRectFor(*this)) + rect = *r; + else + rect = FlipForWritingMode(VisualOverflowRect()); + return UnionRect(rect, LocalSelectionVisualRect()); } PhysicalRect LayoutText::LocalSelectionVisualRect() const {
diff --git a/third_party/blink/renderer/core/layout/layout_text.h b/third_party/blink/renderer/core/layout/layout_text.h index 94dc1ea..7d2ce62 100644 --- a/third_party/blink/renderer/core/layout/layout_text.h +++ b/third_party/blink/renderer/core/layout/layout_text.h
@@ -184,7 +184,7 @@ // Returns the bounding box of visual overflow rects of all line boxes, // in containing block's physical coordinates with flipped blocks direction. - PhysicalRect PhysicalVisualOverflowRect() const; + LayoutRect VisualOverflowRect() const; PhysicalOffset FirstLineBoxTopLeft() const;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.cc index 6ef6cde..1e7fb8e 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.cc
@@ -422,7 +422,7 @@ const auto node_and_offset = ToNodeOffsetPair(position); const Node& node = node_and_offset.first; const unsigned offset = node_and_offset.second; - while (unit != units_.end() && unit->GetOwner() == node) { + while (unit != units_.end() && unit->AssociatedNode() == node) { if (unit->DOMEnd() > offset && unit->GetType() != NGOffsetMappingUnitType::kCollapsed) { const unsigned result = std::max(offset, unit->DOMStart()); @@ -443,7 +443,7 @@ const auto node_and_offset = ToNodeOffsetPair(position); const Node& node = node_and_offset.first; const unsigned offset = node_and_offset.second; - while (unit->GetOwner() == node) { + while (unit->AssociatedNode() == node) { if (unit->DOMStart() < offset && unit->GetType() != NGOffsetMappingUnitType::kCollapsed) { const unsigned result = std::min(offset, unit->DOMEnd());
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_test.cc index 4313efe..78b74c7 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_test.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_test.cc
@@ -1268,6 +1268,41 @@ TEST_RANGE(mapping.GetRanges(), text, 0u, 1u); } +// https://crbug.com/967106 +TEST_F(NGOffsetMappingTest, StartOfNextNonCollapsedContentWithPseudo) { + // The white spaces are necessary for bug repro. Do not remove them. + SetupHtml("t", R"HTML( + <style>span#quote::before { content: '"'}</style> + <div id=t> + <span>foo </span> + <span id=quote>bar</span> + </div>)HTML"); + + const Element* quote = GetElementById("quote"); + const Node* text = quote->previousSibling(); + const Position position = Position::FirstPositionInNode(*text); + + EXPECT_EQ(Position(), + GetOffsetMapping().StartOfNextNonCollapsedContent(position)); +} + +// https://crbug.com/967106 +TEST_F(NGOffsetMappingTest, EndOfLastNonCollapsedContentWithPseudo) { + // The white spaces are necessary for bug repro. Do not remove them. + SetupHtml("t", R"HTML( + <style>span#quote::after { content: '" '}</style> + <div id=t> + <span id=quote>foo</span> + <span>bar</span> + </div>)HTML"); + + const Element* quote = GetElementById("quote"); + const Node* text = quote->nextSibling(); + const Position position = Position::LastPositionInNode(*text); + + EXPECT_EQ(Position(), + GetOffsetMapping().EndOfLastNonCollapsedContent(position)); +} // Test |GetOffsetMapping| which is available both for LayoutNG and for legacy. class NGOffsetMappingGetterTest : public RenderingTest, public testing::WithParamInterface<bool>,
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc index e02e350..61c0739 100644 --- a/third_party/blink/renderer/core/loader/document_loader.cc +++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -307,7 +307,7 @@ } void DocumentLoader::DispatchLinkHeaderPreloads( - ViewportDescriptionWrapper* viewport, + const base::Optional<ViewportDescription>& viewport, PreloadHelper::MediaPreloadPolicy media_policy) { DCHECK_GE(state_, kCommitted); PreloadHelper::LoadLinksFromHeader( @@ -1202,7 +1202,7 @@ response_.HttpHeaderField(http_names::kLink), response_.CurrentRequestUrl(), *GetFrame(), nullptr, PreloadHelper::kDoNotLoadResources, PreloadHelper::kLoadAll, - nullptr /* viewport_description_wrapper */, + base::nullopt /* viewport_description */, nullptr /* alternate_resource_info */); if (!frame_->IsMainFrame() && response_.HasMajorCertificateErrors()) { MixedContentChecker::HandleCertificateError( @@ -1405,7 +1405,8 @@ // Links with media values need more information (like viewport information). // This happens after the first chunk is parsed in HTMLDocumentParser. - DispatchLinkHeaderPreloads(nullptr, PreloadHelper::kOnlyLoadNonMedia); + DispatchLinkHeaderPreloads(base::nullopt /* viewport */, + PreloadHelper::kOnlyLoadNonMedia); frame_->GetPage()->DidCommitLoad(frame_); GetUseCounter().DidCommitLoad(frame_);
diff --git a/third_party/blink/renderer/core/loader/document_loader.h b/third_party/blink/renderer/core/loader/document_loader.h index bf6c92292..efaa869 100644 --- a/third_party/blink/renderer/core/loader/document_loader.h +++ b/third_party/blink/renderer/core/loader/document_loader.h
@@ -32,6 +32,7 @@ #include <memory> #include "base/memory/scoped_refptr.h" +#include "base/optional.h" #include "base/unguessable_token.h" #include "third_party/blink/public/mojom/loader/mhtml_load_result.mojom-shared.h" #include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h" @@ -81,7 +82,6 @@ class SerializedScriptValue; class SubresourceFilter; class WebServiceWorkerNetworkProvider; -struct ViewportDescriptionWrapper; namespace mojom { enum class CommitResult : int32_t; @@ -217,7 +217,7 @@ bool WasBlockedAfterCSP() { return was_blocked_after_csp_; } - void DispatchLinkHeaderPreloads(ViewportDescriptionWrapper*, + void DispatchLinkHeaderPreloads(const base::Optional<ViewportDescription>&, PreloadHelper::MediaPreloadPolicy); void SetServiceWorkerNetworkProvider(
diff --git a/third_party/blink/renderer/core/loader/link_loader.cc b/third_party/blink/renderer/core/loader/link_loader.cc index 3969926..7132c27f 100644 --- a/third_party/blink/renderer/core/loader/link_loader.cc +++ b/third_party/blink/renderer/core/loader/link_loader.cc
@@ -42,6 +42,7 @@ #include "third_party/blink/renderer/core/loader/private/prerender_handle.h" #include "third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.h" #include "third_party/blink/renderer/core/loader/subresource_integrity_helper.h" +#include "third_party/blink/renderer/core/page/viewport_description.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_client.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_finish_observer.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h" @@ -185,7 +186,7 @@ Resource* resource = PreloadHelper::PreloadIfNeeded( params, document, NullURL(), PreloadHelper::kLinkCalledFromMarkup, - nullptr, + base::nullopt /* viewport_description */, client_->IsLinkCreatedByParser() ? kParserInserted : kNotParserInserted); if (!resource) { resource = PreloadHelper::PrefetchIfNeeded(params, document); @@ -193,7 +194,8 @@ if (resource) finish_observer_ = MakeGarbageCollected<FinishObserver>(this, resource); - PreloadHelper::ModulePreloadIfNeeded(params, document, nullptr, this); + PreloadHelper::ModulePreloadIfNeeded( + params, document, base::nullopt /* viewport_description */, this); if (const unsigned prerender_rel_types = PrerenderRelTypesFromRelAttribute(params.rel, document)) {
diff --git a/third_party/blink/renderer/core/loader/preload_helper.cc b/third_party/blink/renderer/core/loader/preload_helper.cc index 9e4bfe4..33f5b7a 100644 --- a/third_party/blink/renderer/core/loader/preload_helper.cc +++ b/third_party/blink/renderer/core/loader/preload_helper.cc
@@ -83,11 +83,12 @@ return false; } -MediaValues* CreateMediaValues(Document& document, - ViewportDescription* viewport_description) { +MediaValues* CreateMediaValues( + Document& document, + const base::Optional<ViewportDescription>& viewport_description) { MediaValues* media_values = MediaValues::CreateDynamicIfFrameExists(document.GetFrame()); - if (viewport_description) { + if (viewport_description.has_value()) { FloatSize initial_viewport(media_values->DeviceWidth(), media_values->DeviceHeight()); PageScaleConstraints constraints = viewport_description->Resolve( @@ -209,7 +210,7 @@ Document& document, const KURL& base_url, LinkCaller caller, - ViewportDescription* viewport_description, + const base::Optional<ViewportDescription>& viewport_description, ParserDisposition parser_disposition) { if (!document.Loader() || !params.rel.IsLinkPreload()) return nullptr; @@ -303,7 +304,7 @@ void PreloadHelper::ModulePreloadIfNeeded( const LinkLoadParameters& params, Document& document, - ViewportDescription* viewport_description, + const base::Optional<ViewportDescription>& viewport_description, SingleModuleClient* client) { if (!document.Loader() || !params.rel.IsModulePreload()) return; @@ -466,7 +467,7 @@ Document* document, CanLoadResources can_load_resources, MediaPreloadPolicy media_policy, - ViewportDescriptionWrapper* viewport_description_wrapper, + const base::Optional<ViewportDescription>& viewport_description, std::unique_ptr<AlternateSignedExchangeResourceInfo> alternate_resource_info) { if (header_value.IsEmpty()) @@ -518,11 +519,6 @@ } if (can_load_resources != kDoNotLoadResources) { DCHECK(document); - ViewportDescription* viewport_description = - (viewport_description_wrapper && viewport_description_wrapper->set) - ? &(viewport_description_wrapper->description) - : nullptr; - PreloadIfNeeded(params, *document, base_url, kLinkCalledFromHeader, viewport_description, kNotParserInserted); PrefetchIfNeeded(params, *document);
diff --git a/third_party/blink/renderer/core/loader/preload_helper.h b/third_party/blink/renderer/core/loader/preload_helper.h index 7ef6395..b045e8e3 100644 --- a/third_party/blink/renderer/core/loader/preload_helper.h +++ b/third_party/blink/renderer/core/loader/preload_helper.h
@@ -6,6 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_PRELOAD_HELPER_H_ #include "base/optional.h" +#include "third_party/blink/renderer/core/page/viewport_description.h" #include "third_party/blink/renderer/platform/loader/fetch/resource.h" namespace blink { @@ -15,8 +16,6 @@ class LocalFrame; class SingleModuleClient; struct LinkLoadParameters; -struct ViewportDescription; -struct ViewportDescriptionWrapper; // PreloadHelper is a helper class for preload, module preload, prefetch, // DNS prefetch, and preconnect triggered by <link> elements and "Link" HTTP @@ -42,7 +41,7 @@ Document*, // can be nullptr CanLoadResources, MediaPreloadPolicy, - ViewportDescriptionWrapper*, + const base::Optional<ViewportDescription>&, std::unique_ptr<AlternateSignedExchangeResourceInfo>); static Resource* StartPreload(ResourceType, FetchParameters&, @@ -67,11 +66,11 @@ Document&, const KURL& base_url, LinkCaller, - ViewportDescription*, + const base::Optional<ViewportDescription>&, ParserDisposition); static void ModulePreloadIfNeeded(const LinkLoadParameters&, Document&, - ViewportDescription*, + const base::Optional<ViewportDescription>&, SingleModuleClient*); static base::Optional<ResourceType> GetResourceTypeFromAsAttribute(
diff --git a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc index c08d392e..593ef5b6 100644 --- a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc +++ b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc
@@ -135,7 +135,7 @@ response.HttpHeaderField(http_names::kLink), response.CurrentRequestUrl(), frame, &frame_or_imported_document_->GetDocument(), resource_loading_policy, PreloadHelper::kLoadAll, - nullptr /* viewport_description_wrapper */, + base::nullopt /* viewport_description */, std::move(alternate_resource_info)); if (response.HasMajorCertificateErrors()) {
diff --git a/third_party/blink/renderer/core/paint/filter_effect_builder.cc b/third_party/blink/renderer/core/paint/filter_effect_builder.cc index 63acec2..67b5222 100644 --- a/third_party/blink/renderer/core/paint/filter_effect_builder.cc +++ b/third_party/blink/renderer/core/paint/filter_effect_builder.cc
@@ -121,14 +121,17 @@ } // namespace -FilterEffectBuilder::FilterEffectBuilder(const FloatRect& reference_box, - float zoom, - const PaintFlags* fill_flags, - const PaintFlags* stroke_flags) +FilterEffectBuilder::FilterEffectBuilder( + const FloatRect& reference_box, + float zoom, + const PaintFlags* fill_flags, + const PaintFlags* stroke_flags, + SkBlurImageFilter::TileMode blur_tile_mode) : reference_box_(reference_box), zoom_(zoom), fill_flags_(fill_flags), - stroke_flags_(stroke_flags) {} + stroke_flags_(stroke_flags), + blur_tile_mode_(blur_tile_mode) {} FilterEffect* FilterEffectBuilder::BuildFilterEffect( const FilterOperations& operations, @@ -370,7 +373,7 @@ case FilterOperation::BLUR: { float pixel_radius = To<BlurFilterOperation>(*op).StdDeviation().GetFloatValue(); - filters.AppendBlurFilter(pixel_radius); + filters.AppendBlurFilter(pixel_radius, blur_tile_mode_); break; } case FilterOperation::DROP_SHADOW: {
diff --git a/third_party/blink/renderer/core/paint/filter_effect_builder.h b/third_party/blink/renderer/core/paint/filter_effect_builder.h index cd7716c..b23df97d 100644 --- a/third_party/blink/renderer/core/paint/filter_effect_builder.h +++ b/third_party/blink/renderer/core/paint/filter_effect_builder.h
@@ -31,6 +31,7 @@ #include "third_party/blink/renderer/platform/graphics/paint/paint_flags.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" +#include "third_party/skia/include/effects/SkBlurImageFilter.h" namespace blink { @@ -50,7 +51,9 @@ FilterEffectBuilder(const FloatRect& reference_box, float zoom, const PaintFlags* fill_flags = nullptr, - const PaintFlags* stroke_flags = nullptr); + const PaintFlags* stroke_flags = nullptr, + SkBlurImageFilter::TileMode blur_tile_mode = + SkBlurImageFilter::kClampToBlack_TileMode); Filter* BuildReferenceFilter(SVGFilterElement&, FilterEffect* previous_effect, @@ -69,6 +72,7 @@ float zoom_; const PaintFlags* fill_flags_; const PaintFlags* stroke_flags_; + const SkBlurImageFilter::TileMode blur_tile_mode_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc index 8e2333e2..ede359b 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.cc +++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -712,9 +712,9 @@ needs_descendant_dependent_flags_update_ = false; if (IsSelfPaintingLayer() && needs_visual_overflow_recalc_) { - auto old_visual_rect = GetLayoutObject().PhysicalVisualOverflowRect(); + LayoutRect old_visual_rect = GetLayoutObject().VisualOverflowRect(); GetLayoutObject().RecalcVisualOverflow(); - if (old_visual_rect != GetLayoutObject().PhysicalVisualOverflowRect()) { + if (old_visual_rect != GetLayoutObject().VisualOverflowRect()) { SetNeedsCompositingInputsUpdateInternal(); MarkAncestorChainForFlagsUpdate(DoesNotNeedDescendantDependentUpdate); } @@ -2566,11 +2566,19 @@ } PhysicalRect PaintLayer::LocalBoundingBox() const { - PhysicalRect rect = GetLayoutObject().PhysicalVisualOverflowRect(); + PhysicalRect rect; + if (GetLayoutObject().IsBox()) { + rect = ToLayoutBox(GetLayoutObject()).PhysicalVisualOverflowRect(); + } else { + LayoutRect layout_rect = GetLayoutObject().VisualOverflowRect(); + rect = GetLayoutObject().FlipForWritingMode(layout_rect); + } + if (GetLayoutObject().IsEffectiveRootScroller() || IsRootLayer()) { rect.Unite( PhysicalRect(rect.offset, GetLayoutObject().View()->ViewRect().size)); } + return rect; } @@ -3310,7 +3318,10 @@ } float zoom = style.EffectiveZoom(); FloatRect reference_box = BackdropFilterReferenceBox(); - return_value = FilterEffectBuilder(reference_box, zoom) + // Use kClamp tile mode to avoid pixel moving filters bringing in black + // transparent pixels from the viewport edge. + return_value = FilterEffectBuilder(reference_box, zoom, nullptr, nullptr, + SkBlurImageFilter::kClamp_TileMode) .BuildFilterOperations(style.BackdropFilter()); DCHECK(!return_value.IsEmpty()); return return_value;
diff --git a/third_party/blink/renderer/devtools/PRESUBMIT.py b/third_party/blink/renderer/devtools/PRESUBMIT.py index 68de82a5..f19b2666 100644 --- a/third_party/blink/renderer/devtools/PRESUBMIT.py +++ b/third_party/blink/renderer/devtools/PRESUBMIT.py
@@ -94,16 +94,33 @@ ] -def _CheckDevtoolsLocalization(input_api, output_api): # pylint: disable=invalid-name +def _CheckDevtoolsWithNodeScript(input_api, output_api, script_path, script_arguments=None): # pylint: disable=invalid-name affected_front_end_files = _getAffectedFrontEndFiles(input_api) if len(affected_front_end_files) == 0: return [] else: - affected_front_end_files = [ - input_api.os_path.join(input_api.PresubmitLocalPath(), file_path) for file_path in affected_front_end_files - ] - script_path = input_api.os_path.join(input_api.PresubmitLocalPath(), "scripts", "check_localizability.js") - return _checkWithNodeScript(input_api, output_api, script_path, affected_front_end_files) + if script_arguments is None: + script_arguments = [] + return _checkWithNodeScript(input_api, output_api, script_path, script_arguments) + + +def _CheckDevtoolsLocalizableResources(input_api, output_api): # pylint: disable=invalid-name + affected_front_end_files = _getAffectedFrontEndFiles(input_api) + if len(affected_front_end_files) == 0: + return [] + script_path = input_api.os_path.join(input_api.PresubmitLocalPath(), "scripts", "check_localizable_resources.js") + args = ['--autofix'] + return _CheckDevtoolsWithNodeScript(input_api, output_api, script_path, args) + + +def _CheckDevtoolsLocalization(input_api, output_api): # pylint: disable=invalid-name + affected_front_end_files = [ + input_api.os_path.join(input_api.PresubmitLocalPath(), file_path) for file_path in _getAffectedFrontEndFiles(input_api) + ] + if len(affected_front_end_files) == 0: + return [] + script_path = input_api.os_path.join(input_api.PresubmitLocalPath(), "scripts", "check_localizability.js") + return _checkWithNodeScript(input_api, output_api, script_path, affected_front_end_files) def _CheckDevtoolsStyle(input_api, output_api): @@ -123,9 +140,9 @@ def _CompileDevtoolsFrontend(input_api, output_api): compile_path = input_api.os_path.join(input_api.PresubmitLocalPath(), "scripts", "compile_frontend.py") - out, _ = input_api.subprocess.Popen( - [input_api.python_executable, compile_path], stdout=input_api.subprocess.PIPE, - stderr=input_api.subprocess.STDOUT).communicate() + out, _ = input_api.subprocess.Popen([input_api.python_executable, compile_path], + stdout=input_api.subprocess.PIPE, + stderr=input_api.subprocess.STDOUT).communicate() if "ERROR" in out or "WARNING" in out: return [output_api.PresubmitError(out)] if "NOTE" in out: @@ -202,6 +219,7 @@ results = [] results.extend(_CheckBuildGN(input_api, output_api)) results.extend(_CheckFormat(input_api, output_api)) + results.extend(_CheckDevtoolsLocalizableResources(input_api, output_api)) results.extend(_CheckDevtoolsLocalization(input_api, output_api)) results.extend(_CheckDevtoolsStyle(input_api, output_api)) results.extend(_CompileDevtoolsFrontend(input_api, output_api)) @@ -237,7 +255,7 @@ return [input_api.os_path.relpath(file_name, devtools_root) for file_name in affected_js_files] -def _checkWithNodeScript(input_api, output_api, script_path, files=None): # pylint: disable=invalid-name +def _checkWithNodeScript(input_api, output_api, script_path, script_arguments=None): # pylint: disable=invalid-name original_sys_path = sys.path try: sys.path = sys.path + [input_api.os_path.join(input_api.PresubmitLocalPath(), "scripts")] @@ -247,11 +265,11 @@ node_path = local_node.node_path() - if files is None: - files = [] + if script_arguments is None: + script_arguments = [] process = input_api.subprocess.Popen( - [node_path, script_path] + files, stdout=input_api.subprocess.PIPE, stderr=input_api.subprocess.STDOUT) + [node_path, script_path] + script_arguments, stdout=input_api.subprocess.PIPE, stderr=input_api.subprocess.STDOUT) out, _ = process.communicate() if process.returncode != 0:
diff --git a/third_party/blink/renderer/devtools/front_end/accessibility/accessibility_strings.grdp b/third_party/blink/renderer/devtools/front_end/accessibility/accessibility_strings.grdp new file mode 100644 index 0000000..4023c8c --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/accessibility/accessibility_strings.grdp
@@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_185551542d4a950d6ed4a90e0875dfde" desc=""> + Computed Properties + </message> + <message name="IDS_DEVTOOLS_191abc41f8f74fb8c9671ca8f21b7433" desc=""> + Element not interesting for accessibility. + </message> + <message name="IDS_DEVTOOLS_1c2be4cda7b85620e6dca5fb505feedc" desc=""> + Element has empty alt text. + </message> + <message name="IDS_DEVTOOLS_3b1afa99cd297c96939424e1438e12f2" desc=""> + Element inherits presentational role from + </message> + <message name="IDS_DEVTOOLS_4ada42850cc2d4e41f3da5254ec2feee" desc=""> + Element is inert. + </message> + <message name="IDS_DEVTOOLS_52886045a6932b0bbb56620fe5c584bf" desc=""> + Ancestor's children are all presentational: + </message> + <message name="IDS_DEVTOOLS_5a51e4de1a235f3f67e816cb561d3d5a" desc=""> + Element is <ph name="ARIAHIDDENSPAN">$1s</ph>. + </message> + <message name="IDS_DEVTOOLS_5cd2b4477fa05212ce32e073702b6938" desc=""> + No ARIA attributes + </message> + <message name="IDS_DEVTOOLS_5d910721a6256ce42c8c6308dc60ff40" desc=""> + Static text node is used as name for + </message> + <message name="IDS_DEVTOOLS_5f05a00053834655de812d3447545a17" desc=""> + No node with this ID. + </message> + <message name="IDS_DEVTOOLS_7d615068dd4fb142c11a29553b9b83bf" desc=""> + Element is presentational. + </message> + <message name="IDS_DEVTOOLS_80c9f4e5b244cf617075b8ce23a3ed27" desc=""> + ARIA Attributes + </message> + <message name="IDS_DEVTOOLS_939aaa05e0943b39eab3a34fd609384d" desc=""> + Scroll into view + </message> + <message name="IDS_DEVTOOLS_970e14ef4e4d726d36b6ed0ea92bef83" desc=""> + Accessibility node not exposed + </message> + <message name="IDS_DEVTOOLS_98b6f72f9b4c1883deddc61bc62d71eb" desc=""> + Element is not visible. + </message> + <message name="IDS_DEVTOOLS_a4853b77c462337ed9fecc32e4d44d7b" desc=""> + Accessibility Tree + </message> + <message name="IDS_DEVTOOLS_a858dfbc32e2169e89668adf8e997f6f" desc=""> + No accessibility node + </message> + <message name="IDS_DEVTOOLS_aff2b966e54c2212e86343d2bb8d3f88" desc=""> + Part of label element: + </message> + <message name="IDS_DEVTOOLS_b05cf8cea038a89494e9e232e65af3f3" desc=""> + Element is not rendered. + </message> + <message name="IDS_DEVTOOLS_cd9da90ce06215f24f648786501e4073" desc=""> + Element is hidden by active modal dialog: + </message> + <message name="IDS_DEVTOOLS_cfa5234b2737df4bc3dc737484605c39" desc=""> + <ph name="ARIAHIDDENSPAN">$1s</ph> is <ph name="TRUESPAN">$2s</ph> on ancestor: + </message> + <message name="IDS_DEVTOOLS_d7dff47e75bfd5f107407eded09ee6f0" desc=""> + Element has <ph name="ROLEPRESENTATIONSPAN">$1s</ph>. + </message> + <message name="IDS_DEVTOOLS_d96143ba1b15645919cea00ec9d1be62" desc=""> + Ignored + </message> + <message name="IDS_DEVTOOLS_dd3195ced9c1810388e28ca2b4eb921f" desc=""> + Not specified + </message> + <message name="IDS_DEVTOOLS_e0dcc9aef6db5e61e4102efdf5d54378" desc=""> + Invalid source. + </message> + <message name="IDS_DEVTOOLS_e0e4fc6213e8b3593495a7260c3a4c2e" desc=""> + Accessibility + </message> + <message name="IDS_DEVTOOLS_e71c63b8e5a312662941ee8606e8c43a" desc=""> + Label for + </message> + <message name="IDS_DEVTOOLS_e7be8f80bd8db0b8ca6bb2dee175b623" desc=""> + Element is in an inert subtree from + </message> + <message name="IDS_DEVTOOLS_fc6dc044799975f19c864e9b31e3bb76" desc=""> + No text content. + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/animation/animation_strings.grdp b/third_party/blink/renderer/devtools/front_end/animation/animation_strings.grdp new file mode 100644 index 0000000..656e1fb --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/animation/animation_strings.grdp
@@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_043d2f0a7edca94cae1cfbf3f90b3b68" desc=""> + Animations + </message> + <message name="IDS_DEVTOOLS_105b296a83f9c105355403f3332af50f" desc=""> + Pause + </message> + <message name="IDS_DEVTOOLS_31fb6ba50d7a98f1650f282ecc45af77" desc=""> + Set speed to <ph name="BUTTON_TEXTCONTENT">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_4008ed4e30be53588254064e9bca502e" desc=""> + Pause timeline + </message> + <message name="IDS_DEVTOOLS_5fe41afb268c87f4f56027023d3e6406" desc=""> + <ph name="PLAYBACKRATE______">$1s</ph>% + </message> + <message name="IDS_DEVTOOLS_81aa2078d1eceede831b2976dbf32e62" desc=""> + Clear all + </message> + <message name="IDS_DEVTOOLS_96952fa958a61d47ed4dee3f2c3dee64" desc=""> + Pause all + </message> + <message name="IDS_DEVTOOLS_96b5ffa6e4c4b57e832f8e26229ed786" desc=""> + Play timeline + </message> + <message name="IDS_DEVTOOLS_9ea575b416c0fb4d80772ab08ce039f8" desc=""> + Select an effect above to inspect and modify. + </message> + <message name="IDS_DEVTOOLS_ba5ef3fb1e406e7707dc5f449adaa176" desc=""> + Listening for animations... + </message> + <message name="IDS_DEVTOOLS_bdf578b505f481a1dbb4555c16dd9a51" desc=""> + Replay timeline + </message> + <message name="IDS_DEVTOOLS_bffa3e523792264bd31830c746b6d388" desc=""> + Resume all + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/audits2/audits2_strings.grdp b/third_party/blink/renderer/devtools/front_end/audits2/audits2_strings.grdp new file mode 100644 index 0000000..8202dda --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/audits2/audits2_strings.grdp
@@ -0,0 +1,148 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_026d213afe4c17e37ac8306b77e9f870" desc=""> + Auditing your web page + </message> + <message name="IDS_DEVTOOLS_0503ffa75a95f35877fe7420d061b6a9" desc=""> + Progressive Web App + </message> + <message name="IDS_DEVTOOLS_070716fc9cd3859f51f3860a349bad2f" desc=""> + Simulated Slow 4G, 4x CPU Slowdown + </message> + <message name="IDS_DEVTOOLS_0f39dfdd740bf99080ca83e56e2cfb4c" desc=""> + 💡 <ph name="THIS__FASTFACTSQUEUED_FASTFACTINDEX_">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_1421c82f3616812789ac346b1638e39d" desc=""> + Run audits + </message> + <message name="IDS_DEVTOOLS_1583d36995134f9120fac115c08e0174" desc=""> + Loading… + </message> + <message name="IDS_DEVTOOLS_15a895a381c23eff5397d8b1f318a726" desc=""> + No network or CPU throttling used. (Useful when not evaluating performance) + </message> + <message name="IDS_DEVTOOLS_161bf73e31de6b8e3d856815473cbe1c" desc=""> + View Trace + </message> + <message name="IDS_DEVTOOLS_17de62900ceac9101c8814b4c4874328" desc=""> + Apply mobile emulation during auditing + </message> + <message name="IDS_DEVTOOLS_193c4edb3ab576449959f6710e017a49" desc=""> + Typical DevTools throttling, with actual traffic shaping and CPU slowdown applied + </message> + <message name="IDS_DEVTOOLS_1c481aa99d081c32182011a758f73d33" desc=""> + <ph name="MATCH_MESSAGE">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_2310408a63388fe57e3a4177168a8798" desc=""> + Desktop + </message> + <message name="IDS_DEVTOOLS_2a96c07a6c11ca7add2b1ffde86efe25" desc=""> + Can only audit HTTP/HTTPS pages and Chrome extensions. Navigate to a different page to start an audit. + </message> + <message name="IDS_DEVTOOLS_39680b3025b1f8d881f9d983623bf071" desc=""> + Lighthouse is loading your page + </message> + <message name="IDS_DEVTOOLS_3b7e043f46813f1d8ffbd462eb77fb6c" desc=""> + How long does this app take to show content and become usable + </message> + <message name="IDS_DEVTOOLS_3e3f8a3abd60f2389b744ca8ed0aa4d9" desc=""> + No throttling + </message> + <message name="IDS_DEVTOOLS_3ee3aab0791156ff1d5e0481ed4589b2" desc=""> + Applied Slow 4G, 4x CPU Slowdown + </message> + <message name="IDS_DEVTOOLS_41fdb410354e76ef7674f98e1cc84c8f" desc=""> + Throttling + </message> + <message name="IDS_DEVTOOLS_48d24d11c7c71282366fe2007d4cee3b" desc=""> + Throttling is simulated, resulting in faster audit runs with similar measurement accuracy + </message> + <message name="IDS_DEVTOOLS_4ab5093468559edd5940ac59f1c6ac02" desc=""> + Try to navigate to the URL in a fresh Chrome profile without any other tabs or extensions open and try again. + </message> + <message name="IDS_DEVTOOLS_55f562701dc2cc775f9adc0478644b2a" desc=""> + Perform an audit… + </message> + <message name="IDS_DEVTOOLS_56395991012586c2067aa7bcb5905b50" desc=""> + Cancelling + </message> + <message name="IDS_DEVTOOLS_64a64ca70e7a909a5a96c07082070bfc" desc=""> + Ah, sorry! We ran into an error. + </message> + <message name="IDS_DEVTOOLS_64d266bad80369458003a71a9e04dd50" desc=""> + Cancelling… + </message> + <message name="IDS_DEVTOOLS_6556b7f666de143f5a9826e048d5dcd8" desc=""> + Is this page usable by people with disabilities or impairments + </message> + <message name="IDS_DEVTOOLS_6565973a762b83f476e9a76a0015b539" desc=""> + At least one category must be selected. + </message> + <message name="IDS_DEVTOOLS_671b3beee69d9180412202b6528ec8f7" desc=""> + Download report + </message> + <message name="IDS_DEVTOOLS_67aa731132e0e7bbabb1b3d3c363e7d6" desc=""> + Multiple tabs are being controlled by the same service worker. Close your other tabs on the same origin to audit this page. + </message> + <message name="IDS_DEVTOOLS_72c4a2e545d220fd8c9ead876a59a89d" desc=""> + Is this page optimized for search engine results ranking + </message> + <message name="IDS_DEVTOOLS_7bd1e4f7363173e2c8329551ca4d38cc" desc=""> + (new audit) + </message> + <message name="IDS_DEVTOOLS_87d17f4624a514e81dc7c8e016a7405c" desc=""> + Mobile + </message> + <message name="IDS_DEVTOOLS_88450f419690173d62fb0a30fb29a951" desc=""> + Auditing <ph name="PAGEHOST">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_8eb7115e5b4ba55f56931ec24c789f9e" desc=""> + Lighthouse is warming up… + </message> + <message name="IDS_DEVTOOLS_8fe967af0fb77d0261a6ead91bcd607f" desc=""> + Reset storage (localStorage, IndexedDB, etc) before auditing. (Good for performance & PWA testing) + </message> + <message name="IDS_DEVTOOLS_9446a98ad14416153cc4d45ab8b531bf" desc=""> + Performance + </message> + <message name="IDS_DEVTOOLS_b06c94565d768dd75535120f2f8482a7" desc=""> + Audits + </message> + <message name="IDS_DEVTOOLS_b1b01acb63f79615b05f6d816705d7d3" desc=""> + Does this page meet the standard of a Progressive Web App + </message> + <message name="IDS_DEVTOOLS_bc28aa52ba5b534ad9d198157c375d67" desc=""> + Clear storage + </message> + <message name="IDS_DEVTOOLS_bcf2457dd80557dd7ebdc1504b6149e6" desc=""> + Does this page follow best practices for modern web development + </message> + <message name="IDS_DEVTOOLS_c2ffe02d76c4f089648f1647b43e4ee5" desc=""> + Best practices + </message> + <message name="IDS_DEVTOOLS_c3669fa42d4becdd2831b9685cf607bb" desc=""> + Identify and fix common problems that affect your site's performance, + accessibility, and user experience. + </message> + <message name="IDS_DEVTOOLS_c91c7b93c28cd18741b71f727ee81ee3" desc=""> + Reports + </message> + <message name="IDS_DEVTOOLS_d59048f21fd887ad520398ce677be586" desc=""> + Learn more + </message> + <message name="IDS_DEVTOOLS_d88946b678e4c2f251d4e292e8142291" desc=""> + SEO + </message> + <message name="IDS_DEVTOOLS_e0ac20adce6ffee48c7151b070aa5737" desc=""> + Device + </message> + <message name="IDS_DEVTOOLS_e499f5109f685235e6280179fe22beec" desc=""> + Drop audit file here + </message> + <message name="IDS_DEVTOOLS_ea4788705e6873b424c65e91c2846b19" desc=""> + Cancel + </message> + <message name="IDS_DEVTOOLS_ea60ba1496b05c6a5816fb75d0665c8d" desc=""> + If this issue is reproducible, please report it at the Lighthouse GitHub repo. + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/bindings/bindings_strings.grdp b/third_party/blink/renderer/devtools/front_end/bindings/bindings_strings.grdp new file mode 100644 index 0000000..dd879ed0 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/bindings/bindings_strings.grdp
@@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_412dac8227bbaf752fecaad8826f20e6" desc=""> + LiveEdit failed: <ph name="ERROR">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_d3ff22990e37ccce8a501ffba38626b7" desc=""> + LiveEdit compile failed: <ph name="EXCEPTIONDETAILS_TEXT">$1s</ph> + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/browser_debugger/browser_debugger_strings.grdp b/third_party/blink/renderer/devtools/front_end/browser_debugger/browser_debugger_strings.grdp new file mode 100644 index 0000000..1d7528f48 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/browser_debugger/browser_debugger_strings.grdp
@@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_0ca08f8f4a8a19f7f1ae87c119494327" desc=""> + Overrides + </message> + <message name="IDS_DEVTOOLS_1106d01848580ffc52dd36e2d60316d9" desc=""> + XHR/fetch Breakpoints + </message> + <message name="IDS_DEVTOOLS_193cfc9be3b995831c6af2fea6650e60" desc=""> + Page + </message> + <message name="IDS_DEVTOOLS_2daf59f0ff992924e42c14c1e674bd6a" desc=""> + Attribute modified + </message> + <message name="IDS_DEVTOOLS_30d67fd6c32c9a9ff5ecb4472b44ed54" desc=""> + Break when URL contains: + </message> + <message name="IDS_DEVTOOLS_340641a167ad6da1bcb4016357f4695d" desc=""> + Content scripts + </message> + <message name="IDS_DEVTOOLS_39c145d69ad05e44e74017346c116251" desc=""> + Remove all DOM breakpoints + </message> + <message name="IDS_DEVTOOLS_47bda3033cb8fe0e76c45c293db011b5" desc=""> + No breakpoints + </message> + <message name="IDS_DEVTOOLS_59eaf6955f44a94237b6d26911c1d983" desc=""> + Break on + </message> + <message name="IDS_DEVTOOLS_626585724f35f9d9fce0bd36525cb7de" desc=""> + DOM Breakpoint + </message> + <message name="IDS_DEVTOOLS_63a6a88c066880c5ac42394a22803ca6" desc=""> + Refresh + </message> + <message name="IDS_DEVTOOLS_66b74432bdc2797086f419010cc5ff86" desc=""> + DOM Breakpoints + </message> + <message name="IDS_DEVTOOLS_6ba3a9ac3e0d57683c56299484b7ee3b" desc=""> + Remove all breakpoints + </message> + <message name="IDS_DEVTOOLS_b4e79b551a1ceae24b7de243ab1fd27c" desc=""> + Add breakpoint + </message> + <message name="IDS_DEVTOOLS_b839f802a330e4d4145cb182e6767f45" desc=""> + Any XHR or fetch + </message> + <message name="IDS_DEVTOOLS_c22470110316d6334bed53ae61a08f59" desc=""> + URL contains "<ph name="URL">$1s</ph>" + </message> + <message name="IDS_DEVTOOLS_c4bd9c57c6b315e3f7374cf77143ca58" desc=""> + Subtree modified + </message> + <message name="IDS_DEVTOOLS_d5bfaaca8e28f8b9b9211038f86a4494" desc=""> + Remove breakpoint + </message> + <message name="IDS_DEVTOOLS_e30c4292775f68b2bc9eb3957a69f899" desc=""> + Global Listeners + </message> + <message name="IDS_DEVTOOLS_ebdb33cde9015fa4b294220ee89cff00" desc=""> + Event Listener Breakpoints + </message> + <message name="IDS_DEVTOOLS_f80938ab8ce27f3427af09c97a718fff" desc=""> + Node removed + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/browser_sdk/browser_sdk_strings.grdp b/third_party/blink/renderer/devtools/front_end/browser_sdk/browser_sdk_strings.grdp new file mode 100644 index 0000000..27e6fc6 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/browser_sdk/browser_sdk_strings.grdp
@@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_07c7413a65777a3d70e32ea32dafa509" desc=""> + Do not preserve log on page reload / navigation + </message> + <message name="IDS_DEVTOOLS_6aed54027cf3a260de904a43cf439cc9" desc=""> + Preserve log on page reload / navigation + </message> + <message name="IDS_DEVTOOLS_edd24cce7afedea5a1b2f90675880687" desc=""> + Preserve log + </message> + <message name="IDS_DEVTOOLS_eec89088ee408b80387155272b113256" desc=""> + Network + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/changes/changes_strings.grdp b/third_party/blink/renderer/devtools/front_end/changes/changes_strings.grdp new file mode 100644 index 0000000..2da2df97 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/changes/changes_strings.grdp
@@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_025502db49a6cf61a8245998129bd973" desc=""> + <ph name="DELETIONS">$1s</ph> deletions (-) + </message> + <message name="IDS_DEVTOOLS_5c2892cb638ec999fe22612587cd4a00" desc=""> + No changes + </message> + <message name="IDS_DEVTOOLS_70c85e43e99bc0cfcbb656123306eb19" desc=""> + <ph name="INSERTIONS">$1s</ph> insertion (+), + </message> + <message name="IDS_DEVTOOLS_af2c230293677261fe33ba6d3fbf02e3" desc=""> + <ph name="INSERTIONS">$1s</ph> insertions (+), + </message> + <message name="IDS_DEVTOOLS_c112bb3542e98308d12d5ecb10a67abc" desc=""> + Changes + </message> + <message name="IDS_DEVTOOLS_c73e4e53c15d9971d9293fcff6c0d8c0" desc=""> + ( … Skipping <ph name="LINES_LENGTH___PADDINGLINES____">$1d</ph> matching lines … ) + </message> + <message name="IDS_DEVTOOLS_ca012662d53a8bde28b4d82722aaff7e" desc=""> + Changes drawer + </message> + <message name="IDS_DEVTOOLS_df5f7764a0991b372d30c55eb57f6a55" desc=""> + Revert all changes + </message> + <message name="IDS_DEVTOOLS_e0e5ea9203300d2eb8ced39dd88c214e" desc=""> + <ph name="DELETIONS">$1s</ph> deletion (-) + </message> + <message name="IDS_DEVTOOLS_f550ec70278cc72604795d91ff8dcd30" desc=""> + Binary data + </message> + <message name="IDS_DEVTOOLS_fa6711f918fe2018131a4ad0380b9e56" desc=""> + <ph name="THIS_UISOURCECODE_DISPLAYNAME__">$1s</ph> (from source map) + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/color_picker/color_picker_strings.grdp b/third_party/blink/renderer/devtools/front_end/color_picker/color_picker_strings.grdp new file mode 100644 index 0000000..2ddfef3 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/color_picker/color_picker_strings.grdp
@@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_146ffe2fd9fa5bec3b63b52543793ec7" desc=""> + Show more + </message> + <message name="IDS_DEVTOOLS_158eabad9d23e8a99bbcfd6f411c575f" desc=""> + Remove color + </message> + <message name="IDS_DEVTOOLS_1690e1c6a6b4c615cc36ab66570996b4" desc=""> + Toggle color picker + </message> + <message name="IDS_DEVTOOLS_19dcdfb6d075db15609e75214f67189f" desc=""> + Remove all to the right + </message> + <message name="IDS_DEVTOOLS_2e8882b1e1deaa1bb50cbdfe188755f6" desc=""> + Copy color to clipboard + </message> + <message name="IDS_DEVTOOLS_38d7dc102a918c3b0031c9fde807308a" desc=""> + Pick background color + </message> + <message name="IDS_DEVTOOLS_39186fc9ea0f3ccf697b31a288e0723f" desc=""> + Toggle background color picker + </message> + <message name="IDS_DEVTOOLS_3b98e2dffc6cb06a89dcb0d5c60a0206" desc=""> + AA + </message> + <message name="IDS_DEVTOOLS_74421a69b1bc40c166be4de5caf0b036" desc=""> + Contrast ratio + </message> + <message name="IDS_DEVTOOLS_b201b2e7e7a20df48b625f20c2f0933e" desc=""> + Color Palettes + </message> + <message name="IDS_DEVTOOLS_b74447172f9edfe492a21feee374c1fd" desc=""> + Clear palette + </message> + <message name="IDS_DEVTOOLS_bbe0cb0a04956e97e8fc70f519d10e0d" desc=""> + <ph name="PALETTE_COLORS_I_">$1s</ph>. Long-click to show alternate shades. + </message> + <message name="IDS_DEVTOOLS_c74ea6dbff701bfa23819583c52ebd97" desc=""> + Show less + </message> + <message name="IDS_DEVTOOLS_ce82e07fa1f0521f5cee30e368fe2e73" desc=""> + : <ph name="AA_TOFIXED___">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_d1e2107b34fa404fabd54bcce4fd858f" desc=""> + Add to palette + </message> + <message name="IDS_DEVTOOLS_e1faffb3e614e6c2fba74296962386b7" desc=""> + AAA + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/components/components_strings.grdp b/third_party/blink/renderer/devtools/front_end/components/components_strings.grdp new file mode 100644 index 0000000..0ad7f6d2 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/components/components_strings.grdp
@@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_013cf261f9ccf5d4f027bc001d0d1d0c" desc=""> + (unknown) + </message> + <message name="IDS_DEVTOOLS_0b484cfcf50c8fabff48c0aad426f544" desc=""> + Dock to left + </message> + <message name="IDS_DEVTOOLS_131c97f8ba5bc0277386d660a18f13b6" desc=""> + Reveal in <ph name="DESTINATION">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_393c3f5ea8ad35c02691d507bdbb31b0" desc=""> + Reveal + </message> + <message name="IDS_DEVTOOLS_7f52f5f786eb8d9bf9e56ce89fb3db3a" desc=""> + Show 1 more frame + </message> + <message name="IDS_DEVTOOLS_93898e12951c906e5286ccb36d980ce5" desc=""> + Blackbox script + </message> + <message name="IDS_DEVTOOLS_9df22f196a33acd0b372fe502de51211" desc=""> + auto + </message> + <message name="IDS_DEVTOOLS_a498f0751d1221223efb0defc71cc804" desc=""> + <ph name="RENDEREDWIDTH">$1s</ph> × <ph name="RENDEREDHEIGHT">$2s</ph> pixels + </message> + <message name="IDS_DEVTOOLS_b836d99a391a4d2baf6624f8f4acbfc0" desc=""> + (intrinsic: <ph name="INTRINSICWIDTH">$1s</ph> × <ph name="INTRINSICHEIGHT">$2s</ph> pixels) + </message> + <message name="IDS_DEVTOOLS_b9dee6bade160c89fb7f0e539d453513" desc=""> + Dock to bottom + </message> + <message name="IDS_DEVTOOLS_c3fe109bf99ade2d76a55e5737015e3e" desc=""> + Stop blackboxing + </message> + <message name="IDS_DEVTOOLS_c850ae12703fa2b00eeaf8445ecf00ef" desc=""> + Show <ph name="TOTALHIDDENCALLFRAMESCOUNT">$1s</ph> more frames + </message> + <message name="IDS_DEVTOOLS_d3d2e617335f08df83599665eef8a418" desc=""> + Close + </message> + <message name="IDS_DEVTOOLS_e48081c5f0698efee665fbf8e9d123f9" desc=""> + Open using <ph name="TITLE">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_e6cd0f8a4fe4fb9e08505b784e48caa2" desc=""> + Link handling: + </message> + <message name="IDS_DEVTOOLS_f53944c3a55bdb5ad65c6226e358a626" desc=""> + Undock into separate window + </message> + <message name="IDS_DEVTOOLS_fe7fb037b290768d6a6be30b237e183d" desc=""> + Dock to right + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/console/console_strings.grdp b/third_party/blink/renderer/devtools/front_end/console/console_strings.grdp new file mode 100644 index 0000000..7d58b2c --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/console/console_strings.grdp
@@ -0,0 +1,294 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_02969932cf572213e2401893f4182af2" desc=""> + Remove all expressions + </message> + <message name="IDS_DEVTOOLS_03342349032c8ef8f5898c49a088de55" desc=""> + Accept suggestion + </message> + <message name="IDS_DEVTOOLS_047e62ee63b0c14a249a79bc6be0a493" desc=""> + Do not group similar messages in console + </message> + <message name="IDS_DEVTOOLS_04c247c2ba261c7511e4f479728bd7ea" desc=""> + Do not treat evaluation as user activation + </message> + <message name="IDS_DEVTOOLS_0511551e6cf7d61acd9b62f9304efa93" desc=""> + Do not clear log on page reload / navigation + </message> + <message name="IDS_DEVTOOLS_07213a0161f52846ab198be103b5ab43" desc=""> + errors + </message> + <message name="IDS_DEVTOOLS_0a2f561bf52ee6d8cd2dda123c8f74fe" desc=""> + Default levels + </message> + <message name="IDS_DEVTOOLS_0b03bf8af8380330766ad55ff2004a95" desc=""> + Selected context only + </message> + <message name="IDS_DEVTOOLS_0bafe921e13474bf5fc3f1ad62496905" desc=""> + [Intervention] <ph name="MESSAGETEXT">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_0bbce02e304562c295a1d57d66c296d3" desc=""> + <URL> + </message> + <message name="IDS_DEVTOOLS_0eaadb4fcb48a0a0ed7bc9868be9fbaa" desc=""> + Warning + </message> + <message name="IDS_DEVTOOLS_0fa06588bd5c83bd6f3b1734eefc6b16" desc=""> + Hide messages from <ph name="NEW_COMMON_PARSEDURL_CONSOLEMESSAGE_URL__DISPLAYNAME">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_142329f312b9f9a97f9726342813dec2" desc=""> + Next/previous line + </message> + <message name="IDS_DEVTOOLS_1a37d25ba6689d174f51ba8e2425fde6" desc=""> + <other> + </message> + <message name="IDS_DEVTOOLS_1ebc7540a5327b857144f04cf1435b4e" desc=""> + Replay XHR + </message> + <message name="IDS_DEVTOOLS_26649c8f3cadc9c0170f2443e6fc0252" desc=""> + <attribute> + </message> + <message name="IDS_DEVTOOLS_278cf66841e1d342f3115006e82c5dd9" desc=""> + Repeat <ph name="THIS__REPEATCOUNT">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_2a5a5a712c2bfb6c506cb669b8d81709" desc=""> + Clear console history + </message> + <message name="IDS_DEVTOOLS_2b76cfdf5b790de0a27ba7fc58a919c8" desc=""> + Warning <ph name="ACCESSIBLENAME">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_2b918231caba2d08f2223246ac06222c" desc=""> + Copy visible styled selection + </message> + <message name="IDS_DEVTOOLS_2c7aea4237e25b4f8ee3b0bf77d6fed0" desc=""> + verbose + </message> + <message name="IDS_DEVTOOLS_2d82fe5a069854a35204b4e64e8e08ae" desc=""> + Console settings + </message> + <message name="IDS_DEVTOOLS_2f20693f226f0545a8b68ef4f59fb02e" desc=""> + [Violation] <ph name="MESSAGETEXT">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_375855385115b292f160b5131495003d" desc=""> + console.clear() was prevented due to 'Preserve log' + </message> + <message name="IDS_DEVTOOLS_383b1deb90603a79d86f3ae82e55a9e2" desc=""> + <ph name="THIS__HIDDENBYFILTERCOUNT">$1s</ph> hidden + </message> + <message name="IDS_DEVTOOLS_3879149292f9af4469cec013785d6dfd" desc=""> + warnings + </message> + <message name="IDS_DEVTOOLS_388024c56c38c3d1c635b09a2b28b8ac" desc=""> + Value below was evaluated just now. + </message> + <message name="IDS_DEVTOOLS_3cec12c2368b11d9585823ac9d631edb" desc=""> + Hide all + </message> + <message name="IDS_DEVTOOLS_4059b0251f66a18cb56f544728796875" desc=""> + Info + </message> + <message name="IDS_DEVTOOLS_405b66a12f196edc715fe9f3f2c84b04" desc=""> + Hide timestamps + </message> + <message name="IDS_DEVTOOLS_411f3a865d83fba7f4772925666cfa7c" desc=""> + Hide network messages + </message> + <message name="IDS_DEVTOOLS_468312e6ff2ebf1b104e5d7f489de74d" desc=""> + Eagerly evaluate text in the prompt + </message> + <message name="IDS_DEVTOOLS_4c8b530161336f95d0c2f13337556954" desc=""> + Show network messages + </message> + <message name="IDS_DEVTOOLS_4cad9e20fde3f8991c5dd1d6a0fe13e7" desc=""> + Remove expression + </message> + <message name="IDS_DEVTOOLS_4d1b0b75a9737b7dcdc3a15a84fe856b" desc=""> + Searching… + </message> + <message name="IDS_DEVTOOLS_4f9afe303d0e8c68e3518756e1734924" desc=""> + Clear console prompt + </message> + <message name="IDS_DEVTOOLS_53f0fca28a013c116a1df533d9bdf764" desc=""> + [Deprecation] <ph name="MESSAGETEXT">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_5ef0c737746fae2ca90e66c39333f8f6" desc=""> + Errors + </message> + <message name="IDS_DEVTOOLS_5f8442a46861496e9d2a3d11be13692b" desc=""> + Writing file… + </message> + <message name="IDS_DEVTOOLS_6047a6c9fb775557639afb3fbc90b4e7" desc=""> + Log levels + </message> + <message name="IDS_DEVTOOLS_63e4e92bb7d207ca577b11c07f827279" desc=""> + Extension + </message> + <message name="IDS_DEVTOOLS_650140bd73628d283d870d4648ae3324" desc=""> + Find string in logs + </message> + <message name="IDS_DEVTOOLS_689202409e48743b914713f96d93947c" desc=""> + Value + </message> + <message name="IDS_DEVTOOLS_6cdd8769d46bb96331ac4a96d3ea84b8" desc=""> + Clear all messages with <ph name="UI_SHORTCUTREGISTRY_SHORTCUTTITLEFORACTION__CONSOLE_CLEAR__">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_6eed4ce2d5859b11dc44a5e3bd91af20" desc=""> + Eager evaluation + </message> + <message name="IDS_DEVTOOLS_78e731027d8fd50ed642340b7c9a63b3" desc=""> + message + </message> + <message name="IDS_DEVTOOLS_7a1920d61156abc05a60135aefe8bc67" desc=""> + Default + </message> + <message name="IDS_DEVTOOLS_7b83d3f08fa392b79e3f553b585971cd" desc=""> + warning + </message> + <message name="IDS_DEVTOOLS_7be1a30a7758269755609f1f7434d828" desc=""> + Group similar messages in console + </message> + <message name="IDS_DEVTOOLS_84d0c431d1472a0609d69b39dcb3a287" desc=""> + (index) + </message> + <message name="IDS_DEVTOOLS_902b0d55fddef6f8d651fe1035b7d4bd" desc=""> + Error + </message> + <message name="IDS_DEVTOOLS_93977f1310f482395375a9950b512462" desc=""> + Eagerly evaluate console prompt text + </message> + <message name="IDS_DEVTOOLS_95c74dafb449d894014c2eb1d80ded01" desc=""> + Edit expression + </message> + <message name="IDS_DEVTOOLS_988aa266ba49ce9da4c7e10f4b477ec4" desc=""> + Next/previous command + </message> + <message name="IDS_DEVTOOLS_9aae9fe27dbf2db0ad90762b5b59d3a7" desc=""> + Clear console + </message> + <message name="IDS_DEVTOOLS_9d8c209e49e328528c39c273798e98c9" desc=""> + Save as... + </message> + <message name="IDS_DEVTOOLS_a092483ed730ed040e5df5776dca49e5" desc=""> + Log XMLHttpRequests + </message> + <message name="IDS_DEVTOOLS_a1948ddb50d0bbd31e36f1fbc45479a0" desc=""> + Autocomplete from history + </message> + <message name="IDS_DEVTOOLS_a1a6657be79cc0fc1e9b23b9e108f043" desc=""> + Expression + </message> + <message name="IDS_DEVTOOLS_a3eb3c95c4cb8e06fd3682c1f0d70bc0" desc=""> + Only show messages from the current context (top, iframe, worker, extension) + </message> + <message name="IDS_DEVTOOLS_abba8787b900565790eae8ceceed3c2b" desc=""> + Do not autocomplete from history + </message> + <message name="IDS_DEVTOOLS_ac17bdcb3f6c8d86ccb64aff1ab8db7c" desc=""> + Console was cleared + </message> + <message name="IDS_DEVTOOLS_ac2671ba859591dd83845c680aaa144e" desc=""> + user messages + </message> + <message name="IDS_DEVTOOLS_ace3e0307b2ce23a81b18747fc5f555f" desc=""> + Function was resolved from bound function. + </message> + <message name="IDS_DEVTOOLS_b184e7a44bed11a41d9c104529010e23" desc=""> + <ph name="THIS__LEVELLABELS_NAME_">$1s</ph> only + </message> + <message name="IDS_DEVTOOLS_b2f8489bbd55a4e9b9edbbbfe49edf70" desc=""> + not available + </message> + <message name="IDS_DEVTOOLS_b5735f8c6deff6306a2216612ca80f0e" desc=""> + JavaScript contexts + </message> + <message name="IDS_DEVTOOLS_bafd7322c6e97d25b6299b5d6fe8920b" desc=""> + No + </message> + <message name="IDS_DEVTOOLS_bb63b17b21e67aa2cc30cf01bae36695" desc=""> + Execute command + </message> + <message name="IDS_DEVTOOLS_bccaa4aa80831b76c11240a16447975f" desc=""> + Console + </message> + <message name="IDS_DEVTOOLS_c0274fa278f2e0dfef862234e0eb9b8b" desc=""> + <exception> + </message> + <message name="IDS_DEVTOOLS_c9818b2c0890a205d294a2b31354f8b4" desc=""> + All levels + </message> + <message name="IDS_DEVTOOLS_ca3c4b269c23985d3c1204c203ad84d8" desc=""> + Group similar + </message> + <message name="IDS_DEVTOOLS_ca6ceb8e597abb1298b84b1aaadc229b" desc=""> + Show timestamps + </message> + <message name="IDS_DEVTOOLS_caf037034c3205725511c1216f772402" desc=""> + <some> event + </message> + <message name="IDS_DEVTOOLS_caf9b6b99962bf5c2264824231d7a40c" desc=""> + info + </message> + <message name="IDS_DEVTOOLS_cb5e100e5a9a3e7f6d1fd97512215282" desc=""> + error + </message> + <message name="IDS_DEVTOOLS_cf3eed6aa30c47cec1321a835dc7b1ac" desc=""> + Treat evaluation as user activation + </message> + <message name="IDS_DEVTOOLS_d0990066fbdfd3753fb45300d57e4364" desc=""> + Hide network + </message> + <message name="IDS_DEVTOOLS_d35866a5d1161b48670e28e8c8550e89" desc=""> + Assertion failed: + </message> + <message name="IDS_DEVTOOLS_d3f526e5326c06d47ab12240d604f87a" desc=""> + took <N>ms + </message> + <message name="IDS_DEVTOOLS_d4a9fa383ab700c5bdd6f31cf7df0faf" desc=""> + Verbose + </message> + <message name="IDS_DEVTOOLS_d61de8e8b9dfdf0e7a52bf2e4fd23e72" desc=""> + M<XX> + </message> + <message name="IDS_DEVTOOLS_d7746aa6b562c73487a4015eef3244e9" desc=""> + IFrame + </message> + <message name="IDS_DEVTOOLS_d7778d0c64b6ba21494c97f77a66885a" desc=""> + Filter + </message> + <message name="IDS_DEVTOOLS_d779282283c011149d163edbcd5e5f11" desc=""> + Evaluate, allowing side effects + </message> + <message name="IDS_DEVTOOLS_de6fc8cb2d1b20158aeda5cd1cb2e03c" desc=""> + Show messages from all contexts + </message> + <message name="IDS_DEVTOOLS_de70938849b75d3db63bba421c93e018" desc=""> + messages + </message> + <message name="IDS_DEVTOOLS_dfcc689f6e70e39a408b78912822cec9" desc=""> + Error <ph name="ACCESSIBLENAME">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_e178ba306750ffbfdba284f60a3743b0" desc=""> + Do not eagerly evaluate console prompt text + </message> + <message name="IDS_DEVTOOLS_e17fdb615452f440c793b5ddad90dd5e" desc=""> + Warnings + </message> + <message name="IDS_DEVTOOLS_e1dd1b8e32626f508bd3a5612a60ab97" desc=""> + Create live expression + </message> + <message name="IDS_DEVTOOLS_eacaf2bd1c1414e5086cf04573e154ef" desc=""> + e.g. /event\d/ -cdn url:a.com + </message> + <message name="IDS_DEVTOOLS_ebfab4df1bb91688c62d4523eba870a5" desc=""> + Evaluate triggers user activation + </message> + <message name="IDS_DEVTOOLS_f8ec55cf268ca6106fb23a98523b7549" desc=""> + user message + </message> + <message name="IDS_DEVTOOLS_fb554075057f4d116097df434bcef393" desc=""> + This value will not be collected until console is cleared. + </message> + <message name="IDS_DEVTOOLS_fbb5dc83cad4daf746720c90bfb8d306" desc=""> + Custom levels + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/console_counters/console_counters_strings.grdp b/third_party/blink/renderer/devtools/front_end/console_counters/console_counters_strings.grdp new file mode 100644 index 0000000..d2ead3e --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/console_counters/console_counters_strings.grdp
@@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_5415b9709f6fda34d7148558bbf4e36b" desc=""> + <ph name="WARNINGS">$1s</ph> warning + </message> + <message name="IDS_DEVTOOLS_8e8fda2f7538782b27f82f8ec3c160eb" desc=""> + <ph name="WARNINGS">$1s</ph> warnings + </message> + <message name="IDS_DEVTOOLS_9a075279073f00bab27c1c7612bb9fc0" desc=""> + <ph name="ERRORS">$1s</ph> errors + </message> + <message name="IDS_DEVTOOLS_a1c00c8d8c543411f73883be7ecfb01b" desc=""> + <ph name="ERRORS">$1s</ph> error + </message> + <message name="IDS_DEVTOOLS_dac90a385f9ee1c4d4cac02579d68185" desc=""> + <ph name="VIOLATIONS">$1s</ph> violation + </message> + <message name="IDS_DEVTOOLS_de292077f92bbd36f5b8bd7131f2ef5a" desc=""> + <ph name="VIOLATIONS">$1s</ph> violations + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/cookie_table/cookie_table_strings.grdp b/third_party/blink/renderer/devtools/front_end/cookie_table/cookie_table_strings.grdp new file mode 100644 index 0000000..3c816c9 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/cookie_table/cookie_table_strings.grdp
@@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_2e7501c512976a9d9a9dca45bce9f128" desc=""> + Expires / Max-Age + </message> + <message name="IDS_DEVTOOLS_382b0f5185773fa0f67a8ed8056c7759" desc=""> + N/A + </message> + <message name="IDS_DEVTOOLS_49ee3087348e8d44e1feda1917443987" desc=""> + Name + </message> + <message name="IDS_DEVTOOLS_6c8f0cef6081f0f97ec0f01a5a3ce2a7" desc=""> + HttpOnly + </message> + <message name="IDS_DEVTOOLS_6f6cb72d544962fa333e2e34ce64f719" desc=""> + Size + </message> + <message name="IDS_DEVTOOLS_71c7ae294b7abd866b3fb295b3b9e4a4" desc=""> + Session + </message> + <message name="IDS_DEVTOOLS_7a2ccf251ecb20b2b84ce0e3c3f72a29" desc=""> + Secure + </message> + <message name="IDS_DEVTOOLS_9f8e4d5e9b6d7a439dc6b5ebc5eedca4" desc=""> + SameSite + </message> + <message name="IDS_DEVTOOLS_ac70412e939d72a9234cdebb1af5867b" desc=""> + Path + </message> + <message name="IDS_DEVTOOLS_eae639a70006feff484a39363c977e24" desc=""> + Domain + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/coverage/coverage_strings.grdp b/third_party/blink/renderer/devtools/front_end/coverage/coverage_strings.grdp new file mode 100644 index 0000000..42fd14a8 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/coverage/coverage_strings.grdp
@@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_0975cd80b6efbfa27546aa1567bc8143" desc=""> + Instrument coverage + </message> + <message name="IDS_DEVTOOLS_140f5ed61f8c7390c3e38d7f6af6bd4b" desc=""> + Click the record button <ph name="RECORDBUTTON">$1s</ph> to start capturing coverage. +Click the reload button <ph name="RELOADBUTTON">$2s</ph> to reload and start capturing coverage. + </message> + <message name="IDS_DEVTOOLS_1a49594b5f00e4f511ae8935c027cd8e" desc=""> + Unused Bytes + </message> + <message name="IDS_DEVTOOLS_2adbfb69a37aa4a29ca846736d2111db" desc=""> + JS (coarse) + </message> + <message name="IDS_DEVTOOLS_2c56c360580420d293172f42d85dfbed" desc=""> + CSS + </message> + <message name="IDS_DEVTOOLS_5bc06f5800d415cc95e1349edbaca425" desc=""> + JS + </message> + <message name="IDS_DEVTOOLS_6525b37c568c526bde7c02fac8195c73" desc=""> + <ph name="UNUSEDSIZE___THIS__COVERAGEINFO_SIZE________">$1.1f</ph> %% + </message> + <message name="IDS_DEVTOOLS_73af525212a812236f1a3618e9cfa717" desc=""> + Export... + </message> + <message name="IDS_DEVTOOLS_8324d82d6d4baaa0405621a1a15f365a" desc=""> + Stop instrumenting coverage and show results + </message> + <message name="IDS_DEVTOOLS_832e506a71f4a57ed15ecbcd771f9247" desc=""> + Total Bytes + </message> + <message name="IDS_DEVTOOLS_8e8c9f0a8c3469d9900728e8b1d451cb" desc=""> + URL filter + </message> + <message name="IDS_DEVTOOLS_95dd3a82779cda9791819969c51c97d3" desc=""> + Click the record button <ph name="RECORDBUTTON">$1s</ph> to start capturing coverage. + </message> + <message name="IDS_DEVTOOLS_9841bdc50c4226cb6ec5db76494249e6" desc=""> + Coverage + </message> + <message name="IDS_DEVTOOLS_a1fa27779242b4902f7ae3bdd5c6d508" desc=""> + Type + </message> + <message name="IDS_DEVTOOLS_bca27ccb808f436cd1ce828dd47604b7" desc=""> + Start instrumenting coverage and reload page + </message> + <message name="IDS_DEVTOOLS_c4ba5b981ea7d2c17178a6c879cc03bd" desc=""> + <ph name="NUMBER_BYTESTOSTRING_UNUSED_">$1s</ph> of <ph name="NUMBER_BYTESTOSTRING_TOTAL_">$2s</ph> bytes are not used. (<ph name="PERCENTUNUSED">$3d</ph>%%) + </message> + <message name="IDS_DEVTOOLS_d95b97f3bac1a32fc1f27686f74b97de" desc=""> + JS coverage is function-level only. Reload the page for block-level coverage. + </message> + <message name="IDS_DEVTOOLS_d98bd5257b9f29c266777264411735a3" desc=""> + Include extension content scripts + </message> + <message name="IDS_DEVTOOLS_e6b391a8d2c4d45902a23a8b6585703d" desc=""> + URL + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/data_grid/data_grid_strings.grdp b/third_party/blink/renderer/devtools/front_end/data_grid/data_grid_strings.grdp new file mode 100644 index 0000000..0cd51ef --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/data_grid/data_grid_strings.grdp
@@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_28de94c6a82d4419a4014addb8aba93c" desc=""> + Show <ph name="THIS__CHUNKSIZE">$1d</ph> after + </message> + <message name="IDS_DEVTOOLS_b33d161950658a73abe8675d311345d2" desc=""> + Edit "<ph name="THIS__COLUMNS_COLUMNID__TITLE">$1s</ph>" + </message> + <message name="IDS_DEVTOOLS_d73d1ee203c4075522513de6fe5557c8" desc=""> + Show <ph name="THIS__CHUNKSIZE">$1d</ph> before + </message> + <message name="IDS_DEVTOOLS_e199c6bb662785b037c5f330f58878ce" desc=""> + Show all <ph name="TOTALSIZE">$1d</ph> + </message> + <message name="IDS_DEVTOOLS_ef61fb324d729c341ea8ab9901e23566" desc=""> + Add new + </message> + <message name="IDS_DEVTOOLS_f2a6c498fb90ee345d997f888fce3b18" desc=""> + Delete + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/devices/devices_strings.grdp b/third_party/blink/renderer/devtools/front_end/devices/devices_strings.grdp new file mode 100644 index 0000000..07a3116 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/devices/devices_strings.grdp
@@ -0,0 +1,111 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_00fcbe531dd989e566cab0a9e250f14c" desc=""> + Port Forwarding: + </message> + <message name="IDS_DEVTOOLS_03fc5c0bd59679c442b86074c7a7cc3a" desc=""> + Port forwarding + </message> + <message name="IDS_DEVTOOLS_042909a8044ec8e1a97069bfdde2fe58" desc=""> + Connected: <ph name="CONNECTED_JOIN______">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_049c45b298c6bc7540d84ab593bedaa6" desc=""> + Transient: <ph name="TRANSIENT_JOIN______">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_0dec6438ad2d934e57d33026770654d1" desc=""> + remote debugging documentation + </message> + <message name="IDS_DEVTOOLS_10e10a814f3c1f9a5e847376c975ea3c" desc=""> + Error: <ph name="ERROR_JOIN______">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_2157ba7738ed20565fd089f2a6287cdd" desc=""> + View less tabs… + </message> + <message name="IDS_DEVTOOLS_258771f02f7548d3282560829e7c9b69" desc=""> + Define the listening port on your device that maps to a port accessible from your development machine. + </message> + <message name="IDS_DEVTOOLS_2ec0d16e4ca169baedb9b2d50ec5c6d7" desc=""> + Connected + </message> + <message name="IDS_DEVTOOLS_34fdf6d76ae3464206146053c8aedcd7" desc=""> + <ph name="THIS__DEVICES_LENGTH">$1d</ph> devices detected. + </message> + <message name="IDS_DEVTOOLS_35a9dbe6b748771b9ea4d5962d37ff6f" desc=""> + Inspect + </message> + <message name="IDS_DEVTOOLS_405590b3c5865df635f2373ee4cb799c" desc=""> + Remote devices + </message> + <message name="IDS_DEVTOOLS_4d1c8263ba1036754f8db14a98f9f006" desc=""> + Reload + </message> + <message name="IDS_DEVTOOLS_67afa587522e088dedac9f252362d16a" desc=""> + Discover USB devices + </message> + <message name="IDS_DEVTOOLS_6ab4529805e55f79b589f0676435dc4e" desc=""> + Pending Authorization + </message> + <message name="IDS_DEVTOOLS_85bd3d2945bf008087e0a3a7d714ae80" desc=""> + localhost: + </message> + <message name="IDS_DEVTOOLS_88183b946cc5f0e8c96b2e66e1c74a7e" desc=""> + Unknown + </message> + <message name="IDS_DEVTOOLS_8c7074069d61ba9d2f76b078fb1dd154" desc=""> + Need help? Read Chrome + </message> + <message name="IDS_DEVTOOLS_926f97ab5b90b053d6a3a31082316f15" desc=""> + No browsers detected. + </message> + <message name="IDS_DEVTOOLS_9b5e7fc14b157afb268b71b01d397eef" desc=""> + Add rule + </message> + <message name="IDS_DEVTOOLS_9ba01fbecae523e4160afa26f75f1757" desc=""> + View more tabs… + </message> + <message name="IDS_DEVTOOLS_a105a2ea6a8f53afe9640d8684ffe5d5" desc=""> + Read + </message> + <message name="IDS_DEVTOOLS_a2040c5569ac3718b10af77aaa3fbb03" desc=""> + Pending authentication: please accept debugging session on the device. + </message> + <message name="IDS_DEVTOOLS_bcca96534b404f08faf65d76be6aa782" desc=""> + 1 device detected. + </message> + <message name="IDS_DEVTOOLS_c03ca67dda321195d74c951097f240c6" desc=""> + Devices + </message> + <message name="IDS_DEVTOOLS_c3bf447eabe632720a3aa1a7ce401274" desc=""> + Open + </message> + <message name="IDS_DEVTOOLS_c9d2bd107ad7a2c20f80efcaaf365d23" desc=""> + for more information. + </message> + <message name="IDS_DEVTOOLS_cc63a5ac37dd9d1c607a59aad3292392" desc=""> + No rules + </message> + <message name="IDS_DEVTOOLS_ceb747e16b7e536d03047492e4491314" desc=""> + remote debugging documentation. + </message> + <message name="IDS_DEVTOOLS_d38dcac8af912356e255cbace8984e9a" desc=""> + New tab: + </message> + <message name="IDS_DEVTOOLS_dabcc308341c912a6b620e1c980e16d6" desc=""> + No devices detected. + </message> + <message name="IDS_DEVTOOLS_e1f70f4a4265cb51c1b219aa60eaa441" desc=""> + Enter URL + </message> + <message name="IDS_DEVTOOLS_e24ee2487879116dcab772c0ac4fe341" desc=""> + Focus + </message> + <message name="IDS_DEVTOOLS_f114563447e4786042d7e7ce05f1157c" desc=""> + Device port (3333) + </message> + <message name="IDS_DEVTOOLS_f4f70727dc34561dfde1a3c529b6205c" desc=""> + Settings + </message> + <message name="IDS_DEVTOOLS_ff89b835f4fc414c9c8f4f96695c2ea8" desc=""> + Local address (dev.example.corp:3333) + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/elements/elements_strings.grdp b/third_party/blink/renderer/devtools/front_end/elements/elements_strings.grdp new file mode 100644 index 0000000..bf0f5fb2 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/elements/elements_strings.grdp
@@ -0,0 +1,327 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_068bc495b79facfaa7918369fa9909eb" desc=""> + Cut element + </message> + <message name="IDS_DEVTOOLS_07f01edb2a05909a9c0d04031d7c43e1" desc=""> + Filter Styles + </message> + <message name="IDS_DEVTOOLS_081c9f670acb11b080077b3fb6127b4c" desc=""> + Add box-shadow + </message> + <message name="IDS_DEVTOOLS_084cd932d6dd317197a20945c76603e2" desc=""> + Inherited from<ph name="___">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_0b17e22ff13be64e3216014d9c2a5354" desc=""> + Enable DOM word wrap + </message> + <message name="IDS_DEVTOOLS_10d084d908583b210d2b1c470855a1d4" desc=""> + Hide HTML comments + </message> + <message name="IDS_DEVTOOLS_14ec3eb094717596986aeef905ecb2d2" desc=""> + New Style Rule + </message> + <message name="IDS_DEVTOOLS_1bc005d87dc22486bbb3c662b6fe46ce" desc=""> + Pseudo ::<ph name="PSEUDOTYPE">$1s</ph> element + </message> + <message name="IDS_DEVTOOLS_1cc5c88b14a818f9f8d053f3c9f9249e" desc=""> + Word wrap + </message> + <message name="IDS_DEVTOOLS_20bfc7bb53e1d2639556bce9852c32d8" desc=""> + Resolve event listeners bound with framework + </message> + <message name="IDS_DEVTOOLS_21c12abe8367dcbdf5d3fee56a4ae9d8" desc=""> + Show detailed inspect tooltip + </message> + <message name="IDS_DEVTOOLS_22a11a2e07e4412afd106977262d7617" desc=""> + Copy selector + </message> + <message name="IDS_DEVTOOLS_254dd634c2a4b01fad95fe963b193ba8" desc=""> + Page DOM + </message> + <message name="IDS_DEVTOOLS_28c0a3050f784583d52339ddb0bc1274" desc=""> + Paste element + </message> + <message name="IDS_DEVTOOLS_2becb310c9830fe3fb19d18eb1808712" desc=""> + (<ph name="USAGE">$1d</ph> glyph) + </message> + <message name="IDS_DEVTOOLS_2c0a7043a9e736eaf14b6614fff102c0" desc=""> + Computed + </message> + <message name="IDS_DEVTOOLS_2ce5967e3862c73a31059c4aa5847464" desc=""> + Open shadow editor. + </message> + <message name="IDS_DEVTOOLS_2ddaa8e6378b906b42429dc4003edbd3" desc=""> + Reveal in Elements panel + </message> + <message name="IDS_DEVTOOLS_2de42fbb00305f8282310f1b3e10ce9a" desc=""> + border + </message> + <message name="IDS_DEVTOOLS_2dff19d6ed78c6ca35cb3beab7b5bf55" desc=""> + Rendered Fonts + </message> + <message name="IDS_DEVTOOLS_2e6591ba49ec23bf6725b74589b66ba3" desc=""> + styles sidebar + </message> + <message name="IDS_DEVTOOLS_2f76fab71405b40cf521f64eab0d350f" desc=""> + Delete element + </message> + <message name="IDS_DEVTOOLS_3427db2c4cb9d8d61c1dd32d218d5699" desc=""> + Use $0 in the console to refer to this element. + </message> + <message name="IDS_DEVTOOLS_365fee797b55ffeac84d2ba82507b721" desc=""> + user agent stylesheet + </message> + <message name="IDS_DEVTOOLS_3afbd9828e011526955ca93b48b57524" desc=""> + Screenshot + </message> + <message name="IDS_DEVTOOLS_3bb3e8c8a24891ba0f7608bcc96f8b0a" desc=""> + Frame + </message> + <message name="IDS_DEVTOOLS_3e255d6c811a40b9ad197fedeadc342c" desc=""> + Local file + </message> + <message name="IDS_DEVTOOLS_3e9bec182c7495247f5f93d3881d630b" desc=""> + :hov + </message> + <message name="IDS_DEVTOOLS_3f8f88e3686b2345cecc9530e19e6172" desc=""> + Store as global variable + </message> + <message name="IDS_DEVTOOLS_417117e823d14c9b7c6533e4b04600a6" desc=""> + (text) + </message> + <message name="IDS_DEVTOOLS_44beac36afb00f088edb0aeab28a300d" desc=""> + Edit text + </message> + <message name="IDS_DEVTOOLS_45a921ffccbc28c2ff80adada350224f" desc=""> + <node> + </message> + <message name="IDS_DEVTOOLS_47210336f82b1488b69932b14038bdff" desc=""> + Increment/decrement with mousewheel or up/down keys. <ph name="CMDORCTRL">$1s</ph>: ±100, Shift: ±10, Alt: ±0.1 + </message> + <message name="IDS_DEVTOOLS_4757fe07fd492a8be0ea6a760d683d6e" desc=""> + position + </message> + <message name="IDS_DEVTOOLS_4c1c7d945fcd04d68bd3b3f1d99a55a1" desc=""> + Styles + </message> + <message name="IDS_DEVTOOLS_4ca94080ccbd5784f5fe296bf1ae3e12" desc=""> + Event Listeners + </message> + <message name="IDS_DEVTOOLS_4cf8e5f6ffbb182b5d480cbabae6a028" desc=""> + Edit attribute + </message> + <message name="IDS_DEVTOOLS_4d9468d79ef34f71ba78a28688fa5d31" desc=""> + Ancestors + </message> + <message name="IDS_DEVTOOLS_5134111907df828fc575c69e22480c1e" desc=""> + Hide element + </message> + <message name="IDS_DEVTOOLS_51f30f4743bd8f0e7141781bd2d93abb" desc=""> + Set color format as authored + </message> + <message name="IDS_DEVTOOLS_55e1bbb4e00add64284ed28f15d40b25" desc=""> + Color format: + </message> + <message name="IDS_DEVTOOLS_581b87189d0bd86aa707e42553032a3e" desc=""> + Children: + </message> + <message name="IDS_DEVTOOLS_5ad5ecf0bc5b6e08d886efd6f6e5649b" desc=""> + Show HTML comments + </message> + <message name="IDS_DEVTOOLS_5adda1916cde33ce6e49c22ba58f03f7" desc=""> + injected stylesheet + </message> + <message name="IDS_DEVTOOLS_5c6236c705b0086fbbdb2df3133f8a06" desc=""> + Reveal DOM node on hover + </message> + <message name="IDS_DEVTOOLS_5de39fa1bce4bbf9232597a2120bc4d4" desc=""> + Open cubic bezier editor. + </message> + <message name="IDS_DEVTOOLS_5eeb03a9c080c299d4804ac765c818c2" desc=""> + No matching selector or style + </message> + <message name="IDS_DEVTOOLS_5fb63579fc981698f97d55bfecb213ea" desc=""> + Copy + </message> + <message name="IDS_DEVTOOLS_6053f828a109e7d9da3690a7416e4eec" desc=""> + Copy XPath + </message> + <message name="IDS_DEVTOOLS_605e072850e19521394f8bad7082acf4" desc=""> + Force element state + </message> + <message name="IDS_DEVTOOLS_63041e09c8660107e507c9c27c08199c" desc=""> + Expand recursively + </message> + <message name="IDS_DEVTOOLS_686676f33cf19ca00788564f43b992cb" desc=""> + Filter Computed Styles + </message> + <message name="IDS_DEVTOOLS_68a483c15a1730a88f2a57b1b1b8b69a" desc=""> + Event listeners category + </message> + <message name="IDS_DEVTOOLS_69f83bbab45ca27c374e76d304ab76be" desc=""> + Find by string, selector, or XPath + </message> + <message name="IDS_DEVTOOLS_6ac7142d0aa79d17f03677fac1249c98" desc=""> + Force state + </message> + <message name="IDS_DEVTOOLS_6ae2f9f803d108269a2cdb714b9851a1" desc=""> + <ph name="NODE_NODENAMEINCORRECTCASE__">$1s</ph>[Attributes Style] + </message> + <message name="IDS_DEVTOOLS_6f3cab519fe7e8f3b7834cf882f9dfe6" desc=""> + Element Classes + </message> + <message name="IDS_DEVTOOLS_78e0b69d17e0287aaae4f79171e5b059" desc=""> + Disable DOM word wrap + </message> + <message name="IDS_DEVTOOLS_795630f9fe735d5c002f28f851d78fac" desc=""> + Framework listeners + </message> + <message name="IDS_DEVTOOLS_7c90d60be6418bb4a858b3733b2560a8" desc=""> + Unknown property name + </message> + <message name="IDS_DEVTOOLS_8551fe4a09c280c278283c10a5a6aa4e" desc=""> + Increment/decrement with mousewheel or up/down keys. <ph name="CMDORCTRL">$1s</ph>: R ±1, Shift: G ±1, Alt: B ±1 + </message> + <message name="IDS_DEVTOOLS_88556207e275bc7d802b4706268d61ae" desc=""> + Copy JS path + </message> + <message name="IDS_DEVTOOLS_88a306e559954dc8c8ae9eb55d62297f" desc=""> + Add attribute + </message> + <message name="IDS_DEVTOOLS_8bd236209fc42bdeffdecd1cc68d7b86" desc=""> + Open color picker. <ph name="SHIFTCLICKMESSAGE">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_8d41e41bf0856d309b43d776c24a0316" desc=""> + Add new class + </message> + <message name="IDS_DEVTOOLS_8f17243e20db8af877d205e488b1f521" desc=""> + Element state: <ph name="______NODE_DOMMODEL___CSSMODEL___PSEUDOSTATE_NODE__JOIN_______">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_91d17eff6a1529e8a4f67a5aa4cabec7" desc=""> + No matching property + </message> + <message name="IDS_DEVTOOLS_956853d02d2c6947b6c15515e669dfad" desc=""> + Set color format to RGB + </message> + <message name="IDS_DEVTOOLS_9835cebf3cf1d09803b6e2c02bc71401" desc=""> + HSL: hsl(300, 80%, 90%) + </message> + <message name="IDS_DEVTOOLS_9a0364b9e99bb480dd25e1f0284c8555" desc=""> + content + </message> + <message name="IDS_DEVTOOLS_9fc2d28c05ed9eb1d75ba4465abf15a9" desc=""> + Properties + </message> + <message name="IDS_DEVTOOLS_a05fb8660778069f6d4a5c5b40a6dbc9" desc=""> + Show user agent shadow DOM + </message> + <message name="IDS_DEVTOOLS_a2f8f2d457d122dd0d135781187aef31" desc=""> + Invalid property value + </message> + <message name="IDS_DEVTOOLS_a78163b8c3f5e5a69fddd2a70c7f7309" desc=""> + Style Attribute + </message> + <message name="IDS_DEVTOOLS_a98895bde5922dd43c82ad7050abc05a" desc=""> + Show listeners on the ancestors + </message> + <message name="IDS_DEVTOOLS_aa56a2e65d8106aef3c61e4f6bf94fdb" desc=""> + Elements + </message> + <message name="IDS_DEVTOOLS_abdf882c25e08d9ba219fe33f17591fe" desc=""> + reveal + </message> + <message name="IDS_DEVTOOLS_acc24772ac31677d076f17d9002b57cd" desc=""> + Collapse children + </message> + <message name="IDS_DEVTOOLS_ad4ac01e4a5688063dace5ba5d0f04de" desc=""> + Insert Style Rule Below + </message> + <message name="IDS_DEVTOOLS_b0351810a5721f657b088608865849dd" desc=""> + via inspector + </message> + <message name="IDS_DEVTOOLS_b1c94ca2fbc3e78fc30069c8d0f01680" desc=""> + All + </message> + <message name="IDS_DEVTOOLS_b70cdb878a204fecf91c7dd1af312421" desc=""> + padding + </message> + <message name="IDS_DEVTOOLS_b9740e9a829cf440e2e863124d53eba3" desc=""> + Shift + Click to change color format. + </message> + <message name="IDS_DEVTOOLS_bd0ca6be53b0f3d2886fd53fcb52574e" desc=""> + Blocking + </message> + <message name="IDS_DEVTOOLS_be9548cd999232697505d4ca2eed2a23" desc=""> + Elements panel + </message> + <message name="IDS_DEVTOOLS_bf22eb56a74b42a33fecf10c831e9509" desc=""> + Copy outerHTML + </message> + <message name="IDS_DEVTOOLS_c3c20058cbdd08782b780612204daafd" desc=""> + Select an element in the page to inspect it + </message> + <message name="IDS_DEVTOOLS_c63621d0ad5163e8c643bb65c65b5aee" desc=""> + Set color format to HEX + </message> + <message name="IDS_DEVTOOLS_c64955a6a59816d4e1206d600020a9fe" desc=""> + Copy element + </message> + <message name="IDS_DEVTOOLS_c736f6b512801b5fe4670e5968ee7be7" desc=""> + Toggle Element State + </message> + <message name="IDS_DEVTOOLS_c8466ef18413aebb4d6ebfce4e1f739d" desc=""> + RGB: rgb(128, 255, 255) + </message> + <message name="IDS_DEVTOOLS_c8997c00026b49aa07e0a8c11511e390" desc=""> + Add text-shadow + </message> + <message name="IDS_DEVTOOLS_c8f439c7ee24c34bc0b2e39a976509ad" desc=""> + (<ph name="USAGE">$1d</ph> glyphs) + </message> + <message name="IDS_DEVTOOLS_cbb022167129a9f635cb4a73b5c72caa" desc=""> + <value is too large to edit> + </message> + <message name="IDS_DEVTOOLS_d0ad356f675744ef8f0311e83400b6ba" desc=""> + Network resource + </message> + <message name="IDS_DEVTOOLS_d42f4851e770aa0f758b01388874f67b" desc=""> + margin + </message> + <message name="IDS_DEVTOOLS_d838bef326860912aa08d977cf3a5f8b" desc=""> + HEX: #dac0de + </message> + <message name="IDS_DEVTOOLS_d981fcf0c74837202331700aca88c801" desc=""> + As authored + </message> + <message name="IDS_DEVTOOLS_eb92025cb8c66f1850c13a9b602a1856" desc=""> + Show all + </message> + <message name="IDS_DEVTOOLS_eeb9a8e813f34f5f036332efc0257246" desc=""> + Capture area screenshot + </message> + <message name="IDS_DEVTOOLS_f2a70e3a6d14a56de7ebbb5b748ed127" desc=""> + Add color + </message> + <message name="IDS_DEVTOOLS_f3d48b9ad0a801282e3adc8b452d5fc0" desc=""> + Edit as HTML + </message> + <message name="IDS_DEVTOOLS_f750c8807bc5f4a7bd259788114a4ebd" desc=""> + Add background-color + </message> + <message name="IDS_DEVTOOLS_f80bc338b6146b566004a046f8137c85" desc=""> + Passive + </message> + <message name="IDS_DEVTOOLS_f8d0f1896a9e4ad16d43caa28534df32" desc=""> + Show All Properties (<ph name="PROPERTIES_LENGTH___COUNT">$1s</ph> more) + </message> + <message name="IDS_DEVTOOLS_fa480abba67730dd6bd15aa40308d78a" desc=""> + Set color format to HSL + </message> + <message name="IDS_DEVTOOLS_fcc980247db918e1b666b78ec7093d8c" desc=""> + Element is hidden + </message> + <message name="IDS_DEVTOOLS_fd9bcae718daadf263a2e73c7745f0a7" desc=""> + Show All Nodes (<ph name="VISIBLECHILDREN_LENGTH___EXPANDEDCHILDCOUNT">$1d</ph> More) + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/emulated_devices/emulated_devices_strings.grdp b/third_party/blink/renderer/devtools/front_end/emulated_devices/emulated_devices_strings.grdp new file mode 100644 index 0000000..ab04673 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/emulated_devices/emulated_devices_strings.grdp
@@ -0,0 +1,102 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_012528cb9fb45d278755f9fec090ed11" desc=""> + Laptop with MDPI screen + </message> + <message name="IDS_DEVTOOLS_079a3d134d2387adc52b2b3895f85e55" desc=""> + iPhone X + </message> + <message name="IDS_DEVTOOLS_0d1160fe394d87ddbc2ca8e7cc25379d" desc=""> + Laptop with touch + </message> + <message name="IDS_DEVTOOLS_0e5aeadd53726e96d7d9faa671b423ae" desc=""> + Kindle Fire HDX + </message> + <message name="IDS_DEVTOOLS_1b9018182a49e16ba85bb095f224867c" desc=""> + iPad + </message> + <message name="IDS_DEVTOOLS_2235bd527cc1684230b1db146c570a9d" desc=""> + Pixel 2 + </message> + <message name="IDS_DEVTOOLS_2c17ed2506add59c15ea763801cfafb1" desc=""> + Nexus 6 + </message> + <message name="IDS_DEVTOOLS_2d1fbe61c136940101281ec1df805c01" desc=""> + Nexus 5 + </message> + <message name="IDS_DEVTOOLS_2d9a25096b47a022c95787ab90308d6b" desc=""> + LG Optimus L70 + </message> + <message name="IDS_DEVTOOLS_4a321c67ad4bac0f3386f5e257b1fba3" desc=""> + Laptop with HiDPI screen + </message> + <message name="IDS_DEVTOOLS_6247fa438881677e5f910b89db1974a7" desc=""> + Nokia N9 + </message> + <message name="IDS_DEVTOOLS_659810deafc0279869114daf8446ef4a" desc=""> + Nexus 10 + </message> + <message name="IDS_DEVTOOLS_6d9131a4a569108e7d19038b27111c86" desc=""> + Nexus 5X + </message> + <message name="IDS_DEVTOOLS_71e3580e3c3a03f17798ebccaad9e6cb" desc=""> + Nexus 7 + </message> + <message name="IDS_DEVTOOLS_71f859515e31ad9bb417977247315f0a" desc=""> + iPad Pro + </message> + <message name="IDS_DEVTOOLS_76c4064f51952f873baa0f9a201b49a3" desc=""> + Nokia Lumia 520 + </message> + <message name="IDS_DEVTOOLS_8be08fbcf1f787159e451a97a7c1cc90" desc=""> + iPhone 6/7/8 Plus + </message> + <message name="IDS_DEVTOOLS_8d0c6a99bcfbb75724c123476d683d3f" desc=""> + iPhone 4 + </message> + <message name="IDS_DEVTOOLS_99d1a0f994cdce14eea8b6ae823d5a76" desc=""> + Galaxy S III + </message> + <message name="IDS_DEVTOOLS_a75624548994321c1cc7173b9933438b" desc=""> + Microsoft Lumia 550 + </message> + <message name="IDS_DEVTOOLS_aa5fa1bdadb078da054c34752031a5e9" desc=""> + iPhone 6/7/8 + </message> + <message name="IDS_DEVTOOLS_b9e5554cdd9d9f2d3df1f30914b617c2" desc=""> + Galaxy Note 3 + </message> + <message name="IDS_DEVTOOLS_be6a9d69eff86af39e5a73345c585da6" desc=""> + iPad Mini + </message> + <message name="IDS_DEVTOOLS_c99b8431589c0273278e87ebf44a7fd6" desc=""> + iPhone 5/SE + </message> + <message name="IDS_DEVTOOLS_cc810fb8b8bc7c7d6a8327f0e7b2aead" desc=""> + Nexus 6P + </message> + <message name="IDS_DEVTOOLS_d4f2f5453f28c5fd35c68f52e4da07cd" desc=""> + BlackBerry Z30 + </message> + <message name="IDS_DEVTOOLS_d6162eb3dd4dc5a9bc67222e24f19b25" desc=""> + Nexus 4 + </message> + <message name="IDS_DEVTOOLS_d8860bf736e83cfb5c13ee82a8f61a43" desc=""> + Microsoft Lumia 950 + </message> + <message name="IDS_DEVTOOLS_dfd6e576e036db4f857c8c03c977d975" desc=""> + Galaxy Note II + </message> + <message name="IDS_DEVTOOLS_e0261d2f1730ebff89bbde9a4bc74ac5" desc=""> + JioPhone 2 + </message> + <message name="IDS_DEVTOOLS_e770076f957c87605ff906d0ed2c4b52" desc=""> + Blackberry PlayBook + </message> + <message name="IDS_DEVTOOLS_eb850446088fbc75e974788cc2b39caa" desc=""> + Pixel 2 XL + </message> + <message name="IDS_DEVTOOLS_f8896f769d62b6102e48039154c4ca5e" desc=""> + Galaxy S5 + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/emulation/emulation_strings.grdp b/third_party/blink/renderer/devtools/front_end/emulation/emulation_strings.grdp new file mode 100644 index 0000000..129c27d --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/emulation/emulation_strings.grdp
@@ -0,0 +1,276 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_09109d98eee81aa68f1196a7a0753240" desc=""> + DPR: <ph name="DEVICESCALE">$1.1f</ph> + </message> + <message name="IDS_DEVTOOLS_0c78cd3aa4c94a64675bc6aa77802843" desc=""> + Device-based + </message> + <message name="IDS_DEVTOOLS_0eb264d46c88af61e587c18f60662df0" desc=""> + Device pixel ratio + </message> + <message name="IDS_DEVTOOLS_0edd9b471d32d5e3bbec7ca8df113568" desc=""> + Toggle device toolbar + </message> + <message name="IDS_DEVTOOLS_138d1a442ecb2e2fd3b083f1842658d0" desc=""> + Custom orientation... + </message> + <message name="IDS_DEVTOOLS_146bdebb324a64d327b1dde22a07d0bd" desc=""> + Laptop + </message> + <message name="IDS_DEVTOOLS_19ada73af65f7c221bd28e78b2eda5cd" desc=""> + Edit… + </message> + <message name="IDS_DEVTOOLS_1b962c3d36319947efad5a45c1ee62b0" desc=""> + Desktop (touch) + </message> + <message name="IDS_DEVTOOLS_1c7444be9626d149ab598fb79b639f96" desc=""> + Portrait + </message> + <message name="IDS_DEVTOOLS_21e2bb42873eddcb9b476b8eafbe0c18" desc=""> + Reset to defaults + </message> + <message name="IDS_DEVTOOLS_223bf25f178896660d7d73af6e0a540d" desc=""> + Laptop L + </message> + <message name="IDS_DEVTOOLS_2496af30b64c3a4ff21e8505ea439a73" desc=""> + 50% + </message> + <message name="IDS_DEVTOOLS_29260f495ba8adcc62fd1307c758ff4e" desc=""> + Show rulers + </message> + <message name="IDS_DEVTOOLS_29296fcb28eb4edf5d0049b6cac7bbd1" desc=""> + <ph name="THIS__MODEL_SCALE________">$1.0f</ph>%% + </message> + <message name="IDS_DEVTOOLS_29eaeee66d8210c1261d748071fb7b0a" desc=""> + Landscape right + </message> + <message name="IDS_DEVTOOLS_2a04aad9d1e40781d70537def184749d" desc=""> + α (alpha) + </message> + <message name="IDS_DEVTOOLS_2d7084def320939c86d40f1208717083" desc=""> + Location unavailable + </message> + <message name="IDS_DEVTOOLS_30bd7ce7de206924302499f197c7a966" desc=""> + 100% + </message> + <message name="IDS_DEVTOOLS_323d4eb70b252acb4a04eaf9e0882597" desc=""> + Geolocation + </message> + <message name="IDS_DEVTOOLS_32954654ac8fe66a1d09be19001de2d4" desc=""> + Width + </message> + <message name="IDS_DEVTOOLS_34e34c43ec6b943c10a3cc1a1a16fb11" desc=""> + Manage + </message> + <message name="IDS_DEVTOOLS_36384a9ea3ec791e6bd4ab6b36f2ff2a" desc=""> + Tablet + </message> + <message name="IDS_DEVTOOLS_3836c33415a6d95d4a63388a6bcadf3b" desc=""> + Device type + </message> + <message name="IDS_DEVTOOLS_38795baa79c9e2422a84156b83d0b73a" desc=""> + Mobile (no touch) + </message> + <message name="IDS_DEVTOOLS_39335086fbaba7128eff0ef52d396131" desc=""> + Show media queries + </message> + <message name="IDS_DEVTOOLS_396f64970a094d8b66d9863bd073eb72" desc=""> + Force enabled + </message> + <message name="IDS_DEVTOOLS_3b0eb7469ba9c95f3a05c4cef1f6aac4" desc=""> + Latitude + </message> + <message name="IDS_DEVTOOLS_414b730ab2cf9123d9230740864ffeec" desc=""> + Close DevTools + </message> + <message name="IDS_DEVTOOLS_4252b72e6ebcd4d4b4c2e46a786f03d2" desc=""> + Zoom + </message> + <message name="IDS_DEVTOOLS_45f80006d304f294d6c1de50c244856e" desc=""> + Add location... + </message> + <message name="IDS_DEVTOOLS_4dab36ac83853282fc0d7bae20c19e90" desc=""> + More options + </message> + <message name="IDS_DEVTOOLS_50510c6a5a0e14ddd3a68f6dd1cf2f79" desc=""> + Device name + </message> + <message name="IDS_DEVTOOLS_526d688f37a86d3c3f27d0c5016eb71d" desc=""> + Reset + </message> + <message name="IDS_DEVTOOLS_58cc7602635a11277aa7531e14b32c97" desc=""> + Portrait upside down + </message> + <message name="IDS_DEVTOOLS_59c06928c1dcdb1a687bf21d73e53a09" desc=""> + Show device frame + </message> + <message name="IDS_DEVTOOLS_614103b76fd0d9de068d69034fb6f987" desc=""> + (<ph name="THIS__MODEL_DEVICE___TITLE">$1s</ph>) + </message> + <message name="IDS_DEVTOOLS_6149711fb8edc5e2adeea7aa63ee11ff" desc=""> + 150% + </message> + <message name="IDS_DEVTOOLS_62759e0d418d7391bf2d54e70cbcc05d" desc=""> + Remove device type + </message> + <message name="IDS_DEVTOOLS_633c01074b6726183e20f42bb3ee01c0" desc=""> + 4K + </message> + <message name="IDS_DEVTOOLS_649676015173b6195516eed77e5aee60" desc=""> + 125% + </message> + <message name="IDS_DEVTOOLS_6adf97f83acf6453d4a6a4b1070f3754" desc=""> + None + </message> + <message name="IDS_DEVTOOLS_7087f70b643f941c968dc3b327cbe111" desc=""> + Adjust with mousewheel or up/down keys. <ph name="CMDORCTRL">$1s</ph>: ±10, Shift: ±1, Alt: ±0.01 + </message> + <message name="IDS_DEVTOOLS_75a37bfcbfe2678114513aef903c4ba5" desc=""> + Default: <ph name="DEFAULTVALUE">$1.1f</ph> + </message> + <message name="IDS_DEVTOOLS_7ad87024f63b3bb0292c21d76f2c7438" desc=""> + Add device pixel ratio + </message> + <message name="IDS_DEVTOOLS_7addb86955014a622eaefae5134fcb7a" desc=""> + Remove device pixel ratio + </message> + <message name="IDS_DEVTOOLS_7f163d0494446906a484df67e90c1d6b" desc=""> + Hide device frame + </message> + <message name="IDS_DEVTOOLS_815dff01257e5ef182b25d4c1ef0a7a0" desc=""> + Landscape + </message> + <message name="IDS_DEVTOOLS_81c3744a7fe979d029d1e7b84afd613f" desc=""> + *Requires reload + </message> + <message name="IDS_DEVTOOLS_82a9b801e28c4dec617b1cabc329f5bd" desc=""> + Capture screenshot + </message> + <message name="IDS_DEVTOOLS_8394f0347c184cf156ac5924dccb773b" desc=""> + Long + </message> + <message name="IDS_DEVTOOLS_8d2de5368588552fbae54044ac5c7b3d" desc=""> + Rotate + </message> + <message name="IDS_DEVTOOLS_8d7b5211545faceef57a041ee56a2f5e" desc=""> + Capture full size screenshot + </message> + <message name="IDS_DEVTOOLS_901bc0a4714ff81c24943a50e620de71" desc=""> + User agent string + </message> + <message name="IDS_DEVTOOLS_95129d2a7de16087427f1632dc691287" desc=""> + Hide media queries + </message> + <message name="IDS_DEVTOOLS_9b4dabc50f0b8ccba1c8981831abdad8" desc=""> + Longitude + </message> + <message name="IDS_DEVTOOLS_9fa08fa6b5a65fd3a2e14858a2559027" desc=""> + β (beta) + </message> + <message name="IDS_DEVTOOLS_9fd04ab471b39141991551708305ceb5" desc=""> + Add custom device... + </message> + <message name="IDS_DEVTOOLS_a043e816a2c42b9290b672b1aa22cb73" desc=""> + Mobile M + </message> + <message name="IDS_DEVTOOLS_a07f7588275e6b286450c54c3fb5bc92" desc=""> + No override + </message> + <message name="IDS_DEVTOOLS_a68cfcae283e3b2a60c99386c809fd6e" desc=""> + Shift+drag horizontally to rotate around the y-axis + </message> + <message name="IDS_DEVTOOLS_a88789aba0125292a7a2b8774a979b37" desc=""> + Geolocations + </message> + <message name="IDS_DEVTOOLS_abbd64f40c34c537d3a571af068fce29" desc=""> + Orientation + </message> + <message name="IDS_DEVTOOLS_af29aa178ae43211319e28f627e96590" desc=""> + Sensors + </message> + <message name="IDS_DEVTOOLS_b0ac9a67aaac87b4b70f5e1b7292b2cc" desc=""> + Fit to window (<ph name="THIS__MODEL_FITSCALE________">$1.0f</ph>%%) + </message> + <message name="IDS_DEVTOOLS_b1596787a9a32a2626743258abf34e80" desc=""> + Landscape left + </message> + <message name="IDS_DEVTOOLS_b2b22e112d16f958f75ea888f9ce8eeb" desc=""> + Display down + </message> + <message name="IDS_DEVTOOLS_b2b2df378a7c7ade199bbaf944cb3f35" desc=""> + Responsive + </message> + <message name="IDS_DEVTOOLS_b435e227d5dd201e1768b2bcb2e0aa81" desc=""> + height + </message> + <message name="IDS_DEVTOOLS_b85e1916c38f0c0c2d0f7c8d210bcf9e" desc=""> + Height (leave empty for full) + </message> + <message name="IDS_DEVTOOLS_b8d750b6ef9a441434c83df4334c4fa0" desc=""> + Display up + </message> + <message name="IDS_DEVTOOLS_b90203c84f857a0403751bf77f100400" desc=""> + Reveal in source code + </message> + <message name="IDS_DEVTOOLS_bb3680a6300bf660b59ba8783b18689b" desc=""> + Hide rulers + </message> + <message name="IDS_DEVTOOLS_c107e6e26d3b1b5eadbf9e842f6c0e05" desc=""> + Add device type + </message> + <message name="IDS_DEVTOOLS_c23fc6f13afcbcd7dee750fe4f074421" desc=""> + Lat + </message> + <message name="IDS_DEVTOOLS_c3abc91ecb930fd1d8a6b1e738eb36be" desc=""> + Custom Geolocations + </message> + <message name="IDS_DEVTOOLS_c3c3720080d9497b9df37fcd78994144" desc=""> + Location name + </message> + <message name="IDS_DEVTOOLS_c4ca4238a0b923820dcc509a6f75849b" desc=""> + 1 + </message> + <message name="IDS_DEVTOOLS_c81e728d9d4c2f636f067f89cc14862c" desc=""> + 2 + </message> + <message name="IDS_DEVTOOLS_cb211766ff41a03bb9f324be3db9dae0" desc=""> + Mobile L + </message> + <message name="IDS_DEVTOOLS_d15305d7a4e34e02489c74a5ef542f36" desc=""> + Off + </message> + <message name="IDS_DEVTOOLS_da31f3ff326e70f6b08748520c553920" desc=""> + γ (gamma) + </message> + <message name="IDS_DEVTOOLS_decc67818f6be186e03a3c27c2eedc9e" desc=""> + Double-click for full height + </message> + <message name="IDS_DEVTOOLS_e67750c8b85dbe1b938397e55488e2d8" desc=""> + Other… + </message> + <message name="IDS_DEVTOOLS_e85c8bc51cfa9b2d3713091fdc87d551" desc=""> + Auto-adjust zoom + </message> + <message name="IDS_DEVTOOLS_eccbc87e4b5ce2fe28308fd9f2a7baf3" desc=""> + 3 + </message> + <message name="IDS_DEVTOOLS_ee1cab1975e28575b1631ee8fc4ea749" desc=""> + Capture node screenshot + </message> + <message name="IDS_DEVTOOLS_ee4cf994f6defec5951824b44f8047b1" desc=""> + Screen options + </message> + <message name="IDS_DEVTOOLS_f0f31c9700c6b10d8a20dc487b2ae6a8" desc=""> + Touch + </message> + <message name="IDS_DEVTOOLS_f2a72a44f7b7d30829c0405ed2385345" desc=""> + Mobile S + </message> + <message name="IDS_DEVTOOLS_f819de81247be4a5428dc0e169de28b8" desc=""> + 75% + </message> + <message name="IDS_DEVTOOLS_fd0a6990abd15cd06c80309237b01262" desc=""> + Emulated Devices + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/event_listeners/event_listeners_strings.grdp b/third_party/blink/renderer/devtools/front_end/event_listeners/event_listeners_strings.grdp new file mode 100644 index 0000000..5e2d7f6 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/event_listeners/event_listeners_strings.grdp
@@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_0b9c1def3b0d84fe6234388ff8dfa8b7" desc=""> + Toggle whether event listener is passive or blocking + </message> + <message name="IDS_DEVTOOLS_1063e38cb53d94d386f21227fcd84717" desc=""> + Remove + </message> + <message name="IDS_DEVTOOLS_7667495b756ef15210cd60285d8de58a" desc=""> + No event listeners + </message> + <message name="IDS_DEVTOOLS_8d036bf35b7274602d923724afeb7878" desc=""> + Toggle Passive + </message> + <message name="IDS_DEVTOOLS_ba54da0de85f689f31c5e48b3e4c0de3" desc=""> + Delete event listener + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/heap_snapshot_worker_strings.grdp b/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/heap_snapshot_worker_strings.grdp new file mode 100644 index 0000000..32fd74a --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/heap_snapshot_worker_strings.grdp
@@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_239026e523e6f9780426e03637c5b4a4" desc=""> + Loading strings… + </message> + <message name="IDS_DEVTOOLS_58e8a5ca400f834526b09d680ddbc5d5" desc=""> + Loading samples… + </message> + <message name="IDS_DEVTOOLS_6a542856aa30e3e814eaed146e67b2fd" desc=""> + Loading nodes… <ph name="PH1">$1d</ph>%% + </message> + <message name="IDS_DEVTOOLS_7da2f27d62adf93b01c2c041f37667b9" desc=""> + Processing snapshot… + </message> + <message name="IDS_DEVTOOLS_84c0ec1ee2bc769daf265e63bd793201" desc=""> + Loading snapshot info… + </message> + <message name="IDS_DEVTOOLS_9bdae72f224411b7f1027a2c5c7c519b" desc=""> + Loading locations… + </message> + <message name="IDS_DEVTOOLS_b0da59cea23d810234b75c2357748ad3" desc=""> + Loading edges… <ph name="PH1">$1d</ph>%% + </message> + <message name="IDS_DEVTOOLS_d67d63eca2747a30e1ffaeb04389c0bb" desc=""> + Loading allocation traces… <ph name="PH1">$1d</ph>%% + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/help/help_strings.grdp b/third_party/blink/renderer/devtools/front_end/help/help_strings.grdp new file mode 100644 index 0000000..8c9f0a79 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/help/help_strings.grdp
@@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_6a26f548831e6a8c26bfbbd9f6ec61e0" desc=""> + Help + </message> + <message name="IDS_DEVTOOLS_7d0ee6fed10d3d4e5c9ee496729ab519" desc=""> + Release notes + </message> + <message name="IDS_DEVTOOLS_8aac48e1ab540a0467ac1c4b884f68c1" desc=""> + Do not show What's New after each update + </message> + <message name="IDS_DEVTOOLS_8caba5463b13f01c4168decae23f9aff" desc=""> + Show What's New after each update + </message> + <message name="IDS_DEVTOOLS_91770f038cd944a1d3b9b347edeb2b10" desc=""> + What's New + </message> + <message name="IDS_DEVTOOLS_a1c58e94227389415de133efdf78ea6e" desc=""> + Appearance + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/host/host_strings.grdp b/third_party/blink/renderer/devtools/front_end/host/host_strings.grdp new file mode 100644 index 0000000..1f48de4 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/host/host_strings.grdp
@@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_92bb7e733a12d24684262f046afcc2fd" desc=""> + DevTools - <ph name="URL_REPLACE___HTTPS____________">$1s</ph> + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/inline_editor/inline_editor_strings.grdp b/third_party/blink/renderer/devtools/front_end/inline_editor/inline_editor_strings.grdp new file mode 100644 index 0000000..ed320a5b --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/inline_editor/inline_editor_strings.grdp
@@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_180bc3b1c5619aaef40e803f49921012" desc=""> + Spread + </message> + <message name="IDS_DEVTOOLS_2134e3ae0c489ce87a007a082d6a9a29" desc=""> + X offset + </message> + <message name="IDS_DEVTOOLS_575ed851c8964c290e73055ffdc085a6" desc=""> + Y offset + </message> + <message name="IDS_DEVTOOLS_5e9fb94d2ec46e6f829196c229e2b194" desc=""> + Outset + </message> + <message name="IDS_DEVTOOLS_8b52de510bc5497ac43abfe566be48ab" desc=""> + Blur + </message> + <message name="IDS_DEVTOOLS_b56d315e49178ba86341ff3b4e337c6b" desc=""> + Inset + </message> + <message name="IDS_DEVTOOLS_d65b5983f317c42c6f6dff5678e628ca" desc=""> + Shift-click to change color format + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/inspector_main/inspector_main_strings.grdp b/third_party/blink/renderer/devtools/front_end/inspector_main/inspector_main_strings.grdp new file mode 100644 index 0000000..a50e0df --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/inspector_main/inspector_main_strings.grdp
@@ -0,0 +1,96 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_099969ccad146161b304e766f9a1fe56" desc=""> + Show ads on this site, if allowed + </message> + <message name="IDS_DEVTOOLS_0b2cccf3868759cb77614faf9afd0342" desc=""> + JavaScript is disabled + </message> + <message name="IDS_DEVTOOLS_0be2a0127487580b30b7d44eb6dd57ae" desc=""> + Paint flashing + </message> + <message name="IDS_DEVTOOLS_0ef16a6645018dec4609e392c7e9bda1" desc=""> + Do not auto-open DevTools for popups + </message> + <message name="IDS_DEVTOOLS_115c68d941dcba0167cee3483c1bbbb2" desc=""> + Shows layer borders (orange/olive) and tiles (cyan) + </message> + <message name="IDS_DEVTOOLS_1808fb32cf4e8a03daa326b48d4246eb" desc=""> + Disable paused state overlay + </message> + <message name="IDS_DEVTOOLS_2b1a578586beb46008e1542e9283ad99" desc=""> + Scrolling performance issues + </message> + <message name="IDS_DEVTOOLS_417316246f12b8235535182cc9eebe45" desc=""> + Forces media type for testing print and screen styles + </message> + <message name="IDS_DEVTOOLS_441e4ae4f15d6bdee7939aa9bfd61010" desc=""> + Plots frames per second, frame rate distribution, and GPU memory + </message> + <message name="IDS_DEVTOOLS_482a4dca0bbd8fcdda5acc6f95f3c279" desc=""> + DevTools + </message> + <message name="IDS_DEVTOOLS_53f2f05226edcd77bd4351cb27d07ba8" desc=""> + Highlights frames (red) detected to be ads. + </message> + <message name="IDS_DEVTOOLS_6eac03f446434baa29ece59d88410812" desc=""> + FPS meter + </message> + <message name="IDS_DEVTOOLS_6f762270888a17bde49797355db7a410" desc=""> + Shows borders around hit-test regions + </message> + <message name="IDS_DEVTOOLS_7962fd6013e985379fd3a4964d769703" desc=""> + Hit-test borders + </message> + <message name="IDS_DEVTOOLS_7e9495c56e55fa2c5236512bf80e5d2b" desc=""> + Don't show Chrome Data Saver warning + </message> + <message name="IDS_DEVTOOLS_8339f28e0c74e2c821b05332280c754b" desc=""> + Force ad blocking on this site + </message> + <message name="IDS_DEVTOOLS_846495f9ceed11accf8879f555936a7d" desc=""> + Navigation + </message> + <message name="IDS_DEVTOOLS_8634af2a16e41305fc8dca2d67360810" desc=""> + Open dedicated DevTools for Node.js + </message> + <message name="IDS_DEVTOOLS_869a8b1ed99306604574dca474a13994" desc=""> + Emulate CSS media + </message> + <message name="IDS_DEVTOOLS_86f849e1a655c2df19f28cb3dfe07bc9" desc=""> + Block ads on this site + </message> + <message name="IDS_DEVTOOLS_886f598a8a9e6a4bfe0c09fcf7779611" desc=""> + Emulate a focused page + </message> + <message name="IDS_DEVTOOLS_9182eda0635ccdc88276ba9e013c5c1b" desc=""> + Do not emulate a focused page + </message> + <message name="IDS_DEVTOOLS_960568e27eb66ea554c3be4cfbefe3d0" desc=""> + Layer borders + </message> + <message name="IDS_DEVTOOLS_a02c83a7dbd96295beaefb72c2bee2de" desc=""> + Main + </message> + <message name="IDS_DEVTOOLS_a15932c4dfbbcbc1ac6f5c27c6fa530f" desc=""> + Highlights elements (teal) that can slow down scrolling, including touch & wheel event handlers and other main-thread scrolling situations. + </message> + <message name="IDS_DEVTOOLS_a6e8f9aed2ac6481dc25a18a33342d03" desc=""> + Rendering + </message> + <message name="IDS_DEVTOOLS_cb835af5f855f79e8611dd3f8fec6aac" desc=""> + Reload page + </message> + <message name="IDS_DEVTOOLS_d543dbe64db0c952d6e13c9519218b3e" desc=""> + Hard reload page + </message> + <message name="IDS_DEVTOOLS_ef95393ad48336d7c3543625354a3d56" desc=""> + Highlight ad frames + </message> + <message name="IDS_DEVTOOLS_f23c9ba06e7123f0b4c906de90fbcc9f" desc=""> + Auto-open DevTools for popups + </message> + <message name="IDS_DEVTOOLS_f6b139a6b392ab11c9c5c8210c525688" desc=""> + Highlights areas of the page (green) that need to be repainted + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/js_profiler/js_profiler_strings.grdp b/third_party/blink/renderer/devtools/front_end/js_profiler/js_profiler_strings.grdp new file mode 100644 index 0000000..cbe64e0 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/js_profiler/js_profiler_strings.grdp
@@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_65b4c7424dd695c30efa73da8396c90c" desc=""> + Profiler + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/langpacks/devtools_ui_strings.grd b/third_party/blink/renderer/devtools/front_end/langpacks/devtools_ui_strings.grd new file mode 100644 index 0000000..132a5c4 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/langpacks/devtools_ui_strings.grd
@@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- DevTools-specific strings. --> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false" source_lang_id="en"> + <outputs> + <output filename="devtools_ui_strings.h" type="rc_header"> + <emit emit_type='prepend'></emit> + </output> + <output filename="devtools_ui_strings_en-US.pak" type="data_package" lang="en-US" /> + </outputs> + <translations> + </translations> + <release seq="1" allow_pseudo="false"> + <messages fallback_to_english="true"> + <part file="../accessibility/accessibility_strings.grdp" /> + <part file="../animation/animation_strings.grdp" /> + <part file="../audits2/audits2_strings.grdp" /> + <part file="../bindings/bindings_strings.grdp" /> + <part file="../browser_debugger/browser_debugger_strings.grdp" /> + <part file="../browser_sdk/browser_sdk_strings.grdp" /> + <part file="../changes/changes_strings.grdp" /> + <part file="../color_picker/color_picker_strings.grdp" /> + <part file="../components/components_strings.grdp" /> + <part file="../console/console_strings.grdp" /> + <part file="../console_counters/console_counters_strings.grdp" /> + <part file="../cookie_table/cookie_table_strings.grdp" /> + <part file="../coverage/coverage_strings.grdp" /> + <part file="../data_grid/data_grid_strings.grdp" /> + <part file="../devices/devices_strings.grdp" /> + <part file="../elements/elements_strings.grdp" /> + <part file="../emulated_devices/emulated_devices_strings.grdp" /> + <part file="../emulation/emulation_strings.grdp" /> + <part file="../event_listeners/event_listeners_strings.grdp" /> + <part file="../heap_snapshot_worker/heap_snapshot_worker_strings.grdp" /> + <part file="../help/help_strings.grdp" /> + <part file="../host/host_strings.grdp" /> + <part file="../inline_editor/inline_editor_strings.grdp" /> + <part file="../inspector_main/inspector_main_strings.grdp" /> + <part file="../js_profiler/js_profiler_strings.grdp" /> + <part file="../layer_viewer/layer_viewer_strings.grdp" /> + <part file="../layers/layers_strings.grdp" /> + <part file="../main/main_strings.grdp" /> + <part file="../mobile_throttling/mobile_throttling_strings.grdp" /> + <part file="../network/network_strings.grdp" /> + <part file="../node_debugger/node_debugger_strings.grdp" /> + <part file="../node_main/node_main_strings.grdp" /> + <part file="../object_ui/object_ui_strings.grdp" /> + <part file="../perf_ui/perf_ui_strings.grdp" /> + <part file="../performance_monitor/performance_monitor_strings.grdp" /> + <part file="../persistence/persistence_strings.grdp" /> + <part file="../product_registry/product_registry_strings.grdp" /> + <part file="../profiler/profiler_strings.grdp" /> + <part file="../protocol_monitor/protocol_monitor_strings.grdp" /> + <part file="../quick_open/quick_open_strings.grdp" /> + <part file="../resources/resources_strings.grdp" /> + <part file="../screencast/screencast_strings.grdp" /> + <part file="../sdk/sdk_strings.grdp" /> + <part file="../search/search_strings.grdp" /> + <part file="../security/security_strings.grdp" /> + <part file="../settings/settings_strings.grdp" /> + <part file="../snippets/snippets_strings.grdp" /> + <part file="../source_frame/source_frame_strings.grdp" /> + <part file="../sources/sources_strings.grdp" /> + <part file="../terminal/terminal_strings.grdp" /> + <part file="../text_editor/text_editor_strings.grdp" /> + <part file="../timeline/timeline_strings.grdp" /> + <part file="../timeline_model/timeline_model_strings.grdp" /> + <part file="../ui/ui_strings.grdp" /> + <part file="../web_audio/web_audio_strings.grdp" /> + <part file="../workspace/workspace_strings.grdp" /> + </messages> + </release> +</grit>
diff --git a/third_party/blink/renderer/devtools/front_end/layer_viewer/layer_viewer_strings.grdp b/third_party/blink/renderer/devtools/front_end/layer_viewer/layer_viewer_strings.grdp new file mode 100644 index 0000000..8fc580f --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/layer_viewer/layer_viewer_strings.grdp
@@ -0,0 +1,213 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_05245b74ad79bb210a68107f7de0c27f" desc=""> + Layer for scrolling container. + </message> + <message name="IDS_DEVTOOLS_08415c56f6c6c2efb0218629836e31bc" desc=""> + Composition due to association with an element with a "backface-visibility: hidden" style. + </message> + <message name="IDS_DEVTOOLS_0aa3ae694efd06789ae1867c80d30222" desc=""> + Composition due to association with an element with a "position: fixed" or "position: sticky" style. + </message> + <message name="IDS_DEVTOOLS_0b4eb322e51b61340668247151340346" desc=""> + Rotate mode (V) + </message> + <message name="IDS_DEVTOOLS_0dd70cbbb618cf0ea39d7e01238ca1b9" desc=""> + Composition due to association with an animated element. + </message> + <message name="IDS_DEVTOOLS_135d78fcc62ff8df8028c33c768900c5" desc=""> + Layer for background. + </message> + <message name="IDS_DEVTOOLS_219e2fb2d37a581ab2bae57397b601f1" desc=""> + <unnamed> + </message> + <message name="IDS_DEVTOOLS_233612553595af00e5d227e136252422" desc=""> + Composition due to association with an element with composited descendants. + </message> + <message name="IDS_DEVTOOLS_25d066be1268d5c07cae5cc26e06ad2b" desc=""> + Slow scroll regions + </message> + <message name="IDS_DEVTOOLS_28b5b4891eb05cc50f537526b24038a9" desc=""> + Composition due to association with a masked element and composited descendants. + </message> + <message name="IDS_DEVTOOLS_2a2924d1d77c00d27ce2509c34861804" desc=""> + Layer for clip. + </message> + <message name="IDS_DEVTOOLS_2ae207ddfe5cd256a768769d93a879e5" desc=""> + Paint Profiler + </message> + <message name="IDS_DEVTOOLS_2ca2308d45c04266f0fb51786e407287" desc=""> + Composition due to association with an element with CSS filters applied and composited descendants. + </message> + <message name="IDS_DEVTOOLS_3228417bf9ed949e7447e7c8dcb17090" desc=""> + Memory estimate + </message> + <message name="IDS_DEVTOOLS_37de7295335e95cb7caf78303a1edad3" desc=""> + Composition due to association with an element with a CSS 3D transform. + </message> + <message name="IDS_DEVTOOLS_398b889c147f3b2cb3c674cfb07315b5" desc=""> + Composition due to association with an element with opacity applied and composited descendants. + </message> + <message name="IDS_DEVTOOLS_3f03ed88ee58335aa3df453443b9c8bc" desc=""> + Profiling… + </message> + <message name="IDS_DEVTOOLS_441f5e043a240bac8dca50f90f7be3de" desc=""> + repaints on scroll + </message> + <message name="IDS_DEVTOOLS_45567a52ec61e3e2b5469b397db3fc2a" desc=""> + <ph name="LAYERVIEWER_LAYERDETAILSVIEW__SLOWSCROLLRECTNAMES_GET_SCROLLRECT_TYPE_">$1s</ph> <ph name="SCROLLRECT_RECT_X">$2d</ph> × <ph name="SCROLLRECT_RECT_Y">$3d</ph> (at <ph name="SCROLLRECT_RECT_WIDTH">$4d</ph>, <ph name="SCROLLRECT_RECT_HEIGHT">$5d</ph>) + </message> + <message name="IDS_DEVTOOLS_459be6cdd6650871d6b740d1ce6bc7a3" desc=""> + mousewheel event listener + </message> + <message name="IDS_DEVTOOLS_4881cc76c5e57422d2841026b9b93692" desc=""> + Wheel event handler + </message> + <message name="IDS_DEVTOOLS_49ceda18652e222780b8a35f506b4678" desc=""> + Pan mode (X) + </message> + <message name="IDS_DEVTOOLS_4a1a29f7d8a02e0294dc9134e97e9134" desc=""> + Sticky position constraint + </message> + <message name="IDS_DEVTOOLS_4ee55709b19d806bb2f83a264a8a0f75" desc=""> + Sticky Box <ph name="STICKYBOXRECT_WIDTH">$1d</ph> × <ph name="STICKYBOXRECT_HEIGHT">$2d</ph> (at <ph name="STICKYBOXRECT_X">$3d</ph>, <ph name="STICKYBOXRECT_Y">$4d</ph>) + </message> + <message name="IDS_DEVTOOLS_5337a3314b26561ccf364e1777455933" desc=""> + Composition due to association with a <video> element. + </message> + <message name="IDS_DEVTOOLS_5639e2813d9549835010567a48349127" desc=""> + (<ph name="THIS__LAYER_WIDTH__">$1d</ph> × <ph name="THIS__LAYER_HEIGHT__">$2d</ph>) + </message> + <message name="IDS_DEVTOOLS_602f4c0713480f019b24f09218dcc7e0" desc=""> + Reset View + </message> + <message name="IDS_DEVTOOLS_697e0fb75c6cf44734697517d44b5922" desc=""> + Composition due to association with an element clipping compositing descendants. + </message> + <message name="IDS_DEVTOOLS_6fac3a4381f0fb07bbf498a08d301d40" desc=""> + Repaints on scroll + </message> + <message name="IDS_DEVTOOLS_7069651490219723e31a486d60d96fc8" desc=""> + Nearest Layer Shifting Sticky Box + </message> + <message name="IDS_DEVTOOLS_70baf8087d35f6bf5bde8b7c0645a1e8" desc=""> + <ph name="TITLE">$1s</ph>: <ph name="NAME">$2s</ph> (<ph name="LAYER_ID__">$3s</ph>) + </message> + <message name="IDS_DEVTOOLS_71084df87a4cc161f7542a0f5295a950" desc=""> + Select a layer to see its details + </message> + <message name="IDS_DEVTOOLS_73c57dbc070bac535d75b4abe9f614a3" desc=""> + Composition due to association with an element overlapping other composited elements. + </message> + <message name="IDS_DEVTOOLS_74248c725e00bf9fe04df4e35b249a19" desc=""> + Misc + </message> + <message name="IDS_DEVTOOLS_74ae7b35b54cd38a932ccc4f1d1c3775" desc=""> + Touch event handler + </message> + <message name="IDS_DEVTOOLS_791faaf55ae39199cc0b4edde837f07a" desc=""> + Layer for video overlay. + </message> + <message name="IDS_DEVTOOLS_7eb830853b9ed22a567e4d7582eafe7c" desc=""> + Composition due to association with an element with CSS filters applied. + </message> + <message name="IDS_DEVTOOLS_82505980aa6b0cabf4cb8013a8a43b62" desc=""> + Non fast scrollable + </message> + <message name="IDS_DEVTOOLS_82d7a4981a35bb7f6dfc8a5485a61bc6" desc=""> + <ph name="LAYER_WIDTH__">$1d</ph> × <ph name="LAYER_HEIGHT__">$2d</ph> (at <ph name="LAYER_OFFSETX__">$3d</ph>,<ph name="LAYER_OFFSETY__">$4d</ph>) + </message> + <message name="IDS_DEVTOOLS_86ee74baff479d85d18f2cda9f8a9518" desc=""> + Bitmap + </message> + <message name="IDS_DEVTOOLS_8810c4e0c498b81a6e4adaeabcb9f624" desc=""> + Composition due to association with an element with a "overflow-scrolling: touch" style. + </message> + <message name="IDS_DEVTOOLS_894982f4a3bc0e770cece61dd12dde55" desc=""> + Composition due to association with an <iframe> element. + </message> + <message name="IDS_DEVTOOLS_932a3ef55ce8133be7b33ded2992fd97" desc=""> + Compositing Reasons + </message> + <message name="IDS_DEVTOOLS_93c3341232864688bcea4d53dff1bf10" desc=""> + Composition due to association with an element with perspective applied. + </message> + <message name="IDS_DEVTOOLS_991bd14abd9e6004de4e7b9bc0769d9d" desc=""> + Layer for foreground. + </message> + <message name="IDS_DEVTOOLS_9b8379825de60ccb900acf83934e1409" desc=""> + Show internal layers + </message> + <message name="IDS_DEVTOOLS_9dffbf69ffba8bc38bc4e01abf4b1675" desc=""> + Text + </message> + <message name="IDS_DEVTOOLS_a673813c8d6c5f511cc4d80830fc4503" desc=""> + Can't display layers, + </message> + <message name="IDS_DEVTOOLS_aefd09cd861bbb01d381cfd74856e877" desc=""> + Composition due to the element being a <canvas> element. + </message> + <message name="IDS_DEVTOOLS_b336b2cbaa7391e6e0dfef888d35a837" desc=""> + touch event listener + </message> + <message name="IDS_DEVTOOLS_b4cc0ce8b989d360cf2bef966626e683" desc=""> + Layer information is not yet available. + </message> + <message name="IDS_DEVTOOLS_b520b88ac5b8fbc5138849baddef2040" desc=""> + Paint count + </message> + <message name="IDS_DEVTOOLS_b7fec868f7541e449cbb32b506aa3668" desc=""> + Check <ph name="UI_XLINK_CREATE__ABOUT_GPU__">$1s</ph> for possible reasons. + </message> + <message name="IDS_DEVTOOLS_c0f4be326648f3fee18ffd278b614126" desc=""> + Profiling Results + </message> + <message name="IDS_DEVTOOLS_c634209b1884c963528d21a21cb64ac8" desc=""> + Nearest Layer Shifting Containing Block + </message> + <message name="IDS_DEVTOOLS_cd5be434fea99c341680590738e3b6d5" desc=""> + WebGL support is disabled in your browser. + </message> + <message name="IDS_DEVTOOLS_ce1efcf7f040106cc8cb2f24c9efee35" desc=""> + Show Paint Profiler + </message> + <message name="IDS_DEVTOOLS_cf4db365a841e7208aad0d474cbfa8e3" desc=""> + Composition due to association with an element with descendants that have a negative z-index. + </message> + <message name="IDS_DEVTOOLS_d446f65fe70f9a640908576792497e25" desc=""> + Composition due to association with an element with a reflection and composited descendants. + </message> + <message name="IDS_DEVTOOLS_dd4d335a4deb975546acc9fb5aa3ffce" desc=""> + Composition due to association with an element that may overlap other composited elements. + </message> + <message name="IDS_DEVTOOLS_dff689f21faf977ee865e312c011c84a" desc=""> + Root layer. + </message> + <message name="IDS_DEVTOOLS_e397c87a940fc2c10225a407c7f124a7" desc=""> + Composition due to association with a plugin. + </message> + <message name="IDS_DEVTOOLS_e763043c4af617c6f33da361d990a77b" desc=""> + Reset transform (0) + </message> + <message name="IDS_DEVTOOLS_e7ee6a7ae0e6f824f5609c7bdac34375" desc=""> + Shapes + </message> + <message name="IDS_DEVTOOLS_ed3a481889f16ef0aab2349f5d8b5f12" desc=""> + Containing Block <ph name="CONTAININGBLOCKRECT_WIDTH">$1d</ph> × <ph name="CONTAININGBLOCKRECT_HEIGHT">$2d</ph> (at <ph name="CONTAININGBLOCKRECT_X">$3d</ph>, <ph name="CONTAININGBLOCKRECT_Y">$4d</ph>) + </message> + <message name="IDS_DEVTOOLS_f1eb415fdb8a15856c29cc2b679e416b" desc=""> + Composition due to association with an element with a "transform-style: preserve-3d" style. + </message> + <message name="IDS_DEVTOOLS_f2a4f55a424726ae504f2e694e3dc2a2" desc=""> + Composition due to association with an element with CSS blending applied and composited descendants. + </message> + <message name="IDS_DEVTOOLS_fa055d01c0a331d642c2f55a39d4e1bb" desc=""> + Composition due to association with an element that has blend mode other than "normal". + </message> + <message name="IDS_DEVTOOLS_fb8ed4e0cd9d6ac3630df425c80d9036" desc=""> + Layer for mask. + </message> + <message name="IDS_DEVTOOLS_fd63c694ddc8073cf10bb8025aa9aaaf" desc=""> + Layer for scrollbar. + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/layers/layers_strings.grdp b/third_party/blink/renderer/devtools/front_end/layers/layers_strings.grdp new file mode 100644 index 0000000..ce01cd6 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/layers/layers_strings.grdp
@@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_3ec365dd533ddb7ef3d1c111186ce872" desc=""> + Details + </message> + <message name="IDS_DEVTOOLS_87bfda183c4f851a101e97bbb1bbace7" desc=""> + Layers + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/main/main_strings.grdp b/third_party/blink/renderer/devtools/front_end/main/main_strings.grdp new file mode 100644 index 0000000..5f0c5c16 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/main/main_strings.grdp
@@ -0,0 +1,129 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_00463255013f500126fb5cc8c824e384" desc=""> + Panel layout: + </message> + <message name="IDS_DEVTOOLS_08e71f00acd63d0a546ba42f9e780ddc" desc=""> + Customize and control DevTools + </message> + <message name="IDS_DEVTOOLS_0a0afb342478f201b92cbc89d19bf14d" desc=""> + Switch to dark theme + </message> + <message name="IDS_DEVTOOLS_13348442cc6a27032d2b4aa28b75a5d3" desc=""> + Search + </message> + <message name="IDS_DEVTOOLS_15fa1acc2a998159c4ed2a950c5c231d" desc=""> + Toggle drawer + </message> + <message name="IDS_DEVTOOLS_1b1ac1c7a54457ce73ddd25a5b51c47d" desc=""> + Drawer sidebar + </message> + <message name="IDS_DEVTOOLS_1cf59b16fd253d6ff4bbee7c237cea0d" desc=""> + Show console + </message> + <message name="IDS_DEVTOOLS_2ab5656e27a0ed871c8de44368f807c6" desc=""> + Styles Pane + </message> + <message name="IDS_DEVTOOLS_2ad9d63b69c4a10a5cc9cad923133bc4" desc=""> + Bottom + </message> + <message name="IDS_DEVTOOLS_36634aa462472ceb907f3aa4401d3a61" desc=""> + Undocked + </message> + <message name="IDS_DEVTOOLS_3b40834e60f26865c1b9582f1745476e" desc=""> + Use horizontal panel layout + </message> + <message name="IDS_DEVTOOLS_3b7e62b6a175b75f4ecf012d17ba7fef" desc=""> + Focus debuggee + </message> + <message name="IDS_DEVTOOLS_4505cad087312551a6fbbe6ebe163e0f" desc=""> + horizontal + </message> + <message name="IDS_DEVTOOLS_4f1133a5722c0189f59e0490b2ae1c31" desc=""> + Go to source + </message> + <message name="IDS_DEVTOOLS_581138047ce1459b079a8c4abba128a1" desc=""> + Go to the panel to the left/right + </message> + <message name="IDS_DEVTOOLS_586740a88e6502850bc64f9f2d04d380" desc=""> + Placement of DevTools relative to the page. (<ph name="TOGGLEDOCKSIDESHORCUTS____NAME">$1s</ph> to restore last position) + </message> + <message name="IDS_DEVTOOLS_5bf4a92da989a6943e3fed84f18c3f0f" desc=""> + Search across all sources + </message> + <message name="IDS_DEVTOOLS_5e2f5f3c24ae8c6ab3eca618826b0e23" desc=""> + Extensions + </message> + <message name="IDS_DEVTOOLS_62fcd77216b456123c822a40ded03347" desc=""> + Select node to inspect + </message> + <message name="IDS_DEVTOOLS_71f0df44b05415f2d20b59bb6188a118" desc=""> + Toggle dock side + </message> + <message name="IDS_DEVTOOLS_75def4784fa71c4ccde7762316ed0e3e" desc=""> + Find next/previous + </message> + <message name="IDS_DEVTOOLS_787ae37366b7a8c53f381abfd315c647" desc=""> + Elements Panel + </message> + <message name="IDS_DEVTOOLS_8645bf45e76c3f958ae99c114c419743" desc=""> + Hide console drawer + </message> + <message name="IDS_DEVTOOLS_92b09c7c48c520c3c55e497875da437c" desc=""> + Right + </message> + <message name="IDS_DEVTOOLS_93445501d5239cedddc0bd6a0a453a95" desc=""> + Dock side + </message> + <message name="IDS_DEVTOOLS_9914a0ce04a7b7b6a8e39bec55064b82" desc=""> + Light + </message> + <message name="IDS_DEVTOOLS_9b1ed2cbe56f7a315f0a365d2b97cb59" desc=""> + Drawer + </message> + <message name="IDS_DEVTOOLS_a18366b217ebf811ad1886e4f4f865b2" desc=""> + Dark + </message> + <message name="IDS_DEVTOOLS_a9e4402481bd9b8e36752bf731f67eb6" desc=""> + Theme: + </message> + <message name="IDS_DEVTOOLS_b0659ae6872366589300ed6c2033ba26" desc=""> + Toggle device mode + </message> + <message name="IDS_DEVTOOLS_b3bf148a3dc8b3367191419e52380982" desc=""> + Use vertical panel layout + </message> + <message name="IDS_DEVTOOLS_b8da6df14bf06283cbf588df6998722e" desc=""> + Panel + </message> + <message name="IDS_DEVTOOLS_b94d8a074eddd267702810179875737f" desc=""> + Debugger + </message> + <message name="IDS_DEVTOOLS_b9cd538a753713464d2ea17d7e975041" desc=""> + More tools + </message> + <message name="IDS_DEVTOOLS_c0fef4f5cd015e4b1e5477f511dc3939" desc=""> + Use automatic panel layout + </message> + <message name="IDS_DEVTOOLS_c2376cec424de4cead5272c492d3d269" desc=""> + Restore last dock position + </message> + <message name="IDS_DEVTOOLS_d33bf99e0756e1d5008cb78902e38ca9" desc=""> + All Panels + </message> + <message name="IDS_DEVTOOLS_db5d5dd2ff01f52ffee4b57ca2b1fcfd" desc=""> + Enable Ctrl + 1-9 shortcut to switch panels + </message> + <message name="IDS_DEVTOOLS_debb0ba164edd1f9254b644de3c6d716" desc=""> + Enable ⌘ + 1-9 shortcut to switch panels + </message> + <message name="IDS_DEVTOOLS_e472458a8014f14176e3c3c3d4dd0ad9" desc=""> + Switch to light theme + </message> + <message name="IDS_DEVTOOLS_e6dec152d6a941fccb0a5e8cc2579cc3" desc=""> + vertical + </message> + <message name="IDS_DEVTOOLS_eafbab965ec3970b0e97705882ebf8d0" desc=""> + Show console drawer + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/mobile_throttling/mobile_throttling_strings.grdp b/third_party/blink/renderer/devtools/front_end/mobile_throttling/mobile_throttling_strings.grdp new file mode 100644 index 0000000..ec6a7fbe --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/mobile_throttling/mobile_throttling_strings.grdp
@@ -0,0 +1,108 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_07a573e3035e9f8a7380a801df3a920f" desc=""> + Slow 3G & 6x CPU slowdown + </message> + <message name="IDS_DEVTOOLS_0936559ca32dc012bcc81444bec17ea4" desc=""> + Force disconnected from network + </message> + <message name="IDS_DEVTOOLS_1363b7d2b4c0a3ac3a89b3ba69d59be7" desc=""> + Network throttling is enabled + </message> + <message name="IDS_DEVTOOLS_17f66753218a6a1e2762c6a60db3d7c4" desc=""> + Mid-tier mobile + </message> + <message name="IDS_DEVTOOLS_26ae7bdd1d6fb8c4886e6fde8d12601c" desc=""> + Latency + </message> + <message name="IDS_DEVTOOLS_275e2c1079aeffdb5f4e22580127b95b" desc=""> + <ph name="CONDITIONS_LATENCY">$1d</ph>ms + </message> + <message name="IDS_DEVTOOLS_3602f195c0823b75591b5546c3d5df00" desc=""> + Requests may be rewritten by local overrides + </message> + <message name="IDS_DEVTOOLS_37234a1bcbabe4e8e7448f4bbcf5c2b4" desc=""> + <ph name="THROUGHPUTINKBPS">$1d</ph><ph name="DELIMITER">$2s</ph>kb/s + </message> + <message name="IDS_DEVTOOLS_38c8cb828795cd6ff1cddda9b4ffcfa8" desc=""> + <ph name="THROUGHPUTINKBPS___________">$1d</ph><ph name="DELIMITER">$2s</ph>Mb/s + </message> + <message name="IDS_DEVTOOLS_4fafba98ddd8a8663d8775a928f2450e" desc=""> + Requests may be blocked + </message> + <message name="IDS_DEVTOOLS_56d7a17ecb7d30faf8daf8a6eb57e3bb" desc=""> + Go offline + </message> + <message name="IDS_DEVTOOLS_6ba7dc45786c25d1e5879b2166894fc5" desc=""> + Go online + </message> + <message name="IDS_DEVTOOLS_801ab24683a4a8c433c6eb40c48bcd9d" desc=""> + Download + </message> + <message name="IDS_DEVTOOLS_8493534a13107469ea63be99410bebfa" desc=""> + Enable slow 3G throttling + </message> + <message name="IDS_DEVTOOLS_8d9da4bc0e49a50e09ac9f7e56789d39" desc=""> + Offline + </message> + <message name="IDS_DEVTOOLS_8fd93ea382b6642f13ff291b76f5bc85" desc=""> + Profile Name + </message> + <message name="IDS_DEVTOOLS_90589c47f06eb971d548591f23c285af" desc=""> + Custom + </message> + <message name="IDS_DEVTOOLS_91412465ea9169dfd901dd5e7c96dd99" desc=""> + Upload + </message> + <message name="IDS_DEVTOOLS_9b6545e4cea9b4ad4979d41bb9170e2b" desc=""> + Advanced + </message> + <message name="IDS_DEVTOOLS_a808cbcba081a943f4faedda831298b5" desc=""> + kb/s + </message> + <message name="IDS_DEVTOOLS_b27fdc01c81857f96f3d5d37d323bcb6" desc=""> + Enable fast 3G throttling + </message> + <message name="IDS_DEVTOOLS_b9f5c797ebbf55adccdd8539a65a0241" desc=""> + Disabled + </message> + <message name="IDS_DEVTOOLS_c47c85f963782364d32f428fcf7631ff" desc=""> + No internet connectivity + </message> + <message name="IDS_DEVTOOLS_c939c288fa6bfab8b8bfb9b86593be20" desc=""> + Add custom profile... + </message> + <message name="IDS_DEVTOOLS_c96084dae377c53ea7e233fc8255e6d5" desc=""> + Fast 3G & 4x CPU slowdown + </message> + <message name="IDS_DEVTOOLS_cb67c2b6640235af7393ca5970c1e887" desc=""> + <ph name="RATE">$1d</ph>× slowdown + </message> + <message name="IDS_DEVTOOLS_d33468989239f9d3c708d05dcd7824f3" desc=""> + <ph name="THROUGHPUTINKBPS_______">$1.1f</ph><ph name="DELIMITER">$2s</ph>Mb/s + </message> + <message name="IDS_DEVTOOLS_d49429dd3e92758c218f94ed0219d620" desc=""> + CPU throttling is enabled + </message> + <message name="IDS_DEVTOOLS_d57c24f3fe52d16e7169b912dd647f0d" desc=""> + optional + </message> + <message name="IDS_DEVTOOLS_eb81441fe20963ff9e8e69c5b32fc625" desc=""> + Presets + </message> + <message name="IDS_DEVTOOLS_ee33e909372d935d190f4fcb2a92d542" desc=""> + ms + </message> + <message name="IDS_DEVTOOLS_f410c3f1a07f566591283f599701e4ab" desc=""> + Add… + </message> + <message name="IDS_DEVTOOLS_fa481f0018f093f34f49bd0f555653f3" desc=""> + Check Network and Performance panels + </message> + <message name="IDS_DEVTOOLS_fcd5c08df997867efb2d80f45c4e1a6c" desc=""> + Low-end mobile + </message> + <message name="IDS_DEVTOOLS_ff45c788a49f2900f274da0c350dcd1d" desc=""> + Network Throttling Profiles + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/network/network_strings.grdp b/third_party/blink/renderer/devtools/front_end/network/network_strings.grdp new file mode 100644 index 0000000..175cbe94a --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/network/network_strings.grdp
@@ -0,0 +1,768 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_0194336f90a2b1de65553e3bec01becd" desc=""> + Copy as fetch + </message> + <message name="IDS_DEVTOOLS_01a8f976083c550f4d5ba8452ec80efb" desc=""> + No custom headers + </message> + <message name="IDS_DEVTOOLS_02d56cf7754ce16d7ce0193fbca7c90a" desc=""> + Caching + </message> + <message name="IDS_DEVTOOLS_040c4b52a3c06c6067fac76c4c7c3a2c" desc=""> + Network conditions + </message> + <message name="IDS_DEVTOOLS_059f48d76d79fe0727740d75dc81fa94" desc=""> + <ph name="SELECTEDTRANSFERSIZE">$1s</ph> B / <ph name="TRANSFERSIZE">$2s</ph> B transferred + </message> + <message name="IDS_DEVTOOLS_06337a0bc6e91b2adb10567bee4d6f14" desc=""> + Copy all as HAR + </message> + <message name="IDS_DEVTOOLS_079accf18103a0f8b9a76ce09cb147d7" desc=""> + Add pattern + </message> + <message name="IDS_DEVTOOLS_08af23a4affc4689447d59935ba3b3b3" desc=""> + Hit <ph name="RELOADSHORTCUTDESCRIPTOR_NAME">$1s</ph> to reload and capture filmstrip. + </message> + <message name="IDS_DEVTOOLS_09bad44011fa6a5a64ada3424ad85f03" desc=""> + <ph name="LOCALIZEDDESCRIPTION">$1s</ph> (Opcode <ph name="OPCODE">$2s</ph>) + </message> + <message name="IDS_DEVTOOLS_09c9ea004b0c0822b75bdec322b90ff4" desc=""> + Waterfall + </message> + <message name="IDS_DEVTOOLS_0bcc4ec10c2e4cee4b9bbabd48501304" desc=""> + Select message to browse its content. + </message> + <message name="IDS_DEVTOOLS_0db377921f4ce762c62526131097968f" desc=""> + General + </message> + <message name="IDS_DEVTOOLS_0f44e9e39cbe2f22bd1bd7b6070cf13d" desc=""> + Enable request blocking + </message> + <message name="IDS_DEVTOOLS_0f591b1d87c91e77d4fa11dc6e44288c" desc=""> + Request and response timeline + </message> + <message name="IDS_DEVTOOLS_117068a6e55846888cbb60978fe82ca2" desc=""> + Stalled + </message> + <message name="IDS_DEVTOOLS_11803f40c277b679b08ce0b8d38fdefa" desc=""> + Preload + </message> + <message name="IDS_DEVTOOLS_12881f9e98bb240671bc3e1787d64a03" desc=""> + Color code by resource type + </message> + <message name="IDS_DEVTOOLS_16f78b9465f03f7ec5a03c24918fbde3" desc=""> + Status Code + </message> + <message name="IDS_DEVTOOLS_1854180b02f297deebed0ec452090842" desc=""> + Served from memory cache, resource size: <ph name="RESOURCESIZE">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_197d4c4eb38925e0c8ab3f2998cd893f" desc=""> + Perform a request or hit <ph name="RELOADSHORTCUTNODE">$1s</ph> to record the reload. + </message> + <message name="IDS_DEVTOOLS_1a0534b264da645e89fcf2cc86ec4cb5" desc=""> + (from prefetch cache) + </message> + <message name="IDS_DEVTOOLS_1a8b6125c4be73210788e4fad96bdbdb" desc=""> + Server Push + </message> + <message name="IDS_DEVTOOLS_1b581452e4e1158b75e514c99a760431" desc=""> + Request Payload + </message> + <message name="IDS_DEVTOOLS_1c047e32d57295a9f0319976c543162e" desc=""> + (blocked:<ph name="REASON">$1s</ph>) + </message> + <message name="IDS_DEVTOOLS_1cb07ce276f37ba2acdfb8605aaefbb8" desc=""> + <ph name="RESOURCESIZE">$1s</ph> B resources + </message> + <message name="IDS_DEVTOOLS_1dc4a71b18d2c3a1442267136158128e" desc=""> + Copy all as cURL (cmd) + </message> + <message name="IDS_DEVTOOLS_1eb445fa6bd078346bf63ecac35fa77c" desc=""> + Base64 + </message> + <message name="IDS_DEVTOOLS_2537b3e6907e17001b7cdf121cd39dc0" desc=""> + (from ServiceWorker) + </message> + <message name="IDS_DEVTOOLS_26b6b5ae2c6e2575b2a451c35e94df23" desc=""> + Waiting (TTFB) + </message> + <message name="IDS_DEVTOOLS_296d9aa276c7b25db8cf45733d8d4042" desc=""> + Signed HTTP exchange + </message> + <message name="IDS_DEVTOOLS_29d37bdcfeb74d25d56bcf841866ae32" desc=""> + Served from ServiceWorker, resource size: <ph name="RESOURCESIZE">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_2bbc845892f400626baab5af687527c5" desc=""> + Start Time + </message> + <message name="IDS_DEVTOOLS_2d13df6f8b5e4c5af9f87e0dc39df69d" desc=""> + Pending + </message> + <message name="IDS_DEVTOOLS_2ef0ae0c4d76a87b28176de205d7d346" desc=""> + Recording frames... + </message> + <message name="IDS_DEVTOOLS_2f618132e0f9cadb9eb3759327b70e74" desc=""> + Import HAR file... + </message> + <message name="IDS_DEVTOOLS_30ad3ea5e350075c1c0a1171c5006ed7" desc=""> + Fetching frames... + </message> + <message name="IDS_DEVTOOLS_3136ed000d43bebb4ca53a9312fbd32c" desc=""> + Add pattern. + </message> + <message name="IDS_DEVTOOLS_31977081ea2c828cc70e6151ab5d7da8" desc=""> + view decoded + </message> + <message name="IDS_DEVTOOLS_31fde7b05ac8952dacf4af8a704074ec" desc=""> + Preview + </message> + <message name="IDS_DEVTOOLS_336439019ce67912717a20d54298bf24" desc=""> + Receiving Push + </message> + <message name="IDS_DEVTOOLS_346ff32eaa3c09983fb2ec057816d352" desc=""> + TIME + </message> + <message name="IDS_DEVTOOLS_3681a6c01fa5b440938e8112bfc13996" desc=""> + ServiceWorker Preparation + </message> + <message name="IDS_DEVTOOLS_36d95f430159f0ac7a477e4ee6c5ad21" desc=""> + Remove all patterns + </message> + <message name="IDS_DEVTOOLS_376815607a4b79934f79305216a8048c" desc=""> + Record (<ph name="RECORDNODE">$1s</ph>) or reload (<ph name="RELOADSHORTCUTNODE">$2s</ph>) to display network activity. + </message> + <message name="IDS_DEVTOOLS_37bb3bd9caf5dafb7c8f9eccb3b9800e" desc=""> + (unable to decode value) + </message> + <message name="IDS_DEVTOOLS_383fc50a38f1666adc3f06d0bdf71467" desc=""> + Are you sure you want to clear browser cookies? + </message> + <message name="IDS_DEVTOOLS_3b5904efd4efd03d09ee9a8f964f39d6" desc=""> + <ph name="NUMBER_BYTESTOSTRING_RESOURCESIZE_">$1s</ph> resources + </message> + <message name="IDS_DEVTOOLS_3b83f6ae91bb21147fd97b8b8229287f" desc=""> + Certificate URL + </message> + <message name="IDS_DEVTOOLS_3c06899dae839e1ca3051475a2b8fa05" desc=""> + Preview not available + </message> + <message name="IDS_DEVTOOLS_3c2f5decde47940c8baf3b80dea449bd" desc=""> + csp + </message> + <message name="IDS_DEVTOOLS_3c309d9a9f7ff31319c7ecb0a19b2b3f" desc=""> + Select automatically + </message> + <message name="IDS_DEVTOOLS_3dab30e9b9adf193562ff9a09dcd41a5" desc=""> + Remote Address + </message> + <message name="IDS_DEVTOOLS_3e0dc7bd31f5ad41b900fef5b7aba791" desc=""> + Don't group network log items by frame + </message> + <message name="IDS_DEVTOOLS_41de6d6cfb8953c021bbe4ba0701c8a1" desc=""> + Messages + </message> + <message name="IDS_DEVTOOLS_41e85145baafb89d0b709ae827218084" desc=""> + Clear browser cache + </message> + <message name="IDS_DEVTOOLS_4202ef115ebede37eb22297113f5fb32" desc=""> + Redirect + </message> + <message name="IDS_DEVTOOLS_42d61b587a0123390822777d84e0f6bd" desc=""> + Response code + </message> + <message name="IDS_DEVTOOLS_44749712dbec183e983dcd78a7736c41" desc=""> + Date + </message> + <message name="IDS_DEVTOOLS_4566ce384ed4a889beb6f6432d5906d7" desc=""> + Network panel + </message> + <message name="IDS_DEVTOOLS_459c830504806e5747ddc40008ccbade" desc=""> + Add custom header… + </message> + <message name="IDS_DEVTOOLS_46ff2c7bbdbb02687287512c874d391f" desc=""> + signed-exchange + </message> + <message name="IDS_DEVTOOLS_490aa6e856ccf208a054389e47ce0d06" desc=""> + Id + </message> + <message name="IDS_DEVTOOLS_4a5a4b959ef84dd7b7ee73e837b6a54e" desc=""> + Reveal in Network panel + </message> + <message name="IDS_DEVTOOLS_4a7ba0d17eafde708ca8f5f34debcfef" desc=""> + <ph name="TRANSFERSIZE">$1s</ph> B transferred + </message> + <message name="IDS_DEVTOOLS_4bd7c2ff07dcc66801a9368957d4bff8" desc=""> + Initiator + </message> + <message name="IDS_DEVTOOLS_4c3880bb027f159e801041b1021e88e8" desc=""> + Method + </message> + <message name="IDS_DEVTOOLS_4dea2ac78e9450e62e96c166ef9f5d4c" desc=""> + Manage Header Columns… + </message> + <message name="IDS_DEVTOOLS_4e88c13fb97f356a81c48bf2644bef51" desc=""> + Connection Start + </message> + <message name="IDS_DEVTOOLS_5023e5b1d1c02cf168a9a67dda6d2d87" desc=""> + Show overview + </message> + <message name="IDS_DEVTOOLS_502996d9790340c5fd7b86a5b93b1c9f" desc=""> + Priority + </message> + <message name="IDS_DEVTOOLS_5101cdda28ea3097ac00cdbfdcedc353" desc=""> + Use default colors + </message> + <message name="IDS_DEVTOOLS_51360304ea03557e79bdf5ff9cd2e234" desc=""> + Issuer + </message> + <message name="IDS_DEVTOOLS_53fa249ce3d02c8a686b657b31d02ee7" desc=""> + Copy response + </message> + <message name="IDS_DEVTOOLS_5639d3df5aea3d9e78027b843ee3cbb2" desc=""> + Receive + </message> + <message name="IDS_DEVTOOLS_566bbee0f961ad71b54c3c2fd36db053" desc=""> + extension + </message> + <message name="IDS_DEVTOOLS_56ecb97c626815b7f982c04e736f624b" desc=""> + Response headers + </message> + <message name="IDS_DEVTOOLS_57db0f3677bfe1e5af2f568c71369e9e" desc=""> + Save all as HAR with content + </message> + <message name="IDS_DEVTOOLS_58f6ae6f525fa723c603752e682be6a7" desc=""> + This request has no response data available. + </message> + <message name="IDS_DEVTOOLS_59535aed1e49266dfd0b93172f5a7242" desc=""> + Group by frame + </message> + <message name="IDS_DEVTOOLS_597b56e53847cd6a4712ac183f61fa68" desc=""> + Cookies + </message> + <message name="IDS_DEVTOOLS_5cb98890f19c13e5fce52287187d9803" desc=""> + <ph name="SELECTEDNODENUMBER">$1s</ph> / <ph name="NODECOUNT">$2s</ph> requests + </message> + <message name="IDS_DEVTOOLS_5e2f683aacb9d5f3635b3f88583dec80" desc=""> + Custom... + </message> + <message name="IDS_DEVTOOLS_5f0ea62e5bc9f795512ef292ff162a2a" desc=""> + Disable cache (while DevTools is open) + </message> + <message name="IDS_DEVTOOLS_5f903b8316b9649547e1b3ceef934183" desc=""> + Stop recording network log + </message> + <message name="IDS_DEVTOOLS_611a2b5dcde004cf68ffd56345584d40" desc=""> + ETag + </message> + <message name="IDS_DEVTOOLS_619d32de7168c6e770464dfc43e374d1" desc=""> + Request Headers + </message> + <message name="IDS_DEVTOOLS_6311ae17c1ee52b36e68aaf4ad066387" desc=""> + Other + </message> + <message name="IDS_DEVTOOLS_6490fac2ddb40e1e2a7e0c43fb661c7b" desc=""> + Failed to load response data + </message> + <message name="IDS_DEVTOOLS_649635a49f102b60bd81884f3e2fd3ca" desc=""> + Collecting content… + </message> + <message name="IDS_DEVTOOLS_65a9d5faea2e8027d9a96544c579e312" desc=""> + Certificate SHA256 + </message> + <message name="IDS_DEVTOOLS_6638d1cbb8be347d80370bc5bb58a0d1" desc=""> + Copy as UTF-8 + </message> + <message name="IDS_DEVTOOLS_6a7c804797a8bb913c82824a6465ede1" desc=""> + Header Name + </message> + <message name="IDS_DEVTOOLS_6a98894cd6b4628f0b5117412aab083e" desc=""> + Cache-Control + </message> + <message name="IDS_DEVTOOLS_6c2a1bf87fb84c91fc7e1120f4e3d0c7" desc=""> + Content Download + </message> + <message name="IDS_DEVTOOLS_6c3ae60298916e218f26a95f4ff21085" desc=""> + Response Cookies + </message> + <message name="IDS_DEVTOOLS_6dd7482f131dc036ea08395a7f3f5e08" desc=""> + Enter a custom user agent + </message> + <message name="IDS_DEVTOOLS_6e68a529a38966508d348e9f65d7ea31" desc=""> + Record network log + </message> + <message name="IDS_DEVTOOLS_71fb2761cd2a446400a8069fe16cd45e" desc=""> + Block request domain + </message> + <message name="IDS_DEVTOOLS_722e6ea747a62b7f93bb017d3dd04cbd" desc=""> + Continuation Frame + </message> + <message name="IDS_DEVTOOLS_72d569ab3718d10a89315f80cf05cc73" desc=""> + Group network log by frame + </message> + <message name="IDS_DEVTOOLS_73c1ba64f0484588be030de81de469ae" desc=""> + Initial connection + </message> + <message name="IDS_DEVTOOLS_7543ba96bb16a5f17f8fb25bdd995d3f" desc=""> + Copy as Base64 + </message> + <message name="IDS_DEVTOOLS_76669aaf74dda2a59e3c363da10c3faf" desc=""> + Reading Push + </message> + <message name="IDS_DEVTOOLS_77f02f5047451625e1c6bb24884cdfe6" desc=""> + Copied as Hex + </message> + <message name="IDS_DEVTOOLS_79307e20670213e6f99203c2d81bbbaf" desc=""> + (ServiceWorker) + </message> + <message name="IDS_DEVTOOLS_7954bc50e461d57fa640f77741cea491" desc=""> + Resource Scheduling + </message> + <message name="IDS_DEVTOOLS_795f3202b17cb6bc3d4b771d8c6c9eaf" desc=""> + other + </message> + <message name="IDS_DEVTOOLS_7b5bea45778433caf34b0ba556a7d93b" desc=""> + (failed) + </message> + <message name="IDS_DEVTOOLS_7c49b153d4b59f8c0cf8c3e18dc80cb7" desc=""> + origin + </message> + <message name="IDS_DEVTOOLS_7de2b6840dd6a1683f809daaf2d95fb0" desc=""> + Hex Viewer + </message> + <message name="IDS_DEVTOOLS_7e1c4c7b01e0fd0ad1e89ca7512f353e" desc=""> + Ping Message + </message> + <message name="IDS_DEVTOOLS_804910399e8d26511871e33416ccd127" desc=""> + Served from disk cache, resource size: <ph name="RESOURCESIZE">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_814f9c3c7e7aa04c21f2e61f5b2dcf18" desc=""> + Copy response headers + </message> + <message name="IDS_DEVTOOLS_8166a4b3fb4979da3a24ed21ced7fdf7" desc=""> + Learn more + </message> + <message name="IDS_DEVTOOLS_827452688eed02a12178e96f924ac529" desc=""> + Scheme + </message> + <message name="IDS_DEVTOOLS_838c672414343cdd527a63d910fb132c" desc=""> + Hide data URLs + </message> + <message name="IDS_DEVTOOLS_850985cd851d0fe440f03f77762e2590" desc=""> + Content-Length + </message> + <message name="IDS_DEVTOOLS_8644fe7afb1a31ea7274f5ee90dff50b" desc=""> + view URL encoded + </message> + <message name="IDS_DEVTOOLS_878ff0bac714397ab62012691efc2087" desc=""> + Text Message + </message> + <message name="IDS_DEVTOOLS_881e9a305ce80960413ab7f227ef879e" desc=""> + User agent + </message> + <message name="IDS_DEVTOOLS_883d7615c4d2de3fa1218f1298c46d0e" desc=""> + Headers + </message> + <message name="IDS_DEVTOOLS_884680dd63eae99eab1a407133df66b7" desc=""> + View certificate + </message> + <message name="IDS_DEVTOOLS_888a77f5ac0748b6c8001822417df8b6" desc=""> + Protocol + </message> + <message name="IDS_DEVTOOLS_889f316cd1f0ac68f8ea3052e8568061" desc=""> + Copy as PowerShell + </message> + <message name="IDS_DEVTOOLS_896ef2edb423627350de605744e10385" desc=""> + Set Cookies + </message> + <message name="IDS_DEVTOOLS_8c074f405ad9737b1b59d35d6aab7cab" desc=""> + Last-Modified + </message> + <message name="IDS_DEVTOOLS_8c09001c99ecb6fdd8d6023fcf039054" desc=""> + Signature + </message> + <message name="IDS_DEVTOOLS_8c2297c17712046f3a7ffd65c2c5ad50" desc=""> + Validity URL + </message> + <message name="IDS_DEVTOOLS_8e40e89c8c95a050dcadea2d7e4d40cc" desc=""> + devtools + </message> + <message name="IDS_DEVTOOLS_8eb2a485218c2fd5b53651ec35337858" desc=""> + Use large request rows + </message> + <message name="IDS_DEVTOOLS_8eed70a0dcf3e8f43d0548cd1e8f22ed" desc=""> + Hides data: and blob: URLs + </message> + <message name="IDS_DEVTOOLS_8f32afe4e92699a3c6923a66815f5e16" desc=""> + Request sent + </message> + <message name="IDS_DEVTOOLS_8f3d10eb21bd36347c258679eba9e92b" desc=""> + Finished + </message> + <message name="IDS_DEVTOOLS_90198f1c07c67e3a44ccc6853651ca2c" desc=""> + Response Headers + </message> + <message name="IDS_DEVTOOLS_9146d056f26c33effdc2f83dd9e79395" desc=""> + Copy all as cURL (bash) + </message> + <message name="IDS_DEVTOOLS_91d92a76f6e3919419b019b07889c73b" desc=""> + Clear browser cookies + </message> + <message name="IDS_DEVTOOLS_92480c24ad37b4f15c6a43fd54ec2376" desc=""> + WebSocket messages + </message> + <message name="IDS_DEVTOOLS_9254e453e41bb4058ee1e8c1a2b81a4d" desc=""> + Queueing + </message> + <message name="IDS_DEVTOOLS_935f218785830f964d0c537b23027045" desc=""> + <ph name="NUMBER_BYTESTOSTRING_SELECTEDTRANSFERSIZE_">$1s</ph> / <ph name="NUMBER_BYTESTOSTRING_TRANSFERSIZE_">$2s</ph> transferred + </message> + <message name="IDS_DEVTOOLS_948ff4d0d124f02ff1dc0a9c56ef8ade" desc=""> + Recording network activity… + </message> + <message name="IDS_DEVTOOLS_94966d90747b97d1f0f206c98a8b1ac3" desc=""> + Send + </message> + <message name="IDS_DEVTOOLS_96b0141273eabab320119c467cdcaf17" desc=""> + Total + </message> + <message name="IDS_DEVTOOLS_96d960cc2b3394824ebfbf25bb960a90" desc=""> + <ph name="LOCALIZEDDESCRIPTION">$1s</ph> (Opcode <ph name="OPCODE">$2s</ph>, mask) + </message> + <message name="IDS_DEVTOOLS_96e9bc575b5d3ed541113a249da8bd24" desc=""> + Capture screenshots + </message> + <message name="IDS_DEVTOOLS_97b7320892b0db86ff1d8dc28ba1af95" desc=""> + Are you sure you want to clear browser cache? + </message> + <message name="IDS_DEVTOOLS_97f0a2ba508f8299c686818366ad712a" desc=""> + (data) + </message> + <message name="IDS_DEVTOOLS_985187565936a7c1e02c9f96852c0f9a" desc=""> + subresource-filter + </message> + <message name="IDS_DEVTOOLS_986371172510b03c03ac7cd17c1f84d4" desc=""> + Served from Signed HTTP Exchange, resource size: <ph name="RESOURCESIZE">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_986491ef3610ed7ef82bd863e4ee00a2" desc=""> + Request blocking + </message> + <message name="IDS_DEVTOOLS_9979c41f94d4d232c06b4c87f2d0f951" desc=""> + Push / + </message> + <message name="IDS_DEVTOOLS_9a41e9b9ca01e7239185b042be18f9eb" desc=""> + Connection ID + </message> + <message name="IDS_DEVTOOLS_9a83ab0d60fed7c37d928ccb30d1b6ae" desc=""> + Parser + </message> + <message name="IDS_DEVTOOLS_9aa1b03934893d7134a660af4204f2a9" desc=""> + Server + </message> + <message name="IDS_DEVTOOLS_9c1ab57e621c2bb257798752dbbe6f14" desc=""> + view source + </message> + <message name="IDS_DEVTOOLS_9cabd6c0f7878c8106104aee4a24a41e" desc=""> + Copy as cURL (cmd) + </message> + <message name="IDS_DEVTOOLS_9e08e91089d39bc26c4c57e9780c2f60" desc=""> + (from memory cache) + </message> + <message name="IDS_DEVTOOLS_9e65b51e82f2a9b9f72ebe3e083582bb" desc=""> + (empty) + </message> + <message name="IDS_DEVTOOLS_9ffaf77e2c524827dff95993361e7115" desc=""> + Raw response data + </message> + <message name="IDS_DEVTOOLS_a00705e19cc5f358d77688d197604cc3" desc=""> + <ph name="NUMBER_BYTESTOSTRING_TRANSFERSIZE_">$1s</ph> transferred + </message> + <message name="IDS_DEVTOOLS_a0820b213c0f695e95fc0c278a05400f" desc=""> + <ph name="COUNT">$1d</ph> blocked + </message> + <message name="IDS_DEVTOOLS_a217246afb12245a032617715f81923b" desc=""> + Manage Header Columns + </message> + <message name="IDS_DEVTOOLS_a227f203e4a2e520debf44ae78f16847" desc=""> + Copied as Base64 + </message> + <message name="IDS_DEVTOOLS_a249aec821f73349cc457658bd6c04f3" desc=""> + Copy as Hex + </message> + <message name="IDS_DEVTOOLS_a299d2f506523f8104dc4202de7b0c64" desc=""> + Export HAR... + </message> + <message name="IDS_DEVTOOLS_a5d6e0224f694699dde6d1bd34d608bd" desc=""> + Copy as cURL + </message> + <message name="IDS_DEVTOOLS_a612782072a3b8f151c5e2120ef20efd" desc=""> + Copy to clipboard + </message> + <message name="IDS_DEVTOOLS_a74e6894e1f36ce12a6773b9a6b9aea8" desc=""> + <ph name="NODECOUNT">$1s</ph> requests + </message> + <message name="IDS_DEVTOOLS_a76d4ef5f3f6a672bbfab2865563e530" desc=""> + Time + </message> + <message name="IDS_DEVTOOLS_a976624c5265b8187b19aea9df9230eb" desc=""> + Color-code resource types + </message> + <message name="IDS_DEVTOOLS_abe6fec6834dc303e1abfb03f9874786" desc=""> + DOMContentLoaded: <ph name="NUMBER_SECONDSTOSTRING_THIS__MAINREQUESTDOMCONTENTLOADEDTIME___BASETIME_">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_ac5eb504b5a840271e066bf6fd3000b8" desc=""> + view parsed + </message> + <message name="IDS_DEVTOOLS_ad86890fb40822a3b12627efaca4ecd7" desc=""> + (disk cache) + </message> + <message name="IDS_DEVTOOLS_add0160d0ea7e2969930b281a6ba1456" desc=""> + Drop HAR files here + </message> + <message name="IDS_DEVTOOLS_ae3b3df9970b49b6523e608759bc957d" desc=""> + UTF-8 + </message> + <message name="IDS_DEVTOOLS_af0a229a0c5be77de07889743db3b409" desc=""> + Copied as UTF-8 + </message> + <message name="IDS_DEVTOOLS_af6ef9fe7e48178f3765aa8e44f9ce5d" desc=""> + Group network log items by frame + </message> + <message name="IDS_DEVTOOLS_b021df6aac4654c454f46c77646e745f" desc=""> + Label + </message> + <message name="IDS_DEVTOOLS_b1f63146853f7f450d8622aae6a73408" desc=""> + Copy as cURL (bash) + </message> + <message name="IDS_DEVTOOLS_b2844b8e17ecaaeae68d018fe9418af0" desc=""> + Valid until + </message> + <message name="IDS_DEVTOOLS_b4774747599df05309e1de2e2734dd3e" desc=""> + Request to ServiceWorker + </message> + <message name="IDS_DEVTOOLS_b6434258c743f8673997b5aeb3721c27" desc=""> + Request Method + </message> + <message name="IDS_DEVTOOLS_b72ac10807b29c77f5b7e4b80ea40414" desc=""> + Explanation + </message> + <message name="IDS_DEVTOOLS_b926fd82158cde57655d0cd1dd8dbc70" desc=""> + Query String Parameters + </message> + <message name="IDS_DEVTOOLS_b9449f52ba4f16fc7dd7fb7cd0c6c5c7" desc=""> + Network throttling + </message> + <message name="IDS_DEVTOOLS_b94a47df08b4ab492c78deb7a2940662" desc=""> + Disable cache + </message> + <message name="IDS_DEVTOOLS_b9ad5629c19552041dadd5b4feb22772" desc=""> + Response Time + </message> + <message name="IDS_DEVTOOLS_ba2a9c6c8c77e03f83ef8bf543612275" desc=""> + Length + </message> + <message name="IDS_DEVTOOLS_bd474658f3a7ae560cc97b6b64264045" desc=""> + mixed-content + </message> + <message name="IDS_DEVTOOLS_bd9176ee57c46268a853e038b133966a" desc=""> + Keep-Alive + </message> + <message name="IDS_DEVTOOLS_bdaacef16991cfa4cf17a388579e7c06" desc=""> + EventStream + </message> + <message name="IDS_DEVTOOLS_c02504bf83e5cc0d2f582f189a804aef" desc=""> + Request Cookies + </message> + <message name="IDS_DEVTOOLS_c2cc7082a89c1ad6631a2f66af5f00c0" desc=""> + Connection + </message> + <message name="IDS_DEVTOOLS_c33fa8b7d663932b656f0f7f53a74e77" desc=""> + Requests are not blocked. + </message> + <message name="IDS_DEVTOOLS_c3c14eb17a6cf9c6120f381790ed06eb" desc=""> + Copy all as PowerShell + </message> + <message name="IDS_DEVTOOLS_c4e4fcc7d371549aec967e7157ba436d" desc=""> + SignedExchange error + </message> + <message name="IDS_DEVTOOLS_c54dcc2fd5e72371ef21f1553d79e740" desc=""> + (canceled) + </message> + <message name="IDS_DEVTOOLS_c6f969f563d21beac9731f177053484c" desc=""> + <ph name="SELECTEDRESOURCESIZE">$1s</ph> B / <ph name="RESOURCESIZE">$2s</ph> B resources + </message> + <message name="IDS_DEVTOOLS_c7892ebbb139886662c6f2fc8c450710" desc=""> + Subject + </message> + <message name="IDS_DEVTOOLS_c81e295bfd7fbaec6257ea14992f4643" desc=""> + Request and response cookies + </message> + <message name="IDS_DEVTOOLS_c84718b71b8ad70dde23736e79e25e83" desc=""> + Pong Message + </message> + <message name="IDS_DEVTOOLS_c91a577b72313356fad611c55f43c10f" desc=""> + End Time + </message> + <message name="IDS_DEVTOOLS_cb64a2679b345ae476ea3a7fb6a70080" desc=""> + Binary Message + </message> + <message name="IDS_DEVTOOLS_cc0af601bfd673427a8abb171f62c707" desc=""> + content-type + </message> + <message name="IDS_DEVTOOLS_cebd9a3a94f022d3600e0f81a9aa2060" desc=""> + <ph name="NUMBER_BYTESTOSTRING_SELECTEDRESOURCESIZE_">$1s</ph> / <ph name="NUMBER_BYTESTOSTRING_RESOURCESIZE_">$2s</ph> resources + </message> + <message name="IDS_DEVTOOLS_cf5c8b06caaf075b4e453ce29d27760f" desc=""> + Served from prefetch cache, resource size: <ph name="RESOURCESIZE">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_cfc36842a01da69c484ffdcc6782f437" desc=""> + Expires + </message> + <message name="IDS_DEVTOOLS_d0a9f074f48f9416d043f27687c1f030" desc=""> + Proxy negotiation + </message> + <message name="IDS_DEVTOOLS_d0e5383d7c91948cfab6cacccec8812d" desc=""> + (from signed-exchange) + </message> + <message name="IDS_DEVTOOLS_d3b69e993f4e9bf9c479c7e794ede387" desc=""> + Timing + </message> + <message name="IDS_DEVTOOLS_d64ed3e9c10229648e069f56e32f4c8e" desc=""> + Response + </message> + <message name="IDS_DEVTOOLS_d76e44f856d0114826e7436a630a3fa7" desc=""> + (signed-exchange) + </message> + <message name="IDS_DEVTOOLS_d7e76ea0c048939444b2aa8653f048d0" desc=""> + Record (<ph name="RECORDNODE">$1s</ph>) to display network activity. + </message> + <message name="IDS_DEVTOOLS_d82a834165b99c4ea0969316296a2bc2" desc=""> + Vary + </message> + <message name="IDS_DEVTOOLS_db67b2de0114bd82fe1383aa067fa6b2" desc=""> + Unblock <ph name="CROPPEDURL">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_dc30bc0c7914db5918da4263fce93ad2" desc=""> + Clear + </message> + <message name="IDS_DEVTOOLS_dc5d60b066d9a30e68dd648dcabf8579" desc=""> + This request has no cookies. + </message> + <message name="IDS_DEVTOOLS_dc66e209093fbef0daa224f2b6401b39" desc=""> + Request/Response + </message> + <message name="IDS_DEVTOOLS_dd47445f60115097d07d4cf2e61d933b" desc=""> + CAUTION: request is not finished yet! + </message> + <message name="IDS_DEVTOOLS_de4642e93235c872dcc21d7e4c926c36" desc=""> + Copy all as fetch + </message> + <message name="IDS_DEVTOOLS_de9b14d980b77c264d42463f407180be" desc=""> + Provisional headers are shown + </message> + <message name="IDS_DEVTOOLS_df080c10e2e9f1e98c180fe2645f6132" desc=""> + Request URL + </message> + <message name="IDS_DEVTOOLS_e186ebc46177c666cd1d5bda52ade420" desc=""> + Response preview + </message> + <message name="IDS_DEVTOOLS_e1905358311029126da11f4e24fca90d" desc=""> + (<ph name="PARAMS_LENGTH">$1d</ph>) + </message> + <message name="IDS_DEVTOOLS_e44c5fc0f8fc0dc0181254373cb07c47" desc=""> + Load: <ph name="NUMBER_SECONDSTOSTRING_THIS__MAINREQUESTLOADTIME___BASETIME_">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_e49d4e7e01be604cfb0cf20a72e0853c" desc=""> + Server Timing + </message> + <message name="IDS_DEVTOOLS_e6702855087694e24e954afab8b7e5d0" desc=""> + Connection Close Message + </message> + <message name="IDS_DEVTOOLS_e6fb9da54f521b9c33d41121d4fcd35c" desc=""> + (memory cache) + </message> + <message name="IDS_DEVTOOLS_e77fef0167598bb39846637ac3915f4e" desc=""> + Clear All + </message> + <message name="IDS_DEVTOOLS_ea52c36203c5f99c3ce2442d531b1a22" desc=""> + SSL + </message> + <message name="IDS_DEVTOOLS_eb0bd7de3ba805621bf9e03e4d16b510" desc=""> + Queued at <ph name="CALCULATOR_FORMATVALUE_REQUEST_ISSUETIME______">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_eb0f48a107df1a0f343d4cd513b555e6" desc=""> + Certificate + </message> + <message name="IDS_DEVTOOLS_eb902cf204f3e4dfffeb56d92a9b5c26" desc=""> + Valid from + </message> + <message name="IDS_DEVTOOLS_ec53a8c4f07baed5d8825072c89799be" desc=""> + Status + </message> + <message name="IDS_DEVTOOLS_ec559fc895e8cc77ef0c4d6fdff5bdcb" desc=""> + Form Data + </message> + <message name="IDS_DEVTOOLS_ec9dca2a4b061ad202945d88657e5ddf" desc=""> + Started at <ph name="CALCULATOR_FORMATVALUE_REQUEST_STARTTIME____">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_edfffa5a1ffba7492b25869813e7e15e" desc=""> + Content-Encoding + </message> + <message name="IDS_DEVTOOLS_ef110dd7355d7315c73995a47fe77dfd" desc=""> + DNS Lookup + </message> + <message name="IDS_DEVTOOLS_f1019fecd69b0e6b6bd12db7f58bbb90" desc=""> + Copy message + </message> + <message name="IDS_DEVTOOLS_f1495279152e772a4ecf5cbf17a07c64" desc=""> + Copy message... + </message> + <message name="IDS_DEVTOOLS_f15c1cae7882448b3fb0404682e17e61" desc=""> + Content + </message> + <message name="IDS_DEVTOOLS_f312b3f268931a1367de22756237b197" desc=""> + Headers and request body + </message> + <message name="IDS_DEVTOOLS_f3f97de67c80480904f958df15b8a57b" desc=""> + Integrity + </message> + <message name="IDS_DEVTOOLS_f508b22c8fc4486b19fee39d5ded3841" desc=""> + Network settings + </message> + <message name="IDS_DEVTOOLS_f531e0844f007af2fa80b328e7c82e72" desc=""> + (from disk cache) + </message> + <message name="IDS_DEVTOOLS_f6068daa29dbb05a7ead1e3b5a48bbee" desc=""> + Data + </message> + <message name="IDS_DEVTOOLS_f6c804a6be9719c98a260380833bfde7" desc=""> + Block request URL + </message> + <message name="IDS_DEVTOOLS_f6d1d4157b75f9b68298f7df187a177c" desc=""> + Finish: <ph name="NUMBER_SECONDSTOSTRING_MAXTIME___BASETIME_">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_f9069c6541beaac49cce4b2542069f02" desc=""> + Referrer Policy + </message> + <message name="IDS_DEVTOOLS_f907e651164789346ae0a1e257c462d8" desc=""> + Script + </message> + <message name="IDS_DEVTOOLS_f95d3d09fc16ae9294fbef87ac8d17cb" desc=""> + (pending) + </message> + <message name="IDS_DEVTOOLS_fae900d6e2cf6b54ffae8cad77b9e2a6" desc=""> + (prefetch cache) + </message> + <message name="IDS_DEVTOOLS_fb0df508eafce0076286884cd92fc8fd" desc=""> + Copy request headers + </message> + <message name="IDS_DEVTOOLS_fb6024596d77a7d0ac213f1f12fa1d8b" desc=""> + Text pattern to block matching requests; use * for wildcard + </message> + <message name="IDS_DEVTOOLS_fd747cf7093bd6b5c8eb3b40658a3b13" desc=""> + Total Duration + </message> + <message name="IDS_DEVTOOLS_fe1bc3eb2f3e1a9a90b5401eb6baa5b9" desc=""> + Copy all as cURL + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/node_debugger/node_debugger_strings.grdp b/third_party/blink/renderer/devtools/front_end/node_debugger/node_debugger_strings.grdp new file mode 100644 index 0000000..0e094599 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/node_debugger/node_debugger_strings.grdp
@@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_6c3a6944a808a7c0bbb6788dbec54a9f" desc=""> + Node + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/node_main/node_main_strings.grdp b/third_party/blink/renderer/devtools/front_end/node_main/node_main_strings.grdp new file mode 100644 index 0000000..45a7dad --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/node_main/node_main_strings.grdp
@@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_28e2b83d6f10a98be7535c7b40b05c6e" desc=""> + Add connection + </message> + <message name="IDS_DEVTOOLS_3fd49f986cbd5dd3148c27c9aaaaa700" desc=""> + Network address (e.g. localhost:9229) + </message> + <message name="IDS_DEVTOOLS_75997049f01ae448c39b8a937c4e2035" desc=""> + No connections specified + </message> + <message name="IDS_DEVTOOLS_81c731365b52528d7d0fdb477ebc3b1d" desc=""> + Specify network endpoint and DevTools will connect to it automatically. + </message> + <message name="IDS_DEVTOOLS_b1f0f05f6f7dcbf25e065bb4c31fec72" desc=""> + Node.js: <ph name="TARGETINFO_URL">$1s</ph> + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/object_ui/object_ui_strings.grdp b/third_party/blink/renderer/devtools/front_end/object_ui/object_ui_strings.grdp new file mode 100644 index 0000000..46d6fa38 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/object_ui/object_ui_strings.grdp
@@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_1381e657bdaaff914f1cf300d9ae12ba" desc=""> + The property is computed with a getter + </message> + <message name="IDS_DEVTOOLS_1e7528fc0ca67eed52813139d5208882" desc=""> + No property getter + </message> + <message name="IDS_DEVTOOLS_21a396ebc3d3f5a85721e8328da386dc" desc=""> + <string is too large to edit> + </message> + <message name="IDS_DEVTOOLS_2c8631472a99e236bd93244d69705c7c" desc=""> + Copy property path + </message> + <message name="IDS_DEVTOOLS_2f68e12de25d8be39f50adf5f7714b3d" desc=""> + Show as JavaScript object + </message> + <message name="IDS_DEVTOOLS_376f6694932cd7a556445e2058dd4255" desc=""> + empty × <ph name="COUNT">$1d</ph> + </message> + <message name="IDS_DEVTOOLS_4ced885857185cb26f013fcaaa03a086" desc=""> + <unreadable> + </message> + <message name="IDS_DEVTOOLS_59aeb2c9970b7b25be2fab2317e31fcb" desc=""> + keywords + </message> + <message name="IDS_DEVTOOLS_a2e4822a98337283e39f7b60acf85ec9" desc=""> + empty + </message> + <message name="IDS_DEVTOOLS_a6565c5180039dd2ca1249796bba00a5" desc=""> + No properties + </message> + <message name="IDS_DEVTOOLS_a73e6bf278578e09d2351ee2ec7a7908" desc=""> + Keys + </message> + <message name="IDS_DEVTOOLS_a983530c8e824d30e214200ef6f8a2d7" desc=""> + (...) + </message> + <message name="IDS_DEVTOOLS_ad921d60486366258809553a3db49a4a" desc=""> + unknown + </message> + <message name="IDS_DEVTOOLS_b0d4998a26f5b5742ad38c4af8817e32" desc=""> + Exception + </message> + <message name="IDS_DEVTOOLS_b46f6ce1cece499f73c9d5c36e4a3de4" desc=""> + Invoke property getter + </message> + <message name="IDS_DEVTOOLS_d50bbea3c85be098dcf221e622cd7718" desc=""> + Lexical scope variables + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/perf_ui/perf_ui_strings.grdp b/third_party/blink/renderer/devtools/front_end/perf_ui/perf_ui_strings.grdp new file mode 100644 index 0000000..d38f94e0 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/perf_ui/perf_ui_strings.grdp
@@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_105078d294d30c978ca2badf7f376934" desc=""> + Scroll + </message> + <message name="IDS_DEVTOOLS_28d0edd045e05cf5af64e35ae0c4c6ef" desc=""> + Low + </message> + <message name="IDS_DEVTOOLS_2bd10b449de36fcff52a5d91a97a7365" desc=""> + %.<ph name="FRACTIONDIGITS">$1s</ph>f + </message> + <message name="IDS_DEVTOOLS_3c4684d2d502d7f9d20e05451c2f581c" desc=""> + Next frame + </message> + <message name="IDS_DEVTOOLS_3f21c340f01b96cb3325a5d38ece9da6" desc=""> + Live memory allocation annotations + </message> + <message name="IDS_DEVTOOLS_4789f23283b3a61f858b641a1bef19a3" desc=""> + Memory + </message> + <message name="IDS_DEVTOOLS_4a6d0345e7b6cfcf339237b9cf2d27b4" desc=""> + Flamechart mouse wheel action: + </message> + <message name="IDS_DEVTOOLS_529a032eab49b8ddc6f49f8bcc086607" desc=""> + Previous frame + </message> + <message name="IDS_DEVTOOLS_582996407922dab08d5cf2b3d2a7c1c9" desc=""> + Highest + </message> + <message name="IDS_DEVTOOLS_655d20c1ca69519ca647684edbb2db35" desc=""> + High + </message> + <message name="IDS_DEVTOOLS_77c168e60d966216cd1261c200f87e27" desc=""> + Show live memory allocation annotations + </message> + <message name="IDS_DEVTOOLS_87f8a6ab85c9ced3702b4ea641ad4bb5" desc=""> + Medium + </message> + <message name="IDS_DEVTOOLS_8d8fcc1abd550c5f25dbfaa57d59cb67" desc=""> + MB + </message> + <message name="IDS_DEVTOOLS_90c96ccfe47a731972d5e64deb5fea36" desc=""> + Hide live memory allocation annotations + </message> + <message name="IDS_DEVTOOLS_ab57fd0432e25d5b3013133a1c910d56" desc=""> + KB + </message> + <message name="IDS_DEVTOOLS_b5b8e20937205384be7b9e0c29a28fdb" desc=""> + Lowest + </message> + <message name="IDS_DEVTOOLS_d085f278b95f303c39ba30f1817cca95" desc=""> + Collect garbage + </message> + <message name="IDS_DEVTOOLS_dac0f9afd816c579ba5c6d7a987c4ba6" desc=""> + <ph name="VALUE">$1.1f</ph> + </message> + <message name="IDS_DEVTOOLS_e2885880b7034cd40dce71aeffa3662f" desc=""> + Doubleclick to zoom image. Click to view preceding requests. + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/performance_monitor/performance_monitor_strings.grdp b/third_party/blink/renderer/devtools/front_end/performance_monitor/performance_monitor_strings.grdp new file mode 100644 index 0000000..33164578 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/performance_monitor/performance_monitor_strings.grdp
@@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_029ce83ef9e87df61fb9e580ac165b4a" desc=""> + DOM Nodes + </message> + <message name="IDS_DEVTOOLS_23ab71fd0704d52052b95e54f8e72fb9" desc=""> + Performance monitor + </message> + <message name="IDS_DEVTOOLS_2bd1b3d3ed5950a8e5a28340e368a4ee" desc=""> + Document Frames + </message> + <message name="IDS_DEVTOOLS_5c1131c8862a07ce54be057f516c840e" desc=""> + Layouts / sec + </message> + <message name="IDS_DEVTOOLS_6cce53fb6e5ccd4313ae3ec26fa42ca4" desc=""> + JS event listeners + </message> + <message name="IDS_DEVTOOLS_81f2166e08f25234e2fbb2cd3175f83e" desc=""> + Graphs displaying a real-time view of performance metrics + </message> + <message name="IDS_DEVTOOLS_9ff3fcf082193aaf2b6889fb4662706a" desc=""> + JS heap size + </message> + <message name="IDS_DEVTOOLS_ac2137ec7c503f6997ddb414265791a9" desc=""> + CPU usage + </message> + <message name="IDS_DEVTOOLS_b4cb01a2ff8576df8cbad0872cc6e4a2" desc=""> + Style recalcs / sec + </message> + <message name="IDS_DEVTOOLS_e99180abf47a8b3a856e0bcb2656990a" desc=""> + Paused + </message> + <message name="IDS_DEVTOOLS_f28128b38efbc6134dc40751ee21fd29" desc=""> + Documents + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/persistence/persistence_strings.grdp b/third_party/blink/renderer/devtools/front_end/persistence/persistence_strings.grdp new file mode 100644 index 0000000..4a042b4 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/persistence/persistence_strings.grdp
@@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_03250d684b667899552f89911582dbdc" desc=""> + <ph name="ITEM">$1s</ph> (via .devtools) + </message> + <message name="IDS_DEVTOOLS_03a21915504df93cf5dba0636080f62e" desc=""> + Workspace + </message> + <message name="IDS_DEVTOOLS_03ad5ac9c1a313e19064670f92981353" desc=""> + Add folder… + </message> + <message name="IDS_DEVTOOLS_14f221497f99c10993cd293628adeefd" desc=""> + Open in containing folder + </message> + <message name="IDS_DEVTOOLS_17d5f7dcd4ef6b9702a8b2ac7d237e5b" desc=""> + Enable override network requests + </message> + <message name="IDS_DEVTOOLS_25ee7702f0b5dbe737d8f0f2ba3ce591" desc=""> + Save for overrides + </message> + <message name="IDS_DEVTOOLS_486658cc6336ffa59ef2fdff0b977a91" desc=""> + Excluded folders + </message> + <message name="IDS_DEVTOOLS_5f6bb21e40e670952b73ca35eafbe35a" desc=""> + Disable override network requests + </message> + <message name="IDS_DEVTOOLS_62def4422771353f5e30763d92474b43" desc=""> + Linked to source map: <ph name="BINDING_NETWORK_URL___TRIMMIDDLE_____">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_8d646fe956bbc874d742471885ffd77c" desc=""> + Folder exclude pattern + </message> + <message name="IDS_DEVTOOLS_ab130072b340b847d8d45ec45d191c3b" desc=""> + Mappings are inferred automatically. + </message> + <message name="IDS_DEVTOOLS_afb4ea732ebcf8bd51a3d99a1b8909a8" desc=""> + Linked to <ph name="PATH">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_cf703cce77386955bfbff86f6ad9be03" desc=""> + Unable to add filesystem: <ph name="ERRORMESSAGE">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_da0b472ac86851a3c0b623260d09546c" desc=""> + Persistence + </message> + <message name="IDS_DEVTOOLS_e13c8cb15857d020445d01a8817f7d34" desc=""> + File system error: <ph name="ERROR_MESSAGE">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_e2b63f5cab4f80fb6745f2f941105371" desc=""> + Enable Local Overrides + </message> + <message name="IDS_DEVTOOLS_ec211f7c20af43e742bf2570c3cb84f9" desc=""> + Add + </message> + <message name="IDS_DEVTOOLS_fddede572fa09e1b1bb28504d8c43343" desc=""> + Folder path + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/product_registry/product_registry_strings.grdp b/third_party/blink/renderer/devtools/front_end/product_registry/product_registry_strings.grdp new file mode 100644 index 0000000..af16ee2 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/product_registry/product_registry_strings.grdp
@@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_8cb0e09c4d24f1c4aef14d8e2f1592a6" desc=""> + Show third party badges + </message> + <message name="IDS_DEVTOOLS_c9b7856510bf5901af2e388926d77b94" desc=""> + Show third party URL badges + </message> + <message name="IDS_DEVTOOLS_e56f0c64e0eb84e8799baa5bf890acb5" desc=""> + Do not show third party badges + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/profiler/profiler_strings.grdp b/third_party/blink/renderer/devtools/front_end/profiler/profiler_strings.grdp new file mode 100644 index 0000000..b46a803 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/profiler/profiler_strings.grdp
@@ -0,0 +1,439 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_00018e8c8fc32e1ec073c0cdbadb5575" desc=""> + <ph name="NUMBER_WITHTHOUSANDSSEPARATOR_VALUE________">$1s</ph> KB + </message> + <message name="IDS_DEVTOOLS_007c41a9025be2c8e14b496ed3ee00f8" desc=""> + Save… + </message> + <message name="IDS_DEVTOOLS_02184526968aa861a744df910647fcf0" desc=""> + Freed Size + </message> + <message name="IDS_DEVTOOLS_0257542bea15eb6baa3fc0364cd3ba24" desc=""> + <ph name="NUMBER_WITHTHOUSANDSSEPARATOR_MATH_ROUND_VALUE_________">$1s</ph> KB + </message> + <message name="IDS_DEVTOOLS_030361ea56fa177ebcbefe708a45b0f2" desc=""> + # Deleted + </message> + <message name="IDS_DEVTOOLS_04042b5589b3d4fd4e1e7e44265ad247" desc=""> + Total page JS heap size change trend over the last <ph name="TRENDINTERVALMINUTES">$1s</ph> minutes. + </message> + <message name="IDS_DEVTOOLS_05ce989cc1015cd221844376fc4cf206" desc=""> + Snapshot <ph name="PROFILE_UID">$1d</ph> + </message> + <message name="IDS_DEVTOOLS_07b20ae970048fc2002d756f27acc863" desc=""> + Renderer + </message> + <message name="IDS_DEVTOOLS_07d2bff541ce0f9ec4389e93a97997ee" desc=""> + Objects allocated between <ph name="LIST_I______TITLE">$1s</ph> and <ph name="LIST_I__TITLE">$2s</ph> + </message> + <message name="IDS_DEVTOOLS_0a63e0039bb8cb9846ad74ace8e1e5de" desc=""> + Call tree + </message> + <message name="IDS_DEVTOOLS_0aa6f4210bf373c95eda00232e93cd98" desc=""> + Distance + </message> + <message name="IDS_DEVTOOLS_11a755d598c0c417f9a36758c3da7481" desc=""> + Stop + </message> + <message name="IDS_DEVTOOLS_13b5bfe96f3e2fe411c9f66f4a582adf" desc=""> + in + </message> + <message name="IDS_DEVTOOLS_164c4aca31febd73a41b50c4a9c406be" desc=""> + Snapshotting… + </message> + <message name="IDS_DEVTOOLS_17321b102f09de9aaa68f2b16a530247" desc=""> + Total JS heap size + </message> + <message name="IDS_DEVTOOLS_17c34fb9ce9a7a20604a5f10e447edce" desc=""> + Heap size change trend over the last <ph name="TRENDINTERVALMINUTES">$1s</ph> minutes. + </message> + <message name="IDS_DEVTOOLS_1816452291df3cd48db5667463361f25" desc=""> + Focus selected function + </message> + <message name="IDS_DEVTOOLS_1d36783e12317ed400ebeddeb072a27b" desc=""> + Chart + </message> + <message name="IDS_DEVTOOLS_1eaeeaeb638fdf7f6eeb047abbfd0f1a" desc=""> + Self Time + </message> + <message name="IDS_DEVTOOLS_1f1e990a1d2ba8ab4dd873a192237c30" desc=""> + <ph name="VALUE">$1.1f</ph> ms + </message> + <message name="IDS_DEVTOOLS_27c0ad7a8ff8f9df8e13bb2d974c95d0" desc=""> + Allocation + </message> + <message name="IDS_DEVTOOLS_290612199861c31d1036b185b4e69b75" desc=""> + Summary + </message> + <message name="IDS_DEVTOOLS_2d7b69664bc4226fb198124fb707e57c" desc=""> + Snapshot <ph name="THIS_NEXTPROFILEUID__">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_2db1f9be46028cfdf9b8f96a0110e637" desc=""> + <ph name="VALUE">$1.2f</ph> %% + </message> + <message name="IDS_DEVTOOLS_2def01e5dee6051b68f5b1e5e2fc8ad4" desc=""> + System Objects + </message> + <message name="IDS_DEVTOOLS_2f318b400ebcb22420251535452efef0" desc=""> + Containment + </message> + <message name="IDS_DEVTOOLS_32e679bdbd5dd7a0bacf024bc30e8a75" desc=""> + Recording… + </message> + <message name="IDS_DEVTOOLS_35066690e799cd4e59123262e41b29c5" desc=""> + Stop CPU profiling + </message> + <message name="IDS_DEVTOOLS_36917e785bd31d786ab9dd7790a9a4c2" desc=""> + JS Heap + </message> + <message name="IDS_DEVTOOLS_3a9619400e054970a7ab8b67c4ce5109" desc=""> + Restore all functions + </message> + <message name="IDS_DEVTOOLS_3ae3895607d1203d8e73e18dd4c4551c" desc=""> + Allocation profiles show sampled native memory allocations from the renderer process. + </message> + <message name="IDS_DEVTOOLS_3b6077563702806850baeddff55ee1c6" desc=""> + Preview is not available + </message> + <message name="IDS_DEVTOOLS_3ce9ab6602763824b2f317965c6a1a20" desc=""> + Heap size in use by live JS objects. + </message> + <message name="IDS_DEVTOOLS_3e6defd685231cdd12065add41996c89" desc=""> + All objects + </message> + <message name="IDS_DEVTOOLS_3eea5ef5cf936633884b33c458451013" desc=""> + Show native functions in JS Profile + </message> + <message name="IDS_DEVTOOLS_412ec4c9168f10f6e2061f65f0358079" desc=""> + Typed Arrays + </message> + <message name="IDS_DEVTOOLS_41a813362d7dc28fd247f233f620cb7b" desc=""> + Can't load profile while another profile is being recorded. + </message> + <message name="IDS_DEVTOOLS_42db600672cae99246e499a23827146b" desc=""> + Heap snapshot profiles show memory distribution among your page's JavaScript objects and related DOM nodes. + </message> + <message name="IDS_DEVTOOLS_4307cf6e92b003765b9f493109f8fa51" desc=""> + Native memory allocation sampling + </message> + <message name="IDS_DEVTOOLS_43190a68dbd847e2f98a7ddd04b2eec5" desc=""> + Live Size + </message> + <message name="IDS_DEVTOOLS_433660c1f9743978edc4ca196b5b9f19" desc=""> + Find by cost (>50ms), name or file + </message> + <message name="IDS_DEVTOOLS_435eaeed5b69a2dfb7f343e28d109ce6" desc=""> + Distance from window object + </message> + <message name="IDS_DEVTOOLS_4715ae2a2790290ba123375faa3a53f2" desc=""> + High resolution CPU profiling + </message> + <message name="IDS_DEVTOOLS_497031794414a552435f90151ac3b54b" desc=""> + Object + </message> + <message name="IDS_DEVTOOLS_4b08055cf5445d820914943222d4910c" desc=""> + Script URL + </message> + <message name="IDS_DEVTOOLS_4ca19c06c6e03c07bced1d97ca861cf0" desc=""> + # Delta + </message> + <message name="IDS_DEVTOOLS_4d4d76db5d9ef72b504f83d89af5b6dd" desc=""> + Selected size: <ph name="NUMBER_BYTESTOSTRING_EVENT_DATA_SIZE_">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_4d8aa0a7e336e08bad365b81a197f184" desc=""> + NATIVE SAMPLING PROFILES + </message> + <message name="IDS_DEVTOOLS_4daace4b0bc45c13739427cfc06cf7b7" desc=""> + Text (Top Down) + </message> + <message name="IDS_DEVTOOLS_5209fac92c957988ce1453bb139790ce" desc=""> + Failed to read file + </message> + <message name="IDS_DEVTOOLS_54a238e21ab577ca9c3100d0ed4cd02d" desc=""> + Retained Size + </message> + <message name="IDS_DEVTOOLS_54ae9758deaa74226306072bea256c3c" desc=""> + Stop heap profiling + </message> + <message name="IDS_DEVTOOLS_54afafa921428eed23978f633af4ce99" desc=""> + Allocation sampling + </message> + <message name="IDS_DEVTOOLS_57b1250c3cbec60c67810ac83afb2c64" desc=""> + (internal array) + </message> + <message name="IDS_DEVTOOLS_5dd1d9f5baa173ae9267b3631da17a83" desc=""> + Self size + </message> + <message name="IDS_DEVTOOLS_5e0ebd581894697a7ae357bea6b7e590" desc=""> + Start CPU profiling + </message> + <message name="IDS_DEVTOOLS_60dcffb26f0ed1b0c73f8cea5d5d9772" desc=""> + Native memory allocation snapshot (<ph name="PROCESSTYPE">$1s</ph>) + </message> + <message name="IDS_DEVTOOLS_61b4b76027d49142c386737a0e94cedb" desc=""> + NATIVE SNAPSHOTS + </message> + <message name="IDS_DEVTOOLS_62b96ca53ee08544d8d96269112df323" desc=""> + JS Arrays + </message> + <message name="IDS_DEVTOOLS_678d0a4421b60dc59999ac02837496a6" desc=""> + Constructor + </message> + <message name="IDS_DEVTOOLS_6b59ba1fcfd868474cae169876f9cbfa" desc=""> + Native memory snapshots show sampled native allocations in the renderer process since start up. + Chrome has to be started with --memlog=all flag. Check flags at chrome://flags + </message> + <message name="IDS_DEVTOOLS_6bb61b1a929f2a0186f2671cd8258bd9" desc=""> + Not optimized: <ph name="THIS__DEOPTREASON">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_6d27e30b2f09c2a451a6d123c1a35805" desc=""> + Run <ph name="_">$1d</ph> + </message> + <message name="IDS_DEVTOOLS_6db0d0f1832acb4a56fc82f2317e61e6" desc=""> + Parsing… + </message> + <message name="IDS_DEVTOOLS_6e9dd9cf5419fd65f433f1e4bbc5e6ad" desc=""> + SAMPLING PROFILES + </message> + <message name="IDS_DEVTOOLS_710686e22674bcc79ef72c2485ca96b9" desc=""> + Alloc. Size + </message> + <message name="IDS_DEVTOOLS_7327aea04bd0403771340a3fe03aa42b" desc=""> + Stopping… + </message> + <message name="IDS_DEVTOOLS_7381d487d18845b379422325c0a768d6" desc=""> + Loaded + </message> + <message name="IDS_DEVTOOLS_75d436b4fd4142db941be900a86b9b3e" desc=""> + Allocation stack + </message> + <message name="IDS_DEVTOOLS_7602c7108888133a3e00de63256ae444" desc=""> + Shallow Size + </message> + <message name="IDS_DEVTOOLS_7806c2199c12b018327832bcb3ae20ce" desc=""> + Detached from DOM tree + </message> + <message name="IDS_DEVTOOLS_78a1e5aee115faf6ebf8f2a38ce553d4" desc=""> + Clear all profiles + </message> + <message name="IDS_DEVTOOLS_7ae47a5ac9257db8c7bb89c7afa4db7c" desc=""> + Take snapshot + </message> + <message name="IDS_DEVTOOLS_7cb94d94002a34c350cad72e6649c5fe" desc=""> + Stack was not recorded for this object because it had been allocated before this profile recording started. + </message> + <message name="IDS_DEVTOOLS_7d3d3a2b500a662396911596807715d0" desc=""> + Tree (Top Down) + </message> + <message name="IDS_DEVTOOLS_7e2586c09a41264908762549314a94c0" desc=""> + CPU PROFILES + </message> + <message name="IDS_DEVTOOLS_85000e6433d4ac4033e6d7f5a3466f92" desc=""> + Reveal in Summary view + </message> + <message name="IDS_DEVTOOLS_86408593c34af77fdd90df932f8b5261" desc=""> + Function + </message> + <message name="IDS_DEVTOOLS_86a699c935e3e7e36e334bb61a336f02" desc=""> + Start heap profiling + </message> + <message name="IDS_DEVTOOLS_86de9c70eae18dbd7e1f99cc73f5ce43" desc=""> + # New + </message> + <message name="IDS_DEVTOOLS_89be9433646f5939040a78971a5d103a" desc=""> + Strings + </message> + <message name="IDS_DEVTOOLS_8b8561904173cf8ded80c66eb9628bc3" desc=""> + ⬇<ph name="CHANGERATETEXT">$1s</ph>/s + </message> + <message name="IDS_DEVTOOLS_8df507632e20dff27e88902c825db002" desc=""> + Heap profiler is recording + </message> + <message name="IDS_DEVTOOLS_8e77c83fffc021286d4790b1a28bd695" desc=""> + Select profiling type + </message> + <message name="IDS_DEVTOOLS_9075bd476d18e24259dc388a4569b723" desc=""> + Record memory allocations using sampling method. + This profile type has minimal performance overhead and can be used for long running operations. + It provides good approximation of allocations broken down by JavaScript execution stack. + </message> + <message name="IDS_DEVTOOLS_9206de0db462c24e8a56433e2f7b7c75" desc=""> + Heap Snapshot + </message> + <message name="IDS_DEVTOOLS_959f661cf87130eea5c8e5671c013741" desc=""> + Objects allocated before <ph name="LIST_I__TITLE">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_967d1bd7c21531622e5edfa6c5bf320a" desc=""> + Take heap snapshot + </message> + <message name="IDS_DEVTOOLS_974eabe9dfc86e52b41b310218ac7d05" desc=""> + Total size + </message> + <message name="IDS_DEVTOOLS_9794a8cf80d4f6b67dca3c7381847486" desc=""> + Self Size (bytes) + </message> + <message name="IDS_DEVTOOLS_9d247d9b5e90f2c983240d32113d06d2" desc=""> + Load… + </message> + <message name="IDS_DEVTOOLS_9e854bf5f75e670228f33f9fe857793d" desc=""> + Size of the object plus the graph it retains in bytes + </message> + <message name="IDS_DEVTOOLS_9f29da220ed82809ec5dd70af4e52904" desc=""> + Total Time + </message> + <message name="IDS_DEVTOOLS_a6122a65eaa676f700ae68d393054a37" desc=""> + Start + </message> + <message name="IDS_DEVTOOLS_a73538b7cd30c19b094438e16da9403d" desc=""> + Exclude selected function + </message> + <message name="IDS_DEVTOOLS_a7bd935a88c629dc11c52e0c16c2a8a0" desc=""> + <ph name="DISTANCE">$1d</ph> + </message> + <message name="IDS_DEVTOOLS_a8445619abd08f3ba0ebfcb31183f7f9" desc=""> + − + </message> + <message name="IDS_DEVTOOLS_a92758ee94689bc49f2d6b891e746737" desc=""> + HEAP SNAPSHOTS + </message> + <message name="IDS_DEVTOOLS_a97cce5b0a66cd7d7b7b7d2e06b7605c" desc=""> + Can't load file. Supported file extensions: '<ph name="ARRAY_FROM_EXTENSIONS__JOIN________">$1s</ph>'. + </message> + <message name="IDS_DEVTOOLS_aab112fba39c10ed5df335ae0e47f329" desc=""> + Not optimized + </message> + <message name="IDS_DEVTOOLS_ad49e602302b1ca117245c4f19ef4450" desc=""> + Retainers + </message> + <message name="IDS_DEVTOOLS_ad857c29fb46afef4e17d658f34ead22" desc=""> + An error occurred when a call to method '<ph name="DATA_ERRORMETHODNAME">$1s</ph>' was requested + </message> + <message name="IDS_DEVTOOLS_aebc3d61d99dd094fd29afc12dcd8e1f" desc=""> + Allocation instrumentation on timeline + </message> + <message name="IDS_DEVTOOLS_b59674dba88cebbb4b94a32066ad3dd0" desc=""> + Loading… <ph name="NUMBER_BYTESTOSTRING_THIS__JSONIFIEDPROFILE_LENGTH_">$1d</ph>%% + </message> + <message name="IDS_DEVTOOLS_b8e4045b98241a124561c4d2a69731b8" desc=""> + Heavy (Bottom Up) + </message> + <message name="IDS_DEVTOOLS_bc033a16b36d2d313489933a63a938cf" desc=""> + Live Heap Profile + </message> + <message name="IDS_DEVTOOLS_bd0a5e31e9b3c87eb2d3c19b00cedfc3" desc=""> + Heap memory usage + </message> + <message name="IDS_DEVTOOLS_c22d30084d8ddc9a571512ddee6a83e9" desc=""> + Total time + </message> + <message name="IDS_DEVTOOLS_c2b9b79ea4770ae01a139fe953310039" desc=""> + Live Count + </message> + <message name="IDS_DEVTOOLS_c33e404a441c6ba9648f88af3c68a1ca" desc=""> + Statistics + </message> + <message name="IDS_DEVTOOLS_c9cc8cce247e49bae79f15173ce97354" desc=""> + Save + </message> + <message name="IDS_DEVTOOLS_ca0dbad92a874b2f69b549293387925e" desc=""> + Code + </message> + <message name="IDS_DEVTOOLS_ca425f84afc5ad77fc9c4d75eed8113f" desc=""> + ⬆<ph name="CHANGERATETEXT">$1s</ph>/s + </message> + <message name="IDS_DEVTOOLS_cce99c598cfdb9773ab041d54c3d973a" desc=""> + Profile + </message> + <message name="IDS_DEVTOOLS_d06bb9eb4ee32f700ffc1c9f8e5c0a25" desc=""> + Aggregated self time + </message> + <message name="IDS_DEVTOOLS_d0f25115288c15321ecf672f0d6a83ea" desc=""> + Profiles + </message> + <message name="IDS_DEVTOOLS_d1c7c250869b52eefda57caa7e6eda20" desc=""> + Stop recording heap profile + </message> + <message name="IDS_DEVTOOLS_d3d9fdef0e91fc4aba18e57475fd74ea" desc=""> + VMs + </message> + <message name="IDS_DEVTOOLS_d46b0b413885c920720180d0af60ff54" desc=""> + Record JavaScript CPU Profile + </message> + <message name="IDS_DEVTOOLS_d4bbbe0308b348c609eb4cab28150f80" desc=""> + Heap snapshot + </message> + <message name="IDS_DEVTOOLS_d5a263d11105678cc9ae7d29efc4ccc8" desc=""> + + Allocation timelines show instrumented JavaScript memory allocations over time. + Once profile is recorded you can select a time interval to see objects that + were allocated within it and still alive by the end of recording. + Use this profile type to isolate memory leaks. + </message> + <message name="IDS_DEVTOOLS_d5e5683e3f616ed72e310476bb97f33f" desc=""> + Size of the object itself in bytes + </message> + <message name="IDS_DEVTOOLS_d9319f0a43aaf399eebd2d28713e823a" desc=""> + Select JavaScript VM instance + </message> + <message name="IDS_DEVTOOLS_d9c86ffece4f8636e406975843aa7b4d" desc=""> + Live objects + </message> + <message name="IDS_DEVTOOLS_da9157d11966e9225d29d4f1f0ca3d75" desc=""> + Total page JS heap size across all VM instances. + </message> + <message name="IDS_DEVTOOLS_dc1270259e986e0406259be39a53c8ad" desc=""> + Record allocation stacks (extra performance overhead) + </message> + <message name="IDS_DEVTOOLS_dce00dbf94282d9be42f7d6a4ebc2c41" desc=""> + Self time + </message> + <message name="IDS_DEVTOOLS_ddacdca2bfda777bb0cb7668d76df5f4" desc=""> + (Anonymous Script <ph name="NODE_CALLFRAME_SCRIPTID">$1s</ph>) + </message> + <message name="IDS_DEVTOOLS_df3b67aec764dd36b2a1e94d7f205051" desc=""> + ALLOCATION TIMELINES + </message> + <message name="IDS_DEVTOOLS_e098faba9dade304f660aed30940747a" desc=""> + Start recording heap profile + </message> + <message name="IDS_DEVTOOLS_e93f994f01c537c4e2f7d8528c3eb5e9" desc=""> + Count + </message> + <message name="IDS_DEVTOOLS_ea1c7351fd540546f03ac089a7b41eb3" desc=""> + Profile loading failed: <ph name="ERROR_MESSAGE">$1s</ph>. + </message> + <message name="IDS_DEVTOOLS_ed195e39f2d26aed511b5c86c75935d8" desc=""> + Size Delta + </message> + <message name="IDS_DEVTOOLS_eec806d119a5eddd61e2ccd21bfd9b20" desc=""> + Aggregated total time + </message> + <message name="IDS_DEVTOOLS_ef15fd2f45e6bb5ce57587895ba64f93" desc=""> + Browser + </message> + <message name="IDS_DEVTOOLS_f19dbf2edb3a0bd74b0524d960ff21eb" desc=""> + Load + </message> + <message name="IDS_DEVTOOLS_f3e40bc520cf1f22e4d36d5c5f8d2618" desc=""> + User object reachable from window + </message> + <message name="IDS_DEVTOOLS_f4dab52bcaa99b605451620178a1ee4e" desc=""> + File '<ph name="READER_FILENAME__">$1s</ph>' read error: <ph name="READER_ERROR___MESSAGE">$2s</ph> + </message> + <message name="IDS_DEVTOOLS_f6c0e3a1c3cfabd32ae8d3ae741fcf0a" desc=""> + Comparison + </message> + <message name="IDS_DEVTOOLS_f6ff777632b4b524d2f203c78359eed2" desc=""> + Saving… <ph name="PERCENTVALUE">$1d</ph>%% + </message> + <message name="IDS_DEVTOOLS_fbbe8b507083defdbfe14a341551c77b" desc=""> + CPU profiles show where the execution time is spent in your page's JavaScript functions. + </message> + <message name="IDS_DEVTOOLS_fdbd92f0c6b67291ca954b74885d434e" desc=""> + Profile <ph name="TYPE_NEXTPROFILEUID__">$1d</ph> + </message> + <message name="IDS_DEVTOOLS_ffd4ebcdf9ad139d4cd2c84d853f4f34" desc=""> + Total Size (bytes) + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/protocol_monitor/protocol_monitor_strings.grdp b/third_party/blink/renderer/devtools/front_end/protocol_monitor/protocol_monitor_strings.grdp new file mode 100644 index 0000000..b9ce807 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/protocol_monitor/protocol_monitor_strings.grdp
@@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_02674a4ef33e11c879283629996c8ff8" desc=""> + Direction + </message> + <message name="IDS_DEVTOOLS_15c2d85f1fae22a3c3a0594510a1f611" desc=""> + Request + </message> + <message name="IDS_DEVTOOLS_2448f896f98bcda2db043a999a00e1d2" desc=""> + <ph name="THIS_DATA_COLUMNID_">$1s</ph> ms + </message> + <message name="IDS_DEVTOOLS_5b6cf869265c13af8566f192b4ab3d2a" desc=""> + Documentation + </message> + <message name="IDS_DEVTOOLS_6a0d9eaee314c567fd72fb97ee707a36" desc=""> + Record + </message> + <message name="IDS_DEVTOOLS_a3d5de3eac8bb00ae86fd1a1005f1500" desc=""> + Timestamp + </message> + <message name="IDS_DEVTOOLS_a854885880458e27324853c6f46e28f7" desc=""> + No message selected + </message> + <message name="IDS_DEVTOOLS_c2474d3f42e95aac175f984da6d91cf5" desc=""> + Protocol monitor + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/quick_open/quick_open_strings.grdp b/third_party/blink/renderer/devtools/front_end/quick_open/quick_open_strings.grdp new file mode 100644 index 0000000..a1176471 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/quick_open/quick_open_strings.grdp
@@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_06f884351ae9dbaaca31602b74d0ed4e" desc=""> + Type '?' to see available commands + </message> + <message name="IDS_DEVTOOLS_22b6fe30dec1ae9c09480cce01cd4065" desc=""> + Run command + </message> + <message name="IDS_DEVTOOLS_74540c79e377bea903e1023a46df5574" desc=""> + Open file + </message> + <message name="IDS_DEVTOOLS_8bb9829a676055080c3d4507e0b5f201" desc=""> + No commands found + </message> + <message name="IDS_DEVTOOLS_af9ccba3ec4346e3acf785f9bea514d8" desc=""> + Show <ph name="EXTENSION_TITLE__">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_e576c23d915755d83e2d1f47bd9f6c22" desc=""> + No results found + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/resources/resources_strings.grdp b/third_party/blink/renderer/devtools/front_end/resources/resources_strings.grdp new file mode 100644 index 0000000..55c8211 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/resources/resources_strings.grdp
@@ -0,0 +1,398 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_01abfc750a0c942167651c40d088531d" desc=""> + # + </message> + <message name="IDS_DEVTOOLS_05b2812ab435addb8ae4853ead93f1b3" desc=""> + Received <ph name="NEW_DATE_VERSION_SCRIPTRESPONSETIME_________TOLOCALESTRING__">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_06933067aafd48425d67bcb01bba5cb6" desc=""> + Update + </message> + <message name="IDS_DEVTOOLS_09428a9282bbb3ffcf3caa7826f0bf83" desc=""> + An unexpected error <ph name="SQLERROR_CODE">$1s</ph> occurred. + </message> + <message name="IDS_DEVTOOLS_0d6fa553290eb4bf9eabe203a43b01d9" desc=""> + Application cache + </message> + <message name="IDS_DEVTOOLS_0f558243fbf45f1cd840fff01957f57b" desc=""> + Clients + </message> + <message name="IDS_DEVTOOLS_1351a3eaa0f925dad980e83905bc1230" desc=""> + Worker: <ph name="TARGETINFO_URL">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_136e9c46f48bf8798df663c4e786c3e3" desc=""> + Update on reload + </message> + <message name="IDS_DEVTOOLS_15fa5e18dc110ac96ef35fd19abc78b3" desc=""> + Time Cached + </message> + <message name="IDS_DEVTOOLS_1722d5b7f86af20cbd8d1981f23a15a3" desc=""> + cookies used by frames from + </message> + <message name="IDS_DEVTOOLS_1818d506396d77b3d035f719885c4cd1" desc=""> + focus + </message> + <message name="IDS_DEVTOOLS_1bea0f12b50db07ee7f2265b790417ff" desc=""> + Installability + </message> + <message name="IDS_DEVTOOLS_1fece652e0dde2e00d1a7662f081dd71" desc=""> + The "<ph name="THIS_TABLENAME">$1s</ph>" +table is empty. + </message> + <message name="IDS_DEVTOOLS_22554c2f3f431fa4243965df392b9ea9" desc=""> + AppCache + </message> + <message name="IDS_DEVTOOLS_29104d3ede0231043a4b92a90b9c2873" desc=""> + Some entries may have been modified + </message> + <message name="IDS_DEVTOOLS_2b81bb9b3deebcbfa05edad7a845005a" desc=""> + Frames + </message> + <message name="IDS_DEVTOOLS_2bf0a735c3ff964861a2b55319edd355" desc=""> + Unregister service workers + </message> + <message name="IDS_DEVTOOLS_2e9d8504b07d0bdf4887f27c070cbbb6" desc=""> + autoIncrement + </message> + <message name="IDS_DEVTOOLS_301addf2037879acf2a972b157d2f4a7" desc=""> + Local Files + </message> + <message name="IDS_DEVTOOLS_3472423ee4037c94e20d64b3aea8aa49" desc=""> + <ph name="SCOPEURL">$1s</ph> - deleted + </message> + <message name="IDS_DEVTOOLS_34b6cd75171affba6957e308dcbd92be" desc=""> + Version + </message> + <message name="IDS_DEVTOOLS_368d9ac76af05f714092bc808a426bfc" desc=""> + Background color + </message> + <message name="IDS_DEVTOOLS_37acadd70183e7ed00222ff38248a6ff" desc=""> + <ph name="NUMBER_BYTESTOSTRING_RESPONSE_USAGE_">$1s</ph> used out of <ph name="NUMBER_BYTESTOSTRING_RESPONSE_QUOTA_">$2s</ph> storage quota. + </message> + <message name="IDS_DEVTOOLS_3a771376134eb624f3e1fdd3d92d9f4c" desc=""> + Select a cache entry above to preview + </message> + <message name="IDS_DEVTOOLS_3afd748bcc6315d69cff002ec6c377ed" desc=""> + <ph name="THIS__REGISTRATION_ERRORS_LENGTH">$1s</ph> registration errors + </message> + <message name="IDS_DEVTOOLS_3eab5d12656f2f4462f6594019e77355" desc=""> + Visible columns + </message> + <message name="IDS_DEVTOOLS_3edf8ca26a1ec14dd6e91dd277ae1de6" desc=""> + Origin + </message> + <message name="IDS_DEVTOOLS_458efe6e41ed41835b8d84b28db3f394" desc=""> + Service workers from other origins + </message> + <message name="IDS_DEVTOOLS_45e035baf33a8e403766a606457f8b10" desc=""> + Theme color + </message> + <message name="IDS_DEVTOOLS_4f36f645368158bc46346b8902fc2566" desc=""> + #<ph name="ACTIVE_ID">$1s</ph> activated and is <ph name="ACTIVE_RUNNINGSTATUS">$2s</ph> + </message> + <message name="IDS_DEVTOOLS_50868c2251b0c3b64ca50052891aec4c" desc=""> + Push data + </message> + <message name="IDS_DEVTOOLS_536cf547cb6ecfe32be6ed3ffdabf893" desc=""> + Clear site data + </message> + <message name="IDS_DEVTOOLS_54f664c70c22054ea0d8d26fc3997ce7" desc=""> + Online + </message> + <message name="IDS_DEVTOOLS_55bce575c41275ddaf5fbd1beb7d6018" desc=""> + #<ph name="INSTALLING_ID">$1s</ph> trying to install + </message> + <message name="IDS_DEVTOOLS_579fdc74b6520ab8906ecddf3e62d951" desc=""> + Application Cache + </message> + <message name="IDS_DEVTOOLS_5bb07b23ba5cd47d49a0a030556b21ba" desc=""> + Background Fetch + </message> + <message name="IDS_DEVTOOLS_625bee64c286ac3018d57e87162f44e9" desc=""> + Delete database + </message> + <message name="IDS_DEVTOOLS_626e8008b253bc4fbef9dca0a3f63903" desc=""> + Instance ID + </message> + <message name="IDS_DEVTOOLS_65ebb2ea77ddbe405def1ad1d01e2e7b" desc=""> + Bypass the service worker and load resources from the network + </message> + <message name="IDS_DEVTOOLS_6670d47e57b4fe982554519effc771c5" desc=""> + Object stores + </message> + <message name="IDS_DEVTOOLS_673eb027e9c056f57140322807351dd5" desc=""> + unique + </message> + <message name="IDS_DEVTOOLS_6827a85b76e967f6a129e08f9272e76d" desc=""> + Local Storage + </message> + <message name="IDS_DEVTOOLS_6c202452e44c42e323204da2a3a3c24a" desc=""> + File System + </message> + <message name="IDS_DEVTOOLS_6e72748dc2f2224dfabb374ca0cc988f" desc=""> + #<ph name="REDUNDANT_ID">$1s</ph> is redundant + </message> + <message name="IDS_DEVTOOLS_76c18f2b1e4155961e10434e3d83317f" desc=""> + Key generator value: <ph name="STRING_METADATA_KEYGENERATORVALUE_">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_76c3e002d3c052bd6a909366a8dc3845" desc=""> + Manifest + </message> + <message name="IDS_DEVTOOLS_795a813f20a4d4b04f85ddb86287fce4" desc=""> + Storage quota is limited in Incognito mode + </message> + <message name="IDS_DEVTOOLS_798a0aef3a97a3eab63d88a0b6c07341" desc=""> + SW Scope + </message> + <message name="IDS_DEVTOOLS_7a06b1cc41f027f75bc7be8ee937c344" desc=""> + Database no longer has expected version. + </message> + <message name="IDS_DEVTOOLS_7adc295d89feec026fbcee16448c31d8" desc=""> + <ph name="UNREACHABLEMAINORIGIN">$1s</ph> (failed to load) + </message> + <message name="IDS_DEVTOOLS_7d52bfc51222e4122623057310cba1ce" desc=""> + Show previous page + </message> + <message name="IDS_DEVTOOLS_7e91f7be5e9ff7a50a44d4a7f21afb90" desc=""> + Start URL + </message> + <message name="IDS_DEVTOOLS_7ed01b26177166f3627e29da31bc7e28" desc=""> + No Application Cache information available. + </message> + <message name="IDS_DEVTOOLS_83b33e9633245178cb76ecb91dd424d8" desc=""> + Select a value to preview + </message> + <message name="IDS_DEVTOOLS_86befdf33863a849060cf9f6d2425cdb" desc=""> + Security origin + </message> + <message name="IDS_DEVTOOLS_87e059dc2492bd5041581f05daef12f7" desc=""> + Filter by Path + </message> + <message name="IDS_DEVTOOLS_886b9bffdebad3a988a8da87b1affa2d" desc=""> + Filter service worker + </message> + <message name="IDS_DEVTOOLS_897356954c2cd3d41b221e3f24f99bba" desc=""> + Key + </message> + <message name="IDS_DEVTOOLS_8c4aa541ee911e8d80451ef8cc304806" desc=""> + Storage + </message> + <message name="IDS_DEVTOOLS_8f67973007158337346584551b093be8" desc=""> + Icons + </message> + <message name="IDS_DEVTOOLS_90e4c7584668933aebe8cf1cbccfe82d" desc=""> + Please confirm delete of "<ph name="THIS__DATABASE_DATABASEID_NAME">$1s</ph>" database. + </message> + <message name="IDS_DEVTOOLS_9122ec25094d00855f48a500241c6008" desc=""> + Service Workers + </message> + <message name="IDS_DEVTOOLS_9350cbb84e8ab827898a783d8f724951" desc=""> + inspect + </message> + <message name="IDS_DEVTOOLS_94aa6cfa461998abe42d53963f1344c3" desc=""> + An error occurred trying to +read the "<ph name="THIS_TABLENAME">$1s</ph>" table. + </message> + <message name="IDS_DEVTOOLS_98fc9226c3fe878e39cd048fbd1c3692" desc=""> + Short name + </message> + <message name="IDS_DEVTOOLS_9999106349673567ecaf1c32c07301a5" desc=""> + #<ph name="WAITING_ID">$1s</ph> waiting to activate + </message> + <message name="IDS_DEVTOOLS_9b2a7456cec10d8b5ab8ce656598320b" desc=""> + Key path: + </message> + <message name="IDS_DEVTOOLS_9b790a1c94937c437f9801d3c970efa7" desc=""> + (empty) + </message> + <message name="IDS_DEVTOOLS_9c6a9d9f033001a9b3104984d319563b" desc=""> + Push + </message> + <message name="IDS_DEVTOOLS_9d4a8f2dfe3c62f3ce3011035d28fb66" desc=""> + Unregister + </message> + <message name="IDS_DEVTOOLS_9dce9dd0f39a17c2e029174f5bc86ef9" desc=""> + Background Sync + </message> + <message name="IDS_DEVTOOLS_9ff9f5649294f7200b671d6389d17d9a" desc=""> + multiEntry + </message> + <message name="IDS_DEVTOOLS_a049ac2b4afe0fb6e78656082858067e" desc=""> + Storage Usage + </message> + <message name="IDS_DEVTOOLS_a274f4d4670213a9045ce258c6c56b80" desc=""> + Notifications + </message> + <message name="IDS_DEVTOOLS_a4ecfc70574394990cf17bd83df499f7" desc=""> + Event + </message> + <message name="IDS_DEVTOOLS_a7d5ee58baead2f3bc229d3d9c047875" desc=""> + Unregister service worker + </message> + <message name="IDS_DEVTOOLS_a89edb1e05005c844b684d1eb0de111a" desc=""> + Cache Storage + </message> + <message name="IDS_DEVTOOLS_ab0cf104f39708eabd07b8cb67e149ba" desc=""> + Cache + </message> + <message name="IDS_DEVTOOLS_ab6ee23f23d1d5f342588e64297efc1c" desc=""> + Session Storage + </message> + <message name="IDS_DEVTOOLS_acb91a6bfd0644c5b90280f9ebf38774" desc=""> + Response-Type + </message> + <message name="IDS_DEVTOOLS_ad2669a90d3964bc67a1a34152122845" desc=""> + Matching entries: <ph name="THIS__RETURNCOUNT">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_ae262bf758227f7e319ba799a861681a" desc=""> + Local and session storage + </message> + <message name="IDS_DEVTOOLS_b275ec0eb3bbc2f5ab8988fe15b47817" desc=""> + Errors and warnings + </message> + <message name="IDS_DEVTOOLS_b5dc9b0e6beecb1e80f6f1b5b3050f12" desc=""> + Application panel + </message> + <message name="IDS_DEVTOOLS_b66b856833f34a841b51c7207dbc601f" desc=""> + IndexedDB + </message> + <message name="IDS_DEVTOOLS_b704442a84076f1139cd70604553e8dc" desc=""> + Clear object store + </message> + <message name="IDS_DEVTOOLS_b9987a246a537f4fe86f1f2e3d10dbdb" desc=""> + Display + </message> + <message name="IDS_DEVTOOLS_ba8d2e1eca2bf52ab3cd0202d4d04c07" desc=""> + Test push message from DevTools. + </message> + <message name="IDS_DEVTOOLS_bb8839cf9d324a22591ff426c28c5345" desc=""> + Show next page + </message> + <message name="IDS_DEVTOOLS_be8545ae7ab0276e15898aae7acfbd7a" desc=""> + Resource + </message> + <message name="IDS_DEVTOOLS_bebc9b50966d8d2bd1913a3c25b707d4" desc=""> + Data may be stale + </message> + <message name="IDS_DEVTOOLS_bec9bd97f1cda22686854c090b5133fc" desc=""> + Save events + </message> + <message name="IDS_DEVTOOLS_c13af79d63bfcb3f07bc3810418c99f8" desc=""> + Delete Selected + </message> + <message name="IDS_DEVTOOLS_c1ea3facd2946b59df718d8dd2737cfa" desc=""> + Background Services + </message> + <message name="IDS_DEVTOOLS_c64518704ce0c0d5501a45763f464276" desc=""> + Usage + </message> + <message name="IDS_DEVTOOLS_c6661c86882ff82da47747b673907fa2" desc=""> + No manifest detected + </message> + <message name="IDS_DEVTOOLS_c76eb02deaa41ffd58d22d08c213fea5" desc=""> + Select an entry to view metadata + </message> + <message name="IDS_DEVTOOLS_c7bc3fddddb62d5b656adc30cea77a55" desc=""> + Presentation + </message> + <message name="IDS_DEVTOOLS_c9a5ab3cec5c1de816c0f8ea8d7edfed" desc=""> + Stop recording events + </message> + <message name="IDS_DEVTOOLS_c9c5c65fb4af9cf90eb99b3b84424189" desc=""> + Identity + </message> + <message name="IDS_DEVTOOLS_cc0041e1d664fd87ad1cfaae4265893f" desc=""> + Bypass for network + </message> + <message name="IDS_DEVTOOLS_cc8763e24276418641ca188290e3334c" desc=""> + On page reload, force the service worker to update, and activate it + </message> + <message name="IDS_DEVTOOLS_ccdc0553283bddb674e37e272a9832f0" desc=""> + Clearing... + </message> + <message name="IDS_DEVTOOLS_cd461eb091b5b58a6fe5a1b5edba4c5f" desc=""> + Refresh Caches + </message> + <message name="IDS_DEVTOOLS_ce0540adc848ff5957d4d857984592d1" desc=""> + Cache storage + </message> + <message name="IDS_DEVTOOLS_ce9d3c5ae4d74bd1e8d01732e264e36b" desc=""> + No metadata for this event + </message> + <message name="IDS_DEVTOOLS_cfde4f71aaac6d02831a661f4f9990f1" desc=""> + App Manifest + </message> + <message name="IDS_DEVTOOLS_d3b206d196cd6be3a2764c1fb90b200f" desc=""> + Delete selected + </message> + <message name="IDS_DEVTOOLS_d4f61ad886e0b169b0394d97bb1a649a" desc=""> + Recording <ph name="RESOURCES_BACKGROUNDSERVICEVIEW_GETUISTRING_THIS__SERVICENAME_">$1s</ph> activity... + </message> + <message name="IDS_DEVTOOLS_d6f875d9f87efbee1a96b8c4f5784d47" desc=""> + Primary key + </message> + <message name="IDS_DEVTOOLS_d892ca11530be1235ec05eb368ecaf37" desc=""> + Start from key + </message> + <message name="IDS_DEVTOOLS_d8e87c0927539672f54462c837be0b7f" desc=""> + Sync + </message> + <message name="IDS_DEVTOOLS_da131b6bd53f501c1323af4b198740d2" desc=""> + Push Messaging + </message> + <message name="IDS_DEVTOOLS_dc105ac52c237f9f09c74b0767f64f74" desc=""> + Content-Type + </message> + <message name="IDS_DEVTOOLS_dc5f1eac93c7e0c1f63f360b24fd8489" desc=""> + Refresh database + </message> + <message name="IDS_DEVTOOLS_dc87ca61695d643744b53bca9bf3f1d5" desc=""> + Total entries: <ph name="STRING_METADATA_ENTRIESCOUNT_">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_ddcf50c29294d4414f3f7c1bbc892cb5" desc=""> + Resources + </message> + <message name="IDS_DEVTOOLS_e00a7ac13697ba51e098449fd644935b" desc=""> + Show events from other domains + </message> + <message name="IDS_DEVTOOLS_e307db07b3975fef922a80d07455ee5e" desc=""> + Database + </message> + <message name="IDS_DEVTOOLS_e44ec1cd1aa0128f893c1c815ea1abe0" desc=""> + Click the record button <ph name="UI_CREATEINLINEBUTTON_LANDINGRECORDBUTTON_">$1s</ph> or hit <ph name="RECORDKEY">$2s</ph> to start recording. + </message> + <message name="IDS_DEVTOOLS_e498749f3c42246d50b15c81c101d988" desc=""> + Application + </message> + <message name="IDS_DEVTOOLS_e60593abb5603af48307343eb862d86a" desc=""> + DOM Storage + </message> + <message name="IDS_DEVTOOLS_e918a12b0b4a962aff8b7119643af250" desc=""> + skipWaiting + </message> + <message name="IDS_DEVTOOLS_ea2b2676c28c0db26d39331a336c6b92" desc=""> + start + </message> + <message name="IDS_DEVTOOLS_ec1e074d56484165315c26a9baebaebd" desc=""> + Web SQL + </message> + <message name="IDS_DEVTOOLS_ec3c33fb128aab90f46c922f8f7098f1" desc=""> + Start recording events + </message> + <message name="IDS_DEVTOOLS_ed1f65c89bd76342be87bec8edd63904" desc=""> + Refresh IndexedDB + </message> + <message name="IDS_DEVTOOLS_eeb6ddeed2e08678ebc14eb39c8340bf" desc=""> + IDB + </message> + <message name="IDS_DEVTOOLS_ef34ee8b3523f523efcf74d28fab2b47" desc=""> + Sync tag + </message> + <message name="IDS_DEVTOOLS_ef399b2d446bb37b7c32ad2cc1b6045b" desc=""> + stop + </message> + <message name="IDS_DEVTOOLS_f31bbdd1b3e85bccd652680e16935819" desc=""> + Source + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/screencast/screencast_strings.grdp b/third_party/blink/renderer/devtools/front_end/screencast/screencast_strings.grdp new file mode 100644 index 0000000..6b5de3a --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/screencast/screencast_strings.grdp
@@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_30b6c2858b9a03c8518c8804bb96067c" desc=""> + Profiling in progress + </message> + <message name="IDS_DEVTOOLS_e2ed1dadec9e90b7108be8256808a5c0" desc=""> + Toggle screencast + </message> + <message name="IDS_DEVTOOLS_f775403b2922abfa05ae76f922fcacf3" desc=""> + The tab is inactive + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/sdk/sdk_strings.grdp b/third_party/blink/renderer/devtools/front_end/sdk/sdk_strings.grdp new file mode 100644 index 0000000..42af092 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/sdk/sdk_strings.grdp
@@ -0,0 +1,306 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_07553a11db31a4433684be32cc4716e3" desc=""> + Cross-Origin Read Blocking (CORB) blocked cross-origin response <ph name="NETWORKREQUEST_URL__">$1s</ph> with MIME type <ph name="NETWORKREQUEST_MIMETYPE">$2s</ph>. See https://www.chromestatus.com/feature/5629709824032768 for more details. + </message> + <message name="IDS_DEVTOOLS_07ba1c48fc0b478df5462700f993fa5e" desc=""> + <ph name="NETWORKREQUEST_RESOURCETYPE___TITLE__">$1s</ph> failed loading: <ph name="NETWORKREQUEST_REQUESTMETHOD">$2s</ph> "<ph name="NETWORKREQUEST_URL__">$3s</ph>". + </message> + <message name="IDS_DEVTOOLS_09cdd6a7321c64bae05b8cca859f1461" desc=""> + Enable cache + </message> + <message name="IDS_DEVTOOLS_0fe1f9158e2f164da1332501f9e65702" desc=""> + Navigated to <ph name="EVENT_DATA_URL">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_1023bf87beb1d2947824df00fa0898ad" desc=""> + Disable async stack traces + </message> + <message name="IDS_DEVTOOLS_150fa516787b5e5d1d2723c84574dbee" desc=""> + HTTP-Based Public Key Pinning is deprecated. Chrome 69 and later will ignore HPKP response headers. (Host: <ph name="PARSED_HOST">$1s</ph>) + </message> + <message name="IDS_DEVTOOLS_185bf49541541933dc3fd1fb89d3fea3" desc=""> + Enable custom formatters + </message> + <message name="IDS_DEVTOOLS_1985576209a186984f171efd81e91e3d" desc=""> + <anonymous> + </message> + <message name="IDS_DEVTOOLS_21070fd87b02611a5426d726a70a5502" desc=""> + No value found for parameter "<ph name="PARAMNAME">$1s</ph>". + </message> + <message name="IDS_DEVTOOLS_212af9ab36fa426a9e52bc1ebfd8665b" desc=""> + Drag / drop + </message> + <message name="IDS_DEVTOOLS_23e5a7b7976e412ece233ceaf8257bc2" desc=""> + Clipboard + </message> + <message name="IDS_DEVTOOLS_23e8e5daea7e9dc939ae4298a6f74e36" desc=""> + ServerTiming: <ph name="MSG">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_28e486be4b3bad598b6e9eaa34ebec76" desc=""> + Set-Cookie header is ignored in response from url: <ph name="RESPONSE_URL">$1s</ph>. Cookie length should be less than or equal to 4096 characters. + </message> + <message name="IDS_DEVTOOLS_2973958e77629e3a167a1a4c60dd5c5f" desc=""> + Slow 3G + </message> + <message name="IDS_DEVTOOLS_3034e08ec0b14678ddb50284eef02ee4" desc=""> + Do not preserve log upon navigation + </message> + <message name="IDS_DEVTOOLS_328d7fa69bbeeeefd8b3db6e1f06a17b" desc=""> + With Block + </message> + <message name="IDS_DEVTOOLS_3437f1aa3e12219221092a45e62c9d4f" desc=""> + Profile '<ph name="DATA_TITLE">$1s</ph>' finished. + </message> + <message name="IDS_DEVTOOLS_365e0172a2e97b0a26274c5bd2e4bad0" desc=""> + Script Blocked by Content Security Policy + </message> + <message name="IDS_DEVTOOLS_38fe155e13d77298cfd5688c3378fa85" desc=""> + Emulate CSS screen media type + </message> + <message name="IDS_DEVTOOLS_3b563524fdb17b4a86590470d40bef74" desc=""> + Media + </message> + <message name="IDS_DEVTOOLS_3d9320c6e796b65a6c91fcd64e27fa88" desc=""> + Hide frames per second (FPS) meter + </message> + <message name="IDS_DEVTOOLS_3ff9f750075f426831f71818a8f4ff12" desc=""> + Request was blocked by DevTools: "<ph name="NETWORKREQUEST_URL__">$1s</ph>". + </message> + <message name="IDS_DEVTOOLS_40dba446b661ae69dea3a8e026f76dfd" desc=""> + Hide paint flashing rectangles + </message> + <message name="IDS_DEVTOOLS_4249b3308a0ed3e1e90e0a91ca11cf21" desc=""> + WebGL Error Fired + </message> + <message name="IDS_DEVTOOLS_4636cded1f8a4578c9e8e7f2fd9cfdee" desc=""> + (binary) + </message> + <message name="IDS_DEVTOOLS_4a2c6d480468877dd33d9a5bae54b549" desc=""> + WebGL Warning Fired + </message> + <message name="IDS_DEVTOOLS_4bfca2e69ec73893d36ebcdcce35cf36" desc=""> + Suspend AudioContext + </message> + <message name="IDS_DEVTOOLS_4cc00b9253c692417d3b0765d5ae5e79" desc=""> + Unable to parse "<ph name="PARAMNAME">$1s</ph>" value "<ph name="PARAMVALUE">$2s</ph>". + </message> + <message name="IDS_DEVTOOLS_4cc6684df7b4a92b1dec6fce3264fac8" desc=""> + Global + </message> + <message name="IDS_DEVTOOLS_509820290d57f333403f490dde7316f4" desc=""> + Local + </message> + <message name="IDS_DEVTOOLS_509a7f125ba127d220887938738af707" desc=""> + Failed to save to temp variable. + </message> + <message name="IDS_DEVTOOLS_52da3e7fcf6abefc2a8807df4b759ef8" desc=""> + setInterval fired + </message> + <message name="IDS_DEVTOOLS_599eba19aa93a929cb8589f148b8a6c4" desc=""> + screen + </message> + <message name="IDS_DEVTOOLS_5c63ad6312d0451b3d1012e5ea8fd08f" desc=""> + Emulate CSS print media type + </message> + <message name="IDS_DEVTOOLS_5fe9d4f417e5f34919b0b6e5f0431ec1" desc=""> + Hide hit-test borders + </message> + <message name="IDS_DEVTOOLS_61cf8510205077b6f5491d38cd44c0f7" desc=""> + Pointer + </message> + <message name="IDS_DEVTOOLS_62efb9ec331e364b96efe68c8b03ca20" desc=""> + Worker + </message> + <message name="IDS_DEVTOOLS_62fce3f916fe47f75c391fd5e4fc3eca" desc=""> + Consider disabling <ph name="COMMON_UISTRING__CHROME_DATA_SAVER__">$1s</ph> while debugging. For more info see: <ph name="_HTTPS___SUPPORT_GOOGLE_COM_CHROME__P_DATASAVER_">$2s</ph> + </message> + <message name="IDS_DEVTOOLS_6617a779f50f7afb7949c7ea3ad52b28" desc=""> + Show hit-test borders + </message> + <message name="IDS_DEVTOOLS_6948a469c79f7dd5426e4f291cba3db1" desc=""> + Chrome Data Saver + </message> + <message name="IDS_DEVTOOLS_6ce4d85a628a88bbdb3ac24a8e5a9c2e" desc=""> + Keyboard + </message> + <message name="IDS_DEVTOOLS_6e2e8696272b40b7a9745c998a39b177" desc=""> + Close AudioContext + </message> + <message name="IDS_DEVTOOLS_6ea5359e01a41842884943125518289b" desc=""> + Canvas + </message> + <message name="IDS_DEVTOOLS_6fdb8f0232e380cf106312e7b880d8d2" desc=""> + Preserve log upon navigation + </message> + <message name="IDS_DEVTOOLS_7121afd196f5c52bef488d5a0f4c097b" desc=""> + Script First Statement + </message> + <message name="IDS_DEVTOOLS_794f64c7f20487f6e13679201deeab3d" desc=""> + Picture-in-Picture + </message> + <message name="IDS_DEVTOOLS_7c2bc755363ab11a1611bfa369654ff8" desc=""> + Show frames per second (FPS) meter + </message> + <message name="IDS_DEVTOOLS_81961fe251f4d1cb4df131561dedf319" desc=""> + Hide layer borders + </message> + <message name="IDS_DEVTOOLS_83f2229658949472d34f78e19475fcdd" desc=""> + Show layer borders + </message> + <message name="IDS_DEVTOOLS_9028784c589c0c809700c7fbc66a5d96" desc=""> + Resource interpreted as <ph name="NETWORKREQUEST_RESOURCETYPE___TITLE__">$1s</ph> but transferred with MIME type <ph name="NETWORKREQUEST_MIMETYPE">$2s</ph>: "<ph name="NETWORKREQUEST_URL__">$3s</ph>". + </message> + <message name="IDS_DEVTOOLS_90da6f38945a1c7e7ba11e3adcbe6919" desc=""> + Pause on exceptions + </message> + <message name="IDS_DEVTOOLS_9108ae673b7efa9620aec771edc9d4de" desc=""> + setTimeout fired + </message> + <message name="IDS_DEVTOOLS_930c85a96d7227c515891c4f86a17c30" desc=""> + Disable JavaScript + </message> + <message name="IDS_DEVTOOLS_93dee6366d66361f36985cf5c88346aa" desc=""> + Create AudioContext + </message> + <message name="IDS_DEVTOOLS_95bbad55f11c237ed89546e748093ba7" desc=""> + Request Animation Frame + </message> + <message name="IDS_DEVTOOLS_96d008db67fc0b5551a926842bbb6a71" desc=""> + Notification + </message> + <message name="IDS_DEVTOOLS_9850063efe194af1c63d2aa61ef94c62" desc=""> + Create canvas context + </message> + <message name="IDS_DEVTOOLS_9dd7b9f5cc1c19a830f153c3e8f1ad89" desc=""> + Fast 3G + </message> + <message name="IDS_DEVTOOLS_9f7d4cb9fefed9daf0e9e4aad0620497" desc=""> + Do not highlight ad frames + </message> + <message name="IDS_DEVTOOLS_a155bce1e541d9234013102c2e613941" desc=""> + ServiceWorkerCacheAgent error deleting cache entry <ph name="CACHE_TOSTRING__">$1s</ph> in cache: <ph name="RESPONSE_PROTOCOL_ERROR_">$2s</ph> + </message> + <message name="IDS_DEVTOOLS_a1595abbb4c3a326636dd178757cd6c1" desc=""> + Control + </message> + <message name="IDS_DEVTOOLS_a720fc15eb9ec85751969e8615ace9e1" desc=""> + Duplicate parameter "<ph name="PARAMNAME">$1s</ph>" ignored. + </message> + <message name="IDS_DEVTOOLS_ac4aac1ba23d844f4976e9fcd1fd4a61" desc=""> + WebGL Error Fired (<ph name="ERRORNAME">$1s</ph>) + </message> + <message name="IDS_DEVTOOLS_af4bb376939e77df0e7c2332b837a866" desc=""> + Closure + </message> + <message name="IDS_DEVTOOLS_b28354b543375bfa94dabaeda722927f" desc=""> + top + </message> + <message name="IDS_DEVTOOLS_b43356cdb7bdec437e117bb1ed5625bc" desc=""> + Capture async stack traces + </message> + <message name="IDS_DEVTOOLS_b50ec339cd40d39d5ff4ca56379e61c6" desc=""> + Paused in debugger + </message> + <message name="IDS_DEVTOOLS_b600e0facf21b7d4a9a769a60b236ba1" desc=""> + Enable JavaScript + </message> + <message name="IDS_DEVTOOLS_ba50636875d999db0c9218b48b23027d" desc=""> + Do not capture async stack traces + </message> + <message name="IDS_DEVTOOLS_ba5b676ccf658f863ef2e3df082ee262" desc=""> + Animation Frame Fired + </message> + <message name="IDS_DEVTOOLS_bc955333ff170762be4971a8fde558cf" desc=""> + WebAudio + </message> + <message name="IDS_DEVTOOLS_c432f4e5fdec5760a2f06b38f646168e" desc=""> + Profile '<ph name="DATA_TITLE">$1s</ph>' started. + </message> + <message name="IDS_DEVTOOLS_c5d59568835d0760e318829b800ee06d" desc=""> + Catch + </message> + <message name="IDS_DEVTOOLS_c64d5c0d5233c7d6e85a41c6dd3c3a3f" desc=""> + Resume AudioContext + </message> + <message name="IDS_DEVTOOLS_c89686a387d2b12b3c729ce35a0bcb5b" desc=""> + Window + </message> + <message name="IDS_DEVTOOLS_c9ad95228aa735bdda1aebf38da022af" desc=""> + Parse + </message> + <message name="IDS_DEVTOOLS_cedab6b9e4e794e93bba797e8aff218a" desc=""> + <ph name="NETWORKREQUEST_RESOURCETYPE___TITLE__">$1s</ph> finished loading: <ph name="NETWORKREQUEST_REQUESTMETHOD">$2s</ph> "<ph name="NETWORKREQUEST_URL__">$3s</ph>". + </message> + <message name="IDS_DEVTOOLS_d24a22fef757966373800aa9795458dc" desc=""> + ? [sm] + </message> + <message name="IDS_DEVTOOLS_d31827f0a164d52b636bb1f71ca4a351" desc=""> + Cancel Animation Frame + </message> + <message name="IDS_DEVTOOLS_d4fad802fc7bf0248d34c685533bd56f" desc=""> + Disable request blocking + </message> + <message name="IDS_DEVTOOLS_d6b6b668dbca9d4fe774bb654226ebe3" desc=""> + Animation + </message> + <message name="IDS_DEVTOOLS_dcd9c13c4f8ae68ea7ae92edf9191264" desc=""> + Deprecated syntax found. Please use: <name>;dur=<duration>;desc=<description> + </message> + <message name="IDS_DEVTOOLS_df9f4292c1d025cbada13b25744d34e5" desc=""> + Do not emulate CSS media type + </message> + <message name="IDS_DEVTOOLS_e1e4c8c9ccd9fc39c391da4bcd093fb2" desc=""> + Block + </message> + <message name="IDS_DEVTOOLS_e2b60c37530e144372a7943df0f6017d" desc=""> + <iframe> + </message> + <message name="IDS_DEVTOOLS_e402c138065e7eece783dc30c6079192" desc=""> + XHR + </message> + <message name="IDS_DEVTOOLS_e485c975c1d6c17d9dfd81128b83f63a" desc=""> + Set innerHTML + </message> + <message name="IDS_DEVTOOLS_e55f75a29310d7b60f7ac1d390c8ae42" desc=""> + Module + </message> + <message name="IDS_DEVTOOLS_e69d85cd1acdf030f0cede48b61d7720" desc=""> + Hide scroll performance bottlenecks + </message> + <message name="IDS_DEVTOOLS_edb020d2175281d94054136e09a3e132" desc=""> + Do not pause on exceptions + </message> + <message name="IDS_DEVTOOLS_efa547f7d0b9924fdc7b301838c99fad" desc=""> + No emulation + </message> + <message name="IDS_DEVTOOLS_efb4777327e6f704fb1519c1882f93ec" desc=""> + Timer + </message> + <message name="IDS_DEVTOOLS_eff8d530f562a22a45fbf1ee83299353" desc=""> + Show scroll performance bottlenecks + </message> + <message name="IDS_DEVTOOLS_f107ac919ab14339cdb22cd00fccd215" desc=""> + Show paint flashing rectangles + </message> + <message name="IDS_DEVTOOLS_f2a47c6809d88e175dade0ef7b16aa13" desc=""> + Mouse + </message> + <message name="IDS_DEVTOOLS_f6137609f4decf877ede5bd3a3125629" desc=""> + DevTools: CPU profile parser is fixing <ph name="COUNT">$1s</ph> missing samples. + </message> + <message name="IDS_DEVTOOLS_f7531e2d0ea27233ce00b5f01c5bf335" desc=""> + print + </message> + <message name="IDS_DEVTOOLS_f9778c8e7464e4bb037ec2463879588f" desc=""> + DOM Mutation + </message> + <message name="IDS_DEVTOOLS_f99d691018d8f37dda14a9cd29c1d1ee" desc=""> + Script blocked due to Content Security Policy directive: <ph name="AUXDATA__DIRECTIVETEXT__">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_fa79cdac06c8d2166fd5cda17ccbc0ce" desc=""> + Extraneous trailing characters. + </message> + <message name="IDS_DEVTOOLS_ff92304ed0236a5f972fd90e9b47fae4" desc=""> + Unrecognized parameter "<ph name="PARAMNAME">$1s</ph>". + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/search/search_strings.grdp b/third_party/blink/renderer/devtools/front_end/search/search_strings.grdp new file mode 100644 index 0000000..ef34ad6 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/search/search_strings.grdp
@@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_2f04f3e6eee339eeb0ddb6c39606424d" desc=""> + Use Regular Expression + </message> + <message name="IDS_DEVTOOLS_44b4e531d5b06deb40b631e4aa3c7e36" desc=""> + Show <ph name="MATCHESLEFTCOUNT">$1d</ph> more + </message> + <message name="IDS_DEVTOOLS_617778f774bc264b169dde60f223285f" desc=""> + Indexing… + </message> + <message name="IDS_DEVTOOLS_9fc52b55092ab8a92303e86722013b36" desc=""> + Search interrupted. + </message> + <message name="IDS_DEVTOOLS_ab29eba562fe20ebb94fed224813c109" desc=""> + Search finished. + </message> + <message name="IDS_DEVTOOLS_b20aa447d2e9b2d5065ac0ac4ed7bcc2" desc=""> + Found <ph name="THIS__SEARCHMATCHESCOUNT">$1d</ph> matching lines in <ph name="THIS__NONEMPTYSEARCHRESULTSCOUNT">$2d</ph> files. + </message> + <message name="IDS_DEVTOOLS_c440d4f6fc7dd9239ada58277b900249" desc=""> + Found <ph name="THIS__SEARCHMATCHESCOUNT">$1d</ph> matching lines in 1 file. + </message> + <message name="IDS_DEVTOOLS_c949475bc69a57c419ac976fe8870652" desc=""> + Match Case + </message> + <message name="IDS_DEVTOOLS_d1e64da6074bf343a0a6bd2cd6515189" desc=""> + Indexing interrupted. + </message> + <message name="IDS_DEVTOOLS_f4c8ff50c8f0b548e3297aeaf3b304b4" desc=""> + Found 1 matching line in 1 file. + </message> + <message name="IDS_DEVTOOLS_f7e2fe044011a710d68a3c4e165ef7bf" desc=""> + No matches found. + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/security/security_strings.grdp b/third_party/blink/renderer/devtools/front_end/security/security_strings.grdp new file mode 100644 index 0000000..46bc61e --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/security/security_strings.grdp
@@ -0,0 +1,144 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_02e168aecffdbc00d48c952eba310b02" desc=""> + Main origin + </message> + <message name="IDS_DEVTOOLS_0f22d804f6720086f2ffe6c4e9d7d3fd" desc=""> + Unknown / canceled + </message> + <message name="IDS_DEVTOOLS_1238f21584e6dc18c44c4d96fc9bef13" desc=""> + Issued at + </message> + <message name="IDS_DEVTOOLS_1dc6f97ea55d39e862637dcb0298a3ff" desc=""> + Open full certificate details + </message> + <message name="IDS_DEVTOOLS_22b29ad1d12365f80273c5b173b2ac6b" desc=""> + Not secure (broken) + </message> + <message name="IDS_DEVTOOLS_22fcd09f19102f883a8e337ea1624b20" desc=""> + Log ID + </message> + <message name="IDS_DEVTOOLS_278dded33791cce4bb389fdf6a516856" desc=""> + Your connection to this origin is not secure. + </message> + <message name="IDS_DEVTOOLS_2ad7083a628c9593e4c538deab838d77" desc=""> + This page is not secure (broken HTTPS). + </message> + <message name="IDS_DEVTOOLS_2fae32629d4ef4fc6341f1751b405e45" desc=""> + Security + </message> + <message name="IDS_DEVTOOLS_36cc7ab088ee5ea657c3d1e47016901b" desc=""> + The security details above are from the first inspected response. + </message> + <message name="IDS_DEVTOOLS_3b878279a04dc47d60932cb294d96259" desc=""> + Overview + </message> + <message name="IDS_DEVTOOLS_3bc80b82af3a60973d57e8ff762b87eb" desc=""> + Your page requested non-secure resources that were blocked. + </message> + <message name="IDS_DEVTOOLS_4212f531450435498e750858b23cc739" desc=""> + No security details are available for this origin. + </message> + <message name="IDS_DEVTOOLS_45c618734371071e7c335c06c1d2852d" desc=""> + This page is secure (valid HTTPS). + </message> + <message name="IDS_DEVTOOLS_46b0ab970c4705a3a388a6d86aa831c2" desc=""> + Main origin (secure) + </message> + <message name="IDS_DEVTOOLS_472acd9e75af12adb6421b3eedc8f975" desc=""> + Reload the page to record requests for HTTP resources. + </message> + <message name="IDS_DEVTOOLS_4b1f76eea8c3d555f4fe2a9efe4513a5" desc=""> + SCT + </message> + <message name="IDS_DEVTOOLS_4e6509e12a8c0ebf2b39fd7e158d48c2" desc=""> + This origin is a non-HTTPS secure origin. + </message> + <message name="IDS_DEVTOOLS_55c917250d323e0d8572a1c3673bc80d" desc=""> + The security of this page is unknown. + </message> + <message name="IDS_DEVTOOLS_5a70e1c7b4fa71a69851e44cda14dff7" desc=""> + Secure origins + </message> + <message name="IDS_DEVTOOLS_628b50e6d53ec0d0e9b62971872e6b8b" desc=""> + Show more (<ph name="SANLIST_LENGTH">$1d</ph> total) + </message> + <message name="IDS_DEVTOOLS_62a0282d39568be094470486eaf70c4f" desc=""> + SAN + </message> + <message name="IDS_DEVTOOLS_6792733f0a02ad04a0a660c9a0bcfad1" desc=""> + Main origin (non-secure) + </message> + <message name="IDS_DEVTOOLS_6f5168da8d36a44f8c196c8aa3ff3e40" desc=""> + Certificate Transparency + </message> + <message name="IDS_DEVTOOLS_71d09158378f6d5172ac991d5f26a1c1" desc=""> + Log name + </message> + <message name="IDS_DEVTOOLS_77ee7df08008633ded94db7e019a2bcc" desc=""> + Non-secure origins + </message> + <message name="IDS_DEVTOOLS_7d5b05ab7e3853d483726a5b1a94c475" desc=""> + Signature algorithm + </message> + <message name="IDS_DEVTOOLS_7e025c9c2b87ac6d946747ea156b3f37" desc=""> + Blocked mixed content + </message> + <message name="IDS_DEVTOOLS_918fa99baa381e2902ad2185ea659228" desc=""> + Hash algorithm + </message> + <message name="IDS_DEVTOOLS_9859694a15c021aa640bfda6b3e4423f" desc=""> + Key exchange group + </message> + <message name="IDS_DEVTOOLS_98bce0cf672e732251f6f4327749ed18" desc=""> + (n/a) + </message> + <message name="IDS_DEVTOOLS_9b30e34fce49de00a7fefd64aa5371fd" desc=""> + This page is not secure. + </message> + <message name="IDS_DEVTOOLS_9c5ad7ee1f9630b92891a478327e670f" desc=""> + View <ph name="FILTERREQUESTCOUNT">$1d</ph> requests in Network Panel + </message> + <message name="IDS_DEVTOOLS_a10edd2a3893a9ba446fb26e7c27556a" desc=""> + This request complies with Chrome's Certificate Transparency policy. + </message> + <message name="IDS_DEVTOOLS_a2b16c6b3db371738d0e5c3f3ba2b54d" desc=""> + This response was loaded from cache. Some security details might be missing. + </message> + <message name="IDS_DEVTOOLS_a574d935216052d2d6ee69b743cd4147" desc=""> + Show full details + </message> + <message name="IDS_DEVTOOLS_a5f643359ba723c6f26cc3a3cfc14874" desc=""> + No security information + </message> + <message name="IDS_DEVTOOLS_a7ec70e97f31322dc2e9aaa805b102ab" desc=""> + View <ph name="FILTERREQUESTCOUNT">$1d</ph> request in Network Panel + </message> + <message name="IDS_DEVTOOLS_b92f649b203ca680d444432324771186" desc=""> + This request does not comply with Chrome's Certificate Transparency policy. + </message> + <message name="IDS_DEVTOOLS_c3db8a95444ea6caa45cc7dcb6e78d64" desc=""> + Security overview + </message> + <message name="IDS_DEVTOOLS_c64a179b75e6bf377700187bea8de65e" desc=""> + Reload to view details + </message> + <message name="IDS_DEVTOOLS_c8ef68c0fce4f4bfe0219809473d3651" desc=""> + Cipher + </message> + <message name="IDS_DEVTOOLS_d42c8bbf1d0f4a65f4dec450f2bc4439" desc=""> + Key exchange + </message> + <message name="IDS_DEVTOOLS_decb9f523d4cf5dc037b61cb555e6bf3" desc=""> + Not secure + </message> + <message name="IDS_DEVTOOLS_ebcaa68d6546adbf82e22d0384d945cf" desc=""> + Hide full details + </message> + <message name="IDS_DEVTOOLS_f701897bd65f88245ebde54a818953a1" desc=""> + Signature data + </message> + <message name="IDS_DEVTOOLS_ffb9069b5d779f0a9e37dfbd47d9edfb" desc=""> + Validation status + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/settings/settings_strings.grdp b/third_party/blink/renderer/devtools/front_end/settings/settings_strings.grdp new file mode 100644 index 0000000..594f0c9 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/settings/settings_strings.grdp
@@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_0f653ae68147586eb189d7baf37a696a" desc=""> + Restore defaults and reload + </message> + <message name="IDS_DEVTOOLS_29e9d8e295b1d5b3002d2d3d5baa4c37" desc=""> + Shortcuts + </message> + <message name="IDS_DEVTOOLS_2cce43a6505a5d1bdf7ea98bf7fd1bc8" desc=""> + Blackbox + </message> + <message name="IDS_DEVTOOLS_331f303e56b067dd84abf94c3bd349c4" desc=""> + Framework Blackboxing + </message> + <message name="IDS_DEVTOOLS_4829262cecb9828817b33e0f9c907f91" desc=""> + Experiments + </message> + <message name="IDS_DEVTOOLS_57391192dfa1f247ad015a0fe2eca48e" desc=""> + Pattern + </message> + <message name="IDS_DEVTOOLS_89bacc9715d030658f2602ce65426a7f" desc=""> + WARNING: + </message> + <message name="IDS_DEVTOOLS_ae25bc3ceebf44be4b59d0ade0e53f0b" desc=""> + No blackboxed patterns + </message> + <message name="IDS_DEVTOOLS_b39a035a995fc6597c8eb942210d1527" desc=""> + Behavior + </message> + <message name="IDS_DEVTOOLS_b791f463c10f80e87e887e1f863f6209" desc=""> + Add pattern... + </message> + <message name="IDS_DEVTOOLS_c745d3ac390f120535d734cd14e2f6aa" desc=""> + Blackbox content scripts (extension scripts in the page) + </message> + <message name="IDS_DEVTOOLS_c9deece3e6de26d07ef6409b96f21fd0" desc=""> + Blackboxing + </message> + <message name="IDS_DEVTOOLS_ce85958ff51e825dcf797d0451b96b71" desc=""> + Blackbox scripts whose names match + </message> + <message name="IDS_DEVTOOLS_d0834fcec6337785ee749c8f5464f6f6" desc=""> + Preferences + </message> + <message name="IDS_DEVTOOLS_d2ef7dcdede23820e315ca1c3425ba4f" desc=""> + Debugger will skip through the scripts and will not stop on exceptions thrown by them. + </message> + <message name="IDS_DEVTOOLS_e3b2f7d0af9c89f5ea504968ffcd2ef0" desc=""> + These experiments could be dangerous and may require restart. + </message> + <message name="IDS_DEVTOOLS_ffebb5ad32e2b253aa418b8d7a70028e" desc=""> + Blackbox content scripts + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/snippets/snippets_strings.grdp b/third_party/blink/renderer/devtools/front_end/snippets/snippets_strings.grdp new file mode 100644 index 0000000..7f0cb369 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/snippets/snippets_strings.grdp
@@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_b1d75786654fa93f10c31c3b544bbd03" desc=""> + Run snippet + </message> + <message name="IDS_DEVTOOLS_e0fe9b9cadde935642ad15a85c79d7b1" desc=""> + No snippets found. + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/source_frame/source_frame_strings.grdp b/third_party/blink/renderer/devtools/front_end/source_frame/source_frame_strings.grdp new file mode 100644 index 0000000..a1d41c7 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/source_frame/source_frame_strings.grdp
@@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_0818b6e40afc14684d727176bd222aa0" desc=""> + Set indentation to 2 spaces + </message> + <message name="IDS_DEVTOOLS_194f5394ae2e9c74dc3c441b92862d1d" desc=""> + Font + </message> + <message name="IDS_DEVTOOLS_22a4f3a07431f171506336782f211c61" desc=""> + Drop image file here + </message> + <message name="IDS_DEVTOOLS_261e3ec3b2545f38725d7bfe67146cc6" desc=""> + Set indentation to 8 spaces + </message> + <message name="IDS_DEVTOOLS_33443fc55632401a517b16878389f2f6" desc=""> + Set indentation to 4 spaces + </message> + <message name="IDS_DEVTOOLS_4cfa6c981549e990fe2344e4c805405e" desc=""> + Find + </message> + <message name="IDS_DEVTOOLS_59cc7cb8dfb2491cc5dfe8ebc546d797" desc=""> + Pretty print + </message> + <message name="IDS_DEVTOOLS_5ada9c9e1dad2e7e20aaa7688d7bd6c7" desc=""> + Line <ph name="LOCATION_______">$1s</ph>, Column <ph name="LOCATION_______">$2s</ph> + </message> + <message name="IDS_DEVTOOLS_6efb3f8d955fc3395726044acec66129" desc=""> + <ph name="THIS__IMAGEPREVIEWELEMENT_NATURALWIDTH">$1d</ph> × <ph name="THIS__IMAGEPREVIEWELEMENT_NATURALHEIGHT">$2d</ph> + </message> + <message name="IDS_DEVTOOLS_700a6fe957fe2782a2412e4397bce276" desc=""> + Open image in new tab + </message> + <message name="IDS_DEVTOOLS_70a0a440eed4f94a3632d346b03d9a53" desc=""> + 2 spaces + </message> + <message name="IDS_DEVTOOLS_7894a953b2e5c818b263e862929417f3" desc=""> + Tab character + </message> + <message name="IDS_DEVTOOLS_84ce71f0603df8984b0adcf5248189e3" desc=""> + Copy image URL + </message> + <message name="IDS_DEVTOOLS_89733eed06340faa760afff3b68a90ba" desc=""> + <ph name="SELECTEDTEXT_LENGTH">$1d</ph> characters selected + </message> + <message name="IDS_DEVTOOLS_a04563146775acda156e27c41a068e65" desc=""> + Nothing to preview + </message> + <message name="IDS_DEVTOOLS_abd971c026bf77d9ed737cebeed94889" desc=""> + Default indentation: + </message> + <message name="IDS_DEVTOOLS_af70cf4b9f56cd69eb56ae32f21e8416" desc=""> + <ph name="SELECTIONS_LENGTH">$1d</ph> selection regions + </message> + <message name="IDS_DEVTOOLS_be53a0541a6d36f6ecb879fa2c584b08" desc=""> + Image + </message> + <message name="IDS_DEVTOOLS_c144a6b9ff31ca0302b1cf94d4d540a0" desc=""> + <ph name="TEXTRANGE_ENDLINE___TEXTRANGE_STARTLINE____">$1d</ph> lines, <ph name="SELECTEDTEXT_LENGTH">$2d</ph> characters selected + </message> + <message name="IDS_DEVTOOLS_d7c4338058e90b2cad7c9ff93588c1ec" desc=""> + 8 spaces + </message> + <message name="IDS_DEVTOOLS_ea1fe1846b8a6d69ebf101a05a5fc194" desc=""> + Copy image as data URI + </message> + <message name="IDS_DEVTOOLS_fb49df2db96d183474fb9e954a9f0e52" desc=""> + Set indentation to tab character + </message> + <message name="IDS_DEVTOOLS_fb61758d0f0fda4ba867c3d5a46c16a7" desc=""> + Sources + </message> + <message name="IDS_DEVTOOLS_fe81050cdc3adc7c1912fc08b7aec77f" desc=""> + 4 spaces + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/sources/sources_strings.grdp b/third_party/blink/renderer/devtools/front_end/sources/sources_strings.grdp new file mode 100644 index 0000000..eadd29d --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/sources/sources_strings.grdp
@@ -0,0 +1,483 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_00a2f9d16aa26eb89a776a3d1ed4f9cd" desc=""> + Expression to check before pausing, e.g. x > 5 + </message> + <message name="IDS_DEVTOOLS_01f0097c3b7f0774139005734eacbae4" desc=""> + Add property path to watch + </message> + <message name="IDS_DEVTOOLS_035e70b676c1a7f341f758eb10a3bd1d" desc=""> + Add conditional breakpoint… + </message> + <message name="IDS_DEVTOOLS_03bfaee27b3b5cfb28deef84a0f416e5" desc=""> + Threads + </message> + <message name="IDS_DEVTOOLS_03c2e7e41ffc181a4e84080b4710e81e" desc=""> + New + </message> + <message name="IDS_DEVTOOLS_05184fe2fb6c76214bc56796837f1c9b" desc=""> + Next call frame + </message> + <message name="IDS_DEVTOOLS_06a75795f2a3be3930c707d64fd488c0" desc=""> + Show trailing whitespace characters + </message> + <message name="IDS_DEVTOOLS_08355a3ae65d425a4a6bac94ce97dcb4" desc=""> + Edit breakpoint… + </message> + <message name="IDS_DEVTOOLS_08fb8cd30c88d3b186962bb2c3226479" desc=""> + Enabled all breakpoints in line + </message> + <message name="IDS_DEVTOOLS_0ab9daf7d77e9446aeae5f66be24e800" desc=""> + Never pause here + </message> + <message name="IDS_DEVTOOLS_0b7328e087472930bcd6e51a840bb454" desc=""> + Open color picker. + </message> + <message name="IDS_DEVTOOLS_0c2c743a6d4f5bb5d3689cd87f7f5e1b" desc=""> + Disable CSS source maps + </message> + <message name="IDS_DEVTOOLS_0d09bbb2a0380f333de821bf7b3aec61" desc=""> + Not paused + </message> + <message name="IDS_DEVTOOLS_1223c0b07c7cf71289fa7f390c192ab5" desc=""> + Bracket matching + </message> + <message name="IDS_DEVTOOLS_127c3c0187f2be68a7c19273f4d8a71b" desc=""> + Delete all watch expressions + </message> + <message name="IDS_DEVTOOLS_14acf8c40287aedb6124add396f6d1c5" desc=""> + Local Modifications... + </message> + <message name="IDS_DEVTOOLS_160023e58c0251b10b570f6b43914bfc" desc=""> + Drop workspace folder here + </message> + <message name="IDS_DEVTOOLS_1cd54499835432c724e9654327ca5788" desc=""> + Code folding + </message> + <message name="IDS_DEVTOOLS_1ced1baad9bf7cd516caae0aa7558853" desc=""> + Debugger paused + </message> + <message name="IDS_DEVTOOLS_1d76fdc8e9a79fa435ee5a2afa4c9bb8" desc=""> + Paused before potential out-of-memory crash + </message> + <message name="IDS_DEVTOOLS_1f15646f60fc3c1dea747963f02d51ac" desc=""> + Group by folder + </message> + <message name="IDS_DEVTOOLS_216a9080bf22a993b2d7f9331d34cc68" desc=""> + Don't pause on exceptions + </message> + <message name="IDS_DEVTOOLS_23682ad11e062879a37272dce2948fa5" desc=""> + Clear configuration + </message> + <message name="IDS_DEVTOOLS_25eeda4a035b17ed5a353480e79dc6fb" desc=""> + Do not detect indentation + </message> + <message name="IDS_DEVTOOLS_26fff70cf6b5204fa5154fa62f5b7b69" desc=""> + Add to watch + </message> + <message name="IDS_DEVTOOLS_27cd6a52dd9de75342d5115dc6bca6ba" desc=""> + Associated files are available via file tree or <ph name="UI_SHORTCUTREGISTRY_SHORTCUTTITLEFORACTION__QUICKOPEN_SHOW__">$1s</ph>. + </message> + <message name="IDS_DEVTOOLS_30af0d86fe286708503f94e65c4da3f6" desc=""> + Paused on breakpoint + </message> + <message name="IDS_DEVTOOLS_30e71ab6fb45b9773731a0af4d7fb3b4" desc=""> + Do not show whitespace characters + </message> + <message name="IDS_DEVTOOLS_327cbc7239d92013006f601d8b9aff8f" desc=""> + Remove folder from workspace + </message> + <message name="IDS_DEVTOOLS_33121362971f65350982fbfea136c37d" desc=""> + Log a message to Console, do not break + </message> + <message name="IDS_DEVTOOLS_339ba442656bbc8e43e64b427dc598ff" desc=""> + Type a number to go to that line. + </message> + <message name="IDS_DEVTOOLS_3486ec2a2dd86270ed12b46a54372d06" desc=""> + Blackbox all content scripts + </message> + <message name="IDS_DEVTOOLS_348b4e067738aac6d7d6c30ccdb59beb" desc=""> + Source Map detected. + </message> + <message name="IDS_DEVTOOLS_34b75062caaa3ec1d9e1ee9b725ae303" desc=""> + Do not automatically reveal files in sidebar + </message> + <message name="IDS_DEVTOOLS_37d2aa45fbe4026fc347be7b07a8a468" desc=""> + Deactivate breakpoints + </message> + <message name="IDS_DEVTOOLS_38173eb2f7725d12dfcf1a920a77ecb4" desc=""> + Create new snippet + </message> + <message name="IDS_DEVTOOLS_3831f64f248899a06a6bbc8b82fccfdf" desc=""> + Log message, e.g. 'x is', x + </message> + <message name="IDS_DEVTOOLS_38b6dddcf45b3d2c9fc86ce4dd2592ba" desc=""> + Add expression + </message> + <message name="IDS_DEVTOOLS_3a4c2017c43ba6b63be4576d17893645" desc=""> + Source map found, but ignored for blackboxed file. + </message> + <message name="IDS_DEVTOOLS_3a9bd88b445fd1f4d4d8c3ce995be74a" desc=""> + Step over next function call + </message> + <message name="IDS_DEVTOOLS_3e27fe84bd1fddd585c8d06e6307b67a" desc=""> + Remove all breakpoints in line + </message> + <message name="IDS_DEVTOOLS_3fd3dddd9661349b90b648bba2748f1b" desc=""> + Sources panel + </message> + <message name="IDS_DEVTOOLS_41c03dfb0ea5890d60756ad55c6e47b1" desc=""> + Detect indentation + </message> + <message name="IDS_DEVTOOLS_434a4d8ac15ff124add730be03574f41" desc=""> + Enable all breakpoints + </message> + <message name="IDS_DEVTOOLS_4541d5953fd7db4d62ef89e9717f845a" desc=""> + Disable autocompletion + </message> + <message name="IDS_DEVTOOLS_46e8256224399a2d32a2f988a21d6562" desc=""> + Select folder for overrides + </message> + <message name="IDS_DEVTOOLS_47dbdb85aee276cd77a84a067af48aa5" desc=""> + Enable tab moves focus + </message> + <message name="IDS_DEVTOOLS_48c7c41b72e1d678923ce3571aa65b2d" desc=""> + Step + </message> + <message name="IDS_DEVTOOLS_4b3812a22a58f04fb5a0598658a3bd27" desc=""> + Go to symbol + </message> + <message name="IDS_DEVTOOLS_4ba67b3e9f4bf3135a50fa54c133fba6" desc=""> + Conditional breakpoint + </message> + <message name="IDS_DEVTOOLS_4bc16757f0e30f62902ac7f86f19b23b" desc=""> + Show function definition + </message> + <message name="IDS_DEVTOOLS_51eb42e9c7ed7951fea0d51a1e4a2cfc" desc=""> + Go to line <ph name="POSITION_LINE">$1s</ph>. + </message> + <message name="IDS_DEVTOOLS_520d0db389f362bf79ef56ca0af3dcab" desc=""> + Format + </message> + <message name="IDS_DEVTOOLS_52b3bc5e77aa070243c36cd40a4d6b6d" desc=""> + Autocompletion + </message> + <message name="IDS_DEVTOOLS_58943fa26a94bc86f7f45106080e4496" desc=""> + Resume script execution + </message> + <message name="IDS_DEVTOOLS_590d0b32e1139c6c3bcb0f99ed978dff" desc=""> + subtree modifications + </message> + <message name="IDS_DEVTOOLS_5a0a64ecca63ba9a006b6397cbdc2b8c" desc=""> + Go to line + </message> + <message name="IDS_DEVTOOLS_5a3bb6a64da384e59876cd0bc00a6eae" desc=""> + Unblackbox this script + </message> + <message name="IDS_DEVTOOLS_5bcc1f50ed61246502d37ce93368dda8" desc=""> + Paused on XHR or fetch + </message> + <message name="IDS_DEVTOOLS_5d113f2038d289f391614c39043629e8" desc=""> + Scope + </message> + <message name="IDS_DEVTOOLS_5e7d63192de1cf31345f98b0252bc523" desc=""> + <not available> + </message> + <message name="IDS_DEVTOOLS_6005268f51bade5b1f650b47b7ff68ff" desc=""> + Stop blackboxing all content scripts + </message> + <message name="IDS_DEVTOOLS_610fbde3ea8bddc086a8f50a83f0fedf" desc=""> + Previous call frame + </message> + <message name="IDS_DEVTOOLS_6121be69f70b38551bf15d90d0806778" desc=""> + Automatically reveal files in sidebar + </message> + <message name="IDS_DEVTOOLS_61cb6bc6751fc6b516847995380fdced" desc=""> + New snippet + </message> + <message name="IDS_DEVTOOLS_64c5d2b51d86c5e1d22a77a4ea5ed174" desc=""> + Disable code folding + </message> + <message name="IDS_DEVTOOLS_6700b68e0b1cd0ed13778682cc1b376d" desc=""> + Enable code folding + </message> + <message name="IDS_DEVTOOLS_681e10aecbafd7dd385fa51798ca0fd6" desc=""> + New file + </message> + <message name="IDS_DEVTOOLS_686182a69271ee4d9caa32b17ad56e9f" desc=""> + Show whitespace characters: + </message> + <message name="IDS_DEVTOOLS_68b3c10a88384bc903eb0bcb08f5e17c" desc=""> + Disable JavaScript source maps + </message> + <message name="IDS_DEVTOOLS_69a309503a6b6e3265981a5db92c82ac" desc=""> + Paused on promise rejection + </message> + <message name="IDS_DEVTOOLS_6bb8aa3b54918eeb27dafcace1e5addd" desc=""> + (no domain) + </message> + <message name="IDS_DEVTOOLS_6cc39b227b3571623cfa817ed5df1c8b" desc=""> + Disable all breakpoints + </message> + <message name="IDS_DEVTOOLS_6e0fdbff6068d8b45cac1f4ae39d6798" desc=""> + Enable autocompletion + </message> + <message name="IDS_DEVTOOLS_6f92b50cf0c9932b9359e4cfa2a6473b" desc=""> + Restart frame + </message> + <message name="IDS_DEVTOOLS_70f2eb480d2c49d1ca88ba9da0af545a" desc=""> + Debugger will skip stepping through this script, and will not stop on exceptions + </message> + <message name="IDS_DEVTOOLS_7129472c5eb598faf47e4e877f2618fd" desc=""> + Breakpoint + </message> + <message name="IDS_DEVTOOLS_74313a1b4f28fd0980e0c7677b38373c" desc=""> + Show all whitespace characters + </message> + <message name="IDS_DEVTOOLS_74662a9a81d3f50d9d1f3dddf044b550" desc=""> + Exclude folder + </message> + <message name="IDS_DEVTOOLS_74ff4bad28abee3489bd8ca138b80bb6" desc=""> + No files found + </message> + <message name="IDS_DEVTOOLS_77898d40c8a26a07d05eedb991359804" desc=""> + (source mapped from <ph name="COMPONENTS_LINKIFIER_LINKIFYURL_ORIGINURL_">$1s</ph>) + </message> + <message name="IDS_DEVTOOLS_7b5c591188e24ed71b8c72b32e86af5e" desc=""> + Disable all breakpoints in line + </message> + <message name="IDS_DEVTOOLS_7e469e0762bb1a977747a18457c2e66f" desc=""> + Show blackboxed frames + </message> + <message name="IDS_DEVTOOLS_80bd21c435b5e5ba6890161f3bc4bfd7" desc=""> + Search in folder + </message> + <message name="IDS_DEVTOOLS_820587f2a3808a99f9ffcc0576b31681" desc=""> + Make a copy… + </message> + <message name="IDS_DEVTOOLS_8317db413bca5e9ed3305fdac525ddd2" desc=""> + No variables + </message> + <message name="IDS_DEVTOOLS_8560d166d251804230566118358414e5" desc=""> + Add watch expression + </message> + <message name="IDS_DEVTOOLS_87837d0ddaa832891236be71b7bf6935" desc=""> + Pause on caught exceptions + </message> + <message name="IDS_DEVTOOLS_906646d2d69e110dcd4cfc74e5790f6f" desc=""> + Paused on event listener + </message> + <message name="IDS_DEVTOOLS_923dab99a01b578dbf1ec09277a0ed2e" desc=""> + Rename… + </message> + <message name="IDS_DEVTOOLS_945efe35b9e3950bd1a796a9310736a6" desc=""> + Go to line <ph name="POSITION_LINE">$1s</ph> and column <ph name="POSITION_COLUMN">$2s</ph>. + </message> + <message name="IDS_DEVTOOLS_9757132fffae1fe86f7c3329dc189e8d" desc=""> + Paused on exception + </message> + <message name="IDS_DEVTOOLS_97edd5423acfdf412ad9ba7f4eaa6d39" desc=""> + No file selected. + </message> + <message name="IDS_DEVTOOLS_9bbb0377ecbf31fdcfcce3283e815311" desc=""> + Ctrl+Enter + </message> + <message name="IDS_DEVTOOLS_9ce5614862050d067b2fca22f4190d12" desc=""> + Source map URL: + </message> + <message name="IDS_DEVTOOLS_9db6195620a7743228ce74addf1414d8" desc=""> + Associated files should be added to the file tree. You can debug these resolved source files as regular JavaScript files. + </message> + <message name="IDS_DEVTOOLS_9f7753821d867a81273a50de2b1e0cac" desc=""> + Pause script execution + </message> + <message name="IDS_DEVTOOLS_a0b40b72aff4851f0c49348f8868b935" desc=""> + Disable bracket matching + </message> + <message name="IDS_DEVTOOLS_a17411e9872c82855a0dc0d000e50c22" desc=""> + Call Stack + </message> + <message name="IDS_DEVTOOLS_a1942a7798767819b93df38c18d1696d" desc=""> + Display variable values inline while debugging + </message> + <message name="IDS_DEVTOOLS_a22d670bd986f8f534fe07a96b38f217" desc=""> + Add logpoint… + </message> + <message name="IDS_DEVTOOLS_a271d86904edd95b1e28f6df6c74c9ac" desc=""> + Disable tab moves focus + </message> + <message name="IDS_DEVTOOLS_a2c01e3ac442e470bc38437752707518" desc=""> + Return value + </message> + <message name="IDS_DEVTOOLS_a2ca04f270c5acfa0cda3aa0fc6976c5" desc=""> + Do not search in anonymous and content scripts + </message> + <message name="IDS_DEVTOOLS_a3fec1fa9178602843f79537c66b1496" desc=""> + Step out of current function + </message> + <message name="IDS_DEVTOOLS_a570cb902fdec05031ec1a25634bdbdb" desc=""> + Open a JavaScript or CSS file to see symbols + </message> + <message name="IDS_DEVTOOLS_a6e75eb31dc77e8d077fb6f92909e191" desc=""> + Open folder + </message> + <message name="IDS_DEVTOOLS_a7706b6eb022a90c58cf658d0085d6d1" desc=""> + Possible ways to cancel this behavior are: + </message> + <message name="IDS_DEVTOOLS_a95c3c1dc2719e527889096bbd7b662c" desc=""> + Search in all files + </message> + <message name="IDS_DEVTOOLS_abe5b14af1d1b81dffc5d6009dead621" desc=""> + Pause only when the condition is true + </message> + <message name="IDS_DEVTOOLS_ac52cf637478f3656a1fdee5c02324fd" desc=""> + Filesystem + </message> + <message name="IDS_DEVTOOLS_acd2fcf9aed3ee59e77566016a828d14" desc=""> + Paused on debugged function + </message> + <message name="IDS_DEVTOOLS_ae76c8d643589ff25d35455a80f12061" desc=""> + Do not display variable values inline while debugging + </message> + <message name="IDS_DEVTOOLS_b16d05636bde9fe84392fd4af198e9c1" desc=""> + Quick source + </message> + <message name="IDS_DEVTOOLS_b1a3aaa0de38001a39eeaf44c523a98c" desc=""> + Changes to this file were not saved to file system. + </message> + <message name="IDS_DEVTOOLS_b2accffe28bb4f4b596c9be64a28d281" desc=""> + Snippets + </message> + <message name="IDS_DEVTOOLS_b402b605feaea6029ac976f4963e20cd" desc=""> + Are you sure you want to close unsaved file: <ph name="UISOURCECODE_NAME__">$1s</ph>? + </message> + <message name="IDS_DEVTOOLS_b526d5bfa95ab0d53b118425336d52a3" desc=""> + Are you sure you want to remove this folder? + </message> + <message name="IDS_DEVTOOLS_b55fd1bae7b054568efa40f60f5b6c43" desc=""> + Enable CSS source maps + </message> + <message name="IDS_DEVTOOLS_b7e7eecbc4a9a1151ccae2f9c5aa7b14" desc=""> + Trailing + </message> + <message name="IDS_DEVTOOLS_b8f2563abb6a5253a6f11f95be0b9b62" desc=""> + Open in Sources panel + </message> + <message name="IDS_DEVTOOLS_b918846bd0a77b2051d8c4019201315f" desc=""> + Remove other breakpoints + </message> + <message name="IDS_DEVTOOLS_b9947e230aa5ac451e3b0649bdb1c7fc" desc=""> + DevTools have unsaved changes that will be permanently lost. + </message> + <message name="IDS_DEVTOOLS_bb9f288b958ce8c8d250cb392e2f1309" desc=""> + You can click the <ph name="TOOLBAR_ELEMENT">$1s</ph> button on the bottom status bar, and continue debugging with the new formatted source. + </message> + <message name="IDS_DEVTOOLS_bd1066101df937dfc5704f95ef779f62" desc=""> + No watch expressions + </message> + <message name="IDS_DEVTOOLS_c081841ffd8efaef2ee0c7bf0507758a" desc=""> + Enable bracket matching + </message> + <message name="IDS_DEVTOOLS_c12de9f9edb401ca79a3291f1831ae6f" desc=""> + Closure (<ph name="UI_BEAUTIFYFUNCTIONNAME_SCOPENAME_">$1s</ph>) + </message> + <message name="IDS_DEVTOOLS_c2e59ab4f410655458110ae524bdc9be" desc=""> + Go to "<ph name="COMMON_UISTRING__BLACKBOXING__">$1s</ph>" tab in settings + </message> + <message name="IDS_DEVTOOLS_c322e65e12002c3bd486ff62ff5b1fd6" desc=""> + node removal + </message> + <message name="IDS_DEVTOOLS_c42094126c68a61cc5359460681e1d90" desc=""> + ⌘+Enter + </message> + <message name="IDS_DEVTOOLS_c5301693c4e792bcd5a479ef38fb8f8d" desc=""> + Run + </message> + <message name="IDS_DEVTOOLS_c70f6a5cffc2538db7304f46556f0b30" desc=""> + Add selected text to watches + </message> + <message name="IDS_DEVTOOLS_c79e1cbadc868bad54f2eabe113c06f0" desc=""> + Enable breakpoint + </message> + <message name="IDS_DEVTOOLS_cd26a6a87959e99fdf99f5ccccef0464" desc=""> + Disable breakpoint + </message> + <message name="IDS_DEVTOOLS_d07d651006c823c6f008158f6eb63056" desc=""> + Resume with all pauses blocked for 500 ms + </message> + <message name="IDS_DEVTOOLS_d127dbe7fc7834601145be34349fc60f" desc=""> + Evaluate selected text in console + </message> + <message name="IDS_DEVTOOLS_d13c3f7baed576768b11a714ef4d90e2" desc=""> + paused + </message> + <message name="IDS_DEVTOOLS_d19dc64c372f09800d8117286c3d0aff" desc=""> + Breakpoints + </message> + <message name="IDS_DEVTOOLS_d1d71571592bcbb9f99bf726a9d0fe0a" desc=""> + Delete watch expression + </message> + <message name="IDS_DEVTOOLS_d280677ba371231189ef4c4fdaa9b4b3" desc=""> + Pretty-print this minified file? + </message> + <message name="IDS_DEVTOOLS_d318592071e92890f8046b4eeeecbdf1" desc=""> + attribute modifications + </message> + <message name="IDS_DEVTOOLS_d6444e40ec843a5dc64161f9eafe07a4" desc=""> + Logpoint + </message> + <message name="IDS_DEVTOOLS_da1c6b95e46b078b40e1a53bc7c44f17" desc=""> + Step into next function call + </message> + <message name="IDS_DEVTOOLS_dab88f58b06d64f6f2b0c157580c8d36" desc=""> + Add source map… + </message> + <message name="IDS_DEVTOOLS_db49f36ab9f08d646ff4416ab5009ab9" desc=""> + This script is blackboxed in debugger + </message> + <message name="IDS_DEVTOOLS_dbcfcc422f1a9f6e817bb7670a93f7d3" desc=""> + Are you sure you want to exclude this folder? + </message> + <message name="IDS_DEVTOOLS_de1b7eb1c5cad7712d521bade538de6e" desc=""> + Search in anonymous and content scripts + </message> + <message name="IDS_DEVTOOLS_e3de97b1a66edbe3fceddb1d5db2df2d" desc=""> + Copy value + </message> + <message name="IDS_DEVTOOLS_e64479370fed877b3ff0b51ee73c95ac" desc=""> + Reveal in sidebar + </message> + <message name="IDS_DEVTOOLS_e68f8487d76aeb933b5b06d7999a0e44" desc=""> + Enable JavaScript source maps + </message> + <message name="IDS_DEVTOOLS_ed5eceb0fe85ceeeabf4b4b93eeca711" desc=""> + Continue to here + </message> + <message name="IDS_DEVTOOLS_f0a47f037ca7a988466a647277ef1134" desc=""> + Paused on assertion + </message> + <message name="IDS_DEVTOOLS_f20658650d987d31063b593c05980397" desc=""> + Watch + </message> + <message name="IDS_DEVTOOLS_f2e95c3adb199ba9a0ec03526b6126ba" desc=""> + Drop in a folder to add to workspace + </message> + <message name="IDS_DEVTOOLS_f395c33fe9c382316b99128e087cb697" desc=""> + Close All + </message> + <message name="IDS_DEVTOOLS_f515d5945239e7a61fa267bd058134f1" desc=""> + Add folder to workspace + </message> + <message name="IDS_DEVTOOLS_f96985d765ed09d4930d76a3ca869508" desc=""> + Terminate current JavaScript call + </message> + <message name="IDS_DEVTOOLS_fd1be3efcf102a4183d9445d789574f4" desc=""> + Are you sure you want to delete this file? + </message> + <message name="IDS_DEVTOOLS_fd8c5cf684c7bd30f907a74603e204ac" desc=""> + Activate breakpoints + </message> + <message name="IDS_DEVTOOLS_fe6e43324287cedf01c16c9eb8d2b121" desc=""> + Copy stack trace + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/terminal/terminal_strings.grdp b/third_party/blink/renderer/devtools/front_end/terminal/terminal_strings.grdp new file mode 100644 index 0000000..a47f40c --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/terminal/terminal_strings.grdp
@@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_514d8a494f087c0d549b9536c2ef3bd9" desc=""> + Terminal + </message> + <message name="IDS_DEVTOOLS_69685b2a57646d0d0bc125b5f94f3931" desc=""> + Terminal service is not available + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/text_editor/text_editor_strings.grdp b/third_party/blink/renderer/devtools/front_end/text_editor/text_editor_strings.grdp new file mode 100644 index 0000000..06bb435 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/text_editor/text_editor_strings.grdp
@@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_55212da7537e29610e52134f4097f0b2" desc=""> + Code editor + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/timeline/timeline_strings.grdp b/third_party/blink/renderer/devtools/front_end/timeline/timeline_strings.grdp new file mode 100644 index 0000000..72eb2f7 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/timeline/timeline_strings.grdp
@@ -0,0 +1,942 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_0007333f80790cc7ef6b97ce5e0ac297" desc=""> + Layout Invalidations + </message> + <message name="IDS_DEVTOOLS_0060636b449d1da5a8581bfee180f0c2" desc=""> + and + </message> + <message name="IDS_DEVTOOLS_00c3783a786856df24fd85e1093ef516" desc=""> + DCL + </message> + <message name="IDS_DEVTOOLS_00eeb588b8336923c7a236079c87c908" desc=""> + Install Timer + </message> + <message name="IDS_DEVTOOLS_01b26724a7b11aab03f175512e2c9f0f" desc=""> + Show recent timeline sessions + </message> + <message name="IDS_DEVTOOLS_01da20cf88fba2246309c541bddac1b1" desc=""> + Documents: <ph name="PH1">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_01ea16e89d02c33ef2a6a5db67665e0a" desc=""> + Main — <ph name="TRACK_URL">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_02a3a357710cc2a5dfdfb74ed012fb59" desc=""> + Url + </message> + <message name="IDS_DEVTOOLS_04cbdd8baeb482d9ff2e48b186479a06" desc=""> + Streaming Wasm Response + </message> + <message name="IDS_DEVTOOLS_05b8804bd8a147740eb7a35786c71a3c" desc=""> + Node: + </message> + <message name="IDS_DEVTOOLS_0638b5f626aa994ad5da95ce95288a66" desc=""> + [ unknown node ] + </message> + <message name="IDS_DEVTOOLS_064866c00b4298761dd36ec9df9be72f" desc=""> + Hit Test + </message> + <message name="IDS_DEVTOOLS_06a83455a448479eb950ea190d815439" desc=""> + Malformed CPU profile format + </message> + <message name="IDS_DEVTOOLS_06b8c6c83d552c894d01ad5c418e566b" desc=""> + Receive Response + </message> + <message name="IDS_DEVTOOLS_0712dbe6e0a2a72e3c3bd1fc42b8ccb3" desc=""> + Style Invalidations + </message> + <message name="IDS_DEVTOOLS_07535d965500993cdde8e7d0c686c993" desc=""> + Onload Event + </message> + <message name="IDS_DEVTOOLS_077569834980c53bd3805bb49d62d910" desc=""> + - Network throttling is enabled + </message> + <message name="IDS_DEVTOOLS_07f0007f9cefa79303d1093070975149" desc=""> + - JavaScript sampling is disabled + </message> + <message name="IDS_DEVTOOLS_07fa8e7d7b4634db5e410fc35dba40f4" desc=""> + Long frame + </message> + <message name="IDS_DEVTOOLS_0877b8db99f11ff69875bf025df75c7f" desc=""> + Animation Frame Requested + </message> + <message name="IDS_DEVTOOLS_08790b919dc10c98ef4f4678e4a4cc98" desc=""> + Fire Idle Callback + </message> + <message name="IDS_DEVTOOLS_08c1f153a1c6f21e1064581df9b05ee8" desc=""> + Layer tree + </message> + <message name="IDS_DEVTOOLS_08d5a8363f4ad65b14c8f9a32dd93944" desc=""> + JS Frame + </message> + <message name="IDS_DEVTOOLS_08db5f30f625a406882862b8a29b1bc6" desc=""> + Major GC + </message> + <message name="IDS_DEVTOOLS_09d66464ad53e6080988ad30824ea023" desc=""> + Frame — <ph name="TRACK_URL">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_0d015d96f63a8c12d96b8399482b593f" desc=""> + Uncategorized + </message> + <message name="IDS_DEVTOOLS_0d43b55b13285fd05236204c9a884f18" desc=""> + (<ph name="TIMELINE_TIMELINEHISTORYMANAGER__COARSEAGE_STARTEDAT_">$1s</ph> ago) + </message> + <message name="IDS_DEVTOOLS_0d58f3789fa2779bb4b2b86f90cab764" desc=""> + Nodes That Need Layout + </message> + <message name="IDS_DEVTOOLS_0e6dea9a8306a3ef170cb8c78263debe" desc=""> + Click the record button <ph name="RECORDBUTTON">$1s</ph> or hit <ph name="RECORDKEY">$2s</ph> to start a new recording. +Click the reload button <ph name="RELOADBUTTON">$3s</ph> or hit <ph name="RELOADKEY">$4s</ph> to record the page load. + </message> + <message name="IDS_DEVTOOLS_0e8dfe937d359c7df31b16ea7e9cca81" desc=""> + Hide chrome frame in Layers view + </message> + <message name="IDS_DEVTOOLS_10aab9f12eca6bca3a6215914bab2745" desc=""> + Allotted Time + </message> + <message name="IDS_DEVTOOLS_121ee86db6c7660edb3864de279ef742" desc=""> + <ph name="ELAPSED_TOFIXED_PRECISE_________">$1s</ph> sec + </message> + <message name="IDS_DEVTOOLS_12ddabfc2210fb123f96a03f03816024" desc=""> + Recurring handler took <ph name="NUMBER_MILLISTOSTRING_EVENT_DURATION__TRUE_">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_1572a49e8ab36a669016c48d7fca5d76" desc=""> + Cache Consume Options + </message> + <message name="IDS_DEVTOOLS_16bfbf9c462762cf1cba4134ec53c504" desc=""> + Loading + </message> + <message name="IDS_DEVTOOLS_177845b60fde99c43c2af204188dd7c6" desc=""> + No Grouping + </message> + <message name="IDS_DEVTOOLS_17f2327f2e0ec63f2a2e6300fc1b70a7" desc=""> + Show memory timeline + </message> + <message name="IDS_DEVTOOLS_187c6ad3a74cc93ac6c2229d398e383e" desc=""> + Nodes + </message> + <message name="IDS_DEVTOOLS_18fe96f0c47fa8c62afe3be31d97b880" desc=""> + Finish Loading + </message> + <message name="IDS_DEVTOOLS_1b01d1ef7772f8e0c0e0427e4faad653" desc=""> + Listeners: <ph name="PH1">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_1b2c363066d5912ae8b27a1527f3d45e" desc=""> + Group by Domain + </message> + <message name="IDS_DEVTOOLS_1e3eaaac8d3c9cffea8ee7f03a8a6121" desc=""> + DOMContentLoaded Event + </message> + <message name="IDS_DEVTOOLS_205fd38626b73da9d837e61b2c7af71f" desc=""> + Evaluate Script + </message> + <message name="IDS_DEVTOOLS_20ec6a94230f361368789ddd8bec855c" desc=""> + Malformed timeline input, wrong JSON brackets balance + </message> + <message name="IDS_DEVTOOLS_21263b6755fb99797d30820fd4d2b4f0" desc=""> + <ph name="URL">$1s</ph> [<ph name="STARTLINE____">$2s</ph>…<ph name="ENDLINE____">$3s</ph>] + </message> + <message name="IDS_DEVTOOLS_217b22459b85349fbfbb7e797719cc37" desc=""> + Receive WebSocket Handshake + </message> + <message name="IDS_DEVTOOLS_2267d2f9ecae3136874e6017d01f4574" desc=""> + Group by Activity + </message> + <message name="IDS_DEVTOOLS_232e59f3380381caf0634ab2f035dbf2" desc=""> + (from service worker) + </message> + <message name="IDS_DEVTOOLS_237f26bfdd9351cd363bca657ff35551" desc=""> + . Long frame times are an indication of + </message> + <message name="IDS_DEVTOOLS_2383a71629ce9189cb494c3fb8af7ac4" desc=""> + Heaviest stack + </message> + <message name="IDS_DEVTOOLS_23ca9d66c8f521090421155382ef94b9" desc=""> + Key Down + </message> + <message name="IDS_DEVTOOLS_248307dc00d11b9b67fdbfd34507f0aa" desc=""> + XHR Load + </message> + <message name="IDS_DEVTOOLS_24aa4117da86c41684ad25742832dfa6" desc=""> + Async + </message> + <message name="IDS_DEVTOOLS_25a5e1f05232eae2d3a9c1ff4cb83869" desc=""> + Function Call + </message> + <message name="IDS_DEVTOOLS_277b749cfb8e0389d1b89e7cb671753a" desc=""> + Context Menu + </message> + <message name="IDS_DEVTOOLS_2875ec54afbd9922e0553f4b441aa54b" desc=""> + Painting + </message> + <message name="IDS_DEVTOOLS_2a0e96bf571559add541036a25ca1d36" desc=""> + Call Stacks + </message> + <message name="IDS_DEVTOOLS_2a5021aea912316167342b34cbf358b4" desc=""> + Compile Module + </message> + <message name="IDS_DEVTOOLS_2ae3330084b44abd37672d0ca603471e" desc=""> + <ph name="BEGINDATA__DIRTYOBJECTS__">$1s</ph> of <ph name="BEGINDATA__TOTALOBJECTS__">$2s</ph> + </message> + <message name="IDS_DEVTOOLS_2b2195634ae5a0d7c6dada694bdcdc65" desc=""> + Callback ID + </message> + <message name="IDS_DEVTOOLS_2b55387dd066c5bac646ac61543d152d" desc=""> + CPU + </message> + <message name="IDS_DEVTOOLS_2b66d07a14b9e6da66cde6baab473e92" desc=""> + <ph name="SELFCATEGORY_TITLE">$1s</ph> (children) + </message> + <message name="IDS_DEVTOOLS_2d2af0b530003b552681f91e29c509d1" desc=""> + Recalculation Forced + </message> + <message name="IDS_DEVTOOLS_2da2415714a5e7450a9a127431c02a41" desc=""> + Send Request + </message> + <message name="IDS_DEVTOOLS_2f3e2f48b161c9cadd45dcdffd726c79" desc=""> + JS Heap: <ph name="PH1">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_2f709c2af7d47a610e3c48a87d1ec429" desc=""> + Invalidate Layout + </message> + <message name="IDS_DEVTOOLS_2fc3f5e968c02091e3ba9863088f0651" desc=""> + Callback Function + </message> + <message name="IDS_DEVTOOLS_31084046e4a000cc4ac980dc68ea9ce9" desc=""> + Parse Script + </message> + <message name="IDS_DEVTOOLS_316853cc3718335f11c048e33b9be98a" desc=""> + Click + </message> + <message name="IDS_DEVTOOLS_31c6b3fdfaaa80dba2dbf92a4600524c" desc=""> + Sign + </message> + <message name="IDS_DEVTOOLS_3227e479f6541c685b08023affdc8c69" desc=""> + Consumed Cache Size + </message> + <message name="IDS_DEVTOOLS_324118a6721dd6b8a9b9f4e327df2bf5" desc=""> + Input + </message> + <message name="IDS_DEVTOOLS_33991558a089f674da1c5c26fd0a6161" desc=""> + jank + </message> + <message name="IDS_DEVTOOLS_347aadfc505a4bc6b2f9d81363d2331c" desc=""> + NET + </message> + <message name="IDS_DEVTOOLS_3581b739d9d4895d0f69d9a897b02a3f" desc=""> + Verify Reply + </message> + <message name="IDS_DEVTOOLS_359783360b8522c55aa7a9c7d5593d5d" desc=""> + Pinch End + </message> + <message name="IDS_DEVTOOLS_361beede47de122bfb91fe1da6e3f1a7" desc=""> + Legacy Timeline format is not supported. + </message> + <message name="IDS_DEVTOOLS_38108192a74ae7b3deda8762ff299109" desc=""> + <ph name="TITLE">$1s</ph> - Details + </message> + <message name="IDS_DEVTOOLS_390afae8f87b5024e0c32c4e6ce3e2da" desc=""> + Run Microtasks + </message> + <message name="IDS_DEVTOOLS_3b419ceb25fddb807ea9483f65fded06" desc=""> + Capture settings + </message> + <message name="IDS_DEVTOOLS_3d1f92a565d3b1a61880236e33c49bf3" desc=""> + Timeline + </message> + <message name="IDS_DEVTOOLS_3de9387fc230ce74214446e58c4fefde" desc=""> + Compile + </message> + <message name="IDS_DEVTOOLS_3df7062234c9e55d49648289c5b2c80f" desc=""> + Time spent in rendering + </message> + <message name="IDS_DEVTOOLS_3e8e23cb13898f3f9760a0f1d9203bd1" desc=""> + Stack trace: + </message> + <message name="IDS_DEVTOOLS_3eec15d0ba9a93d3176bab9218bb2570" desc=""> + Failed to save timeline: <ph name="ERROR_MESSAGE">$1s</ph> (<ph name="ERROR_NAME">$2s</ph>, <ph name="ERROR_CODE">$3s</ph>) + </message> + <message name="IDS_DEVTOOLS_3f978efb26e66c6c9af5db34268ccf41" desc=""> + Compiled Wasm Module + </message> + <message name="IDS_DEVTOOLS_40a15f22bd3574304d7843344006e0b6" desc=""> + First Contentful Paint + </message> + <message name="IDS_DEVTOOLS_41b1478092e85f8c8fa1f98e5efc9b35" desc=""> + Layout Forced + </message> + <message name="IDS_DEVTOOLS_427b6d816d7fdd86cabe48d8180a3cc9" desc=""> + Image URL + </message> + <message name="IDS_DEVTOOLS_44ff4e8748811d0661f820aeb28ecaf4" desc=""> + XHR Ready State Change + </message> + <message name="IDS_DEVTOOLS_46a2a41cc6e552044816a2d04634545d" desc=""> + State + </message> + <message name="IDS_DEVTOOLS_46fa564bb1eed5cd3992cac85e8f094b" desc=""> + Screenshots + </message> + <message name="IDS_DEVTOOLS_476f68367f02309b39daf298981e30c5" desc=""> + Minor GC + </message> + <message name="IDS_DEVTOOLS_4802a5ac6005a6ab9c68a2fb29e30a3e" desc=""> + Paint + </message> + <message name="IDS_DEVTOOLS_485ee6de8f9a0e36c182bb56a05b2ca2" desc=""> + Mouse Wheel + </message> + <message name="IDS_DEVTOOLS_48c84951d13f2944b6003832cd4ffcba" desc=""> + <ph name="EVENTDATA__ENCODEDDATALENGTH__">$1s</ph> Bytes + </message> + <message name="IDS_DEVTOOLS_498f79c4c5bbde77f1bceb6c86fd0f6d" desc=""> + Show + </message> + <message name="IDS_DEVTOOLS_4bbc0d1543b5258061fd5c8590fdbe9e" desc=""> + Encoded Data + </message> + <message name="IDS_DEVTOOLS_4c2a8fe7eaf24721cc7a9f0175115bd4" desc=""> + Message + </message> + <message name="IDS_DEVTOOLS_4dab9fd6bdee5285598246c6ea7cc88f" desc=""> + Fling Halt + </message> + <message name="IDS_DEVTOOLS_4ebada6a2af2bcba53ded1d7b414f081" desc=""> + FP + </message> + <message name="IDS_DEVTOOLS_4fec5edf718a9ca2c6245167b78f029a" desc=""> + Scroll End + </message> + <message name="IDS_DEVTOOLS_50294a317f78ab6caf9ad2558a4b7484" desc=""> + Invalidations + </message> + <message name="IDS_DEVTOOLS_504d75604f56770c3c513de2c49ecbe8" desc=""> + Wasm Module Cache Hit + </message> + <message name="IDS_DEVTOOLS_5288680dbe452673259047491b87d17d" desc=""> + CPU time + </message> + <message name="IDS_DEVTOOLS_52f9ec21735243ad9917cda3ca077d32" desc=""> + GPU + </message> + <message name="IDS_DEVTOOLS_53081d6225e780e0f0d94351251be91c" desc=""> + (changed "<ph name="INVALIDATION_SELECTORPART">$1s</ph>"<ph name="EXTRADATA">$2s</ph>) + </message> + <message name="IDS_DEVTOOLS_539dddc574d3cd85ba73df93df7a76d0" desc=""> + Stack Trace + </message> + <message name="IDS_DEVTOOLS_5402f18025999ebf70fd56d8ca1b1909" desc=""> + GC Event + </message> + <message name="IDS_DEVTOOLS_5481039ec867c9ad2d5a313287124961" desc=""> + Fling Start + </message> + <message name="IDS_DEVTOOLS_548babdfd161a8fc2d4b634b682a456d" desc=""> + (changed attribute to "<ph name="INVALIDATION_CHANGEDATTRIBUTE">$1s</ph>"<ph name="EXTRADATA">$2s</ph>) + </message> + <message name="IDS_DEVTOOLS_54fd6de66ec40dc89ec90ba5429094d7" desc=""> + Group by Category + </message> + <message name="IDS_DEVTOOLS_5564c00b6210082e536c897014f72361" desc=""> + Start profiling and reload page + </message> + <message name="IDS_DEVTOOLS_55b4b48b80795ee9b6a3220ca415786d" desc=""> + Schedule Style Recalculation + </message> + <message name="IDS_DEVTOOLS_57f06e0eceb273507ade79baf8d3a2d4" desc=""> + Tap Begin + </message> + <message name="IDS_DEVTOOLS_585bc08ce62507965db6ec748c5a251e" desc=""> + Timer ID + </message> + <message name="IDS_DEVTOOLS_5878904937ecbc1d0556f79782ab03cd" desc=""> + Scroll Update + </message> + <message name="IDS_DEVTOOLS_59cf59caeba8075dec6a745b083edd0c" desc=""> + Time Waiting for Main Thread + </message> + <message name="IDS_DEVTOOLS_5a750f86ef41f22f852c43351e3ff383" desc=""> + Verify + </message> + <message name="IDS_DEVTOOLS_5af8622e730a34a15962fb8f46df1b5e" desc=""> + Captures advanced paint instrumentation, introduces significant performance overhead + </message> + <message name="IDS_DEVTOOLS_5bcd94bc1f71db5659b35ad5deeb94c7" desc=""> + Fling + </message> + <message name="IDS_DEVTOOLS_5c593b83b0fca15af4b50ca95c9d3e87" desc=""> + Sign Reply + </message> + <message name="IDS_DEVTOOLS_5e8170b28aaa693ca9170bb0d65b3043" desc=""> + Destroy WebSocket + </message> + <message name="IDS_DEVTOOLS_5faec6160efeed8f7d29c081b92e8890" desc=""> + User Timing + </message> + <message name="IDS_DEVTOOLS_5fbceaa309bba91ee916d46e06ac0080" desc=""> + Touch Move + </message> + <message name="IDS_DEVTOOLS_5fe7053d3a0e35c2a3242996e690e160" desc=""> + Update Layer + </message> + <message name="IDS_DEVTOOLS_60c21f78ce2dcd2da001fa3221c8ca15" desc=""> + Nodes: + </message> + <message name="IDS_DEVTOOLS_60f718c3ba644a198920a74083ccb80f" desc=""> + Blackboxed + </message> + <message name="IDS_DEVTOOLS_611d29c748a7931c825a247fcf3f290e" desc=""> + Encrypt + </message> + <message name="IDS_DEVTOOLS_61b67ca7c1d8eea5b55d23bbb615d944" desc=""> + Recalculate Style + </message> + <message name="IDS_DEVTOOLS_6347d5359bdee6d82717b4ad73aee504" desc=""> + Frame Started Loading + </message> + <message name="IDS_DEVTOOLS_63b8e6041614e4130722f79ab66087e6" desc=""> + Send WebSocket Handshake + </message> + <message name="IDS_DEVTOOLS_63e467c0720678aa503a5f0c022d56c5" desc=""> + First Invalidated + </message> + <message name="IDS_DEVTOOLS_640d76ebf7917e7353ea0444790c9794" desc=""> + Image Resize + </message> + <message name="IDS_DEVTOOLS_66f1aed235ade25269a561e81cbbb43a" desc=""> + Scripting + </message> + <message name="IDS_DEVTOOLS_67eed98f4bc75c4ab261b79a0e2c52cd" desc=""> + Cache Rejected + </message> + <message name="IDS_DEVTOOLS_686155af75a60a0f6e9d80c1f7edd3e9" desc=""> + JavaScript + </message> + <message name="IDS_DEVTOOLS_6978c23868116ca3eccb809bc699742e" desc=""> + - Significant overhead due to paint instrumentation + </message> + <message name="IDS_DEVTOOLS_6a389f626da11df07508bf251de59c23" desc=""> + Frame Start + </message> + <message name="IDS_DEVTOOLS_6aafe894685594a908a8996d68e88028" desc=""> + Hide records shorter than <ph name="DURATIONMS">$1d</ph> ms + </message> + <message name="IDS_DEVTOOLS_6c906c5f560faeb38f51683bc22fb212" desc=""> + Group by Subdomain + </message> + <message name="IDS_DEVTOOLS_6d12d9901547700bfcefb2a3e5cff2b6" desc=""> + heaviest stack + </message> + <message name="IDS_DEVTOOLS_6d1b752b6cdcfb71d098cc271bc133aa" desc=""> + Embedder Callback + </message> + <message name="IDS_DEVTOOLS_6d555ca89f5ca9fc68e5d418b4cf732b" desc=""> + Draw Frame + </message> + <message name="IDS_DEVTOOLS_6d8a59067ffe0498f3f5f2c03025b799" desc=""> + Group by URL + </message> + <message name="IDS_DEVTOOLS_70582905817c902e7a334c24718cba88" desc=""> + Touch End + </message> + <message name="IDS_DEVTOOLS_70bac6f11765f731510b0ac659fd26a1" desc=""> + Malformed timeline data: <ph name="E_TOSTRING__">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_70d68501018d9d6496e55cad8a2c3ba1" desc=""> + Load profile... + </message> + <message name="IDS_DEVTOOLS_7125f394de382b13a7e7a5a4b6d23364" desc=""> + Raster + </message> + <message name="IDS_DEVTOOLS_71613aba6474d2e2dc12d00cc46743f0" desc=""> + Touch Start + </message> + <message name="IDS_DEVTOOLS_7363d05ecc1497f2f8ae05b334b45651" desc=""> + Disable JavaScript samples + </message> + <message name="IDS_DEVTOOLS_73cf2f244bc0cb0d205b99c04fa13978" desc=""> + Tap + </message> + <message name="IDS_DEVTOOLS_762e3a77ecdd773da2b859e6807529a2" desc=""> + Decrypt + </message> + <message name="IDS_DEVTOOLS_76e815d5323a5f3c80a3d186c416e92b" desc=""> + [Chrome extensions overhead] + </message> + <message name="IDS_DEVTOOLS_76ecb02d1f339c2dd6f14c41ead368c1" desc=""> + Handler took <ph name="NUMBER_MILLISTOSTRING_EVENT_DURATION__TRUE_">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_77c18a89217b2a9a2553ac9a0598b99a" desc=""> + Rasterizer Thread <ph name="RASTERCOUNT">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_7820708244a842157c5fc8186e7b2bfa" desc=""> + Wasm Module Cache Invalid + </message> + <message name="IDS_DEVTOOLS_787ddae3fd4c1a93cc28af8bb3940bdc" desc=""> + Image Decode + </message> + <message name="IDS_DEVTOOLS_798afebf1a5e9d795a96f0c82cccaae2" desc=""> + Cached Wasm Module + </message> + <message name="IDS_DEVTOOLS_7b3a6b02f467b95f2b5267aa94708c07" desc=""> + Thread <ph name="__THREADINDEX">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_7d341c08fd102f0b86285b5ff2e26ea7" desc=""> + <ph name="TITLE">$1s</ph>: <ph name="EVENTDATA__MESSAGE__">$2s</ph> + </message> + <message name="IDS_DEVTOOLS_80a4b8755d836d50c19e6eefb976bc2e" desc=""> + <ph name="SELFCATEGORY_TITLE">$1s</ph> (self) + </message> + <message name="IDS_DEVTOOLS_81e91be8db96be69e372f0c715ec7444" desc=""> + Collected + </message> + <message name="IDS_DEVTOOLS_81ff3427527105233469f158360d8b02" desc=""> + Select item for details. + </message> + <message name="IDS_DEVTOOLS_83561bf6ac8333e0d1627887d533907c" desc=""> + Drop timeline file or URL here + </message> + <message name="IDS_DEVTOOLS_83e393be9178c404eb013bca48782312" desc=""> + <ph name="CLIPWIDTH">$1s</ph> × <ph name="CLIPHEIGHT">$2s</ph> + </message> + <message name="IDS_DEVTOOLS_86c8559f4d7d1d74dc3e04baf2b65cc6" desc=""> + Decoded Body + </message> + <message name="IDS_DEVTOOLS_871646cb17b6936aa29df33b8d550051" desc=""> + Update Layer Tree + </message> + <message name="IDS_DEVTOOLS_87644f7e0957c4bf2990aedfe046b71e" desc=""> + GPU Memory [KB]: <ph name="PH1">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_87ba2ecc8b6915e8bd6f5089918229fd" desc=""> + Range + </message> + <message name="IDS_DEVTOOLS_883b293ae308d8e3caf1614c8a2fda61" desc=""> + Group by Frame + </message> + <message name="IDS_DEVTOOLS_88d982014902936a7e7ab24058c88ed0" desc=""> + Unknown cause for + </message> + <message name="IDS_DEVTOOLS_89be1120d42e0cbacbf46eee77766b76" desc=""> + . + </message> + <message name="IDS_DEVTOOLS_8a51f964740c2a7cb6e68404bda36ef1" desc=""> + <ph name="NUMBER_BYTESTOSTRING_DELTA_">$1s</ph> collected + </message> + <message name="IDS_DEVTOOLS_8af5f76068f881acfad9d2880a4e2310" desc=""> + Input Latency + </message> + <message name="IDS_DEVTOOLS_8b8747bfcec728cdf8d54030e4d28451" desc=""> + Processing profile… + </message> + <message name="IDS_DEVTOOLS_8b92f105e7b7e01e4c7ed00d415318f3" desc=""> + Stylesheet URL + </message> + <message name="IDS_DEVTOOLS_8c311ee6ad411f13da478e4996907ffa" desc=""> + After recording, select an area of interest in the overview by dragging. +Then, zoom and pan the timeline with the mousewheel or <ph name="NAVIGATENODE">$1s</ph> keys. +<ph name="LEARNMORENODE">$2s</ph> + </message> + <message name="IDS_DEVTOOLS_8cd016d3ad1e59b37133d6c993455d70" desc=""> + Timer Installed + </message> + <message name="IDS_DEVTOOLS_8cda3116eb86d6a743edfebd3c2eda15" desc=""> + Request Idle Callback + </message> + <message name="IDS_DEVTOOLS_8d98af06b412f3f2455c2786e88aabdb" desc=""> + Nodes: <ph name="PH1">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_8dc1f1afb0dcd5282b146c8cf5d758e1" desc=""> + Unexpected entryIndex <ph name="ENTRYINDEX">$1d</ph> + </message> + <message name="IDS_DEVTOOLS_8f25fae98e6ef6ff87364e590df8cee5" desc=""> + Long task + </message> + <message name="IDS_DEVTOOLS_8f27b153047f3da699b39221b47b3217" desc=""> + Initializing profiler… + </message> + <message name="IDS_DEVTOOLS_91412421a30e87ce15a4f10ea39f6682" desc=""> + WASD + </message> + <message name="IDS_DEVTOOLS_920fd776137a582939eac4fc07808754" desc=""> + <ph name="NUMBER_MILLISTOSTRING_FRAME_ENDTIME___FRAME_STARTTIME__TRUE_">$1s</ph> (at <ph name="NUMBER_MILLISTOSTRING_FRAME_STARTTIMEOFFSET__TRUE_">$2s</ph>) + </message> + <message name="IDS_DEVTOOLS_92f0ea95e53565026335b840b8788bf4" desc=""> + <ph name="NUMBER_MILLISTOSTRING_TOTALTIME__TRUE_">$1s</ph> (self <ph name="NUMBER_MILLISTOSTRING_SELFTIME__TRUE_">$2s</ph>) + </message> + <message name="IDS_DEVTOOLS_932cc5549fb2d58c13ce13653469d309" desc=""> + Mouse Down + </message> + <message name="IDS_DEVTOOLS_9352d706112654ca7c3f2595bc529cf5" desc=""> + Paint Image + </message> + <message name="IDS_DEVTOOLS_9399a34c7d7f4a7c046016e38f80e046" desc=""> + is a likely performance bottleneck. + </message> + <message name="IDS_DEVTOOLS_93c8e71d1b0e18d58736d3e255a14533" desc=""> + Buffer usage + </message> + <message name="IDS_DEVTOOLS_956f8281d37fdceec7698094b6236870" desc=""> + (from cache) + </message> + <message name="IDS_DEVTOOLS_9669f96ca9d2e20feda07d349d3cac86" desc=""> + Key Up + </message> + <message name="IDS_DEVTOOLS_976e665bbff13a2a2a2eb4a83b8bb602" desc=""> + Save profile... + </message> + <message name="IDS_DEVTOOLS_97c091732895087b8900d81105e54446" desc=""> + Frame Start (main thread) + </message> + <message name="IDS_DEVTOOLS_997a8c473db4f81c5fb3d5900030d44d" desc=""> + (no recordings) + </message> + <message name="IDS_DEVTOOLS_9a2837081f4b4cd67f625bd8e7567383" desc=""> + Compile Script + </message> + <message name="IDS_DEVTOOLS_9a4a3be092449d965b794e48c6f6163c" desc=""> + Rasterize Paint + </message> + <message name="IDS_DEVTOOLS_9bedd08947719ccd339c3493e6701d4b" desc=""> + Request Main Thread Frame + </message> + <message name="IDS_DEVTOOLS_9c80c1f042e925ffbb94db9a17eb03df" desc=""> + Dedicated Worker + </message> + <message name="IDS_DEVTOOLS_9d07f3bb674a88ea26f10e6b7589e000" desc=""> + Aggregated Time + </message> + <message name="IDS_DEVTOOLS_9d2ee5f9ab058df4d72a137e13bd4df2" desc=""> + [ <ph name="INVALIDATION_NODENAME">$1s</ph> ] + </message> + <message name="IDS_DEVTOOLS_a10717d996573373c8f9a01c49bbb6a5" desc=""> + Loading profile… + </message> + <message name="IDS_DEVTOOLS_a3b61900010aa9472919c6c7ac247fed" desc=""> + (changed id to "<ph name="INVALIDATION_CHANGEDID">$1s</ph>"<ph name="EXTRADATA">$2s</ph>) + </message> + <message name="IDS_DEVTOOLS_a45da96d0bf6575970f2d27af22be28a" desc=""> + System + </message> + <message name="IDS_DEVTOOLS_a580a76abe8b0912889d80f5c4cb9559" desc=""> + Group by Product + </message> + <message name="IDS_DEVTOOLS_a6f22a2373839a1d417d7a4078f0383a" desc=""> + - CPU throttling is enabled + </message> + <message name="IDS_DEVTOOLS_a7c815fafe60ae637d38216fa6300395" desc=""> + FCP + </message> + <message name="IDS_DEVTOOLS_aa40d845ecb78d5bd01ff8b0cc9e213e" desc=""> + Receive Data + </message> + <message name="IDS_DEVTOOLS_aa49e59ec25c5938e9629495e54b913a" desc=""> + Worker — <ph name="TRACK_URL">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_ab0b54125d50a09e75f3829e7e90b8ea" desc=""> + WebSocket Protocol + </message> + <message name="IDS_DEVTOOLS_ac3b5b333d7529f2d6e178a1d326315c" desc=""> + Disables JavaScript sampling, reduces overhead when running against mobile devices + </message> + <message name="IDS_DEVTOOLS_ac5bb077c33753116b5e91ff1766e7bc" desc=""> + Received + </message> + <message name="IDS_DEVTOOLS_aed0e2bd848c2ac9dddb03d8c21c67b6" desc=""> + Touch Cancel + </message> + <message name="IDS_DEVTOOLS_b030f7d30297555390c6d2d23af55fa1" desc=""> + moments + </message> + <message name="IDS_DEVTOOLS_b06f8ae307ae18937eff67f286f45a20" desc=""> + Repeats + </message> + <message name="IDS_DEVTOOLS_b0f2106d388ba5a6a92ac83146df9770" desc=""> + Idle callback execution extended beyond deadline by <ph name="EXCEEDEDMS">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_b14bde4124700a984f3840be64c98bf2" desc=""> + Invoked by Timeout + </message> + <message name="IDS_DEVTOOLS_b24dc7fd5bcbe91ffc080f0220f50dfe" desc=""> + DOM GC + </message> + <message name="IDS_DEVTOOLS_b2ef7b20ebc78fa300ef24c1965033bc" desc=""> + Pending for + </message> + <message name="IDS_DEVTOOLS_b357598ce3db447b0138d1a5ea6b76cc" desc=""> + Layout root + </message> + <message name="IDS_DEVTOOLS_b3bfefedfa27aa11e79f637b22b16d09" desc=""> + [V8 Runtime] + </message> + <message name="IDS_DEVTOOLS_b49fe3f49a656887d446c2da3851a88a" desc=""> + Network request + </message> + <message name="IDS_DEVTOOLS_b4c7087912916a68642000d8759baec2" desc=""> + Scroll Begin + </message> + <message name="IDS_DEVTOOLS_b53fbbb58656447400f07904e68c0f12" desc=""> + Create WebSocket + </message> + <message name="IDS_DEVTOOLS_b59387e4d62a4e3fe4285a1311dcd272" desc=""> + Event Log + </message> + <message name="IDS_DEVTOOLS_b6722804f5872cdd88347da194d42087" desc=""> + HEAP + </message> + <message name="IDS_DEVTOOLS_b8a4d4c7e6bb7b5534b856ce7a9ccde0" desc=""> + Drag + </message> + <message name="IDS_DEVTOOLS_b9048f8879ceb809dd8d8bc0866306b5" desc=""> + , and <ph name="INVALIDATIONNODES_LENGTH____">$1s</ph> others + </message> + <message name="IDS_DEVTOOLS_b94c9f4242a696995ec1a85feeb138e2" desc=""> + Layer Root + </message> + <message name="IDS_DEVTOOLS_b9749b1e497d9193cd4307bb9e341287" desc=""> + Decrypt Reply + </message> + <message name="IDS_DEVTOOLS_b9f3a3a888d3796e0248b3f65b14349e" desc=""> + Bottom-Up + </message> + <message name="IDS_DEVTOOLS_bd03acccca092608aac93f5fadb091d5" desc=""> + Streamed + </message> + <message name="IDS_DEVTOOLS_be7e368875c5373b1cfbc3b97abc8742" desc=""> + ≥ <ph name="DURATIONMS">$1d</ph> ms + </message> + <message name="IDS_DEVTOOLS_be85f6b3661854c85ddbde4c1429b2a2" desc=""> + (<ph name="CLIP___">$1s</ph>, <ph name="CLIP___">$2s</ph>) + </message> + <message name="IDS_DEVTOOLS_be97c5beb33f5316b2c221bfbb95852b" desc=""> + MIME Type + </message> + <message name="IDS_DEVTOOLS_bea8bf1ee3b28d900843d6ea1e0440db" desc=""> + Tap Halt + </message> + <message name="IDS_DEVTOOLS_bf4bbfdff02c062ac1a0badec650946d" desc=""> + Async Task + </message> + <message name="IDS_DEVTOOLS_c123b11aa670647408778a3b81a21d70" desc=""> + FPS + </message> + <message name="IDS_DEVTOOLS_c26f31b8ab9b92198caf6894823b14f7" desc=""> + <ph name="HOURS">$1s</ph> h + </message> + <message name="IDS_DEVTOOLS_c4030781aba9b3bf12bc9d7c031b586d" desc=""> + [unattributed] + </message> + <message name="IDS_DEVTOOLS_c472e98c996b5d0a818722fcbe0af52d" desc=""> + Key Character + </message> + <message name="IDS_DEVTOOLS_c5374020999c64f3332f04b296f61a19" desc=""> + <ph name="WIDTH">$1d</ph> × <ph name="HEIGHT">$2d</ph> + </message> + <message name="IDS_DEVTOOLS_c5c7073f423645e437dd5d02419a911a" desc=""> + Mouse Up + </message> + <message name="IDS_DEVTOOLS_c85a251cc457840f1e032f1b733e9398" desc=""> + Timeout + </message> + <message name="IDS_DEVTOOLS_c86fd16c7ad825ebab7026a3e8fa7c4e" desc=""> + Parse Stylesheet + </message> + <message name="IDS_DEVTOOLS_c91e491bb45df4c3796656945c4b86a2" desc=""> + (changed pesudo to "<ph name="INVALIDATION_CHANGEDPSEUDO">$1s</ph>"<ph name="EXTRADATA">$2s</ph>) + </message> + <message name="IDS_DEVTOOLS_cba3eb593893730dfd61ce641be2502a" desc=""> + Network: + </message> + <message name="IDS_DEVTOOLS_cbacb5bbda9c8eeb8e3a7e8e53fbcc59" desc=""> + Timer Fired + </message> + <message name="IDS_DEVTOOLS_cbf04be3b9563f7d53998e76488efb4a" desc=""> + Mouse Move + </message> + <message name="IDS_DEVTOOLS_cc4950eab5e0aaef9820cc6388a97640" desc=""> + Related Node + </message> + <message name="IDS_DEVTOOLS_cdcf2d0d2f648704b8223f9a96ad0b14" desc=""> + Parse HTML + </message> + <message name="IDS_DEVTOOLS_cdfb064314e94077caa817714d943c6f" desc=""> + Elements Affected + </message> + <message name="IDS_DEVTOOLS_ce5bf551379459c1c61d2a204061c455" desc=""> + Location + </message> + <message name="IDS_DEVTOOLS_cf56f8ebb3727b1d4d5a17fb18d4df74" desc=""> + Paint Setup + </message> + <message name="IDS_DEVTOOLS_d0369e883465f2849df8b38966901bbf" desc=""> + CPU: + </message> + <message name="IDS_DEVTOOLS_d07a2a1ecbb76d84f08a686e6c9639ea" desc=""> + Evaluate Module + </message> + <message name="IDS_DEVTOOLS_d0c91aff68287a1a0003af56b91cadde" desc=""> + [<ph name="MIN">$1s</ph> – <ph name="MAX">$2s</ph>] + </message> + <message name="IDS_DEVTOOLS_d14e91fe7abe33fc8a05c193fc812d68" desc=""> + Mime Type + </message> + <message name="IDS_DEVTOOLS_d20caec3b48a1eef164cb4ca81ba2587" desc=""> + L + </message> + <message name="IDS_DEVTOOLS_d24cdb5cd4bcfa9bab80d1fd5dc08b91" desc=""> + <ph name="URL">$1s</ph> [<ph name="STARTLINE____">$2s</ph>…] + </message> + <message name="IDS_DEVTOOLS_d3064df90a9cacec6d462ba65032fd08" desc=""> + CPU profile for a target is not available. + </message> + <message name="IDS_DEVTOOLS_d47c9bd21b8b13b29cb0757777f54d04" desc=""> + Idle Callback Requested + </message> + <message name="IDS_DEVTOOLS_d49a276b363c437fe2446074595fd325" desc=""> + <ph name="REASON">$1s</ph> for + </message> + <message name="IDS_DEVTOOLS_d5b4c38ebb6e58f520e8d1e816ad841e" desc=""> + Stopping timeline… + </message> + <message name="IDS_DEVTOOLS_d5e3345f0d0b507c8993b1ca0e0ac2c4" desc=""> + First Paint + </message> + <message name="IDS_DEVTOOLS_d84fe3f1d290e4855cc0487b5ea18a4a" desc=""> + Pinch Begin + </message> + <message name="IDS_DEVTOOLS_d88a137b62e15eece2884fa04bc36099" desc=""> + <ph name="THIS__STYLE_TITLE">$1s</ph> at <ph name="STARTTIME">$2s</ph> + </message> + <message name="IDS_DEVTOOLS_d97477d6d8a838ead9348185bb5b6742" desc=""> + Thread + </message> + <message name="IDS_DEVTOOLS_da3c710f68f0c891ecad19dcbf2ab349" desc=""> + Console Time + </message> + <message name="IDS_DEVTOOLS_da5b09b6bbef223b458f5a5318c1261d" desc=""> + First Meaningful Paint + </message> + <message name="IDS_DEVTOOLS_dbcc430b9ebc8e22dc874b108f77e4a9" desc=""> + Timings + </message> + <message name="IDS_DEVTOOLS_dc1085228e13a69521f0d08a4f03c304" desc=""> + Call Tree + </message> + <message name="IDS_DEVTOOLS_dc16531c312e4d4c024ffd577d123887" desc=""> + Listeners + </message> + <message name="IDS_DEVTOOLS_dc63e2b8b0f6f66d3dd2dc5d49483eec" desc=""> + Show all records + </message> + <message name="IDS_DEVTOOLS_dd694dc279a5fbefed6a8323c15f4e67" desc=""> + Cancel Idle Callback + </message> + <message name="IDS_DEVTOOLS_dd810137d5737309d18208a7be75773f" desc=""> + Malformed timeline data: Unknown JSON format + </message> + <message name="IDS_DEVTOOLS_dde38f333e095c2293593f504fd701a2" desc=""> + JavaScript Profiler + </message> + <message name="IDS_DEVTOOLS_de1ec1ac3add3d69ffedffd437af7056" desc=""> + Pinch Update + </message> + <message name="IDS_DEVTOOLS_df2c48ebe0a4927e0f33ce3adeaa265b" desc=""> + Range: <ph name="NUMBER_MILLISTOSTRING_STARTOFFSET_">$1s</ph> – <ph name="NUMBER_MILLISTOSTRING_ENDOFFSET_">$2s</ph> + </message> + <message name="IDS_DEVTOOLS_df839b886d238c3ce6de2fa9f9615518" desc=""> + FMP + </message> + <message name="IDS_DEVTOOLS_dfe67b764ba5e3f6b674f049db64e165" desc=""> + First Layout Invalidation + </message> + <message name="IDS_DEVTOOLS_e02d2ae03de9d493df2b6b2d2813d302" desc=""> + Duration + </message> + <message name="IDS_DEVTOOLS_e0c70bcb54d7f58615eb895c232049ce" desc=""> + Composite Layers + </message> + <message name="IDS_DEVTOOLS_e1851406e1e939d1ddaf625e577d6731" desc=""> + <ph name="MINUTES">$1s</ph> m + </message> + <message name="IDS_DEVTOOLS_e2daed94bbd6483ac087b1da9a06e3fd" desc=""> + <ph name="NUMBER_PRECISEMILLISTOSTRING_FRAME_DURATION____">$1s</ph> ~ <ph name="_______FRAME_DURATION">$2.0f</ph> fps + </message> + <message name="IDS_DEVTOOLS_e599161956d626eda4cb0a5ffb85271c" desc=""> + Idle + </message> + <message name="IDS_DEVTOOLS_e5cfc515f312c9e85f367e9854d9963e" desc=""> + Digest + </message> + <message name="IDS_DEVTOOLS_e6dd8524d6da96536b22201a9a46285a" desc=""> + GPU Memory + </message> + <message name="IDS_DEVTOOLS_e77edad5ae632de2e062ef4bb6c80d8a" desc=""> + took <ph name="NUMBER_MILLISTOSTRING_EVENT_DURATION__TRUE_">$1s</ph>. + </message> + <message name="IDS_DEVTOOLS_e88587c08bb701308040c1d45394ecad" desc=""> + Tap Down + </message> + <message name="IDS_DEVTOOLS_ea972b3952b64289353946d365786435" desc=""> + Encrypt Reply + </message> + <message name="IDS_DEVTOOLS_eaeb30f9f18e0c50b178676f3eaef45f" desc=""> + Task + </message> + <message name="IDS_DEVTOOLS_ebd9bec4d70abc789d439c1f136b0538" desc=""> + Layout + </message> + <message name="IDS_DEVTOOLS_ec21eddec143497cea80ab45444a5dab" desc=""> + Owner Element + </message> + <message name="IDS_DEVTOOLS_ecfc2dffe568c10a67dbc6d3724cfde2" desc=""> + Activity + </message> + <message name="IDS_DEVTOOLS_ed3fec59c125d9d20096de997602a46d" desc=""> + Remove Timer + </message> + <message name="IDS_DEVTOOLS_ee1532a0110d6e08d330eca2f822a8c1" desc=""> + Interactions + </message> + <message name="IDS_DEVTOOLS_eecac07978e7842e41f7dbc578482368" desc=""> + Produced Cache Size + </message> + <message name="IDS_DEVTOOLS_ef5db075f5ef10fbe063c7108aa49b25" desc=""> + <ph name="DOMAIN">$1s</ph> #<ph name="SEQUENCENUMBER">$2d</ph> + </message> + <message name="IDS_DEVTOOLS_f17085a56d199cb15adf7c101d611bcc" desc=""> + (changed class to "<ph name="INVALIDATION_CHANGEDCLASS">$1s</ph>"<ph name="EXTRADATA">$2s</ph>) + </message> + <message name="IDS_DEVTOOLS_f34ebd9ed4156c54fbd77bb3a5b3107a" desc=""> + Save profile… + </message> + <message name="IDS_DEVTOOLS_f466ef0697891303497dfbf951a14b1d" desc=""> + Idle Frame + </message> + <message name="IDS_DEVTOOLS_f4843c1c797abf1a256c8802b6cd9f51" desc=""> + Dimensions + </message> + <message name="IDS_DEVTOOLS_f4af86c1492aed890460419da6d5e5e9" desc=""> + <ph name="NUMBER_BYTESTOSTRING_MINUSEDHEAPSIZE_">$1s</ph> – <ph name="NUMBER_BYTESTOSTRING_MAXUSEDHEAPSIZE_">$2s</ph> + </message> + <message name="IDS_DEVTOOLS_f5baffc95ebfe1ede488388589db922b" desc=""> + Other Invalidations + </message> + <message name="IDS_DEVTOOLS_fa7c73b6eb5f3c3b77e47d8a4557af3e" desc=""> + Load profile… + </message> + <message name="IDS_DEVTOOLS_faa313428f0d69de3acffbd44c3df1ec" desc=""> + Enable advanced paint instrumentation (slow) + </message> + <message name="IDS_DEVTOOLS_fb29a86861ace71b3d0203222b687dc0" desc=""> + Digest Reply + </message> + <message name="IDS_DEVTOOLS_fc763cb31e9938f37737394681228f83" desc=""> + , + </message> + <message name="IDS_DEVTOOLS_fd87735db5aee919b6f95f0413a5f542" desc=""> + Forced reflow + </message> + <message name="IDS_DEVTOOLS_feab2dfada0f566072a2a5c3268c2b02" desc=""> + Subframe + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/timeline_model/timeline_model_strings.grdp b/third_party/blink/renderer/devtools/front_end/timeline_model/timeline_model_strings.grdp new file mode 100644 index 0000000..8e9b291a --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/timeline_model/timeline_model_strings.grdp
@@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_3f2fac4932c34252407760c51ae69add" desc=""> + Two flings at the same time? <ph name="FLINGSTART_STARTTIME">$1s</ph> vs <ph name="EVENT_STARTTIME">$2s</ph> + </message> + <message name="IDS_DEVTOOLS_939f0ea548384887196004acbb969c45" desc=""> + Two touches at the same time? <ph name="TOUCHSTART_STARTTIME">$1s</ph> vs <ph name="EVENT_STARTTIME">$2s</ph> + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/ui/ui_strings.grdp b/third_party/blink/renderer/devtools/front_end/ui/ui_strings.grdp new file mode 100644 index 0000000..cd35e68 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/ui/ui_strings.grdp
@@ -0,0 +1,291 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_00618c7a664449da0ec12190348c685a" desc=""> + Switch between files with the same name and different extensions. + </message> + <message name="IDS_DEVTOOLS_0118d8300f0ad71843ef9f47acca779f" desc=""> + Close others + </message> + <message name="IDS_DEVTOOLS_02b411e36e8eaa1f554ca176a106a79d" desc=""> + <ph name="MEGABYTES">$1.0f</ph> MB + </message> + <message name="IDS_DEVTOOLS_0c89face91afb1a048a34349404d11c0" desc=""> + Add selection to watch + </message> + <message name="IDS_DEVTOOLS_0cbca9a34ab68b4be10dd4d09dd61bfd" desc=""> + Search previous + </message> + <message name="IDS_DEVTOOLS_0d76841780a2811f3c24a4f8faf129d0" desc=""> + Show previous/next recording + </message> + <message name="IDS_DEVTOOLS_0ebe6df8a3ac338e0512acc741823fdb" desc=""> + Replace + </message> + <message name="IDS_DEVTOOLS_0f8854fb5bc175b0cd33a1e8518b366f" desc=""> + Switch to pan mode + </message> + <message name="IDS_DEVTOOLS_10f0bad7213cafe18fb1cf55180a11da" desc=""> + (async) + </message> + <message name="IDS_DEVTOOLS_1299e7f10b9d0110e7fa5368d1307500" desc=""> + long text was truncated (<ph name="TOTALBYTES">$1s</ph>) + </message> + <message name="IDS_DEVTOOLS_16d0b9499edfdb8274382a91686ae1ae" desc=""> + Performance Panel + </message> + <message name="IDS_DEVTOOLS_17d440bf27df66479f0fb39cb4f4ad09" desc=""> + Reset view + </message> + <message name="IDS_DEVTOOLS_1d5f9d3b8b2be8824c18022f024a43a0" desc=""> + Decrement value + </message> + <message name="IDS_DEVTOOLS_21e2320215eb46d452e7494f3dd1c798" desc=""> + Next/previous property + </message> + <message name="IDS_DEVTOOLS_2c0924faed417c521b57d553c678ec21" desc=""> + Step into + </message> + <message name="IDS_DEVTOOLS_2dfef1e9ae6e4da36eb0bbeea94742b9" desc=""> + <ph name="MEGABYTES">$1.1f</ph> MB + </message> + <message name="IDS_DEVTOOLS_2ea54663ae9e3a586132a34a98d85ccf" desc=""> + Async Call + </message> + <message name="IDS_DEVTOOLS_3a39eb38e879f66d1c57dedd478272da" desc=""> + Open in new tab + </message> + <message name="IDS_DEVTOOLS_3b41735478b3a3fd8bcc06f6c7a6b56c" desc=""> + Copy link address + </message> + <message name="IDS_DEVTOOLS_3b5f1c7ab5345e75ee764983f8091933" desc=""> + Pan or rotate up/down + </message> + <message name="IDS_DEVTOOLS_3b9dc6454ee96394b3d853e8d597ebc6" desc=""> + Increment value + </message> + <message name="IDS_DEVTOOLS_3f0b6654f9648ab6331823837c2b9f73" desc=""> + Step over + </message> + <message name="IDS_DEVTOOLS_3f9eccbca028a6949c39933d13f82e56" desc=""> + Step out + </message> + <message name="IDS_DEVTOOLS_44ac014b674d7d86a04702e6fd1fa858" desc=""> + Reconnect when ready by reopening DevTools. + </message> + <message name="IDS_DEVTOOLS_47df0ee8f6dc4f553c907c49e686216c" desc=""> + Memory Panel + </message> + <message name="IDS_DEVTOOLS_47e0270ab1827aab8faa1c85d89bd48f" desc=""> + <ph name="UI_KEYBOARDSHORTCUT_SHORTCUTTOSTRING_____UI_KEYBOARDSHORTCUT_MODIFIERS_CTRLORMETA_">$1s</ph>Click to select multiple types + </message> + <message name="IDS_DEVTOOLS_4819fdb79641baf4a4c8a2ca2159a312" desc=""> + <ph name="BYTES">$1.0f</ph> B + </message> + <message name="IDS_DEVTOOLS_48f12760504bf8e958a4bdde56d4fa46" desc=""> + 1 match + </message> + <message name="IDS_DEVTOOLS_4b50fa6fd1a6a30c9b16f71dd2600574" desc=""> + Jump to next editing location + </message> + <message name="IDS_DEVTOOLS_4c4306efb0e40e97e5f8693613b1fcfd" desc=""> + Go to matching bracket + </message> + <message name="IDS_DEVTOOLS_4f348d8d1f134f0980102a4a6508cd5e" desc=""> + Pan or rotate left/right + </message> + <message name="IDS_DEVTOOLS_52ebc26c2921d5b84fc670dff9891821" desc=""> + Zoom out + </message> + <message name="IDS_DEVTOOLS_534d1b2eaff704d4888de7c4a5e282c0" desc=""> + Debugging connection was closed. Reason: + </message> + <message name="IDS_DEVTOOLS_5372591390f99dcf8e0467c671abbc23" desc=""> + Switch to rotate mode + </message> + <message name="IDS_DEVTOOLS_56797cefb1efc9130f7c48a7d1db0f0c" desc=""> + Panels + </message> + <message name="IDS_DEVTOOLS_5ccb2f9327ce0aba7567b62e9e1d15a5" desc=""> + Close tabs to the right + </message> + <message name="IDS_DEVTOOLS_5d3d95cb74ad59528ab385023f8a2a39" desc=""> + Save profile + </message> + <message name="IDS_DEVTOOLS_63e29f78b2e7788d9234a5790897fa71" desc=""> + DevTools was disconnected from the page. + </message> + <message name="IDS_DEVTOOLS_650654cb12c12b00e68b4384e0aede82" desc=""> + <ph name="THIS__ONLYCOMPLETION_TEXT">$1s</ph>, suggestion + </message> + <message name="IDS_DEVTOOLS_678b7bbae3b9b67cee8bce1fac3067d7" desc=""> + Full list of DevTools keyboard shortcuts and gestures + </message> + <message name="IDS_DEVTOOLS_6a5fa3625d6317cd74f686720d9c411e" desc=""> + Promise rejected + </message> + <message name="IDS_DEVTOOLS_6e0e121820384f135321cb766273f4da" desc=""> + Soft undo + </message> + <message name="IDS_DEVTOOLS_6ed5ccb02cd39be4a7a98739f5696d43" desc=""> + Record page reload + </message> + <message name="IDS_DEVTOOLS_7102e4c0bf381bdbaa934e3dccb5b283" desc=""> + (anonymous) + </message> + <message name="IDS_DEVTOOLS_71fc9f874ad2b8e691e9e797eda7d353" desc=""> + Expand/collapse + </message> + <message name="IDS_DEVTOOLS_728618db1e2c850d3f7363ff2768d6b6" desc=""> + Increment CSS unit by 10 + </message> + <message name="IDS_DEVTOOLS_7423ba80f2fff2568d2c642c6be84ede" desc=""> + Close drawer + </message> + <message name="IDS_DEVTOOLS_75cfe68daf4ccd62d15e9e0fb5ec1097" desc=""> + Increment CSS unit by 1 + </message> + <message name="IDS_DEVTOOLS_76f8c7ad696be0b330b46afe79ac279d" desc=""> + Start/stop recording + </message> + <message name="IDS_DEVTOOLS_79fb17b82d0adb283dc78efc0d7f73e8" desc=""> + Temporarily toggle pan/rotate mode while held + </message> + <message name="IDS_DEVTOOLS_7b91156d64b76a5dda815937fce9119d" desc=""> + Zoom in + </message> + <message name="IDS_DEVTOOLS_7cf206a681131cf4d86fc190f2d9ad27" desc=""> + Reconnect DevTools + </message> + <message name="IDS_DEVTOOLS_7dce122004969d56ae2e0245cb754d35" desc=""> + Edit + </message> + <message name="IDS_DEVTOOLS_84e1d403df34bad00840ee636021698c" desc=""> + Close <ph name="THIS_TITLE">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_860429066968657205b314b6b4143da7" desc=""> + Layers Panel + </message> + <message name="IDS_DEVTOOLS_86e8f8f8327d28b74e5bd3ab581f77ee" desc=""> + e.g. /small[\d]+/ url:a.com/b + </message> + <message name="IDS_DEVTOOLS_89345110b204ed302eddff2ddbd0f4d9" desc=""> + Toggle breakpoint enabled + </message> + <message name="IDS_DEVTOOLS_894dab8359b886762113f6b64ce9f107" desc=""> + Replace all + </message> + <message name="IDS_DEVTOOLS_8e44b2127a4fb456a78feced6731a496" desc=""> + <ph name="CURRENTMATCHINDEX____">$1d</ph> of <ph name="MATCHES">$2d</ph> + </message> + <message name="IDS_DEVTOOLS_925f3a6eef3896d617fc0ab413f9c123" desc=""> + <ph name="MATCHES">$1d</ph> matches + </message> + <message name="IDS_DEVTOOLS_92d347b9338f3ffaa227ee482078bbb7" desc=""> + Toggle comment + </message> + <message name="IDS_DEVTOOLS_966f6f045ff62d8c920c755930f4fd7b" desc=""> + Toggle edit as HTML + </message> + <message name="IDS_DEVTOOLS_96ec2a08daf01bc10adc6e4ac4c76ceb" desc=""> + Decrement CSS unit by 10 + </message> + <message name="IDS_DEVTOOLS_96fb9e0d650af5b1fc4ec6c7bc11b49b" desc=""> + More Tools + </message> + <message name="IDS_DEVTOOLS_9f52d2760e4266c7904c59fd9d3e7321" desc=""> + Pick a recording from history + </message> + <message name="IDS_DEVTOOLS_9f98ff6e7e9fd0475daeb2005234ab5d" desc=""> + <ph name="KILOBYTES">$1.0f</ph> KB + </message> + <message name="IDS_DEVTOOLS_a7659dc1b20557ca85c11efc57ace59f" desc=""> + Toggle all breakpoints + </message> + <message name="IDS_DEVTOOLS_a950da8e902568f9a6879abe4313efe7" desc=""> + Once page is reloaded, DevTools will automatically reconnect. + </message> + <message name="IDS_DEVTOOLS_addec426932e71323700afa1911f8f1c" desc=""> + more + </message> + <message name="IDS_DEVTOOLS_ae240dc70adad29732bb1fdf0c746b84" desc=""> + <ph name="KILOBYTES">$1.1f</ph> KB + </message> + <message name="IDS_DEVTOOLS_b014fff4db17dba07ddb6ea5efafd32e" desc=""> + Jump to previous/next frame + </message> + <message name="IDS_DEVTOOLS_b1402575685f74c0c38dabac64e95cc0" desc=""> + Navigate elements + </message> + <message name="IDS_DEVTOOLS_b228e7bd736e688236ab3aa37996bf8f" desc=""> + Decrement by <ph name="__">$1f</ph> + </message> + <message name="IDS_DEVTOOLS_b79165bf6163186253ed04568e1aee11" desc=""> + Pause/ Continue + </message> + <message name="IDS_DEVTOOLS_b79f0c59be8253d3acb4515071312bda" desc=""> + Hide <ph name="THIS__SHOWHIDESIDEBARBUTTONTITLE">$1s</ph> + </message> + <message name="IDS_DEVTOOLS_b7ad6a024765bbfbff22dedf9afe0d17" desc=""> + Jump to previous editing location + </message> + <message name="IDS_DEVTOOLS_bc39d641a1e16fb73f2ce5520d250ed0" desc=""> + Go to member + </message> + <message name="IDS_DEVTOOLS_bd474df0d4b1bb32aac1b31560b962fb" desc=""> + Next/previous call frame + </message> + <message name="IDS_DEVTOOLS_c449b64ade0e464abfc5cb5368775233" desc=""> + Decrement CSS unit by 1 + </message> + <message name="IDS_DEVTOOLS_d06337cfbcc777e0a7caa50ef1a9986a" desc=""> + More tabs + </message> + <message name="IDS_DEVTOOLS_d2923d7d060c61c17d06c22166b2be41" desc=""> + Promise resolved + </message> + <message name="IDS_DEVTOOLS_d9f57fb1f634a4e047fd69b574434c7f" desc=""> + Evaluate selection in console + </message> + <message name="IDS_DEVTOOLS_dd73c24f4702950125e2fcb7d26ca5fe" desc=""> + Show more (<ph name="TOTALBYTES">$1s</ph>) + </message> + <message name="IDS_DEVTOOLS_dd92c3884d43902407a4c2f0d8cc0eb1" desc=""> + Toggle breakpoint + </message> + <message name="IDS_DEVTOOLS_e0aa021e21dddbd6d8cecec71e9cf564" desc=""> + OK + </message> + <message name="IDS_DEVTOOLS_e0f1691bdb67d9859e5a6a8d7c26e6a1" desc=""> + Text Editor + </message> + <message name="IDS_DEVTOOLS_e118bd20c49240fd8387f3bd901cb4f1" desc=""> + Load profile + </message> + <message name="IDS_DEVTOOLS_e6290b661dba9591e4c505fb50257d0c" desc=""> + Search next + </message> + <message name="IDS_DEVTOOLS_e7a555523728cc11719011fa5a7e77ba" desc=""> + Select next occurrence + </message> + <message name="IDS_DEVTOOLS_e81c4e4f2b7b93b481e13a8553c2ae1b" desc=""> + or + </message> + <message name="IDS_DEVTOOLS_e9947a82726be2fb77368eb27c082402" desc=""> + (no item selected) + </message> + <message name="IDS_DEVTOOLS_f68d3333dcde01f3ef29184f1bcdf1c5" desc=""> + never show + </message> + <message name="IDS_DEVTOOLS_f6c46678b34ad4b4c0241c9487a26b59" desc=""> + Increment by <ph name="__">$1f</ph> + </message> + <message name="IDS_DEVTOOLS_f8fbc6412a360fc4f854f34a776e2af2" desc=""> + Another profiler is already active + </message> + <message name="IDS_DEVTOOLS_fa66e32280e1ee04b8e8cd36626b65f0" desc=""> + Close editor tab + </message> + <message name="IDS_DEVTOOLS_fbbbb283efc814825613301c22951ba7" desc=""> + Close all + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/web_audio/web_audio_strings.grdp b/third_party/blink/renderer/devtools/front_end/web_audio/web_audio_strings.grdp new file mode 100644 index 0000000..665fadf --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/web_audio/web_audio_strings.grdp
@@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_13d286ca90ba61a4151f3dcb6e353cc8" desc=""> + OfflineAudioContext + </message> + <message name="IDS_DEVTOOLS_28fce67b0d0976eaca9b69748126a6d2" desc=""> + Open a page that uses Web Audio API to start monitoring. + </message> + <message name="IDS_DEVTOOLS_40097404a926dce6324e58f598bd7dcb" desc=""> + Render Capacity + </message> + <message name="IDS_DEVTOOLS_40734192aacef5d658541080315dd644" desc=""> + Callback Buffer Size + </message> + <message name="IDS_DEVTOOLS_545e39748691e8a65093c525011a321b" desc=""> + Max Output Channels + </message> + <message name="IDS_DEVTOOLS_5f8695ebb8bc9a78c593ee7bfae153a5" desc=""> + AudioContext + </message> + <message name="IDS_DEVTOOLS_b78dc7712ef83a078c1c68822d2a1a3f" desc=""> + BaseAudioContexts + </message> + <message name="IDS_DEVTOOLS_f047f03535a9154caf9a858b5aed17c0" desc=""> + Current Time + </message> + <message name="IDS_DEVTOOLS_f579f693ac9ecb3fb9e822bf32028e13" desc=""> + Sample Rate + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/workspace/workspace_strings.grdp b/third_party/blink/renderer/devtools/front_end/workspace/workspace_strings.grdp new file mode 100644 index 0000000..a38a4055 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/workspace/workspace_strings.grdp
@@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_DEVTOOLS_818fc883495655418c9124800c52b7ee" desc=""> + This file was changed externally. Would you like to reload it? + </message> +</grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/package.json b/third_party/blink/renderer/devtools/package.json index 4a01845..2c03d53e 100644 --- a/third_party/blink/renderer/devtools/package.json +++ b/third_party/blink/renderer/devtools/package.json
@@ -15,6 +15,7 @@ "check-gn": "node scripts/check_gn.js", "check-json": "node scripts/json_validator/validate_module_json.js", "check-loc": "node scripts/check_localizability.js -a", + "check-grdp": "node scripts/check_localizable_resources.js", "generate-jsconfig": "node scripts/generate_jsconfig.js" }, "repository": {
diff --git a/third_party/blink/renderer/devtools/scripts/check_localizability.js b/third_party/blink/renderer/devtools/scripts/check_localizability.js index 963eb49..30102a70 100644 --- a/third_party/blink/renderer/devtools/scripts/check_localizability.js +++ b/third_party/blink/renderer/devtools/scripts/check_localizability.js
@@ -11,21 +11,11 @@ // In this case, add it to the excluded errors at the top of the script. const path = require('path'); +const localizationUtils = require('./localization_utils/localization_utils'); +const esprimaTypes = localizationUtils.esprimaTypes; +const escodegen = localizationUtils.escodegen; +const esprima = localizationUtils.esprima; -// Use modules in third_party/node/node_modules -const THIRD_PARTY_PATH = path.resolve(__dirname, '..', '..', '..', '..'); -const REPO_NODE_MODULES_PATH = path.resolve(THIRD_PARTY_PATH, 'node', 'node_modules'); -const escodegen = require(path.resolve(REPO_NODE_MODULES_PATH, 'escodegen')); -const esprima = require(path.resolve(REPO_NODE_MODULES_PATH, 'esprima')); - -const fs = require('fs'); -const {promisify} = require('util'); -const readDirAsync = promisify(fs.readdir); -const readFileAsync = promisify(fs.readFile); -const statAsync = promisify(fs.stat); - -const excludeFiles = ['lighthouse-dt-bundle.js', 'Tests.js']; -const excludeDirs = ['_test_runner', 'Images', 'node_modules']; // Exclude known errors const excludeErrors = [ 'Common.UIString(view.title())', 'Common.UIString(setting.title() || \'\')', 'Common.UIString(option.text)', @@ -34,16 +24,6 @@ 'Common.UIString(extension.title())', 'Common.UIString(this._currentValueLabel, value)' ]; -const esprimaTypes = { - BI_EXPR: 'BinaryExpression', - CALL_EXPR: 'CallExpression', - COND_EXPR: 'ConditionalExpression', - IDENTIFIER: 'Identifier', - MEMBER_EXPR: 'MemberExpression', - TAGGED_TEMP_EXPR: 'TaggedTemplateExpression', - TEMP_LITERAL: 'TemplateLiteral' -}; - const usage = `Usage: node ${path.basename(process.argv[0])} [-a | <.js file path>*] -a: If present, check all devtools frontend .js files @@ -62,7 +42,7 @@ let filePaths = []; if (process.argv[2] === '-a') { const frontendPath = path.resolve(__dirname, '..', 'front_end'); - await getFilesFromDirectory(frontendPath, filePaths); + await localizationUtils.getFilesFromDirectory(frontendPath, filePaths, ['.js']); } else { filePaths = process.argv.slice(2); } @@ -86,73 +66,15 @@ main(); -function verifyIdentifier(node, name) { - return node !== undefined && node.type === esprimaTypes.IDENTIFIER && node.name === name; -} - -/** - * Verify callee of objectName.propertyName(), e.g. Common.UIString(). - */ -function verifyCallExpressionCallee(callee, objectName, propertyName) { - return callee !== undefined && callee.type === esprimaTypes.MEMBER_EXPR && callee.computed === false && - verifyIdentifier(callee.object, objectName) && verifyIdentifier(callee.property, propertyName); -} - -function isNodeCallOnObject(node, objectName, propertyName) { - return node !== undefined && node.type === esprimaTypes.CALL_EXPR && - verifyCallExpressionCallee(node.callee, objectName, propertyName); -} - -function isNodeCommonUIStringCall(node) { - return isNodeCallOnObject(node, 'Common', 'UIString'); -} - -function isNodeUIformatLocalized(node) { - return isNodeCallOnObject(node, 'UI', 'formatLocalized'); -} - -function isNodelsTaggedTemplateExpression(node) { - return node !== undefined && node.type === esprimaTypes.TAGGED_TEMP_EXPR && verifyIdentifier(node.tag, 'ls') && - node.quasi !== undefined && node.quasi.type !== undefined && node.quasi.type === esprimaTypes.TEMP_LITERAL; -} - function includesConditionalExpression(listOfElements) { return listOfElements.filter(ele => ele !== undefined && ele.type === esprimaTypes.COND_EXPR).length > 0; } -function getLocalizationCase(node) { - if (isNodeCommonUIStringCall(node)) - return 'Common.UIString'; - else if (isNodelsTaggedTemplateExpression(node)) - return 'Tagged Template'; - else if (isNodeUIformatLocalized(node)) - return 'UI.formatLocalized'; - else - return null; -} - -function isLocalizationCall(node) { - return isNodeCommonUIStringCall(node) || isNodelsTaggedTemplateExpression(node) || isNodeUIformatLocalized(node); -} - function addError(error, errors) { if (!errors.includes(error)) errors.push(error); } -function getLocation(node) { - if (node !== undefined && node.loc !== undefined && node.loc.start !== undefined && node.loc.end !== undefined && - node.loc.start.line !== undefined && node.loc.end.line !== undefined) { - const startLine = node.loc.start.line; - const endLine = node.loc.end.line; - if (startLine === endLine) - return ` Line ${startLine}`; - else - return ` Line ${node.loc.start.line}-${node.loc.end.line}`; - } - return ''; -} - function buildConcatenatedNodesList(node, nodes) { if (!node) return; @@ -173,7 +95,7 @@ */ function checkConcatenation(parentNode, node, filePath, errors) { function isWord(node) { - return (node.type === 'Literal' && !!node.value.match(/[a-z]/i)); + return (node.type === esprimaTypes.LITERAL && !!node.value.match(/[a-z]/i)); } function isConcatenation(node) { return (node !== undefined && node.type === esprimaTypes.BI_EXPR && node.operator === '+'); @@ -183,16 +105,18 @@ return; if (isConcatenation(node)) { - let concatenatedNodes = []; + const concatenatedNodes = []; buildConcatenatedNodesList(node, concatenatedNodes); - const hasLocalizationCall = !!concatenatedNodes.find(currentNode => isLocalizationCall(currentNode)); + const hasLocalizationCall = + !!concatenatedNodes.find(currentNode => localizationUtils.isLocalizationCall(currentNode)); if (hasLocalizationCall) { const hasAlphabeticLiteral = !!concatenatedNodes.find(currentNode => isWord(currentNode)); if (hasAlphabeticLiteral) { const code = escodegen.generate(node); addError( `${filePath}${ - getLocation(node)}: string concatenation should be changed to variable substitution with ls: ${code}`, + localizationUtils.getLocationMessage( + node.loc)}: string concatenation should be changed to variable substitution with ls: ${code}`, errors); } } @@ -200,26 +124,18 @@ } /** - * Verify if callee is functionName() or object.functionName(). - */ -function verifyFunctionCallee(callee, functionName) { - return callee !== undefined && - ((callee.type === esprimaTypes.IDENTIFIER && callee.name === functionName) || - (callee.type === esprimaTypes.MEMBER_EXPR && verifyIdentifier(callee.property, functionName))); -} - -/** * Check if an argument of a function is localized. */ function checkFunctionArgument(functionName, argumentIndex, node, filePath, errors) { - if (node !== undefined && node.type === esprimaTypes.CALL_EXPR && verifyFunctionCallee(node.callee, functionName) && - node.arguments !== undefined && node.arguments.length > argumentIndex) { + if (node !== undefined && node.type === esprimaTypes.CALL_EXPR && + localizationUtils.verifyFunctionCallee(node.callee, functionName) && node.arguments !== undefined && + node.arguments.length > argumentIndex) { const arg = node.arguments[argumentIndex]; // No need to localize empty strings. - if (arg.type == 'Literal' && arg.value === '') + if (arg.type === esprimaTypes.LITERAL && arg.value === '') return; - if (!isLocalizationCall(arg)) { + if (!localizationUtils.isLocalizationCall(arg)) { let order = ''; switch (argumentIndex) { case 0: @@ -235,8 +151,8 @@ order = `${argumentIndex + 1}th`; } addError( - `${filePath}${getLocation(node)}: ${order} argument to ${functionName}() should be localized: ${ - escodegen.generate(node)}`, + `${filePath}${localizationUtils.getLocationMessage(node.loc)}: ${order} argument to ${ + functionName}() should be localized: ${escodegen.generate(node)}`, errors); } } @@ -266,19 +182,22 @@ return; } - const locCase = getLocalizationCase(node); + const locCase = localizationUtils.getLocalizationCase(node); const code = escodegen.generate(node); switch (locCase) { case 'Common.UIString': case 'UI.formatLocalized': const firstArgType = node.arguments[0].type; - if (firstArgType !== 'Literal' && firstArgType !== 'TemplateLiteral' && firstArgType !== 'Identifier' && - !excludeErrors.includes(code)) { - addError(`${filePath}${getLocation(node)}: first argument to call should be a string: ${code}`, errors); + if (firstArgType !== esprimaTypes.LITERAL && firstArgType !== esprimaTypes.TEMP_LITERAL && + firstArgType !== esprimaTypes.IDENTIFIER && !excludeErrors.includes(code)) { + addError( + `${filePath}${localizationUtils.getLocationMessage(node.loc)}: first argument to call should be a string: ${ + code}`, + errors); } if (includesConditionalExpression(node.arguments.slice(1))) { addError( - `${filePath}${getLocation(node)}: conditional(s) found in ${ + `${filePath}${localizationUtils.getLocationMessage(node.loc)}: conditional(s) found in ${ code}. Please extract conditional(s) out of the localization call.`, errors); } @@ -286,7 +205,7 @@ case 'Tagged Template': if (includesConditionalExpression(node.quasi.expressions)) { addError( - `${filePath}${getLocation(node)}: conditional(s) found in ${ + `${filePath}${localizationUtils.getLocationMessage(node.loc)}: conditional(s) found in ${ code}. Please extract conditional(s) out of the localization call.`, errors); } @@ -303,42 +222,11 @@ } } -function getRelativeFilePathFromSrc(fullFilePath) { - return path.relative(path.resolve(THIRD_PARTY_PATH, '..'), fullFilePath); -} - async function auditFileForLocalizability(filePath, errors) { - const fileContent = await readFileAsync(filePath); - const ast = esprima.parse(fileContent.toString(), {loc: true}); + const fileContent = await localizationUtils.parseFileContent(filePath); + const ast = esprima.parse(fileContent, {loc: true}); - const relativeFilePath = getRelativeFilePathFromSrc(filePath); + const relativeFilePath = localizationUtils.getRelativeFilePathFromSrc(filePath); for (const node of ast.body) analyzeNode(undefined, node, relativeFilePath, errors); } - -function shouldParseDirectory(directoryName) { - return !excludeDirs.reduce((result, dir) => result || directoryName.indexOf(dir) !== -1, false); -} - -function shouldParseFile(filePath) { - return (path.extname(filePath) === '.js' && !excludeFiles.includes(path.basename(filePath))); -} - -async function getFilesFromItem(itemPath, filePaths) { - const stat = await statAsync(itemPath); - if (stat.isDirectory() && shouldParseDirectory(itemPath)) - return await getFilesFromDirectory(itemPath, filePaths); - - if (shouldParseFile(itemPath)) - filePaths.push(itemPath); -} - -async function getFilesFromDirectory(directoryPath, filePaths) { - const itemNames = await readDirAsync(directoryPath); - const promises = []; - for (const itemName of itemNames) { - const itemPath = path.resolve(directoryPath, itemName); - promises.push(getFilesFromItem(itemPath, filePaths)); - } - await Promise.all(promises); -}
diff --git a/third_party/blink/renderer/devtools/scripts/check_localizable_resources.js b/third_party/blink/renderer/devtools/scripts/check_localizable_resources.js new file mode 100644 index 0000000..946cbcf --- /dev/null +++ b/third_party/blink/renderer/devtools/scripts/check_localizable_resources.js
@@ -0,0 +1,240 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Copyright (C) Microsoft Corporation. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * This script is part of the presubmit check that parses DevTools frontend .js and + * module.json files, collects localizable strings, checks if frontend strings are + * in .grd/.grdp files and reports error if present. + * + * If argument '--autofix' is present, add the new resources to and remove unused + * messages from GRDP files. + */ + +const fs = require('fs'); +const path = require('path'); +const {promisify} = require('util'); +const writeFileAsync = promisify(fs.writeFile); +const appendFileAsync = promisify(fs.appendFile); +const checkLocalizedStrings = require('./localization_utils/check_localized_strings'); +const localizationUtils = require('./localization_utils/localization_utils'); + +const grdpFileStart = '<?xml version="1.0" encoding="utf-8"?>\n<grit-part>\n'; +const grdpFileEnd = '</grit-part>'; + +async function main() { + let frontendStrings; + let IDSkeys; + + try { + [frontendStrings, IDSkeys] = await checkLocalizedStrings.parseLocalizableResourceMaps(false); + + if (process.argv.includes('--autofix')) { + await autofix(frontendStrings, IDSkeys); + } else { + await getErrors(frontendStrings, IDSkeys); + } + } catch (e) { + console.log(`Error: ${e.message}`); + process.exit(1); + } +} + +main(); + +async function getErrors(frontendStrings, IDSkeys) { + const toAddError = await checkLocalizedStrings.getAndReportResourcesToAdd(frontendStrings, IDSkeys); + const toRemoveError = checkLocalizedStrings.getAndReportResourcesToRemove(frontendStrings, IDSkeys); + let error = `${toAddError ? toAddError : ''}${toRemoveError ? toRemoveError : ''}`; + + if (error === '') { + console.log('DevTools localizable resources checker passed.'); + return; + } + + error += '\nThe errors are potentially fixable with the `--autofix` option.'; + + throw new Error(error); +} + +async function autofix(frontendStrings, IDSkeys) { + const resourceAdded = await addResourcesToGRDP(frontendStrings, IDSkeys); + const resourceRemoved = await removeResourcesFromGRDP(frontendStrings, IDSkeys); + + if (!resourceAdded && !resourceRemoved) { + console.log('DevTools localizable resources checker passed.'); + return; + } + + let message = + 'Found changes to localizable DevTools strings.\nDevTools localizable resources checker has updated the appropriate grdp file(s).'; + if (resourceAdded) + message += '\nManually write a description for any new <message> entries.'; + message += '\nUse git status to see what has changed.'; + throw new Error(message); +} + +// Return true if any resources are added +async function addResourcesToGRDP(frontendStrings, IDSkeys) { + const keysToAddToGRD = checkLocalizedStrings.getDifference(IDSkeys, frontendStrings); + if (keysToAddToGRD.size === 0) + return false; + + const frontendPath = path.resolve(__dirname, '..', 'front_end'); + const frontendDirs = await localizationUtils.getChildDirectoriesFromDirectory(frontendPath); + // Map file path to its parent grdp file path + const filePathToGrdpFilePath = new Map(); + // Map grdp file path to strings to be added to that file so that we only need to + // modify every grdp file once + const grdpFilePathToStrings = new Map(); + + // Get the grdp files that need to be modified + for (const [key, stringObj] of keysToAddToGRD) { + let grdpFilePath = ''; + if (filePathToGrdpFilePath.has(stringObj.filepath)) { + grdpFilePath = filePathToGrdpFilePath.get(stringObj.filepath); + } else { + grdpFilePath = localizationUtils.getGRDPFilePath(stringObj.filepath, frontendDirs); + filePathToGrdpFilePath.set(stringObj.filepath, grdpFilePath); + } + + if (!grdpFilePathToStrings.has(grdpFilePath)) + grdpFilePathToStrings.set(grdpFilePath, []); + + // Add the IDS key to stringObj so we have access to it later + stringObj.ids = key; + grdpFilePathToStrings.get(grdpFilePath).push(stringObj); + } + + const promises = []; + + const grdpFilePathsToAdd = []; + for (let [grdpFilePath, stringsToAdd] of grdpFilePathToStrings) { + // The grdp file doesn't exist, so create one. + if (!fs.existsSync(grdpFilePath)) { + let grdpMessagesToAdd = ''; + for (const stringObj of stringsToAdd) + grdpMessagesToAdd += localizationUtils.createGrdpMessage(stringObj.ids, stringObj); + + // Create a new grdp file and reference it in the parent grd file + promises.push(appendFileAsync(grdpFilePath, `${grdpFileStart}${grdpMessagesToAdd}${grdpFileEnd}`)); + grdpFilePathsToAdd.push( + path.relative(path.dirname(localizationUtils.GRD_PATH), grdpFilePath).split(path.sep).join('/')); + continue; + } + + const grdpFileContent = await localizationUtils.parseFileContent(grdpFilePath); + const grdpFileLines = grdpFileContent.split('\n'); + + let newGrdpFileContent = ''; + const IDSRegex = new RegExp(`"(${localizationUtils.IDSPrefix}.*?)"`); + for (let i = 0; i < grdpFileLines.length; i++) { + const grdpLine = grdpFileLines[i]; + const match = grdpLine.match(IDSRegex); + // match[0]: full match + // match[1]: message IDS key + if (match) { + const ids = match[1]; + const stringsToAddRemaining = []; + for (const stringObj of stringsToAdd) { + // Insert the new <message> in sorted order. + if (ids > stringObj.ids) + newGrdpFileContent += localizationUtils.createGrdpMessage(stringObj.ids, stringObj); + else + stringsToAddRemaining.push(stringObj); + } + stringsToAdd = stringsToAddRemaining; + } else if (grdpLine.includes(grdpFileEnd)) { + // Just hit the end tag, so insert any remaining <message>s. + for (const stringObj of stringsToAdd) + newGrdpFileContent += localizationUtils.createGrdpMessage(stringObj.ids, stringObj); + } + newGrdpFileContent += grdpLine; + if (i < grdpFileLines.length - 1) + newGrdpFileContent += '\n'; + } + + promises.push(writeFileAsync(grdpFilePath, newGrdpFileContent)); + } + promises.push(addChildGRDPFilePathsToGRD(grdpFilePathsToAdd.sort())); + await Promise.all(promises); + return true; +} + +async function addChildGRDPFilePathsToGRD(relativeGrdpFilePaths) { + function createPartFileEntry(relativeGrdpFilePath) { + return ` <part file="${relativeGrdpFilePath}" />\n`; + } + + const grdFileContent = await localizationUtils.parseFileContent(localizationUtils.GRD_PATH); + const grdLines = grdFileContent.split('\n'); + + let newGrdFileContent = ''; + for (let i = 0; i < grdLines.length; i++) { + const grdLine = grdLines[i]; + // match[0]: full match + // match[1]: relative grdp file path + const match = grdLine.match(/<part file="(.*?)"/); + if (match) { + const relativeGrdpFilePathsRemaining = []; + for (const relativeGrdpFilePath of relativeGrdpFilePaths) { + if (relativeGrdpFilePath < match[1]) + newGrdFileContent += createPartFileEntry(relativeGrdpFilePath); + else + relativeGrdpFilePathsRemaining.push(relativeGrdpFilePath); + } + relativeGrdpFilePaths = relativeGrdpFilePathsRemaining; + } else if (grdLine.includes('</messages>')) { + for (const relativeGrdpFilePath of relativeGrdpFilePaths) + newGrdFileContent += createPartFileEntry(relativeGrdpFilePath); + } + newGrdFileContent += grdLine; + if (i < grdLines.length - 1) + newGrdFileContent += '\n'; + } + return writeFileAsync(localizationUtils.GRD_PATH, newGrdFileContent); +} + +// Return true if any resources are removed +async function removeResourcesFromGRDP(frontendStrings, IDSkeys) { + const keysToRemoveFromGRD = checkLocalizedStrings.getDifference(frontendStrings, IDSkeys); + if (keysToRemoveFromGRD.size === 0) + return false; + + // Map grdp file path to message IDS keys to remove + const grdpFilePathToKeys = new Map(); + for (const [key, messageObj] of keysToRemoveFromGRD) { + if (!grdpFilePathToKeys.has(messageObj.filepath)) + grdpFilePathToKeys.set(messageObj.filepath, []); + + grdpFilePathToKeys.get(messageObj.filepath).push(key); + } + + const promises = []; + for (const [grdpFilePath, listOfKeys] of grdpFilePathToKeys) { + let newGrdpFileContent = ''; + const grdpFileContent = await localizationUtils.parseFileContent(grdpFilePath); + const grdpFileLines = grdpFileContent.split('\n'); + + for (let i = 0; i < grdpFileLines.length; i++) { + if (!lineContainsIDS(grdpFileLines[i], listOfKeys)) { + newGrdpFileContent += grdpFileLines[i]; + if (i < grdpFileLines.length - 1) + newGrdpFileContent += '\n'; + continue; + } + + while (!grdpFileLines[i].includes('</message>')) + i++; + } + + promises.push(writeFileAsync(grdpFilePath, newGrdpFileContent)); + } + await Promise.all(promises); + return true; +} + +function lineContainsIDS(line, listOfIDS) { + return listOfIDS.some(ids => line.includes(ids)); +}
diff --git a/third_party/blink/renderer/devtools/scripts/localization_utils/check_localized_strings.js b/third_party/blink/renderer/devtools/scripts/localization_utils/check_localized_strings.js new file mode 100644 index 0000000..be79c23 --- /dev/null +++ b/third_party/blink/renderer/devtools/scripts/localization_utils/check_localized_strings.js
@@ -0,0 +1,384 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * Functions in this script parse DevTools frontend .js and module.json files, + * collect localizable strings, check if frontend strings are in .grd/.grdp + * files and report error if present. + */ + +const fs = require('fs'); +const path = require('path'); +const {promisify} = require('util'); +const writeFileAsync = promisify(fs.writeFile); +const localizationUtils = require('./localization_utils'); +const escodegen = localizationUtils.escodegen; +const esprimaTypes = localizationUtils.esprimaTypes; +const esprima = localizationUtils.esprima; +const DEVTOOLS_FRONTEND_PATH = path.resolve(__dirname, '..', '..', 'front_end'); +const extensionStringKeys = ['category', 'destination', 'title', 'title-mac']; + +// Format of frontendStrings +// { IDS_md5-hash => { +// string: string, +// code: string, +// filepath: string, +// location: { +// start: { +// line: number, (1-based) +// column: number (0-based) +// }, +// end: { +// line: number, +// column: number +// } +// }, +// arguments: string[] +// } +// } +const frontendStrings = new Map(); + +// Format +// { +// IDS_KEY => { +// filepath: string, +// location: { +// start: { +// line: number +// }, +// end: { +// line: number +// } +// } +// } +// } +const IDSkeys = new Map(); + +const devtoolsFrontendPath = path.resolve(__dirname, '..', '..', 'front_end'); + +async function parseLocalizableResourceMaps(isDebug) { + const devtoolsFiles = []; + await localizationUtils.getFilesFromDirectory(devtoolsFrontendPath, devtoolsFiles, ['.js', 'module.json']); + + const promises = [parseLocalizableStrings(devtoolsFiles, isDebug), parseIDSKeys(localizationUtils.GRD_PATH, isDebug)]; + return Promise.all(promises); +} + +/** + * The following functions parse localizable strings (wrapped in + * Common.UIString, UI.formatLocalized or ls``) from devtools frontend files. + */ + +async function parseLocalizableStrings(devtoolsFiles, isDebug) { + const promises = devtoolsFiles.map(filePath => parseLocalizableStringsFromFile(filePath)); + await Promise.all(promises); + if (isDebug) + await writeFileAsync(path.resolve(__dirname, 'localizable_strings.json'), JSON.stringify(frontendStrings)); + return frontendStrings; +} + +async function parseLocalizableStringsFromFile(filePath) { + const fileContent = await localizationUtils.parseFileContent(filePath); + if (path.basename(filePath) === 'module.json') + return parseLocalizableStringFromModuleJson(fileContent, filePath); + + const ast = esprima.parse(fileContent, {loc: true}); + for (const node of ast.body) + parseLocalizableStringFromNode(node, filePath); +} + +function parseLocalizableStringFromModuleJson(fileContent, filePath) { + const fileJSON = JSON.parse(fileContent); + if (!fileJSON.extensions) + return; + + for (const extension of fileJSON.extensions) { + for (const key in extension) { + if (extensionStringKeys.includes(key)) { + addString(extension[key], extension[key], filePath); + } else if (key === 'device') { + addString(extension.device.title, extension.device.title, filePath); + } else if (key === 'options') { + for (const option of extension.options) { + addString(option.title, option.title, filePath); + if (option.text !== undefined) + addString(option.text, option.text, filePath); + } + } + } + } +} + +function parseLocalizableStringFromNode(node, filePath) { + if (!node) + return; + + if (Array.isArray(node)) { + for (const child of node) + parseLocalizableStringFromNode(child, filePath); + + return; + } + + const keys = Object.keys(node); + const objKeys = keys.filter(key => key !== 'loc' && typeof node[key] === 'object'); + if (objKeys.length === 0) { + // base case: all values are non-objects -> node is a leaf + return; + } + + const locCase = localizationUtils.getLocalizationCase(node); + switch (locCase) { + case 'Common.UIString': + handleCommonUIString(node, filePath); + break; + case 'UI.formatLocalized': + if (node.arguments !== undefined && node.arguments[1] !== undefined && node.arguments[1].elements !== undefined) + handleCommonUIString(node, filePath, node.arguments[1].elements); + break; + case 'Tagged Template': + handleTemplateLiteral(node.quasi, escodegen.generate(node), filePath); + break; + case null: + break; + default: + throw new Error( + `${filePath}${localizationUtils.getLocationMessage(node.loc)}: unexpected localization case for node: ${ + escodegen.generate(node)}`); + } + + for (const key of objKeys) { + // recursively parse all the child nodes + parseLocalizableStringFromNode(node[key], filePath); + } +} + +function handleCommonUIString(node, filePath, argumentNodes) { + if (argumentNodes === undefined) + argumentNodes = node.arguments.slice(1); + const firstArgType = node.arguments[0].type; + switch (firstArgType) { + case esprimaTypes.LITERAL: + const message = node.arguments[0].value; + addString(message, escodegen.generate(node), filePath, node.loc, argumentNodes); + break; + case esprimaTypes.TEMP_LITERAL: + handleTemplateLiteral(node.arguments[0], escodegen.generate(node), filePath, argumentNodes); + break; + default: + break; + } +} + +function handleTemplateLiteral(node, code, filePath, argumentNodes) { + if (node.expressions.length === 0) { + // template literal does not contain any variables, parse the value + addString(node.quasis[0].value.cooked, code, filePath, node.loc, argumentNodes); + return; + } + + argumentNodes = node.expressions; + let processedMsg = ''; + for (let i = 0; i < node.quasis.length; i++) { + processedMsg += node.quasis[i].value.cooked; + if (i < node.expressions.length) { + // add placeholder for variable so that + // the ph tag gets generated + processedMsg += '%s'; + } + } + addString(processedMsg, code, filePath, node.loc, argumentNodes); +} + +function addString(str, code, filePath, location, argumentNodes) { + const currentString = { + string: str, + code: code, + filepath: filePath, + }; + if (location) + currentString.location = location; + if (argumentNodes && argumentNodes.length > 0) + currentString.arguments = argumentNodes.map(argNode => escodegen.generate(argNode)); + + // In the case of duplicates, to enforce that entries are added to + // a consistent GRDP file, we use the file path that sorts lowest as + // the winning entry into frontendStrings. + const ids = localizationUtils.getIDSKey(str); + if (frontendStrings.has(ids) && frontendStrings.get(ids).filepath <= filePath) + return; + frontendStrings.set(ids, currentString); +} + +/** + * The following functions parse <message>s and their IDS keys from + * devtools frontend grdp files. + */ + +async function parseIDSKeys(grdFilePath, isDebug) { + // NOTE: this function assumes that no <message> tags are present in the parent + const grdpFilePaths = await parseGRDFile(grdFilePath); + await parseGRDPFiles(grdpFilePaths); + if (isDebug) + await writeFileAsync(path.resolve(__dirname, 'IDS_Keys.json'), JSON.stringify(IDSkeys)); + return IDSkeys; +} + +async function parseGRDFile(grdFilePath) { + const fileContent = await localizationUtils.parseFileContent(grdFilePath); + const grdFileDir = path.dirname(grdFilePath); + const partFileRegex = /<part file="(.*?)"/g; + + let match; + const grdpFilePaths = new Set(); + while ((match = partFileRegex.exec(fileContent)) !== null) { + if (match.index === partFileRegex.lastIndex) + partFileRegex.lastIndex++; + // match[0]: full match + // match[1]: part file path + grdpFilePaths.add(path.resolve(grdFileDir, match[1])); + } + return grdpFilePaths; +} + +function parseGRDPFiles(grdpFilePaths) { + const promises = Array.from(grdpFilePaths, grdpFilePath => parseGRDPFile(grdpFilePath)); + return Promise.all(promises); +} + +function trimGrdpPlaceholder(placeholder) { + const exampleRegex = new RegExp('<ex>.*?<\/ex>', 'gms'); + // $1s<ex>my example</ex> -> $1s + return placeholder.replace(exampleRegex, '').trim(); +} + +function convertToFrontendPlaceholders(message) { + // <ph name="phname">$1s<ex>my example</ex></ph> and <ph name="phname2">$2.3f</ph> + // match[0]: <ph name="phname1">$1s</ph> + // match[1]: $1s<ex>my example</ex> + let placeholderRegex = new RegExp('<ph[^>]*>(.*?)<\/ph>', 'gms'); + let match; + while ((match = placeholderRegex.exec(message)) !== null) { + const placeholder = match[0]; + const placeholderValue = trimGrdpPlaceholder(match[1]); + const newPlaceholderValue = placeholderValue.replace(/\$[1-9]/, '%'); + message = + message.substring(0, match.index) + newPlaceholderValue + message.substring(match.index + placeholder.length); + // Modified the message, so search from the beginning of the string again. + placeholderRegex.lastIndex = 0; + } + return message; +} + +function trimGrdpMessage(message) { + // ' Message text \n ' trims to ' Message text '. + const fixedLeadingWhitespace = 4; // GRDP encoding uses 4 leading spaces. + const trimmedMessage = message.substring(4); + return trimmedMessage.substring(0, trimmedMessage.lastIndexOf('\n')); +} + +async function parseGRDPFile(filePath) { + const fileContent = await localizationUtils.parseFileContent(filePath); + + function lineNumberOfIndex(str, index) { + const stringToIndex = str.substr(0, index); + return stringToIndex.split('\n').length; + } + + // Example: + // <message name="IDS_*" desc="*"> + // Message text here with optional placeholders <ph name="phname">$1s</ph> + // </message> + // match[0]: the entire '<message>...</message>' block. + // match[1]: ' Message text here with optional placeholders <ph name="phname">$1s</ph>\n ' + const messageRegex = new RegExp('<message[^>]*>\s*\n(.*?)<\/message>', 'gms'); + let match; + while ((match = messageRegex.exec(fileContent)) !== null) { + const line = lineNumberOfIndex(fileContent, match.index); + + let message = match[1]; + message = trimGrdpMessage(message); + message = convertToFrontendPlaceholders(message); + message = localizationUtils.sanitizeStringIntoFrontendFormat(message); + + const ids = localizationUtils.getIDSKey(message); + IDSkeys.set(ids, {filepath: filePath, location: {start: {line}, end: {line}}}); + } +} + +/** + * The following functions compare frontend localizable strings + * with grdp <message>s and report error of resources to add or + * remove. + */ +async function getAndReportResourcesToAdd(frontendStrings, IDSkeys) { + const keysToAddToGRD = getDifference(IDSkeys, frontendStrings); + if (keysToAddToGRD.size === 0) + return; + + let errorStr = 'The following frontend string(s) need to be added to GRD/GRDP file(s).\n'; + errorStr += 'Please refer to auto-generated message(s) below and modify as needed.\n\n'; + + const frontendDirs = await localizationUtils.getChildDirectoriesFromDirectory(DEVTOOLS_FRONTEND_PATH); + const fileToGRDPMap = new Map(); + + // Example error message: + // third_party/blink/renderer/devtools/front_end/network/NetworkDataGridNode.js Line 973: ls`(disk cache)` + // Add a new message tag for this string to third_party\blink\renderer\devtools\front_end\network\network_strings.grdp + // <message name="IDS_DEVTOOLS_ad86890fb40822a3b12627efaca4ecd7" desc="Fill in the description."> + // (disk cache) + // </message> + for (const [key, stringObj] of keysToAddToGRD) { + let relativeGRDPFilePath = ''; + if (fileToGRDPMap.has(stringObj.filepath)) { + relativeGRDPFilePath = fileToGRDPMap.get(stringObj.filepath); + } else { + relativeGRDPFilePath = localizationUtils.getRelativeFilePathFromSrc( + localizationUtils.getGRDPFilePath(stringObj.filepath, frontendDirs)); + fileToGRDPMap.set(stringObj.filepath, relativeGRDPFilePath); + } + errorStr += `${localizationUtils.getRelativeFilePathFromSrc(stringObj.filepath)}${ + localizationUtils.getLocationMessage(stringObj.location)}: ${stringObj.code}\n`; + errorStr += `Add a new message tag for this string to ${ + localizationUtils.getRelativeFilePathFromSrc( + localizationUtils.getGRDPFilePath(stringObj.filepath, frontendDirs))}\n\n`; + errorStr += localizationUtils.createGrdpMessage(key, stringObj); + } + return errorStr; +} + +function getAndReportResourcesToRemove(frontendStrings, IDSkeys) { + const keysToRemoveFromGRD = getDifference(frontendStrings, IDSkeys); + if (keysToRemoveFromGRD.size === 0) + return; + + let errorStr = + '\nThe message(s) associated with the following IDS key(s) should be removed from its GRD/GRDP file(s):\n'; + // Example error message: + // third_party/blink/renderer/devtools/front_end/help/help_strings.grdp Line 18: IDS_DEVTOOLS_7d0ee6fed10d3d4e5c9ee496729ab519 + for (const [key, keyObj] of keysToRemoveFromGRD) { + errorStr += `${localizationUtils.getRelativeFilePathFromSrc(keyObj.filepath)}${ + localizationUtils.getLocationMessage(keyObj.location)}: ${key}\n\n`; + } + return errorStr; +} + +/** + * Output a Map containing entries that are in @comparison but not @reference in sorted order. + */ +function getDifference(reference, comparison) { + const difference = []; + for (const [key, value] of comparison) { + if (!reference.has(key)) + difference.push([key, value]); + } + return new Map(difference.sort()); +} + +module.exports = { + parseLocalizableResourceMaps, + getAndReportResourcesToAdd, + getAndReportResourcesToRemove, + getDifference +};
diff --git a/third_party/blink/renderer/devtools/scripts/localization_utils/localization_utils.js b/third_party/blink/renderer/devtools/scripts/localization_utils/localization_utils.js new file mode 100644 index 0000000..11119c5 --- /dev/null +++ b/third_party/blink/renderer/devtools/scripts/localization_utils/localization_utils.js
@@ -0,0 +1,269 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +const fs = require('fs'); +const md5 = require('./md5'); +const {promisify} = require('util'); +const path = require('path'); +const readFileAsync = promisify(fs.readFile); +const readDirAsync = promisify(fs.readdir); +const statAsync = promisify(fs.stat); + +const esprimaTypes = { + BI_EXPR: 'BinaryExpression', + CALL_EXPR: 'CallExpression', + COND_EXPR: 'ConditionalExpression', + IDENTIFIER: 'Identifier', + LITERAL: 'Literal', + MEMBER_EXPR: 'MemberExpression', + TAGGED_TEMP_EXPR: 'TaggedTemplateExpression', + TEMP_LITERAL: 'TemplateLiteral' +}; + +const excludeFiles = ['lighthouse-dt-bundle.js', 'Tests.js']; +const excludeDirs = ['test_runner', 'Images', 'langpacks', 'node_modules']; +const cppSpecialCharactersMap = { + '"': '\\"', + '\\': '\\\\', + '\n': '\\n' +}; +const IDSPrefix = 'IDS_DEVTOOLS_'; + +const THIRD_PARTY_PATH = path.resolve(__dirname, '..', '..', '..', '..', '..'); +const SRC_PATH = path.resolve(THIRD_PARTY_PATH, '..'); +const GRD_PATH = path.resolve(__dirname, '..', '..', 'front_end', 'langpacks', 'devtools_ui_strings.grd'); +const REPO_NODE_MODULES_PATH = path.resolve(THIRD_PARTY_PATH, 'node', 'node_modules'); +const escodegen = require(path.resolve(REPO_NODE_MODULES_PATH, 'escodegen')); +const esprima = require(path.resolve(REPO_NODE_MODULES_PATH, 'esprima')); + +function getRelativeFilePathFromSrc(filePath) { + return path.relative(SRC_PATH, filePath); +} + +function shouldParseDirectory(directoryName) { + return !excludeDirs.some(dir => directoryName.includes(dir)); +} + +/** + * @filepath can be partial path or full path, as long as it contains the file name. + */ +function shouldParseFile(filepath) { + return !excludeFiles.includes(path.basename(filepath)); +} + +async function parseFileContent(filePath) { + const fileContent = await readFileAsync(filePath); + return fileContent.toString(); +} + +function isNodeCallOnObject(node, objectName, propertyName) { + return node !== undefined && node.type === esprimaTypes.CALL_EXPR && + verifyCallExpressionCallee(node.callee, objectName, propertyName); +} + +function isNodeCommonUIStringCall(node) { + return isNodeCallOnObject(node, 'Common', 'UIString'); +} + +function isNodeUIformatLocalized(node) { + return isNodeCallOnObject(node, 'UI', 'formatLocalized'); +} + +function isNodelsTaggedTemplateExpression(node) { + return node !== undefined && node.type === esprimaTypes.TAGGED_TEMP_EXPR && verifyIdentifier(node.tag, 'ls') && + node.quasi !== undefined && node.quasi.type !== undefined && node.quasi.type === esprimaTypes.TEMP_LITERAL; +} + +/** + * Verify callee of objectName.propertyName(), e.g. Common.UIString(). + */ +function verifyCallExpressionCallee(callee, objectName, propertyName) { + return callee !== undefined && callee.type === esprimaTypes.MEMBER_EXPR && callee.computed === false && + verifyIdentifier(callee.object, objectName) && verifyIdentifier(callee.property, propertyName); +} + +function verifyIdentifier(node, name) { + return node !== undefined && node.type === esprimaTypes.IDENTIFIER && node.name === name; +} + +function getLocalizationCase(node) { + if (isNodeCommonUIStringCall(node)) + return 'Common.UIString'; + else if (isNodelsTaggedTemplateExpression(node)) + return 'Tagged Template'; + else if (isNodeUIformatLocalized(node)) + return 'UI.formatLocalized'; + else + return null; +} + +function isLocalizationCall(node) { + return isNodeCommonUIStringCall(node) || isNodelsTaggedTemplateExpression(node) || isNodeUIformatLocalized(node); +} + +/** + * Verify if callee is functionName() or object.functionName(). + */ +function verifyFunctionCallee(callee, functionName) { + return callee !== undefined && + ((callee.type === esprimaTypes.IDENTIFIER && callee.name === functionName) || + (callee.type === esprimaTypes.MEMBER_EXPR && verifyIdentifier(callee.property, functionName))); +} + +function getLocationMessage(location) { + if (location !== undefined && location.start !== undefined && location.end !== undefined && + location.start.line !== undefined && location.end.line !== undefined) { + const startLine = location.start.line; + const endLine = location.end.line; + if (startLine === endLine) + return ` Line ${startLine}`; + else + return ` Line ${location.start.line}-${location.end.line}`; + } + return ''; +} + +function sanitizeStringIntoGRDFormat(str) { + return str.replace(/&/g, '&') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/"/g, '"') + .replace(/'/g, ''') +} + +function sanitizeStringIntoFrontendFormat(str) { + return str.replace(/'/g, '\'') + .replace(/"/g, '"') + .replace(/>/g, '>') + .replace(/</g, '<') + .replace(/&/g, '&'); +} + +function sanitizeString(str, specialCharactersMap) { + let sanitizedStr = ''; + for (let i = 0; i < str.length; i++) { + let currChar = str.charAt(i); + if (specialCharactersMap[currChar] !== undefined) + currChar = specialCharactersMap[currChar]; + + sanitizedStr += currChar; + } + return sanitizedStr; +} + +function sanitizeStringIntoCppFormat(str) { + return sanitizeString(str, cppSpecialCharactersMap); +} + +async function getFilesFromItem(itemPath, filePaths, acceptedFileEndings) { + const stat = await statAsync(itemPath); + if (stat.isDirectory() && shouldParseDirectory(itemPath)) + return await getFilesFromDirectory(itemPath, filePaths, acceptedFileEndings); + + const hasAcceptedEnding = + acceptedFileEndings.some(acceptedEnding => itemPath.toLowerCase().endsWith(acceptedEnding.toLowerCase())); + if (hasAcceptedEnding && shouldParseFile(itemPath)) + filePaths.push(itemPath); +} + +async function getFilesFromDirectory(directoryPath, filePaths, acceptedFileEndings) { + const itemNames = await readDirAsync(directoryPath); + const promises = []; + for (const itemName of itemNames) { + const itemPath = path.resolve(directoryPath, itemName); + promises.push(getFilesFromItem(itemPath, filePaths, acceptedFileEndings)); + } + return Promise.all(promises); +} + +async function getChildDirectoriesFromDirectory(directoryPath) { + const dirPaths = []; + const itemNames = await readDirAsync(directoryPath); + for (const itemName of itemNames) { + const itemPath = path.resolve(directoryPath, itemName); + const stat = await statAsync(itemPath); + if (stat.isDirectory() && shouldParseDirectory(itemName)) + dirPaths.push(itemPath); + } + return dirPaths; +} + +/** + * Get the parent grdp file path for the input frontend file path. + * NOTE: Naming convention of a grdp file is the name of the child directory under + * devtools/front_end plus _strings.grdp + */ +function getGRDPFilePath(frontendFilepath, frontendDirs) { + const frontendDirsLowerCase = frontendDirs.map(dir => dir.toLowerCase()); + const dirpath = path.dirname(frontendFilepath); + if (frontendDirsLowerCase.includes(dirpath.toLowerCase())) + return path.resolve(dirpath, `${path.basename(dirpath)}_strings.grdp`); +} + +function modifyStringIntoGRDFormat(str, args) { + let sanitizedStr = sanitizeStringIntoGRDFormat(str); + + const phRegex = /%d|%f|%s|%.[0-9]f/gm; + if (!str.match(phRegex)) + return sanitizedStr; + + let phNames; + if (args !== undefined) + phNames = args.map(arg => arg.replace(/[^a-zA-Z]/gm, '_').toUpperCase()); + else + phNames = ['PH1', 'PH2', 'PH3', 'PH4', 'PH5', 'PH6', 'PH7', 'PH8', 'PH9']; + + // It replaces all placeholders with <ph> tags. + let match; + let count = 1; + while ((match = phRegex.exec(sanitizedStr)) !== null) { + // This is necessary to avoid infinite loops with zero-width matches + if (match.index === phRegex.lastIndex) + phRegex.lastIndex++; + + // match[0]: the placeholder (e.g. %d, %s, %.2f, etc.) + const ph = match[0]; + // e.g. $1s, $1d, $1.2f + const newPh = `$${count}` + ph.substr(1); + + const i = sanitizedStr.indexOf(ph); + sanitizedStr = `${sanitizedStr.substring(0, i)}<ph name="${phNames[count - 1]}">${newPh}</ph>${ + sanitizedStr.substring(i + ph.length)}`; + count++; + } + return sanitizedStr; +} + +function createGrdpMessage(ids, stringObj) { + let message = ` <message name="${ids}" desc="">\n`; + message += ` ${modifyStringIntoGRDFormat(stringObj.string, stringObj.arguments)}\n`; + message += ' </message>\n'; + return message; +} + +function getIDSKey(str) { + return `${IDSPrefix}${md5(str)}` +} + +module.exports = { + createGrdpMessage, + escodegen, + esprima, + esprimaTypes, + getChildDirectoriesFromDirectory, + getFilesFromDirectory, + getGRDPFilePath, + getIDSKey, + getLocalizationCase, + getLocationMessage, + getRelativeFilePathFromSrc, + GRD_PATH, + IDSPrefix, + isLocalizationCall, + modifyStringIntoGRDFormat, + parseFileContent, + sanitizeStringIntoCppFormat, + sanitizeStringIntoFrontendFormat, + verifyFunctionCallee +}; \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/scripts/localization_utils/md5.js b/third_party/blink/renderer/devtools/scripts/localization_utils/md5.js new file mode 100644 index 0000000..3f59f37 --- /dev/null +++ b/third_party/blink/renderer/devtools/scripts/localization_utils/md5.js
@@ -0,0 +1,157 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/* + * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message + * Digest Algorithm, as defined in RFC 1321. + * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * Distributed under the BSD License + * See http://pajhome.org.uk/crypt/md5 for more info. + */ +function md5(s) { + return binl2hex(core_md5(str2binl(s), s.length * 8)); +} + +function core_md5(x, len) { + /* append padding */ + x[len >> 5] |= 0x80 << ((len) % 32); + x[(((len + 64) >>> 9) << 4) + 14] = len; + + var a = 1732584193; + var b = -271733879; + var c = -1732584194; + var d = 271733878; + + for (var i = 0; i < x.length; i += 16) { + var olda = a; + var oldb = b; + var oldc = c; + var oldd = d; + + a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936); + d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586); + c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819); + b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330); + a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897); + d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426); + c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341); + b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983); + a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416); + d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417); + c = md5_ff(c, d, a, b, x[i + 10], 17, -42063); + b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162); + a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682); + d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101); + c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290); + b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329); + + a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510); + d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632); + c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713); + b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302); + a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691); + d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083); + c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335); + b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848); + a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438); + d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690); + c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961); + b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501); + a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467); + d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784); + c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473); + b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734); + + a = md5_hh(a, b, c, d, x[i + 5], 4, -378558); + d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463); + c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562); + b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556); + a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060); + d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353); + c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632); + b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640); + a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174); + d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222); + c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979); + b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189); + a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487); + d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835); + c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520); + b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651); + + a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844); + d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415); + c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905); + b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055); + a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571); + d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606); + c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523); + b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799); + a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359); + d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744); + c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380); + b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649); + a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070); + d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379); + c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259); + b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551); + + a = safe_add(a, olda); + b = safe_add(b, oldb); + c = safe_add(c, oldc); + d = safe_add(d, oldd); + } + return Array(a, b, c, d); +} + +function md5_cmn(q, a, b, x, s, t) { + return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b); +} + +function md5_ff(a, b, c, d, x, s, t) { + return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); +} + +function md5_gg(a, b, c, d, x, s, t) { + return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); +} + +function md5_hh(a, b, c, d, x, s, t) { + return md5_cmn(b ^ c ^ d, a, b, x, s, t); +} + +function md5_ii(a, b, c, d, x, s, t) { + return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); +} + +function safe_add(x, y) { + var lsw = (x & 0xFFFF) + (y & 0xFFFF); + var msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); +} + +function bit_rol(num, cnt) { + return (num << cnt) | (num >>> (32 - cnt)); +} + +function str2binl(str) { + var bin = Array(); + var mask = (1 << 8) - 1; + for (var i = 0; i < str.length * 8; i += 8) + bin[i >> 5] |= (str.charCodeAt(i / 8) & mask) << (i % 32); + return bin; +} + +function binl2hex(binarray) { + var hex_tab = '0123456789abcdef'; + var str = ''; + for (var i = 0; i < binarray.length * 4; i++) { + str += hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8 + 4)) & 0xF) + + hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8)) & 0xF); + } + return str; +} + +module.exports = md5; \ No newline at end of file
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_request_loader.cc b/third_party/blink/renderer/modules/indexeddb/idb_request_loader.cc index 111b6a9..1181fe0f 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_request_loader.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_request_loader.cc
@@ -75,7 +75,7 @@ ExecutionContext* exection_context = queue_item_->Request()->GetExecutionContext(); - // The execution context was town down. The loader will eventually get a + // The execution context was torn down. The loader will eventually get a // Cancel() call. if (!exection_context) return;
diff --git a/third_party/blink/renderer/modules/xr/xr.cc b/third_party/blink/renderer/modules/xr/xr.cc index b13eb0b..a62f61a 100644 --- a/third_party/blink/renderer/modules/xr/xr.cc +++ b/third_party/blink/renderer/modules/xr/xr.cc
@@ -77,6 +77,9 @@ return XRSession::kModeInline; } +// When updating this list, also update XRRuntimeManager's +// AreArFeaturesEnabled() until https://crbug.com/966647 is fixed. +// TODO(https://crbug.com/966647) remove the above comment when fixed. bool AreArRuntimeFeaturesEnabled(const FeatureContext* context) { return RuntimeEnabledFeatures::WebXRHitTestEnabled(context) || RuntimeEnabledFeatures::WebXRPlaneDetectionEnabled(context);
diff --git a/third_party/blink/renderer/platform/graphics/compositor_filter_operations.cc b/third_party/blink/renderer/platform/graphics/compositor_filter_operations.cc index f370641..7cbf81a 100644 --- a/third_party/blink/renderer/platform/graphics/compositor_filter_operations.cc +++ b/third_party/blink/renderer/platform/graphics/compositor_filter_operations.cc
@@ -53,8 +53,11 @@ filter_operations_.Append(cc::FilterOperation::CreateOpacityFilter(amount)); } -void CompositorFilterOperations::AppendBlurFilter(float amount) { - filter_operations_.Append(cc::FilterOperation::CreateBlurFilter(amount)); +void CompositorFilterOperations::AppendBlurFilter( + float amount, + SkBlurImageFilter::TileMode tile_mode) { + filter_operations_.Append( + cc::FilterOperation::CreateBlurFilter(amount, tile_mode)); } void CompositorFilterOperations::AppendDropShadowFilter(IntPoint offset,
diff --git a/third_party/blink/renderer/platform/graphics/compositor_filter_operations.h b/third_party/blink/renderer/platform/graphics/compositor_filter_operations.h index bfb58a14..b6755ec 100644 --- a/third_party/blink/renderer/platform/graphics/compositor_filter_operations.h +++ b/third_party/blink/renderer/platform/graphics/compositor_filter_operations.h
@@ -30,7 +30,9 @@ void AppendBrightnessFilter(float amount); void AppendContrastFilter(float amount); void AppendOpacityFilter(float amount); - void AppendBlurFilter(float amount); + void AppendBlurFilter(float amount, + SkBlurImageFilter::TileMode tile_mode = + SkBlurImageFilter::kClampToBlack_TileMode); void AppendDropShadowFilter(IntPoint offset, float std_deviation, Color); void AppendColorMatrixFilter(const cc::FilterOperation::Matrix&); void AppendZoomFilter(float amount, int inset);
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index d8717c7..445778a 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -375,7 +375,7 @@ }, { name: "CSSPictureInPicture", - status: "stable", + status: "experimental", depends_on: ["PictureInPictureAPI"], }, {
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint index 9cc40d8..d417982 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint +++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint
@@ -392,7 +392,7 @@ crbug.com/909749 fast/events/touch/compositor-touch-hit-rects-non-composited-scroll.html [ Failure ] # Backdrop filter -crbug.com/923429 css3/filters/backdrop-filter-basic-blur.html [ Failure ] +crbug.com/923429 css3/filters/backdrop-filter-basic-blur.html [ Timeout Failure ] crbug.com/923429 css3/filters/backdrop-filter-browser-zoom.html [ Failure ] crbug.com/923429 css3/filters/backdrop-filter-border-radius.html [ Failure ] crbug.com/923429 css3/filters/backdrop-filter-clip-rect-zoom.html [ Failure ] @@ -400,6 +400,7 @@ crbug.com/923429 css3/filters/backdrop-filter-rendering.html [ Failure ] crbug.com/923429 css3/filters/backdrop-filter-rendering-no-background.html [ Failure ] crbug.com/923429 css3/filters/backdrop-filter-transform.html [ Failure ] +crbug.com/923429 css3/filters/backdrop-filter-edge-pixels.html [ Failure ] crbug.com/923429 external/wpt/css/filter-effects/backdrop-filter-basic-background-color.html [ Failure ] crbug.com/923429 external/wpt/css/filter-effects/backdrop-filter-basic-opacity-2.html [ Failure ] crbug.com/923429 external/wpt/css/filter-effects/backdrop-filter-basic.html [ Failure ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 00022d5..47f62ea 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -2771,7 +2771,6 @@ # needs implementation of test_driver_internal.action_sequence crbug.com/893480 external/wpt/infrastructure/testdriver/actions/elementTiming.html [ Timeout ] crbug.com/893480 external/wpt/infrastructure/testdriver/actions/multiDevice.html [ Failure Timeout ] -crbug.com/893480 external/wpt/infrastructure/testdriver/actions/actionsWithKeyPressed.html [ Failure Timeout ] # Hit a DCHECK crbug.com/918664 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/sizing/block-size-with-min-or-max-content-table-1a.html [ Failure Pass ] @@ -2782,6 +2781,16 @@ crbug.com/965409 external/wpt/css/css-font-loading/fontface-descriptor-updates.html [ Failure ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 [ Mac10.12 ] external/wpt/preload/download-resources.html [ Failure Timeout ] +crbug.com/626703 [ Mac10.13 ] external/wpt/preload/download-resources.html [ Failure Timeout ] +crbug.com/626703 [ Retina ] external/wpt/preload/download-resources.html [ Failure Timeout ] +crbug.com/626703 [ Mac10.10 ] external/wpt/preload/download-resources.html [ Failure Timeout ] +crbug.com/626703 [ Mac10.10 ] external/wpt/preload/onerror-event.html [ Failure Timeout ] +crbug.com/626703 [ Win ] external/wpt/preload/onerror-event.html [ Failure Timeout ] +crbug.com/626703 [ Mac10.12 ] external/wpt/preload/onerror-event.html [ Failure Timeout ] +crbug.com/626703 [ Mac10.13 ] external/wpt/preload/onerror-event.html [ Failure Timeout ] +crbug.com/626703 [ Retina ] external/wpt/preload/onerror-event.html [ Timeout ] +crbug.com/626703 [ Win7 ] external/wpt/service-workers/service-worker/fetch-event-async-respond-with.https.html [ Timeout ] crbug.com/626703 virtual/layout_ng_experimental/external/wpt/css/css-contain/contain-layout-button-001.html [ Failure ] crbug.com/626703 external/wpt/css/css-contain/contain-layout-button-001.html [ Failure ] crbug.com/626703 external/wpt/css/css-writing-modes/text-combine-upright-digits-001-manual.html [ Skip ]
diff --git a/third_party/blink/web_tests/css3/filters/backdrop-filter-basic-blur-expected.png b/third_party/blink/web_tests/css3/filters/backdrop-filter-basic-blur-expected.png index 71307d03..d3be83b 100644 --- a/third_party/blink/web_tests/css3/filters/backdrop-filter-basic-blur-expected.png +++ b/third_party/blink/web_tests/css3/filters/backdrop-filter-basic-blur-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/css3/filters/backdrop-filter-edge-pixels-expected.png b/third_party/blink/web_tests/css3/filters/backdrop-filter-edge-pixels-expected.png new file mode 100644 index 0000000..7e810e0 --- /dev/null +++ b/third_party/blink/web_tests/css3/filters/backdrop-filter-edge-pixels-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/css3/filters/backdrop-filter-edge-pixels.html b/third_party/blink/web_tests/css3/filters/backdrop-filter-edge-pixels.html new file mode 100644 index 0000000..89b1114 --- /dev/null +++ b/third_party/blink/web_tests/css3/filters/backdrop-filter-edge-pixels.html
@@ -0,0 +1,25 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> + +<div class="red_square"></div> +<div class="filter"></div> + +<style> +div { + width: 100px; + position: absolute; +} +body { overflow: hidden; margin: 0;} +.red_square { + height: 100px; + left:30px; + top: 20px; + background: red; + transform: rotate(30deg); +} +.filter { + height: 200px; + background: transparent; + backdrop-filter: blur(20px); +} +</style>
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json index afde87d..00f086fb 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
@@ -69189,6 +69189,18 @@ {} ] ], + "css/css-text/text-transform/text-transform-upperlower-044.html": [ + [ + "css/css-text/text-transform/text-transform-upperlower-044.html", + [ + [ + "/css/css-text/text-transform/reference/text-transform-upperlower-044-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-text/text-transform/text-transform-upperlower-101.html": [ [ "css/css-text/text-transform/text-transform-upperlower-101.html", @@ -94427,6 +94439,18 @@ {} ] ], + "css/css-writing-modes/percentage-padding-in-shrink-to-fit.html": [ + [ + "css/css-writing-modes/percentage-padding-in-shrink-to-fit.html", + [ + [ + "/css/reference/nothing.html", + "==" + ] + ], + {} + ] + ], "css/css-writing-modes/relpos-inline-overflowing-block-vrl.html": [ [ "css/css-writing-modes/relpos-inline-overflowing-block-vrl.html", @@ -112067,18 +112091,6 @@ {} ] ], - "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue.html": [ - [ - "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue.html", - [ - [ - "/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue-ref.html", - "==" - ] - ], - {} - ] - ], "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-line-doesnt-fit.html": [ [ "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-line-doesnt-fit.html", @@ -133681,6 +133693,11 @@ {} ] ], + "css/css-backgrounds/parsing/background-position-computed-expected.txt": [ + [ + {} + ] + ], "css/css-backgrounds/parsing/background-position-x-computed-expected.txt": [ [ {} @@ -153046,6 +153063,11 @@ {} ] ], + "css/css-text/text-transform/reference/text-transform-upperlower-044-ref.html": [ + [ + {} + ] + ], "css/css-text/text-transform/reference/text-transform-upperlower-101-ref.html": [ [ {} @@ -178856,11 +178878,6 @@ {} ] ], - "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue-ref.html": [ - [ - {} - ] - ], "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-line-doesnt-fit-ref.html": [ [ {} @@ -178871,11 +178888,26 @@ {} ] ], + "html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-error-expected.txt": [ + [ + {} + ] + ], + "html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-expected.txt": [ + [ + {} + ] + ], "html/semantics/embedded-content/media-elements/track/track-element/track-helpers.js": [ [ {} ] ], + "html/semantics/embedded-content/media-elements/track/track-element/track-selection-task-order-expected.txt": [ + [ + {} + ] + ], "html/semantics/embedded-content/media-elements/track/track-element/track-text-track-cue-list-expected.txt": [ [ {} @@ -182506,6 +182538,11 @@ {} ] ], + "imagebitmap-renderingcontext/context-creation-with-alpha-expected.txt": [ + [ + {} + ] + ], "images/META.yml": [ [ {} @@ -183051,11 +183088,6 @@ {} ] ], - "infrastructure/metadata/infrastructure/testdriver/actions/actionsWithKeyPressed.html.ini": [ - [ - {} - ] - ], "infrastructure/metadata/infrastructure/testdriver/actions/elementPosition.html.ini": [ [ {} @@ -194511,6 +194543,11 @@ {} ] ], + "service-workers/service-worker/resources/update-during-installation-worker.py": [ + [ + {} + ] + ], "service-workers/service-worker/resources/update-fetch-worker.py": [ [ {} @@ -203551,6 +203588,11 @@ {} ] ], + "wake-lock/wakelock-screen-type-on-worker.https.worker-expected.txt": [ + [ + {} + ] + ], "wake-lock/wakelock-state-is-global.https-expected.txt": [ [ {} @@ -203561,6 +203603,11 @@ {} ] ], + "wake-lock/wakelock-type.https.any.worker-expected.txt": [ + [ + {} + ] + ], "wasm/META.yml": [ [ {} @@ -203906,11 +203953,6 @@ {} ] ], - "web-animations/interfaces/Animation/constructor-expected.txt": [ - [ - {} - ] - ], "web-animations/interfaces/Animation/finished-expected.txt": [ [ {} @@ -204036,6 +204078,11 @@ {} ] ], + "web-animations/timing-model/animations/setting-the-start-time-of-an-animation-expected.txt": [ + [ + {} + ] + ], "web-animations/timing-model/animations/setting-the-target-effect-of-an-animation-expected.txt": [ [ {} @@ -231578,6 +231625,12 @@ {} ] ], + "css/css-backgrounds/parsing/background-attachment-computed.html": [ + [ + "css/css-backgrounds/parsing/background-attachment-computed.html", + {} + ] + ], "css/css-backgrounds/parsing/background-attachment-invalid.html": [ [ "css/css-backgrounds/parsing/background-attachment-invalid.html", @@ -231590,6 +231643,12 @@ {} ] ], + "css/css-backgrounds/parsing/background-clip-computed.html": [ + [ + "css/css-backgrounds/parsing/background-clip-computed.html", + {} + ] + ], "css/css-backgrounds/parsing/background-clip-invalid.html": [ [ "css/css-backgrounds/parsing/background-clip-invalid.html", @@ -231602,6 +231661,12 @@ {} ] ], + "css/css-backgrounds/parsing/background-color-computed.html": [ + [ + "css/css-backgrounds/parsing/background-color-computed.html", + {} + ] + ], "css/css-backgrounds/parsing/background-color-invalid.html": [ [ "css/css-backgrounds/parsing/background-color-invalid.html", @@ -231614,6 +231679,18 @@ {} ] ], + "css/css-backgrounds/parsing/background-computed.html": [ + [ + "css/css-backgrounds/parsing/background-computed.html", + {} + ] + ], + "css/css-backgrounds/parsing/background-image-computed.html": [ + [ + "css/css-backgrounds/parsing/background-image-computed.html", + {} + ] + ], "css/css-backgrounds/parsing/background-image-invalid.html": [ [ "css/css-backgrounds/parsing/background-image-invalid.html", @@ -231632,6 +231709,12 @@ {} ] ], + "css/css-backgrounds/parsing/background-origin-computed.html": [ + [ + "css/css-backgrounds/parsing/background-origin-computed.html", + {} + ] + ], "css/css-backgrounds/parsing/background-origin-invalid.html": [ [ "css/css-backgrounds/parsing/background-origin-invalid.html", @@ -231644,6 +231727,12 @@ {} ] ], + "css/css-backgrounds/parsing/background-position-computed.html": [ + [ + "css/css-backgrounds/parsing/background-position-computed.html", + {} + ] + ], "css/css-backgrounds/parsing/background-position-invalid.html": [ [ "css/css-backgrounds/parsing/background-position-invalid.html", @@ -231692,6 +231781,12 @@ {} ] ], + "css/css-backgrounds/parsing/background-repeat-computed.html": [ + [ + "css/css-backgrounds/parsing/background-repeat-computed.html", + {} + ] + ], "css/css-backgrounds/parsing/background-repeat-invalid.html": [ [ "css/css-backgrounds/parsing/background-repeat-invalid.html", @@ -231704,6 +231799,12 @@ {} ] ], + "css/css-backgrounds/parsing/background-size-computed.html": [ + [ + "css/css-backgrounds/parsing/background-size-computed.html", + {} + ] + ], "css/css-backgrounds/parsing/background-size-invalid.html": [ [ "css/css-backgrounds/parsing/background-size-invalid.html", @@ -235616,6 +235717,60 @@ {} ] ], + "css/css-logical/parsing/border-block-color-computed.html": [ + [ + "css/css-logical/parsing/border-block-color-computed.html", + {} + ] + ], + "css/css-logical/parsing/border-block-color-invalid.html": [ + [ + "css/css-logical/parsing/border-block-color-invalid.html", + {} + ] + ], + "css/css-logical/parsing/border-block-color-valid.html": [ + [ + "css/css-logical/parsing/border-block-color-valid.html", + {} + ] + ], + "css/css-logical/parsing/border-block-style-computed.html": [ + [ + "css/css-logical/parsing/border-block-style-computed.html", + {} + ] + ], + "css/css-logical/parsing/border-block-style-invalid.html": [ + [ + "css/css-logical/parsing/border-block-style-invalid.html", + {} + ] + ], + "css/css-logical/parsing/border-block-style-valid.html": [ + [ + "css/css-logical/parsing/border-block-style-valid.html", + {} + ] + ], + "css/css-logical/parsing/border-block-width-computed.html": [ + [ + "css/css-logical/parsing/border-block-width-computed.html", + {} + ] + ], + "css/css-logical/parsing/border-block-width-invalid.html": [ + [ + "css/css-logical/parsing/border-block-width-invalid.html", + {} + ] + ], + "css/css-logical/parsing/border-block-width-valid.html": [ + [ + "css/css-logical/parsing/border-block-width-valid.html", + {} + ] + ], "css/css-logical/parsing/inline-size-invalid.html": [ [ "css/css-logical/parsing/inline-size-invalid.html", @@ -269204,6 +269359,12 @@ {} ] ], + "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue.html": [ + [ + "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue.html", + {} + ] + ], "html/semantics/embedded-content/media-elements/track/track-element/track-cues-cuechange.html": [ [ "html/semantics/embedded-content/media-elements/track/track-element/track-cues-cuechange.html", @@ -269400,6 +269561,12 @@ {} ] ], + "html/semantics/embedded-content/media-elements/track/track-element/track-selection-task-order.html": [ + [ + "html/semantics/embedded-content/media-elements/track/track-element/track-selection-task-order.html", + {} + ] + ], "html/semantics/embedded-content/media-elements/track/track-element/track-text-track-cue-list.html": [ [ "html/semantics/embedded-content/media-elements/track/track-element/track-text-track-cue-list.html", @@ -278065,18 +278232,6 @@ {} ] ], - "imagebitmap-renderingcontext/context-creation-offscreen-with-alpha.html": [ - [ - "imagebitmap-renderingcontext/context-creation-offscreen-with-alpha.html", - {} - ] - ], - "imagebitmap-renderingcontext/context-creation-offscreen.html": [ - [ - "imagebitmap-renderingcontext/context-creation-offscreen.html", - {} - ] - ], "imagebitmap-renderingcontext/context-creation-with-alpha.html": [ [ "imagebitmap-renderingcontext/context-creation-with-alpha.html", @@ -278095,30 +278250,6 @@ {} ] ], - "imagebitmap-renderingcontext/toBlob-origin-clean-offscreen.sub.html": [ - [ - "imagebitmap-renderingcontext/toBlob-origin-clean-offscreen.sub.html", - {} - ] - ], - "imagebitmap-renderingcontext/tranferFromImageBitmap-ToBlob-offscreen.html": [ - [ - "imagebitmap-renderingcontext/tranferFromImageBitmap-ToBlob-offscreen.html", - {} - ] - ], - "imagebitmap-renderingcontext/tranferFromImageBitmap-TransferToImageBitmap-offscreen.html": [ - [ - "imagebitmap-renderingcontext/tranferFromImageBitmap-TransferToImageBitmap-offscreen.html", - {} - ] - ], - "imagebitmap-renderingcontext/tranferFromImageBitmap-null-offscreen.html": [ - [ - "imagebitmap-renderingcontext/tranferFromImageBitmap-null-offscreen.html", - {} - ] - ], "imagebitmap-renderingcontext/tranferFromImageBitmap-null.html": [ [ "imagebitmap-renderingcontext/tranferFromImageBitmap-null.html", @@ -278612,14 +278743,6 @@ {} ] ], - "infrastructure/testdriver/actions/actionsWithKeyPressed.html": [ - [ - "infrastructure/testdriver/actions/actionsWithKeyPressed.html", - { - "testdriver": true - } - ] - ], "infrastructure/testdriver/actions/elementPosition.html": [ [ "infrastructure/testdriver/actions/elementPosition.html", @@ -295370,6 +295493,12 @@ {} ] ], + "portals/portal-non-http-navigation.html": [ + [ + "portals/portal-non-http-navigation.html", + {} + ] + ], "portals/portal-onload-event.html": [ [ "portals/portal-onload-event.html", @@ -296015,6 +296144,12 @@ {} ] ], + "referrer-policy/generic/iframe-src-change.html": [ + [ + "referrer-policy/generic/iframe-src-change.html", + {} + ] + ], "referrer-policy/generic/link-rel-prefetch.html": [ [ "referrer-policy/generic/link-rel-prefetch.html", @@ -317669,16 +317804,41 @@ {} ] ], - "wake-lock/wakelock-insecure-context.html": [ + "wake-lock/wakelock-insecure-context.any.js": [ [ - "wake-lock/wakelock-insecure-context.html", - {} + "wake-lock/wakelock-insecure-context.any.html", + { + "script_metadata": [ + [ + "title", + "Wake Lock API is not exposed in an insecure context" + ] + ] + } + ], + [ + "wake-lock/wakelock-insecure-context.any.worker.html", + { + "script_metadata": [ + [ + "title", + "Wake Lock API is not exposed in an insecure context" + ] + ] + } ] ], - "wake-lock/wakelock-state-is-global.https.html": [ + "wake-lock/wakelock-screen-type-on-worker.https.worker.js": [ [ - "wake-lock/wakelock-state-is-global.https.html", - {} + "wake-lock/wakelock-screen-type-on-worker.https.worker.html", + { + "script_metadata": [ + [ + "title", + "Screen wake lock should not be allowed in dedicated worker" + ] + ] + } ] ], "wake-lock/wakelock-supported-by-feature-policy.html": [ @@ -317687,10 +317847,28 @@ {} ] ], - "wake-lock/wakelock-type.https.html": [ + "wake-lock/wakelock-type.https.any.js": [ [ - "wake-lock/wakelock-type.https.html", - {} + "wake-lock/wakelock-type.https.any.html", + { + "script_metadata": [ + [ + "title", + "WakeLock.request() with invalid type" + ] + ] + } + ], + [ + "wake-lock/wakelock-type.https.any.worker.html", + { + "script_metadata": [ + [ + "title", + "WakeLock.request() with invalid type" + ] + ] + } ] ], "wasm/create_multiple_memory.worker.js": [ @@ -349483,7 +349661,7 @@ "testharness" ], "bluetooth/characteristic/writeValue/buffer-is-detached.https.html": [ - "762735c320b1a7f626b448933e2fd0a0dac4793d", + "b8a1abfa5afe3d514d6884b58268dc47cfc15f5e", "testharness" ], "bluetooth/characteristic/writeValue/characteristic-is-removed.https.html": [ @@ -349511,7 +349689,7 @@ "testharness" ], "bluetooth/descriptor/writeValue/buffer-is-detached.https.html": [ - "2402d89440e6f011e9eab37519faefb0643d29bf", + "2ab990de61c5603976d3dc915d078a59f11d30a2", "testharness" ], "bluetooth/descriptor/writeValue/gen-service-is-removed.https.html": [ @@ -374390,6 +374568,10 @@ "5ed794153083a7e06eb2e98b7ebdb5bec2676d28", "visual" ], + "css/css-backgrounds/parsing/background-attachment-computed.html": [ + "ceb76c2cdae213b5dad7e1f770590e0b4b054f12", + "testharness" + ], "css/css-backgrounds/parsing/background-attachment-invalid.html": [ "30757f3a4d02a9b1d1fc82c19255804ee2b20ae9", "testharness" @@ -374398,6 +374580,10 @@ "14d72c606ba52e85d296a5404c2546486765cd42", "testharness" ], + "css/css-backgrounds/parsing/background-clip-computed.html": [ + "9e8b7631bbb37c20fe7bdf5b43206a1e9aa20ce7", + "testharness" + ], "css/css-backgrounds/parsing/background-clip-invalid.html": [ "96831e06fc9cce1c9c45e4d44c83f04d2350d0ab", "testharness" @@ -374406,14 +374592,26 @@ "e262a788bd0296deb0429fd4fc4257390776680a", "testharness" ], + "css/css-backgrounds/parsing/background-color-computed.html": [ + "7fbeac81a9f328be670c81be4b645e0e37461e91", + "testharness" + ], "css/css-backgrounds/parsing/background-color-invalid.html": [ - "b94875402d89839fdb717883f11eff7f880036bf", + "bf315fdb4e49038dae3eb16d3df7308840b51ca3", "testharness" ], "css/css-backgrounds/parsing/background-color-valid.html": [ "3859b932c82287c0e103f1a7aebb1ed190b735a0", "testharness" ], + "css/css-backgrounds/parsing/background-computed.html": [ + "cb7d10998e0f46c2553fe161cb215179c4bab4c7", + "testharness" + ], + "css/css-backgrounds/parsing/background-image-computed.html": [ + "af14f6cf6e8e23de029f7079fe653144218b0ecf", + "testharness" + ], "css/css-backgrounds/parsing/background-image-invalid.html": [ "eaba64a715ce71a9f828569a24df51f1476664dd", "testharness" @@ -374426,6 +374624,10 @@ "4ea58da801961ba9c8a315ebb0b1de846e16f889", "testharness" ], + "css/css-backgrounds/parsing/background-origin-computed.html": [ + "4e5280135d8d2d5bf3ea73cd92505f78c7e09f52", + "testharness" + ], "css/css-backgrounds/parsing/background-origin-invalid.html": [ "5da00dabe33473254830990c43375ac349eea330", "testharness" @@ -374434,8 +374636,16 @@ "7e3b0fffcad133948567c5a31b9dcb232891e610", "testharness" ], + "css/css-backgrounds/parsing/background-position-computed-expected.txt": [ + "b49d3c27b9c4354dd2725115560d41aa9e6108e6", + "support" + ], + "css/css-backgrounds/parsing/background-position-computed.html": [ + "c5e30745f476027170420039873f1911908676df", + "testharness" + ], "css/css-backgrounds/parsing/background-position-invalid.html": [ - "bb974afd9f41d8ca4f0ac82db10e57e4bf6d74b7", + "966db4c31a9b1b9d55afbce41ec31bbb98dfc69f", "testharness" ], "css/css-backgrounds/parsing/background-position-valid.html": [ @@ -374443,11 +374653,11 @@ "testharness" ], "css/css-backgrounds/parsing/background-position-x-computed-expected.txt": [ - "777dc05f71398e2ff86c17fbd43010519f07e4ca", + "2f99244a7c09ca63b8ee31c6c08ee5eeb364ad6a", "support" ], "css/css-backgrounds/parsing/background-position-x-computed.html": [ - "6e997c95ae0b632713bed16a84d07c3ac6379d1b", + "f64d2658637ae013997dcdac15d090149304d6df", "testharness" ], "css/css-backgrounds/parsing/background-position-x-invalid.html": [ @@ -374463,11 +374673,11 @@ "testharness" ], "css/css-backgrounds/parsing/background-position-y-computed-expected.txt": [ - "86634ba52c136e54a4a635d9de6baa8d41dc4bd1", + "f96b97f83ea9cb15609b98a3ff7ae5f207559047", "support" ], "css/css-backgrounds/parsing/background-position-y-computed.html": [ - "ceff11f624d2d04fdca3201af09023081c3bf759", + "103a26037b7115d09472bd58dc49349e698ef020", "testharness" ], "css/css-backgrounds/parsing/background-position-y-invalid.html": [ @@ -374482,6 +374692,10 @@ "1413a2e959a4cf00b64fecf06932a083e1480e54", "testharness" ], + "css/css-backgrounds/parsing/background-repeat-computed.html": [ + "f58ab577791a869c837b08c39514d3ee8b17eba6", + "testharness" + ], "css/css-backgrounds/parsing/background-repeat-invalid.html": [ "abb153378f4ce02507d39c5a5a979689df58c8ba", "testharness" @@ -374490,6 +374704,10 @@ "2f72e03c73332dcf4356796ea3164fe170a21620", "testharness" ], + "css/css-backgrounds/parsing/background-size-computed.html": [ + "01091f541ff3494d9949d620521ea6e91d9d9f97", + "testharness" + ], "css/css-backgrounds/parsing/background-size-invalid.html": [ "01a0322002bc4fecc9c48d2266e39d1c2da3e500", "testharness" @@ -393422,6 +393640,42 @@ "47170e48f15f90488542daf7ede743cd55f75172", "testharness" ], + "css/css-logical/parsing/border-block-color-computed.html": [ + "dc9e44edb1a11c374074c266c2b0929a5f13580b", + "testharness" + ], + "css/css-logical/parsing/border-block-color-invalid.html": [ + "1c25f125fe32fe138d4ef1a656c4a249cd981136", + "testharness" + ], + "css/css-logical/parsing/border-block-color-valid.html": [ + "aefe0f268b0f7a91d46fb40c4b051587de1f2ac7", + "testharness" + ], + "css/css-logical/parsing/border-block-style-computed.html": [ + "beb3869863ccf016457b03bf4a8c401b7a69c47c", + "testharness" + ], + "css/css-logical/parsing/border-block-style-invalid.html": [ + "680e510aae6853fc48ad65f2eb3a0fabdb436936", + "testharness" + ], + "css/css-logical/parsing/border-block-style-valid.html": [ + "860a1052b8346aadbbbf18faf818ab9248f35535", + "testharness" + ], + "css/css-logical/parsing/border-block-width-computed.html": [ + "3b4d934f8b23b29cd5d7b3aae039ac51ac4ab410", + "testharness" + ], + "css/css-logical/parsing/border-block-width-invalid.html": [ + "65990fe930d2b8b69a2863d675bbfd993291ce5a", + "testharness" + ], + "css/css-logical/parsing/border-block-width-valid.html": [ + "98987df9a703ef38d20c6bc1581b2ca136342615", + "testharness" + ], "css/css-logical/parsing/inline-size-invalid.html": [ "d3d5d3f84d9d01392533e787b9e6755d592ec96e", "testharness" @@ -407235,7 +407489,7 @@ "support" ], "css/css-text/text-transform/reference/text-transform-upperlower-039-ref.html": [ - "0e243edde50eeddae6b52604051ade41194cf447", + "f4fb6804434e02f283fe036e8a110a5652fc8cb3", "support" ], "css/css-text/text-transform/reference/text-transform-upperlower-040-ref.html": [ @@ -407254,6 +407508,10 @@ "5c5e18c2f7451fb5a236c9fae6344786a65336b3", "support" ], + "css/css-text/text-transform/reference/text-transform-upperlower-044-ref.html": [ + "3eed1edb80e628c28f6a483db4a6980a4b36064e", + "support" + ], "css/css-text/text-transform/reference/text-transform-upperlower-101-ref.html": [ "0105b021d468598eec8e48de849d4764a9e517af", "support" @@ -407595,7 +407853,7 @@ "reftest" ], "css/css-text/text-transform/text-transform-upperlower-039.html": [ - "40f36e0be3cd440d8f8820e5636455e90b5b9e68", + "470a4f6fb549f29d9a29f43b68df63b304c851e2", "reftest" ], "css/css-text/text-transform/text-transform-upperlower-040.html": [ @@ -407614,6 +407872,10 @@ "d56f6b3ee3bf1cd0d692d36a782c0040129b31a4", "reftest" ], + "css/css-text/text-transform/text-transform-upperlower-044.html": [ + "6d81c4540a132fc5db5a8361154c3f04f1087f32", + "reftest" + ], "css/css-text/text-transform/text-transform-upperlower-101.html": [ "e4f2ca7d9f510359541f974e4f648c89de6e1561", "reftest" @@ -423858,6 +424120,10 @@ "187d875cd5115cec781d18bf4fca715441d5b2d7", "reftest" ], + "css/css-writing-modes/percentage-padding-in-shrink-to-fit.html": [ + "2d4364c886c48c3ef7ebddfb43d2210bdf75e094", + "reftest" + ], "css/css-writing-modes/reference/available-size-001-ref.html": [ "84252946946d4e444f8b0dd69381a1bd04554c80", "support" @@ -437471,11 +437737,11 @@ "testharness" ], "dom/events/EventListener-handleEvent-expected.txt": [ - "5269d0c706742beeafd9b5be98bf7f4b08e1c4ac", + "ee188fd998810a6b4b6f2ea6230fd4c32abe91f3", "support" ], "dom/events/EventListener-handleEvent.html": [ - "6630f273fff4b450d1fcc425828b5f1f53357e54", + "1eb80ccb15f0bc6fda7d04d4fc01555ea6b8ab04", "testharness" ], "dom/events/EventListener-incumbent-global-1.sub.html": [ @@ -438939,7 +439205,7 @@ "testharness" ], "dom/traversal/TreeWalker-acceptNode-filter.html": [ - "1446f40f68dd25f13b97bdce2a425cd9f36104d1", + "e2110aff3b3dec517f70866f908de2f919c089a4", "testharness" ], "dom/traversal/TreeWalker-basic.html": [ @@ -444775,7 +445041,7 @@ "testharness" ], "fetch/corb/script-resource-with-nonsniffable-types.tentative.sub.html": [ - "62fd9ca389da9fda5e7c6655ae88be57b7688d5b", + "e599bf26f9445e9e96ee98e4bbab2895e2283fe2", "testharness" ], "fetch/corb/style-css-mislabeled-as-html-nosniff.sub.html": [ @@ -450635,7 +450901,7 @@ "testharness" ], "html/dom/interfaces.https_exclude=(Document_Window_HTML._)-expected.txt": [ - "d9a59c802f3368cc0d818e3f221e9e1e60e545e0", + "efc72ac6e85df27db2bee1d3de2d0524ece4421c", "support" ], "html/dom/interfaces.https_include=(Document_Window)-expected.txt": [ @@ -450643,11 +450909,11 @@ "support" ], "html/dom/interfaces.https_include=HTML._-expected.txt": [ - "9eb12ff6ce99e7f2e5058c918bde46ba2ca12322", + "ff83da82f19174e6967a57bac2261f4daabd9c64", "support" ], "html/dom/interfaces.worker-expected.txt": [ - "f31faed6e03fe737629ad68d4b9c83b5bd599850", + "c2e30c2ea7e56bf6e4864ca4bb552e331e16ea48", "support" ], "html/dom/interfaces.worker.js": [ @@ -457519,7 +457785,7 @@ "testharness" ], "html/semantics/embedded-content/media-elements/track/track-element/track-active-cues.html": [ - "67ab3bdb138230fa64f0a04c0cc2bd780a23ec65", + "501cf3f92a2796c2685a046829593821d7414b2c", "testharness" ], "html/semantics/embedded-content/media-elements/track/track-element/track-add-remove-cue.html": [ @@ -457598,16 +457864,12 @@ "76019c9b41e4fd4c56f4252d399f088b7b3e4470", "reftest" ], - "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue-ref.html": [ - "837c4fd7833d569f2949bf1c2a677836ac851597", - "support" - ], "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-empty-cue.html": [ - "c2d300999eeaa207365b5c0b42f9b033e6b96446", - "reftest" + "427189f6fc78074ae13c58e94ae3d02bc0e513b2", + "testharness" ], "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-line-doesnt-fit-ref.html": [ - "c4c14bc2a394ff19c14bfa76c4b59ad5d6ddb618", + "8354041eb2a0aa57b283e12d9c0390f16327ac80", "support" ], "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-line-doesnt-fit.html": [ @@ -457615,7 +457877,7 @@ "reftest" ], "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-transformed-video-ref.html": [ - "c3ee804c485b762d8b69614136558bbf2ed833a8", + "39461350b089b9041a71a6ca9aad7f1cfc078d68", "support" ], "html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-transformed-video.html": [ @@ -457670,12 +457932,20 @@ "ff447f33f2e85d77dbfc1d84e46e4a2c2ec245ac", "testharness" ], + "html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-error-expected.txt": [ + "4c3f1e5fdded729f49f8dbd82a4953d060002a38", + "support" + ], "html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-error.html": [ - "ffc8ec0682dedc522f4713dcf3ba58b31debbb8b", + "dd97d0522d781f685178763df67dbb3145290ca3", "testharness" ], + "html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-expected.txt": [ + "4c3f1e5fdded729f49f8dbd82a4953d060002a38", + "support" + ], "html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change.html": [ - "34a53d153190afe44357d5b53e184050de092b18", + "f3c78668b4ac6862dc60eb9d4f6c30e149fa07af", "testharness" ], "html/semantics/embedded-content/media-elements/track/track-element/track-helpers.js": [ @@ -457711,7 +457981,7 @@ "testharness" ], "html/semantics/embedded-content/media-elements/track/track-element/track-mode-not-changed-by-new-track.html": [ - "2902ba90bc97355bea3902a1a6dcb81d4e4e9e41", + "3ec47a39e2f229e48c3ae14ec6428c88931013a7", "testharness" ], "html/semantics/embedded-content/media-elements/track/track-element/track-mode-triggers-loading.html": [ @@ -457754,6 +458024,14 @@ "1f7df3b68232eef2010b7c8df665ec39b68af08e", "testharness" ], + "html/semantics/embedded-content/media-elements/track/track-element/track-selection-task-order-expected.txt": [ + "4fddcc451df5ef1673936383c4f029e69842815f", + "support" + ], + "html/semantics/embedded-content/media-elements/track/track-element/track-selection-task-order.html": [ + "522d067adfc500a4e773c267c663f331d86c57cc", + "testharness" + ], "html/semantics/embedded-content/media-elements/track/track-element/track-text-track-cue-list-expected.txt": [ "040deeef2e98886f03913317283e22c787880673", "support" @@ -461367,7 +461645,7 @@ "support" ], "html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.html": [ - "97320090cf039c7352d3f302a42c4bee8765bbd7", + "73eebaff70f09bb98a3b7dd6b59f9357a3ab0668", "testharness" ], "html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener_base-expected.txt": [ @@ -461375,7 +461653,7 @@ "support" ], "html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener_base.html": [ - "8d1b54baccdfd49403c6d192d4c287d3d8818636", + "3da6a49ef866e7c048461d60b398ad619e72d986", "testharness" ], "html/semantics/links/linktypes/alternate-css-ref.html": [ @@ -461407,11 +461685,11 @@ "support" ], "html/semantics/rellist-feature-detection-expected.txt": [ - "a00858d5f893aa6d6e1bff2e145b72ea2c1fcf4d", + "8e4fd0837cfd3d013c37ab0bb1b37439f7a26b7a", "support" ], "html/semantics/rellist-feature-detection.html": [ - "d290439d8ee647b2f8d95ddc45ac390dccde9843", + "45debcc49a487d43437b04e6e8a429f7db321db1", "testharness" ], "html/semantics/scripting-1/META.yml": [ @@ -466370,16 +466648,12 @@ "21c5ea48ad4cadff96c401972594083958f447f3", "testharness" ], - "imagebitmap-renderingcontext/context-creation-offscreen-with-alpha.html": [ - "b565def964d0eb422702bc73054b6c4dfa0a3cb3", - "testharness" - ], - "imagebitmap-renderingcontext/context-creation-offscreen.html": [ - "41cc6dc02a239cf26ea37bbdca1a252f19917ee7", - "testharness" + "imagebitmap-renderingcontext/context-creation-with-alpha-expected.txt": [ + "f4a8ae2398153c9cb61dcc17e9ada6959624c221", + "support" ], "imagebitmap-renderingcontext/context-creation-with-alpha.html": [ - "2c8fa08b9d340c9c0f1cb446a7a445fdc08cfff0", + "4354b9ac4188cd904f7e941001e724f78b0bde54", "testharness" ], "imagebitmap-renderingcontext/context-creation.html": [ @@ -466390,24 +466664,8 @@ "eca7afe9ddd18f23e14f9cb2b16208713af7974b", "testharness" ], - "imagebitmap-renderingcontext/toBlob-origin-clean-offscreen.sub.html": [ - "0a0e203249f13f45198cbc05316b81694377d588", - "testharness" - ], - "imagebitmap-renderingcontext/tranferFromImageBitmap-ToBlob-offscreen.html": [ - "6a555fe25aad6b823a87282472345acb7d9dbf78", - "testharness" - ], - "imagebitmap-renderingcontext/tranferFromImageBitmap-TransferToImageBitmap-offscreen.html": [ - "9f9c3395733a8a39de61ce8a616c3871e20e7e4f", - "testharness" - ], - "imagebitmap-renderingcontext/tranferFromImageBitmap-null-offscreen.html": [ - "e05a623a2fe1d1e290391ca4688285b14b9537b5", - "testharness" - ], "imagebitmap-renderingcontext/tranferFromImageBitmap-null.html": [ - "19d2f17ed3aff43da03836b8a62272e20bf12e55", + "c12a8c93fdb0f83c371982958838b8fa29c4f91d", "testharness" ], "imagebitmap-renderingcontext/transferFromImageBitmap-detached.html": [ @@ -467010,10 +467268,6 @@ "cbae6b15410e13433c4a9fadd8c2a8cc5fbc4fdc", "support" ], - "infrastructure/metadata/infrastructure/testdriver/actions/actionsWithKeyPressed.html.ini": [ - "f62bf62a9713c2c12e4d572e0701efde494224c0", - "support" - ], "infrastructure/metadata/infrastructure/testdriver/actions/elementPosition.html.ini": [ "9ae71a6e73e22a855c69d3269936d71c17d6e9e5", "support" @@ -467214,10 +467468,6 @@ "ea7973a62e0ee9cdc874879fd844b2309e944e61", "testharness" ], - "infrastructure/testdriver/actions/actionsWithKeyPressed.html": [ - "74e939f5fde4773aade6ce4f7bbee573e39ae8ec", - "testharness" - ], "infrastructure/testdriver/actions/elementPosition.html": [ "145852e7b51bd0cdc9e7b4ef5ebddcbf1c0235c5", "testharness" @@ -467603,7 +467853,7 @@ "support" ], "interfaces/html.idl": [ - "a9bd85aff37c761c03c9135f12c71f9c66a4ce77", + "5ae46f742922f4c455380745f124769399086eb9", "support" ], "interfaces/image-capture.idl": [ @@ -467651,7 +467901,7 @@ "support" ], "interfaces/mediacapture-streams.idl": [ - "427aa92dd1f750f305bccb0b9514820f5bc1d29b", + "c07b7e3301248f4945aacbbbe1a0c84330bbe086", "support" ], "interfaces/mediasession.idl": [ @@ -467835,7 +468085,7 @@ "support" ], "interfaces/wake-lock.idl": [ - "863cef13f3c39e852920fdf3763848562fe7360c", + "21a3406f5894629ab5838dcf85474043c5138867", "support" ], "interfaces/wasm-js-api.idl": [ @@ -467863,7 +468113,7 @@ "support" ], "interfaces/webaudio.idl": [ - "4679558023ae87655f46b10d5a57d39269c6e8c9", + "aa137c12f01e0ceee5af4435f38187d19c2acfcb", "support" ], "interfaces/webauthn.idl": [ @@ -467895,7 +468145,7 @@ "support" ], "interfaces/webrtc.idl": [ - "6ae34167ded31a5927791915eb56bc55f09c59dd", + "4b5d1c1c581869cdfcefab4584c2b05b2dcb1f86", "support" ], "interfaces/webusb.idl": [ @@ -467907,7 +468157,7 @@ "support" ], "interfaces/webxr.idl": [ - "2d1bd9fe5f5702d69051fe00b2f958a9a3a4b82c", + "63327a3f55d79f1acdc2cbd53a98b0a089aade2d", "support" ], "interfaces/worklets.idl": [ @@ -481335,7 +481585,7 @@ "testharness" ], "pointerevents/pointerevent_pointerout_pen.html": [ - "972f99d95080ab702da79f8125119a2b27778a84", + "a718468c49a965eefee134cc6e6ec4051042cb49", "testharness" ], "pointerevents/pointerevent_pointerout_received_once.html": [ @@ -481403,7 +481653,7 @@ "testharness" ], "pointerevents/pointerevent_suppress_compat_events_on_drag_mouse.html": [ - "5bab6e66121cebc47213914fb07f7995d8b0722d", + "6ed75ab4cbcda3c673b3328a826019bdade4db5d", "testharness" ], "pointerevents/pointerevent_touch-action-auto-css_touch.html": [ @@ -481419,7 +481669,7 @@ "testharness" ], "pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch.html": [ - "f05aadf39e8435dea374386a796c15fc747f15b0", + "bdd2809354c7a39a7b9acd75c5208cba324fecf1", "testharness" ], "pointerevents/pointerevent_touch-action-inherit_child-none_touch.html": [ @@ -481650,6 +481900,10 @@ "780e8b58af98cc910e3739e3a9a2e5567d5613d0", "testharness" ], + "portals/portal-non-http-navigation.html": [ + "3b79df3c230e1128574d4a6eb81d407cd9303e2c", + "testharness" + ], "portals/portal-onload-event.html": [ "c9f07fcc889043cd523206728f7daaaefa653409", "testharness" @@ -481839,7 +482093,7 @@ "support" ], "preload/download-resources.html": [ - "510ebb480457e9e1b0d6ea788a8bd36c825bc634", + "557c9656b1813c52e373ee70e565a44e966389bf", "testharness" ], "preload/dynamic-adding-preload-imagesrcset.html": [ @@ -481859,7 +482113,7 @@ "testharness" ], "preload/link-header-on-subresource.html": [ - "087a3429e649348d2b35fd92bf03ebc6307c72dc", + "7047115a1caf4989ea5e80e80db35bc2dcdf2a6b", "testharness" ], "preload/link-header-preload-delay-onload.html": [ @@ -481903,7 +482157,7 @@ "support" ], "preload/onerror-event.html": [ - "8190be87a4b7caf69ba07d07d239ff8143be3b05", + "2038e06e941cf7b146fcb744c6c5a2ded3072abc", "testharness" ], "preload/onload-event-expected.txt": [ @@ -481915,11 +482169,11 @@ "testharness" ], "preload/preload-csp.sub.html": [ - "65e9b3a2a6d350598e88cd2c8a7e4fa8d10d7533", + "62d0c71039b7c06a4299ac71e055ff3786de5c41", "testharness" ], "preload/preload-default-csp.sub.html": [ - "923431456cf7e01d66556fda7241be0e660dacc0", + "9fc11945866834c70c9ad270fb11d37a443ac3d0", "testharness" ], "preload/preload-strict-dynamic.html": [ @@ -482570,6 +482824,10 @@ "28e83df6c2ab9b27417b15948929d044095fdceb", "testharness" ], + "referrer-policy/generic/iframe-src-change.html": [ + "15202a76a1ea3b7ad8deb35cdb33826414d7a95b", + "testharness" + ], "referrer-policy/generic/link-rel-prefetch.html": [ "914ddfc4b225d26c675c61ecf623fdebb10e4524", "testharness" @@ -492123,7 +492381,7 @@ "support" ], "resources/chromium/webxr-test.js": [ - "8816273705806dd8efb9c33a52a61689f802ecf2", + "5406b6745bdf021b59aa21f669e0cdbc6e858045", "support" ], "resources/chromium/webxr-test.js.headers": [ @@ -495787,7 +496045,7 @@ "support" ], "service-workers/service-worker/resources/test-helpers.sub.js": [ - "14101319fa9d9e4c76f33a471098d280f117a15f", + "af8dad3a5be8aa831900b183ad7ee9a10417ba1a", "support" ], "service-workers/service-worker/resources/test-request-headers-worker.js": [ @@ -495815,7 +496073,11 @@ "support" ], "service-workers/service-worker/resources/update-during-installation-worker.js": [ - "dabeec077f77d5e8d1924eb5f3bd5d8667b129f5", + "3f89881c04384590b8b132c392977256bfb847ed", + "support" + ], + "service-workers/service-worker/resources/update-during-installation-worker.py": [ + "95e4522007c1d2be14045f7582ebe2b5347abd87", "support" ], "service-workers/service-worker/resources/update-fetch-worker.py": [ @@ -496063,7 +496325,7 @@ "testharness" ], "service-workers/service-worker/update-not-allowed.https.html": [ - "71fe1730e0d68e4e7e0949cfa408d3c2d4ed9d39", + "0a54aa9350382bb082f407a1ea30b265575baae9", "testharness" ], "service-workers/service-worker/update-on-navigation.https.html": [ @@ -504783,7 +505045,7 @@ "support" ], "tools/wptrunner/wptrunner/browsers/firefox.py": [ - "454b08612aaca41e439fc7a9011019e7c4655c26", + "3b6949a42f5df564284eea15cd110e8c1a7763ee", "support" ], "tools/wptrunner/wptrunner/browsers/ie.py": [ @@ -506662,18 +506924,22 @@ "6f05d23550e2b0c967fac5b436a5e3336222ffe2", "support" ], - "wake-lock/wakelock-insecure-context.html": [ - "2c61f41311db3f9edf0502ea752ca27970eed3fb", + "wake-lock/wakelock-insecure-context.any.js": [ + "f32cc3c354354f99852bb198760cdbd9229355a4", + "testharness" + ], + "wake-lock/wakelock-screen-type-on-worker.https.worker-expected.txt": [ + "7019eb31819a0309d864b0bae9112977e6bbe04b", + "support" + ], + "wake-lock/wakelock-screen-type-on-worker.https.worker.js": [ + "28e3394279c0b4311a80aad43ced0f9ea79e029f", "testharness" ], "wake-lock/wakelock-state-is-global.https-expected.txt": [ "08b692aa24612df2abc368d9afd1075449409b65", "support" ], - "wake-lock/wakelock-state-is-global.https.html": [ - "2eee31982498caab44b5160237c7ce7f8ce9a569", - "testharness" - ], "wake-lock/wakelock-supported-by-feature-policy.html": [ "d6289fff43c8717ac6e9ace59713e6fd70bd249d", "testharness" @@ -506682,10 +506948,14 @@ "409d107ad314e8b92d69fd27e40f2e6a89c9c63c", "support" ], - "wake-lock/wakelock-type.https.html": [ - "df7a68a040bef273efcd2584dfe3612adc05d85b", + "wake-lock/wakelock-type.https.any.js": [ + "cc37c768272512ec412fb749cebd77afa8662ac3", "testharness" ], + "wake-lock/wakelock-type.https.any.worker-expected.txt": [ + "9d738db325137ae52ec28c20e296b2ece04fede7", + "support" + ], "wasm/META.yml": [ "3ea02ee7c9e41831aafbd37436f59b51244b142e", "support" @@ -507266,10 +507536,6 @@ "9005db9e9f2a8bcf3c9bf90bcea0ca882398442f", "testharness" ], - "web-animations/interfaces/Animation/constructor-expected.txt": [ - "aee33fa5df746c6835fcff3325d2236fb6edfe85", - "support" - ], "web-animations/interfaces/Animation/constructor.html": [ "fcbaab1e8dbad3a64852c67931ba7be97b94b0d3", "testharness" @@ -507558,6 +507824,10 @@ "9d07d53df46164d53b1a3c8f4a10787608c5f014", "testharness" ], + "web-animations/timing-model/animations/setting-the-start-time-of-an-animation-expected.txt": [ + "5677028f1a13bc273443b1d8f1c989cf7f2ded47", + "support" + ], "web-animations/timing-model/animations/setting-the-start-time-of-an-animation.html": [ "454a294239aa61130dc56af910fe1aa8faf4900b", "testharness" @@ -507571,7 +507841,7 @@ "testharness" ], "web-animations/timing-model/animations/setting-the-timeline-of-an-animation-expected.txt": [ - "a1f4b2ba477fadf6a05988b605e0996944e9face", + "1b685b0566ee9e911c2ff10658344aa0d25c7ea4", "support" ], "web-animations/timing-model/animations/setting-the-timeline-of-an-animation.html": [ @@ -507587,7 +507857,7 @@ "testharness" ], "web-animations/timing-model/time-transformations/transformed-progress-expected.txt": [ - "756e479dd16b564fa648b7c0fa829dcfb591d151", + "7f4f1efda60a77468f935161dd930411cd3c654e", "support" ], "web-animations/timing-model/time-transformations/transformed-progress.html": [ @@ -510731,11 +511001,11 @@ "testharness" ], "webrtc/RTCPeerConnection-addIceCandidate-expected.txt": [ - "bd31c0bae79f5f15c96716a48a7103f551ba535a", + "1ca662a424c727cd2876fe769d45a9da4100d487", "support" ], "webrtc/RTCPeerConnection-addIceCandidate.html": [ - "c51c11fccbfae40de733b882503be402cbf7aa7a", + "ed52ace59e60c1ea11285052ab2e1efa17a4d941", "testharness" ], "webrtc/RTCPeerConnection-addTrack.https.html": [ @@ -510823,7 +511093,7 @@ "testharness" ], "webrtc/RTCPeerConnection-helper.js": [ - "fde1c6f0374a02c0998fdfe3a1ba5e7046d314f4", + "d859ac736ae6bf0187640dbe2148d8e0d64d9345", "support" ], "webrtc/RTCPeerConnection-iceConnectionState-disconnected.https.html": [ @@ -518759,7 +519029,7 @@ "support" ], "xhr/resources/access-control-basic-options-not-supported.py": [ - "0c69c76293eaeebc1e9c18fed7904c3bdcdc0d8e", + "77b274e957ca87270926ad4622d2c79ec9600fed", "support" ], "xhr/resources/access-control-basic-preflight-cache-invalidation.py": [ @@ -519215,11 +519485,11 @@ "testharness" ], "xhr/responsexml-document-properties-expected.txt": [ - "a81e1945acb11ce4a31d375186db53782d88913a", + "c7661c57fd9a9d4a5c6cf0bd78d914d8eaccffc1", "support" ], "xhr/responsexml-document-properties.htm": [ - "b008348e58f0f8751d9d1b83531e843af8239a6d", + "9071fab121fc8e55d885c4fc89636380b66c226c", "testharness" ], "xhr/responsexml-get-twice.htm": [
diff --git a/third_party/blink/web_tests/external/wpt/bluetooth/characteristic/writeValue/buffer-is-detached.https.html b/third_party/blink/web_tests/external/wpt/bluetooth/characteristic/writeValue/buffer-is-detached.https.html index 762735c..b8a1abfa 100644 --- a/third_party/blink/web_tests/external/wpt/bluetooth/characteristic/writeValue/buffer-is-detached.https.html +++ b/third_party/blink/web_tests/external/wpt/bluetooth/characteristic/writeValue/buffer-is-detached.https.html
@@ -11,26 +11,18 @@ window.postMessage('', '*', [buffer]); } -bluetooth_test(async () => { +bluetooth_test(async (t) => { let {characteristic, fake_characteristic} = await getMeasurementIntervalCharacteristic(); let typed_array = Uint8Array.of(1, 2); detachBuffer(typed_array.buffer); - try { - await characteristic.writeValue(typed_array); - assert_unreached(); - } catch (e) { - assert_equals(e.code, DOMException.INVALID_STATE_ERR, e.toString()); - } + await promise_rejects( + t, 'InvalidStateError', characteristic.writeValue(typed_array)); let array_buffer = Uint8Array.of(3, 4).buffer; detachBuffer(array_buffer); - try { - await characteristic.writeValue(array_buffer); - assert_unreached(); - } catch (e) { - assert_equals(e.code, DOMException.INVALID_STATE_ERR, e.toString()); - } + await promise_rejects( + t, 'InvalidStateError', characteristic.writeValue(array_buffer)); }, 'writeValue() fails when passed a detached buffer'); </script>
diff --git a/third_party/blink/web_tests/external/wpt/bluetooth/descriptor/writeValue/buffer-is-detached.https.html b/third_party/blink/web_tests/external/wpt/bluetooth/descriptor/writeValue/buffer-is-detached.https.html index 2402d89..2ab990d 100644 --- a/third_party/blink/web_tests/external/wpt/bluetooth/descriptor/writeValue/buffer-is-detached.https.html +++ b/third_party/blink/web_tests/external/wpt/bluetooth/descriptor/writeValue/buffer-is-detached.https.html
@@ -11,26 +11,18 @@ window.postMessage('', '*', [buffer]); } -bluetooth_test(async () => { +bluetooth_test(async (t) => { let {descriptor, fake_descriptor} = await getUserDescriptionDescriptor(); let typed_array = Uint8Array.of(1, 2); detachBuffer(typed_array.buffer); - try { - await descriptor.writeValue(typed_array); - assert_unreached(); - } catch (e) { - assert_equals(e.code, DOMException.INVALID_STATE_ERR, e.toString()); - } + await promise_rejects( + t, 'InvalidStateError', descriptor.writeValue(typed_array)); let array_buffer = Uint8Array.of(3, 4).buffer; detachBuffer(array_buffer); - try { - await descriptor.writeValue(array_buffer); - assert_unreached(); - } catch (e) { - assert_equals(e.code, DOMException.INVALID_STATE_ERR, e.toString()); - } + await promise_rejects( + t, 'InvalidStateError', descriptor.writeValue(array_buffer)); }, 'writeValue() fails when passed a detached buffer'); </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/reference/text-transform-upperlower-039-ref.html b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/reference/text-transform-upperlower-039-ref.html index 0e243ed..f4fb680 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/reference/text-transform-upperlower-039-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/reference/text-transform-upperlower-039-ref.html
@@ -17,7 +17,10 @@ </head> <body> <p class="instructions">Test passes if both characters in each pair match. If you are missing a font glyph for a character, ignore that pair, but report which characters were ignored.</p> -<div class="test" lang="lt"><span>i̇̀ i̇̀</span> <span>i̇́ i̇́</span> <span>i̇̃ i̇̃</span></div> +<div class="test" lang="lt"> + <span>i̇̀ i̇̀</span> <span>i̇́ i̇́</span> <span>i̇̃ i̇̃</span> + <span>i̇̀ i̇̀</span> <span>j̇́ j̇́</span> <span>į̇̃ į̇̃</span> +</div> <!--Notes: The language of the test box is set to Lithuanian (lt) -->
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/reference/text-transform-upperlower-044-ref.html b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/reference/text-transform-upperlower-044-ref.html new file mode 100644 index 0000000..3eed1ed --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/reference/text-transform-upperlower-044-ref.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html lang="en"> +<head> +<meta charset="utf-8"/> +<title>CSS3 Text, text transform: Lithuanian, uppercase</title> +<link rel='author' title='Jonathan Kew' href='mailto:jkew@mozilla.com'> +<style type='text/css'> +@font-face { + font-family: 'webfont'; + src: url('/fonts/DoulosSIL-R.woff') format('woff'); + font-weight: normal; + font-style: normal; + } +.test, .ref { font-size: 200%; line-height: 2.5em; font-family: webfont, serif; } +.test span, .ref span { margin-right: 1em; white-space: nowrap; } +</style> +</head> +<body> +<p class="instructions">Test passes if both characters in each pair match. If you are missing a font glyph for a character, ignore that pair, but report which characters were ignored.</p> +<div class="test" lang="lt"> + <span>Ì Ì</span> + <span>Í Í</span> + <span>Ĩ Ĩ</span> + <span>I I</span> + <span>J J</span> + <span>Į Į</span> + <span>Ẋ Ẋ</span> +</div> +<!--Notes: +The language of the test box is set to Lithuanian (lt) +--> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-upperlower-039.html b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-upperlower-039.html index 40f36e0..470a4f6f 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-upperlower-039.html +++ b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-upperlower-039.html
@@ -22,7 +22,10 @@ </head> <body> <p class="instructions">Test passes if both characters in each pair match. If you are missing a font glyph for a character, ignore that pair, but report which characters were ignored.</p> -<div class="test" lang="lt"><span>Ì i̇̀</span> <span>Í i̇́</span> <span>Ĩ i̇̃</span></div> +<div class="test" lang="lt"> + <span>Ì i̇̀</span> <span>Í i̇́</span> <span>Ĩ i̇̃</span> + <span>Ì i̇̀</span> <span>J́ j̇́</span> <span>Į̃ į̇̃</span> +</div> <!--Notes: The language of the test box is set to Lithuanian (lt) -->
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-upperlower-044.html b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-upperlower-044.html new file mode 100644 index 0000000..6d81c45 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-upperlower-044.html
@@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html lang="en"> +<head> +<meta charset="utf-8"/> +<title>CSS3 Text, text transform: Lithuanian, uppercase</title> +<meta name="assert" content="text-transform: uppercase will uppercase Lithuanian as described in Unicode's SpecialCasing.txt ."> +<link rel='author' title='Jonathan Kew' href='mailto:jkew@mozilla.com'> +<link rel='help' href='https://drafts.csswg.org/css-text-3/#text-transform'> +<link rel="match" href="reference/text-transform-upperlower-044-ref.html"> +<style type='text/css'> +@font-face { + font-family: 'webfont'; + src: url('/fonts/DoulosSIL-R.woff') format('woff'); + font-weight: normal; + font-style: normal; + } +.test, .ref { font-size: 200%; line-height: 2.5em; font-family: webfont, serif; } +.test span, .ref span { margin-right: 1em; white-space: nowrap; } +/* the CSS above is not part of the test */ +.test { text-transform: uppercase; } +</style> +</head> +<body> +<p class="instructions">Test passes if both characters in each pair match. If you are missing a font glyph for a character, ignore that pair, but report which characters were ignored.</p> +<div class="test" lang="lt"> + <span>i̇̀ Ì</span> + <span>i̇́ Í</span> + <span>i̇̃ Ĩ</span> + <span>i̇ I</span> + <span>j̇ J</span> + <span>į̇ Į</span> + <span>ẋ Ẋ</span> <!-- check that dot isn't deleted in other contexts --> +</div> +<!--Notes: +The language of the test box is set to Lithuanian (lt) +--> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/dom/events/EventListener-handleEvent-expected.txt b/third_party/blink/web_tests/external/wpt/dom/events/EventListener-handleEvent-expected.txt index 5269d0c..ee188fd9 100644 --- a/third_party/blink/web_tests/external/wpt/dom/events/EventListener-handleEvent-expected.txt +++ b/third_party/blink/web_tests/external/wpt/dom/events/EventListener-handleEvent-expected.txt
@@ -2,6 +2,8 @@ PASS calls `handleEvent` method of `EventListener` PASS rethrows errors when getting `handleEvent` PASS performs `Get` every time event is dispatched -FAIL throws if `handleEvent` is not callable assert_true: expected true got false +PASS doesn't call `handleEvent` method on callable `EventListener` +FAIL throws if `handleEvent` is falsy and not callable assert_true: expected true got false +FAIL throws if `handleEvent` is thruthy and not callable assert_true: expected true got false Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/dom/events/EventListener-handleEvent.html b/third_party/blink/web_tests/external/wpt/dom/events/EventListener-handleEvent.html index 6630f27..1eb80cc 100644 --- a/third_party/blink/web_tests/external/wpt/dom/events/EventListener-handleEvent.html +++ b/third_party/blink/web_tests/external/wpt/dom/events/EventListener-handleEvent.html
@@ -5,13 +5,12 @@ <script src="/resources/testharnessreport.js"></script> <link rel="help" href="https://dom.spec.whatwg.org/#callbackdef-eventlistener"> <div id=log></div> -<div id=target></div> <script> setup({ allow_uncaught_exception: true }); test(function(t) { var type = "foo"; - var target = document.getElementById("target"); + var target = document.createElement("div"); var eventListener = { handleEvent: function(evt) { var that = this; @@ -30,12 +29,16 @@ test(function(t) { var type = "foo"; - var target = document.getElementById("target"); - var thrownError = new Error(); + var target = document.createElement("div"); + var thrownError = { name: "test" }; var uncaughtError; - - window.addEventListener("error", function(event) { + var errorHandler = function(event) { uncaughtError = event.error; + }; + + window.addEventListener("error", errorHandler); + t.add_cleanup(function() { + window.removeEventListener("error", errorHandler); }); target.addEventListener(type, { @@ -50,7 +53,7 @@ test(function(t) { var type = "foo"; - var target = document.getElementById("target"); + var target = document.createElement("div"); var calls = 0; target.addEventListener(type, { @@ -68,11 +71,27 @@ test(function(t) { var type = "foo"; - var target = document.getElementById("target"); - var uncaughtError; + var target = document.createElement("div"); + var calls = 0; + var eventListener = function() { calls++; }; + eventListener.handleEvent = t.unreached_func("`handleEvent` method should not be called on functions"); - window.addEventListener("error", function(event) { + target.addEventListener(type, eventListener); + target.dispatchEvent(new Event(type)); + assert_equals(calls, 1); +}, "doesn't call `handleEvent` method on callable `EventListener`"); + +test(function(t) { + var type = "foo"; + var target = document.createElement("div"); + var uncaughtError; + var errorHandler = function(event) { uncaughtError = event.error; + }; + + window.addEventListener("error", errorHandler); + t.add_cleanup(function() { + window.removeEventListener("error", errorHandler); }); target.addEventListener(type, { @@ -81,5 +100,26 @@ target.dispatchEvent(new Event(type)); assert_true(uncaughtError instanceof TypeError); -}, "throws if `handleEvent` is not callable"); +}, "throws if `handleEvent` is falsy and not callable"); + +test(function(t) { + var type = "foo"; + var target = document.createElement("div"); + var uncaughtError; + var errorHandler = function(event) { + uncaughtError = event.error; + }; + + window.addEventListener("error", errorHandler); + t.add_cleanup(function() { + window.removeEventListener("error", errorHandler); + }); + + target.addEventListener(type, { + handleEvent: 1, + }); + + target.dispatchEvent(new Event(type)); + assert_true(uncaughtError instanceof TypeError); +}, "throws if `handleEvent` is thruthy and not callable"); </script>
diff --git a/third_party/blink/web_tests/external/wpt/dom/traversal/TreeWalker-acceptNode-filter.html b/third_party/blink/web_tests/external/wpt/dom/traversal/TreeWalker-acceptNode-filter.html index 1446f40f..e2110aff 100644 --- a/third_party/blink/web_tests/external/wpt/dom/traversal/TreeWalker-acceptNode-filter.html +++ b/third_party/blink/web_tests/external/wpt/dom/traversal/TreeWalker-acceptNode-filter.html
@@ -8,6 +8,7 @@ <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="traversal-support.js"></script> +<link rel="help" href="https://dom.spec.whatwg.org/#callbackdef-nodefilter"> <div id=log></div> </head> <body> @@ -102,10 +103,10 @@ assert_node(walker.currentNode, { type: Element, id: 'root' }); }, 'Testing with object with non-function acceptNode property'); -test(function() +test(function(t) { var filter = function() { return NodeFilter.FILTER_ACCEPT; }; - filter.acceptNode = function(node) { return NodeFilter.FILTER_SKIP; }; + filter.acceptNode = t.unreached_func("`acceptNode` method should not be called on functions"); var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, filter); assert_node(walker.firstChild(), { type: Element, id: 'A1' }); assert_node(walker.nextNode(), { type: Element, id: 'B1' }); @@ -113,17 +114,6 @@ test(function() { - var filter = { - acceptNode: function(node) { - return NodeFilter.FILTER_ACCEPT; - } - }; - var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, filter); - assert_node(walker.firstChild(), { type: Element, id: 'A1' }); -}, 'Testing acceptNode callee'); - -test(function() -{ var test_error = { name: "test" }; var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, function(node) { @@ -135,6 +125,38 @@ assert_node(walker.currentNode, { type: Element, id: 'root' }); }, 'Testing with filter function that throws'); +test(function() { + var testError = { name: "test" }; + var filter = { + get acceptNode() { + throw testError; + }, + }; + + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, filter); + assert_throws(testError, function() { walker.firstChild(); }); + assert_node(walker.currentNode, { type: Element, id: 'root' }); + assert_throws(testError, function() { walker.nextNode(); }); + assert_node(walker.currentNode, { type: Element, id: 'root' }); +}, "rethrows errors when getting `acceptNode`"); + +test(function() { + var calls = 0; + var walker = document.createTreeWalker(testElement, NodeFilter.SHOW_ELEMENT, { + get acceptNode() { + calls++; + return function() { + return NodeFilter.FILTER_ACCEPT; + }; + }, + }); + + assert_equals(calls, 0); + walker.nextNode(); + walker.nextNode(); + assert_equals(calls, 2); +}, "performs `Get` on every traverse"); + test(function() { var test_error = { name: "test" };
diff --git "a/third_party/blink/web_tests/external/wpt/html/dom/interfaces.https_exclude=\050Document_Window_HTML._\051-expected.txt" "b/third_party/blink/web_tests/external/wpt/html/dom/interfaces.https_exclude=\050Document_Window_HTML._\051-expected.txt" index d9a59c8..efc72ac6 100644 --- "a/third_party/blink/web_tests/external/wpt/html/dom/interfaces.https_exclude=\050Document_Window_HTML._\051-expected.txt" +++ "b/third_party/blink/web_tests/external/wpt/html/dom/interfaces.https_exclude=\050Document_Window_HTML._\051-expected.txt"
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 1148 tests; 1131 PASS, 17 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 1163 tests; 1146 PASS, 17 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS idl_test setup PASS Partial interface Document: original interface defined PASS Partial interface mixin NavigatorID: original interface mixin defined @@ -643,6 +643,21 @@ PASS CustomElementRegistry interface: operation get(DOMString) PASS CustomElementRegistry interface: operation whenDefined(DOMString) PASS CustomElementRegistry interface: operation upgrade(Node) +PASS ElementInternals interface: existence and properties of interface object +PASS ElementInternals interface object length +PASS ElementInternals interface object name +PASS ElementInternals interface: existence and properties of interface prototype object +PASS ElementInternals interface: existence and properties of interface prototype object's "constructor" property +PASS ElementInternals interface: existence and properties of interface prototype object's @@unscopables property +PASS ElementInternals interface: operation setFormValue([object Object],[object Object],[object Object], [object Object],[object Object],[object Object]) +PASS ElementInternals interface: attribute form +PASS ElementInternals interface: operation setValidity(ValidityStateFlags, DOMString, HTMLElement) +PASS ElementInternals interface: attribute willValidate +PASS ElementInternals interface: attribute validity +PASS ElementInternals interface: attribute validationMessage +PASS ElementInternals interface: operation checkValidity() +PASS ElementInternals interface: operation reportValidity() +PASS ElementInternals interface: attribute labels PASS DataTransfer interface: existence and properties of interface object PASS DataTransfer interface object length PASS DataTransfer interface object name
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/interfaces.https_include=HTML._-expected.txt b/third_party/blink/web_tests/external/wpt/html/dom/interfaces.https_include=HTML._-expected.txt index 9eb12ff..ff83da82f 100644 --- a/third_party/blink/web_tests/external/wpt/html/dom/interfaces.https_include=HTML._-expected.txt +++ b/third_party/blink/web_tests/external/wpt/html/dom/interfaces.https_include=HTML._-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 3613 tests; 3572 PASS, 41 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 3618 tests; 3577 PASS, 41 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS idl_test setup PASS Partial interface Document: original interface defined PASS Partial interface mixin NavigatorID: original interface mixin defined @@ -100,6 +100,7 @@ PASS HTMLElement interface: attribute spellcheck PASS HTMLElement interface: attribute autocapitalize PASS HTMLElement interface: attribute innerText +PASS HTMLElement interface: operation attachInternals() PASS HTMLElement interface: attribute onabort PASS HTMLElement interface: attribute onauxclick PASS HTMLElement interface: attribute onblur @@ -189,6 +190,7 @@ PASS HTMLElement interface: document.createElement("noscript") must inherit property "spellcheck" with the proper type PASS HTMLElement interface: document.createElement("noscript") must inherit property "autocapitalize" with the proper type PASS HTMLElement interface: document.createElement("noscript") must inherit property "innerText" with the proper type +PASS HTMLElement interface: document.createElement("noscript") must inherit property "attachInternals()" with the proper type PASS HTMLElement interface: document.createElement("noscript") must inherit property "onabort" with the proper type PASS HTMLElement interface: document.createElement("noscript") must inherit property "onauxclick" with the proper type PASS HTMLElement interface: document.createElement("noscript") must inherit property "onblur" with the proper type @@ -1479,6 +1481,7 @@ PASS HTMLFormElement interface: attribute elements PASS HTMLFormElement interface: attribute length PASS HTMLFormElement interface: operation submit() +PASS HTMLFormElement interface: operation requestSubmit(HTMLElement) PASS HTMLFormElement interface: operation reset() PASS HTMLFormElement interface: operation checkValidity() PASS HTMLFormElement interface: operation reportValidity() @@ -1498,6 +1501,8 @@ PASS HTMLFormElement interface: document.createElement("form") must inherit property "elements" with the proper type PASS HTMLFormElement interface: document.createElement("form") must inherit property "length" with the proper type PASS HTMLFormElement interface: document.createElement("form") must inherit property "submit()" with the proper type +PASS HTMLFormElement interface: document.createElement("form") must inherit property "requestSubmit(HTMLElement)" with the proper type +PASS HTMLFormElement interface: calling requestSubmit(HTMLElement) on document.createElement("form") with too few arguments must throw TypeError PASS HTMLFormElement interface: document.createElement("form") must inherit property "reset()" with the proper type PASS HTMLFormElement interface: document.createElement("form") must inherit property "checkValidity()" with the proper type PASS HTMLFormElement interface: document.createElement("form") must inherit property "reportValidity()" with the proper type
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/interfaces.worker-expected.txt b/third_party/blink/web_tests/external/wpt/html/dom/interfaces.worker-expected.txt index e00efd4..c2e30c2e 100644 --- a/third_party/blink/web_tests/external/wpt/html/dom/interfaces.worker-expected.txt +++ b/third_party/blink/web_tests/external/wpt/html/dom/interfaces.worker-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 652 tests; 611 PASS, 41 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 660 tests; 611 PASS, 49 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS idl_test setup PASS Partial interface Document: original interface defined PASS Partial interface mixin NavigatorID: original interface mixin defined @@ -188,7 +188,14 @@ PASS Path2D interface: operation rect(unrestricted double, unrestricted double, unrestricted double, unrestricted double) PASS Path2D interface: operation arc(unrestricted double, unrestricted double, unrestricted double, unrestricted double, unrestricted double, boolean) PASS Path2D interface: operation ellipse(unrestricted double, unrestricted double, unrestricted double, unrestricted double, unrestricted double, unrestricted double, unrestricted double, boolean) -PASS ImageBitmapRenderingContext interface: existence and properties of interface object +FAIL ImageBitmapRenderingContext interface: existence and properties of interface object assert_own_property: self does not have own property "ImageBitmapRenderingContext" expected property "ImageBitmapRenderingContext" missing +FAIL ImageBitmapRenderingContext interface object length assert_own_property: self does not have own property "ImageBitmapRenderingContext" expected property "ImageBitmapRenderingContext" missing +FAIL ImageBitmapRenderingContext interface object name assert_own_property: self does not have own property "ImageBitmapRenderingContext" expected property "ImageBitmapRenderingContext" missing +FAIL ImageBitmapRenderingContext interface: existence and properties of interface prototype object assert_own_property: self does not have own property "ImageBitmapRenderingContext" expected property "ImageBitmapRenderingContext" missing +FAIL ImageBitmapRenderingContext interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "ImageBitmapRenderingContext" expected property "ImageBitmapRenderingContext" missing +FAIL ImageBitmapRenderingContext interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "ImageBitmapRenderingContext" expected property "ImageBitmapRenderingContext" missing +FAIL ImageBitmapRenderingContext interface: attribute canvas assert_own_property: self does not have own property "ImageBitmapRenderingContext" expected property "ImageBitmapRenderingContext" missing +FAIL ImageBitmapRenderingContext interface: operation transferFromImageBitmap(ImageBitmap) assert_own_property: self does not have own property "ImageBitmapRenderingContext" expected property "ImageBitmapRenderingContext" missing PASS OffscreenCanvas interface: existence and properties of interface object PASS OffscreenCanvas interface object length PASS OffscreenCanvas interface object name @@ -278,6 +285,7 @@ PASS OffscreenCanvasRenderingContext2D interface: operation arc(unrestricted double, unrestricted double, unrestricted double, unrestricted double, unrestricted double, boolean) PASS OffscreenCanvasRenderingContext2D interface: operation ellipse(unrestricted double, unrestricted double, unrestricted double, unrestricted double, unrestricted double, unrestricted double, unrestricted double, boolean) PASS CustomElementRegistry interface: existence and properties of interface object +PASS ElementInternals interface: existence and properties of interface object PASS DataTransfer interface: existence and properties of interface object PASS DataTransferItemList interface: existence and properties of interface object PASS DataTransferItem interface: existence and properties of interface object
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-active-cues.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-active-cues.html index 67ab3bdb..501cf3f92 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-active-cues.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-active-cues.html
@@ -17,6 +17,9 @@ var video = document.createElement('video'); video.src = getVideoURI('/media/movie_5'); + // uanset media element's `show-poster` flag in order to run `time marches on` + // when we add new cues into media element's cues list. + video.play(); var trackElement = document.createElement('track'); trackElement.onload = t.step_func(eventCallback); @@ -36,4 +39,4 @@ trackElement.default = true; video.appendChild(trackElement); }); -</script> \ No newline at end of file +</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-error-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-error-expected.txt new file mode 100644 index 0000000..4c3f1e5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-error-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL HTMLTrackElement 'src' attribute mutations assert_equals: cues list is reset immediately after 'src' mutation with the new URL expected 0 but got 4 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-error.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-error.html index ffc8ec0..dd97d05 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-error.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-error.html
@@ -21,7 +21,7 @@ break; case 1: case 3: - case 5: + case 4: assert_unreached("'error' event did not fire, stage = " + stage); break; case 2: @@ -30,21 +30,10 @@ assert_equals(cues[cues.length-1].text, 'I said Bear is coming now!!!! Tab separators.', "Last cue content check"); ++stage; testTrack.src = ""; // this should fail - // CuesList will be cleared in the next tick. Spec claims that this should happen immediately, - // but all implementations are doing this asynchronously. - assert_equals(cues.length, 4, "Number of cues immediately after 'src' mutation with the empty URL"); + assert_equals(cues.length, 0, "cues list is reset immediately after 'src' mutation with the new URL"); // This should raise onError event. If no, we'll know about this after some time. timer = t.step_timeout(t.unreached_func("'error' event is not fired when an empty URL is set"), 100); break; - case 4: - assert_equals(testTrack.readyState, HTMLTrackElement.LOADED, "readyState after loading of the second track"); - assert_equals(cues.length, 4, "Number of cues after loading of the second track"); - assert_equals(cues[cues.length-1].text, 'I said Bear is coming now!!!! Tab separators.', "Last cue content check"); - ++stage; - testTrack.removeAttribute('src'); - // This should raise onError event, so we'll wait for it for some time - timer = t.step_timeout(t.unreached_func("'error' event is not fired when an empty URL is set"), 100); - break; default: assert_unreached("unexpected stage number = " + stage); break; @@ -55,7 +44,6 @@ switch (stage) { case 0: case 2: - case 4: assert_unreached("'error' event fired, stage = " + stage); break; case 1: @@ -72,8 +60,14 @@ assert_equals(cues.length, 0, "Number of cues with an empty URL set"); ++stage; testTrack.src = "resources/settings.vtt"; + // error should happen when we remove `src` during loading, so we have to wait a task because loading starts asynchronously. + t.step_timeout(() => { + testTrack.removeAttribute('src'); + // This should raise onError event, so we'll wait for it for some time + timer = t.step_timeout(t.unreached_func("'error' event is not fired when an empty URL is set"), 100); + }, 0); break; - case 5: + case 4: clearTimeout(timer); assert_equals(testTrack.readyState, HTMLTrackElement.ERROR, "readyState after removing 'src' attr"); assert_equals(cues.length, 0, "Number of cues after removing 'src' attr"); @@ -89,4 +83,4 @@ testTrack.onerror = t.step_func(step_onError); }); </script> -</video> \ No newline at end of file +</video>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-expected.txt new file mode 100644 index 0000000..4c3f1e5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL HTMLTrackElement 'src' attribute mutations assert_equals: cues list is reset immediately after 'src' mutation with the new URL expected 0 but got 4 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change.html index 34a53d15..f3c78668 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change.html
@@ -18,9 +18,7 @@ assert_equals(cues[cues.length-1].text, 'I said Bear is coming now!!!! Tab separators.', "Last cue content check"); ++stage; testTrack.src = "resources/entities.vtt"; - // CuesList will be cleared in a microtask. Spec claims that this should happen immediately, - // but all known implementations are doing this asynchronously. - assert_equals(cues.length, 4, "Number of cues immediately after 'src' mutation with the new URL"); + assert_equals(cues.length, 0, "cues list is reset immediately after 'src' mutation with the new URL"); break; case 1: assert_equals(testTrack.readyState, HTMLTrackElement.LOADED), "readyState after loading of the second track"; @@ -54,4 +52,4 @@ testTrack.onerror = t.unreached_func("'error' event should not fire"); }); </script> -</video> \ No newline at end of file +</video>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-mode-not-changed-by-new-track.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-mode-not-changed-by-new-track.html index 2902ba9..3ec47a3 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-mode-not-changed-by-new-track.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-mode-not-changed-by-new-track.html
@@ -33,11 +33,12 @@ assert_equals(track1.track.cues.length, 12); assert_equals(track1.track.cues[11].startTime, 22); - // Add a caption track, configured to load automatically. + // Add a caption track, and explicitly enable it. track2 = document.createElement('track'); track2.setAttribute('kind', 'captions'); track2.setAttribute('default', 'default'); track2.setAttribute('src', 'resources/webvtt-file.vtt'); + track2.track.mode = 'showing'; track2.onload = t.step_func(captionsTrackLoaded); video.appendChild(track2); } @@ -56,7 +57,7 @@ track3.mode = 'showing'; } - function trackAdded() { + function trackAdded(event) { // Check that metadata track state has not changed. assert_equals(track1.readyState, HTMLTrackElement.LOADED); assert_equals(track1.track.mode, 'hidden');
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-selection-task-order-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-selection-task-order-expected.txt new file mode 100644 index 0000000..4fddcc4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-selection-task-order-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL HTMLTrackElement Text Track Selection Task Order assert_equals: Text track selection hasn't started yet. expected "disabled" but got "showing" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-selection-task-order.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-selection-task-order.html new file mode 100644 index 0000000..522d067a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-selection-task-order.html
@@ -0,0 +1,36 @@ +<!DOCTYPE html> +<title>HTMLTrackElement Text Track Selection Task Order</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +/** + * This test is used to ensure that we queue 'honor user preferences for automatic + * text track selection' as a macro task, not a micro task. In this test, we + * trigger a media event before queuing a text track selection task, and check + * the text track's mode to know whether the text track selection runs after the + * task for media event. + */ +async_test(function(t) { + let video = document.createElement("video"); + video.play(); + video.onplay = t.step_func(startedPlay); + + // When we create a text track element, it queue a task to run automatic + // text track selection later. + let track = document.createElement("track"); + track.default = true; + video.appendChild(track); + assert_equals(track.track.mode, "disabled", "Text track's mode is disabled by default."); + + function startedPlay() { + assert_equals(track.track.mode, "disabled", "Text track selection hasn't started yet."); + track.onerror = t.step_func_done(trackError); + } + + function trackError() { + assert_equals(track.track.mode, "showing", "Text track selection modified track's mode."); + t.done(); + } +}); + +</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.html b/third_party/blink/web_tests/external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.html index 9732009..73eebaf 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.html
@@ -17,21 +17,12 @@ <a href="support/target_blank_implicit_noopener.html?a7" id="a7" rel="opener noreferrer" target="_blank">Click me</a> <a href="support/target_blank_implicit_noopener.html?a8" id="a8" rel="noopener opener noreferrer" target="_blank">Click me</a> - <img src="/images/threecolors.png" /> - <area shape="rect" coords="0,0,99,50" href="support/target_blank_implicit_noopener.html?area1" id="area1" rel="noopener" target="_blank" /> - </img> - <img src="/images/threecolors.png" /> - <area shape="rect" coords="0,0,99,50" href="support/target_blank_implicit_noopener.html?area2" id="area2" rel="opener" target="_blank" /> - </img> - <img src="/images/threecolors.png" /> - <area shape="rect" coords="0,0,99,50" href="support/target_blank_implicit_noopener.html?area3" id="area3" target="_blank" /> - </img> - <img src="/images/threecolors.png" /> - <area shape="rect" coords="0,0,99,50" href="support/target_blank_implicit_noopener.html?area4" id="area4" rel="opener noopener" target="_blank" /> - </img> - <img src="/images/threecolors.png" /> - <area shape="rect" coords="0,0,99,50" href="support/target_blank_implicit_noopener.html?area5" id="area5" rel="noopener opener" target="_blank" /> - </img> + <!-- Although this is not valid, per the processing model of area it ought to work --> + <area shape="rect" coords="0,0,99,50" href="support/target_blank_implicit_noopener.html?area1" id="area1" rel="noopener" target="_blank"> + <area shape="rect" coords="0,0,99,50" href="support/target_blank_implicit_noopener.html?area2" id="area2" rel="opener" target="_blank"> + <area shape="rect" coords="0,0,99,50" href="support/target_blank_implicit_noopener.html?area3" id="area3" target="_blank"> + <area shape="rect" coords="0,0,99,50" href="support/target_blank_implicit_noopener.html?area4" id="area4" rel="opener noopener" target="_blank"> + <area shape="rect" coords="0,0,99,50" href="support/target_blank_implicit_noopener.html?area5" id="area5" rel="noopener opener" target="_blank"> <script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener_base.html b/third_party/blink/web_tests/external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener_base.html index 8d1b54b..3da6a49e 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener_base.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener_base.html
@@ -18,21 +18,12 @@ <a href="support/target_blank_implicit_noopener.html?a7" id="a7" rel="opener noreferrer">Click me</a> <a href="support/target_blank_implicit_noopener.html?a8" id="a8" rel="noopener opener noreferrer">Click me</a> - <img src="/images/threecolors.png" /> - <area shape="rect" coords="0,0,99,50" href="support/target_blank_implicit_noopener.html?area1" id="area1" rel="noopener"> - </img> - <img src="/images/threecolors.png" /> - <area shape="rect" coords="0,0,99,50" href="support/target_blank_implicit_noopener.html?area2" id="area2" rel="opener"> - </img> - <img src="/images/threecolors.png" /> - <area shape="rect" coords="0,0,99,50" href="support/target_blank_implicit_noopener.html?area3" id="area3"> - </img> - <img src="/images/threecolors.png" /> - <area shape="rect" coords="0,0,99,50" href="support/target_blank_implicit_noopener.html?area4" id="area4" rel="opener noopener"> - </img> - <img src="/images/threecolors.png" /> - <area shape="rect" coords="0,0,99,50" href="support/target_blank_implicit_noopener.html?area5" id="area5" rel="noopener opener"> - </img> + <!-- Although this is not valid, per the processing model of area it ought to work --> + <area shape="rect" coords="0,0,99,50" href="support/target_blank_implicit_noopener.html?area1" id="area1" rel="noopener"> + <area shape="rect" coords="0,0,99,50" href="support/target_blank_implicit_noopener.html?area2" id="area2" rel="opener"> + <area shape="rect" coords="0,0,99,50" href="support/target_blank_implicit_noopener.html?area3" id="area3"> + <area shape="rect" coords="0,0,99,50" href="support/target_blank_implicit_noopener.html?area4" id="area4" rel="opener noopener"> + <area shape="rect" coords="0,0,99,50" href="support/target_blank_implicit_noopener.html?area5" id="area5" rel="noopener opener"> <script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/rellist-feature-detection-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/rellist-feature-detection-expected.txt index a00858d5f..8e4fd083 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/rellist-feature-detection-expected.txt +++ b/third_party/blink/web_tests/external/wpt/html/semantics/rellist-feature-detection-expected.txt
@@ -1,4 +1,7 @@ This is a testharness.js-based test. -FAIL Make sure that relList based feature detection is working assert_true: tag = A, link type = opener must be supported expected true got false +PASS Make sure that relList based feature detection is working for <link> +FAIL Make sure that relList based feature detection is working for <a> assert_true: tag = A, link type = opener must be supported expected true got false +FAIL Make sure that relList based feature detection is working for <area> assert_true: tag = AREA, link type = opener must be supported expected true got false +FAIL Make sure that relList based feature detection is working for <form> Cannot read property 'contains' of undefined Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/rellist-feature-detection.html b/third_party/blink/web_tests/external/wpt/html/semantics/rellist-feature-detection.html index d290439..45debcc 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/rellist-feature-detection.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/rellist-feature-detection.html
@@ -24,10 +24,11 @@ 'apple-touch-icon-precomposed', 'canonical'] }; link_support_table['area'] = link_support_table['a']; -link_support_table['form'] = link_support_table['form']; +link_support_table['form'] = link_support_table['a']; -function test_rellist(tag_name, rel_table) { - let element = document.createElement(tag_name); +function test_rellist(tag_name) { + const rel_table = link_support_table[tag_name]; + const element = document.createElement(tag_name); let tag = element.tagName; // Test that setting rel is also setting relList, for both // valid and invalid values. @@ -74,10 +75,10 @@ } } -test(function() { - test_rellist('LINK', link_support_table['link']); - test_rellist('A', link_support_table['a']); - test_rellist('AREA', link_support_table['area']); - test_rellist('FORM', link_support_table['form']); -}, 'Make sure that relList based feature detection is working'); +['link', 'a', 'area', 'form'].forEach(tag_name => { + test( + () => test_rellist(tag_name), + `Make sure that relList based feature detection is working for <${tag_name}>` + ); +}); </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/text-level-semantics/the-ruby-element/rt-without-ruby-crash.html b/third_party/blink/web_tests/external/wpt/html/semantics/text-level-semantics/the-ruby-element/rt-without-ruby-crash.html new file mode 100644 index 0000000..3caed3a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/text-level-semantics/the-ruby-element/rt-without-ruby-crash.html
@@ -0,0 +1,11 @@ +<!DOCTYPE html> +<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> +<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=967255"> +<rt style="display:block;"> + <div></div> +</rt> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + test(()=> { }, "No crash"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/infrastructure/metadata/infrastructure/testdriver/actions/actionsWithKeyPressed.html.ini b/third_party/blink/web_tests/external/wpt/infrastructure/metadata/infrastructure/testdriver/actions/actionsWithKeyPressed.html.ini deleted file mode 100644 index f62bf62a..0000000 --- a/third_party/blink/web_tests/external/wpt/infrastructure/metadata/infrastructure/testdriver/actions/actionsWithKeyPressed.html.ini +++ /dev/null
@@ -1,9 +0,0 @@ -[actionsWithKeyPressed.html] - expected: - if product == "safari" or product == "firefox": ERROR - - - [TestDriver actions: actions with key pressed] - expected: - if product == "chrome": FAIL -
diff --git a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/actions/actionsWithKeyPressed.html b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/actions/actionsWithKeyPressed.html deleted file mode 100644 index 74e939f5..0000000 --- a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/actions/actionsWithKeyPressed.html +++ /dev/null
@@ -1,67 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>TestDriver actions: actions with key pressed</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/resources/testdriver.js"></script> -<script src="/resources/testdriver-actions.js"></script> -<script src="/resources/testdriver-vendor.js"></script> - -<style> -div#test1, div#test2 { - position: fixed; - top: 0; - left: 0; - width: 100px; - height: 100px; - background-color: blue; -} - -div#test2 { - position: fixed; - top: 100px; - left: 0; - width: 100px; - height: 100px; - background-color: green; -} -</style> - -<div id="test1"> -</div> - -<div id="test2"> -</div> - -<script> -let keys = []; - -async_test(t => { - let test1 = document.getElementById("test1"); - let test2 = document.getElementById("test2"); - document.getElementById("test1").addEventListener("click", - e => {keys.push(e.getModifierState("Control"))}); - document.getElementById("test2").addEventListener("click", - e => {keys.push(e.getModifierState("Control"))}); - - let actions = new test_driver.Actions() - .keyDown("\uE009") - .addTick() - .pointerMove(0, 0, {origin: test1}) - .pointerDown() - .pointerUp() - .pointerMove(0, 0, {origin: test2}) - .pointerDown() - .pointerUp() - .addTick() - .keyUp("\uE009") - .addTick() - .pointerMove(0, 0, {origin: test1}) - .pointerDown() - .pointerUp(); - - actions.send() - .then(t.step_func_done(() => assert_array_equals(keys, [true, true, false]))) - .catch(e => t.step_func(() => assert_unreached("Actions sequence failed " + e))); -}); -</script>
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/html.idl b/third_party/blink/web_tests/external/wpt/interfaces/html.idl index f44f5da..5ae46f74 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/html.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/html.idl
@@ -116,6 +116,8 @@ [CEReactions] attribute DOMString autocapitalize; [CEReactions] attribute [TreatNullAs=EmptyString] DOMString innerText; + + ElementInternals attachInternals(); }; HTMLElement includes GlobalEventHandlers; @@ -795,6 +797,7 @@ getter (RadioNodeList or Element) (DOMString name); void submit(); + void requestSubmit(optional HTMLElement submitter); [CEReactions] void reset(); boolean checkValidity(); boolean reportValidity(); @@ -1412,9 +1415,9 @@ }; Path2D includes CanvasPath; -[Exposed=Window] +[Exposed=(Window,Worker)] interface ImageBitmapRenderingContext { - readonly attribute HTMLCanvasElement canvas; + readonly attribute (HTMLCanvasElement or OffscreenCanvas) canvas; void transferFromImageBitmap(ImageBitmap? bitmap); }; @@ -1422,14 +1425,14 @@ boolean alpha = true; }; -typedef (OffscreenCanvasRenderingContext2D or WebGLRenderingContext or WebGL2RenderingContext) OffscreenRenderingContext; +typedef (OffscreenCanvasRenderingContext2D or ImageBitmapRenderingContext or WebGLRenderingContext or WebGL2RenderingContext) OffscreenRenderingContext; dictionary ImageEncodeOptions { DOMString type = "image/png"; unrestricted double quality; }; -enum OffscreenRenderingContextId { "2d", "webgl", "webgl2" }; +enum OffscreenRenderingContextId { "2d", "bitmaprenderer", "webgl", "webgl2" }; [Constructor([EnforceRange] unsigned long long width, [EnforceRange] unsigned long long height), Exposed=(Window,Worker), Transferable] interface OffscreenCanvas : EventTarget { @@ -1477,6 +1480,40 @@ DOMString extends; }; +[Exposed=Window] +interface ElementInternals { + // Form-associated custom elements + + void setFormValue((File or USVString or FormData)? value, + optional (File or USVString or FormData)? state); + + readonly attribute HTMLFormElement? form; + + void setValidity(ValidityStateFlags flags, + optional DOMString message, + optional HTMLElement anchor); + readonly attribute boolean willValidate; + readonly attribute ValidityState validity; + readonly attribute DOMString validationMessage; + boolean checkValidity(); + boolean reportValidity(); + + readonly attribute NodeList labels; +}; + +dictionary ValidityStateFlags { + boolean valueMissing = false; + boolean typeMismatch = false; + boolean patternMismatch = false; + boolean tooLong = false; + boolean tooShort = false; + boolean rangeUnderflow = false; + boolean rangeOverflow = false; + boolean stepMismatch = false; + boolean badInput = false; + boolean customError = false; +}; + dictionary FocusOptions { boolean preventScroll = false; };
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/mediacapture-streams.idl b/third_party/blink/web_tests/external/wpt/interfaces/mediacapture-streams.idl index 427aa92..c07b7e3 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/mediacapture-streams.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/mediacapture-streams.idl
@@ -52,7 +52,6 @@ boolean frameRate = true; boolean facingMode = true; boolean resizeMode = true; - boolean volume = true; boolean sampleRate = true; boolean sampleSize = true; boolean echoCancellation = true; @@ -71,7 +70,6 @@ DoubleRange frameRate; sequence<DOMString> facingMode; sequence<DOMString> resizeMode; - DoubleRange volume; ULongRange sampleRate; ULongRange sampleSize; sequence<boolean> echoCancellation; @@ -94,7 +92,6 @@ ConstrainDouble frameRate; ConstrainDOMString facingMode; ConstrainDOMString resizeMode; - ConstrainDouble volume; ConstrainULong sampleRate; ConstrainULong sampleSize; ConstrainBoolean echoCancellation; @@ -113,7 +110,6 @@ double frameRate; DOMString facingMode; DOMString resizeMode; - double volume; long sampleRate; long sampleSize; boolean echoCancellation;
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/wake-lock.idl b/third_party/blink/web_tests/external/wpt/interfaces/wake-lock.idl index 863cef1..21a3406 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/wake-lock.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/wake-lock.idl
@@ -16,5 +16,5 @@ }; dictionary WakeLockRequestOptions { - AbortSignal? signal = null; + AbortSignal signal; };
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/webaudio.idl b/third_party/blink/web_tests/external/wpt/interfaces/webaudio.idl index 4679558..aa137c1 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/webaudio.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/webaudio.idl
@@ -568,7 +568,8 @@ [Exposed=Window, SecureContext, - Constructor (BaseAudioContext context, DOMString name, optional AudioWorkletNodeOptions options)] + Constructor (BaseAudioContext context, DOMString name, + optional AudioWorkletNodeOptions options)] interface AudioWorkletNode : AudioNode { readonly attribute AudioParamMap parameters; readonly attribute MessagePort port;
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/webrtc.idl b/third_party/blink/web_tests/external/wpt/interfaces/webrtc.idl index 6ae3416..4b5d1c1c 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/webrtc.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/webrtc.idl
@@ -382,7 +382,7 @@ required DOMHighResTimeStamp timestamp; required unsigned long source; double audioLevel; - unsigned long rtpTimestamp; + required unsigned long rtpTimestamp; }; dictionary RTCRtpSynchronizationSource : RTCRtpContributingSource {
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/webxr.idl b/third_party/blink/web_tests/external/wpt/interfaces/webxr.idl index 2d1bd9fe5..63327a3 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/webxr.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/webxr.idl
@@ -32,7 +32,7 @@ // Attributes readonly attribute XREnvironmentBlendMode environmentBlendMode; [SameObject] readonly attribute XRRenderState renderState; - readonly attribute XRInputSourceArray inputSources; + [SameObject] readonly attribute XRInputSourceArray inputSources; // Methods void updateRenderState(optional XRRenderStateInit state);
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_suppress_compat_events_on_drag_mouse.html b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_suppress_compat_events_on_drag_mouse.html index 5bab6e66..6ed75ab 100644 --- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_suppress_compat_events_on_drag_mouse.html +++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_suppress_compat_events_on_drag_mouse.html
@@ -46,7 +46,6 @@ var target_list = ["target0", "target1"]; var pointer_event_list = ["pointerdown" , "pointermove", "pointerup"]; var mouse_event_list = ["mousedown", "mouseup", "mousemove"]; - var last_pointer_event = null; target_list.forEach(function(targetId) { var target = document.getElementById(targetId); @@ -64,8 +63,6 @@ if (label === "pointerdown@target0") event.preventDefault(); - - last_pointer_event = event; }); }); @@ -77,11 +74,6 @@ event_log.push(event.type + "@" + targetId); include_next_mousemove = (event.type == "mousedown"); - test(function() { - test(function () { - assert_equals(event.timeStamp, last_pointer_event.timeStamp, "The time stamp of the compat mouse event should be the same as its pointerevent"); - }); - }, event.type + "'s time stamp should be the same as " + last_pointer_event.type + "'s time stamp."); }); }); });
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch.html b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch.html index bdd2809..f05aadf 100644 --- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch.html +++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch.html
@@ -92,7 +92,7 @@ function run() { var target0 = document.getElementById("target0"); var btnComplete = document.getElementById("btnComplete"); - var actions_promise; + var clickIsReceived = false; // Check if touch-action attribute works properly for embedded divs // Scrollable-Parent, Child: `auto`, Grand-Child: `none` @@ -103,11 +103,7 @@ assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test"); assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test"); }); - - // Make sure the test finishes after all the input actions are completed. - actions_promise.then( () => { - test_touchaction.done(); - }); + clickIsReceived = true; updateDescriptionComplete(); }); @@ -116,11 +112,15 @@ }); // Inject touch inputs. - actions_promise = touchScrollInTarget(scrollTarget, 'down'); - actions_promise.then(function() { - touchScrollInTarget(scrollTarget, 'right'); + touchScrollInTarget(scrollTarget, 'down').then(function() { + return touchScrollInTarget(scrollTarget, 'right'); }).then(function() { - clickInTarget("touch", btnComplete); + return clickInTarget("touch", btnComplete); + }).then(function() { + test_touchaction.step(function () { + assert_true(clickIsReceived, "click should be received before the test finishes"); + }, "click should be received before the test finishes"); + test_touchaction.done(); }); } </script>
diff --git a/third_party/blink/web_tests/external/wpt/preload/download-resources.html b/third_party/blink/web_tests/external/wpt/preload/download-resources.html index 510ebb4..557c965 100644 --- a/third_party/blink/web_tests/external/wpt/preload/download-resources.html +++ b/third_party/blink/web_tests/external/wpt/preload/download-resources.html
@@ -1,10 +1,8 @@ <!DOCTYPE html> +<title>Makes sure that preloaded resources are downloaded</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/preload/resources/preload_helper.js"></script> -<script> - var t = async_test('Makes sure that preloaded resources are downloaded'); -</script> <link rel=preload href="resources/dummy.js" as=script> <link rel=preload href="resources/dummy.css" as=style> <link rel=preload href="resources/square.png" as=image> @@ -17,9 +15,25 @@ <link rel=preload href="resources/dummy.xml" as="fetch"> <body> <script> - window.addEventListener("load", t.step_func(function() { - t.step_timeout(function() { - verifyPreloadAndRTSupport() + setup({explicit_done: true}); + + var iterations = 0; + + function check_finished() { + if (numberOfResourceTimingEntries("resources/dummy.js") == 1 && + numberOfResourceTimingEntries("resources/dummy.css") == 1 && + numberOfResourceTimingEntries("/fonts/CanvasTest.ttf") == 1 && + numberOfResourceTimingEntries("resources/white.mp4") == 1 && + numberOfResourceTimingEntries("resources/sound_5.oga") == 1 && + numberOfResourceTimingEntries("resources/foo.vtt") == 1 && + numberOfResourceTimingEntries("resources/dummy.xml?foo=bar") == 0 && + numberOfResourceTimingEntries("resources/dummy.xml?novalue") == 0 && + numberOfResourceTimingEntries("resources/dummy.xml") == 1) { + done(); + } + iterations++; + if (iterations == 10) { + // At least one is expected to fail, but this should give details to the exact failure(s). verifyNumberOfResourceTimingEntries("resources/dummy.js", 1); verifyNumberOfResourceTimingEntries("resources/dummy.css", 1); verifyNumberOfResourceTimingEntries("/fonts/CanvasTest.ttf", 1); @@ -29,8 +43,15 @@ verifyNumberOfResourceTimingEntries("resources/dummy.xml?foo=bar", 0); verifyNumberOfResourceTimingEntries("resources/dummy.xml?novalue", 0); verifyNumberOfResourceTimingEntries("resources/dummy.xml", 1); - t.done(); - }, 5000); - })); + done(); + } else { + step_timeout(check_finished, 500); + } + } + + window.addEventListener("load", function() { + verifyPreloadAndRTSupport(); + step_timeout(check_finished, 500); + }); </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/preload/link-header-on-subresource.html b/third_party/blink/web_tests/external/wpt/preload/link-header-on-subresource.html index 087a342..7047115 100644 --- a/third_party/blink/web_tests/external/wpt/preload/link-header-on-subresource.html +++ b/third_party/blink/web_tests/external/wpt/preload/link-header-on-subresource.html
@@ -1,18 +1,31 @@ <!DOCTYPE html> +<title>Makes sure that Link headers on subresources preload resources</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/preload/resources/preload_helper.js"></script> -<script> - var t = async_test('Makes sure that Link headers on subresources preload resources'); -</script> <link rel=stylesheet href="resources/dummy-preloads-subresource.css?link-header-on-subresource"> <script> - window.addEventListener("load", t.step_func(function() { - t.step_timeout(function() { - verifyPreloadAndRTSupport(); + setup({explicit_done: true}); + + var iterations = 0; + + function check_finished() { + if (numberOfResourceTimingEntries("/fonts/CanvasTest.ttf?link-header-on-subresource") == 1) { + done(); + } + iterations++; + if (iterations == 10) { + // This is expected to fail, but this should give details to the exact failure. verifyNumberOfResourceTimingEntries("/fonts/CanvasTest.ttf?link-header-on-subresource", 1); - t.done(); - }, 5000); - })); + done(); + } else { + step_timeout(check_finished, 500); + } + } + + window.addEventListener("load", function() { + verifyPreloadAndRTSupport(); + step_timeout(check_finished, 500); + }); </script>
diff --git a/third_party/blink/web_tests/external/wpt/preload/onerror-event.html b/third_party/blink/web_tests/external/wpt/preload/onerror-event.html index 8190be87..2038e06 100644 --- a/third_party/blink/web_tests/external/wpt/preload/onerror-event.html +++ b/third_party/blink/web_tests/external/wpt/preload/onerror-event.html
@@ -1,12 +1,10 @@ <!DOCTYPE html> <html> -<head></head> -<body> +<title>Makes sure that preloaded resources trigger the onerror event</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/preload/resources/preload_helper.js"></script> <script> - var t = async_test('Makes sure that preloaded resources trigger the onerror event'); var scriptFailed = false; var styleFailed = false; var imageFailed = false; @@ -28,10 +26,20 @@ <link rel=preload href="non-existent/dummy.xml?foo" as=foobarxmlthing onerror="gibberishFailed = true;"> <link rel=preload href="non-existent/dummy.xml?fetch" as=fetch onerror="fetchFailed = true;"> <link rel=preload href="non-existent/dummy.xml?empty" onerror="emptyFailed = true;"> +<body> <script> - window.onload = t.step_func(function() { - t.step_timeout(function() { - verifyPreloadAndRTSupport(); + setup({explicit_done: true}); + + var iterations = 0; + + function check_finished() { + if (styleFailed && scriptFailed && imageFailed && fontFailed && videoFailed && audioFailed && + trackFailed && !gibberishFailed && fetchFailed && !emptyFailed) { + done(); + } + iterations++; + if (iterations == 10) { + // At least one is expected to fail, but this should give details to the exact failure(s). assert_true(styleFailed, "style triggered error event"); assert_true(scriptFailed, "script triggered error event"); assert_true(imageFailed, "image triggered error event"); @@ -42,8 +50,15 @@ assert_false(gibberishFailed, "gibberish as value did not trigger error event"); assert_true(fetchFailed, "fetch as triggered error event"); assert_false(emptyFailed, "empty as triggered error event"); - t.done(); - }, 5000); + done(); + } else { + step_timeout(check_finished, 500); + } + } + + window.addEventListener("load", function() { + verifyPreloadAndRTSupport(); + step_timeout(check_finished, 500); }); </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/preload/preload-csp.sub.html b/third_party/blink/web_tests/external/wpt/preload/preload-csp.sub.html index 65e9b3a..62d0c710 100644 --- a/third_party/blink/web_tests/external/wpt/preload/preload-csp.sub.html +++ b/third_party/blink/web_tests/external/wpt/preload/preload-csp.sub.html
@@ -15,41 +15,41 @@ <link rel=preload href="resources/dummy.xml"> <body> <script> -setup({explicit_done: true}); + setup({explicit_done: true}); -var iterations = 0; + var iterations = 0; -function check_finished() { - if (numberOfResourceTimingEntries("{{host}}:{{ports[http][1]}}/preload/resources/dummy.js") == 0 && - numberOfResourceTimingEntries("resources/dummy.css") == 0 && - numberOfResourceTimingEntries("resources/square.png") == 0 && - numberOfResourceTimingEntries("/fonts/CanvasTest.ttf") == 0 && - numberOfResourceTimingEntries("resources/white.mp4") == 0 && - numberOfResourceTimingEntries("resources/sound_5.oga") == 0 && - numberOfResourceTimingEntries("resources/foo.vtt") == 0 && - numberOfResourceTimingEntries("resources/dummy.xml") == 0) { - done(); + function check_finished() { + if (numberOfResourceTimingEntries("{{host}}:{{ports[http][1]}}/preload/resources/dummy.js") == 0 && + numberOfResourceTimingEntries("resources/dummy.css") == 0 && + numberOfResourceTimingEntries("resources/square.png") == 0 && + numberOfResourceTimingEntries("/fonts/CanvasTest.ttf") == 0 && + numberOfResourceTimingEntries("resources/white.mp4") == 0 && + numberOfResourceTimingEntries("resources/sound_5.oga") == 0 && + numberOfResourceTimingEntries("resources/foo.vtt") == 0 && + numberOfResourceTimingEntries("resources/dummy.xml") == 0) { + done(); + } + iterations++; + if (iterations == 10) { + // At least one is expected to fail, but this should give details to the exact failure(s). + verifyNumberOfResourceTimingEntries("{{host}}:{{ports[http][1]}}/preload/resources/dummy.js", 0); + verifyNumberOfResourceTimingEntries("resources/dummy.css", 0); + verifyNumberOfResourceTimingEntries("resources/square.png", 0); + verifyNumberOfResourceTimingEntries("/fonts/CanvasTest.ttf", 0); + verifyNumberOfResourceTimingEntries("resources/white.mp4", 0); + verifyNumberOfResourceTimingEntries("resources/sound_5.oga", 0); + verifyNumberOfResourceTimingEntries("resources/foo.vtt", 0); + verifyNumberOfResourceTimingEntries("resources/dummy.xml", 0); + done(); + } else { + step_timeout(check_finished, 500); + } } - iterations++; - if (iterations == 10) { - // At least one is expected to fail, but this should give details to the exact failure(s). - verifyNumberOfResourceTimingEntries("{{host}}:{{ports[http][1]}}/preload/resources/dummy.js", 0); - verifyNumberOfResourceTimingEntries("resources/dummy.css", 0); - verifyNumberOfResourceTimingEntries("resources/square.png", 0); - verifyNumberOfResourceTimingEntries("/fonts/CanvasTest.ttf", 0); - verifyNumberOfResourceTimingEntries("resources/white.mp4", 0); - verifyNumberOfResourceTimingEntries("resources/sound_5.oga", 0); - verifyNumberOfResourceTimingEntries("resources/foo.vtt", 0); - verifyNumberOfResourceTimingEntries("resources/dummy.xml", 0); - done(); - } else { + + window.addEventListener("load", function() { + verifyPreloadAndRTSupport(); step_timeout(check_finished, 500); - } -} - -window.addEventListener("load", function() { - verifyPreloadAndRTSupport(); - step_timeout(check_finished, 500); -}); + }); </script>
diff --git a/third_party/blink/web_tests/external/wpt/preload/preload-default-csp.sub.html b/third_party/blink/web_tests/external/wpt/preload/preload-default-csp.sub.html index 92343145..9fc1194 100644 --- a/third_party/blink/web_tests/external/wpt/preload/preload-default-csp.sub.html +++ b/third_party/blink/web_tests/external/wpt/preload/preload-default-csp.sub.html
@@ -15,41 +15,41 @@ <link rel=preload href="resources/dummy.xml"> <body> <script> -setup({explicit_done: true}); + setup({explicit_done: true}); -var iterations = 0; + var iterations = 0; -function check_finished() { - if (numberOfResourceTimingEntries("{{host}}:{{ports[http][1]}}/preload/resources/dummy.js") == 0 && - numberOfResourceTimingEntries("resources/dummy.css") == 0 && - numberOfResourceTimingEntries("resources/square.png") == 0 && - numberOfResourceTimingEntries("/fonts/CanvasTest.ttf") == 0 && - numberOfResourceTimingEntries("resources/white.mp4") == 0 && - numberOfResourceTimingEntries("resources/sound_5.oga") == 0 && - numberOfResourceTimingEntries("resources/foo.vtt") == 0 && - numberOfResourceTimingEntries("resources/dummy.xml") == 0) { - done(); + function check_finished() { + if (numberOfResourceTimingEntries("{{host}}:{{ports[http][1]}}/preload/resources/dummy.js") == 0 && + numberOfResourceTimingEntries("resources/dummy.css") == 0 && + numberOfResourceTimingEntries("resources/square.png") == 0 && + numberOfResourceTimingEntries("/fonts/CanvasTest.ttf") == 0 && + numberOfResourceTimingEntries("resources/white.mp4") == 0 && + numberOfResourceTimingEntries("resources/sound_5.oga") == 0 && + numberOfResourceTimingEntries("resources/foo.vtt") == 0 && + numberOfResourceTimingEntries("resources/dummy.xml") == 0) { + done(); + } + iterations++; + if (iterations == 10) { + // At least one is expected to fail, but this should give details to the exact failure(s). + verifyNumberOfResourceTimingEntries("{{host}}:{{ports[http][1]}}/preload/resources/dummy.js", 0); + verifyNumberOfResourceTimingEntries("resources/dummy.css", 0); + verifyNumberOfResourceTimingEntries("resources/square.png", 0); + verifyNumberOfResourceTimingEntries("/fonts/CanvasTest.ttf", 0); + verifyNumberOfResourceTimingEntries("resources/white.mp4", 0); + verifyNumberOfResourceTimingEntries("resources/sound_5.oga", 0); + verifyNumberOfResourceTimingEntries("resources/foo.vtt", 0); + verifyNumberOfResourceTimingEntries("resources/dummy.xml", 0); + done(); + } else { + step_timeout(check_finished, 500); + } } - iterations++; - if (iterations == 10) { - // At least one is expected to fail, but this should give details to the exact failure(s). - verifyNumberOfResourceTimingEntries("{{host}}:{{ports[http][1]}}/preload/resources/dummy.js", 0); - verifyNumberOfResourceTimingEntries("resources/dummy.css", 0); - verifyNumberOfResourceTimingEntries("resources/square.png", 0); - verifyNumberOfResourceTimingEntries("/fonts/CanvasTest.ttf", 0); - verifyNumberOfResourceTimingEntries("resources/white.mp4", 0); - verifyNumberOfResourceTimingEntries("resources/sound_5.oga", 0); - verifyNumberOfResourceTimingEntries("resources/foo.vtt", 0); - verifyNumberOfResourceTimingEntries("resources/dummy.xml", 0); - done(); - } else { + + window.addEventListener("load", function() { + verifyPreloadAndRTSupport(); step_timeout(check_finished, 500); - } -} - -window.addEventListener("load", function() { - verifyPreloadAndRTSupport(); - step_timeout(check_finished, 500); -}); + }); </script>
diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/generic/iframe-src-change.html b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/iframe-src-change.html new file mode 100644 index 0000000..15202a7 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/referrer-policy/generic/iframe-src-change.html
@@ -0,0 +1,37 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> +<script> +function nextMessage() { + return new Promise((resolve, reject) => { + window.addEventListener('message', e => resolve(e.data), {once: true}); + }); +} + +promise_test(async () => { + let iframe = document.createElement('iframe'); + iframe.setAttribute('src', '/common/security-features/subresource/document.py?first') + iframe.setAttribute('referrerpolicy', 'no-referrer'); + document.body.appendChild(iframe); + + try { + { + let {referrer: documentReferrer, headers: {referer: httpReferrer}} = await nextMessage(); + assert_equals(httpReferrer, undefined, 'expected no HTTP Referer header on initial load'); + assert_equals(documentReferrer, undefined, 'expected no document.referrer on initial load'); + } + + iframe.setAttribute('src', '/common/security-features/subresource/document.py?second'); + + { + let {referrer: documentReferrer, headers: {referer: httpReferrer}} = await nextMessage(); + assert_equals(httpReferrer, undefined, 'expected no HTTP Referer header on src change'); + assert_equals(documentReferrer, undefined, 'expected no document.referrer on src change'); + } + } finally { + iframe.remove(); + } +}, "Checks that referrerpolicy is respected when an iframe's src changes."); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/firefox.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/firefox.py index 454b086..3b6949a 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/firefox.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/firefox.py
@@ -161,6 +161,7 @@ "wasm": kwargs.get("wasm", True), "verify": kwargs["verify"], "headless": "MOZ_HEADLESS" in os.environ, + "fission": get_bool_pref("fission.autostart"), "sw-e10s": get_bool_pref("dom.serviceWorkers.parent_intercept")} rv.update(run_info_browser_version(kwargs["binary"])) return rv
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-insecure-context.any.js b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-insecure-context.any.js new file mode 100644 index 0000000..f32cc3c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-insecure-context.any.js
@@ -0,0 +1,5 @@ +//META: title=Wake Lock API is not exposed in an insecure context + +test(() => { + assert_false("WakeLock" in self, "'WakeLock' must not be exposed"); +}, "Wake Lock API is not exposed in an insecure context");
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-insecure-context.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-insecure-context.html deleted file mode 100644 index 2c61f41..0000000 --- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-insecure-context.html +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>Wake Lock API is not exposed in an insecure context</title> -<link rel="help" href="https://w3c.github.io/wake-lock/#wake-locks"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script> - -test(t => { - assert_false("WakeLock" in self, "'WakeLock' must not be exposed"); -}, "Wake Lock API is not exposed in an insecure context"); - -</script>
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-screen-type-on-worker.https.worker-expected.txt b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-screen-type-on-worker.https.worker-expected.txt new file mode 100644 index 0000000..7019eb3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-screen-type-on-worker.https.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Screen wake lock should not be allowed in dedicated worker WakeLock is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-screen-type-on-worker.https.worker.js b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-screen-type-on-worker.https.worker.js new file mode 100644 index 0000000..28e3394 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-screen-type-on-worker.https.worker.js
@@ -0,0 +1,8 @@ +//META: title=Screen wake lock should not be allowed in dedicated worker +importScripts("/resources/testharness.js"); + +promise_test(t => { + return promise_rejects(t, "NotAllowedError", WakeLock.request('screen')); +}, "Screen wake lock should not be allowed in dedicated worker"); + +done();
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-state-is-global.https.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-state-is-global.https.html deleted file mode 100644 index 2eee319..0000000 --- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-state-is-global.https.html +++ /dev/null
@@ -1,75 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>wake lock state should be global</title> -<link rel="help" href="https://w3c.github.io/wake-lock/"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> - -<body> -<script id="iframe" type="text/plain"> -let iframeWakeLock; -const controller = new AbortController(); -const signal = controller.signal; -window.onmessage = async message => { - switch(message.data) { - case "ACQUIRED": - iframeWakeLock = new WakeLock("screen"); - await iframeWakeLock.request({ signal }); - parent.postMessage(iframeWakeLock.active, "*"); - break; - case "RELEASED": - controller.abort(); - parent.postMessage(iframeWakeLock.active, "*"); - break; - default: - parent.postMessage("unknown operation", "*"); - } -} -</script> - -<script> -function load_iframe() { - return new Promise(resolve => { - const iframe = document.createElement("iframe"); - iframe.onload = () => { resolve(iframe); }; - iframe.srcdoc = "<script>" + - document.getElementById('iframe').textContent + - "<\/script>"; - document.body.appendChild(iframe); - }); -} - -function wait_for_message(iframe) { - return new Promise(resolve => { - self.addEventListener("message", function listener(e) { - if (e.source === iframe.contentWindow) { - resolve(e.data); - self.removeEventListener("message", listener); - } - }); - }); -} - -promise_test(async t => { - const wakeLock = await new WakeLock("screen"); - const iframe = await load_iframe(); - const eventWatcher = new EventWatcher(t, wakeLock, "activechange"); - - assert_false(wakeLock.active, "wakeLock is initially false"); - - //when iframe wake lock is acquired, parent wake lock should be actived - iframe.contentWindow.postMessage("ACQUIRED", "*"); - const isActive1 = await wait_for_message(iframe); - await eventWatcher.wait_for("activechange"); - assert_true(isActive1, "the iframe wake lock state is actived when iframe wake lock is acquired"); - assert_true(wakeLock.active, "the wake lock state is actived when iframe wake lock is acquired"); - - //when iframe wake lock is released, parent wake lock should be inactived - iframe.contentWindow.postMessage("RELEASED", "*"); - const isActive2 = await wait_for_message(iframe); - eventWatcher.wait_for("activechange"); - assert_false(isActive2, "the iframe wake lock state is inactived when iframe wake lock is released"); - assert_false(wakeLock.active, "the wake lock state is inactived when iframe wake lock is released"); -}, "Test that wake lock state should be global"); -</script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-type.https.any.js b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-type.https.any.js new file mode 100644 index 0000000..cc37c76 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-type.https.any.js
@@ -0,0 +1,19 @@ +//META: title=WakeLock.request() with invalid type + +promise_test(async t => { + await promise_rejects(t, new TypeError(), WakeLock.request()); +}, "'TypeError' is thrown when set an empty wake lock type"); + +promise_test(t => { + const invalidTypes = [ + "invalid", + null, + 123, + {}, + "", + true + ]; + return Promise.all(invalidTypes.map(invalidType => { + return promise_rejects(t, new TypeError(), WakeLock.request(invalidType)); + })); +}, "'TypeError' is thrown when set an invalid wake lock type");
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-type.https.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-type.https.any.worker-expected.txt new file mode 100644 index 0000000..9d738db3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-type.https.any.worker-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +FAIL 'TypeError' is thrown when set an empty wake lock type promise_test: Unhandled rejection with value: object "ReferenceError: WakeLock is not defined" +FAIL 'TypeError' is thrown when set an invalid wake lock type WakeLock is not defined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-type.https.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-type.https.html deleted file mode 100644 index df7a68a0..0000000 --- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-type.https.html +++ /dev/null
@@ -1,38 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>WakeLockType Test</title> -<link rel="help" href="https://w3c.github.io/wake-lock/"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> - -<script> - -test(() => { - const wakeLock = new WakeLock("screen"); - assert_equals(wakeLock.type, "screen"); -}, "Test that wakeLock.type is 'screen' when screen wake lock is invoked"); - -test(() => { - const wakeLock = new WakeLock("system"); - assert_equals(wakeLock.type, "system"); -}, "Test that wakeLock.type is 'system' when system wake lock is invoked"); - -test(() => { - assert_throws(new TypeError(), () => new WakeLock()); -}, "'TypeError' is thrown when set an empty wake lock type"); - -test(() => { - const invalidTypes = [ - "invalid", - null, - 123, - {}, - "", - true - ]; - invalidTypes.map(invalidType => { - assert_throws(new TypeError(), () => new WakeLock(invalidType)); - }) -}, "'TypeError' is thrown when set an invalid wake lock type"); - -</script>
diff --git a/third_party/blink/web_tests/external/wpt/xhr/resources/access-control-basic-options-not-supported.py b/third_party/blink/web_tests/external/wpt/xhr/resources/access-control-basic-options-not-supported.py index 0c69c76..77b274e9 100644 --- a/third_party/blink/web_tests/external/wpt/xhr/resources/access-control-basic-options-not-supported.py +++ b/third_party/blink/web_tests/external/wpt/xhr/resources/access-control-basic-options-not-supported.py
@@ -3,7 +3,10 @@ # Allow simple requests, but deny preflight if request.method != "OPTIONS": - response.headers.set("Access-Control-Allow-Credentials", "true") - response.headers.set("Access-Control-Allow-Origin", request.headers.get("origin")) + if "origin" in request.headers: + response.headers.set("Access-Control-Allow-Credentials", "true") + response.headers.set("Access-Control-Allow-Origin", request.headers["origin"]) + else: + response.status = 500 else: response.status = 400
diff --git a/third_party/blink/web_tests/external/wpt/xhr/responsexml-document-properties-expected.txt b/third_party/blink/web_tests/external/wpt/xhr/responsexml-document-properties-expected.txt index a81e194..c7661c5 100644 --- a/third_party/blink/web_tests/external/wpt/xhr/responsexml-document-properties-expected.txt +++ b/third_party/blink/web_tests/external/wpt/xhr/responsexml-document-properties-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -FAIL domain assert_equals: expected (undefined) undefined but got (string) "web-platform.test" +PASS domain PASS URL PASS documentURI PASS baseURI
diff --git a/third_party/blink/web_tests/external/wpt/xhr/responsexml-document-properties.htm b/third_party/blink/web_tests/external/wpt/xhr/responsexml-document-properties.htm index b008348..9071fab 100644 --- a/third_party/blink/web_tests/external/wpt/xhr/responsexml-document-properties.htm +++ b/third_party/blink/web_tests/external/wpt/xhr/responsexml-document-properties.htm
@@ -12,9 +12,11 @@ var client = new XMLHttpRequest() client.open("GET", "resources/well-formed.xml", false) client.send(null) - var responseURL = new URL('resources/well-formed.xml', location.href).href + var responseURLObject = new URL('resources/well-formed.xml', location.href); + var responseURL = responseURLObject.href + var responseDomain = responseURLObject.hostname var expected = { - domain:undefined, + domain:responseDomain, URL:responseURL, documentURI:responseURL, baseURI:responseURL,
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/devtools/elements/highlight/highlight-node-vertical-rl-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/devtools/elements/highlight/highlight-node-vertical-rl-expected.txt deleted file mode 100644 index 0d88251..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/devtools/elements/highlight/highlight-node-vertical-rl-expected.txt +++ /dev/null
@@ -1,358 +0,0 @@ - - -container{ - "paths": [ - { - "path": [ - "M", - 80, - 50, - "L", - 380, - 50, - "L", - 380, - 350, - "L", - 80, - 350, - "Z" - ], - "fillColor": "rgba(255, 0, 0, 0)", - "outlineColor": "rgba(128, 0, 0, 0)", - "name": "content" - }, - { - "path": [ - "M", - 80, - 50, - "L", - 380, - 50, - "L", - 380, - 350, - "L", - 80, - 350, - "Z" - ], - "fillColor": "rgba(0, 255, 0, 0)", - "name": "padding" - }, - { - "path": [ - "M", - 80, - 50, - "L", - 380, - 50, - "L", - 380, - 350, - "L", - 80, - 350, - "Z" - ], - "fillColor": "rgba(0, 0, 255, 0)", - "name": "border" - }, - { - "path": [ - "M", - 0, - 0, - "L", - 800, - 0, - "L", - 800, - 420, - "L", - 0, - 420, - "Z" - ], - "fillColor": "rgba(255, 255, 255, 0)", - "name": "margin" - } - ], - "showRulers": true, - "showExtensionLines": true, - "elementInfo": { - "tagName": "div", - "idValue": "container", - "nodeWidth": "300", - "nodeHeight": "300" - } -} -child{ - "paths": [ - { - "path": [ - "M", - 220, - 100, - "L", - 320, - 100, - "L", - 320, - 200, - "L", - 220, - 200, - "Z" - ], - "fillColor": "rgba(255, 0, 0, 0)", - "outlineColor": "rgba(128, 0, 0, 0)", - "name": "content" - }, - { - "path": [ - "M", - 140, - 50, - "L", - 380, - 50, - "L", - 380, - 270, - "L", - 140, - 270, - "Z" - ], - "fillColor": "rgba(0, 255, 0, 0)", - "name": "padding" - }, - { - "path": [ - "M", - 140, - 50, - "L", - 380, - 50, - "L", - 380, - 270, - "L", - 140, - 270, - "Z" - ], - "fillColor": "rgba(0, 0, 255, 0)", - "name": "border" - }, - { - "path": [ - "M", - 140, - 50, - "L", - 380, - 50, - "L", - 380, - 350, - "L", - 140, - 350, - "Z" - ], - "fillColor": "rgba(255, 255, 255, 0)", - "name": "margin" - } - ], - "showRulers": true, - "showExtensionLines": true, - "elementInfo": { - "tagName": "div", - "idValue": "child", - "nodeWidth": "240", - "nodeHeight": "220" - } -} -span{ - "paths": [ - { - "path": [ - "M", - 310, - 100, - "L", - 320, - 100, - "L", - 320, - 170, - "L", - 310, - 170, - "Z" - ], - "fillColor": "rgba(255, 0, 0, 0)", - "outlineColor": "rgba(128, 0, 0, 0)", - "name": "content" - }, - { - "path": [ - "M", - 310, - 100, - "L", - 320, - 100, - "L", - 320, - 170, - "L", - 310, - 170, - "Z" - ], - "fillColor": "rgba(0, 255, 0, 0)", - "name": "padding" - }, - { - "path": [ - "M", - 310, - 100, - "L", - 320, - 100, - "L", - 320, - 170, - "L", - 310, - 170, - "Z" - ], - "fillColor": "rgba(0, 0, 255, 0)", - "name": "border" - }, - { - "path": [ - "M", - 310, - 100, - "L", - 320, - 100, - "L", - 320, - 170, - "L", - 310, - 170, - "Z" - ], - "fillColor": "rgba(255, 255, 255, 0)", - "name": "margin" - } - ], - "showRulers": true, - "showExtensionLines": true, - "elementInfo": { - "tagName": "span", - "idValue": "span", - "nodeWidth": "10", - "nodeHeight": "70" - } -} -TEXT{ - "paths": [ - { - "path": [ - "M", - 310, - 100, - "L", - 320, - 100, - "L", - 320, - 170, - "L", - 310, - 170, - "Z" - ], - "fillColor": "rgba(255, 0, 0, 0)", - "outlineColor": "rgba(128, 0, 0, 0)", - "name": "content" - }, - { - "path": [ - "M", - 310, - 100, - "L", - 320, - 100, - "L", - 320, - 170, - "L", - 310, - 170, - "Z" - ], - "fillColor": "rgba(0, 255, 0, 0)", - "name": "padding" - }, - { - "path": [ - "M", - 310, - 100, - "L", - 320, - 100, - "L", - 320, - 170, - "L", - 310, - 170, - "Z" - ], - "fillColor": "rgba(0, 0, 255, 0)", - "name": "border" - }, - { - "path": [ - "M", - 310, - 100, - "L", - 320, - 100, - "L", - 320, - 170, - "L", - 310, - 170, - "Z" - ], - "fillColor": "rgba(255, 255, 255, 0)", - "name": "margin" - } - ], - "showRulers": true, - "showExtensionLines": true, - "elementInfo": { - "nodeWidth": "10", - "nodeHeight": "70", - "tagName": "#text" - } -} -
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-node-vertical-rl-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-node-vertical-rl-expected.txt deleted file mode 100644 index 19c8be8..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-node-vertical-rl-expected.txt +++ /dev/null
@@ -1,358 +0,0 @@ - - -container{ - "paths": [ - { - "path": [ - "M", - 80, - 50, - "L", - 380, - 50, - "L", - 380, - 350, - "L", - 80, - 350, - "Z" - ], - "fillColor": "rgba(255, 0, 0, 0)", - "outlineColor": "rgba(128, 0, 0, 0)", - "name": "content" - }, - { - "path": [ - "M", - 80, - 50, - "L", - 380, - 50, - "L", - 380, - 350, - "L", - 80, - 350, - "Z" - ], - "fillColor": "rgba(0, 255, 0, 0)", - "name": "padding" - }, - { - "path": [ - "M", - 80, - 50, - "L", - 380, - 50, - "L", - 380, - 350, - "L", - 80, - 350, - "Z" - ], - "fillColor": "rgba(0, 0, 255, 0)", - "name": "border" - }, - { - "path": [ - "M", - 0, - 0, - "L", - 440, - 0, - "L", - 440, - 420, - "L", - 0, - 420, - "Z" - ], - "fillColor": "rgba(255, 255, 255, 0)", - "name": "margin" - } - ], - "showRulers": true, - "showExtensionLines": true, - "elementInfo": { - "tagName": "div", - "idValue": "container", - "nodeWidth": "300", - "nodeHeight": "300" - } -} -child{ - "paths": [ - { - "path": [ - "M", - 220, - 100, - "L", - 320, - 100, - "L", - 320, - 200, - "L", - 220, - 200, - "Z" - ], - "fillColor": "rgba(255, 0, 0, 0)", - "outlineColor": "rgba(128, 0, 0, 0)", - "name": "content" - }, - { - "path": [ - "M", - 140, - 50, - "L", - 380, - 50, - "L", - 380, - 270, - "L", - 140, - 270, - "Z" - ], - "fillColor": "rgba(0, 255, 0, 0)", - "name": "padding" - }, - { - "path": [ - "M", - 140, - 50, - "L", - 380, - 50, - "L", - 380, - 270, - "L", - 140, - 270, - "Z" - ], - "fillColor": "rgba(0, 0, 255, 0)", - "name": "border" - }, - { - "path": [ - "M", - 140, - 50, - "L", - 380, - 50, - "L", - 380, - 350, - "L", - 140, - 350, - "Z" - ], - "fillColor": "rgba(255, 255, 255, 0)", - "name": "margin" - } - ], - "showRulers": true, - "showExtensionLines": true, - "elementInfo": { - "tagName": "div", - "idValue": "child", - "nodeWidth": "240", - "nodeHeight": "220" - } -} -span{ - "paths": [ - { - "path": [ - "M", - 310, - 100, - "L", - 320, - 100, - "L", - 320, - 170, - "L", - 310, - 170, - "Z" - ], - "fillColor": "rgba(255, 0, 0, 0)", - "outlineColor": "rgba(128, 0, 0, 0)", - "name": "content" - }, - { - "path": [ - "M", - 310, - 100, - "L", - 320, - 100, - "L", - 320, - 170, - "L", - 310, - 170, - "Z" - ], - "fillColor": "rgba(0, 255, 0, 0)", - "name": "padding" - }, - { - "path": [ - "M", - 310, - 100, - "L", - 320, - 100, - "L", - 320, - 170, - "L", - 310, - 170, - "Z" - ], - "fillColor": "rgba(0, 0, 255, 0)", - "name": "border" - }, - { - "path": [ - "M", - 310, - 100, - "L", - 320, - 100, - "L", - 320, - 170, - "L", - 310, - 170, - "Z" - ], - "fillColor": "rgba(255, 255, 255, 0)", - "name": "margin" - } - ], - "showRulers": true, - "showExtensionLines": true, - "elementInfo": { - "tagName": "span", - "idValue": "span", - "nodeWidth": "10", - "nodeHeight": "70" - } -} -TEXT{ - "paths": [ - { - "path": [ - "M", - 310, - 100, - "L", - 320, - 100, - "L", - 320, - 170, - "L", - 310, - 170, - "Z" - ], - "fillColor": "rgba(255, 0, 0, 0)", - "outlineColor": "rgba(128, 0, 0, 0)", - "name": "content" - }, - { - "path": [ - "M", - 310, - 100, - "L", - 320, - 100, - "L", - 320, - 170, - "L", - 310, - 170, - "Z" - ], - "fillColor": "rgba(0, 255, 0, 0)", - "name": "padding" - }, - { - "path": [ - "M", - 310, - 100, - "L", - 320, - 100, - "L", - 320, - 170, - "L", - 310, - 170, - "Z" - ], - "fillColor": "rgba(0, 0, 255, 0)", - "name": "border" - }, - { - "path": [ - "M", - 310, - 100, - "L", - 320, - 100, - "L", - 320, - 170, - "L", - 310, - 170, - "Z" - ], - "fillColor": "rgba(255, 255, 255, 0)", - "name": "margin" - } - ], - "showRulers": true, - "showExtensionLines": true, - "elementInfo": { - "nodeWidth": "10", - "nodeHeight": "70", - "tagName": "#text" - } -} -
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-node-vertical-rl.js b/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-node-vertical-rl.js deleted file mode 100644 index 372151e8..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-node-vertical-rl.js +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -(async function() { - TestRunner.addResult(`\n`); - await TestRunner.loadModule('elements_test_runner'); - await TestRunner.loadModule('console_test_runner'); - await TestRunner.showPanel('elements'); - await TestRunner.loadHTML(` - <script src="/js-test-resources/ahem.js"></script> - <style> - body { - margin: 0; - font: 10px/10px Ahem; - } - #container { - margin: 50px 60px 70px 80px; - width: 300px; - height: 300px; - writing-mode: vertical-rl; - } - #child { - padding: 50px 60px 70px 80px; - width: 100px; - height: 100px; - } - </style> - <div id="container"> - <div id="child"> - <span id="span">ABCDEFG</span> - </div> - </div> - `); - - await TestRunner.evaluateInPagePromise(''); - function dumpHighlight(id) { - return new Promise(resolve => ElementsTestRunner.dumpInspectorHighlightJSON(id, resolve)); - } - await dumpHighlight('container'); - await dumpHighlight('child'); - await dumpHighlight('span'); - - let textNode = await ElementsTestRunner.findNodePromise(node => node.nodeValue() == 'ABCDEFG'); - let result = await TestRunner.OverlayAgent.getHighlightObjectForTest(textNode.id); - TestRunner.addResult('TEXT' + JSON.stringify(result, null, 2)); - TestRunner.completeTest(); -})();
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/preload/download-resources-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/preload/download-resources-expected.txt new file mode 100644 index 0000000..066ba1f --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/external/wpt/preload/download-resources-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Makes sure that preloaded resources are downloaded Uncaught Error: assert_equals: resources/white.mp4 expected 1 but got 0 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/preload/onerror-event-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/preload/onerror-event-expected.txt new file mode 100644 index 0000000..aa88efb --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/external/wpt/preload/onerror-event-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Makes sure that preloaded resources trigger the onerror event Uncaught Error: assert_true: video triggered error event expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/external/wpt/preload/onerror-event-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/external/wpt/preload/onerror-event-expected.txt new file mode 100644 index 0000000..aa88efb --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac10.10/external/wpt/preload/onerror-event-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Makes sure that preloaded resources trigger the onerror event Uncaught Error: assert_true: video triggered error event expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/external/wpt/preload/onerror-event-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.11/external/wpt/preload/onerror-event-expected.txt new file mode 100644 index 0000000..aa88efb --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac10.11/external/wpt/preload/onerror-event-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Makes sure that preloaded resources trigger the onerror event Uncaught Error: assert_true: video triggered error event expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/external/wpt/preload/onerror-event-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.12/external/wpt/preload/onerror-event-expected.txt new file mode 100644 index 0000000..aa88efb --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac10.12/external/wpt/preload/onerror-event-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Makes sure that preloaded resources trigger the onerror event Uncaught Error: assert_true: video triggered error event expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-retina/external/wpt/preload/onerror-event-expected.txt b/third_party/blink/web_tests/platform/mac-retina/external/wpt/preload/onerror-event-expected.txt new file mode 100644 index 0000000..0ef49ad --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-retina/external/wpt/preload/onerror-event-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Makes sure that preloaded resources trigger the onerror event assert_true: video triggered error event expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/preload/download-resources-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/preload/download-resources-expected.txt new file mode 100644 index 0000000..066ba1f --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/external/wpt/preload/download-resources-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Makes sure that preloaded resources are downloaded Uncaught Error: assert_equals: resources/white.mp4 expected 1 but got 0 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/preload/onerror-event-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/preload/onerror-event-expected.txt new file mode 100644 index 0000000..aa88efb --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/external/wpt/preload/onerror-event-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Makes sure that preloaded resources trigger the onerror event Uncaught Error: assert_true: video triggered error event expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/preload/onerror-event-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/preload/onerror-event-expected.txt new file mode 100644 index 0000000..aa88efb --- /dev/null +++ b/third_party/blink/web_tests/platform/win/external/wpt/preload/onerror-event-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Makes sure that preloaded resources trigger the onerror event Uncaught Error: assert_true: video triggered error event expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win7/external/wpt/preload/onerror-event-expected.txt b/third_party/blink/web_tests/platform/win7/external/wpt/preload/onerror-event-expected.txt new file mode 100644 index 0000000..aa88efb --- /dev/null +++ b/third_party/blink/web_tests/platform/win7/external/wpt/preload/onerror-event-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Makes sure that preloaded resources trigger the onerror event Uncaught Error: assert_true: video triggered error event expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/webxr_test_pages/webxr-samples/js/xrray-module.js b/third_party/webxr_test_pages/webxr-samples/js/xrray-module.js index ea5b134..218967e 100644 --- a/third_party/webxr_test_pages/webxr-samples/js/xrray-module.js +++ b/third_party/webxr_test_pages/webxr-samples/js/xrray-module.js
@@ -42,7 +42,7 @@ for(let col = 0; col < 4; ++col) { for(let row = 0; row < 4; ++row) { for(let k = 0; k < 4; ++k) { - result[col * 4 + row] += rhs[col][k] * lhs[k][row]; + result[col * 4 + row] += rhs[col * 4 + k] * lhs[k * 4 + row]; } } } @@ -89,7 +89,7 @@ // second column axis.x * axis.y * one_minus_cos_angle - axis.z * sin_angle, cos_angle + axis.y * axis.y * one_minus_cos_angle, - axis.z * axis.y * one_minus_cos_angle + x * sin_angle, + axis.z * axis.y * one_minus_cos_angle + axis.x * sin_angle, 0, // third column axis.x * axis.z * one_minus_cos_angle + axis.y * sin_angle, @@ -108,7 +108,6 @@ export class XRRay { constructor() { - if (arguments.length > 0 && arguments[0] instanceof XRRigidTransform) { if(arguments.length != 1) throw new Error("Invalid number of arguments!"); @@ -139,7 +138,7 @@ ]); const initial_ray_direction = [0, 0, -1]; - const desired_ray_direction = [direction.x, direction.y, direction.z]; + const desired_ray_direction = [this.direction_.x, this.direction_.y, this.direction_.z]; const cos_angle = dot(initial_ray_direction, desired_ray_direction); @@ -153,14 +152,14 @@ const axis = new DOMPointReadOnly(1, 0, 0, 0); cos_angle = -1; - this.matrix_ = rotate(this.matrix_, axis, Math.acos(angle)); + this.matrix_ = rotate(this.matrix_, axis, Math.acos(cos_angle)); } else { // Rotation needed - create it from axis-angle. - const cross_initial_desired = cross(initialRayDirection, desiredRayDirection); + const cross_initial_desired = cross(initial_ray_direction, desired_ray_direction); const axis = normalizeLength(new DOMPointReadOnly( cross_initial_desired[0], cross_initial_desired[1], cross_initial_desired[2], 0)); - this.matrix_ = rotate(this.matrix_, axis, Math.acos(angle)); + this.matrix_ = rotate(this.matrix_, axis, Math.acos(cos_angle)); } }
diff --git a/third_party/webxr_test_pages/webxr-samples/proposals/phone-ar-plane-detection.html b/third_party/webxr_test_pages/webxr-samples/proposals/phone-ar-plane-detection.html index d97424d2..59b0e43f 100644 --- a/third_party/webxr_test_pages/webxr-samples/proposals/phone-ar-plane-detection.html +++ b/third_party/webxr_test_pages/webxr-samples/proposals/phone-ar-plane-detection.html
@@ -294,7 +294,7 @@ } function DOMPointFromVec4(vector) { - return { x : vector[0], y : vector[1], z : vector[2], w : vector[3]} + return new DOMPointReadOnly(vector[0], vector[1], vector[2], vector[3]); } let rayOrigin = vec4.create();
diff --git a/tools/gritsettings/translation_expectations.pyl b/tools/gritsettings/translation_expectations.pyl index 83c03e53..dbe60d3 100644 --- a/tools/gritsettings/translation_expectations.pyl +++ b/tools/gritsettings/translation_expectations.pyl
@@ -83,6 +83,7 @@ "cloud_print/virtual_driver/win/install/virtual_driver_setup_resources.grd": "Separate release process", "components/components_locale_settings.grd": "Not UI strings; localized separately", "components/omnibox/resources/omnibox_resources.grd": "Not UI strings; localized separately", + "third_party/blink/renderer/devtools/front_end/langpacks/devtools_ui_strings.grd" : "Devtools UI strings that are optionally enabled by browser.", "tools/grit/grit/testdata/buildinfo.grd": "Test data", "tools/grit/grit/testdata/chrome/app/generated_resources.grd": "Test data", "tools/grit/grit/testdata/substitute.grd": "Test data",
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 5833ef05..c487a20 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -50749,6 +50749,9 @@ </enum> <enum name="SCTCanBeChecked"> + <obsolete> + Deprecated after 2019-04. + </obsolete> <int value="0" label="No valid STH"/> <int value="1" label="Requires newer STH"/> <int value="2" label="Can be checked for inclusion"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 154a5fa..f1a3731 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -5111,8 +5111,8 @@ </summary> </histogram> -<histogram name="Arc.CupsPrinting.PageCount" expires_after="2019-06-20"> - <owner>skau@google.com</owner> +<histogram name="Arc.CupsPrinting.PageCount" expires_after="2020-01-20"> + <owner>skau@chromium.org</owner> <owner>vkuzkokov@google.com</owner> <summary> The number of pages sent to a native printer by ARC. Reported for every @@ -22239,7 +22239,7 @@ </histogram> <histogram name="CrosUsb.NotificationClosed" enum="CrosUsbNotificationClosed" - expires_after="2019-07-01"> + expires_after="2021-07-01"> <owner>benwells@chromium.org</owner> <owner>nverne@chromium.org</owner> <owner>tbuckley@chromium.org</owner> @@ -51809,7 +51809,7 @@ </histogram> <histogram base="true" name="MachineLearningService.CpuTimeMicrosec" - units="microseconds"> + units="microseconds" expires_after="2020-02-01"> <!-- Name completed by histogram_suffixes name="MachineLearningServiceRequests" --> @@ -51821,7 +51821,8 @@ </histogram> <histogram name="MachineLearningService.CpuUsageMilliPercent" - units="1/1000ths of %" expires_after="2019-07-01"> + units="1/1000ths of %" expires_after="2020-02-01"> + <owner>alanlxl@chromium.org</owner> <owner>amoylan@chromium.org</owner> <summary> Fraction of total CPU resources used by Chrome OS ML Service, sampled every @@ -51830,7 +51831,8 @@ </histogram> <histogram name="MachineLearningService.CreateGraphExecutorResult.Event" - enum="MachineLearningServiceCreateGraphExecutorResultEvent"> + enum="MachineLearningServiceCreateGraphExecutorResultEvent" + expires_after="2020-02-01"> <owner>amoylan@chromium.org</owner> <owner>alanlxl@chromium.org</owner> <summary> @@ -51839,7 +51841,7 @@ </histogram> <histogram base="true" name="MachineLearningService.ElapsedTimeMicrosec" - units="microseconds"> + units="microseconds" expires_after="2020-02-01"> <!-- Name completed by histogram_suffixes name="MachineLearningServiceRequests" --> @@ -51849,7 +51851,7 @@ </histogram> <histogram name="MachineLearningService.ExecuteResult.Event" - enum="MachineLearningServiceExecuteResultEvent"> + enum="MachineLearningServiceExecuteResultEvent" expires_after="2020-02-01"> <owner>amoylan@chromium.org</owner> <owner>alanlxl@chromium.org</owner> <summary> @@ -51858,7 +51860,8 @@ </histogram> <histogram name="MachineLearningService.LoadModelResult.Event" - enum="MachineLearningServiceLoadModelResultEvent"> + enum="MachineLearningServiceLoadModelResultEvent" + expires_after="2020-02-01"> <owner>amoylan@chromium.org</owner> <owner>alanlxl@chromium.org</owner> <summary> @@ -51867,7 +51870,8 @@ </histogram> <histogram name="MachineLearningService.MojoConnectionEvent" - enum="MachineLearningServiceMojoConnectionEvent" expires_after="2019-07-01"> + enum="MachineLearningServiceMojoConnectionEvent" expires_after="2020-02-01"> + <owner>alanlxl@chromium.org</owner> <owner>amoylan@chromium.org</owner> <summary> Events related to the connection and disconnection of the Mojo IPC channel @@ -51876,7 +51880,8 @@ </histogram> <histogram name="MachineLearningService.PeakPrivateMemoryKb" units="KB" - expires_after="2019-07-01"> + expires_after="2020-02-01"> + <owner>alanlxl@chromium.org</owner> <owner>amoylan@chromium.org</owner> <summary> Peak private (non-shared) memory used by Chrome OS ML Service over the last @@ -51885,7 +51890,7 @@ </histogram> <histogram base="true" name="MachineLearningService.PrivateMemoryDeltaKb" - units="KB"> + units="KB" expires_after="2020-02-01"> <!-- Name completed by histogram_suffixes name="MachineLearningServiceRequests" --> @@ -51897,7 +51902,8 @@ </histogram> <histogram name="MachineLearningService.PrivateMemoryKb" units="KB" - expires_after="2019-07-01"> + expires_after="2020-02-01"> + <owner>alanlxl@chromium.org</owner> <owner>amoylan@chromium.org</owner> <summary> Private (non-shared) memory used by Chrome OS ML Service, sampled every 5 @@ -53202,10 +53208,10 @@ </histogram> <histogram name="Media.Audio.Render.StreamBrokerDisconnectReason2" - enum="AudioOutputStreamDisconnectReason2" expires_after="2019-06-01"> - <owner>jonasolsson@chromium.org</owner> - <owner>maxmorin@chromium.org</owner> + enum="AudioOutputStreamDisconnectReason2" expires_after="2019-09-01"> <owner>olka@chromium.org</owner> + <owner>grunell@chromium.org</owner> + <owner>maxmorin@chromium.org</owner> <summary> Describes why and in which state an audio output stream ended. </summary> @@ -65464,7 +65470,10 @@ </histogram> <histogram name="Net.CertificateTransparency.CanInclusionCheckSCT" - enum="SCTCanBeChecked" expires_after="M78"> + enum="SCTCanBeChecked" expires_after="M76"> + <obsolete> + Removed in Chrome 76. + </obsolete> <owner>estark@chromium.org</owner> <owner>rsleevi@chromium.org</owner> <summary> @@ -65599,7 +65608,10 @@ </histogram> <histogram name="Net.CertificateTransparency.DnsQueryAuditProofError" - enum="NetErrorCodes" expires_after="M78"> + enum="NetErrorCodes" expires_after="M76"> + <obsolete> + Removed in Chrome 76. + </obsolete> <owner>robpercival@chromium.org</owner> <summary> Counts of specific error codes returned by LogDnsClient at the end of an @@ -65609,7 +65621,10 @@ </histogram> <histogram name="Net.CertificateTransparency.DnsQueryAuditProofRcode" - enum="AsyncDNSRcode"> + enum="AsyncDNSRcode" expires_after="M76"> + <obsolete> + Removed in Chrome 76. + </obsolete> <owner>robpercival@chromium.org</owner> <summary> Counts of specific DNS response codes returned by LogDnsClient at the end of @@ -65620,7 +65635,10 @@ </histogram> <histogram name="Net.CertificateTransparency.DnsQueryDuration" units="ms" - expires_after="M78"> + expires_after="M76"> + <obsolete> + Removed in Chrome 76. + </obsolete> <owner>robpercival@chromium.org</owner> <summary> The time taken attempting to obtain an inclusion proof from a Certificate @@ -65630,7 +65648,10 @@ </histogram> <histogram name="Net.CertificateTransparency.DnsQueryDuration.Success" - units="ms" expires_after="M78"> + units="ms" expires_after="M76"> + <obsolete> + Removed in Chrome 76. + </obsolete> <owner>robpercival@chromium.org</owner> <summary> The time taken to successfully obtain an inclusion proof from a Certificate @@ -65640,7 +65661,10 @@ </histogram> <histogram name="Net.CertificateTransparency.DnsQueryLeafIndexError" - enum="NetErrorCodes"> + enum="NetErrorCodes" expires_after="M76"> + <obsolete> + Removed in Chrome 76. + </obsolete> <owner>robpercival@chromium.org</owner> <summary> Counts of specific error codes returned by LogDnsClient at the end of an @@ -65650,7 +65674,10 @@ </histogram> <histogram name="Net.CertificateTransparency.DnsQueryLeafIndexRcode" - enum="AsyncDNSRcode" expires_after="M78"> + enum="AsyncDNSRcode" expires_after="M76"> + <obsolete> + Removed in Chrome 76. + </obsolete> <owner>robpercival@chromium.org</owner> <summary> Counts of specific DNS response codes returned by LogDnsClient at the end of @@ -65720,7 +65747,10 @@ </histogram> <histogram name="Net.CertificateTransparency.InclusionCheckResult" - enum="CTLogEntryInclusionCheckResult" expires_after="M78"> + enum="CTLogEntryInclusionCheckResult" expires_after="M76"> + <obsolete> + Removed in Chrome 76. + </obsolete> <owner>estark@chromium.org</owner> <owner>rsleevi@chromium.org</owner> <summary> @@ -65744,7 +65774,11 @@ </summary> </histogram> -<histogram name="Net.CertificateTransparency.PilotSTHAge" units="ms"> +<histogram name="Net.CertificateTransparency.PilotSTHAge" units="ms" + expires_after="M76"> + <obsolete> + Removed in Chrome 76. + </obsolete> <owner>estark@chromium.org</owner> <owner>rsleevi@chromium.org</owner> <summary> @@ -73600,7 +73634,7 @@ </histogram> <histogram name="Net.SSLTLS13Downgrade" enum="BooleanDowngrade" - expires_after="2019-06-30"> + expires_after="2019-12-31"> <owner>svaldez@chromium.org</owner> <owner>davidben@chromium.org</owner> <summary> @@ -73611,7 +73645,7 @@ </histogram> <histogram name="Net.SSLTLS13DowngradeTLS13Experiment" enum="BooleanDowngrade" - expires_after="2019-06-30"> + expires_after="2019-12-31"> <owner>svaldez@chromium.org</owner> <owner>davidben@chromium.org</owner> <summary> @@ -73623,7 +73657,7 @@ </histogram> <histogram name="Net.SSLTLS13DowngradeType" enum="TLS13DowngradeType" - expires_after="2019-06-30"> + expires_after="2019-12-31"> <owner>svaldez@chromium.org</owner> <owner>davidben@chromium.org</owner> <summary> @@ -73633,7 +73667,7 @@ </histogram> <histogram name="Net.SSLTLS13DowngradeTypeTLS13Experiment" - enum="TLS13DowngradeType" expires_after="2019-06-30"> + enum="TLS13DowngradeType" expires_after="2019-12-31"> <owner>svaldez@chromium.org</owner> <owner>davidben@chromium.org</owner> <summary>
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config index 5551a94..208b227 100644 --- a/tools/perf/expectations.config +++ b/tools/perf/expectations.config
@@ -37,6 +37,9 @@ crbug.com/853738 [ Android_Webview ] blink_perf.canvas/draw-video-to-hw-accelerated-canvas-2d.html [ Skip ] crbug.com/853738 [ Android_Webview ] blink_perf.canvas/upload-video-to-sub-texture.html [ Skip ] crbug.com/853738 [ Android_Webview ] blink_perf.canvas/upload-video-to-texture.html [ Skip ] +crbug.com/967809 [ Android_Webview ] blink_perf.canvas/draw-video-to-hw-accelerated-canvas-2d_RAF.html?RAF [ Skip ] +crbug.com/967809 [ Android_Webview ] blink_perf.canvas/upload-video-to-sub-texture_RAF.html?RAF [ Skip ] +crbug.com/967809 [ Android_Webview ] blink_perf.canvas/upload-video-to-texture_RAF.html?RAF [ Skip ] # Benchmark: blink_perf.css crbug.com/891878 [ Nexus5X_Webview ] blink_perf.css/CustomPropertiesVarAlias.html [ Skip ] @@ -248,6 +251,7 @@ crbug.com/954948 [ Android_Webview ] rendering.mobile/cnn_mobile_pinch_2018 [ Skip ] crbug.com/966637 [ Pixel2_Webview ] rendering.mobile/google_news_mobile_2018 [ Skip ] crbug.com/966631 [ Pixel_2 ] rendering.mobile/* [ Skip ] # mass disabling to set up the bot for pixel 2 +crbug.com/967809 [ Android_Webview ] rendering.mobile/microsoft_video_city [ Skip ] # Benchmark: rasterize_and_record_micro.top_25 crbug.com/764543 [ All ] rasterize_and_record_micro.top_25/file://static_top_25/wikipedia.html [ Skip ]
diff --git a/ui/base/clipboard/test/test_clipboard.cc b/ui/base/clipboard/test/test_clipboard.cc index 6fa3c0e..6e299a4 100644 --- a/ui/base/clipboard/test/test_clipboard.cc +++ b/ui/base/clipboard/test/test_clipboard.cc
@@ -8,6 +8,7 @@ #include "base/memory/ptr_util.h" #include "base/numerics/safe_conversions.h" #include "base/strings/utf_string_conversions.h" +#include "build/build_config.h" #include "skia/ext/skia_utils_base.h" #include "ui/base/clipboard/clipboard_constants.h" #include "ui/base/clipboard/clipboard_monitor.h" @@ -39,6 +40,12 @@ bool TestClipboard::IsFormatAvailable(const ClipboardFormatType& format, ClipboardType type) const { +#if defined(OS_LINUX) + // The linux clipboard treats the presence of text on the clipboard + // as the url format being available. + if (format.Equals(ClipboardFormatType::GetUrlType())) + return IsFormatAvailable(ClipboardFormatType::GetPlainTextType(), type); +#endif // OS_LINUX const DataStore& store = GetStore(type); return store.data.find(format) != store.data.end(); }
diff --git a/ui/gfx/mojo/rrect_f_struct_traits.h b/ui/gfx/mojo/rrect_f_struct_traits.h index 46f97d2..017abcb 100644 --- a/ui/gfx/mojo/rrect_f_struct_traits.h +++ b/ui/gfx/mojo/rrect_f_struct_traits.h
@@ -89,9 +89,10 @@ gfx::Vector2dF upper_left; if (!data.ReadUpperLeft(&upper_left)) return false; - *out = gfx::RRectF(rect, upper_left.x(), upper_left.y()); - if (type <= gfx::RRectF::Type::kSimple) + if (type <= gfx::RRectF::Type::kSimple) { + *out = gfx::RRectF(rect, upper_left.x(), upper_left.y()); return true; + } gfx::Vector2dF upper_right; gfx::Vector2dF lower_right; gfx::Vector2dF lower_left; @@ -100,9 +101,9 @@ !data.ReadLowerLeft(&lower_left)) { return false; } - out->SetCornerRadii(gfx::RRectF::Corner::kUpperRight, upper_right); - out->SetCornerRadii(gfx::RRectF::Corner::kLowerRight, lower_right); - out->SetCornerRadii(gfx::RRectF::Corner::kLowerLeft, lower_left); + *out = gfx::RRectF(rect, upper_left.x(), upper_left.y(), upper_right.x(), + upper_right.y(), lower_right.x(), lower_right.y(), + lower_left.x(), lower_left.y()); return true; } };
diff --git a/ui/gfx/mojo/struct_traits_unittest.cc b/ui/gfx/mojo/struct_traits_unittest.cc index dcc1add1..d0102eb 100644 --- a/ui/gfx/mojo/struct_traits_unittest.cc +++ b/ui/gfx/mojo/struct_traits_unittest.cc
@@ -273,6 +273,12 @@ EXPECT_EQ(input.GetType(), RRectF::Type::kOval); proxy->EchoRRectF(input, &output); EXPECT_EQ(input, output); + input.SetCornerRadii(RRectF::Corner::kUpperLeft, 50, 50); + input.SetCornerRadii(RRectF::Corner::kUpperRight, 20, 20); + input.SetCornerRadii(RRectF::Corner::kLowerRight, 0, 0); + input.SetCornerRadii(RRectF::Corner::kLowerLeft, 0, 0); + proxy->EchoRRectF(input, &output); + EXPECT_EQ(input, output); } } // namespace gfx
diff --git a/ui/gfx/rrect_f.cc b/ui/gfx/rrect_f.cc index 7d3a6255..4f08af2 100644 --- a/ui/gfx/rrect_f.cc +++ b/ui/gfx/rrect_f.cc
@@ -42,11 +42,19 @@ float lower_right_x, float lower_right_y, float lower_left_x, - float lower_left_y) - : RRectF(x, y, width, height, upper_left_x, upper_left_y) { - SetCornerRadii(RRectF::Corner::kUpperRight, upper_right_x, upper_right_y); - SetCornerRadii(RRectF::Corner::kLowerRight, lower_right_x, lower_right_y); - SetCornerRadii(RRectF::Corner::kLowerLeft, lower_left_x, lower_left_y); + float lower_left_y) { + SkVector radii[4] = { + {upper_left_x, upper_left_y}, + {upper_right_x, upper_right_y}, + {lower_right_x, lower_right_y}, + {lower_left_x, lower_left_y}, + }; + skrrect_.setRectRadii(SkRect::MakeXYWH(x, y, width, height), radii); + if (IsEmpty()) { + // Make sure that empty rects are created fully empty, not with some + // non-zero dimensions. + skrrect_ = SkRRect::MakeEmpty(); + } } gfx::Vector2dF RRectF::GetSimpleRadii() const {
diff --git a/ui/gl/direct_composition_surface_win.cc b/ui/gl/direct_composition_surface_win.cc index ceb798c..b749445e 100644 --- a/ui/gl/direct_composition_surface_win.cc +++ b/ui/gl/direct_composition_surface_win.cc
@@ -31,11 +31,6 @@ namespace gl { namespace { -struct OverlaySupportInfo { - DXGI_FORMAT format; - UINT flags; -}; - // Indicates support for either NV12 or YUY2 hardware overlays. bool g_supports_overlays = false; @@ -47,12 +42,15 @@ // overlays using command line flags. DXGI_FORMAT g_overlay_format_used = DXGI_FORMAT_NV12; -// This is the raw support info, which shouldn't depend on field trial state, or -// command line flags. Ordered by most preferred to least preferred format. -OverlaySupportInfo g_overlay_support_info[] = { - {DXGI_FORMAT_NV12, 0}, - {DXGI_FORMAT_YUY2, 0}, -}; +// These are the raw support info, which shouldn't depend on field trial state, +// or command line flags. +UINT g_nv12_overlay_support_flags = 0; +UINT g_yuy2_overlay_support_flags = 0; + +bool FlagsSupportsOverlays(UINT flags) { + return (flags & (DXGI_OVERLAY_SUPPORT_FLAG_DIRECT | + DXGI_OVERLAY_SUPPORT_FLAG_SCALING)); +} void InitializeHardwareOverlaySupport() { static bool overlay_support_initialized = false; @@ -95,7 +93,6 @@ return; } - bool supports_nv12_rec709 = false; unsigned int i = 0; while (true) { Microsoft::WRL::ComPtr<IDXGIOutput> output; @@ -106,62 +103,47 @@ if (FAILED(output.As(&output3))) continue; DCHECK(output3); + output3->CheckOverlaySupport(DXGI_FORMAT_NV12, d3d11_device.Get(), + &g_nv12_overlay_support_flags); + output3->CheckOverlaySupport(DXGI_FORMAT_YUY2, d3d11_device.Get(), + &g_yuy2_overlay_support_flags); + if (FlagsSupportsOverlays(g_nv12_overlay_support_flags) && + base::FeatureList::IsEnabled( + features::kDirectCompositionPreferNV12Overlays)) { + // NV12 format is preferred if it's supported. - // TODO(zmo): Get rid of the loop and just set two global vars for NV12 - // and YUY2. - for (auto& info : g_overlay_support_info) { - if (FAILED(output3->CheckOverlaySupport(info.format, d3d11_device.Get(), - &info.flags))) { - continue; - } // Per Intel's request, use NV12 only when // COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709 is also supported. Rec 709 is // commonly used for H.264 and HEVC. At least one Intel Gen9 SKU will not // support NV12 overlays. - if (info.format == DXGI_FORMAT_NV12) { - UINT color_space_support_flags = 0; - Microsoft::WRL::ComPtr<IDXGIOutput4> output4; - if (FAILED(output.As(&output4))) - continue; - - if (FAILED(output4->CheckOverlayColorSpaceSupport( - info.format, DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709, - d3d11_device.Get(), &color_space_support_flags))) { - continue; - } - supports_nv12_rec709 = - !!(color_space_support_flags & - DXGI_OVERLAY_COLOR_SPACE_SUPPORT_FLAG_PRESENT); - } - - // Formats are ordered by most preferred to least preferred. Don't choose - // a less preferred format, but keep going so that we can record overlay - // support for all formats in UMA. - if (g_supports_overlays) - continue; - // Overlays are supported for NV12 only if the feature flag to prefer NV12 - // over YUY2 is enabled. - bool prefer_nv12 = base::FeatureList::IsEnabled( - features::kDirectCompositionPreferNV12Overlays); - if (info.format == DXGI_FORMAT_NV12 && - (!prefer_nv12 || !supports_nv12_rec709)) - continue; - // Some new Intel drivers only claim to support unscaled overlays, but - // scaled overlays still work. It's possible DWM works around it by - // performing an extra scaling Blt before calling the driver. Even when - // scaled overlays aren't actually supported, presentation using the - // overlay path should be relatively efficient. - if (info.flags & (DXGI_OVERLAY_SUPPORT_FLAG_DIRECT | - DXGI_OVERLAY_SUPPORT_FLAG_SCALING)) { - g_overlay_format_used = info.format; - + UINT color_space_support_flags = 0; + Microsoft::WRL::ComPtr<IDXGIOutput4> output4; + if (SUCCEEDED(output.As(&output4)) && + SUCCEEDED(output4->CheckOverlayColorSpaceSupport( + DXGI_FORMAT_NV12, DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709, + d3d11_device.Get(), &color_space_support_flags)) && + (color_space_support_flags & + DXGI_OVERLAY_COLOR_SPACE_SUPPORT_FLAG_PRESENT)) { + // Some new Intel drivers only claim to support unscaled overlays, but + // scaled overlays still work. It's possible DWM works around it by + // performing an extra scaling Blt before calling the driver. Even when + // scaled overlays aren't actually supported, presentation using the + // overlay path should be relatively efficient. + g_overlay_format_used = DXGI_FORMAT_NV12; g_supports_overlays = true; - - DXGI_OUTPUT_DESC monitor_desc = {}; - if (SUCCEEDED(output3->GetDesc(&monitor_desc))) { - g_overlay_monitor_size = - gfx::Rect(monitor_desc.DesktopCoordinates).size(); - } + } + } + if (!g_supports_overlays && + FlagsSupportsOverlays(g_yuy2_overlay_support_flags)) { + // If NV12 isn't supported, fallback to YUY2 if it's supported. + g_overlay_format_used = DXGI_FORMAT_YUY2; + g_supports_overlays = true; + } + if (g_supports_overlays) { + DXGI_OUTPUT_DESC monitor_desc = {}; + if (SUCCEEDED(output3->GetDesc(&monitor_desc))) { + g_overlay_monitor_size = + gfx::Rect(monitor_desc.DesktopCoordinates).size(); } } // Early out after the first output that reports overlay support. All @@ -278,30 +260,20 @@ // static bool DirectCompositionSurfaceWin::AreScaledOverlaysSupported() { - for (const auto& info : g_overlay_support_info) { - if (info.format == g_overlay_format_used) - return !!(info.flags & DXGI_OVERLAY_SUPPORT_FLAG_SCALING); - } - NOTREACHED(); - return false; + InitializeHardwareOverlaySupport(); + if (g_overlay_format_used == DXGI_FORMAT_NV12) + return !!(g_nv12_overlay_support_flags & DXGI_OVERLAY_SUPPORT_FLAG_SCALING); + DCHECK_EQ(DXGI_FORMAT_YUY2, g_overlay_format_used); + return !!(g_yuy2_overlay_support_flags & DXGI_OVERLAY_SUPPORT_FLAG_SCALING); } // static -bool DirectCompositionSurfaceWin::SupportsOverlayFormat( - DXGI_FORMAT format, - bool* supports_scaling) { +UINT DirectCompositionSurfaceWin::GetOverlaySupportFlags(DXGI_FORMAT format) { InitializeHardwareOverlaySupport(); - DCHECK(supports_scaling); - *supports_scaling = false; - for (const auto& info : g_overlay_support_info) { - if (info.flags) { - if (format == info.format) { - *supports_scaling = !!(info.flags & DXGI_OVERLAY_SUPPORT_FLAG_SCALING); - return true; - } - } - } - return false; + if (format == DXGI_FORMAT_NV12) + return g_nv12_overlay_support_flags; + DCHECK_EQ(DXGI_FORMAT_YUY2, format); + return g_yuy2_overlay_support_flags; } // static @@ -317,17 +289,18 @@ // static void DirectCompositionSurfaceWin::SetScaledOverlaysSupportedForTesting( bool supported) { - for (auto& info : g_overlay_support_info) { - if (supported) - info.flags |= DXGI_OVERLAY_SUPPORT_FLAG_SCALING; - else - info.flags &= ~DXGI_OVERLAY_SUPPORT_FLAG_SCALING; + if (supported) { + g_nv12_overlay_support_flags |= DXGI_OVERLAY_SUPPORT_FLAG_SCALING; + g_yuy2_overlay_support_flags |= DXGI_OVERLAY_SUPPORT_FLAG_SCALING; + } else { + g_nv12_overlay_support_flags &= ~DXGI_OVERLAY_SUPPORT_FLAG_SCALING; + g_yuy2_overlay_support_flags &= ~DXGI_OVERLAY_SUPPORT_FLAG_SCALING; } } // static -void DirectCompositionSurfaceWin::SetPreferNV12OverlaysForTesting() { - g_overlay_format_used = DXGI_FORMAT_NV12; +void DirectCompositionSurfaceWin::SetPreferYUY2OverlaysForTesting() { + g_overlay_format_used = DXGI_FORMAT_YUY2; } // static
diff --git a/ui/gl/direct_composition_surface_win.h b/ui/gl/direct_composition_surface_win.h index 18277e7d..6cf4ca5a 100644 --- a/ui/gl/direct_composition_surface_win.h +++ b/ui/gl/direct_composition_surface_win.h
@@ -64,17 +64,17 @@ // Returns monitor size. static gfx::Size GetOverlayMonitorSize(); - // Returns if the given format is supported for hardware overlays. - // Also, if |supports_scaling| is set to true, SCALING mode is supported for - // the given format; otherwise, only DIRECT mode is supported. - static bool SupportsOverlayFormat(DXGI_FORMAT format, bool* supports_scaling); + // Returns overlay support flags for the given format. + // Caller should check for DXGI_OVERLAY_SUPPORT_FLAG_DIRECT and + // DXGI_OVERLAY_SUPPORT_FLAG_SCALING bits. + static UINT GetOverlaySupportFlags(DXGI_FORMAT format); // Returns true if there is an HDR capable display connected. static bool IsHDRSupported(); static void SetScaledOverlaysSupportedForTesting(bool value); - static void SetPreferNV12OverlaysForTesting(); + static void SetPreferYUY2OverlaysForTesting(); bool InitializeNativeWindow();
diff --git a/ui/gl/direct_composition_surface_win_unittest.cc b/ui/gl/direct_composition_surface_win_unittest.cc index 6315b63..e09996b 100644 --- a/ui/gl/direct_composition_surface_win_unittest.cc +++ b/ui/gl/direct_composition_surface_win_unittest.cc
@@ -600,6 +600,48 @@ DirectCompositionSurfaceTest::TearDown(); } + void InitializeForPixelTest(const gfx::Size& window_size, + const gfx::Size& texture_size, + const gfx::Rect& content_rect, + const gfx::Rect& quad_rect) { + EXPECT_TRUE(surface_->Resize(window_size, 1.0, + GLSurface::ColorSpace::UNSPECIFIED, true)); + EXPECT_TRUE(surface_->SetDrawRectangle(gfx::Rect(window_size))); + + glClearColor(0.0, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + + Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device = + QueryD3D11DeviceObjectFromANGLE(); + + Microsoft::WRL::ComPtr<ID3D11Texture2D> texture = + CreateNV12Texture(d3d11_device, texture_size, true); + Microsoft::WRL::ComPtr<IDXGIResource1> resource; + texture.As(&resource); + HANDLE handle = 0; + resource->CreateSharedHandle(nullptr, DXGI_SHARED_RESOURCE_READ, nullptr, + &handle); + // The format doesn't matter, since we aren't binding. + scoped_refptr<GLImageDXGI> image_dxgi( + new GLImageDXGI(texture_size, nullptr)); + ASSERT_TRUE(image_dxgi->InitializeHandle(base::win::ScopedHandle(handle), 0, + gfx::BufferFormat::RGBA_8888)); + + // Pass content rect with odd with and height. Surface should round up + // width and height when creating swap chain. + ui::DCRendererLayerParams params; + params.y_image = image_dxgi; + params.uv_image = image_dxgi; + params.content_rect = content_rect; + params.quad_rect = quad_rect; + surface_->ScheduleDCLayer(params); + + EXPECT_EQ(gfx::SwapResult::SWAP_ACK, + surface_->SwapBuffers(base::DoNothing())); + + Sleep(1000); + } + void PixelTestSwapChain(bool layers_enabled) { if (!surface_) return; @@ -782,36 +824,10 @@ return; gfx::Size window_size(100, 100); - EXPECT_TRUE(surface_->Resize(window_size, 1.0, - GLSurface::ColorSpace::UNSPECIFIED, true)); - - Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device = - QueryD3D11DeviceObjectFromANGLE(); - gfx::Size texture_size(50, 50); - Microsoft::WRL::ComPtr<ID3D11Texture2D> texture = - CreateNV12Texture(d3d11_device, texture_size, true); - Microsoft::WRL::ComPtr<IDXGIResource1> resource; - texture.As(&resource); - HANDLE handle = 0; - resource->CreateSharedHandle(nullptr, DXGI_SHARED_RESOURCE_READ, nullptr, - &handle); - // The format doesn't matter, since we aren't binding. - scoped_refptr<GLImageDXGI> image_dxgi(new GLImageDXGI(texture_size, nullptr)); - ASSERT_TRUE(image_dxgi->InitializeHandle(base::win::ScopedHandle(handle), 0, - gfx::BufferFormat::RGBA_8888)); - - ui::DCRendererLayerParams params; - params.y_image = image_dxgi; - params.uv_image = image_dxgi; - params.content_rect = gfx::Rect(texture_size); - params.quad_rect = gfx::Rect(window_size); - surface_->ScheduleDCLayer(params); - - EXPECT_EQ(gfx::SwapResult::SWAP_ACK, - surface_->SwapBuffers(base::DoNothing())); - - Sleep(1000); + gfx::Rect content_rect(texture_size); + gfx::Rect quad_rect(window_size); + InitializeForPixelTest(window_size, texture_size, content_rect, quad_rect); SkColor expected_color = SkColorSetRGB(0xe1, 0x90, 0xeb); SkColor actual_color = @@ -826,40 +842,10 @@ return; gfx::Size window_size(100, 100); - EXPECT_TRUE(surface_->Resize(window_size, 1.0, - GLSurface::ColorSpace::UNSPECIFIED, true)); - EXPECT_TRUE(surface_->SetDrawRectangle(gfx::Rect(window_size))); - - glClearColor(0.0, 0.0, 0.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - - Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device = - QueryD3D11DeviceObjectFromANGLE(); - gfx::Size texture_size(50, 50); - Microsoft::WRL::ComPtr<ID3D11Texture2D> texture = - CreateNV12Texture(d3d11_device, texture_size, true); - Microsoft::WRL::ComPtr<IDXGIResource1> resource; - texture.As(&resource); - HANDLE handle = 0; - resource->CreateSharedHandle(nullptr, DXGI_SHARED_RESOURCE_READ, nullptr, - &handle); - // The format doesn't matter, since we aren't binding. - scoped_refptr<GLImageDXGI> image_dxgi(new GLImageDXGI(texture_size, nullptr)); - ASSERT_TRUE(image_dxgi->InitializeHandle(base::win::ScopedHandle(handle), 0, - gfx::BufferFormat::RGBA_8888)); - - // Layer with empty bounds rect. - ui::DCRendererLayerParams params; - params.y_image = image_dxgi; - params.uv_image = image_dxgi; - params.content_rect = gfx::Rect(texture_size); - surface_->ScheduleDCLayer(params); - - EXPECT_EQ(gfx::SwapResult::SWAP_ACK, - surface_->SwapBuffers(base::DoNothing())); - - Sleep(1000); + gfx::Rect content_rect(texture_size); + gfx::Rect quad_rect; // Layer with empty bounds rect. + InitializeForPixelTest(window_size, texture_size, content_rect, quad_rect); // No color is written since the visual committed to DirectComposition has no // content. @@ -927,45 +913,14 @@ TEST_F(DirectCompositionPixelTest, NV12SwapChain) { if (!surface_) return; - DirectCompositionSurfaceWin::SetPreferNV12OverlaysForTesting(); gfx::Size window_size(100, 100); - EXPECT_TRUE(surface_->Resize(window_size, 1.0, - GLSurface::ColorSpace::UNSPECIFIED, true)); - EXPECT_TRUE(surface_->SetDrawRectangle(gfx::Rect(window_size))); - - glClearColor(0.0, 0.0, 0.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - - Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device = - QueryD3D11DeviceObjectFromANGLE(); - gfx::Size texture_size(50, 50); - Microsoft::WRL::ComPtr<ID3D11Texture2D> texture = - CreateNV12Texture(d3d11_device, texture_size, true); - Microsoft::WRL::ComPtr<IDXGIResource1> resource; - texture.As(&resource); - HANDLE handle = 0; - resource->CreateSharedHandle(nullptr, DXGI_SHARED_RESOURCE_READ, nullptr, - &handle); - // The format doesn't matter, since we aren't binding. - scoped_refptr<GLImageDXGI> image_dxgi(new GLImageDXGI(texture_size, nullptr)); - ASSERT_TRUE(image_dxgi->InitializeHandle(base::win::ScopedHandle(handle), 0, - gfx::BufferFormat::RGBA_8888)); - - // Pass content rect with odd with and height. Surface should round up width - // and height when creating swap chain. - ui::DCRendererLayerParams params; - params.y_image = image_dxgi; - params.uv_image = image_dxgi; - params.content_rect = gfx::Rect(0, 0, 49, 49); - params.quad_rect = gfx::Rect(window_size); - surface_->ScheduleDCLayer(params); - - EXPECT_EQ(gfx::SwapResult::SWAP_ACK, - surface_->SwapBuffers(base::DoNothing())); - - Sleep(1000); + // Pass content rect with odd with and height. Surface should round up + // width and height when creating swap chain. + gfx::Rect content_rect(0, 0, 49, 49); + gfx::Rect quad_rect(window_size); + InitializeForPixelTest(window_size, texture_size, content_rect, quad_rect); Microsoft::WRL::ComPtr<IDXGISwapChain1> swap_chain = surface_->GetLayerSwapChainForTesting(0); @@ -993,40 +948,10 @@ DirectCompositionSurfaceWin::SetScaledOverlaysSupportedForTesting(true); gfx::Size window_size(100, 100); - EXPECT_TRUE(surface_->Resize(window_size, 1.0, - GLSurface::ColorSpace::UNSPECIFIED, true)); - EXPECT_TRUE(surface_->SetDrawRectangle(gfx::Rect(window_size))); - - glClearColor(0.0, 0.0, 0.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - - Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device = - QueryD3D11DeviceObjectFromANGLE(); - gfx::Size texture_size(50, 50); - Microsoft::WRL::ComPtr<ID3D11Texture2D> texture = - CreateNV12Texture(d3d11_device, texture_size, true); - Microsoft::WRL::ComPtr<IDXGIResource1> resource; - texture.As(&resource); - HANDLE handle = 0; - resource->CreateSharedHandle(nullptr, DXGI_SHARED_RESOURCE_READ, nullptr, - &handle); - // The format doesn't matter, since we aren't binding. - scoped_refptr<GLImageDXGI> image_dxgi(new GLImageDXGI(texture_size, nullptr)); - ASSERT_TRUE(image_dxgi->InitializeHandle(base::win::ScopedHandle(handle), 0, - gfx::BufferFormat::RGBA_8888)); - - ui::DCRendererLayerParams params; - params.y_image = image_dxgi; - params.uv_image = image_dxgi; - params.content_rect = gfx::Rect(texture_size); - params.quad_rect = gfx::Rect(gfx::Point(25, 25), texture_size); - surface_->ScheduleDCLayer(params); - - EXPECT_EQ(gfx::SwapResult::SWAP_ACK, - surface_->SwapBuffers(base::DoNothing())); - - Sleep(1000); + gfx::Rect content_rect(texture_size); + gfx::Rect quad_rect(gfx::Point(25, 25), texture_size); + InitializeForPixelTest(window_size, texture_size, content_rect, quad_rect); SkColor video_color = SkColorSetRGB(0xe1, 0x90, 0xeb); struct {
diff --git a/ui/gl/gl_surface_egl_surface_control.h b/ui/gl/gl_surface_egl_surface_control.h index cd31529..3a4b9d9 100644 --- a/ui/gl/gl_surface_egl_surface_control.h +++ b/ui/gl/gl_surface_egl_surface_control.h
@@ -193,7 +193,7 @@ bool transaction_ack_pending_ = false; gfx::OverlayTransform display_transform_ = gfx::OVERLAY_TRANSFORM_NONE; - EGLSurface offscreen_surface_; + EGLSurface offscreen_surface_ = nullptr; base::CancelableOnceClosure check_pending_presentation_callback_queue_task_; scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner_;
diff --git a/ui/views/controls/editable_combobox/editable_combobox.cc b/ui/views/controls/editable_combobox/editable_combobox.cc index f60d1c9..56ba44e 100644 --- a/ui/views/controls/editable_combobox/editable_combobox.cc +++ b/ui/views/controls/editable_combobox/editable_combobox.cc
@@ -291,6 +291,7 @@ } EditableCombobox::~EditableCombobox() { + CloseMenu(); textfield_->set_controller(nullptr); textfield_->RemoveObserver(this); }
diff --git a/ui/views/controls/editable_combobox/editable_combobox_unittest.cc b/ui/views/controls/editable_combobox/editable_combobox_unittest.cc index 1114ea17..c9f42e5 100644 --- a/ui/views/controls/editable_combobox/editable_combobox_unittest.cc +++ b/ui/views/controls/editable_combobox/editable_combobox_unittest.cc
@@ -110,6 +110,10 @@ }; void EditableComboboxTest::TearDown() { + if (IsMenuOpen()) { + combobox_->GetMenuRunnerForTest()->Cancel(); + WaitForMenuClosureAnimation(); + } if (widget_) widget_->Close(); ViewsTestBase::TearDown(); @@ -142,8 +146,6 @@ dummy_focusable_view_->SetID(2); InitWidget(); - combobox_->GetTextfieldForTest()->RequestFocus(); - combobox_->RequestFocus(); } // Initializes the widget where the combobox and the dummy control live. @@ -237,8 +239,6 @@ TEST_F(EditableComboboxTest, FocusOnTextfieldOpensMenu) { InitEditableCombobox(); - dummy_focusable_view_->RequestFocus(); - WaitForMenuClosureAnimation(); EXPECT_FALSE(IsMenuOpen()); combobox_->GetTextfieldForTest()->RequestFocus(); EXPECT_TRUE(IsMenuOpen());
diff --git a/ui/webui/resources/cr_elements/cr_icons_css.html b/ui/webui/resources/cr_elements/cr_icons_css.html index ca9a5cf..2b4f7d0 100644 --- a/ui/webui/resources/cr_elements/cr_icons_css.html +++ b/ui/webui/resources/cr_elements/cr_icons_css.html
@@ -98,7 +98,7 @@ .cr-icon).icon-more-vert { background-image: url(../images/dark/icon_more_vert.svg); } - :-webkit-any(paper-n-button, .cr-icon).icon-more-vert-light-mode { + :-webkit-any(cr-icon-button, .cr-icon).icon-more-vert-light-mode { background-image: url(../images/icon_more_vert.svg); }
diff --git a/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.js b/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.js index 4432178..3c8530df 100644 --- a/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.js +++ b/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.js
@@ -39,7 +39,10 @@ placeholder: String, /** @type {!Array<string>} */ - items: Array, + items: { + type: Array, + observer: 'onItemsChanged_', + }, /** @type {string} */ value: { @@ -58,6 +61,37 @@ /** @type {boolean} */ updateValueOnInput: Boolean, + + /** @private {boolean} */ + dropdownRefitPending_: Boolean, + }, + + /** + * Enqueue a task to refit the iron-dropdown if it is open. + * @suppress {missingProperties} Property refit never defined on dropdown + * @private + */ + enqueueDropdownRefit_: function() { + const dropdown = this.$$('iron-dropdown'); + if (!this.dropdownRefitPending_ && dropdown.opened) { + this.dropdownRefitPending_ = true; + setTimeout(() => { + dropdown.refit(); + this.dropdownRefitPending_ = false; + }, 0); + } + }, + + /** + * @param {!Array<string>} oldValue + * @param {!Array<string>} newValue + * @private + */ + onItemsChanged_: function(oldValue, newValue) { + // Refit the iron-dropdown so that it can expand as neccessary to + // accommodate new items. Refitting is done on a new task because the change + // notification might not yet have propagated to the iron-dropdown. + this.enqueueDropdownRefit_(); }, /** @private */ @@ -72,6 +106,15 @@ if (this.updateValueOnInput) { this.value = this.$.search.value; } + + // iron-dropdown sets its max-height when it is opened. If the current value + // results in no filtered items in the drop down list, the iron-dropdown + // will have a max-height for 0 items. If the user then clears the input + // field, a non-zero number of items might be displayed in the drop-down, + // but the height is still limited based on 0 items. This results in a tiny, + // but scollable dropdown. Refitting the dropdown allows it to expand to + // accommodate the new items. + this.enqueueDropdownRefit_(); }, /** @@ -118,4 +161,4 @@ return errorMessage; }, -}); \ No newline at end of file +});