diff --git a/BUILD.gn b/BUILD.gn index 6eefc1b..549429e 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -101,7 +101,6 @@ "//chrome", "//chrome/installer/zucchini:zucchini", "//chrome/installer/zucchini:zucchini_unittests", - "//chrome/profiling:unit_tests", "//chrome/test:browser_tests", "//chrome/test:interactive_ui_tests", "//chrome/test:sync_integration_tests", @@ -714,6 +713,10 @@ deps += [ "//tools/perf/contrib/vr_benchmarks:vr_perf_tests" ] } } + + if (is_fuchsia) { + deps += [ "//headless" ] + } } # TODO(GYP_GONE): This target exists for compatibility with GYP, specifically
diff --git a/DEPS b/DEPS index dbf21c3..2bb9e459 100644 --- a/DEPS +++ b/DEPS
@@ -40,11 +40,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': '32fa5104148722dbd6aac1ce8d38dcf47737f669', + 'skia_revision': '13544dffb9f700c1c387a90ae78a8b2c5b9ed061', # 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': 'f1317ecc526a2026e55c9bd6c532c3046defdeaa', + 'v8_revision': '07ee877db98940f66f9625ca1c6215c19450aa0b', # 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. @@ -64,7 +64,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': 'd27998f6526272a5b8732106aa9b75f724434aca', + 'pdfium_revision': 'd3002340caad8d688d0e4928a36e90d354a797bd', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -96,7 +96,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': '0eeb5baed7a4417ac083221805842019185ccec0', + 'catapult_revision': '5db51352aa5cca18e236d28ce85ba8b8a818fe12', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -362,7 +362,7 @@ Var('chromium_git') + '/external/github.com/swisspol/GCDWebServer.git' + '@' + '43555c66627f6ed44817855a0f6d465f559d30e0', 'src/ios/third_party/material_components_ios/src': - Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'c2a357fb67321e9660190c55b49836c51fe04821', + Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'a0466df249c593ba65007440d7a84e4665ac2631', 'src/ios/third_party/material_font_disk_loader_ios/src': Var('chromium_git') + '/external/github.com/material-foundation/material-font-disk-loader-ios.git' + '@' + '8e30188777b016182658fbaa0a4a020a48183224',
diff --git a/WATCHLISTS b/WATCHLISTS index 5ee2978..19924ac 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -772,6 +772,9 @@ 'courgette': { 'filepath': 'courgette/', }, + 'cq': { + 'filepath': 'infra/config/cq.cfg', + }, 'cr_elements': { 'filepath': 'ui/webui/resources/cr_element', }, @@ -920,9 +923,6 @@ 'gn': { 'filepath': 'tools/gn', }, - 'goma': { - 'filepath': 'infra/config/cq.cfg', - }, 'gpu': { 'filepath': 'gpu/', }, @@ -1985,6 +1985,11 @@ 'twellington+watch@chromium.org'], 'courgette': ['huangs+watch@chromium.org', 'wfh+watch@chromium.org'], + 'cq': ['cq-config-changes@chromium.org', + 'shinyak+cc@chromium.org', + 'tikuta+cc@chromium.org', + 'ukai+cc@chromium.org', + 'yyanagisawa+cc@chromium.org'], 'cr_elements': ['michaelpg+watch-elements@chromium.org', 'stevenjb+watch-md-settings@chromium.org'], 'custom_tabs': ['lizeb+watch-custom-tabs@chromium.org'], @@ -2037,10 +2042,6 @@ 'gn': ['agrieve+watch@chromium.org', 'dpranke@chromium.org', 'tfarina@chromium.org'], - 'goma': ['shinyak+cc@chromium.com', - 'tikuta+cc@chromium.com', - 'ukai+cc@chromium.com', - 'yyanagisawa+cc@chromium.com'], 'gpu': ['piman+watch@chromium.org'], 'history_ui': ['pam+watch@chromium.org'], 'hotword': ['rlp+watch@chromium.org'],
diff --git a/android_webview/browser/aw_browser_main_parts.cc b/android_webview/browser/aw_browser_main_parts.cc index 7f05440..6418442 100644 --- a/android_webview/browser/aw_browser_main_parts.cc +++ b/android_webview/browser/aw_browser_main_parts.cc
@@ -149,7 +149,7 @@ } if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableWebViewFinch)) { + switches::kEnableWebViewVariations)) { AwMetricsServiceClient::GetOrCreateGUID(); }
diff --git a/android_webview/browser/aw_contents_statics.cc b/android_webview/browser/aw_contents_statics.cc index 43b71bd..be551515 100644 --- a/android_webview/browser/aw_contents_statics.cc +++ b/android_webview/browser/aw_contents_statics.cc
@@ -13,6 +13,7 @@ #include "base/android/jni_string.h" #include "base/android/scoped_java_ref.h" #include "base/callback.h" +#include "components/security_interstitials/core/urls.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" #include "content/public/common/url_constants.h" @@ -52,6 +53,15 @@ } // namespace // static +ScopedJavaLocalRef<jstring> GetSafeBrowsingPrivacyPolicyUrl( + JNIEnv* env, + const JavaParamRef<jclass>&) { + // TODO(ntfschr): append the locale to this URL + return base::android::ConvertUTF8ToJavaString( + env, security_interstitials::kSafeBrowsingPrivacyPolicyUrl); +} + +// static void ClearClientCertPreferences(JNIEnv* env, const JavaParamRef<jclass>&, const JavaParamRef<jobject>& callback) {
diff --git a/android_webview/browser/aw_metrics_service_client.cc b/android_webview/browser/aw_metrics_service_client.cc index b8b55aa..1a7e8e7 100644 --- a/android_webview/browser/aw_metrics_service_client.cc +++ b/android_webview/browser/aw_metrics_service_client.cc
@@ -125,10 +125,10 @@ request_context_ = request_context; channel_ = GetChannelFromPackageName(); - // If Finch is enabled for WebView the GUID will already have been read at - // startup + // If variations are enabled for WebView the GUID will already have been read + // at startup if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableWebViewFinch)) { + switches::kEnableWebViewVariations)) { InitializeWithGUID(); } else { content::BrowserThread::PostTaskAndReply( @@ -141,7 +141,8 @@ void AwMetricsServiceClient::InitializeWithGUID() { // The guid must have already been initialized at this point, either - // synchronously or asynchronously depending on the kEnableWebViewFinch flag + // synchronously or asynchronously depending on the kEnableWebViewVariations + // flag DCHECK_EQ(g_client_id_guid.Get().length(), GUID_SIZE); pref_service_->SetString(metrics::prefs::kMetricsClientID, g_client_id_guid.Get());
diff --git a/android_webview/common/aw_switches.cc b/android_webview/common/aw_switches.cc index 555513c9f..a8d9e825 100644 --- a/android_webview/common/aw_switches.cc +++ b/android_webview/common/aw_switches.cc
@@ -6,7 +6,7 @@ namespace switches { -const char kEnableWebViewFinch[] = "enable-webview-finch"; +const char kEnableWebViewVariations[] = "enable-webview-variations"; const char kSyncOnDrawHardware[] = "sync-on-draw-hardware"; const char kWebViewSandboxedRenderer[] = "webview-sandboxed-renderer";
diff --git a/android_webview/common/aw_switches.h b/android_webview/common/aw_switches.h index c41a274..341712b 100644 --- a/android_webview/common/aw_switches.h +++ b/android_webview/common/aw_switches.h
@@ -7,7 +7,7 @@ namespace switches { -extern const char kEnableWebViewFinch[]; +extern const char kEnableWebViewVariations[]; extern const char kSyncOnDrawHardware[]; extern const char kWebViewSandboxedRenderer[]; extern const char kWebViewEnableSafeBrowsingSupport[];
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java index 6a5c5cc..c7eb4e9 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java
@@ -583,6 +583,16 @@ AwContentsStatics.setSafeBrowsingWhitelist(urls, callback); } + /** + * Returns a URL pointing to the privacy policy for Safe Browsing reporting. + * + * @return the url pointing to a privacy policy document which can be displayed + * to users. + */ + // TODO(ntfschr): add @Override once next android SDK rolls + public Uri getSafeBrowsingPrivacyPolicyUrl() { + return AwContentsStatics.getSafeBrowsingPrivacyPolicyUrl(); + } }; } }
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java b/android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java index e4e2605..f03750db 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java
@@ -6,6 +6,7 @@ import android.annotation.TargetApi; import android.content.Context; +import android.net.Uri; import android.webkit.ValueCallback; import org.chromium.base.ThreadUtils; @@ -154,6 +155,10 @@ } } + public static Uri getSafeBrowsingPrivacyPolicyUrl() { + return Uri.parse(nativeGetSafeBrowsingPrivacyPolicyUrl()); + } + public static void setCheckClearTextPermitted(boolean permitted) { nativeSetCheckClearTextPermitted(permitted); } @@ -176,6 +181,7 @@ //-------------------------------------------------------------------------------------------- // Native methods //-------------------------------------------------------------------------------------------- + private static native String nativeGetSafeBrowsingPrivacyPolicyUrl(); private static native void nativeClearClientCertPreferences(Runnable callback); private static native String nativeGetUnreachableWebDataUrl(); private static native String nativeGetProductVersion();
diff --git a/android_webview/javatests/AndroidManifest.xml b/android_webview/javatests/AndroidManifest.xml index ed0ae66f..07a3566 100644 --- a/android_webview/javatests/AndroidManifest.xml +++ b/android_webview/javatests/AndroidManifest.xml
@@ -8,6 +8,10 @@ <instrumentation android:name="org.chromium.android_webview.test.AwInstrumentationTestRunner" android:targetPackage="org.chromium.android_webview.shell" android:label="Tests for org.chromium.android_webview"/> + <instrumentation android:name="org.chromium.base.test.BaseChromiumAndroidJUnitRunner" + android:targetPackage="org.chromium.android_webview.shell" + chromium-junit4="true" + android:label="Tests for org.chromium.android_webview"/> <uses-permission android:name="android.permission.RUN_INSTRUMENTATION" /> <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" /> <uses-permission android:name="android.permission.READ_LOGS"/>
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AcceptLanguageTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AcceptLanguageTest.java index fdbc2148..187b398 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AcceptLanguageTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AcceptLanguageTest.java
@@ -85,9 +85,9 @@ getJavaScriptResultBodyTextContent(mAwContents, mContentsClient)); assertEquals(LocaleUtils.getDefaultLocaleString(), acceptLanguages[0]); - String[] acceptLanguagesJs = getAcceptLanguages( - JSUtils.executeJavaScriptAndWaitForResult( - this, mAwContents, mContentsClient.getOnEvaluateJavaScriptResultHelper(), + String[] acceptLanguagesJs = + getAcceptLanguages(JSUtils.executeJavaScriptAndWaitForResult(getInstrumentation(), + mAwContents, mContentsClient.getOnEvaluateJavaScriptResultHelper(), "navigator.languages.join(',')")); assertEquals(acceptLanguagesJs.length, acceptLanguages.length); for (int i = 0; i < acceptLanguagesJs.length; ++i) { @@ -128,9 +128,10 @@ assertEquals( LocaleUtils.getDefaultLocaleListString(), TextUtils.join(",", acceptLanguages)); - String[] acceptLanguagesJs = getAcceptLanguages(JSUtils.executeJavaScriptAndWaitForResult( - this, mAwContents, mContentsClient.getOnEvaluateJavaScriptResultHelper(), - "navigator.languages.join(',')")); + String[] acceptLanguagesJs = + getAcceptLanguages(JSUtils.executeJavaScriptAndWaitForResult(getInstrumentation(), + mAwContents, mContentsClient.getOnEvaluateJavaScriptResultHelper(), + "navigator.languages.join(',')")); assertEquals(acceptLanguagesJs.length, acceptLanguages.length); for (int i = 0; i < acceptLanguagesJs.length; ++i) { assertEquals(acceptLanguagesJs[i], acceptLanguages[i]);
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java index 4ff65e9..84f74a24 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java
@@ -126,7 +126,7 @@ } @Override - protected TestDependencyFactory createTestDependencyFactory() { + public TestDependencyFactory createTestDependencyFactory() { return new TestDependencyFactory() { @Override public AwScrollOffsetManager createScrollOffsetManager(
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java index ad613bf..16b780d 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java
@@ -70,7 +70,7 @@ } @Override - protected TestDependencyFactory createTestDependencyFactory() { + public TestDependencyFactory createTestDependencyFactory() { return new TestDependencyFactory() { @Override public AwLayoutSizer createLayoutSizer() {
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 new file mode 100644 index 0000000..d3bd9a5 --- /dev/null +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwActivityTestRule.java
@@ -0,0 +1,412 @@ +// 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. + +package org.chromium.android_webview.test; + +import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout; + +import android.app.Instrumentation; +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.rule.ActivityTestRule; + +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +import org.chromium.android_webview.AwBrowserContext; +import org.chromium.android_webview.AwContents; +import org.chromium.android_webview.AwContentsClient; +import org.chromium.android_webview.AwSettings; +import org.chromium.android_webview.test.AwTestBase.PopupInfo; +import org.chromium.android_webview.test.AwTestBase.TestDependencyFactory; +import org.chromium.android_webview.test.AwTestCommon.AwTestCommonCallback; +import org.chromium.base.test.util.CallbackHelper; +import org.chromium.base.test.util.InMemorySharedPreferences; +import org.chromium.net.test.util.TestWebServer; + +import java.lang.annotation.Annotation; +import java.util.Map; +import java.util.concurrent.Callable; + +/** Custom ActivityTestRunner for WebView instrumentation tests */ +public class AwActivityTestRule + extends ActivityTestRule<AwTestRunnerActivity> implements AwTestCommonCallback { + public static final long WAIT_TIMEOUT_MS = scaleTimeout(15000); + + public static final int CHECK_INTERVAL = 100; + + private Description mCurrentTestDescription; + + private final AwTestCommon mTestCommon; + + public AwActivityTestRule() { + super(AwTestRunnerActivity.class); + mTestCommon = new AwTestCommon(this); + } + + @Override + public Statement apply(final Statement base, Description description) { + mCurrentTestDescription = description; + return super.apply(new Statement() { + @Override + public void evaluate() throws Throwable { + setUp(); + base.evaluate(); + } + }, description); + } + + public void setUp() throws Exception { + mTestCommon.setUp(); + } + + @Override + public AwBrowserContext createAwBrowserContextOnUiThread( + InMemorySharedPreferences prefs, Context appContext) { + return new AwBrowserContext(prefs, appContext); + } + + @Override + public TestDependencyFactory createTestDependencyFactory() { + return new TestDependencyFactory(); + } + + /** + * Override this to return false if the test doesn't want to create an + * AwBrowserContext automatically. + */ + @Override + public boolean needsAwBrowserContextCreated() { + return true; + } + + /** + * Override this to return false if the test doesn't want the browser + * startup sequence to be run automatically. + * + * @return Whether the instrumentation test requires the browser process to + * already be started. + */ + @Override + public boolean needsBrowserProcessStarted() { + return true; + } + + public void createAwBrowserContext() { + mTestCommon.createAwBrowserContext(); + } + + public void startBrowserProcess() throws Exception { + mTestCommon.startBrowserProcess(); + } + + /** + * Runs a {@link Callable} on the main thread, blocking until it is + * complete, and returns the result. Calls + * {@link Instrumentation#waitForIdleSync()} first to help avoid certain + * race conditions. + * + * @param <R> Type of result to return + */ + public <R> R runTestOnUiThreadAndGetResult(Callable<R> callable) throws Exception { + return mTestCommon.runTestOnUiThreadAndGetResult(callable); + } + + public void enableJavaScriptOnUiThread(final AwContents awContents) { + mTestCommon.enableJavaScriptOnUiThread(awContents); + } + + public void setNetworkAvailableOnUiThread( + final AwContents awContents, final boolean networkUp) { + mTestCommon.setNetworkAvailableOnUiThread(awContents, networkUp); + } + + /** + * Loads url on the UI thread and blocks until onPageFinished is called. + */ + public void loadUrlSync(final AwContents awContents, CallbackHelper onPageFinishedHelper, + final String url) throws Exception { + mTestCommon.loadUrlSync(awContents, onPageFinishedHelper, url); + } + + public void loadUrlSync(final AwContents awContents, CallbackHelper onPageFinishedHelper, + final String url, final Map<String, String> extraHeaders) throws Exception { + mTestCommon.loadUrlSync(awContents, onPageFinishedHelper, url, extraHeaders); + } + + public void loadUrlSyncAndExpectError(final AwContents awContents, + CallbackHelper onPageFinishedHelper, CallbackHelper onReceivedErrorHelper, + final String url) throws Exception { + mTestCommon.loadUrlSyncAndExpectError( + awContents, onPageFinishedHelper, onReceivedErrorHelper, url); + } + + /** + * Loads url on the UI thread but does not block. + */ + public void loadUrlAsync(final AwContents awContents, final String url) throws Exception { + mTestCommon.loadUrlAsync(awContents, url); + } + + public void loadUrlAsync( + final AwContents awContents, final String url, final Map<String, String> extraHeaders) { + mTestCommon.loadUrlAsync(awContents, url, extraHeaders); + } + + /** + * Posts url on the UI thread and blocks until onPageFinished is called. + */ + public void postUrlSync(final AwContents awContents, CallbackHelper onPageFinishedHelper, + final String url, byte[] postData) throws Exception { + mTestCommon.postUrlSync(awContents, onPageFinishedHelper, url, postData); + } + + /** + * Loads url on the UI thread but does not block. + */ + public void postUrlAsync(final AwContents awContents, final String url, byte[] postData) + throws Exception { + mTestCommon.postUrlAsync(awContents, url, postData); + } + + /** + * Loads data on the UI thread and blocks until onPageFinished is called. + */ + public void loadDataSync(final AwContents awContents, CallbackHelper onPageFinishedHelper, + final String data, final String mimeType, final boolean isBase64Encoded) + throws Exception { + mTestCommon.loadDataSync(awContents, onPageFinishedHelper, data, mimeType, isBase64Encoded); + } + + public void loadDataSyncWithCharset(final AwContents awContents, + CallbackHelper onPageFinishedHelper, final String data, final String mimeType, + final boolean isBase64Encoded, final String charset) throws Exception { + mTestCommon.loadDataSyncWithCharset( + awContents, onPageFinishedHelper, data, mimeType, isBase64Encoded, charset); + } + + /** + * Loads data on the UI thread but does not block. + */ + public void loadDataAsync(final AwContents awContents, final String data, final String mimeType, + final boolean isBase64Encoded) throws Exception { + mTestCommon.loadDataAsync(awContents, data, mimeType, isBase64Encoded); + } + + public void loadDataWithBaseUrlSync(final AwContents awContents, + CallbackHelper onPageFinishedHelper, final String data, final String mimeType, + final boolean isBase64Encoded, final String baseUrl, final String historyUrl) + throws Throwable { + mTestCommon.loadDataWithBaseUrlSync(awContents, onPageFinishedHelper, data, mimeType, + isBase64Encoded, baseUrl, historyUrl); + } + + public void loadDataWithBaseUrlAsync(final AwContents awContents, final String data, + final String mimeType, final boolean isBase64Encoded, final String baseUrl, + final String historyUrl) throws Throwable { + mTestCommon.loadDataWithBaseUrlAsync( + awContents, data, mimeType, isBase64Encoded, baseUrl, historyUrl); + } + + /** + * Reloads the current page synchronously. + */ + public void reloadSync(final AwContents awContents, CallbackHelper onPageFinishedHelper) + throws Exception { + mTestCommon.reloadSync(awContents, onPageFinishedHelper); + } + + /** + * Stops loading on the UI thread. + */ + public void stopLoading(final AwContents awContents) { + mTestCommon.stopLoading(awContents); + } + + public void waitForVisualStateCallback(final AwContents awContents) throws Exception { + mTestCommon.waitForVisualStateCallback(awContents); + } + + public void insertVisualStateCallbackOnUIThread(final AwContents awContents, + final long requestId, final AwContents.VisualStateCallback callback) { + mTestCommon.insertVisualStateCallbackOnUIThread(awContents, requestId, callback); + } + + // Waits for the pixel at the center of AwContents to color up into expectedColor. + // Note that this is a stricter condition that waiting for a visual state callback, + // as visual state callback only indicates that *something* has appeared in WebView. + public void waitForPixelColorAtCenterOfView(final AwContents awContents, + final AwTestContainerView testContainerView, final int expectedColor) throws Exception { + mTestCommon.waitForPixelColorAtCenterOfView(awContents, testContainerView, expectedColor); + } + + public AwTestContainerView createAwTestContainerView(final AwContentsClient awContentsClient) { + return mTestCommon.createAwTestContainerView(awContentsClient); + } + + public AwTestContainerView createAwTestContainerView(final AwContentsClient awContentsClient, + boolean supportsLegacyQuirks, final TestDependencyFactory testDependencyFactory) { + return mTestCommon.createAwTestContainerView( + awContentsClient, supportsLegacyQuirks, testDependencyFactory); + } + + public AwBrowserContext getAwBrowserContext() { + return mTestCommon.getAwBrowserContext(); + } + + public AwTestContainerView createDetachedAwTestContainerView( + final AwContentsClient awContentsClient) { + return mTestCommon.createDetachedAwTestContainerView(awContentsClient); + } + + public AwTestContainerView createDetachedAwTestContainerView( + final AwContentsClient awContentsClient, boolean supportsLegacyQuirks, + TestDependencyFactory testDependencyFactory) { + return mTestCommon.createDetachedAwTestContainerView( + awContentsClient, supportsLegacyQuirks, testDependencyFactory); + } + + protected boolean isHardwareAcceleratedTest() { + return mTestCommon.isHardwareAcceleratedTest(); + } + + public AwTestContainerView createAwTestContainerViewOnMainSync(final AwContentsClient client) + throws Exception { + return mTestCommon.createAwTestContainerViewOnMainSync(client); + } + + public AwTestContainerView createAwTestContainerViewOnMainSync( + final AwContentsClient client, final boolean supportsLegacyQuirks) { + return mTestCommon.createAwTestContainerViewOnMainSync(client, supportsLegacyQuirks); + } + + public AwTestContainerView createAwTestContainerViewOnMainSync(final AwContentsClient client, + final boolean supportsLegacyQuirks, final TestDependencyFactory testDependencyFactory) { + return mTestCommon.createAwTestContainerViewOnMainSync( + client, supportsLegacyQuirks, testDependencyFactory); + } + + public void destroyAwContentsOnMainSync(final AwContents awContents) { + mTestCommon.destroyAwContentsOnMainSync(awContents); + } + + public String getTitleOnUiThread(final AwContents awContents) throws Exception { + return mTestCommon.getTitleOnUiThread(awContents); + } + + public AwSettings getAwSettingsOnUiThread(final AwContents awContents) throws Exception { + return mTestCommon.getAwSettingsOnUiThread(awContents); + } + + /** + * Verify double quotes in both sides of the raw string. Strip the double quotes and + * returns rest of the string. + */ + protected String maybeStripDoubleQuotes(String raw) { + return mTestCommon.maybeStripDoubleQuotes(raw); + } + + /** + * Executes the given snippet of JavaScript code within the given ContentView. Returns the + * result of its execution in JSON format. + */ + public String executeJavaScriptAndWaitForResult(final AwContents awContents, + TestAwContentsClient viewClient, final String code) throws Exception { + return mTestCommon.executeJavaScriptAndWaitForResult(awContents, viewClient, code); + } + + /** + * Executes JavaScript code within the given ContentView to get the text content in + * document body. Returns the result string without double quotes. + */ + public String getJavaScriptResultBodyTextContent( + final AwContents awContents, final TestAwContentsClient viewClient) throws Exception { + return mTestCommon.getJavaScriptResultBodyTextContent(awContents, viewClient); + } + + /** + * Wrapper around CriteriaHelper.pollInstrumentationThread. This uses AwTestBase-specifc + * timeouts and treats timeouts and exceptions as test failures automatically. + */ + public static void pollInstrumentationThread(final Callable<Boolean> callable) + throws Exception { + AwTestCommon.pollInstrumentationThread(callable); + } + + /** + * Wrapper around {@link AwTestBase#poll()} but runs the callable on the UI thread. + */ + public void pollUiThread(final Callable<Boolean> callable) throws Exception { + mTestCommon.pollUiThread(callable); + } + + /** + * Clears the resource cache. Note that the cache is per-application, so this will clear the + * cache for all WebViews used. + */ + public void clearCacheOnUiThread(final AwContents awContents, final boolean includeDiskFiles) + throws Exception { + mTestCommon.clearCacheOnUiThread(awContents, includeDiskFiles); + } + + /** + * Returns pure page scale. + */ + public float getScaleOnUiThread(final AwContents awContents) throws Exception { + return mTestCommon.getScaleOnUiThread(awContents); + } + + /** + * Returns page scale multiplied by the screen density. + */ + public float getPixelScaleOnUiThread(final AwContents awContents) throws Exception { + return mTestCommon.getPixelScaleOnUiThread(awContents); + } + + /** + * Returns whether a user can zoom the page in. + */ + public boolean canZoomInOnUiThread(final AwContents awContents) throws Exception { + return mTestCommon.canZoomInOnUiThread(awContents); + } + + /** + * Returns whether a user can zoom the page out. + */ + public boolean canZoomOutOnUiThread(final AwContents awContents) throws Exception { + return mTestCommon.canZoomOutOnUiThread(awContents); + } + + public void killRenderProcessOnUiThreadAsync(final AwContents awContents) throws Exception { + mTestCommon.killRenderProcessOnUiThreadAsync(awContents); + } + + /** + * Loads the main html then triggers the popup window. + */ + public void triggerPopup(final AwContents parentAwContents, + TestAwContentsClient parentAwContentsClient, TestWebServer testWebServer, + String mainHtml, String popupHtml, String popupPath, String triggerScript) + throws Exception { + mTestCommon.triggerPopup(parentAwContents, parentAwContentsClient, testWebServer, mainHtml, + popupHtml, popupPath, triggerScript); + } + + /** + * Supplies the popup window with AwContents then waits for the popup window to finish loading. + */ + public PopupInfo connectPendingPopup(final AwContents parentAwContents) throws Exception { + return mTestCommon.connectPendingPopup(parentAwContents); + } + + @Override + public boolean testMethodHasAnnotation(Class<? extends Annotation> clazz) { + return mCurrentTestDescription.getAnnotation(clazz) != null ? true : false; + } + + @Override + public Instrumentation getInstrumentation() { + return InstrumentationRegistry.getInstrumentation(); + } +}
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldInterceptRequestTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldInterceptRequestTest.java index 5e3004e..f56533f1 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldInterceptRequestTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldInterceptRequestTest.java
@@ -214,7 +214,7 @@ mShouldInterceptRequestHelper.getRequestsForUrl(pageWithFormUrl).method); callCount = mShouldInterceptRequestHelper.getCallCount(); - JSUtils.clickOnLinkUsingJs(this, mAwContents, + JSUtils.clickOnLinkUsingJs(getInstrumentation(), mAwContents, mContentsClient.getOnEvaluateJavaScriptResultHelper(), "link"); mShouldInterceptRequestHelper.waitForCallback(callCount); assertEquals("POST",
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldOverrideUrlLoadingTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldOverrideUrlLoadingTest.java index c02be0dc..28090bd1 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldOverrideUrlLoadingTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientShouldOverrideUrlLoadingTest.java
@@ -78,7 +78,7 @@ private void clickOnLinkUsingJs() throws Throwable { enableJavaScriptOnUiThread(mAwContents); - JSUtils.clickOnLinkUsingJs(this, mAwContents, + JSUtils.clickOnLinkUsingJs(getInstrumentation(), mAwContents, mContentsClient.getOnEvaluateJavaScriptResultHelper(), "link"); } @@ -926,8 +926,9 @@ loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), urlWithLink); // Executing JS code that tries to navigate somewhere should not create an intent. - assertEquals("\"" + testUrl + "\"", JSUtils.executeJavaScriptAndWaitForResult( - this, mAwContents, new OnEvaluateJavaScriptResultHelper(), + assertEquals("\"" + testUrl + "\"", + JSUtils.executeJavaScriptAndWaitForResult(getInstrumentation(), mAwContents, + new OnEvaluateJavaScriptResultHelper(), "document.location.href='" + testUrl + "'")); assertNull(getActivity().getLastSentIntent());
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 cb5c93d..e0c4d29 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
@@ -42,7 +42,7 @@ } @Override - protected TestDependencyFactory createTestDependencyFactory() { + public TestDependencyFactory createTestDependencyFactory() { if (mOverridenFactory == null) { return new TestDependencyFactory(); } else {
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 ce37246..a787e7c 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
@@ -4,6 +4,8 @@ package org.chromium.android_webview.test; +import static org.chromium.android_webview.test.AwTestCommon.WAIT_TIMEOUT_MS; + import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -11,14 +13,19 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.support.test.InstrumentationRegistry; import android.support.test.filters.LargeTest; import android.support.test.filters.SmallTest; -import android.test.UiThreadTest; import android.util.Pair; import android.view.KeyEvent; import android.view.View; import android.webkit.JavascriptInterface; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + import org.chromium.android_webview.AwContents; import org.chromium.android_webview.AwSettings; import org.chromium.android_webview.AwSwitches; @@ -52,117 +59,141 @@ /** * AwContents tests. */ -public class AwContentsTest extends AwTestBase { +@RunWith(AwJUnit4ClassRunner.class) +public class AwContentsTest { + @Rule + public AwActivityTestRule mActivityTestRule = new AwActivityTestRule(); private TestAwContentsClient mContentsClient = new TestAwContentsClient(); + @Test @SmallTest @Feature({"AndroidWebView"}) - @UiThreadTest public void testCreateDestroy() throws Throwable { // NOTE this test runs on UI thread, so we cannot call any async methods. - createAwTestContainerView(mContentsClient).getAwContents().destroy(); + mActivityTestRule.runOnUiThread(new Runnable() { + @Override + public void run() { + mActivityTestRule.createAwTestContainerView(mContentsClient) + .getAwContents() + .destroy(); + } + }); } + @Test @SmallTest @Feature({"AndroidWebView"}) public void testCreateLoadPageDestroy() throws Throwable { AwTestContainerView awTestContainerView = - createAwTestContainerViewOnMainSync(mContentsClient); - loadDataSync(awTestContainerView.getAwContents(), mContentsClient.getOnPageFinishedHelper(), - CommonResources.ABOUT_HTML, "text/html", false); + mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient); + mActivityTestRule.loadDataSync(awTestContainerView.getAwContents(), + mContentsClient.getOnPageFinishedHelper(), CommonResources.ABOUT_HTML, "text/html", + false); - destroyAwContentsOnMainSync(awTestContainerView.getAwContents()); + mActivityTestRule.destroyAwContentsOnMainSync(awTestContainerView.getAwContents()); // It should be safe to call destroy multiple times. - destroyAwContentsOnMainSync(awTestContainerView.getAwContents()); + mActivityTestRule.destroyAwContentsOnMainSync(awTestContainerView.getAwContents()); } + @Test @LargeTest @Feature({"AndroidWebView"}) public void testCreateLoadDestroyManyTimes() throws Throwable { for (int i = 0; i < 10; ++i) { - AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient); + AwTestContainerView testView = + mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient); AwContents awContents = testView.getAwContents(); - loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), + mActivityTestRule.loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); - destroyAwContentsOnMainSync(awContents); + mActivityTestRule.destroyAwContentsOnMainSync(awContents); } } + @Test @LargeTest @Feature({"AndroidWebView"}) public void testCreateLoadDestroyManyAtOnce() throws Throwable { AwTestContainerView views[] = new AwTestContainerView[10]; for (int i = 0; i < views.length; ++i) { - views[i] = createAwTestContainerViewOnMainSync(mContentsClient); - loadUrlSync(views[i].getAwContents(), mContentsClient.getOnPageFinishedHelper(), + views[i] = mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient); + mActivityTestRule.loadUrlSync(views[i].getAwContents(), + mContentsClient.getOnPageFinishedHelper(), ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); } for (int i = 0; i < views.length; ++i) { - destroyAwContentsOnMainSync(views[i].getAwContents()); + mActivityTestRule.destroyAwContentsOnMainSync(views[i].getAwContents()); views[i] = null; } } + @Test @SmallTest @Feature({"AndroidWebView"}) - @UiThreadTest public void testWebViewApisFailGracefullyAfterDestruction() throws Throwable { - AwContents awContents = - createAwTestContainerView(mContentsClient).getAwContents(); - awContents.destroy(); + mActivityTestRule.runOnUiThread(new Runnable() { + @Override + public void run() { + AwContents awContents = mActivityTestRule.createAwTestContainerView(mContentsClient) + .getAwContents(); + awContents.destroy(); - // The documentation for WebView#destroy() reads "This method should be called - // after this WebView has been removed from the view system. No other methods - // may be called on this WebView after destroy". - // However, some apps do not respect that restriction so we need to ensure that - // we fail gracefully and do not crash when APIs are invoked after destruction. - // Due to the large number of APIs we only test a representative selection here. - awContents.clearHistory(); - awContents.loadUrl("http://www.google.com"); - awContents.findAllAsync("search"); - assertNull(awContents.getUrl()); - assertFalse(awContents.canGoBack()); - awContents.disableJavascriptInterfacesInspection(); - awContents.invokeZoomPicker(); - awContents.onResume(); - awContents.stopLoading(); - awContents.onWindowVisibilityChanged(View.VISIBLE); - awContents.requestFocus(); - awContents.isMultiTouchZoomSupported(); - awContents.setOverScrollMode(View.OVER_SCROLL_NEVER); - awContents.pauseTimers(); - awContents.onContainerViewScrollChanged(200, 200, 100, 100); - awContents.computeScroll(); - awContents.onMeasure(100, 100); - awContents.onDraw(new Canvas()); - awContents.getMostRecentProgress(); - assertEquals(0, awContents.computeHorizontalScrollOffset()); - assertEquals(0, awContents.getContentWidthCss()); - awContents.onKeyUp(KeyEvent.KEYCODE_BACK, - new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MENU)); + // The documentation for WebView#destroy() reads "This method should be called + // after this WebView has been removed from the view system. No other methods + // may be called on this WebView after destroy". + // However, some apps do not respect that restriction so we need to ensure that + // we fail gracefully and do not crash when APIs are invoked after destruction. + // Due to the large number of APIs we only test a representative selection here. + awContents.clearHistory(); + awContents.loadUrl("http://www.google.com"); + awContents.findAllAsync("search"); + Assert.assertNull(awContents.getUrl()); + Assert.assertFalse(awContents.canGoBack()); + awContents.disableJavascriptInterfacesInspection(); + awContents.invokeZoomPicker(); + awContents.onResume(); + awContents.stopLoading(); + awContents.onWindowVisibilityChanged(View.VISIBLE); + awContents.requestFocus(); + awContents.isMultiTouchZoomSupported(); + awContents.setOverScrollMode(View.OVER_SCROLL_NEVER); + awContents.pauseTimers(); + awContents.onContainerViewScrollChanged(200, 200, 100, 100); + awContents.computeScroll(); + awContents.onMeasure(100, 100); + awContents.onDraw(new Canvas()); + awContents.getMostRecentProgress(); + Assert.assertEquals(0, awContents.computeHorizontalScrollOffset()); + Assert.assertEquals(0, awContents.getContentWidthCss()); + awContents.onKeyUp(KeyEvent.KEYCODE_BACK, + new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MENU)); + } + }); } + @Test @SmallTest @Feature({"AndroidWebView"}) public void testUseAwSettingsAfterDestroy() throws Throwable { AwTestContainerView awTestContainerView = - createAwTestContainerViewOnMainSync(mContentsClient); - AwSettings awSettings = getAwSettingsOnUiThread(awTestContainerView.getAwContents()); - loadDataSync(awTestContainerView.getAwContents(), mContentsClient.getOnPageFinishedHelper(), - CommonResources.ABOUT_HTML, "text/html", false); - destroyAwContentsOnMainSync(awTestContainerView.getAwContents()); + mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient); + AwSettings awSettings = + mActivityTestRule.getAwSettingsOnUiThread(awTestContainerView.getAwContents()); + mActivityTestRule.loadDataSync(awTestContainerView.getAwContents(), + mContentsClient.getOnPageFinishedHelper(), CommonResources.ABOUT_HTML, "text/html", + false); + mActivityTestRule.destroyAwContentsOnMainSync(awTestContainerView.getAwContents()); // AwSettings should still be usable even after native side is destroyed. String newFontFamily = "serif"; awSettings.setStandardFontFamily(newFontFamily); - assertEquals(newFontFamily, awSettings.getStandardFontFamily()); + Assert.assertEquals(newFontFamily, awSettings.getStandardFontFamily()); boolean newBlockNetworkLoads = !awSettings.getBlockNetworkLoads(); awSettings.setBlockNetworkLoads(newBlockNetworkLoads); - assertEquals(newBlockNetworkLoads, awSettings.getBlockNetworkLoads()); + Assert.assertEquals(newBlockNetworkLoads, awSettings.getBlockNetworkLoads()); } private int callDocumentHasImagesSync(final AwContents awContents) @@ -178,21 +209,23 @@ s.release(); } }); - runTestOnUiThread(new Runnable() { + InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { @Override public void run() { awContents.documentHasImages(msg); } }); - assertTrue(s.tryAcquire(WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS)); + Assert.assertTrue(s.tryAcquire(AwActivityTestRule.WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS)); int result = val.get(); return result; } + @Test @SmallTest @Feature({"AndroidWebView"}) public void testDocumentHasImages() throws Throwable { - AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient); + AwTestContainerView testView = + mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient); AwContents awContents = testView.getAwContents(); final CallbackHelper loadHelper = mContentsClient.getOnPageFinishedHelper(); @@ -202,21 +235,22 @@ final String imageDoc = "<head/><body><img/><img/></body>"; // Make sure a document that does not have images returns 0 - loadDataSync(awContents, loadHelper, emptyDoc, mime, false); + mActivityTestRule.loadDataSync(awContents, loadHelper, emptyDoc, mime, false); int result = callDocumentHasImagesSync(awContents); - assertEquals(0, result); + Assert.assertEquals(0, result); // Make sure a document that does have images returns 1 - loadDataSync(awContents, loadHelper, imageDoc, mime, false); + mActivityTestRule.loadDataSync(awContents, loadHelper, imageDoc, mime, false); result = callDocumentHasImagesSync(awContents); - assertEquals(1, result); + Assert.assertEquals(1, result); } + @Test @SmallTest @Feature({"AndroidWebView"}) public void testClearCacheMemoryAndDisk() throws Throwable { final AwTestContainerView testContainer = - createAwTestContainerViewOnMainSync(mContentsClient); + mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient); final AwContents awContents = testContainer.getAwContents(); TestWebServer webServer = TestWebServer.start(); @@ -230,46 +264,44 @@ pagePath, "<html><body>foo</body></html>", headers); // First load to populate cache. - clearCacheOnUiThread(awContents, true); - loadUrlSync(awContents, - mContentsClient.getOnPageFinishedHelper(), - pageUrl); - assertEquals(1, webServer.getRequestCount(pagePath)); + mActivityTestRule.clearCacheOnUiThread(awContents, true); + mActivityTestRule.loadUrlSync( + awContents, mContentsClient.getOnPageFinishedHelper(), pageUrl); + Assert.assertEquals(1, webServer.getRequestCount(pagePath)); // Load about:blank so next load is not treated as reload by webkit and force // revalidate with the server. - loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), + mActivityTestRule.loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); // No clearCache call, so should be loaded from cache. - loadUrlSync(awContents, - mContentsClient.getOnPageFinishedHelper(), - pageUrl); - assertEquals(1, webServer.getRequestCount(pagePath)); + mActivityTestRule.loadUrlSync( + awContents, mContentsClient.getOnPageFinishedHelper(), pageUrl); + Assert.assertEquals(1, webServer.getRequestCount(pagePath)); // Same as above. - loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), + mActivityTestRule.loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); // Clear cache, so should hit server again. - clearCacheOnUiThread(awContents, true); - loadUrlSync(awContents, - mContentsClient.getOnPageFinishedHelper(), - pageUrl); - assertEquals(2, webServer.getRequestCount(pagePath)); + mActivityTestRule.clearCacheOnUiThread(awContents, true); + mActivityTestRule.loadUrlSync( + awContents, mContentsClient.getOnPageFinishedHelper(), pageUrl); + Assert.assertEquals(2, webServer.getRequestCount(pagePath)); } finally { webServer.shutdown(); } } + @Test @SmallTest @Feature({"AndroidWebView"}) public void testClearCacheInQuickSuccession() throws Throwable { final AwTestContainerView testContainer = - createAwTestContainerViewOnMainSync(new TestAwContentsClient()); + mActivityTestRule.createAwTestContainerViewOnMainSync(new TestAwContentsClient()); final AwContents awContents = testContainer.getAwContents(); - runTestOnUiThread(new Runnable() { + InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { @Override public void run() { for (int i = 0; i < 10; ++i) { @@ -279,11 +311,13 @@ }); } + @Test @SmallTest @Feature({"AndroidWebView"}) public void testGetFavicon() throws Throwable { AwContents.setShouldDownloadFavicons(); - final AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient); + final AwTestContainerView testView = + mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient); final AwContents awContents = testView.getAwContents(); TestWebServer webServer = TestWebServer.start(); @@ -298,10 +332,11 @@ // the page load completes which makes it slightly hard to test. final Bitmap defaultFavicon = awContents.getFavicon(); - getAwSettingsOnUiThread(awContents).setImagesEnabled(true); - loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), pageUrl); + mActivityTestRule.getAwSettingsOnUiThread(awContents).setImagesEnabled(true); + mActivityTestRule.loadUrlSync( + awContents, mContentsClient.getOnPageFinishedHelper(), pageUrl); - pollUiThread(new Callable<Boolean>() { + mActivityTestRule.pollUiThread(new Callable<Boolean>() { @Override public Boolean call() { return awContents.getFavicon() != null @@ -312,19 +347,21 @@ final Object originalFaviconSource = (new URL(faviconUrl)).getContent(); final Bitmap originalFavicon = BitmapFactory.decodeStream((InputStream) originalFaviconSource); - assertNotNull(originalFavicon); + Assert.assertNotNull(originalFavicon); - assertTrue(awContents.getFavicon().sameAs(originalFavicon)); + Assert.assertTrue(awContents.getFavicon().sameAs(originalFavicon)); } finally { webServer.shutdown(); } } + @Test @Feature({"AndroidWebView", "Downloads"}) @SmallTest public void testDownload() throws Throwable { - AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient); + AwTestContainerView testView = + mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient); AwContents awContents = testView.getAwContents(); final String data = "download data"; @@ -343,42 +380,47 @@ final OnDownloadStartHelper downloadStartHelper = mContentsClient.getOnDownloadStartHelper(); final int callCount = downloadStartHelper.getCallCount(); - loadUrlAsync(awContents, pageUrl); + mActivityTestRule.loadUrlAsync(awContents, pageUrl); downloadStartHelper.waitForCallback(callCount); - assertEquals(pageUrl, downloadStartHelper.getUrl()); - assertEquals(contentDisposition, downloadStartHelper.getContentDisposition()); - assertEquals(mimeType, downloadStartHelper.getMimeType()); - assertEquals(data.length(), downloadStartHelper.getContentLength()); + Assert.assertEquals(pageUrl, downloadStartHelper.getUrl()); + Assert.assertEquals(contentDisposition, downloadStartHelper.getContentDisposition()); + Assert.assertEquals(mimeType, downloadStartHelper.getMimeType()); + Assert.assertEquals(data.length(), downloadStartHelper.getContentLength()); } finally { webServer.shutdown(); } } + @Test @Feature({"AndroidWebView", "setNetworkAvailable"}) @SmallTest public void testSetNetworkAvailable() throws Throwable { - AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient); + AwTestContainerView testView = + mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient); AwContents awContents = testView.getAwContents(); String script = "navigator.onLine"; - enableJavaScriptOnUiThread(awContents); - loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), + mActivityTestRule.enableJavaScriptOnUiThread(awContents); + mActivityTestRule.loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); // Default to "online". - assertEquals("true", executeJavaScriptAndWaitForResult(awContents, mContentsClient, - script)); + Assert.assertEquals("true", + mActivityTestRule.executeJavaScriptAndWaitForResult( + awContents, mContentsClient, script)); // Forcing "offline". - setNetworkAvailableOnUiThread(awContents, false); - assertEquals("false", executeJavaScriptAndWaitForResult(awContents, mContentsClient, - script)); + mActivityTestRule.setNetworkAvailableOnUiThread(awContents, false); + Assert.assertEquals("false", + mActivityTestRule.executeJavaScriptAndWaitForResult( + awContents, mContentsClient, script)); // Forcing "online". - setNetworkAvailableOnUiThread(awContents, true); - assertEquals("true", executeJavaScriptAndWaitForResult(awContents, mContentsClient, - script)); + mActivityTestRule.setNetworkAvailableOnUiThread(awContents, true); + Assert.assertEquals("true", + mActivityTestRule.executeJavaScriptAndWaitForResult( + awContents, mContentsClient, script)); } @@ -394,13 +436,15 @@ } } + @Test @Feature({"AndroidWebView", "Android-JavaBridge"}) @SmallTest public void testJavaBridge() throws Throwable { - final AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient); + final AwTestContainerView testView = + mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient); final CallbackHelper callback = new CallbackHelper(); - runTestOnUiThread(new Runnable() { + InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { @Override public void run() { AwContents awContents = testView.getAwContents(); @@ -413,56 +457,64 @@ callback.waitForCallback(0, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); } + @Test @Feature({"AndroidWebView"}) @SmallTest public void testEscapingOfErrorPage() throws Throwable { - AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient); + AwTestContainerView testView = + mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient); AwContents awContents = testView.getAwContents(); String script = "window.failed == true"; - enableJavaScriptOnUiThread(awContents); + mActivityTestRule.enableJavaScriptOnUiThread(awContents); CallbackHelper onPageFinishedHelper = mContentsClient.getOnPageFinishedHelper(); int currentCallCount = onPageFinishedHelper.getCallCount(); - loadUrlAsync(awContents, + mActivityTestRule.loadUrlAsync(awContents, "file:///file-that-does-not-exist#<script>window.failed = true;</script>"); - onPageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_MS, - TimeUnit.MILLISECONDS); + onPageFinishedHelper.waitForCallback( + currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); - assertEquals("false", executeJavaScriptAndWaitForResult(awContents, mContentsClient, - script)); + Assert.assertEquals("false", + mActivityTestRule.executeJavaScriptAndWaitForResult( + awContents, mContentsClient, script)); } + @Test @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE") @Feature({"AndroidWebView"}) @SmallTest public void testCanInjectHeaders() throws Throwable { final AwTestContainerView testContainer = - createAwTestContainerViewOnMainSync(mContentsClient); + mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient); final AwContents awContents = testContainer.getAwContents(); - enableJavaScriptOnUiThread(awContents); + mActivityTestRule.enableJavaScriptOnUiThread(awContents); - EmbeddedTestServer testServer = - EmbeddedTestServer.createAndStartServer(getInstrumentation().getContext()); + EmbeddedTestServer testServer = EmbeddedTestServer.createAndStartServer( + InstrumentationRegistry.getInstrumentation().getContext()); try { String url = testServer.getURL("/echoheader?X-foo"); final Map<String, String> extraHeaders = new HashMap<String, String>(); extraHeaders.put("X-foo", "bar"); - loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), url, extraHeaders); + mActivityTestRule.loadUrlSync( + awContents, mContentsClient.getOnPageFinishedHelper(), url, extraHeaders); - String xfoo = getJavaScriptResultBodyTextContent(awContents, mContentsClient); - assertEquals("bar", xfoo); + String xfoo = mActivityTestRule.getJavaScriptResultBodyTextContent( + awContents, mContentsClient); + Assert.assertEquals("bar", xfoo); url = testServer.getURL("/echoheader?Referer"); extraHeaders.clear(); extraHeaders.put("Referer", "http://www.example.com/"); - loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), url, extraHeaders); + mActivityTestRule.loadUrlSync( + awContents, mContentsClient.getOnPageFinishedHelper(), url, extraHeaders); - String referer = getJavaScriptResultBodyTextContent(awContents, mContentsClient); - assertEquals("http://www.example.com/", referer); + String referer = mActivityTestRule.getJavaScriptResultBodyTextContent( + awContents, mContentsClient); + Assert.assertEquals("http://www.example.com/", referer); } finally { testServer.stopAndDestroyServer(); } @@ -471,17 +523,19 @@ // This is a meta test that we don't accidentally turn off hardware // acceleration in instrumentation tests without notice. Do not add the // @DisableHardwareAccelerationForTest annotation for this test. + @Test @Feature({"AndroidWebView"}) @SmallTest public void testHardwareModeWorks() throws Throwable { AwTestContainerView testContainer = - createAwTestContainerViewOnMainSync(mContentsClient); - assertTrue(testContainer.isHardwareAccelerated()); - assertTrue(testContainer.isBackedByHardwareView()); + mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient); + Assert.assertTrue(testContainer.isHardwareAccelerated()); + Assert.assertTrue(testContainer.isBackedByHardwareView()); } // TODO(hush): more ssl tests. And put the ssl tests into a separate test // class. + @Test @Feature({"AndroidWebView"}) @SmallTest // If the user allows the ssl error, the same ssl error will not trigger @@ -489,7 +543,7 @@ // error will still trigger the onReceivedSslError callback. public void testSslPreferences() throws Throwable { final AwTestContainerView testContainer = - createAwTestContainerViewOnMainSync(mContentsClient); + mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient); final AwContents awContents = testContainer.getAwContents(); TestWebServer webServer = TestWebServer.startSsl(); final String pagePath = "/hello.html"; @@ -499,54 +553,62 @@ mContentsClient.getOnReceivedSslErrorHelper(); int onSslErrorCallCount = onReceivedSslErrorHelper.getCallCount(); - loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), pageUrl); + mActivityTestRule.loadUrlSync( + awContents, mContentsClient.getOnPageFinishedHelper(), pageUrl); - assertEquals(onSslErrorCallCount + 1, onReceivedSslErrorHelper.getCallCount()); - assertEquals(1, webServer.getRequestCount(pagePath)); + Assert.assertEquals(onSslErrorCallCount + 1, onReceivedSslErrorHelper.getCallCount()); + Assert.assertEquals(1, webServer.getRequestCount(pagePath)); // Now load the page again. This time, we expect no ssl error, because // user's decision should be remembered. onSslErrorCallCount = onReceivedSslErrorHelper.getCallCount(); - loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), pageUrl); - assertEquals(onSslErrorCallCount, onReceivedSslErrorHelper.getCallCount()); + mActivityTestRule.loadUrlSync( + awContents, mContentsClient.getOnPageFinishedHelper(), pageUrl); + Assert.assertEquals(onSslErrorCallCount, onReceivedSslErrorHelper.getCallCount()); // Now clear the ssl preferences then load the same url again. Expect to see // onReceivedSslError getting called again. awContents.clearSslPreferences(); onSslErrorCallCount = onReceivedSslErrorHelper.getCallCount(); - loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), pageUrl); - assertEquals(onSslErrorCallCount + 1, onReceivedSslErrorHelper.getCallCount()); + mActivityTestRule.loadUrlSync( + awContents, mContentsClient.getOnPageFinishedHelper(), pageUrl); + Assert.assertEquals(onSslErrorCallCount + 1, onReceivedSslErrorHelper.getCallCount()); // Now clear the stored decisions and tell the client to deny ssl errors. awContents.clearSslPreferences(); mContentsClient.setAllowSslError(false); onSslErrorCallCount = onReceivedSslErrorHelper.getCallCount(); - loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), pageUrl); - assertEquals(onSslErrorCallCount + 1, onReceivedSslErrorHelper.getCallCount()); + mActivityTestRule.loadUrlSync( + awContents, mContentsClient.getOnPageFinishedHelper(), pageUrl); + Assert.assertEquals(onSslErrorCallCount + 1, onReceivedSslErrorHelper.getCallCount()); // Now load the same page again. This time, we still expect onReceivedSslError, // because we only remember user's decision if it is "allow". onSslErrorCallCount = onReceivedSslErrorHelper.getCallCount(); - loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), pageUrl); - assertEquals(onSslErrorCallCount + 1, onReceivedSslErrorHelper.getCallCount()); + mActivityTestRule.loadUrlSync( + awContents, mContentsClient.getOnPageFinishedHelper(), pageUrl); + Assert.assertEquals(onSslErrorCallCount + 1, onReceivedSslErrorHelper.getCallCount()); } /** * Verifies that Web Notifications and the Push API are not exposed in WebView. */ + @Test @Feature({"AndroidWebView"}) @SmallTest public void testPushAndNotificationsDisabled() throws Throwable { - AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient); + AwTestContainerView testView = + mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient); AwContents awContents = testView.getAwContents(); String script = "window.Notification || window.PushManager"; - enableJavaScriptOnUiThread(awContents); - loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), + mActivityTestRule.enableJavaScriptOnUiThread(awContents); + mActivityTestRule.loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); - assertEquals("null", executeJavaScriptAndWaitForResult(awContents, mContentsClient, - script)); + Assert.assertEquals("null", + mActivityTestRule.executeJavaScriptAndWaitForResult( + awContents, mContentsClient, script)); } private static class MockBindingManager implements BindingManager { @@ -573,8 +635,8 @@ } catch (InterruptedException e) { } } - assertTrue(mForegroundState.size() != 0); - assertEquals(inForeground, mForegroundState.get(0).booleanValue()); + Assert.assertTrue(mForegroundState.size() != 0); + Assert.assertEquals(inForeground, mForegroundState.get(0)); mForegroundState.remove(0); return; } @@ -612,6 +674,7 @@ /** * Verifies that a child process is actually gets created with WEBVIEW_SANDBOXED_RENDERER flag. */ + @Test @Feature({"AndroidWebView"}) @SmallTest @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER) @@ -619,21 +682,24 @@ public void testSandboxedRendererWorks() throws Throwable { MockBindingManager bindingManager = new MockBindingManager(); ChildProcessLauncherHelper.setBindingManagerForTesting(bindingManager); - assertFalse(bindingManager.isChildProcessCreated()); + Assert.assertFalse(bindingManager.isChildProcessCreated()); - AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient); + AwTestContainerView testView = + mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient); AwContents awContents = testView.getAwContents(); final String pageTitle = "I am sandboxed"; - loadDataSync(awContents, mContentsClient.getOnPageFinishedHelper(), + mActivityTestRule.loadDataSync(awContents, mContentsClient.getOnPageFinishedHelper(), "<html><head><title>" + pageTitle + "</title></head></html>", "text/html", false); - assertEquals(pageTitle, getTitleOnUiThread(awContents)); + Assert.assertEquals(pageTitle, mActivityTestRule.getTitleOnUiThread(awContents)); - assertTrue(bindingManager.isChildProcessCreated()); + Assert.assertTrue(bindingManager.isChildProcessCreated()); // Test end-to-end interaction with the renderer. - AwSettings awSettings = getAwSettingsOnUiThread(awContents); + AwSettings awSettings = mActivityTestRule.getAwSettingsOnUiThread(awContents); awSettings.setJavaScriptEnabled(true); - assertEquals("42", JSUtils.executeJavaScriptAndWaitForResult(this, awContents, + Assert.assertEquals("42", + JSUtils.executeJavaScriptAndWaitForResult( + InstrumentationRegistry.getInstrumentation(), awContents, mContentsClient.getOnEvaluateJavaScriptResultHelper(), "21 + 21")); } @@ -641,6 +707,7 @@ * By default the renderer should be considererd to be in the * foreground. */ + @Test @Feature({"AndroidWebView"}) @SmallTest @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER) @@ -648,14 +715,15 @@ public void testRendererPriorityStartsHigh() throws Throwable { MockBindingManager bindingManager = new MockBindingManager(); ChildProcessLauncherHelper.setBindingManagerForTesting(bindingManager); - assertFalse(bindingManager.isChildProcessCreated()); + Assert.assertFalse(bindingManager.isChildProcessCreated()); - AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient); + AwTestContainerView testView = + mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient); AwContents awContents = testView.getAwContents(); - loadDataSync(awContents, mContentsClient.getOnPageFinishedHelper(), "<html></html>", - "text/html", false); + mActivityTestRule.loadDataSync(awContents, mContentsClient.getOnPageFinishedHelper(), + "<html></html>", "text/html", false); - assertTrue(bindingManager.isChildProcessCreated()); + Assert.assertTrue(bindingManager.isChildProcessCreated()); bindingManager.assertSetInForegroundCall(true); } @@ -663,6 +731,7 @@ * If we specify that the priority is WAIVED, then the renderer * should not be in the foreground. */ + @Test @Feature({"AndroidWebView"}) @SmallTest @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER) @@ -670,21 +739,22 @@ public void testRendererPriorityLow() throws Throwable { MockBindingManager bindingManager = new MockBindingManager(); ChildProcessLauncherHelper.setBindingManagerForTesting(bindingManager); - assertFalse(bindingManager.isChildProcessCreated()); + Assert.assertFalse(bindingManager.isChildProcessCreated()); - final AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient); + final AwTestContainerView testView = + mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient); final AwContents awContents = testView.getAwContents(); - runTestOnUiThread(new Runnable() { + InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { @Override public void run() { awContents.setRendererPriorityPolicy(RendererPriority.WAIVED, false); } }); - loadDataSync(awContents, mContentsClient.getOnPageFinishedHelper(), "<html></html>", - "text/html", false); + mActivityTestRule.loadDataSync(awContents, mContentsClient.getOnPageFinishedHelper(), + "<html></html>", "text/html", false); - assertTrue(awContents.isPageVisible()); - assertTrue(bindingManager.isChildProcessCreated()); + Assert.assertTrue(awContents.isPageVisible()); + Assert.assertTrue(bindingManager.isChildProcessCreated()); bindingManager.assertSetInForegroundCall(false); } @@ -693,6 +763,7 @@ * background, then pausing the view should send the renderer to * the background. */ + @Test @Feature({"AndroidWebView"}) @SmallTest @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER) @@ -700,23 +771,24 @@ public void testRendererPriorityManaged() throws Throwable { MockBindingManager bindingManager = new MockBindingManager(); ChildProcessLauncherHelper.setBindingManagerForTesting(bindingManager); - assertFalse(bindingManager.isChildProcessCreated()); + Assert.assertFalse(bindingManager.isChildProcessCreated()); - final AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient); + final AwTestContainerView testView = + mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient); final AwContents awContents = testView.getAwContents(); - runTestOnUiThread(new Runnable() { + InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { @Override public void run() { awContents.setRendererPriorityPolicy(RendererPriority.HIGH, true); } }); - loadDataSync(awContents, mContentsClient.getOnPageFinishedHelper(), "<html></html>", - "text/html", false); + mActivityTestRule.loadDataSync(awContents, mContentsClient.getOnPageFinishedHelper(), + "<html></html>", "text/html", false); - assertTrue(awContents.isPageVisible()); - assertTrue(bindingManager.isChildProcessCreated()); + Assert.assertTrue(awContents.isPageVisible()); + Assert.assertTrue(bindingManager.isChildProcessCreated()); bindingManager.assertSetInForegroundCall(true); - runTestOnUiThread(new Runnable() { + InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { @Override public void run() { awContents.onPause(); @@ -725,30 +797,39 @@ bindingManager.assertSetInForegroundCall(false); } + @Test @Feature({"AndroidWebView"}) @SmallTest - @UiThreadTest @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER) @SkipCommandLineParameterization public void testPauseDestroyResume() throws Throwable { - AwContents awContents; - awContents = createAwTestContainerView(mContentsClient).getAwContents(); - awContents.pauseTimers(); - awContents.pauseTimers(); - awContents.destroy(); - awContents = createAwTestContainerView(mContentsClient).getAwContents(); - awContents.resumeTimers(); + mActivityTestRule.runOnUiThread(new Runnable() { + @Override + public void run() { + AwContents awContents; + awContents = mActivityTestRule.createAwTestContainerView(mContentsClient) + .getAwContents(); + awContents.pauseTimers(); + awContents.pauseTimers(); + awContents.destroy(); + awContents = mActivityTestRule.createAwTestContainerView(mContentsClient) + .getAwContents(); + awContents.resumeTimers(); + } + }); } /** Regression test for https://crbug.com/732976. Load a data URL, then immediately * after that load a javascript URL. The data URL navigation shouldn't be blocked. */ + @Test @LargeTest @Feature({"AndroidWebView"}) public void testJavaScriptUrlAfterLoadData() throws Throwable { - AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient); + AwTestContainerView testView = + mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient); final AwContents awContents = testView.getAwContents(); - getInstrumentation().runOnMainSync(new Runnable() { + mActivityTestRule.runOnUiThread(new Runnable() { @Override public void run() { // Run javascript navigation immediately, without waiting for the completion of data @@ -760,10 +841,10 @@ mContentsClient.getOnPageFinishedHelper().waitForCallback( 0, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); - assertEquals("data:text/html,<html>test</html>", awContents.getLastCommittedUrl()); + Assert.assertEquals("data:text/html,<html>test</html>", awContents.getLastCommittedUrl()); TestAwContentsClient.AddMessageToConsoleHelper consoleHelper = mContentsClient.getAddMessageToConsoleHelper(); - assertEquals(0, consoleHelper.getMessages().size()); + Assert.assertEquals(0, consoleHelper.getMessages().size()); } }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwSecondBrowserProcessTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwSecondBrowserProcessTest.java index 328b864..a864b82 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwSecondBrowserProcessTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwSecondBrowserProcessTest.java
@@ -31,7 +31,7 @@ private int mSecondBrowserServicePid; @Override - protected boolean needsBrowserProcessStarted() { + public boolean needsBrowserProcessStarted() { return false; }
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 eb19757..fd5db6f 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
@@ -2930,7 +2930,7 @@ } @Override - protected TestDependencyFactory createTestDependencyFactory() { + public TestDependencyFactory createTestDependencyFactory() { if (mOverridenFactory == null) { return new TestDependencyFactory(); } else { @@ -2960,12 +2960,12 @@ final AwTestContainerView mContainerView = createAwTestContainerViewOnMainSync(client); final AwContents awContents = mContainerView.getAwContents(); enableJavaScriptOnUiThread(awContents); - JSUtils.executeJavaScriptAndWaitForResult(this, awContents, + JSUtils.executeJavaScriptAndWaitForResult(getInstrumentation(), awContents, client.getOnEvaluateJavaScriptResultHelper(), "window.emptyDocumentPersistenceTest = true;"); loadUrlSync(awContents, client.getOnPageFinishedHelper(), ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); - String result = JSUtils.executeJavaScriptAndWaitForResult(this, awContents, + String result = JSUtils.executeJavaScriptAndWaitForResult(getInstrumentation(), awContents, client.getOnEvaluateJavaScriptResultHelper(), "window.emptyDocumentPersistenceTest ? 'set' : 'not set';"); assertEquals(allow ? "\"set\"" : "\"not set\"", result); @@ -3038,12 +3038,12 @@ awContents, client.getOnPageFinishedHelper(), testPageHtml, "text/html", false); // Focus on an empty DIV. - JSUtils.executeJavaScriptAndWaitForResult(this, awContents, + JSUtils.executeJavaScriptAndWaitForResult(getInstrumentation(), awContents, client.getOnEvaluateJavaScriptResultHelper(), "window.a.focus();"); assertEquals(1, getSelectionChangeCountForSelectionUpdateTest(awContents, client)); // Create and delete a zero-width space. See crbug.com/698752 for details. - JSUtils.executeJavaScriptAndWaitForResult(this, awContents, + JSUtils.executeJavaScriptAndWaitForResult(getInstrumentation(), awContents, client.getOnEvaluateJavaScriptResultHelper(), "(function() {" + "var sel = window.getSelection();" @@ -3075,16 +3075,16 @@ String expectedTitle = Integer.toString(mTitleIdx); // Since selectionchange event is posted on a message loop, we run another message loop // before we get the result. On Chromium both run on the same message loop. - JSUtils.executeJavaScriptAndWaitForResult(this, awContents, + JSUtils.executeJavaScriptAndWaitForResult(getInstrumentation(), awContents, client.getOnEvaluateJavaScriptResultHelper(), "setTimeout(function() { document.title = '" + expectedTitle + "'; });"); pollTitleAs(expectedTitle, awContents); - String result = JSUtils.executeJavaScriptAndWaitForResult( - this, awContents, client.getOnEvaluateJavaScriptResultHelper(), "window.cnt"); + String result = JSUtils.executeJavaScriptAndWaitForResult(getInstrumentation(), awContents, + client.getOnEvaluateJavaScriptResultHelper(), "window.cnt"); // Clean up - JSUtils.executeJavaScriptAndWaitForResult( - this, awContents, client.getOnEvaluateJavaScriptResultHelper(), "window.cnt = 0;"); + JSUtils.executeJavaScriptAndWaitForResult(getInstrumentation(), awContents, + client.getOnEvaluateJavaScriptResultHelper(), "window.cnt = 0;"); return Integer.parseInt(result); }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwStrictModeTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwStrictModeTest.java index 898d9eb..80f6261 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwStrictModeTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwStrictModeTest.java
@@ -33,13 +33,13 @@ } @Override - protected boolean needsAwBrowserContextCreated() { + public boolean needsAwBrowserContextCreated() { return false; } @Override - protected boolean needsBrowserProcessStarted() { + public boolean needsBrowserProcessStarted() { // Don't start the browser process in AwTestBase - we want to start it ourselves with // strictmode policies turned on. return false;
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java index f67a272..c39c643 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java
@@ -9,12 +9,9 @@ import android.app.Instrumentation; import android.content.Context; import android.os.Build; -import android.util.AndroidRuntimeException; -import android.util.Log; import android.view.ViewGroup; import org.chromium.android_webview.AwBrowserContext; -import org.chromium.android_webview.AwBrowserProcess; import org.chromium.android_webview.AwContents; import org.chromium.android_webview.AwContents.DependencyFactory; import org.chromium.android_webview.AwContents.InternalAccessDelegate; @@ -22,18 +19,13 @@ import org.chromium.android_webview.AwContentsClient; import org.chromium.android_webview.AwSettings; import org.chromium.android_webview.AwSwitches; -import org.chromium.android_webview.test.util.GraphicsTestUtils; -import org.chromium.android_webview.test.util.JSUtils; -import org.chromium.base.ThreadUtils; +import org.chromium.android_webview.test.AwTestCommon.AwTestCommonCallback; +import org.chromium.base.Log; import org.chromium.base.test.BaseActivityInstrumentationTestCase; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.InMemorySharedPreferences; import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.base.test.util.parameter.CommandLineParameter; -import org.chromium.content.browser.test.util.Criteria; -import org.chromium.content.browser.test.util.CriteriaHelper; -import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnPageFinishedHelper; -import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.net.test.util.TestWebServer; import java.lang.annotation.Annotation; @@ -41,94 +33,102 @@ import java.lang.reflect.Method; import java.util.Map; import java.util.concurrent.Callable; -import java.util.concurrent.FutureTask; -import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** - * A base class for android_webview tests. WebView only runs on KitKat and later, - * so make sure no one attempts to run the tests on earlier OS releases. - * - * By default, all tests run both in single-process mode, and with sandboxed renderer. - * If a test doesn't yet work with sandboxed renderer, an entire class, or an individual test - * method can be marked for single-process testing only by adding the following annotation: - * - * @SkipCommandLineParameterization + * A base class for android_webview tests. WebView only runs on KitKat and + * later, so make sure no one attempts to run the tests on earlier OS releases. + * By default, all tests run both in single-process mode, and with sandboxed + * renderer. If a test doesn't yet work with sandboxed renderer, an entire + * class, or an individual test method can be marked for single-process testing + * only by adding @SkipCommandLineParameterization to the test */ @MinAndroidSdkLevel(Build.VERSION_CODES.KITKAT) @CommandLineParameter({"", AwSwitches.WEBVIEW_SANDBOXED_RENDERER}) -public class AwTestBase extends BaseActivityInstrumentationTestCase<AwTestRunnerActivity> { - public static final long WAIT_TIMEOUT_MS = scaleTimeout(15000); - public static final int CHECK_INTERVAL = 100; +public class AwTestBase extends BaseActivityInstrumentationTestCase<AwTestRunnerActivity> + implements AwTestCommonCallback { private static final String TAG = "AwTestBase"; - private static final Pattern MAYBE_QUOTED_STRING = Pattern.compile("^(\"?)(.*)\\1$"); - // The browser context needs to be a process-wide singleton. - private AwBrowserContext mBrowserContext; + public static final long WAIT_TIMEOUT_MS = scaleTimeout(15000); + + public static final int CHECK_INTERVAL = 100; + + private final AwTestCommon mTestCommon; public AwTestBase() { super(AwTestRunnerActivity.class); + mTestCommon = new AwTestCommon(this); } @Override protected void setUp() throws Exception { - if (needsAwBrowserContextCreated()) { - createAwBrowserContext(); - } - - super.setUp(); - if (needsBrowserProcessStarted()) { - startBrowserProcess(); - } + mTestCommon.setUp(); } - protected void createAwBrowserContext() { - if (mBrowserContext != null) { - throw new AndroidRuntimeException("There should only be one browser context."); - } - getActivity(); // The Activity must be launched in order to load native code - final InMemorySharedPreferences prefs = new InMemorySharedPreferences(); - final Context appContext = getInstrumentation().getTargetContext().getApplicationContext(); - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - mBrowserContext = createAwBrowserContextOnUiThread(prefs, appContext); - } - }); - } - - protected AwBrowserContext createAwBrowserContextOnUiThread( + @Override + public AwBrowserContext createAwBrowserContextOnUiThread( InMemorySharedPreferences prefs, Context appContext) { return new AwBrowserContext(prefs, appContext); } + @Override + public TestDependencyFactory createTestDependencyFactory() { + return new TestDependencyFactory(); + } + + /** + * Override this to return false if the test doesn't want to create an + * AwBrowserContext automatically. + */ + @Override + public boolean needsAwBrowserContextCreated() { + return true; + } + + /** + * Override this to return false if the test doesn't want the browser + * startup sequence to be run automatically. + * + * @return Whether the instrumentation test requires the browser process to + * already be started. + */ + @Override + public boolean needsBrowserProcessStarted() { + return true; + } + + /** + * Checks the current test has |clazz| annotation. Note this swallows + * NoSuchMethodException and returns false in that case. + */ + @Override + public boolean testMethodHasAnnotation(Class<? extends Annotation> clazz) { + String testName = getName(); + Method method = null; + try { + method = getClass().getMethod(testName); + } catch (NoSuchMethodException e) { + Log.w(TAG, "Test method name not found.", e); + return false; + } + + // Cast to AnnotatedElement to work around a compilation failure. + // Method.isAnnotationPresent() was removed in Java 8 (which is used by + // the Android N SDK), + // so compilation with Java 7 fails. See crbug.com/608792. + return ((AnnotatedElement) method).isAnnotationPresent(clazz); + } + + @Override + public void runOnUiThread(Runnable runnable) { + getInstrumentation().runOnMainSync(runnable); + } + + protected void createAwBrowserContext() { + mTestCommon.createAwBrowserContext(); + } + protected void startBrowserProcess() throws Exception { - // The Activity must be launched in order for proper webview statics to be setup. - getActivity(); - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - AwBrowserProcess.start(); - } - }); - } - - /** - * Override this to return false if the test doesn't want to create an AwBrowserContext - * automatically. - */ - protected boolean needsAwBrowserContextCreated() { - return true; - } - - /** - * Override this to return false if the test doesn't want the browser startup sequence to - * be run automatically. - * @return Whether the instrumentation test requires the browser process to already be started. - */ - protected boolean needsBrowserProcessStarted() { - return true; + mTestCommon.startBrowserProcess(); } /** @@ -141,28 +141,16 @@ */ public <R> R runTestOnUiThreadAndGetResult(Callable<R> callable) throws Exception { - FutureTask<R> task = new FutureTask<R>(callable); - getInstrumentation().runOnMainSync(task); - return task.get(); + return mTestCommon.runTestOnUiThreadAndGetResult(callable); } public void enableJavaScriptOnUiThread(final AwContents awContents) { - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - awContents.getSettings().setJavaScriptEnabled(true); - } - }); + mTestCommon.enableJavaScriptOnUiThread(awContents); } public void setNetworkAvailableOnUiThread(final AwContents awContents, final boolean networkUp) { - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - awContents.setNetworkAvailable(networkUp); - } - }); + mTestCommon.setNetworkAvailableOnUiThread(awContents, networkUp); } /** @@ -171,30 +159,22 @@ public void loadUrlSync(final AwContents awContents, CallbackHelper onPageFinishedHelper, final String url) throws Exception { - loadUrlSync(awContents, onPageFinishedHelper, url, null); + mTestCommon.loadUrlSync(awContents, onPageFinishedHelper, url); } public void loadUrlSync(final AwContents awContents, CallbackHelper onPageFinishedHelper, final String url, final Map<String, String> extraHeaders) throws Exception { - int currentCallCount = onPageFinishedHelper.getCallCount(); - loadUrlAsync(awContents, url, extraHeaders); - onPageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_MS, - TimeUnit.MILLISECONDS); + mTestCommon.loadUrlSync(awContents, onPageFinishedHelper, url, extraHeaders); } public void loadUrlSyncAndExpectError(final AwContents awContents, CallbackHelper onPageFinishedHelper, CallbackHelper onReceivedErrorHelper, final String url) throws Exception { - int onErrorCallCount = onReceivedErrorHelper.getCallCount(); - int onFinishedCallCount = onPageFinishedHelper.getCallCount(); - loadUrlAsync(awContents, url); - onReceivedErrorHelper.waitForCallback(onErrorCallCount, 1, WAIT_TIMEOUT_MS, - TimeUnit.MILLISECONDS); - onPageFinishedHelper.waitForCallback(onFinishedCallCount, 1, WAIT_TIMEOUT_MS, - TimeUnit.MILLISECONDS); + mTestCommon.loadUrlSyncAndExpectError( + awContents, onPageFinishedHelper, onReceivedErrorHelper, url); } /** @@ -202,18 +182,13 @@ */ public void loadUrlAsync(final AwContents awContents, final String url) throws Exception { - loadUrlAsync(awContents, url, null); + mTestCommon.loadUrlAsync(awContents, url); } public void loadUrlAsync(final AwContents awContents, final String url, final Map<String, String> extraHeaders) { - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - awContents.loadUrl(url, extraHeaders); - } - }); + mTestCommon.loadUrlAsync(awContents, url, extraHeaders); } /** @@ -222,10 +197,7 @@ public void postUrlSync(final AwContents awContents, CallbackHelper onPageFinishedHelper, final String url, byte[] postData) throws Exception { - int currentCallCount = onPageFinishedHelper.getCallCount(); - postUrlAsync(awContents, url, postData); - onPageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_MS, - TimeUnit.MILLISECONDS); + mTestCommon.postUrlSync(awContents, onPageFinishedHelper, url, postData); } /** @@ -233,17 +205,7 @@ */ public void postUrlAsync(final AwContents awContents, final String url, byte[] postData) throws Exception { - class PostUrl implements Runnable { - byte[] mPostData; - public PostUrl(byte[] postData) { - mPostData = postData; - } - @Override - public void run() { - awContents.postUrl(url, mPostData); - } - } - getInstrumentation().runOnMainSync(new PostUrl(postData)); + mTestCommon.postUrlAsync(awContents, url, postData); } /** @@ -253,10 +215,7 @@ CallbackHelper onPageFinishedHelper, final String data, final String mimeType, final boolean isBase64Encoded) throws Exception { - int currentCallCount = onPageFinishedHelper.getCallCount(); - loadDataAsync(awContents, data, mimeType, isBase64Encoded); - onPageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_MS, - TimeUnit.MILLISECONDS); + mTestCommon.loadDataSync(awContents, onPageFinishedHelper, data, mimeType, isBase64Encoded); } public void loadDataSyncWithCharset(final AwContents awContents, @@ -264,16 +223,8 @@ final String data, final String mimeType, final boolean isBase64Encoded, final String charset) throws Exception { - int currentCallCount = onPageFinishedHelper.getCallCount(); - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - awContents.loadUrl(LoadUrlParams.createLoadDataParams( - data, mimeType, isBase64Encoded, charset)); - } - }); - onPageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_MS, - TimeUnit.MILLISECONDS); + mTestCommon.loadDataSyncWithCharset( + awContents, onPageFinishedHelper, data, mimeType, isBase64Encoded, charset); } /** @@ -282,34 +233,22 @@ public void loadDataAsync(final AwContents awContents, final String data, final String mimeType, final boolean isBase64Encoded) throws Exception { - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - awContents.loadData(data, mimeType, isBase64Encoded ? "base64" : null); - } - }); + mTestCommon.loadDataAsync(awContents, data, mimeType, isBase64Encoded); } public void loadDataWithBaseUrlSync(final AwContents awContents, CallbackHelper onPageFinishedHelper, final String data, final String mimeType, final boolean isBase64Encoded, final String baseUrl, final String historyUrl) throws Throwable { - int currentCallCount = onPageFinishedHelper.getCallCount(); - loadDataWithBaseUrlAsync(awContents, data, mimeType, isBase64Encoded, baseUrl, historyUrl); - onPageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_MS, - TimeUnit.MILLISECONDS); + mTestCommon.loadDataWithBaseUrlSync(awContents, onPageFinishedHelper, data, mimeType, + isBase64Encoded, baseUrl, historyUrl); } public void loadDataWithBaseUrlAsync(final AwContents awContents, final String data, final String mimeType, final boolean isBase64Encoded, final String baseUrl, final String historyUrl) throws Throwable { - runTestOnUiThread(new Runnable() { - @Override - public void run() { - awContents.loadDataWithBaseURL( - baseUrl, data, mimeType, isBase64Encoded ? "base64" : null, historyUrl); - } - }); + mTestCommon.loadDataWithBaseUrlAsync( + awContents, data, mimeType, isBase64Encoded, baseUrl, historyUrl); } /** @@ -317,104 +256,211 @@ */ public void reloadSync(final AwContents awContents, CallbackHelper onPageFinishedHelper) throws Exception { - int currentCallCount = onPageFinishedHelper.getCallCount(); - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - awContents.getNavigationController().reload(true); - } - }); - onPageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_MS, - TimeUnit.MILLISECONDS); + mTestCommon.reloadSync(awContents, onPageFinishedHelper); } /** * Stops loading on the UI thread. */ public void stopLoading(final AwContents awContents) { - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - awContents.stopLoading(); - } - }); + mTestCommon.stopLoading(awContents); } public void waitForVisualStateCallback(final AwContents awContents) throws Exception { - final CallbackHelper ch = new CallbackHelper(); - final int chCount = ch.getCallCount(); - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - final long requestId = 666; - awContents.insertVisualStateCallback(requestId, - new AwContents.VisualStateCallback() { - @Override - public void onComplete(long id) { - assertEquals(requestId, id); - ch.notifyCalled(); - } - }); - } - }); - ch.waitForCallback(chCount); + mTestCommon.waitForVisualStateCallback(awContents); } public void insertVisualStateCallbackOnUIThread(final AwContents awContents, final long requestId, final AwContents.VisualStateCallback callback) { - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - awContents.insertVisualStateCallback(requestId, callback); - } - }); + mTestCommon.insertVisualStateCallbackOnUIThread(awContents, requestId, callback); } - // Waits for the pixel at the center of AwContents to color up into expectedColor. - // Note that this is a stricter condition that waiting for a visual state callback, - // as visual state callback only indicates that *something* has appeared in WebView. + // Waits for the pixel at the center of AwContents to color up into + // expectedColor. + // Note that this is a stricter condition that waiting for a visual state + // callback, + // as visual state callback only indicates that *something* has appeared in + // WebView. public void waitForPixelColorAtCenterOfView(final AwContents awContents, final AwTestContainerView testContainerView, final int expectedColor) throws Exception { - pollUiThread(new Callable<Boolean>() { - @Override - public Boolean call() throws Exception { - return GraphicsTestUtils.getPixelColorAtCenterOfView(awContents, testContainerView) - == expectedColor; - } - }); + mTestCommon.waitForPixelColorAtCenterOfView(awContents, testContainerView, expectedColor); + } + + public AwTestContainerView createAwTestContainerView( + final AwContentsClient awContentsClient) { + return mTestCommon.createAwTestContainerView(awContentsClient); + } + + public AwTestContainerView createAwTestContainerView(final AwContentsClient awContentsClient, + boolean supportsLegacyQuirks, final TestDependencyFactory testDependencyFactory) { + return mTestCommon.createAwTestContainerView( + awContentsClient, supportsLegacyQuirks, testDependencyFactory); + } + + public AwBrowserContext getAwBrowserContext() { + return mTestCommon.getAwBrowserContext(); + } + + public AwTestContainerView createDetachedAwTestContainerView( + final AwContentsClient awContentsClient) { + return mTestCommon.createDetachedAwTestContainerView(awContentsClient); + } + + public AwTestContainerView createDetachedAwTestContainerView( + final AwContentsClient awContentsClient, boolean supportsLegacyQuirks, + TestDependencyFactory testDependencyFactory) { + return mTestCommon.createDetachedAwTestContainerView( + awContentsClient, supportsLegacyQuirks, testDependencyFactory); + } + + protected boolean isHardwareAcceleratedTest() { + return mTestCommon.isHardwareAcceleratedTest(); + } + + public AwTestContainerView createAwTestContainerViewOnMainSync( + final AwContentsClient client) throws Exception { + return mTestCommon.createAwTestContainerViewOnMainSync(client); + } + + public AwTestContainerView createAwTestContainerViewOnMainSync( + final AwContentsClient client, final boolean supportsLegacyQuirks) { + return mTestCommon.createAwTestContainerViewOnMainSync(client, supportsLegacyQuirks); + } + + public AwTestContainerView createAwTestContainerViewOnMainSync(final AwContentsClient client, + final boolean supportsLegacyQuirks, final TestDependencyFactory testDependencyFactory) { + return mTestCommon.createAwTestContainerViewOnMainSync( + client, supportsLegacyQuirks, testDependencyFactory); + } + + public void destroyAwContentsOnMainSync(final AwContents awContents) { + mTestCommon.destroyAwContentsOnMainSync(awContents); + } + + public String getTitleOnUiThread(final AwContents awContents) throws Exception { + return mTestCommon.getTitleOnUiThread(awContents); + } + + public AwSettings getAwSettingsOnUiThread( + final AwContents awContents) throws Exception { + return mTestCommon.getAwSettingsOnUiThread(awContents); } /** - * Checks the current test has |clazz| annotation. Note this swallows NoSuchMethodException - * and returns false in that case. + * Verify double quotes in both sides of the raw string. Strip the double + * quotes and returns rest of the string. */ - private boolean testMethodHasAnnotation(Class<? extends Annotation> clazz) { - String testName = getName(); - Method method = null; - try { - method = getClass().getMethod(testName); - } catch (NoSuchMethodException e) { - Log.w(TAG, "Test method name not found.", e); - return false; - } - - // Cast to AnnotatedElement to work around a compilation failure. - // Method.isAnnotationPresent() was removed in Java 8 (which is used by the Android N SDK), - // so compilation with Java 7 fails. See crbug.com/608792. - return ((AnnotatedElement) method).isAnnotationPresent(clazz); + protected String maybeStripDoubleQuotes(String raw) { + return mTestCommon.maybeStripDoubleQuotes(raw); } /** - * Factory class used in creation of test AwContents instances. - * - * Test cases can provide subclass instances to the createAwTest* methods in order to create an - * AwContents instance with injected test dependencies. + * Executes the given snippet of JavaScript code within the given + * ContentView. Returns the result of its execution in JSON format. + */ + public String executeJavaScriptAndWaitForResult(final AwContents awContents, + TestAwContentsClient viewClient, final String code) throws Exception { + return mTestCommon.executeJavaScriptAndWaitForResult(awContents, viewClient, code); + } + + /** + * Executes JavaScript code within the given ContentView to get the text content in + * document body. Returns the result string without double quotes. + */ + protected String getJavaScriptResultBodyTextContent( + final AwContents awContents, final TestAwContentsClient viewClient) throws Exception { + return mTestCommon.getJavaScriptResultBodyTextContent(awContents, viewClient); + } + + /** + * Wrapper around CriteriaHelper.pollInstrumentationThread. This uses AwTestBase-specifc + * timeouts and treats timeouts and exceptions as test failures automatically. + */ + public static void pollInstrumentationThread(final Callable<Boolean> callable) + throws Exception { + AwTestCommon.pollInstrumentationThread(callable); + } + + /** + * Wrapper around {@link AwTestBase#poll()} but runs the callable on the UI + * thread. + */ + public void pollUiThread(final Callable<Boolean> callable) throws Exception { + mTestCommon.pollUiThread(callable); + } + + /** + * Clears the resource cache. Note that the cache is per-application, so + * this will clear the cache for all WebViews used. + */ + public void clearCacheOnUiThread( + final AwContents awContents, + final boolean includeDiskFiles) throws Exception { + mTestCommon.clearCacheOnUiThread(awContents, includeDiskFiles); + } + + /** + * Returns pure page scale. + */ + public float getScaleOnUiThread(final AwContents awContents) throws Exception { + return mTestCommon.getScaleOnUiThread(awContents); + } + + /** + * Returns page scale multiplied by the screen density. + */ + public float getPixelScaleOnUiThread(final AwContents awContents) throws Exception { + return mTestCommon.getPixelScaleOnUiThread(awContents); + } + + /** + * Returns whether a user can zoom the page in. + */ + public boolean canZoomInOnUiThread(final AwContents awContents) throws Exception { + return mTestCommon.canZoomInOnUiThread(awContents); + } + + /** + * Returns whether a user can zoom the page out. + */ + public boolean canZoomOutOnUiThread(final AwContents awContents) throws Exception { + return mTestCommon.canZoomOutOnUiThread(awContents); + } + + public void killRenderProcessOnUiThreadAsync(final AwContents awContents) throws Exception { + mTestCommon.killRenderProcessOnUiThreadAsync(awContents); + } + + /** + * Loads the main html then triggers the popup window. + */ + public void triggerPopup(final AwContents parentAwContents, + TestAwContentsClient parentAwContentsClient, TestWebServer testWebServer, + String mainHtml, String popupHtml, String popupPath, String triggerScript) + throws Exception { + mTestCommon.triggerPopup(parentAwContents, parentAwContentsClient, testWebServer, mainHtml, + popupHtml, popupPath, triggerScript); + } + + /** + * Supplies the popup window with AwContents then waits for the popup window + * to finish loading. + */ + public PopupInfo connectPendingPopup(final AwContents parentAwContents) throws Exception { + return mTestCommon.connectPendingPopup(parentAwContents); + } + + /** + * Factory class used in creation of test AwContents instances. Test cases + * can provide subclass instances to the createAwTest* methods in order to + * create an AwContents instance with injected test dependencies. */ public static class TestDependencyFactory extends AwContents.DependencyFactory { - public AwTestContainerView createAwTestContainerView(AwTestRunnerActivity activity, - boolean allowHardwareAcceleration) { + public AwTestContainerView createAwTestContainerView( + AwTestRunnerActivity activity, boolean allowHardwareAcceleration) { return new AwTestContainerView(activity, allowHardwareAcceleration); } + public AwSettings createAwSettings(Context context, boolean supportsLegacyQuirks) { return new AwSettings(context, false /* isAccessFromFileURLsGrantedByDefault */, supportsLegacyQuirks, false /* allowEmptyDocumentPersistence */, @@ -432,279 +478,6 @@ } } - protected TestDependencyFactory createTestDependencyFactory() { - return new TestDependencyFactory(); - } - - public AwTestContainerView createAwTestContainerView( - final AwContentsClient awContentsClient) { - return createAwTestContainerView(awContentsClient, false, null); - } - - public AwTestContainerView createAwTestContainerView(final AwContentsClient awContentsClient, - boolean supportsLegacyQuirks, final TestDependencyFactory testDependencyFactory) { - AwTestContainerView testContainerView = createDetachedAwTestContainerView( - awContentsClient, supportsLegacyQuirks, testDependencyFactory); - getActivity().addView(testContainerView); - testContainerView.requestFocus(); - return testContainerView; - } - - public AwBrowserContext getAwBrowserContext() { - return mBrowserContext; - } - - public AwTestContainerView createDetachedAwTestContainerView( - final AwContentsClient awContentsClient) { - return createDetachedAwTestContainerView(awContentsClient, false, null); - } - - public AwTestContainerView createDetachedAwTestContainerView( - final AwContentsClient awContentsClient, boolean supportsLegacyQuirks, - TestDependencyFactory testDependencyFactory) { - if (testDependencyFactory == null) { - testDependencyFactory = createTestDependencyFactory(); - } - boolean allowHardwareAcceleration = isHardwareAcceleratedTest(); - final AwTestContainerView testContainerView = - testDependencyFactory.createAwTestContainerView( - getActivity(), allowHardwareAcceleration); - - AwSettings awSettings = - testDependencyFactory.createAwSettings(getActivity(), supportsLegacyQuirks); - AwContents awContents = testDependencyFactory.createAwContents(mBrowserContext, - testContainerView, testContainerView.getContext(), - testContainerView.getInternalAccessDelegate(), - testContainerView.getNativeDrawGLFunctorFactory(), awContentsClient, awSettings, - testDependencyFactory); - testContainerView.initialize(awContents); - return testContainerView; - } - - protected boolean isHardwareAcceleratedTest() { - return !testMethodHasAnnotation(DisableHardwareAccelerationForTest.class); - } - - public AwTestContainerView createAwTestContainerViewOnMainSync( - final AwContentsClient client) throws Exception { - return createAwTestContainerViewOnMainSync(client, false, null); - } - - public AwTestContainerView createAwTestContainerViewOnMainSync( - final AwContentsClient client, final boolean supportsLegacyQuirks) { - return createAwTestContainerViewOnMainSync(client, supportsLegacyQuirks, null); - } - - public AwTestContainerView createAwTestContainerViewOnMainSync(final AwContentsClient client, - final boolean supportsLegacyQuirks, final TestDependencyFactory testDependencyFactory) { - return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<AwTestContainerView>() { - @Override - public AwTestContainerView call() { - return createAwTestContainerView( - client, supportsLegacyQuirks, testDependencyFactory); - } - }); - } - - public void destroyAwContentsOnMainSync(final AwContents awContents) { - if (awContents == null) return; - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - awContents.destroy(); - } - }); - } - - public String getTitleOnUiThread(final AwContents awContents) throws Exception { - return runTestOnUiThreadAndGetResult(new Callable<String>() { - @Override - public String call() throws Exception { - return awContents.getTitle(); - } - }); - } - - public AwSettings getAwSettingsOnUiThread( - final AwContents awContents) throws Exception { - return runTestOnUiThreadAndGetResult(new Callable<AwSettings>() { - @Override - public AwSettings call() throws Exception { - return awContents.getSettings(); - } - }); - } - - /** - * Verify double quotes in both sides of the raw string. Strip the double quotes and - * returns rest of the string. - */ - protected String maybeStripDoubleQuotes(String raw) { - assertNotNull(raw); - Matcher m = MAYBE_QUOTED_STRING.matcher(raw); - assertTrue(m.matches()); - return m.group(2); - } - - /** - * Executes the given snippet of JavaScript code within the given ContentView. Returns the - * result of its execution in JSON format. - */ - public String executeJavaScriptAndWaitForResult(final AwContents awContents, - TestAwContentsClient viewClient, final String code) throws Exception { - return JSUtils.executeJavaScriptAndWaitForResult(this, awContents, - viewClient.getOnEvaluateJavaScriptResultHelper(), - code); - } - - /** - * Executes JavaScript code within the given ContentView to get the text content in - * document body. Returns the result string without double quotes. - */ - protected String getJavaScriptResultBodyTextContent( - final AwContents awContents, final TestAwContentsClient viewClient) throws Exception { - String raw = executeJavaScriptAndWaitForResult( - awContents, viewClient, "document.body.textContent"); - return maybeStripDoubleQuotes(raw); - } - - /** - * Wrapper around CriteriaHelper.pollInstrumentationThread. This uses AwTestBase-specifc - * timeouts and treats timeouts and exceptions as test failures automatically. - */ - public static void pollInstrumentationThread(final Callable<Boolean> callable) - throws Exception { - CriteriaHelper.pollInstrumentationThread(new Criteria() { - @Override - public boolean isSatisfied() { - try { - return callable.call(); - } catch (Throwable e) { - Log.e(TAG, "Exception while polling.", e); - return false; - } - } - }, WAIT_TIMEOUT_MS, CHECK_INTERVAL); - } - - /** - * Wrapper around {@link AwTestBase#poll()} but runs the callable on the UI thread. - */ - public void pollUiThread(final Callable<Boolean> callable) throws Exception { - pollInstrumentationThread(new Callable<Boolean>() { - @Override - public Boolean call() throws Exception { - return runTestOnUiThreadAndGetResult(callable); - } - }); - } - - /** - * Clears the resource cache. Note that the cache is per-application, so this will clear the - * cache for all WebViews used. - */ - public void clearCacheOnUiThread( - final AwContents awContents, - final boolean includeDiskFiles) throws Exception { - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - awContents.clearCache(includeDiskFiles); - } - }); - } - - /** - * Returns pure page scale. - */ - public float getScaleOnUiThread(final AwContents awContents) throws Exception { - return runTestOnUiThreadAndGetResult(new Callable<Float>() { - @Override - public Float call() throws Exception { - return awContents.getPageScaleFactor(); - } - }); - } - - /** - * Returns page scale multiplied by the screen density. - */ - public float getPixelScaleOnUiThread(final AwContents awContents) throws Exception { - return runTestOnUiThreadAndGetResult(new Callable<Float>() { - @Override - public Float call() throws Exception { - return awContents.getScale(); - } - }); - } - - /** - * Returns whether a user can zoom the page in. - */ - public boolean canZoomInOnUiThread(final AwContents awContents) throws Exception { - return runTestOnUiThreadAndGetResult(new Callable<Boolean>() { - @Override - public Boolean call() throws Exception { - return awContents.canZoomIn(); - } - }); - } - - /** - * Returns whether a user can zoom the page out. - */ - public boolean canZoomOutOnUiThread(final AwContents awContents) throws Exception { - return runTestOnUiThreadAndGetResult(new Callable<Boolean>() { - @Override - public Boolean call() throws Exception { - return awContents.canZoomOut(); - } - }); - } - - public void killRenderProcessOnUiThreadAsync(final AwContents awContents) throws Exception { - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - awContents.killRenderProcess(); - } - }); - } - - /** - * Loads the main html then triggers the popup window. - */ - public void triggerPopup(final AwContents parentAwContents, - TestAwContentsClient parentAwContentsClient, TestWebServer testWebServer, - String mainHtml, String popupHtml, String popupPath, String triggerScript) - throws Exception { - enableJavaScriptOnUiThread(parentAwContents); - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - parentAwContents.getSettings().setSupportMultipleWindows(true); - parentAwContents.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); - } - }); - - final String parentUrl = testWebServer.setResponse("/popupParent.html", mainHtml, null); - if (popupHtml != null) { - testWebServer.setResponse(popupPath, popupHtml, null); - } else { - testWebServer.setResponseWithNoContentStatus(popupPath); - } - - parentAwContentsClient.getOnCreateWindowHelper().setReturnValue(true); - loadUrlSync(parentAwContents, parentAwContentsClient.getOnPageFinishedHelper(), parentUrl); - - TestAwContentsClient.OnCreateWindowHelper onCreateWindowHelper = - parentAwContentsClient.getOnCreateWindowHelper(); - int currentCallCount = onCreateWindowHelper.getCallCount(); - parentAwContents.evaluateJavaScriptForTests(triggerScript, null); - onCreateWindowHelper.waitForCallback( - currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); - } - /** * POD object for holding references to helper objects of a popup window. */ @@ -712,6 +485,7 @@ public final TestAwContentsClient popupContentsClient; public final AwTestContainerView popupContainerView; public final AwContents popupContents; + public PopupInfo(TestAwContentsClient popupContentsClient, AwTestContainerView popupContainerView, AwContents popupContents) { this.popupContentsClient = popupContentsClient; @@ -719,37 +493,4 @@ this.popupContents = popupContents; } } - - /** - * Supplies the popup window with AwContents then waits for the popup window to finish loading. - */ - public PopupInfo connectPendingPopup(final AwContents parentAwContents) throws Exception { - TestAwContentsClient popupContentsClient; - AwTestContainerView popupContainerView; - final AwContents popupContents; - popupContentsClient = new TestAwContentsClient(); - popupContainerView = createAwTestContainerViewOnMainSync(popupContentsClient); - popupContents = popupContainerView.getAwContents(); - enableJavaScriptOnUiThread(popupContents); - - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - parentAwContents.supplyContentsForPopup(popupContents); - } - }); - - OnPageFinishedHelper onPageFinishedHelper = popupContentsClient.getOnPageFinishedHelper(); - int finishCallCount = onPageFinishedHelper.getCallCount(); - TestAwContentsClient.OnReceivedTitleHelper onReceivedTitleHelper = - popupContentsClient.getOnReceivedTitleHelper(); - int titleCallCount = onReceivedTitleHelper.getCallCount(); - - onPageFinishedHelper.waitForCallback(finishCallCount, 1, WAIT_TIMEOUT_MS, - TimeUnit.MILLISECONDS); - onReceivedTitleHelper.waitForCallback(titleCallCount, 1, WAIT_TIMEOUT_MS, - TimeUnit.MILLISECONDS); - - return new PopupInfo(popupContentsClient, popupContainerView, popupContents); - } }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwTestCommon.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwTestCommon.java new file mode 100644 index 0000000..5ea6498 --- /dev/null +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwTestCommon.java
@@ -0,0 +1,570 @@ +// 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. + +package org.chromium.android_webview.test; + +import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout; + +import android.app.Instrumentation; +import android.content.Context; +import android.util.AndroidRuntimeException; + +import org.junit.Assert; + +import org.chromium.android_webview.AwBrowserContext; +import org.chromium.android_webview.AwBrowserProcess; +import org.chromium.android_webview.AwContents; +import org.chromium.android_webview.AwContentsClient; +import org.chromium.android_webview.AwSettings; +import org.chromium.android_webview.test.AwTestBase.PopupInfo; +import org.chromium.android_webview.test.AwTestBase.TestDependencyFactory; +import org.chromium.android_webview.test.util.GraphicsTestUtils; +import org.chromium.android_webview.test.util.JSUtils; +import org.chromium.base.Log; +import org.chromium.base.ThreadUtils; +import org.chromium.base.test.util.CallbackHelper; +import org.chromium.base.test.util.InMemorySharedPreferences; +import org.chromium.content.browser.test.util.Criteria; +import org.chromium.content.browser.test.util.CriteriaHelper; +import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnPageFinishedHelper; +import org.chromium.content_public.browser.LoadUrlParams; +import org.chromium.net.test.util.TestWebServer; + +import java.lang.annotation.Annotation; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +// TODO(yolandyan): move this class to its test rule once JUnit4 migration is over +final class AwTestCommon { + static final long WAIT_TIMEOUT_MS = scaleTimeout(15000); + + static final int CHECK_INTERVAL = 100; + + private static final String TAG = "AwTestCommon"; + + private static final Pattern MAYBE_QUOTED_STRING = Pattern.compile("^(\"?)(.*)\\1$"); + + // The browser context needs to be a process-wide singleton. + private AwBrowserContext mBrowserContext; + + private final AwTestCommonCallback mCallback; + + AwTestCommon(AwTestCommonCallback callback) { + mCallback = callback; + } + + void setUp() throws Exception { + if (mCallback.needsAwBrowserContextCreated()) { + createAwBrowserContext(); + } + if (mCallback.needsBrowserProcessStarted()) { + startBrowserProcess(); + } + } + + void createAwBrowserContext() { + if (mBrowserContext != null) { + throw new AndroidRuntimeException("There should only be one browser context."); + } + mCallback.getActivity(); // The Activity must be launched in order to load native code + final InMemorySharedPreferences prefs = new InMemorySharedPreferences(); + final Context appContext = + mCallback.getInstrumentation().getTargetContext().getApplicationContext(); + mCallback.getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + mBrowserContext = + mCallback.createAwBrowserContextOnUiThread(prefs, appContext); + } + }); + } + + void startBrowserProcess() throws Exception { + // The Activity must be launched in order for proper webview statics to be setup. + mCallback.getActivity(); + mCallback.getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + AwBrowserProcess.start(); + } + }); + } + + <R> R runTestOnUiThreadAndGetResult(Callable<R> callable) throws Exception { + FutureTask<R> task = new FutureTask<R>(callable); + mCallback.getInstrumentation().runOnMainSync(task); + return task.get(); + } + + void enableJavaScriptOnUiThread(final AwContents awContents) { + mCallback.getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + awContents.getSettings().setJavaScriptEnabled(true); + } + }); + } + + void setNetworkAvailableOnUiThread(final AwContents awContents, final boolean networkUp) { + mCallback.getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + awContents.setNetworkAvailable(networkUp); + } + }); + } + + void loadUrlSync(final AwContents awContents, CallbackHelper onPageFinishedHelper, + final String url) throws Exception { + loadUrlSync(awContents, onPageFinishedHelper, url, null); + } + + void loadUrlSync(final AwContents awContents, CallbackHelper onPageFinishedHelper, + final String url, final Map<String, String> extraHeaders) throws Exception { + int currentCallCount = onPageFinishedHelper.getCallCount(); + loadUrlAsync(awContents, url, extraHeaders); + onPageFinishedHelper.waitForCallback( + currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); + } + + void loadUrlSyncAndExpectError(final AwContents awContents, CallbackHelper onPageFinishedHelper, + CallbackHelper onReceivedErrorHelper, final String url) throws Exception { + int onErrorCallCount = onReceivedErrorHelper.getCallCount(); + int onFinishedCallCount = onPageFinishedHelper.getCallCount(); + loadUrlAsync(awContents, url); + onReceivedErrorHelper.waitForCallback( + onErrorCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); + onPageFinishedHelper.waitForCallback( + onFinishedCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); + } + + void loadUrlAsync(final AwContents awContents, final String url) throws Exception { + loadUrlAsync(awContents, url, null); + } + + void loadUrlAsync( + final AwContents awContents, final String url, final Map<String, String> extraHeaders) { + mCallback.getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + awContents.loadUrl(url, extraHeaders); + } + }); + } + + void postUrlSync(final AwContents awContents, CallbackHelper onPageFinishedHelper, + final String url, byte[] postData) throws Exception { + int currentCallCount = onPageFinishedHelper.getCallCount(); + postUrlAsync(awContents, url, postData); + onPageFinishedHelper.waitForCallback( + currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); + } + + void postUrlAsync(final AwContents awContents, final String url, byte[] postData) + throws Exception { + class PostUrl implements Runnable { + byte[] mPostData; + public PostUrl(byte[] postData) { + mPostData = postData; + } + @Override + public void run() { + awContents.postUrl(url, mPostData); + } + } + mCallback.getInstrumentation().runOnMainSync(new PostUrl(postData)); + } + + void loadDataSync(final AwContents awContents, CallbackHelper onPageFinishedHelper, + final String data, final String mimeType, final boolean isBase64Encoded) + throws Exception { + int currentCallCount = onPageFinishedHelper.getCallCount(); + loadDataAsync(awContents, data, mimeType, isBase64Encoded); + onPageFinishedHelper.waitForCallback( + currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); + } + + void loadDataSyncWithCharset(final AwContents awContents, CallbackHelper onPageFinishedHelper, + final String data, final String mimeType, final boolean isBase64Encoded, + final String charset) throws Exception { + int currentCallCount = onPageFinishedHelper.getCallCount(); + mCallback.getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + awContents.loadUrl(LoadUrlParams.createLoadDataParams( + data, mimeType, isBase64Encoded, charset)); + } + }); + onPageFinishedHelper.waitForCallback( + currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); + } + + void loadDataAsync(final AwContents awContents, final String data, final String mimeType, + final boolean isBase64Encoded) throws Exception { + mCallback.getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + awContents.loadData(data, mimeType, isBase64Encoded ? "base64" : null); + } + }); + } + + void loadDataWithBaseUrlSync(final AwContents awContents, CallbackHelper onPageFinishedHelper, + final String data, final String mimeType, final boolean isBase64Encoded, + final String baseUrl, final String historyUrl) throws Throwable { + int currentCallCount = onPageFinishedHelper.getCallCount(); + loadDataWithBaseUrlAsync(awContents, data, mimeType, isBase64Encoded, baseUrl, historyUrl); + onPageFinishedHelper.waitForCallback( + currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); + } + + void loadDataWithBaseUrlAsync(final AwContents awContents, final String data, + final String mimeType, final boolean isBase64Encoded, final String baseUrl, + final String historyUrl) throws Throwable { + mCallback.runOnUiThread(new Runnable() { + @Override + public void run() { + awContents.loadDataWithBaseURL( + baseUrl, data, mimeType, isBase64Encoded ? "base64" : null, historyUrl); + } + }); + } + + void reloadSync(final AwContents awContents, CallbackHelper onPageFinishedHelper) + throws Exception { + int currentCallCount = onPageFinishedHelper.getCallCount(); + mCallback.getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + awContents.getNavigationController().reload(true); + } + }); + onPageFinishedHelper.waitForCallback( + currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); + } + + void stopLoading(final AwContents awContents) { + mCallback.getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + awContents.stopLoading(); + } + }); + } + + void waitForVisualStateCallback(final AwContents awContents) throws Exception { + final CallbackHelper ch = new CallbackHelper(); + final int chCount = ch.getCallCount(); + mCallback.getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + final long requestId = 666; + awContents.insertVisualStateCallback( + requestId, new AwContents.VisualStateCallback() { + @Override + public void onComplete(long id) { + Assert.assertEquals(requestId, id); + ch.notifyCalled(); + } + }); + } + }); + ch.waitForCallback(chCount); + } + + void insertVisualStateCallbackOnUIThread(final AwContents awContents, final long requestId, + final AwContents.VisualStateCallback callback) { + mCallback.getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + awContents.insertVisualStateCallback(requestId, callback); + } + }); + } + + void waitForPixelColorAtCenterOfView(final AwContents awContents, + final AwTestContainerView testContainerView, final int expectedColor) throws Exception { + pollUiThread(new Callable<Boolean>() { + @Override + public Boolean call() throws Exception { + return GraphicsTestUtils.getPixelColorAtCenterOfView(awContents, testContainerView) + == expectedColor; + } + }); + } + + AwTestContainerView createAwTestContainerView(final AwContentsClient awContentsClient) { + return createAwTestContainerView(awContentsClient, false, null); + } + + AwTestContainerView createAwTestContainerView(final AwContentsClient awContentsClient, + boolean supportsLegacyQuirks, final TestDependencyFactory testDependencyFactory) { + AwTestContainerView testContainerView = createDetachedAwTestContainerView( + awContentsClient, supportsLegacyQuirks, testDependencyFactory); + mCallback.getActivity().addView(testContainerView); + testContainerView.requestFocus(); + return testContainerView; + } + + AwBrowserContext getAwBrowserContext() { + return mBrowserContext; + } + + AwTestContainerView createDetachedAwTestContainerView(final AwContentsClient awContentsClient) { + return createDetachedAwTestContainerView(awContentsClient, false, null); + } + + AwTestContainerView createDetachedAwTestContainerView(final AwContentsClient awContentsClient, + boolean supportsLegacyQuirks, TestDependencyFactory testDependencyFactory) { + if (testDependencyFactory == null) { + testDependencyFactory = mCallback.createTestDependencyFactory(); + } + boolean allowHardwareAcceleration = isHardwareAcceleratedTest(); + final AwTestContainerView testContainerView = + testDependencyFactory.createAwTestContainerView( + mCallback.getActivity(), allowHardwareAcceleration); + + AwSettings awSettings = testDependencyFactory.createAwSettings( + mCallback.getActivity(), supportsLegacyQuirks); + AwContents awContents = testDependencyFactory.createAwContents(mBrowserContext, + testContainerView, testContainerView.getContext(), + testContainerView.getInternalAccessDelegate(), + testContainerView.getNativeDrawGLFunctorFactory(), awContentsClient, awSettings, + testDependencyFactory); + testContainerView.initialize(awContents); + return testContainerView; + } + + boolean isHardwareAcceleratedTest() { + return !mCallback.testMethodHasAnnotation(DisableHardwareAccelerationForTest.class); + } + + AwTestContainerView createAwTestContainerViewOnMainSync(final AwContentsClient client) + throws Exception { + return createAwTestContainerViewOnMainSync(client, false, null); + } + + AwTestContainerView createAwTestContainerViewOnMainSync( + final AwContentsClient client, final boolean supportsLegacyQuirks) { + return createAwTestContainerViewOnMainSync(client, supportsLegacyQuirks, null); + } + + AwTestContainerView createAwTestContainerViewOnMainSync(final AwContentsClient client, + final boolean supportsLegacyQuirks, final TestDependencyFactory testDependencyFactory) { + return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<AwTestContainerView>() { + @Override + public AwTestContainerView call() { + return createAwTestContainerView( + client, supportsLegacyQuirks, testDependencyFactory); + } + }); + } + + void destroyAwContentsOnMainSync(final AwContents awContents) { + if (awContents == null) return; + mCallback.getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + awContents.destroy(); + } + }); + } + + String getTitleOnUiThread(final AwContents awContents) throws Exception { + return runTestOnUiThreadAndGetResult(new Callable<String>() { + @Override + public String call() throws Exception { + return awContents.getTitle(); + } + }); + } + + AwSettings getAwSettingsOnUiThread(final AwContents awContents) throws Exception { + return runTestOnUiThreadAndGetResult(new Callable<AwSettings>() { + @Override + public AwSettings call() throws Exception { + return awContents.getSettings(); + } + }); + } + + String maybeStripDoubleQuotes(String raw) { + Assert.assertNotNull(raw); + Matcher m = MAYBE_QUOTED_STRING.matcher(raw); + Assert.assertTrue(m.matches()); + return m.group(2); + } + + String executeJavaScriptAndWaitForResult(final AwContents awContents, + TestAwContentsClient viewClient, final String code) throws Exception { + return JSUtils.executeJavaScriptAndWaitForResult(mCallback.getInstrumentation(), awContents, + viewClient.getOnEvaluateJavaScriptResultHelper(), code); + } + + /** + * Executes JavaScript code within the given ContentView to get the text content in + * document body. Returns the result string without double quotes. + */ + String getJavaScriptResultBodyTextContent( + final AwContents awContents, final TestAwContentsClient viewClient) throws Exception { + String raw = executeJavaScriptAndWaitForResult( + awContents, viewClient, "document.body.textContent"); + return maybeStripDoubleQuotes(raw); + } + + static void pollInstrumentationThread(final Callable<Boolean> callable) throws Exception { + CriteriaHelper.pollInstrumentationThread(new Criteria() { + @Override + public boolean isSatisfied() { + try { + return callable.call(); + } catch (Throwable e) { + Log.e(TAG, "Exception while polling.", e); + return false; + } + } + }, WAIT_TIMEOUT_MS, CHECK_INTERVAL); + } + + void pollUiThread(final Callable<Boolean> callable) throws Exception { + pollInstrumentationThread(new Callable<Boolean>() { + @Override + public Boolean call() throws Exception { + return runTestOnUiThreadAndGetResult(callable); + } + }); + } + + void clearCacheOnUiThread(final AwContents awContents, final boolean includeDiskFiles) + throws Exception { + mCallback.getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + awContents.clearCache(includeDiskFiles); + } + }); + } + + float getScaleOnUiThread(final AwContents awContents) throws Exception { + return runTestOnUiThreadAndGetResult(new Callable<Float>() { + @Override + public Float call() throws Exception { + return awContents.getPageScaleFactor(); + } + }); + } + + float getPixelScaleOnUiThread(final AwContents awContents) throws Exception { + return runTestOnUiThreadAndGetResult(new Callable<Float>() { + @Override + public Float call() throws Exception { + return awContents.getScale(); + } + }); + } + + boolean canZoomInOnUiThread(final AwContents awContents) throws Exception { + return runTestOnUiThreadAndGetResult(new Callable<Boolean>() { + @Override + public Boolean call() throws Exception { + return awContents.canZoomIn(); + } + }); + } + + boolean canZoomOutOnUiThread(final AwContents awContents) throws Exception { + return runTestOnUiThreadAndGetResult(new Callable<Boolean>() { + @Override + public Boolean call() throws Exception { + return awContents.canZoomOut(); + } + }); + } + + void killRenderProcessOnUiThreadAsync(final AwContents awContents) throws Exception { + mCallback.getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + awContents.killRenderProcess(); + } + }); + } + + void triggerPopup(final AwContents parentAwContents, + TestAwContentsClient parentAwContentsClient, TestWebServer testWebServer, + String mainHtml, String popupHtml, String popupPath, String triggerScript) + throws Exception { + enableJavaScriptOnUiThread(parentAwContents); + mCallback.getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + parentAwContents.getSettings().setSupportMultipleWindows(true); + parentAwContents.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); + } + }); + + final String parentUrl = testWebServer.setResponse("/popupParent.html", mainHtml, null); + if (popupHtml != null) { + testWebServer.setResponse(popupPath, popupHtml, null); + } else { + testWebServer.setResponseWithNoContentStatus(popupPath); + } + + parentAwContentsClient.getOnCreateWindowHelper().setReturnValue(true); + loadUrlSync(parentAwContents, parentAwContentsClient.getOnPageFinishedHelper(), parentUrl); + + TestAwContentsClient.OnCreateWindowHelper onCreateWindowHelper = + parentAwContentsClient.getOnCreateWindowHelper(); + int currentCallCount = onCreateWindowHelper.getCallCount(); + parentAwContents.evaluateJavaScriptForTests(triggerScript, null); + onCreateWindowHelper.waitForCallback( + currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); + } + + PopupInfo connectPendingPopup(final AwContents parentAwContents) throws Exception { + TestAwContentsClient popupContentsClient; + AwTestContainerView popupContainerView; + final AwContents popupContents; + popupContentsClient = new TestAwContentsClient(); + popupContainerView = createAwTestContainerViewOnMainSync(popupContentsClient); + popupContents = popupContainerView.getAwContents(); + enableJavaScriptOnUiThread(popupContents); + + mCallback.getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + parentAwContents.supplyContentsForPopup(popupContents); + } + }); + + OnPageFinishedHelper onPageFinishedHelper = popupContentsClient.getOnPageFinishedHelper(); + int finishCallCount = onPageFinishedHelper.getCallCount(); + TestAwContentsClient.OnReceivedTitleHelper onReceivedTitleHelper = + popupContentsClient.getOnReceivedTitleHelper(); + int titleCallCount = onReceivedTitleHelper.getCallCount(); + + onPageFinishedHelper.waitForCallback( + finishCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); + onReceivedTitleHelper.waitForCallback( + titleCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); + + return new PopupInfo(popupContentsClient, popupContainerView, popupContents); + } + + interface AwTestCommonCallback { + Instrumentation getInstrumentation(); + AwTestRunnerActivity getActivity(); + void runOnUiThread(Runnable runnable) throws Throwable; + boolean testMethodHasAnnotation(Class<? extends Annotation> clazz); + AwBrowserContext createAwBrowserContextOnUiThread( + InMemorySharedPreferences prefs, Context appContext); + TestDependencyFactory createTestDependencyFactory(); + boolean needsAwBrowserContextCreated(); + boolean needsBrowserProcessStarted(); + } +}
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnPageFinishedTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnPageFinishedTest.java index 8e39f2e6..1aa25a7 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnPageFinishedTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnPageFinishedTest.java
@@ -264,7 +264,7 @@ int onPageFinishedCallCount = onPageFinishedHelper.getCallCount(); int onPageStartedCallCount = onPageStartedHelper.getCallCount(); - JSUtils.clickOnLinkUsingJs(this, mAwContents, + JSUtils.clickOnLinkUsingJs(getInstrumentation(), mAwContents, mContentsClient.getOnEvaluateJavaScriptResultHelper(), "link"); onPageFinishedHelper.waitForCallback(onPageFinishedCallCount);
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerStartupTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerStartupTest.java index d49a3de4..777ff9c 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerStartupTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerStartupTest.java
@@ -43,12 +43,12 @@ } @Override - protected boolean needsAwBrowserContextCreated() { + public boolean needsAwBrowserContextCreated() { return false; } @Override - protected boolean needsBrowserProcessStarted() { + public boolean needsBrowserProcessStarted() { return false; }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java index f094c9a..d9405ab5 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java
@@ -114,13 +114,12 @@ private void setCookieWithJavaScript(final String name, final String value) throws Throwable { - JSUtils.executeJavaScriptAndWaitForResult( - this, mAwContents, + JSUtils.executeJavaScriptAndWaitForResult(getInstrumentation(), mAwContents, mContentsClient.getOnEvaluateJavaScriptResultHelper(), "var expirationDate = new Date();" - + "expirationDate.setDate(expirationDate.getDate() + 5);" - + "document.cookie='" + name + "=" + value - + "; expires=' + expirationDate.toUTCString();"); + + "expirationDate.setDate(expirationDate.getDate() + 5);" + + "document.cookie='" + name + "=" + value + + "; expires=' + expirationDate.toUTCString();"); } @MediumTest @@ -366,15 +365,14 @@ @MediumTest @Feature({"AndroidWebView", "Privacy"}) public void testThirdPartyCookie() throws Throwable { - // In theory we need two servers to test this, one server ('the first party') which returns - // a response with a link to a second server ('the third party') at different origin. This - // second server attempts to set a cookie which should fail if AcceptThirdPartyCookie() is - // false. - // Strictly according to the letter of RFC6454 it should be possible to set this situation - // up with two TestServers on different ports (these count as having different origins) but - // Chrome is not strict about this and does not check the port. Instead we cheat making some - // of the urls come from localhost and some from 127.0.0.1 which count (both in theory and - // pratice) as having different origins. + // In theory we need two servers to test this, one server ('the first + // party') which returns a response with a link to a second server ('the third party') at + // different origin. This second server attempts to set a cookie which should fail if + // AcceptThirdPartyCookie() is false. Strictly according to the letter of RFC6454 it should + // be possible to set this situation up with two TestServers on different ports (these count + // as having different origins) but Chrome is not strict about this and does not check the + // port. Instead we cheat making some of the urls come from localhost and some from + // 127.0.0.1 which count (both in theory and pratice) as having different origins. TestWebServer webServer = TestWebServer.start(); try { // Turn global allow on.
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/GeolocationTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/GeolocationTest.java index c636700..494855b 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/GeolocationTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/GeolocationTest.java
@@ -102,7 +102,7 @@ } @Override - protected TestDependencyFactory createTestDependencyFactory() { + public TestDependencyFactory createTestDependencyFactory() { return mOverridenFactory == null ? new TestDependencyFactory() : mOverridenFactory; }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/HttpCacheTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/HttpCacheTest.java index d08ee36..2c42c0a 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/HttpCacheTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/HttpCacheTest.java
@@ -18,7 +18,7 @@ public class HttpCacheTest extends AwTestBase { @Override - protected boolean needsBrowserProcessStarted() { + public boolean needsBrowserProcessStarted() { return false; }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/LoadUrlTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/LoadUrlTest.java index 5ac1e250..675ff54 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/LoadUrlTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/LoadUrlTest.java
@@ -288,8 +288,8 @@ validateHeadersValue(awContents, contentsClient, extraHeaders, true); int currentCallCount = contentsClient.getOnPageFinishedHelper().getCallCount(); - JSUtils.clickOnLinkUsingJs( - this, awContents, contentsClient.getOnEvaluateJavaScriptResultHelper(), "click"); + JSUtils.clickOnLinkUsingJs(getInstrumentation(), awContents, + contentsClient.getOnEvaluateJavaScriptResultHelper(), "click"); contentsClient.getOnPageFinishedHelper().waitForCallback( currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); // No extra headers for the page navigated via clicking.
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java index 220cfad..e459e3a 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java
@@ -310,7 +310,7 @@ * sites are malicious */ @Override - protected AwBrowserContext createAwBrowserContextOnUiThread( + public AwBrowserContext createAwBrowserContextOnUiThread( InMemorySharedPreferences prefs, Context appContext) { return new MockAwBrowserContext(prefs, appContext); } @@ -984,4 +984,15 @@ // trace unless on the instrumentation thread. assertTrue("Callback should run on UI Thread", mOnUiThread); } + + @SmallTest + @Feature({"AndroidWebView"}) + public void testGetSafeBrowsingPrivacyPolicyUrl() throws Throwable { + final Uri privacyPolicyUrl = Uri.parse("https://www.google.com/chrome/browser/privacy/") + .buildUpon() + .fragment("safe-browsing-policies") + .build(); + assertEquals(privacyPolicyUrl, AwContentsStatics.getSafeBrowsingPrivacyPolicyUrl()); + assertNotNull(AwContentsStatics.getSafeBrowsingPrivacyPolicyUrl()); + } }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/util/JSUtils.java b/android_webview/javatests/src/org/chromium/android_webview/test/util/JSUtils.java index 306be04..4f35e75 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/util/JSUtils.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/util/JSUtils.java
@@ -4,12 +4,12 @@ package org.chromium.android_webview.test.util; -import android.test.InstrumentationTestCase; - -import junit.framework.Assert; - import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout; +import android.app.Instrumentation; + +import org.junit.Assert; + import org.chromium.android_webview.AwContents; import org.chromium.content.browser.test.util.Criteria; import org.chromium.content.browser.test.util.CriteriaHelper; @@ -22,18 +22,16 @@ private static final long WAIT_TIMEOUT_MS = scaleTimeout(2000); private static final int CHECK_INTERVAL = 100; - public static void clickOnLinkUsingJs( - final InstrumentationTestCase testCase, + public static void clickOnLinkUsingJs(final Instrumentation instrumentation, final AwContents awContents, final OnEvaluateJavaScriptResultHelper onEvaluateJavaScriptResultHelper, final String linkId) throws Exception { - CriteriaHelper.pollInstrumentationThread(new Criteria() { @Override public boolean isSatisfied() { try { - String linkIsNotNull = executeJavaScriptAndWaitForResult(testCase, awContents, - onEvaluateJavaScriptResultHelper, + String linkIsNotNull = executeJavaScriptAndWaitForResult(instrumentation, + awContents, onEvaluateJavaScriptResultHelper, "document.getElementById('" + linkId + "') != null"); return linkIsNotNull.equals("true"); } catch (Throwable t) { @@ -44,7 +42,7 @@ } }, WAIT_TIMEOUT_MS, CHECK_INTERVAL); - testCase.getInstrumentation().runOnMainSync(new Runnable() { + instrumentation.runOnMainSync(new Runnable() { @Override public void run() { awContents.getWebContents().evaluateJavaScriptForTests( @@ -56,12 +54,11 @@ }); } - public static String executeJavaScriptAndWaitForResult( - InstrumentationTestCase testCase, + public static String executeJavaScriptAndWaitForResult(Instrumentation instrumentation, final AwContents awContents, final OnEvaluateJavaScriptResultHelper onEvaluateJavaScriptResultHelper, final String code) throws Exception { - testCase.getInstrumentation().runOnMainSync(new Runnable() { + instrumentation.runOnMainSync(new Runnable() { @Override public void run() { onEvaluateJavaScriptResultHelper.evaluateJavaScriptForTests(
diff --git a/android_webview/test/BUILD.gn b/android_webview/test/BUILD.gn index c3ebb792..8c3b2e3e 100644 --- a/android_webview/test/BUILD.gn +++ b/android_webview/test/BUILD.gn
@@ -26,6 +26,8 @@ "//base:base_java_test_support", "//components/policy/android:policy_java_test_support", "//content/public/android:content_java", + "//third_party/android_support_test_runner:runner_java", + "//third_party/junit", "//ui/android:ui_java", ] @@ -40,6 +42,7 @@ "shell/src/org/chromium/android_webview/test/AwInstrumentationTestRunner.java", "shell/src/org/chromium/android_webview/test/AwTestContainerView.java", "shell/src/org/chromium/android_webview/test/AwTestRunnerActivity.java", + "shell/src/org/chromium/android_webview/test/AwJUnit4ClassRunner.java", "shell/src/org/chromium/android_webview/test/NullContentsClient.java", "shell/src/org/chromium/android_webview/test/SecondBrowserProcess.java", "shell/src/org/chromium/android_webview/test/TestContentProvider.java", @@ -126,7 +129,9 @@ "//device/geolocation:geolocation_java_test_support", "//net/android:net_java", "//net/android:net_java_test_support", + "//third_party/android_support_test_runner:rules_java", "//third_party/android_support_test_runner:runner_java", + "//third_party/junit", "//ui/android:ui_java", ] java_files = [ @@ -166,7 +171,9 @@ "../javatests/src/org/chromium/android_webview/test/AwServiceWorkerClientTest.java", "../javatests/src/org/chromium/android_webview/test/AwSettingsTest.java", "../javatests/src/org/chromium/android_webview/test/AwStrictModeTest.java", + "../javatests/src/org/chromium/android_webview/test/AwTestCommon.java", "../javatests/src/org/chromium/android_webview/test/AwTestBase.java", + "../javatests/src/org/chromium/android_webview/test/AwActivityTestRule.java", "../javatests/src/org/chromium/android_webview/test/AwWebContentsObserverTest.java", "../javatests/src/org/chromium/android_webview/test/AwVariationsSeedFetchServiceTest.java", "../javatests/src/org/chromium/android_webview/test/AwZoomTest.java",
diff --git a/android_webview/test/shell/src/org/chromium/android_webview/test/AwJUnit4ClassRunner.java b/android_webview/test/shell/src/org/chromium/android_webview/test/AwJUnit4ClassRunner.java new file mode 100644 index 0000000..4bedc5d --- /dev/null +++ b/android_webview/test/shell/src/org/chromium/android_webview/test/AwJUnit4ClassRunner.java
@@ -0,0 +1,97 @@ +// 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. + +package org.chromium.android_webview.test; + +import android.support.test.InstrumentationRegistry; + +import org.junit.runner.notification.RunNotifier; +import org.junit.runners.model.FrameworkMethod; +import org.junit.runners.model.InitializationError; + +import org.chromium.android_webview.AwSwitches; +import org.chromium.base.CollectionUtil; +import org.chromium.base.CommandLine; +import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.BaseTestResult.PreTestHook; +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.parameter.SkipCommandLineParameterization; +import org.chromium.policy.test.annotations.Policies; + +import java.util.ArrayList; +import java.util.List; + +/** + * A custom runner for //chrome JUnit4 tests. + */ +public final class AwJUnit4ClassRunner extends BaseJUnit4ClassRunner { + /** + * Create an AwJUnit4ClassRunner to run {@code klass} and initialize values + * + * @param klass Test class to run + * @throws InitializationError if the test class is malformed + */ + public AwJUnit4ClassRunner(Class<?> klass) throws InitializationError { + super(klass, null, defaultPreTestHooks()); + } + + private static List<PreTestHook> defaultPreTestHooks() { + return CollectionUtil.newArrayList(Policies.getRegistrationHook()); + } + + @Override + protected List<FrameworkMethod> getChildren() { + List<FrameworkMethod> result = new ArrayList<>(); + for (FrameworkMethod method : computeTestMethods()) { + if (method.getAnnotation(SkipCommandLineParameterization.class) == null) { + result.add(new WebViewMultiProcessFrameworkMethod(method)); + } + result.add(method); + } + return result; + } + + @Override + protected void runChild(FrameworkMethod method, RunNotifier notifier) { + CommandLineFlags.setUp(InstrumentationRegistry.getTargetContext(), method.getMethod()); + if (method instanceof WebViewMultiProcessFrameworkMethod) { + CommandLine.getInstance().appendSwitch(AwSwitches.WEBVIEW_SANDBOXED_RENDERER); + } + super.runChild(method, notifier); + } + + /** + * Custom FrameworkMethod class indicate this test method will run in multiprocess mode. + * + * The clas also add "__multiprocess_mode" postfix to the test name. + */ + private static class WebViewMultiProcessFrameworkMethod extends FrameworkMethod { + public WebViewMultiProcessFrameworkMethod(FrameworkMethod method) { + super(method.getMethod()); + } + + @Override + public String getName() { + return super.getName() + "__multiprocess_mode"; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof WebViewMultiProcessFrameworkMethod) { + WebViewMultiProcessFrameworkMethod method = + (WebViewMultiProcessFrameworkMethod) obj; + return super.equals(obj) && method.getName().equals(getName()); + } + return false; + } + + @Override + public int hashCode() { + int result = 17; + result = 31 * result + super.hashCode(); + result = 31 * result + getName().hashCode(); + return result; + } + } +}
diff --git a/ash/app_list/app_list_presenter_delegate_unittest.cc b/ash/app_list/app_list_presenter_delegate_unittest.cc index 71eb479..d0bb651 100644 --- a/ash/app_list/app_list_presenter_delegate_unittest.cc +++ b/ash/app_list/app_list_presenter_delegate_unittest.cc
@@ -525,14 +525,17 @@ TapAndClickOutsideClosesPeekingAppList) { const bool test_mouse_event = TestMouseEventParam(); app_list_presenter_impl()->Show(GetPrimaryDisplayId()); - EXPECT_EQ(app_list_presenter_impl()->GetView()->app_list_state(), - app_list::AppListView::PEEKING); + EXPECT_EQ(app_list::AppListView::PEEKING, + app_list_presenter_impl()->GetView()->app_list_state()); ui::test::EventGenerator& generator = GetEventGenerator(); // Tapping outside the bounds closes the app list. - gfx::Point tap_point = - app_list_presenter_impl()->GetView()->bounds().origin(); - tap_point.Offset(0, -10); + const gfx::Rect peeking_bounds = + app_list_presenter_impl()->GetView()->GetBoundsInScreen(); + gfx::Point tap_point = peeking_bounds.origin(); + tap_point.Offset(10, -10); + ASSERT_FALSE(peeking_bounds.Contains(tap_point)); + if (test_mouse_event) { generator.MoveMouseTo(tap_point); generator.ClickLeftButton();
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn index ff8fe16..b3d5baa 100644 --- a/ash/public/cpp/BUILD.gn +++ b/ash/public/cpp/BUILD.gn
@@ -41,6 +41,7 @@ "shelf_types.h", "shell_window_ids.cc", "shell_window_ids.h", + "voice_interaction_state.h", "window_pin_type.cc", "window_pin_type.h", "window_properties.cc",
diff --git a/ash/public/cpp/voice_interaction_state.h b/ash/public/cpp/voice_interaction_state.h new file mode 100644 index 0000000..fd9d049 --- /dev/null +++ b/ash/public/cpp/voice_interaction_state.h
@@ -0,0 +1,21 @@ +// 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_VOICE_INTERACTION_STATE_H_ +#define ASH_PUBLIC_CPP_VOICE_INTERACTION_STATE_H_ + +namespace ash { + +enum class VoiceInteractionState { + // Voice interaction service is not ready yet, request sent will be waiting. + NOT_READY = 0, + // Voice interaction session is stopped. + STOPPED, + // Voice interaction session is currently running. + RUNNING +}; + +} // namespace ash + +#endif // ASH_PUBLIC_CPP_VOICE_INTERACTION_STATE_H_
diff --git a/ash/resources/vector_icons/BUILD.gn b/ash/resources/vector_icons/BUILD.gn index 569640d..70a3281 100644 --- a/ash/resources/vector_icons/BUILD.gn +++ b/ash/resources/vector_icons/BUILD.gn
@@ -100,8 +100,6 @@ "shelf_overflow.icon", "shelf_overview.1x.icon", "shelf_overview.icon", - "shelf_voice_interaction.1x.icon", - "shelf_voice_interaction.icon", "system_menu_accessibility.1x.icon", "system_menu_accessibility.icon", "system_menu_accessibility_auto_click.1x.icon",
diff --git a/ash/resources/vector_icons/shelf_voice_interaction.1x.icon b/ash/resources/vector_icons/shelf_voice_interaction.1x.icon deleted file mode 100644 index 57ed627..0000000 --- a/ash/resources/vector_icons/shelf_voice_interaction.1x.icon +++ /dev/null
@@ -1,38 +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. - -CANVAS_DIMENSIONS, 24, -PATH_COLOR_ARGB, 0xFF, 0x34, 0xA8, 0x53, -MOVE_TO, 22.36f, 8.64f, -CUBIC_TO, 23.27f, 8.64f, 24, 7.9f, 24, 7, -CUBIC_TO, 24, 6.1f, 23.27f, 5.36f, 22.36f, 5.36f, -CUBIC_TO, 21.46f, 5.36f, 20.73f, 6.1f, 20.73f, 7, -CUBIC_TO, 20.73f, 7.9f, 21.46f, 8.64f, 22.36f, 8.64f, -LINE_TO, 22.36f, 8.64f, -CLOSE, -NEW_PATH, -PATH_COLOR_ARGB, 0xFF, 0xEB, 0x43, 0x35, -MOVE_TO, 17.45f, 14.09f, -CUBIC_TO, 19.26f, 14.09f, 20.73f, 12.63f, 20.73f, 10.82f, -CUBIC_TO, 20.73f, 9.01f, 19.26f, 7.55f, 17.45f, 7.55f, -CUBIC_TO, 15.65f, 7.55f, 14.18f, 9.01f, 14.18f, 10.82f, -CUBIC_TO, 14.18f, 12.63f, 15.65f, 14.09f, 17.45f, 14.09f, -CLOSE, -NEW_PATH, -PATH_COLOR_ARGB, 0xFF, 0xFB, 0xBC, 0x05, -MOVE_TO, 17.45f, 22.82f, -CUBIC_TO, 19.56f, 22.82f, 21.27f, 21.11f, 21.27f, 19, -CUBIC_TO, 21.27f, 16.89f, 19.56f, 15.18f, 17.45f, 15.18f, -CUBIC_TO, 15.35f, 15.18f, 13.64f, 16.89f, 13.64f, 19, -CUBIC_TO, 13.64f, 21.11f, 15.35f, 22.82f, 17.45f, 22.82f, -CLOSE, -NEW_PATH, -PATH_COLOR_ARGB, 0xFF, 0x42, 0x85, 0xF4, -MOVE_TO, 6.55f, 14.09f, -CUBIC_TO, 10.16f, 14.09f, 13.09f, 11.16f, 13.09f, 7.55f, -CUBIC_TO, 13.09f, 3.93f, 10.16f, 1, 6.55f, 1, -CUBIC_TO, 2.93f, 1, 0, 3.93f, 0, 7.55f, -CUBIC_TO, 0, 11.16f, 2.93f, 14.09f, 6.55f, 14.09f, -CLOSE, -END
diff --git a/ash/resources/vector_icons/shelf_voice_interaction.icon b/ash/resources/vector_icons/shelf_voice_interaction.icon deleted file mode 100644 index 188c78d..0000000 --- a/ash/resources/vector_icons/shelf_voice_interaction.icon +++ /dev/null
@@ -1,38 +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. - -CANVAS_DIMENSIONS, 48, -PATH_COLOR_ARGB, 0xFF, 0x34, 0xA8, 0x53, -MOVE_TO, 44.73f, 17.27f, -CUBIC_TO, 46.53f, 17.27f, 48, 15.81f, 48, 14, -CUBIC_TO, 48, 12.19f, 46.53f, 10.73f, 44.73f, 10.73f, -CUBIC_TO, 42.92f, 10.73f, 41.45f, 12.19f, 41.45f, 14, -CUBIC_TO, 41.45f, 15.81f, 42.92f, 17.27f, 44.73f, 17.27f, -LINE_TO, 44.73f, 17.27f, -CLOSE, -NEW_PATH, -PATH_COLOR_ARGB, 0xFF, 0xEB, 0x43, 0x35, -MOVE_TO, 34.91f, 28.18f, -CUBIC_TO, 38.52f, 28.18f, 41.45f, 25.25f, 41.45f, 21.64f, -CUBIC_TO, 41.45f, 18.02f, 38.52f, 15.09f, 34.91f, 15.09f, -CUBIC_TO, 31.29f, 15.09f, 28.36f, 18.02f, 28.36f, 21.64f, -CUBIC_TO, 28.36f, 25.25f, 31.29f, 28.18f, 34.91f, 28.18f, -CLOSE, -NEW_PATH, -PATH_COLOR_ARGB, 0xFF, 0xFB, 0xBC, 0x05, -MOVE_TO, 34.91f, 45.64f, -CUBIC_TO, 39.13f, 45.64f, 42.55f, 42.22f, 42.55f, 38, -CUBIC_TO, 42.55f, 33.78f, 39.13f, 30.36f, 34.91f, 30.36f, -CUBIC_TO, 30.69f, 30.36f, 27.27f, 33.78f, 27.27f, 38, -CUBIC_TO, 27.27f, 42.22f, 30.69f, 45.64f, 34.91f, 45.64f, -CLOSE, -NEW_PATH, -PATH_COLOR_ARGB, 0xFF, 0x42, 0x85, 0xF4, -MOVE_TO, 13.09f, 28.18f, -CUBIC_TO, 20.32f, 28.18f, 26.18f, 22.32f, 26.18f, 15.09f, -CUBIC_TO, 26.18f, 7.86f, 20.32f, 2, 13.09f, 2, -CUBIC_TO, 5.86f, 2, 0, 7.86f, 0, 15.09f, -CUBIC_TO, 0, 22.32f, 5.86f, 28.18f, 13.09f, 28.18f, -CLOSE, -END
diff --git a/ash/shelf/app_list_button.cc b/ash/shelf/app_list_button.cc index a782a63..57cfa11 100644 --- a/ash/shelf/app_list_button.cc +++ b/ash/shelf/app_list_button.cc
@@ -381,7 +381,8 @@ if (chromeos::switches::IsVoiceInteractionEnabled()) // active: 100% alpha, inactive: 54% alpha - fg_flags.setAlpha(voice_interaction_running_ + fg_flags.setAlpha(voice_interaction_state_ == + ash::VoiceInteractionState::RUNNING ? kVoiceInteractionRunningAlpha : kVoiceInteractionNotRunningAlpha); @@ -459,19 +460,34 @@ OnAppListDismissed(); } -void AppListButton::OnVoiceInteractionStatusChanged(bool running) { - voice_interaction_running_ = running; +void AppListButton::OnVoiceInteractionStatusChanged( + ash::VoiceInteractionState state) { + voice_interaction_state_ = state; SchedulePaint(); - // Voice interaction window shows up, we start hiding the animation if it is - // running. - if (running && voice_interaction_overlay_->IsBursting()) { - voice_interaction_animation_hide_delay_timer_->Start( - FROM_HERE, - base::TimeDelta::FromMilliseconds( - kVoiceInteractionAnimationHideDelayMs), - base::Bind(&VoiceInteractionOverlay::HideAnimation, - base::Unretained(voice_interaction_overlay_))); + switch (state) { + case ash::VoiceInteractionState::STOPPED: + break; + case ash::VoiceInteractionState::NOT_READY: + // If we are showing the bursting or waiting animation, no need to do + // anything. Otherwise show the waiting animation now. + if (!voice_interaction_overlay_->IsBursting() && + !voice_interaction_overlay_->IsWaiting()) { + voice_interaction_overlay_->WaitingAnimation(); + } + break; + case ash::VoiceInteractionState::RUNNING: + // we start hiding the animation if it is running. + if (voice_interaction_overlay_->IsBursting() || + voice_interaction_overlay_->IsWaiting()) { + voice_interaction_animation_hide_delay_timer_->Start( + FROM_HERE, + base::TimeDelta::FromMilliseconds( + kVoiceInteractionAnimationHideDelayMs), + base::Bind(&VoiceInteractionOverlay::HideAnimation, + base::Unretained(voice_interaction_overlay_))); + } + break; } } @@ -479,9 +495,10 @@ // We only show the voice interaction icon and related animation when the // shelf is at the bottom position and voice interaction is not running. ShelfAlignment alignment = shelf_->alignment(); - bool show_icon = (alignment == SHELF_ALIGNMENT_BOTTOM || - alignment == SHELF_ALIGNMENT_BOTTOM_LOCKED) && - !voice_interaction_running_; + bool show_icon = + (alignment == SHELF_ALIGNMENT_BOTTOM || + alignment == SHELF_ALIGNMENT_BOTTOM_LOCKED) && + (voice_interaction_state_ == ash::VoiceInteractionState::STOPPED); voice_interaction_overlay_->StartAnimation(show_icon); }
diff --git a/ash/shelf/app_list_button.h b/ash/shelf/app_list_button.h index 2bf9232..a12d66bf 100644 --- a/ash/shelf/app_list_button.h +++ b/ash/shelf/app_list_button.h
@@ -8,6 +8,7 @@ #include <memory> #include "ash/ash_export.h" +#include "ash/public/cpp/voice_interaction_state.h" #include "ash/shell_observer.h" #include "base/macros.h" #include "third_party/skia/include/core/SkColor.h" @@ -69,7 +70,8 @@ // ShellObserver: void OnAppListVisibilityChanged(bool shown, aura::Window* root_window) override; - void OnVoiceInteractionStatusChanged(bool running) override; + void OnVoiceInteractionStatusChanged( + ash::VoiceInteractionState state) override; void StartVoiceInteractionAnimation(); @@ -98,7 +100,8 @@ std::unique_ptr<base::OneShotTimer> voice_interaction_animation_hide_delay_timer_; - bool voice_interaction_running_ = false; + ash::VoiceInteractionState voice_interaction_state_ = + ash::VoiceInteractionState::STOPPED; // Flag that gets set each time we receive a mouse or gesture event. It is // then used to render the ink drop in the right location.
diff --git a/ash/shelf/voice_interaction_overlay.cc b/ash/shelf/voice_interaction_overlay.cc index 97b934a..2495e28 100644 --- a/ash/shelf/voice_interaction_overlay.cc +++ b/ash/shelf/voice_interaction_overlay.cc
@@ -288,6 +288,22 @@ gfx::Tween::LINEAR_OUT_SLOW_IN, animation_observer); } + void SetToLarge(const gfx::PointF& new_center) { + PaintedShapeTransforms transforms; + SetPaintedLayersVisible(true); + // Hide the foreground layers and only show the background layers. + for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i) + painted_layers_[i]->SetVisible(false); + // Hide the shadow layer + shadow_layer_->SetVisible(false); + + center_point_ = new_center; + // Set the painted layers to the large rectangle size + CalculateRectTransforms(large_size_, kBackgroundCornerRadiusDip, + &transforms); + SetTransforms(transforms); + } + void ResetShape() { // This reverts to the original small round shape. shadow_layer_->SetVisible(true); @@ -581,9 +597,6 @@ icon_layer_(base::MakeUnique<VoiceInteractionIcon>()), background_layer_(base::MakeUnique<VoiceInteractionIconBackground>()), host_view_(host_view), - is_bursting_(false), - show_icon_(false), - should_hide_animation_(false), circle_layer_delegate_(kRippleColor, kRippleCircleInitRadiusDip) { SetPaintToLayer(ui::LAYER_NOT_DRAWN); layer()->set_name("VoiceInteractionOverlay:ROOT_LAYER"); @@ -605,7 +618,7 @@ VoiceInteractionOverlay::~VoiceInteractionOverlay() {} void VoiceInteractionOverlay::StartAnimation(bool show_icon) { - is_bursting_ = false; + animation_state_ = AnimationState::STARTING; show_icon_ = show_icon; SetVisible(true); @@ -715,8 +728,7 @@ } void VoiceInteractionOverlay::BurstAnimation() { - is_bursting_ = true; - should_hide_animation_ = false; + animation_state_ = AnimationState::BURSTING; gfx::Point center = host_view_->GetAppListButtonCenterPoint(); gfx::Transform transform; @@ -766,10 +778,6 @@ } // Setup background animation. - ui::CallbackLayerAnimationObserver* observer = - new ui::CallbackLayerAnimationObserver( - base::Bind(&VoiceInteractionOverlay::AnimationEndedCallback, - base::Unretained(this))); // Transform to new shape. // We want to animate from the background's current position into a larger // size. The animation moves the background's center point while morphing from @@ -785,12 +793,70 @@ gfx::PointF( kBackgroundLargeWidthDip / 2 + kBackgroundPaddingDip - x_offset, -kBackgroundLargeHeightDip / 2 - kBackgroundPaddingDip - y_offset), - observer); - observer->SetActive(); + nullptr); +} + +void VoiceInteractionOverlay::WaitingAnimation() { + // If we are already playing burst animation, it will end up at waiting state + // anyway. No need to do anything. + if (IsBursting()) + return; + + animation_state_ = AnimationState::WAITING; + + gfx::Point center = host_view_->GetAppListButtonCenterPoint(); + gfx::Transform transform; + + ripple_layer_->SetOpacity(0); + icon_layer_->SetOpacity(0); + background_layer_->SetOpacity(0); + SetVisible(true); + + // Setup icon layer. + { + transform.Translate(kBackgroundLargeWidthDip / 2 + kBackgroundPaddingDip - + kIconEndSizeDip / 2, + -kBackgroundLargeHeightDip / 2 - kBackgroundPaddingDip - + kIconEndSizeDip / 2); + SkMScalar scale_factor = kIconEndSizeDip / kIconInitSizeDip; + transform.Scale(scale_factor, scale_factor); + icon_layer_->SetTransform(transform); + + ui::ScopedLayerAnimationSettings settings(icon_layer_->GetAnimator()); + settings.SetTransitionDuration( + base::TimeDelta::FromMilliseconds(kBackgroundMorphDurationMs)); + settings.SetPreemptionStrategy( + ui::LayerAnimator::PreemptionStrategy::ENQUEUE_NEW_ANIMATION); + settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN); + + icon_layer_->SetOpacity(1); + icon_layer_->StartAnimation(); + } + + // Setup background layer. + { + float x_offset = center.x() - kBackgroundSizeDip / 2; + float y_offset = center.y() - kBackgroundSizeDip / 2; + + transform.MakeIdentity(); + background_layer_->SetTransform(transform); + background_layer_->SetToLarge(gfx::PointF( + kBackgroundLargeWidthDip / 2 + kBackgroundPaddingDip - x_offset, + -kBackgroundLargeHeightDip / 2 - kBackgroundPaddingDip - y_offset)); + + ui::ScopedLayerAnimationSettings settings(background_layer_->GetAnimator()); + settings.SetTransitionDuration( + base::TimeDelta::FromMilliseconds(kBackgroundMorphDurationMs)); + settings.SetPreemptionStrategy( + ui::LayerAnimator::PreemptionStrategy::ENQUEUE_NEW_ANIMATION); + settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN); + + background_layer_->SetOpacity(1); + } } void VoiceInteractionOverlay::EndAnimation() { - if (is_bursting_) { + if (IsBursting()) { // Too late, user action already fired, we have to finish what's started. return; } @@ -868,14 +934,7 @@ } void VoiceInteractionOverlay::HideAnimation() { - is_bursting_ = false; - - if (background_layer_->GetAnimator()->is_animating()) { - // Wait for current animation to finish - should_hide_animation_ = true; - return; - } - should_hide_animation_ = false; + animation_state_ = AnimationState::HIDDEN; // Setup ripple animations. { @@ -915,12 +974,4 @@ } } -bool VoiceInteractionOverlay::AnimationEndedCallback( - const ui::CallbackLayerAnimationObserver& observer) { - if (should_hide_animation_) - HideAnimation(); - - return true; -} - } // namespace ash
diff --git a/ash/shelf/voice_interaction_overlay.h b/ash/shelf/voice_interaction_overlay.h index f126751..4f89c08 100644 --- a/ash/shelf/voice_interaction_overlay.h +++ b/ash/shelf/voice_interaction_overlay.h
@@ -13,10 +13,6 @@ #include "ui/views/animation/ink_drop_painted_layer_delegates.h" #include "ui/views/view.h" -namespace ui { -class CallbackLayerAnimationObserver; -} // namespace ui - namespace ash { class AppListButton; @@ -31,12 +27,25 @@ void StartAnimation(bool show_icon); void EndAnimation(); void BurstAnimation(); + void WaitingAnimation(); void HideAnimation(); - bool IsBursting() const { return is_bursting_; } + bool IsBursting() const { + return AnimationState::BURSTING == animation_state_; + } + bool IsWaiting() const { return AnimationState::WAITING == animation_state_; } private: - bool AnimationEndedCallback( - const ui::CallbackLayerAnimationObserver& observer); + enum class AnimationState { + // Indicates no animation is playing. + HIDDEN = 0, + // Indicates currently playing the starting animation. + STARTING, + // Indiates the current animation is in the bursting phase, which means no + // turning back. + BURSTING, + // Indicates currently playing the waiting animation. + WAITING + }; std::unique_ptr<ui::Layer> ripple_layer_; std::unique_ptr<VoiceInteractionIcon> icon_layer_; @@ -44,16 +53,10 @@ AppListButton* host_view_; - // Indiates the current animation is in the bursting phase, which means no - // turning back. - bool is_bursting_; + AnimationState animation_state_ = AnimationState::HIDDEN; // Whether showing the icon animation or not. - bool show_icon_; - - // Whether we should hide the burst animation when the animation ends. This is - // used to synchronize the animation and the underlying window's appearance. - bool should_hide_animation_; + bool show_icon_ = false; views::CircleLayerDelegate circle_layer_delegate_;
diff --git a/ash/shell.cc b/ash/shell.cc index b656fd50..b2f7edf4 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -617,9 +617,9 @@ observer.OnAppListVisibilityChanged(visible, root_window); } -void Shell::NotifyVoiceInteractionStatusChanged(bool running) { +void Shell::NotifyVoiceInteractionStatusChanged(VoiceInteractionState state) { for (auto& observer : shell_observers_) - observer.OnVoiceInteractionStatusChanged(running); + observer.OnVoiceInteractionStatusChanged(state); } ////////////////////////////////////////////////////////////////////////////////
diff --git a/ash/shell.h b/ash/shell.h index 1a34aebd..5518b03 100644 --- a/ash/shell.h +++ b/ash/shell.h
@@ -173,6 +173,7 @@ enum class Config; enum class LoginStatus; +enum class VoiceInteractionState; // Shell is a singleton object that presents the Shell API and implements the // RootWindow's delegate interface. @@ -617,7 +618,7 @@ void NotifyAppListVisibilityChanged(bool visible, aura::Window* root_window); - void NotifyVoiceInteractionStatusChanged(bool running); + void NotifyVoiceInteractionStatusChanged(VoiceInteractionState state); private: FRIEND_TEST_ALL_PREFIXES(ExtendedDesktopTest, TestCursor);
diff --git a/ash/shell_observer.h b/ash/shell_observer.h index fbf20b4..5e4f2561 100644 --- a/ash/shell_observer.h +++ b/ash/shell_observer.h
@@ -16,6 +16,8 @@ namespace ash { +enum class VoiceInteractionState; + class ASH_EXPORT ShellObserver { public: // Called when the AppList is shown or dismissed. @@ -68,8 +70,8 @@ // Called when a new KeyboardController is created. virtual void OnKeyboardControllerCreated() {} - // Called when voice interaction session starts / finishes. - virtual void OnVoiceInteractionStatusChanged(bool running) {} + // Called when voice interaction session state changes. + virtual void OnVoiceInteractionStatusChanged(VoiceInteractionState state) {} // Called at the end of Shell::Init. virtual void OnShellInitialized() {}
diff --git a/ash/wallpaper/wallpaper_controller.cc b/ash/wallpaper/wallpaper_controller.cc index 39c54bc..4aa97499 100644 --- a/ash/wallpaper/wallpaper_controller.cc +++ b/ash/wallpaper/wallpaper_controller.cc
@@ -9,6 +9,7 @@ #include "ash/ash_switches.h" #include "ash/display/window_tree_host_manager.h" +#include "ash/login/ui/login_constants.h" #include "ash/public/cpp/ash_pref_names.h" #include "ash/public/cpp/config.h" #include "ash/public/cpp/shell_window_ids.h" @@ -425,6 +426,9 @@ return; } + if (Shell::Get()->session_controller()->IsUserSessionBlocked()) + component->SetWallpaperBlur(login_constants::kBlurSigma); + RootWindowController* controller = RootWindowController::ForWindow(root_window); controller->SetAnimatingWallpaperWidgetController(
diff --git a/ash/wallpaper/wallpaper_view.cc b/ash/wallpaper/wallpaper_view.cc index ec74bc7..bb7f32c 100644 --- a/ash/wallpaper/wallpaper_view.cc +++ b/ash/wallpaper/wallpaper_view.cc
@@ -263,8 +263,6 @@ aura::Window* container = root_window->GetChildById(container_id); wallpaper_widget->SetBounds(container->bounds()); - if (Shell::Get()->session_controller()->IsUserSessionBlocked()) - wallpaper_widget->GetLayer()->SetLayerBlur(login_constants::kBlurSigma); return wallpaper_widget; }
diff --git a/ash/wallpaper/wallpaper_widget_controller.cc b/ash/wallpaper/wallpaper_widget_controller.cc index ecedde7..db2883c 100644 --- a/ash/wallpaper/wallpaper_widget_controller.cc +++ b/ash/wallpaper/wallpaper_widget_controller.cc
@@ -70,6 +70,8 @@ WallpaperWidgetController::~WallpaperWidgetController() { if (widget_) { + if (widget_->GetLayer()->layer_blur() > 0.0f) + widget_parent_->layer()->SetCacheRenderSurface(false); views::Widget* widget = widget_; RemoveObservers(); widget->CloseNow(); @@ -88,11 +90,15 @@ bool WallpaperWidgetController::Reparent(aura::Window* root_window, int container) { if (widget_) { + // Ensures the cache render surface of the old parent is unset. + widget_parent_->layer()->SetCacheRenderSurface(false); widget_parent_->RemoveObserver(this); aura::Window* window = widget_->GetNativeWindow(); root_window->GetChildById(container)->AddChild(window); widget_parent_ = widget_->GetNativeWindow()->parent(); widget_parent_->AddObserver(this); + if (widget_->GetLayer()->layer_blur() > 0.0f) + widget_parent_->layer()->SetCacheRenderSurface(true); return true; } // Nothing to reparent. @@ -128,6 +134,12 @@ } } +void WallpaperWidgetController::SetWallpaperBlur(float blur_sigma) { + widget_->GetLayer()->SetLayerBlur(blur_sigma); + // Force the use of cache render surface to make blur more efficient. + widget_parent_->layer()->SetCacheRenderSurface(blur_sigma > 0.0f); +} + AnimatingWallpaperWidgetController::AnimatingWallpaperWidgetController( WallpaperWidgetController* controller) : controller_(controller) {}
diff --git a/ash/wallpaper/wallpaper_widget_controller.h b/ash/wallpaper/wallpaper_widget_controller.h index 1c379ee9..99363043b 100644 --- a/ash/wallpaper/wallpaper_widget_controller.h +++ b/ash/wallpaper/wallpaper_widget_controller.h
@@ -42,6 +42,9 @@ // necessary this as |layer_| doesn't have access to the root window). void StartAnimating(RootWindowController* root_window_controller); + // Blur pixels of the wallpaper layer by 3 * the given amount. + void SetWallpaperBlur(float blur_sigma); + views::Widget* widget() { return widget_; } private:
diff --git a/base/android/java/src/org/chromium/base/ContentUriUtils.java b/base/android/java/src/org/chromium/base/ContentUriUtils.java index a239fd4..ba92a56c 100644 --- a/base/android/java/src/org/chromium/base/ContentUriUtils.java +++ b/base/android/java/src/org/chromium/base/ContentUriUtils.java
@@ -176,10 +176,7 @@ public static String getDisplayName(Uri uri, Context context, String columnField) { if (uri == null) return ""; ContentResolver contentResolver = context.getContentResolver(); - Cursor cursor = null; - try { - cursor = contentResolver.query(uri, null, null, null, null); - + try (Cursor cursor = contentResolver.query(uri, null, null, null, null)) { if (cursor != null && cursor.getCount() >= 1) { cursor.moveToFirst(); int displayNameIndex = cursor.getColumnIndex(columnField); @@ -207,8 +204,6 @@ // Some android models don't handle the provider call correctly. // see crbug.com/345393 return ""; - } finally { - StreamUtil.closeQuietly(cursor); } return ""; } @@ -226,10 +221,7 @@ return false; } ContentResolver contentResolver = ContextUtils.getApplicationContext().getContentResolver(); - Cursor cursor = null; - try { - cursor = contentResolver.query(uri, null, null, null, null); - + try (Cursor cursor = contentResolver.query(uri, null, null, null, null)) { if (cursor != null && cursor.getCount() >= 1) { cursor.moveToFirst(); return hasVirtualFlag(cursor); @@ -238,8 +230,6 @@ // Some android models don't handle the provider call correctly. // see crbug.com/345393 return false; - } finally { - StreamUtil.closeQuietly(cursor); } return false; }
diff --git a/base/android/java/src/org/chromium/base/SecureRandomInitializer.java b/base/android/java/src/org/chromium/base/SecureRandomInitializer.java index 294b1e6..bfd7b49 100644 --- a/base/android/java/src/org/chromium/base/SecureRandomInitializer.java +++ b/base/android/java/src/org/chromium/base/SecureRandomInitializer.java
@@ -24,16 +24,12 @@ * Safely initializes the random number generator, by seeding it with data from /dev/urandom. */ public static void initialize(SecureRandom generator) throws IOException { - FileInputStream fis = null; - try { + try (FileInputStream fis = new FileInputStream("/dev/urandom")) { byte[] seedBytes = new byte[NUM_RANDOM_BYTES]; - fis = new FileInputStream("/dev/urandom"); if (fis.read(seedBytes) != seedBytes.length) { throw new IOException("Failed to get enough random data."); } generator.setSeed(seedBytes); - } finally { - StreamUtil.closeQuietly(fis); } } }
diff --git a/base/message_loop/message_loop_io_posix_unittest.cc b/base/message_loop/message_loop_io_posix_unittest.cc index 75d25ad..4a6d103 100644 --- a/base/message_loop/message_loop_io_posix_unittest.cc +++ b/base/message_loop/message_loop_io_posix_unittest.cc
@@ -36,26 +36,10 @@ int err = pipe(pipefds); ASSERT_EQ(0, err); read_fd_ = ScopedFD(pipefds[0]); - ASSERT_TRUE(SetNonBlocking(read_fd_.get())); write_fd_ = ScopedFD(pipefds[1]); } void TriggerReadEvent() { - // First empty the pipe buffer. - while (true) { - char c; - int result = HANDLE_EINTR(read(read_fd_.get(), &c, 1)); - if (result == -1) { - if (errno != EWOULDBLOCK) { - PLOG(ERROR) << "read"; - FAIL(); - } - break; - } - - EXPECT_GT(result, 0); - }; - // Write from the other end of the pipe to trigger the event. char c = '\0'; EXPECT_EQ(1, HANDLE_EINTR(write(write_fd_.get(), &c, 1))); @@ -87,20 +71,49 @@ std::unique_ptr<MessageLoopForIO::FileDescriptorWatcher> watcher_to_delete_; }; -// Watcher that calls specified closures when read/write events occur. +// Watcher that calls specified closures when read/write events occur. Verifies +// that each non-null closure passed to this class is called once and only once. +// Also resets the read event by reading from the FD. class CallClosureHandler : public MessageLoopForIO::Watcher { public: CallClosureHandler(OnceClosure read_closure, OnceClosure write_closure) : read_closure_(std::move(read_closure)), write_closure_(std::move(write_closure)) {} - ~CallClosureHandler() override {} + ~CallClosureHandler() override { + EXPECT_TRUE(read_closure_.is_null()); + EXPECT_TRUE(write_closure_.is_null()); + } - // base:MessagePumpFuchsia::Watcher interface + void SetReadClosure(OnceClosure read_closure) { + EXPECT_TRUE(read_closure_.is_null()); + read_closure_ = std::move(read_closure); + } + + void SetWriteClosure(OnceClosure write_closure) { + EXPECT_TRUE(write_closure_.is_null()); + write_closure_ = std::move(write_closure); + } + + // base:MessagePumpFuchsia::Watcher interface. void OnFileCanReadWithoutBlocking(int fd) override { + // Empty the pipe buffer to reset the event. Otherwise libevent + // implementation of MessageLoop may call the event handler again even if + // |read_closure_| below quits the RunLoop. + char c; + int result = HANDLE_EINTR(read(fd, &c, 1)); + if (result == -1) { + PLOG(ERROR) << "read"; + FAIL(); + } + EXPECT_EQ(result, 1); + + ASSERT_FALSE(read_closure_.is_null()); std::move(read_closure_).Run(); } + void OnFileCanWriteWithoutBlocking(int fd) override { + ASSERT_FALSE(write_closure_.is_null()); std::move(write_closure_).Run(); } @@ -238,6 +251,92 @@ RunLoop().RunUntilIdle(); } +// Verify that non-persistent watcher is called only once. +TEST_F(MessageLoopForIoPosixTest, NonPersistentWatcher) { + MessageLoopForIO message_loop; + MessageLoopForIO::FileDescriptorWatcher watcher(FROM_HERE); + + RunLoop run_loop; + CallClosureHandler handler(run_loop.QuitClosure(), OnceClosure()); + + // Create a non-persistent watcher. + ASSERT_TRUE(MessageLoopForIO::current()->WatchFileDescriptor( + read_fd_.get(), /* persistent= */ false, MessageLoopForIO::WATCH_READ, + &watcher, &handler)); + + TriggerReadEvent(); + run_loop.Run(); + + // Trigger the event again. handler should not be called again. + TriggerReadEvent(); + RunLoop().RunUntilIdle(); +} + +// Verify that persistent watcher is called every time the event is triggered. +TEST_F(MessageLoopForIoPosixTest, PersistentWatcher) { + MessageLoopForIO message_loop; + MessageLoopForIO::FileDescriptorWatcher watcher(FROM_HERE); + + RunLoop run_loop1; + CallClosureHandler handler(run_loop1.QuitClosure(), OnceClosure()); + + // Create persistent watcher. + ASSERT_TRUE(MessageLoopForIO::current()->WatchFileDescriptor( + read_fd_.get(), /* persistent= */ true, MessageLoopForIO::WATCH_READ, + &watcher, &handler)); + + TriggerReadEvent(); + run_loop1.Run(); + + RunLoop run_loop2; + handler.SetReadClosure(run_loop2.QuitClosure()); + + // Trigger the event again. handler should be called now, which will quit + // run_loop2. + TriggerReadEvent(); + run_loop2.Run(); +} + +void StopWatchingAndWatchAgain( + MessageLoopForIO::FileDescriptorWatcher* controller, + int fd, + MessageLoopForIO::Watcher* new_handler, + RunLoop* run_loop) { + controller->StopWatchingFileDescriptor(); + + ASSERT_TRUE(MessageLoopForIO::current()->WatchFileDescriptor( + fd, /* persistent= */ true, MessageLoopForIO::WATCH_READ, controller, + new_handler)); + + run_loop->Quit(); +} + +// Verify that a watcher can be stopped and reused from an event handler. +TEST_F(MessageLoopForIoPosixTest, StopAndRestartFromHandler) { + MessageLoopForIO message_loop; + MessageLoopForIO::FileDescriptorWatcher watcher(FROM_HERE); + + RunLoop run_loop1; + RunLoop run_loop2; + CallClosureHandler handler2(run_loop2.QuitClosure(), OnceClosure()); + CallClosureHandler handler1(BindOnce(&StopWatchingAndWatchAgain, &watcher, + read_fd_.get(), &handler2, &run_loop1), + OnceClosure()); + + // Create persistent watcher. + ASSERT_TRUE(MessageLoopForIO::current()->WatchFileDescriptor( + read_fd_.get(), /* persistent= */ true, MessageLoopForIO::WATCH_READ, + &watcher, &handler1)); + + TriggerReadEvent(); + run_loop1.Run(); + + // Trigger the event again. handler2 should be called now, which will quit + // run_loop2 + TriggerReadEvent(); + run_loop2.Run(); +} + } // namespace #endif // !defined(OS_NACL)
diff --git a/base/message_loop/message_pump_fuchsia.cc b/base/message_loop/message_pump_fuchsia.cc index ab1fab1..4199ffc 100644 --- a/base/message_loop/message_pump_fuchsia.cc +++ b/base/message_loop/message_pump_fuchsia.cc
@@ -18,16 +18,19 @@ MessagePumpFuchsia::MxHandleWatchController::~MxHandleWatchController() { if (!StopWatchingMxHandle()) NOTREACHED(); - if (was_destroyed_) { - DCHECK(!*was_destroyed_); - *was_destroyed_ = true; - } } bool MessagePumpFuchsia::MxHandleWatchController::StopWatchingMxHandle() { - // Clear |persistent_| flag, so that if we are stopped mid-callback, we - // won't re-instate the wait operation. - persistent_ = false; + if (was_stopped_) { + DCHECK(!*was_stopped_); + *was_stopped_ = true; + + // |was_stopped_| points at a value stored on the stack, which will go out + // of scope. MessagePumpFuchsia::Run() will reset it only if the value is + // false. So we need to reset this pointer here as well, to make sure it's + // not used again. + was_stopped_ = nullptr; + } // If the pump is gone, or we haven't begun waiting, then there is nothing // to cancel. @@ -50,17 +53,17 @@ uint32_t events; __mxio_wait_end(io_, signals, &events); - // Each |watcher_| callback we invoke may delete |this| from under us. The - // pump has set |was_destroyed_| to point to a safe location on the calling - // stack, so we can use that to detect deletion mid-callback avoid doing - // further work that would touch |this|. - bool* was_destroyed = was_destroyed_; + // Each |watcher_| callback we invoke may stop or delete |this|. The pump has + // set |was_stopped_| to point to a safe location on the calling stack, so we + // can use that to detect being stopped mid-callback and avoid doing further + // work that would touch |this|. + bool* was_stopped = was_stopped_; if (events & MXIO_EVT_WRITABLE) watcher_->OnFileCanWriteWithoutBlocking(fd_); - if (!*was_destroyed && (events & MXIO_EVT_READABLE)) + if (!*was_stopped && (events & MXIO_EVT_READABLE)) watcher_->OnFileCanReadWithoutBlocking(fd_); - // Don't add additional work here without checking |*was_destroyed_| again. + // Don't add additional work here without checking |*was_stopped_| again. } MessagePumpFuchsia::FdWatchController::FdWatchController( @@ -247,18 +250,18 @@ mx_signals_t signals = controller->WaitEnd(packet.signal.observed); - // In the case of a persistent Watch, the Watch may be deleted by the - // caller within the callback, in which case |controller| is no longer - // valid, and we mustn't continue the watch. We check for this with a bool - // on the stack, which the Watch receives a pointer to, to set it so we - // can detect destruction. - bool controller_was_destroyed = false; - controller->was_destroyed_ = &controller_was_destroyed; + // In the case of a persistent Watch, the Watch may be stopped and + // potentially deleted by the caller within the callback, in which case + // |controller| should not be accessed again, and we mustn't continue the + // watch. We check for this with a bool on the stack, which the Watch + // receives a pointer to. + bool controller_was_stopped = false; + controller->was_stopped_ = &controller_was_stopped; controller->watcher_->OnMxHandleSignalled(controller->handle_, signals); - if (!controller_was_destroyed) { - controller->was_destroyed_ = nullptr; + if (!controller_was_stopped) { + controller->was_stopped_ = nullptr; if (controller->persistent_) controller->WaitBegin(); }
diff --git a/base/message_loop/message_pump_fuchsia.h b/base/message_loop/message_pump_fuchsia.h index 1aad9f7..41b4904 100644 --- a/base/message_loop/message_pump_fuchsia.h +++ b/base/message_loop/message_pump_fuchsia.h
@@ -58,10 +58,10 @@ // This bool is used by the pump when invoking the MxHandleWatcher callback, // and by the FdHandleWatchController when invoking read & write callbacks, // to cope with the possibility of the caller deleting the *Watcher within - // the callback. The pump sets |was_destroyed_| to a location on the stack, + // the callback. The pump sets |was_stopped_| to a location on the stack, // and the Watcher writes to it, if set, when deleted, allowing the pump // to check the value on the stack to short-cut any post-callback work. - bool* was_destroyed_ = nullptr; + bool* was_stopped_ = nullptr; protected: friend class MessagePumpFuchsia;
diff --git a/base/metrics/histogram.cc b/base/metrics/histogram.cc index 7c2a6c2..7cdddcd 100644 --- a/base/metrics/histogram.cc +++ b/base/metrics/histogram.cc
@@ -48,9 +48,6 @@ constexpr uintptr_t kDummyValue = 0xDEADBEEF; #endif -// TODO(asvitkine): Remove this after crbug/736675. -char g_last_logged_histogram_name[256] = {0}; - bool ReadHistogramArguments(PickleIterator* iter, std::string* histogram_name, int* flags, @@ -478,9 +475,6 @@ DCHECK_EQ(0, ranges(0)); DCHECK_EQ(kSampleType_MAX, ranges(bucket_count())); - strlcpy(g_last_logged_histogram_name, histogram_name().c_str(), - sizeof(g_last_logged_histogram_name)); - if (value > kSampleType_MAX - 1) value = kSampleType_MAX - 1; if (value < 0) @@ -584,9 +578,9 @@ return is_valid; // Abort if a problem is found (except "flags", which could legally be zero). - const std::string debug_string = base::StringPrintf( - "%s/%" PRIu32 "/%d/%s", histogram_name().c_str(), bad_fields, - corrupted_count, g_last_logged_histogram_name); + const std::string debug_string = + base::StringPrintf("%s/%" PRIu32 "/%d", histogram_name().c_str(), + bad_fields, corrupted_count); #if !defined(OS_NACL) // Temporary for https://crbug.com/736675. base::debug::ScopedCrashKey crash_key("bad_histogram", debug_string);
diff --git a/base/process/memory_fuchsia.cc b/base/process/memory_fuchsia.cc index 7ddaeb5..6f559a43 100644 --- a/base/process/memory_fuchsia.cc +++ b/base/process/memory_fuchsia.cc
@@ -8,6 +8,10 @@ namespace base { +void EnableTerminationOnOutOfMemory() { + // Nothing to be done here. +} + void EnableTerminationOnHeapCorruption() { // Nothing to be done here. }
diff --git a/base/test/launcher/test_launcher.cc b/base/test/launcher/test_launcher.cc index 0223991..a610b22 100644 --- a/base/test/launcher/test_launcher.cc +++ b/base/test/launcher/test_launcher.cc
@@ -62,6 +62,12 @@ #include "base/win/windows_version.h" #endif +#if defined(OS_FUCHSIA) +// TODO(scottmg): For temporary code in OnOutputTimeout(). +#include <magenta/syscalls.h> +#include <magenta/syscalls/object.h> +#endif + namespace base { // See https://groups.google.com/a/chromium.org/d/msg/chromium-dev/nkdTP7sstSc/uT3FaE_sgkAJ . @@ -1169,6 +1175,26 @@ #else fprintf(stdout, "\t%s\n", pair.second.GetCommandLineString().c_str()); #endif + +#if defined(OS_FUCHSIA) + // TODO(scottmg): Temporary code to try to identify why child processes + // appear to not be terminated after a timeout correctly. + // https://crbug.com/750370 and https://crbug.com/738275. + + mx_info_process_t proc_info = {}; + mx_status_t status = + mx_object_get_info(pair.first, MX_INFO_PROCESS, &proc_info, + sizeof(proc_info), nullptr, nullptr); + if (status != MX_OK) { + fprintf(stdout, "mx_object_get_info failed for '%s', status=%d\n", + pair.second.GetCommandLineString().c_str(), status); + } else { + fprintf(stdout, " return_code=%d\n", proc_info.return_code); + fprintf(stdout, " started=%d\n", proc_info.started); + fprintf(stdout, " exited=%d\n", proc_info.exited); + fprintf(stdout, " debugger_attached=%d\n", proc_info.debugger_attached); + } +#endif // OS_FUCHSIA } fflush(stdout);
diff --git a/base/threading/platform_thread.h b/base/threading/platform_thread.h index ad1b7d4..0fb7073 100644 --- a/base/threading/platform_thread.h +++ b/base/threading/platform_thread.h
@@ -20,6 +20,8 @@ #include <windows.h> #elif defined(OS_MACOSX) #include <mach/mach_types.h> +#elif defined(OS_FUCHSIA) +#include <magenta/types.h> #elif defined(OS_POSIX) #include <pthread.h> #include <unistd.h> @@ -32,6 +34,8 @@ typedef DWORD PlatformThreadId; #elif defined(OS_MACOSX) typedef mach_port_t PlatformThreadId; +#elif defined(OS_FUCHSIA) +typedef mx_handle_t PlatformThreadId; #elif defined(OS_POSIX) typedef pid_t PlatformThreadId; #endif
diff --git a/base/threading/platform_thread_fuchsia.cc b/base/threading/platform_thread_fuchsia.cc index 6a9ed18..aea9551 100644 --- a/base/threading/platform_thread_fuchsia.cc +++ b/base/threading/platform_thread_fuchsia.cc
@@ -52,7 +52,8 @@ void PlatformThread::SetName(const std::string& name) { // TODO(fuchsia): There's no system-level API to communicate a thread name // (for the debugger, etc.), so for now only set to our internal mechanisms. - ThreadIdNameManager::GetInstance()->SetName(pthread_self(), name); + ThreadIdNameManager::GetInstance()->SetName(PlatformThread::CurrentId(), + name); tracked_objects::ThreadData::InitializeThreadContext(name); }
diff --git a/base/threading/platform_thread_posix.cc b/base/threading/platform_thread_posix.cc index e049a54..d1e6e675 100644 --- a/base/threading/platform_thread_posix.cc +++ b/base/threading/platform_thread_posix.cc
@@ -28,6 +28,10 @@ #include <sys/syscall.h> #endif +#if defined(OS_FUCHSIA) +#include <magenta/process.h> +#endif + namespace base { void InitThreading(); @@ -137,7 +141,9 @@ return syscall(__NR_gettid); #elif defined(OS_ANDROID) return gettid(); -#elif defined(OS_SOLARIS) || defined(OS_QNX) || defined(OS_FUCHSIA) +#elif defined(OS_FUCHSIA) + return mx_thread_self(); +#elif defined(OS_SOLARIS) || defined(OS_QNX) return pthread_self(); #elif defined(OS_NACL) && defined(__GLIBC__) return pthread_self();
diff --git a/build/android/BUILD.gn b/build/android/BUILD.gn index f00a35c..80c21c1 100644 --- a/build/android/BUILD.gn +++ b/build/android/BUILD.gn
@@ -11,6 +11,13 @@ "buildhooks/java/org/chromium/build/BuildHooks.java", "buildhooks/java/org/chromium/build/Callback.java", ] + + # Make all targets pull in the try-with-resources support files. + # If an apk ends up not using any such statements, ProGuard will remove + # them. + deps = [ + "//third_party/bazel/desugar:desugar_runtime_java", + ] no_build_hooks = true supports_android = true }
diff --git a/build/android/gyp/create_test_runner_script.py b/build/android/gyp/create_test_runner_script.py index f6a2c3d..a67da882 100755 --- a/build/android/gyp/create_test_runner_script.py +++ b/build/android/gyp/create_test_runner_script.py
@@ -70,14 +70,14 @@ group.add_argument('--additional-apk-incremental', action='append', dest='additional_apks_incremental', default=[]) group.add_argument('--apk-under-test') - group.add_argument('--apk-under-test-incremental-install-script') + group.add_argument('--apk-under-test-incremental-install-json') group.add_argument('--executable-dist-dir') group.add_argument('--isolate-file-path') group.add_argument('--output-directory') group.add_argument('--runtime-deps-path') group.add_argument('--test-apk') group.add_argument('--test-jar') - group.add_argument('--test-apk-incremental-install-script') + group.add_argument('--test-apk-incremental-install-json') group.add_argument('--coverage-dir') group.add_argument('--android-manifest-path') group.add_argument('--resource-zips') @@ -112,11 +112,11 @@ if args.apk_under_test: test_runner_path_args.append( ('--apk-under-test', RelativizePathToScript(args.apk_under_test))) - if args.apk_under_test_incremental_install_script: + if args.apk_under_test_incremental_install_json: test_runner_path_args.append( - ('--apk-under-test-incremental-install-script', + ('--apk-under-test-incremental-install-json', RelativizePathToScript( - args.apk_under_test_incremental_install_script))) + args.apk_under_test_incremental_install_json))) if args.executable_dist_dir: test_runner_path_args.append( ('--executable-dist-dir', @@ -136,10 +136,10 @@ if args.test_jar: test_runner_path_args.append( ('--test-jar', RelativizePathToScript(args.test_jar))) - if args.test_apk_incremental_install_script: + if args.test_apk_incremental_install_json: test_runner_path_args.append( - ('--test-apk-incremental-install-script', - RelativizePathToScript(args.test_apk_incremental_install_script))) + ('--test-apk-incremental-install-json', + RelativizePathToScript(args.test_apk_incremental_install_json))) if args.coverage_dir: test_runner_path_args.append( ('--coverage-dir', RelativizePathToScript(args.coverage_dir)))
diff --git a/build/android/gyp/desugar.py b/build/android/gyp/desugar.py index 6455279..bf51b007 100755 --- a/build/android/gyp/desugar.py +++ b/build/android/gyp/desugar.py
@@ -6,9 +6,7 @@ import argparse import os -import shutil import sys -import tempfile from util import build_utils @@ -30,10 +28,9 @@ bootclasspath_entry, '--output', output_jar, - # Disable try-with-resources due to proguard duplicate zip entry error - # TODO(zpeng): Enable try-with-resources with - # desugar_try_with_resources_omit_runtime_classes - '--desugar_try_with_resources_if_needed=false', + # Don't include try-with-resources files in every .jar. Instead, they + # are included via //third_party/bazel/desugar:desugar_runtime_java. + '--desugar_try_with_resources_omit_runtime_classes', ] for path in classpath: cmd += ['--classpath_entry', path]
diff --git a/build/android/gyp/javac.py b/build/android/gyp/javac.py index adeed36..3ca6bd5 100755 --- a/build/android/gyp/javac.py +++ b/build/android/gyp/javac.py
@@ -371,8 +371,11 @@ if options.java_version == '1.8' and options.bootclasspath: # Android's boot jar doesn't contain all java 8 classes. # See: https://github.com/evant/gradle-retrolambda/issues/23. - javac_path = os.path.realpath(distutils.spawn.find_executable('javac')) - jdk_dir = os.path.dirname(os.path.dirname(javac_path)) + # Get the path of the jdk folder by searching for the 'jar' executable. We + # cannot search for the 'javac' executable because goma provides a custom + # version of 'javac'. + jar_path = os.path.realpath(distutils.spawn.find_executable('jar')) + jdk_dir = os.path.dirname(os.path.dirname(jar_path)) rt_jar = os.path.join(jdk_dir, 'jre', 'lib', 'rt.jar') options.bootclasspath.append(rt_jar)
diff --git a/build/android/lint/suppressions.xml b/build/android/lint/suppressions.xml index 7ad4dde..6f2698fd 100644 --- a/build/android/lint/suppressions.xml +++ b/build/android/lint/suppressions.xml
@@ -193,6 +193,8 @@ <issue id="NewApi" severity="ignore"/> <issue id="NewApi"> <ignore regexp="Attribute `paddingStart` referenced here can result in a crash on some specific devices older than API 17"/> + <!-- We support try-with-resources via desugar. --> + <ignore regexp="Try-with-resources requires API level 19"/> <ignore regexp="chrome/android/java/res/values-v17/styles.xml"/> <ignore regexp="chromecast/internal"/> <ignore regexp="com/android/tv"/>
diff --git a/build/android/pylib/utils/instrumentation_tracing.py b/build/android/pylib/utils/instrumentation_tracing.py index fe23894..7e00c58 100644 --- a/build/android/pylib/utils/instrumentation_tracing.py +++ b/build/android/pylib/utils/instrumentation_tracing.py
@@ -4,7 +4,15 @@ """Functions to instrument all Python function calls. -Generates a JSON file readable by Chrome's about:tracing.""" +This generates a JSON file readable by Chrome's about:tracing. To use it, +either call start_instrumenting and stop_instrumenting at the appropriate times, +or use the Instrument context manager. + +A function is only traced if it is from a Python module that matches at least +one regular expression object in to_include, and does not match any in +to_exclude. In between the start and stop events, every function call of a +function from such a module will be added to the trace. +""" import contextlib import functools
diff --git a/build/android/test_runner.pydeps b/build/android/test_runner.pydeps index 1d03946..573577e 100644 --- a/build/android/test_runner.pydeps +++ b/build/android/test_runner.pydeps
@@ -71,6 +71,7 @@ ../../third_party/catapult/devil/devil/utils/host_utils.py ../../third_party/catapult/devil/devil/utils/lazy/__init__.py ../../third_party/catapult/devil/devil/utils/lazy/weak_constant.py +../../third_party/catapult/devil/devil/utils/logging_common.py ../../third_party/catapult/devil/devil/utils/lsusb.py ../../third_party/catapult/devil/devil/utils/parallelizer.py ../../third_party/catapult/devil/devil/utils/reraiser_thread.py
diff --git a/build/config/android/config.gni b/build/config/android/config.gni index 1ff5744..8135f242 100644 --- a/build/config/android/config.gni +++ b/build/config/android/config.gni
@@ -80,7 +80,7 @@ } webview_public_framework_jar = - "//third_party/android_platform/webview/frameworks_7.1.1_r28.jar" + "//third_party/android_system_sdk/android_system.jar" if (!defined(webview_framework_jar)) { webview_framework_jar = webview_public_framework_jar }
diff --git a/build/mac_toolchain.py b/build/mac_toolchain.py index 3852dba..50f2ef6 100755 --- a/build/mac_toolchain.py +++ b/build/mac_toolchain.py
@@ -13,6 +13,7 @@ user interaction. """ +from distutils.version import LooseVersion import os import platform import plistlib @@ -132,10 +133,11 @@ os.unlink(name) -def AcceptLicense(target_os): - """Use xcodebuild to accept new toolchain license if necessary. Don't accept - the license if a newer license has already been accepted. This only works if - xcodebuild and xcode-select are passwordless in sudoers.""" +def FinalizeUnpack(target_os): + """Use xcodebuild to accept new toolchain license and run first launch + installers if necessary. Don't accept the license if a newer license has + already been accepted. This only works if xcodebuild and xcode-select are + passwordless in sudoers.""" # Check old license try: @@ -164,6 +166,11 @@ pass print "Accepting license." + target_version_plist_path = \ + os.path.join(TOOLCHAIN_BUILD_DIR % target_os, + *['Contents','version.plist']) + target_version_plist = LoadPlist(target_version_plist_path) + short_version_string = target_version_plist['CFBundleShortVersionString'] old_path = subprocess.Popen(['/usr/bin/xcode-select', '-p'], stdout=subprocess.PIPE).communicate()[0].strip() try: @@ -171,6 +178,11 @@ TOOLCHAIN_BUILD_DIR % target_os, 'Contents/Developer') subprocess.check_call(['sudo', '/usr/bin/xcode-select', '-s', build_dir]) subprocess.check_call(['sudo', '/usr/bin/xcodebuild', '-license', 'accept']) + + if target_os == 'ios' and \ + LooseVersion(short_version_string) >= LooseVersion("9.0"): + print "Installing packages." + subprocess.check_call(['sudo', '/usr/bin/xcodebuild', '-runFirstLaunch']) finally: subprocess.check_call(['sudo', '/usr/bin/xcode-select', '-s', old_path]) @@ -216,7 +228,7 @@ if ReadStampFile(target_os) == toolchain_version: print 'Toolchain (%s) is already up to date.' % toolchain_version - AcceptLicense(target_os) + FinalizeUnpack(target_os) return 0 if not CanAccessToolchainBucket(): @@ -234,7 +246,7 @@ toolchain_file = toolchain_filename % toolchain_version toolchain_full_url = TOOLCHAIN_URL + toolchain_file DownloadAndUnpack(toolchain_full_url, TOOLCHAIN_BUILD_DIR % target_os) - AcceptLicense(target_os) + FinalizeUnpack(target_os) print 'Toolchain %s unpacked.' % toolchain_version WriteStampFile(target_os, toolchain_version)
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc index cbeeee4..182b8c21 100644 --- a/build/sanitizers/tsan_suppressions.cc +++ b/build/sanitizers/tsan_suppressions.cc
@@ -265,10 +265,6 @@ // "race:third_party/harfbuzz-ng/src/*\n" - // TODO(asvitkine): Remove these after crbug/736675. - "race:base::Histogram::AddCount\n" - "race:AddCount\n" - // End of suppressions. ; // Please keep this semicolon.
diff --git a/build/vs_toolchain.py b/build/vs_toolchain.py index 6555127..88dda3b 100755 --- a/build/vs_toolchain.py +++ b/build/vs_toolchain.py
@@ -328,13 +328,18 @@ if not win_sdk_dir: return - debug_files = ['dbghelp.dll', 'dbgcore.dll'] - for debug_file in debug_files: + # List of debug files that should be copied, the first element of the tuple is + # the name of the file and the second indicates if it's optional. + debug_files = [('dbghelp.dll', False), ('dbgcore.dll', True)] + for debug_file, is_optional in debug_files: full_path = os.path.join(win_sdk_dir, 'Debuggers', target_cpu, debug_file) if not os.path.exists(full_path): - raise Exception('%s not found in "%s"\r\nYou must install the ' - '"Debugging Tools for Windows" feature from the Windows ' - '10 SDK.' % (debug_file, full_path)) + if is_optional: + continue + else: + raise Exception('%s not found in "%s"\r\nYou must install the ' + '"Debugging Tools for Windows" feature from the Windows' + ' 10 SDK.' % (debug_file, full_path)) target_path = os.path.join(target_dir, debug_file) _CopyRuntimeImpl(target_path, full_path)
diff --git a/cc/base/synced_property.h b/cc/base/synced_property.h index f0ff329..6b8b91e 100644 --- a/cc/base/synced_property.h +++ b/cc/base/synced_property.h
@@ -62,31 +62,39 @@ } // Push the latest value from the main thread onto pending tree-associated - // state. Returns true if this had any effect. - bool PushFromMainThread(typename T::ValueType main_thread_value) { - bool changed = pending_base_.get() != main_thread_value; - + // state. Returns true if pushing the value results in different values + // between the main layer tree and the pending tree. + bool PushMainToPending(typename T::ValueType main_thread_value) { reflected_delta_in_pending_tree_ = reflected_delta_in_main_tree_; reflected_delta_in_main_tree_ = T::Identity(); pending_base_ = T(main_thread_value); - return changed; + return Current(false) != main_thread_value; } // Push the value associated with the pending tree to be the active base - // value. As part of this, subtract the delta reflected in the pending tree + // value. As part of this, subtract the delta reflected in the pending tree // from the active tree delta (which will make the delta zero at steady state, // or make it contain only the difference since the last send). + // Returns true if pushing the update results in: + // 1) Different values on the pending tree and the active tree. + // 2) An update to the current value on the active tree. + // The reason for considering the second case only when pushing to the active + // tree, as opposed to when pushing to the pending tree, is that only the + // active tree computes state using this value which is not computed on the + // pending tree and not pushed during activation (aka scrollbar geometries). bool PushPendingToActive() { - bool changed = active_base_.get() != pending_base_.get() || - active_delta_.get() != PendingDelta().get(); + typename T::ValueType pending_value_before_push = Current(false); + typename T::ValueType active_value_before_push = Current(true); active_base_ = pending_base_; active_delta_ = PendingDelta(); reflected_delta_in_pending_tree_ = T::Identity(); clobber_active_value_ = false; - return changed; + typename T::ValueType current_active_value = Current(true); + return pending_value_before_push != current_active_value || + active_value_before_push != current_active_value; } // This simulates the consequences of the sent value getting committed and
diff --git a/cc/ipc/BUILD.gn b/cc/ipc/BUILD.gn index 1f42567..4dfd33aa 100644 --- a/cc/ipc/BUILD.gn +++ b/cc/ipc/BUILD.gn
@@ -48,7 +48,6 @@ "local_surface_id.mojom", "quads.mojom", "selection.mojom", - "shared_bitmap_allocation_notifier.mojom", "shared_quad_state.mojom", "surface_id.mojom", "texture_mailbox.mojom",
diff --git a/cc/paint/paint_op_reader.cc b/cc/paint/paint_op_reader.cc index 0ebedc1..cd1e43e 100644 --- a/cc/paint/paint_op_reader.cc +++ b/cc/paint/paint_op_reader.cc
@@ -248,7 +248,11 @@ } ref.positions_.resize(positions_size); ReadData(positions_size * sizeof(SkScalar), ref.positions_.data()); + // We don't write the cached shader, so don't attempt to read it either. + + if (!(*shader)->IsValid()) + valid_ = false; } bool PaintOpReader::AlignMemory(size_t alignment) {
diff --git a/cc/paint/paint_shader.cc b/cc/paint/paint_shader.cc index c5138268..7d5d710 100644 --- a/cc/paint/paint_shader.cc +++ b/cc/paint/paint_shader.cc
@@ -245,4 +245,28 @@ return GetSkShader()->isOpaque(); } +bool PaintShader::IsValid() const { + // If we managed to create a shader already, then we should be valid. + if (cached_shader_) + return true; + + switch (shader_type_) { + case Type::kColor: + return true; + case Type::kLinearGradient: + case Type::kRadialGradient: + case Type::kTwoPointConicalGradient: + case Type::kSweepGradient: + return colors_.size() >= 2 && + (positions_.empty() || positions_.size() == colors_.size()); + case Type::kImage: + return !!image_; + case Type::kPaintRecord: + return !!record_; + case Type::kShaderCount: + return false; + } + return false; +} + } // namespace cc
diff --git a/cc/paint/paint_shader.h b/cc/paint/paint_shader.h index 65ab74d..8a133709 100644 --- a/cc/paint/paint_shader.h +++ b/cc/paint/paint_shader.h
@@ -116,6 +116,12 @@ bool IsOpaque() const; + // Returns true if the shader looks like it is valid (ie the members required + // for this shader type all look reasonable. Returns false otherwise. Note + // that this is a best effort function since truly validating whether the + // shader is correct is hard. + bool IsValid() const; + private: friend class PaintFlags; friend class PaintOpReader;
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index 10b3be3..f34b3a4 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc
@@ -1256,7 +1256,7 @@ tree_impl->set_top_controls_height(top_controls_height_); tree_impl->set_bottom_controls_height(bottom_controls_height_); tree_impl->PushBrowserControlsFromMainThread(top_controls_shown_ratio_); - tree_impl->elastic_overscroll()->PushFromMainThread(elastic_overscroll_); + tree_impl->elastic_overscroll()->PushMainToPending(elastic_overscroll_); if (tree_impl->IsActiveTree()) tree_impl->elastic_overscroll()->PushPendingToActive();
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 77e3137..eddb892 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -4979,7 +4979,7 @@ DrawFrame(); host_impl_->active_tree()->SetCurrentBrowserControlsShownRatio(0.f); - host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread( + host_impl_->active_tree()->top_controls_shown_ratio()->PushMainToPending( 30.f / top_controls_height_); host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive(); EXPECT_FLOAT_EQ(30.f, @@ -5013,7 +5013,7 @@ layer_size_, layer_size_, layer_size_); DrawFrame(); - host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread( + host_impl_->active_tree()->top_controls_shown_ratio()->PushMainToPending( 20.f / top_controls_height_); host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive(); host_impl_->active_tree()->SetCurrentBrowserControlsShownRatio( @@ -5066,8 +5066,7 @@ host_impl_->sync_tree()->PushBrowserControlsFromMainThread(1.f); host_impl_->sync_tree()->set_browser_controls_shrink_blink_size(true); - host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread( - 1.f); + host_impl_->active_tree()->top_controls_shown_ratio()->PushMainToPending(1.f); host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive(); host_impl_->active_tree()->SetCurrentBrowserControlsShownRatio(0.f); @@ -5432,7 +5431,7 @@ host_impl_->active_tree() ->top_controls_shown_ratio() ->PullDeltaForMainThread(); - host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread( + host_impl_->active_tree()->top_controls_shown_ratio()->PushMainToPending( delta); } @@ -12392,7 +12391,7 @@ // When building property trees from impl side, the builder uses the scroll // offset of layer_impl to initialize the scroll offset in scroll tree: - // scroll_tree.synced_scroll_offset.PushFromMainThread( + // scroll_tree.synced_scroll_offset.PushMainToPending( // layer->CurrentScrollOffset()). // However, layer_impl does not store scroll_offset, so it is using scroll // tree's scroll offset to initialize itself. Usually this approach works
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index ad5557d..2bc0189 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc
@@ -755,26 +755,14 @@ if (page_scale_factor) { DCHECK(!IsActiveTree() || !layer_tree_host_impl_->pending_tree()); - changed_page_scale |= page_scale_factor_->Delta() != 1.f; - // TODO(enne): Once CDP goes away, ignore this call below. The only time - // the property trees will differ is if there's been a page scale on the - // compositor thread after the begin frame, which is the delta check above. changed_page_scale |= - page_scale_factor_->PushFromMainThread(*page_scale_factor); + page_scale_factor_->PushMainToPending(*page_scale_factor); } if (IsActiveTree()) { - // TODO(enne): Pushing from pending to active should never require - // DidUpdatePageScale. The values should already be set by the fully - // computed property trees being synced from one tree to another. Remove - // this once CDP goes away. changed_page_scale |= page_scale_factor_->PushPendingToActive(); } - // TODO(pdr): Simplify the logic here and the equivalent logic in - // ScrollTree::PushScrollUpdatesFromMainThread where two types of changes - // are detected: whether the current value changed, and whether the pushes - // have any effect. if (changed_page_scale) DidUpdatePageScale(); @@ -840,7 +828,7 @@ if (top_controls_shown_ratio) { DCHECK(!IsActiveTree() || !layer_tree_host_impl_->pending_tree()); - top_controls_shown_ratio_->PushFromMainThread(*top_controls_shown_ratio); + top_controls_shown_ratio_->PushMainToPending(*top_controls_shown_ratio); } if (IsActiveTree()) { bool changed_active = top_controls_shown_ratio_->PushPendingToActive();
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc index 88492b90..e3096fb7 100644 --- a/cc/trees/property_tree.cc +++ b/cc/trees/property_tree.cc
@@ -1413,21 +1413,22 @@ SyncedScrollOffset* synced_scroll_offset = GetOrCreateSyncedScrollOffset(id); - bool changed = synced_scroll_offset->PushFromMainThread(map_entry.second); + // If the value on the main thread differs from the value on the pending + // tree after state sync, we need to update the scroll state on the newly + // committed PropertyTrees. + bool needs_scroll_update = + synced_scroll_offset->PushMainToPending(map_entry.second); // If we are committing directly to the active tree, push pending to active - // here. + // here. If the value differs between the pending and active trees, we need + // to update the scroll state on the newly activated PropertyTrees. + // In the case of pushing to the active tree, even if the pending and active + // tree state match but the value on the active tree changed, we need to + // update the scrollbar geometries. if (property_trees()->is_active) - changed |= synced_scroll_offset->PushPendingToActive(); + needs_scroll_update |= synced_scroll_offset->PushPendingToActive(); - // If the pushed main thread scroll offset differs from the current scroll - // offset (accounting for delta), ensure DidUpdateScrollOffset is called to - // update the TransformNode's scroll offset. We also need to ensure - // scrollbar geometries are updated if the underlying scroll offset changes. - // TODO(pdr): This is confusing because we need to account for multiple - // cases where the value is dirty. - if (changed || map_entry.second != synced_scroll_offset->Current( - property_trees()->is_active)) + if (needs_scroll_update) sync_tree->DidUpdateScrollOffset(id); } } @@ -1457,17 +1458,17 @@ map_entry.second->AbortCommit(); } -bool ScrollTree::SetBaseScrollOffset(ElementId id, +void ScrollTree::SetBaseScrollOffset(ElementId id, const gfx::ScrollOffset& scroll_offset) { if (property_trees()->is_main_thread) { scroll_offset_map_[id] = scroll_offset; - return true; + return; } // Scroll offset updates on the impl thread should only be for layers which // were created on the main thread. But this method is called when we build // PropertyTrees on the impl thread from LayerTreeImpl. - return GetOrCreateSyncedScrollOffset(id)->PushFromMainThread(scroll_offset); + GetOrCreateSyncedScrollOffset(id)->PushMainToPending(scroll_offset); } bool ScrollTree::SetScrollOffset(ElementId id, @@ -1491,7 +1492,7 @@ const gfx::ScrollOffset& offset) { DCHECK(!property_trees()->is_main_thread); SyncedScrollOffset* synced_scroll_offset = GetOrCreateSyncedScrollOffset(id); - bool changed = synced_scroll_offset->PushFromMainThread(offset); + bool changed = synced_scroll_offset->PushMainToPending(offset); if (property_trees()->is_active) changed |= synced_scroll_offset->PushPendingToActive(); return changed;
diff --git a/cc/trees/property_tree.h b/cc/trees/property_tree.h index 60f88e4..22ac11c 100644 --- a/cc/trees/property_tree.h +++ b/cc/trees/property_tree.h
@@ -429,7 +429,7 @@ void PushScrollUpdatesFromPendingTree(PropertyTrees* pending_property_trees, LayerTreeImpl* active_tree); - bool SetBaseScrollOffset(ElementId id, + void SetBaseScrollOffset(ElementId id, const gfx::ScrollOffset& scroll_offset); bool SetScrollOffset(ElementId id, const gfx::ScrollOffset& scroll_offset); void SetScrollOffsetClobberActiveValue(ElementId id) {
diff --git a/cc/trees/tree_synchronizer_unittest.cc b/cc/trees/tree_synchronizer_unittest.cc index daf5888..6753d9e 100644 --- a/cc/trees/tree_synchronizer_unittest.cc +++ b/cc/trees/tree_synchronizer_unittest.cc
@@ -572,7 +572,7 @@ // the pending base and active base must be the same at this stage. scoped_refptr<SyncedScrollOffset> scroll_layer_offset = new SyncedScrollOffset; - scroll_layer_offset->PushFromMainThread(scroll_layer->scroll_offset()); + scroll_layer_offset->PushMainToPending(scroll_layer->scroll_offset()); scroll_layer_offset->PushPendingToActive(); EXPECT_TRUE(AreScrollOffsetsEqual( scroll_layer_offset.get(), @@ -582,7 +582,7 @@ scoped_refptr<SyncedScrollOffset> transient_scroll_layer_offset = new SyncedScrollOffset; - transient_scroll_layer_offset->PushFromMainThread( + transient_scroll_layer_offset->PushMainToPending( transient_scroll_layer->scroll_offset()); transient_scroll_layer_offset->PushPendingToActive(); EXPECT_TRUE( @@ -628,7 +628,7 @@ scroll_layer_offset->SetCurrent(gfx::ScrollOffset(20, 30)); scroll_layer_offset->PullDeltaForMainThread(); scroll_layer_offset->SetCurrent(gfx::ScrollOffset(40, 50)); - scroll_layer_offset->PushFromMainThread(gfx::ScrollOffset(100, 100)); + scroll_layer_offset->PushMainToPending(gfx::ScrollOffset(100, 100)); scroll_layer_offset->PushPendingToActive(); EXPECT_TRUE(AreScrollOffsetsEqual( scroll_layer_offset.get(),
diff --git a/chrome/VERSION b/chrome/VERSION index d326ec9..97a8eb6 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=62 MINOR=0 -BUILD=3183 +BUILD=3184 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java index faba0f76..a31031c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java
@@ -33,7 +33,6 @@ import android.widget.ImageButton; import android.widget.ListView; import android.widget.PopupWindow; -import android.widget.PopupWindow.OnDismissListener; import org.chromium.base.AnimationFrameTimeHistogram; import org.chromium.base.ApiCompatibilityUtils; @@ -177,18 +176,15 @@ boolean anchorAtBottom = isAnchorAtBottom(anchorView, visibleDisplayFrame); int footerHeight = 0; - mPopup.setOnDismissListener(new OnDismissListener() { - @Override - public void onDismiss() { - if (anchorView instanceof ImageButton) { - ((ImageButton) anchorView).setSelected(false); - } - - if (mMenuItemEnterAnimator != null) mMenuItemEnterAnimator.cancel(); - - mHandler.appMenuDismissed(); - mHandler.onMenuVisibilityChanged(false); + mPopup.setOnDismissListener(() -> { + if (anchorView instanceof ImageButton) { + ((ImageButton) anchorView).setSelected(false); } + + if (mMenuItemEnterAnimator != null) mMenuItemEnterAnimator.cancel(); + + mHandler.appMenuDismissed(); + mHandler.onMenuVisibilityChanged(false); }); // Some OEMs don't actually let us change the background... but they still return the
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java index b3e00ae..7d26ac8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java
@@ -15,7 +15,6 @@ import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; -import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; @@ -258,12 +257,7 @@ holder.title.setText(titleItem.getTitle()); holder.title.setEnabled(titleItem.isEnabled()); holder.title.setFocusable(titleItem.isEnabled()); - holder.title.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - mAppMenu.onItemClick(titleItem); - } - }); + holder.title.setOnClickListener(v -> mAppMenu.onItemClick(titleItem)); if (subItem.isCheckable()) { // Display a checkbox for the MenuItem. @@ -330,19 +324,9 @@ button.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); } - button.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - mAppMenu.onItemClick(item); - } - }); + button.setOnClickListener(v -> mAppMenu.onItemClick(item)); - button.setOnLongClickListener(new View.OnLongClickListener() { - @Override - public boolean onLongClick(View v) { - return mAppMenu.onItemLongClick(item, v); - } - }); + button.setOnLongClickListener(v -> mAppMenu.onItemLongClick(item, v)); highlightItemIfNecessary(button, true, item.getItemId()); @@ -366,12 +350,7 @@ // This will ensure that the item is not highlighted when selected. convertView.setEnabled(isEnabled); - convertView.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - mAppMenu.onItemClick(item); - } - }); + convertView.setOnClickListener(v -> mAppMenu.onItemClick(item)); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuDragHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuDragHelper.java index 1f87c978..9fdbad7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuDragHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuDragHelper.java
@@ -68,24 +68,21 @@ // If user is dragging and the popup ListView is too big to display at once, // mDragScrolling animator scrolls mPopup.getListView() automatically depending on // the user's touch position. - mDragScrolling.setTimeListener(new TimeAnimator.TimeListener() { - @Override - public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) { - if (mAppMenu.getListView() == null) return; + mDragScrolling.setTimeListener((animation, totalTime, deltaTime) -> { + if (mAppMenu.getListView() == null) return; - // We keep both mDragScrollOffset and mDragScrollOffsetRounded because - // the actual scrolling is by the rounded value but at the same time we also - // want to keep the precise scroll value in float. - mDragScrollOffset += (deltaTime * 0.001f) * mDragScrollingVelocity; - int diff = Math.round(mDragScrollOffset - mDragScrollOffsetRounded); - mDragScrollOffsetRounded += diff; - mAppMenu.getListView().smoothScrollBy(diff, 0); + // We keep both mDragScrollOffset and mDragScrollOffsetRounded because + // the actual scrolling is by the rounded value but at the same time we also + // want to keep the precise scroll value in float. + mDragScrollOffset += (deltaTime * 0.001f) * mDragScrollingVelocity; + int diff = Math.round(mDragScrollOffset - mDragScrollOffsetRounded); + mDragScrollOffsetRounded += diff; + mAppMenu.getListView().smoothScrollBy(diff, 0); - // Force touch move event to highlight items correctly for the scrolled position. - if (!Float.isNaN(mLastTouchX) && !Float.isNaN(mLastTouchY)) { - menuItemAction(Math.round(mLastTouchX), Math.round(mLastTouchY), - ITEM_ACTION_HIGHLIGHT); - } + // Force touch move event to highlight items correctly for the scrolled position. + if (!Float.isNaN(mLastTouchX) && !Float.isNaN(mLastTouchY)) { + menuItemAction(Math.round(mLastTouchX), Math.round(mLastTouchY), + ITEM_ACTION_HIGHLIGHT); } });
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java index 60ea19a2..92fe2be 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java
@@ -43,12 +43,7 @@ mContext = null; // Clean up the native counterpart. This is posted to allow the native counterpart // to fully finish the construction of this glue object before we attempt to delete it. - new Handler().post(new Runnable() { - @Override - public void run() { - dismissed(); - } - }); + new Handler().post(() -> dismissed()); } else { mAutofillPopup = new AutofillPopup(activity, anchorView, this); mContext = activity;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskBridge.java index 73d1e979..774eca29 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskBridge.java
@@ -32,12 +32,7 @@ mCardUnmaskPrompt = null; // Clean up the native counterpart. This is posted to allow the native counterpart // to fully finish the construction of this glue object before we attempt to delete it. - new Handler().post(new Runnable() { - @Override - public void run() { - dismissed(); - } - }); + new Handler().post(() -> dismissed()); } else { mCardUnmaskPrompt = new CardUnmaskPrompt(activity, this, title, instructions, confirmButtonLabel, ResourceId.mapToDrawableId(iconId),
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskPrompt.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskPrompt.java index 0212c7d..c712cfbd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskPrompt.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskPrompt.java
@@ -21,11 +21,9 @@ import android.text.Editable; import android.text.InputFilter; import android.text.TextWatcher; -import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; -import android.view.View.OnFocusChangeListener; import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.view.inputmethod.EditorInfo; @@ -213,39 +211,27 @@ new InputFilter[] {new InputFilter.LengthFilter(mDelegate.getExpectedCvcLength())}); // Hitting the "submit" button on the software keyboard should submit the form if valid. - mCardUnmaskInput.setOnEditorActionListener(new TextView.OnEditorActionListener() { - @Override - public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - if (actionId == EditorInfo.IME_ACTION_DONE) { - Button positiveButton = mDialog.getButton(AlertDialog.BUTTON_POSITIVE); - if (positiveButton.isEnabled()) positiveButton.performClick(); - return true; - } - return false; + mCardUnmaskInput.setOnEditorActionListener((v14, actionId, event) -> { + if (actionId == EditorInfo.IME_ACTION_DONE) { + Button positiveButton = mDialog.getButton(AlertDialog.BUTTON_POSITIVE); + if (positiveButton.isEnabled()) positiveButton.performClick(); + return true; } + return false; }); // Create the listeners to be notified when the user focuses out the input fields. - mCardUnmaskInput.setOnFocusChangeListener(new OnFocusChangeListener() { - @Override - public void onFocusChange(View v, boolean hasFocus) { - mDidFocusOnCvc = true; - validate(); - } + mCardUnmaskInput.setOnFocusChangeListener((v13, hasFocus) -> { + mDidFocusOnCvc = true; + validate(); }); - mMonthInput.setOnFocusChangeListener(new OnFocusChangeListener() { - @Override - public void onFocusChange(View v, boolean hasFocus) { - mDidFocusOnMonth = true; - validate(); - } + mMonthInput.setOnFocusChangeListener((v12, hasFocus) -> { + mDidFocusOnMonth = true; + validate(); }); - mYearInput.setOnFocusChangeListener(new OnFocusChangeListener() { - @Override - public void onFocusChange(View v, boolean hasFocus) { - mDidFocusOnYear = true; - validate(); - } + mYearInput.setOnFocusChangeListener((v1, hasFocus) -> { + mDidFocusOnYear = true; + validate(); }); // Load the error messages to show to the user. @@ -288,23 +274,14 @@ // the dialog. Button verifyButton = mDialog.getButton(AlertDialog.BUTTON_POSITIVE); verifyButton.setEnabled(false); - verifyButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - mDelegate.onUserInput(mCardUnmaskInput.getText().toString(), + verifyButton.setOnClickListener( + view -> mDelegate.onUserInput(mCardUnmaskInput.getText().toString(), mMonthInput.getText().toString(), Integer.toString(getFourDigitYear()), - mStoreLocallyCheckbox != null && mStoreLocallyCheckbox.isChecked()); - } - }); + mStoreLocallyCheckbox != null && mStoreLocallyCheckbox.isChecked())); mCardUnmaskInput.addTextChangedListener(this); - mCardUnmaskInput.post(new Runnable() { - @Override - public void run() { - setInitialFocus(); - } - }); + mCardUnmaskInput.post(() -> setInitialFocus()); } public void update(String title, String instructions, boolean shouldRequestExpirationDate) { @@ -345,12 +322,7 @@ setNoRetryError(errorMessage); } } else { - Runnable dismissRunnable = new Runnable() { - @Override - public void run() { - dismiss(); - } - }; + Runnable dismissRunnable = () -> dismiss(); if (mSuccessMessageDurationMilliseconds > 0) { mVerificationProgressBar.setVisibility(View.GONE); mDialog.findViewById(R.id.verification_success).setVisibility(View.VISIBLE); @@ -453,17 +425,9 @@ mStoreLocallyTooltipPopup.setOutsideTouchable(true); mStoreLocallyTooltipPopup.setBackgroundDrawable(ApiCompatibilityUtils.getDrawable( resources, R.drawable.store_locally_tooltip_background)); - mStoreLocallyTooltipPopup.setOnDismissListener(new PopupWindow.OnDismissListener() { - @Override - public void onDismiss() { - Handler h = new Handler(); - h.postDelayed(new Runnable() { - @Override - public void run() { - mStoreLocallyTooltipPopup = null; - } - }, 200); - } + mStoreLocallyTooltipPopup.setOnDismissListener(() -> { + Handler h = new Handler(); + h.postDelayed(() -> mStoreLocallyTooltipPopup = null, 200); }); mStoreLocallyTooltipPopup.showAsDropDown(mStoreLocallyCheckbox, ViewCompat.getPaddingStart(mStoreLocallyCheckbox), 0);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/PasswordGenerationPopupBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/PasswordGenerationPopupBridge.java index 2c3654cd2..85b976c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/PasswordGenerationPopupBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/PasswordGenerationPopupBridge.java
@@ -54,12 +54,7 @@ mPopup = null; // Prevent destroying the native counterpart when it's about to derefence its own // members in UpdateBoundsAndRedrawPopup(). - new Handler().post(new Runnable() { - @Override - public void run() { - onDismiss(); - } - }); + new Handler().post(() -> onDismiss()); } else { mPopup = new DropdownPopupWindow(mContext, anchorView); mPopup.setOnItemClickListener(this);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java index 261ef68..128c5df 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -28,6 +28,7 @@ import android.os.SystemClock; import android.provider.Settings; import android.speech.RecognizerIntent; +import android.support.annotation.DrawableRes; import android.support.annotation.IntDef; import android.text.InputType; import android.text.TextUtils; @@ -164,6 +165,7 @@ private NavigationButtonType mNavigationButtonType; // The type of the security icon currently active. + @DrawableRes private int mSecurityIconResource; private final OmniboxResultsAdapter mSuggestionListAdapter; @@ -1306,6 +1308,7 @@ * @param isOfflinePage Whether the page for which the icon is shown is an offline page. * @return The resource ID of the icon that should be displayed, 0 if no icon should show. */ + @DrawableRes public static int getSecurityIconResource( int securityLevel, boolean isSmallDevice, boolean isOfflinePage) { if (isOfflinePage) { @@ -1370,6 +1373,7 @@ @Override public void updateSecurityIcon(int securityLevel) { boolean isSmallDevice = !DeviceFormFactor.isTablet(); + @DrawableRes int id = getSecurityIconResource( securityLevel, isSmallDevice, mToolbarDataProvider.isOfflinePage()); if (id == 0) { @@ -1422,6 +1426,15 @@ } /** + * @return The ID of the drawable currently shown in the security icon. + */ + @VisibleForTesting + @DrawableRes + int getSecurityIconResourceId() { + return mSecurityIconResource; + } + + /** * Sets the type of the current navigation type and updates the UI to match it. * @param buttonType The type of navigation button to be shown. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/AddressEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/AddressEditor.java index cec5022..57dc10e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/AddressEditor.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/AddressEditor.java
@@ -189,28 +189,22 @@ // If the user clicks [Cancel], send |toEdit| address back to the caller, which was the // original state (could be null, a complete address, a partial address). - mEditor.setCancelCallback(new Runnable() { - @Override - public void run() { - // This makes sure that onSubKeysReceived returns early if it's - // ever called when Cancel has already occurred. - mAdminAreasLoaded = true; - PersonalDataManager.getInstance().cancelPendingGetSubKeys(); - callback.onResult(toEdit); - } + mEditor.setCancelCallback(() -> { + // This makes sure that onSubKeysReceived returns early if it's + // ever called when Cancel has already occurred. + mAdminAreasLoaded = true; + PersonalDataManager.getInstance().cancelPendingGetSubKeys(); + callback.onResult(toEdit); }); // If the user clicks [Done], save changes on disk, mark the address "complete," and send it // back to the caller. - mEditor.setDoneCallback(new Runnable() { - @Override - public void run() { - mAdminAreasLoaded = true; - PersonalDataManager.getInstance().cancelPendingGetSubKeys(); - commitChanges(mProfile); - address.completeAddress(mProfile); - callback.onResult(address); - } + mEditor.setDoneCallback(() -> { + mAdminAreasLoaded = true; + PersonalDataManager.getInstance().cancelPendingGetSubKeys(); + commitChanges(mProfile); + address.completeAddress(mProfile); + callback.onResult(address); }); loadAdminAreasForCountry(mProfile.getCountryCode());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentApp.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentApp.java index 6f8bfbe3..0777a1a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentApp.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentApp.java
@@ -7,8 +7,6 @@ import android.app.Activity; import android.content.ComponentName; import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnCancelListener; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.ServiceConnection; @@ -183,11 +181,8 @@ return; } - mHandler.postDelayed(new Runnable() { - @Override - public void run() { - if (!mIsReadyToPayQueried) respondToGetInstrumentsQuery(null); - } + mHandler.postDelayed(() -> { + if (!mIsReadyToPayQueried) respondToGetInstrumentsQuery(null); }, SERVICE_CONNECTION_TIMEOUT_MS); } @@ -198,19 +193,16 @@ } if (mInstrumentsCallback == null) return; - mHandler.post(new Runnable() { - @Override - public void run() { - ThreadUtils.assertOnUiThread(); - if (mInstrumentsCallback == null) return; - List<PaymentInstrument> instruments = null; - if (instrument != null) { - instruments = new ArrayList<>(); - instruments.add(instrument); - } - mInstrumentsCallback.onInstrumentsReady(AndroidPaymentApp.this, instruments); - mInstrumentsCallback = null; + mHandler.post(() -> { + ThreadUtils.assertOnUiThread(); + if (mInstrumentsCallback == null) return; + List<PaymentInstrument> instruments = null; + if (instrument != null) { + instruments = new ArrayList<>(); + instruments.add(instrument); } + mInstrumentsCallback.onInstrumentsReady(AndroidPaymentApp.this, instruments); + mInstrumentsCallback = null; }); } @@ -235,12 +227,7 @@ respondToGetInstrumentsQuery(null); return; } - mHandler.postDelayed(new Runnable() { - @Override - public void run() { - respondToGetInstrumentsQuery(null); - } - }, READY_TO_PAY_TIMEOUT_MS); + mHandler.postDelayed(() -> respondToGetInstrumentsQuery(null), READY_TO_PAY_TIMEOUT_MS); } @Override @@ -298,27 +285,13 @@ .setTitle(R.string.external_app_leave_incognito_warning_title) .setMessage(R.string.external_payment_app_leave_incognito_warning) .setPositiveButton(R.string.ok, - new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - launchPaymentApp(id, merchantName, schemelessOrigin, - schemelessIframeOrigin, certificateChain, methodDataMap, - total, displayItems, modifiers); - } - }) + (OnClickListener) (dialog, which) -> launchPaymentApp(id, merchantName, + schemelessOrigin, + schemelessIframeOrigin, certificateChain, methodDataMap, + total, displayItems, modifiers)) .setNegativeButton(R.string.cancel, - new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - notifyErrorInvokingPaymentApp(); - } - }) - .setOnCancelListener(new OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - notifyErrorInvokingPaymentApp(); - } - }) + (OnClickListener) (dialog, which) -> notifyErrorInvokingPaymentApp()) + .setOnCancelListener(dialog -> notifyErrorInvokingPaymentApp()) .show(); } @@ -443,12 +416,7 @@ } private void notifyErrorInvokingPaymentApp() { - mHandler.post(new Runnable() { - @Override - public void run() { - mInstrumentDetailsCallback.onInstrumentDetailsError(); - } - }); + mHandler.post(() -> mInstrumentDetailsCallback.onInstrumentDetailsError()); } private static String serializeDetails(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentApp.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentApp.java index 0c1514a..a3c6dce3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentApp.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentApp.java
@@ -96,12 +96,7 @@ } } - new Handler().post(new Runnable() { - @Override - public void run() { - callback.onInstrumentsReady(AutofillPaymentApp.this, instruments); - } - }); + new Handler().post(() -> callback.onInstrumentsReady(AutofillPaymentApp.this, instruments)); } /** @return A set of card networks (e.g., "visa", "amex") accepted by "basic-card" method. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java index c48b16b1..91c3f30 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java
@@ -33,7 +33,6 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; -import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -202,17 +201,14 @@ } // Sort profiles for billing address according to completeness. - Collections.sort(mProfilesForBillingAddress, new Comparator<AutofillProfile>() { - @Override - public int compare(AutofillProfile a, AutofillProfile b) { - boolean isAComplete = AutofillAddress.checkAddressCompletionStatus( - a, AutofillAddress.NORMAL_COMPLETENESS_CHECK) - == AutofillAddress.COMPLETE; - boolean isBComplete = AutofillAddress.checkAddressCompletionStatus( - b, AutofillAddress.NORMAL_COMPLETENESS_CHECK) - == AutofillAddress.COMPLETE; - return ApiCompatibilityUtils.compareBoolean(isBComplete, isAComplete); - } + Collections.sort(mProfilesForBillingAddress, (a, b) -> { + boolean isAComplete = AutofillAddress.checkAddressCompletionStatus( + a, AutofillAddress.NORMAL_COMPLETENESS_CHECK) + == AutofillAddress.COMPLETE; + boolean isBComplete = AutofillAddress.checkAddressCompletionStatus( + b, AutofillAddress.NORMAL_COMPLETENESS_CHECK) + == AutofillAddress.COMPLETE; + return ApiCompatibilityUtils.compareBoolean(isBComplete, isAComplete); }); mCardIssuerNetworks = new HashMap<>(); @@ -254,16 +250,13 @@ } }; - mCardIconGenerator = new EditorValueIconGenerator() { - @Override - public int getIconResourceId(@Nullable CharSequence value) { - if (value == null) return 0; - CardIssuerNetwork cardTypeInfo = mCardIssuerNetworks.get( - PersonalDataManager.getInstance().getBasicCardIssuerNetwork( - value.toString(), false)); - if (cardTypeInfo == null) return 0; - return cardTypeInfo.icon; - } + mCardIconGenerator = value -> { + if (value == null) return 0; + CardIssuerNetwork cardTypeInfo = mCardIssuerNetworks.get( + PersonalDataManager.getInstance().getBasicCardIssuerNetwork( + value.toString(), false)); + if (cardTypeInfo == null) return 0; + return cardTypeInfo.icon; }; mCalendar = new AsyncTask<Void, Void, Calendar>() { @@ -378,12 +371,7 @@ try { calendar = mCalendar.get(); } catch (InterruptedException | ExecutionException e) { - mHandler.post(new Runnable() { - @Override - public void run() { - callback.onResult(null); - } - }); + mHandler.post(() -> callback.onResult(null)); return; } assert calendar != null; @@ -406,33 +394,25 @@ // If the user clicks [Cancel], send |toEdit| card back to the caller (will return original // state, which could be null, a full card, or a partial card). - editor.setCancelCallback(new Runnable() { - @Override - public void run() { - callback.onResult(toEdit); - } - }); + editor.setCancelCallback(() -> callback.onResult(toEdit)); // If the user clicks [Done], save changes on disk, mark the card "complete," and send it // back to the caller. - editor.setDoneCallback(new Runnable() { - @Override - public void run() { - commitChanges(card, isNewCard); + editor.setDoneCallback(() -> { + commitChanges(card, isNewCard); - String methodName = card.getBasicCardIssuerNetwork(); - if (mAcceptedBasicCardIssuerNetworks.contains(methodName)) { - methodName = AutofillPaymentApp.BASIC_CARD_METHOD_NAME; - } - assert methodName != null; - - AutofillProfile billingAddress = - findTargetProfile(mProfilesForBillingAddress, card.getBillingAddressId()); - assert billingAddress != null; - - instrument.completeInstrument(card, methodName, billingAddress); - callback.onResult(instrument); + String methodName = card.getBasicCardIssuerNetwork(); + if (mAcceptedBasicCardIssuerNetworks.contains(methodName)) { + methodName = AutofillPaymentApp.BASIC_CARD_METHOD_NAME; } + assert methodName != null; + + AutofillProfile billingAddress = + findTargetProfile(mProfilesForBillingAddress, card.getBillingAddressId()); + assert billingAddress != null; + + instrument.completeInstrument(card, methodName, billingAddress); + callback.onResult(instrument); }); mEditorDialog.show(editor); @@ -502,13 +482,10 @@ null /* value */); if (mCanScan) { mNumberField.addActionIcon(R.drawable.ic_photo_camera, - R.string.autofill_scan_credit_card, new Runnable() { - @Override - public void run() { - if (mIsScanning) return; - mIsScanning = true; - mCardScanner.scan(); - } + R.string.autofill_scan_credit_card, (Runnable) () -> { + if (mIsScanning) return; + mIsScanning = true; + mCardScanner.scan(); }); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ContactEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ContactEditor.java index 0ec3a51..8e98658 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ContactEditor.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ContactEditor.java
@@ -188,41 +188,33 @@ // If the user clicks [Cancel], send |toEdit| contact back to the caller, which was the // original state (could be null, a complete contact, a partial contact). - editor.setCancelCallback(new Runnable() { - @Override - public void run() { - callback.onResult(toEdit); + editor.setCancelCallback(() -> callback.onResult(toEdit)); + + editor.setDoneCallback(() -> { + String name = null; + String phone = null; + String email = null; + AutofillProfile profile = contact.getProfile(); + + if (nameField != null) { + name = nameField.getValue().toString(); + profile.setFullName(name); } - }); - editor.setDoneCallback(new Runnable() { - @Override - public void run() { - String name = null; - String phone = null; - String email = null; - AutofillProfile profile = contact.getProfile(); - - if (nameField != null) { - name = nameField.getValue().toString(); - profile.setFullName(name); - } - - if (phoneField != null) { - phone = phoneField.getValue().toString(); - profile.setPhoneNumber(phone); - } - - if (emailField != null) { - email = emailField.getValue().toString(); - profile.setEmailAddress(email); - } - - profile.setGUID(PersonalDataManager.getInstance().setProfileToLocal(profile)); - profile.setIsLocal(true); - contact.completeContact(profile.getGUID(), name, phone, email); - callback.onResult(contact); + if (phoneField != null) { + phone = phoneField.getValue().toString(); + profile.setPhoneNumber(phone); } + + if (emailField != null) { + email = emailField.getValue().toString(); + profile.setEmailAddress(email); + } + + profile.setGUID(PersonalDataManager.getInstance().setProfileToLocal(profile)); + profile.setIsLocal(true); + contact.completeContact(profile.getGUID(), name, phone, email); + callback.onResult(contact); }); mEditorDialog.show(editor);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/JourneyLogger.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/JourneyLogger.java index 249b9378..39f47c15 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/JourneyLogger.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/JourneyLogger.java
@@ -115,6 +115,20 @@ mJourneyLoggerAndroid, requestShipping, requestEmail, requestPhone, requestName); } + /* + * Records what types of payment methods were requested by the merchant in the Payment Request. + * + * @param requestedBasicCard Whether the merchant requested basic-card. + * @param requestedMethodGoogle Whether the merchant requested a Google payment method. + * @param requestedMethodOther Whether the merchant requested a non basic-card, non-Google + * payment method. + */ + public void setRequestedPaymentMethodTypes(boolean requestedBasicCard, + boolean requestedMethodGoogle, boolean requestedMethodOther) { + nativeSetRequestedPaymentMethodTypes(mJourneyLoggerAndroid, requestedBasicCard, + requestedMethodGoogle, requestedMethodOther); + } + /** * Records the payment method that was selected by the user. * @@ -189,7 +203,10 @@ private native void nativeSetRequestedInformation(long nativeJourneyLoggerAndroid, boolean requestShipping, boolean requestEmail, boolean requestPhone, boolean requestName); + private native void nativeSetRequestedPaymentMethodTypes(long nativeJourneyLoggerAndroid, + boolean requestedBasicCard, boolean requestedMethodGoogle, + boolean requestedMethodOther); private native void nativeSetCompleted(long nativeJourneyLoggerAndroid); private native void nativeSetAborted(long nativeJourneyLoggerAndroid, int reason); private native void nativeSetNotShown(long nativeJourneyLoggerAndroid, int reason); -} \ No newline at end of file +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java index c42f510..e218b43 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
@@ -7,7 +7,6 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; -import android.graphics.Bitmap; import android.os.Handler; import android.support.v4.util.ArrayMap; import android.text.TextUtils; @@ -30,7 +29,8 @@ import org.chromium.chrome.browser.payments.ui.LineItem; import org.chromium.chrome.browser.payments.ui.PaymentInformation; import org.chromium.chrome.browser.payments.ui.PaymentOption; -import org.chromium.chrome.browser.payments.ui.PaymentRequestSection.OptionSection.FocusChangedObserver; +import org.chromium.chrome.browser.payments.ui.PaymentRequestSection.OptionSection + .FocusChangedObserver; import org.chromium.chrome.browser.payments.ui.PaymentRequestUI; import org.chromium.chrome.browser.payments.ui.SectionInformation; import org.chromium.chrome.browser.payments.ui.ShoppingCart; @@ -190,12 +190,7 @@ private static final String ANDROID_PAY_METHOD_NAME = "https://android.com/pay"; private static final String PAY_WITH_GOOGLE_METHOD_NAME = "https://google.com/pay"; private static final Comparator<Completable> COMPLETENESS_COMPARATOR = - new Comparator<Completable>() { - @Override - public int compare(Completable a, Completable b) { - return (b.isComplete() ? 1 : 0) - (a.isComplete() ? 1 : 0); - } - }; + (a, b) -> (b.isComplete() ? 1 : 0) - (a.isComplete() ? 1 : 0); /** * Sorts the payment instruments by several rules: @@ -207,34 +202,31 @@ * instruments. */ private static final Comparator<PaymentInstrument> PAYMENT_INSTRUMENT_COMPARATOR = - new Comparator<PaymentInstrument>() { - @Override - public int compare(PaymentInstrument a, PaymentInstrument b) { - // Payment apps (not autofill) first. - int autofill = - (a.isAutofillInstrument() ? 1 : 0) - (b.isAutofillInstrument() ? 1 : 0); - if (autofill != 0) return autofill; + (a, b) -> { + // Payment apps (not autofill) first. + int autofill = + (a.isAutofillInstrument() ? 1 : 0) - (b.isAutofillInstrument() ? 1 : 0); + if (autofill != 0) return autofill; - // Complete cards before cards with missing information. - int completeness = (b.isComplete() ? 1 : 0) - (a.isComplete() ? 1 : 0); - if (completeness != 0) return completeness; + // Complete cards before cards with missing information. + int completeness = (b.isComplete() ? 1 : 0) - (a.isComplete() ? 1 : 0); + if (completeness != 0) return completeness; - // Cards with matching type before unknown type cards. - int typeMatch = (b.isExactlyMatchingMerchantRequest() ? 1 : 0) - - (a.isExactlyMatchingMerchantRequest() ? 1 : 0); - if (typeMatch != 0) return typeMatch; + // Cards with matching type before unknown type cards. + int typeMatch = (b.isExactlyMatchingMerchantRequest() ? 1 : 0) + - (a.isExactlyMatchingMerchantRequest() ? 1 : 0); + if (typeMatch != 0) return typeMatch; - // Preselectable instruments before non-preselectable instruments. - // Note that this only affects service worker payment apps' instruments for now - // since autofill payment instruments have already been sorted by preselect - // after sorting by completeness and typeMatch. And the other payment apps' - // instruments can always be preselected. - int canPreselect = (b.canPreselect() ? 1 : 0) - (a.canPreselect() ? 1 : 0); - if (canPreselect != 0) return canPreselect; + // Preselectable instruments before non-preselectable instruments. + // Note that this only affects service worker payment apps' instruments for now + // since autofill payment instruments have already been sorted by preselect + // after sorting by completeness and typeMatch. And the other payment apps' + // instruments can always be preselected. + int canPreselect = (b.canPreselect() ? 1 : 0) - (a.canPreselect() ? 1 : 0); + if (canPreselect != 0) return canPreselect; - // More frequently and recently used instruments first. - return compareInstrumentsByFrecency(b, a); - } + // More frequently and recently used instruments first. + return compareInstrumentsByFrecency(b, a); }; /** Every origin can call canMakePayment() every 30 minutes. */ @@ -497,6 +489,22 @@ PaymentAppFactory.getInstance().create(mWebContents, Collections.unmodifiableSet(mMethodData.keySet()), this /* callback */); + // Log the various types of payment methods that were requested by the merchant. + boolean requestedMethodGoogle = false; + boolean requestedMethodOther = false; + for (String methodName : mMethodData.keySet()) { + if (methodName.equals(ANDROID_PAY_METHOD_NAME) + || methodName.equals(PAY_WITH_GOOGLE_METHOD_NAME)) { + requestedMethodGoogle = true; + } else if (methodName.startsWith(UrlConstants.HTTPS_URL_PREFIX)) { + // Any method that starts with https and is not Android pay or Google pay is in the + // "other" category. + requestedMethodOther = true; + } + } + mJourneyLogger.setRequestedPaymentMethodTypes(mMerchantSupportsAutofillPaymentInstruments, + requestedMethodGoogle, requestedMethodOther); + // If there is a single payment method and the merchant has not requested any other // information, we can safely go directly to the payment app instead of showing // Payment Request UI. @@ -544,13 +552,10 @@ faviconHelper.getLocalFaviconImageForURL(Profile.getLastUsedProfile(), mWebContents.getLastCommittedUrl(), activity.getResources().getDimensionPixelSize(R.dimen.payments_favicon_size), - new FaviconHelper.FaviconImageCallback() { - @Override - public void onFaviconAvailable(Bitmap bitmap, String iconUrl) { - if (mClient != null && bitmap == null) mClient.warnNoFavicon(); - if (mUI != null && bitmap != null) mUI.setTitleBitmap(bitmap); - faviconHelper.destroy(); - } + (bitmap, iconUrl) -> { + if (mClient != null && bitmap == null) mClient.warnNoFavicon(); + if (mUI != null && bitmap != null) mUI.setTitleBitmap(bitmap); + faviconHelper.destroy(); }); // Add the callback to change the label of shipping addresses depending on the focus. @@ -1054,11 +1059,8 @@ if (mPaymentMethodsSection == null) return; - mHandler.post(new Runnable() { - @Override - public void run() { - if (mUI != null) providePaymentInformation(); - } + mHandler.post(() -> { + if (mUI != null) providePaymentInformation(); }); } @@ -1077,30 +1079,22 @@ @Override public void getShoppingCart(final Callback<ShoppingCart> callback) { - mHandler.post(new Runnable() { - @Override - public void run() { - callback.onResult(mUiShoppingCart); - } - }); + mHandler.post(() -> callback.onResult(mUiShoppingCart)); } @Override public void getSectionInformation(@PaymentRequestUI.DataType final int optionType, final Callback<SectionInformation> callback) { - mHandler.post(new Runnable() { - @Override - public void run() { - if (optionType == PaymentRequestUI.TYPE_SHIPPING_ADDRESSES) { - callback.onResult(mShippingAddressesSection); - } else if (optionType == PaymentRequestUI.TYPE_SHIPPING_OPTIONS) { - callback.onResult(mUiShippingOptions); - } else if (optionType == PaymentRequestUI.TYPE_CONTACT_DETAILS) { - callback.onResult(mContactSection); - } else if (optionType == PaymentRequestUI.TYPE_PAYMENT_METHODS) { - assert mPaymentMethodsSection != null; - callback.onResult(mPaymentMethodsSection); - } + mHandler.post(() -> { + if (optionType == PaymentRequestUI.TYPE_SHIPPING_ADDRESSES) { + callback.onResult(mShippingAddressesSection); + } else if (optionType == PaymentRequestUI.TYPE_SHIPPING_OPTIONS) { + callback.onResult(mUiShippingOptions); + } else if (optionType == PaymentRequestUI.TYPE_CONTACT_DETAILS) { + callback.onResult(mContactSection); + } else if (optionType == PaymentRequestUI.TYPE_PAYMENT_METHODS) { + assert mPaymentMethodsSection != null; + callback.onResult(mPaymentMethodsSection); } }); } @@ -1462,12 +1456,8 @@ // period expires. query = new CanMakePaymentQuery(Collections.unmodifiableMap(mMethodData)); sCanMakePaymentQueries.put(canMakePaymentId, query); - mHandler.postDelayed(new Runnable() { - @Override - public void run() { - sCanMakePaymentQueries.remove(canMakePaymentId); - } - }, CAN_MAKE_PAYMENT_QUERY_PERIOD_MS); + mHandler.postDelayed(() -> sCanMakePaymentQueries.remove(canMakePaymentId), + CAN_MAKE_PAYMENT_QUERY_PERIOD_MS); } else if (shouldEnforceCanMakePaymentQueryQuota() && !query.matchesPaymentMethods(Collections.unmodifiableMap(mMethodData))) { // If there has been a canMakePayment() query in the last 30 minutes, but the previous @@ -1810,12 +1800,9 @@ */ private void closeUI(boolean immediateClose) { if (mUI != null) { - mUI.close(immediateClose, new Runnable() { - @Override - public void run() { - if (mClient != null) mClient.onComplete(); - closeClient(); - } + mUI.close(immediateClose, () -> { + if (mClient != null) mClient.onComplete(); + closeClient(); }); mUI = null; mIsCurrentPaymentRequestShowing = false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentApp.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentApp.java index 8dac78e..2d36d86 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentApp.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentApp.java
@@ -78,13 +78,10 @@ public void getInstruments(Map<String, PaymentMethodData> unusedMethodDataMap, String unusedOrigin, String unusedIFrameOrigin, byte[][] unusedCertificateChain, final InstrumentsCallback callback) { - new Handler().post(new Runnable() { - @Override - public void run() { - List<PaymentInstrument> instruments = new ArrayList(); - instruments.add(ServiceWorkerPaymentApp.this); - callback.onInstrumentsReady(ServiceWorkerPaymentApp.this, instruments); - } + new Handler().post(() -> { + List<PaymentInstrument> instruments = new ArrayList(); + instruments.add(ServiceWorkerPaymentApp.this); + callback.onInstrumentsReady(ServiceWorkerPaymentApp.this, instruments); }); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/accessibility/FontSizePrefsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/accessibility/FontSizePrefsTest.java index b4916d58..7cecc91d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/accessibility/FontSizePrefsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/accessibility/FontSizePrefsTest.java
@@ -22,8 +22,6 @@ import org.chromium.chrome.browser.accessibility.FontSizePrefs.FontSizePrefsObserver; import org.chromium.chrome.browser.test.ChromeBrowserTestRule; -import java.util.concurrent.Callable; - /** * Tests for {@link FontSizePrefs}. */ @@ -175,89 +173,54 @@ } private void assertConsistent() { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - Assert.assertEquals(getUserFontScaleFactor(), mUserFontScaleFactor, EPSILON); - Assert.assertEquals(getFontScaleFactor(), mFontScaleFactor, EPSILON); - Assert.assertEquals(getForceEnableZoom(), mForceEnableZoom); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + Assert.assertEquals(getUserFontScaleFactor(), mUserFontScaleFactor, EPSILON); + Assert.assertEquals(getFontScaleFactor(), mFontScaleFactor, EPSILON); + Assert.assertEquals(getForceEnableZoom(), mForceEnableZoom); }); } } private FontSizePrefs getFontSizePrefs(final Context context) { - return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<FontSizePrefs>() { - @Override - public FontSizePrefs call() { - return FontSizePrefs.getInstance(context); - } - }); + return ThreadUtils.runOnUiThreadBlockingNoException( + () -> FontSizePrefs.getInstance(context)); } private TestingObserver createAndAddFontSizePrefsObserver() { - return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<TestingObserver>() { - @Override - public TestingObserver call() { - TestingObserver observer = new TestingObserver(); - mFontSizePrefs.addObserver(observer); - return observer; - } + return ThreadUtils.runOnUiThreadBlockingNoException(() -> { + TestingObserver observer = new TestingObserver(); + mFontSizePrefs.addObserver(observer); + return observer; }); } private void setUserFontScaleFactor(final float fontsize) { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mFontSizePrefs.setUserFontScaleFactor(fontsize); - } - }); + ThreadUtils.runOnUiThreadBlocking(() -> mFontSizePrefs.setUserFontScaleFactor(fontsize)); } private float getUserFontScaleFactor() { - return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Float>() { - @Override - public Float call() { - return mFontSizePrefs.getUserFontScaleFactor(); - } - }); + return ThreadUtils.runOnUiThreadBlockingNoException( + () -> mFontSizePrefs.getUserFontScaleFactor()); } private float getFontScaleFactor() { - return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Float>() { - @Override - public Float call() { - return mFontSizePrefs.getFontScaleFactor(); - } - }); + return ThreadUtils.runOnUiThreadBlockingNoException( + () -> mFontSizePrefs.getFontScaleFactor()); } private void setForceEnableZoomFromUser(final boolean enabled) { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mFontSizePrefs.setForceEnableZoomFromUser(enabled); - } - }); + ThreadUtils.runOnUiThreadBlocking(() -> mFontSizePrefs.setForceEnableZoomFromUser(enabled)); } private boolean getForceEnableZoom() { - return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Boolean>() { - @Override - public Boolean call() { - return mFontSizePrefs.getForceEnableZoom(); - } - }); + return ThreadUtils.runOnUiThreadBlockingNoException( + () -> mFontSizePrefs.getForceEnableZoom()); } private void setSystemFontScaleForTest(final float systemFontScale) { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mFontSizePrefs.setSystemFontScaleForTest(systemFontScale); - mFontSizePrefs.onSystemFontScaleChanged(); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + mFontSizePrefs.setSystemFontScaleForTest(systemFontScale); + mFontSizePrefs.onSystemFontScaleChanged(); }); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java index fd791d0..37feb71 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java
@@ -35,8 +35,6 @@ import org.chromium.content.browser.test.util.Criteria; import org.chromium.content.browser.test.util.CriteriaHelper; -import java.util.concurrent.Callable; - /** * Tests AppMenu popup */ @@ -81,32 +79,18 @@ InstrumentationRegistry.getInstrumentation().setInTouchMode(false); ChromeActivity.setAppMenuHandlerFactoryForTesting( - new ChromeActivity.AppMenuHandlerFactory() { - @Override - public AppMenuHandler get(Activity activity, AppMenuPropertiesDelegate delegate, - int menuResourceId) { - mAppMenuHandler = - new AppMenuHandlerForTest(activity, delegate, menuResourceId); - return mAppMenuHandler; - } + (activity, delegate, menuResourceId) -> { + mAppMenuHandler = + new AppMenuHandlerForTest(activity, delegate, menuResourceId); + return mAppMenuHandler; }); mActivityTestRule.startMainActivityWithURL(TEST_URL); showAppMenuAndAssertMenuShown(); mAppMenu = mActivityTestRule.getActivity().getAppMenuHandler().getAppMenu(); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - mAppMenu.getListView().setSelection(0); - } - }); - CriteriaHelper.pollInstrumentationThread(Criteria.equals(0, new Callable<Integer>() { - @Override - public Integer call() { - return getCurrentFocusedRow(); - } - })); + ThreadUtils.runOnUiThread(() -> mAppMenu.getListView().setSelection(0)); + CriteriaHelper.pollInstrumentationThread(Criteria.equals(0, () -> getCurrentFocusedRow())); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); } @@ -231,12 +215,7 @@ } private void showAppMenuAndAssertMenuShown() { - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - mAppMenuHandler.showAppMenu(null, false); - } - }); + ThreadUtils.runOnUiThread((Runnable) () -> mAppMenuHandler.showAppMenu(null, false)); CriteriaHelper.pollInstrumentationThread(new Criteria("AppMenu did not show") { @Override public boolean isSatisfied() { @@ -264,23 +243,14 @@ pressKey(towardsTop ? KeyEvent.KEYCODE_DPAD_UP : KeyEvent.KEYCODE_DPAD_DOWN); final int expectedPosition = index + increment; CriteriaHelper.pollInstrumentationThread( - Criteria.equals(expectedPosition, new Callable<Integer>() { - @Override - public Integer call() { - return getCurrentFocusedRow(); - } - })); + Criteria.equals(expectedPosition, () -> getCurrentFocusedRow())); } // Try moving past it by one. if (movePast) { pressKey(towardsTop ? KeyEvent.KEYCODE_DPAD_UP : KeyEvent.KEYCODE_DPAD_DOWN); - CriteriaHelper.pollInstrumentationThread(Criteria.equals(end, new Callable<Integer>() { - @Override - public Integer call() { - return getCurrentFocusedRow(); - } - })); + CriteriaHelper.pollInstrumentationThread(Criteria.equals(end, + () -> getCurrentFocusedRow())); } // The menu should stay open. @@ -289,12 +259,9 @@ private void pressKey(final int keycode) { final View view = mAppMenu.getListView(); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keycode)); - view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keycode)); - } + ThreadUtils.runOnUiThread(() -> { + view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keycode)); + view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keycode)); }); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/ChromeHomeAppMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/ChromeHomeAppMenuTest.java index ae62965..298000e1 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/ChromeHomeAppMenuTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/ChromeHomeAppMenuTest.java
@@ -60,12 +60,9 @@ assertTrue(iconRow.getReloadButtonForTests().isEnabled()); // Navigate backward, open the menu and assert forward button is enabled. - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mAppMenuHandler.hideAppMenu(); - mBottomSheetTestRule.getActivity().getActivityTab().goBack(); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + mAppMenuHandler.hideAppMenu(); + mBottomSheetTestRule.getActivity().getActivityTab().goBack(); }); showAppMenuAndAssertMenuShown(); @@ -76,12 +73,8 @@ @Test @SmallTest public void testTabSwitcherMenu() throws IllegalArgumentException { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mBottomSheetTestRule.getActivity().getLayoutManager().showOverview(false); - } - }); + ThreadUtils.runOnUiThreadBlocking( + () -> mBottomSheetTestRule.getActivity().getLayoutManager().showOverview(false)); showAppMenuAndAssertMenuShown(); AppMenu appMenu = mAppMenuHandler.getAppMenu(); @@ -90,12 +83,7 @@ } private void showAppMenuAndAssertMenuShown() { - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - mAppMenuHandler.showAppMenu(null, false); - } - }); + ThreadUtils.runOnUiThread((Runnable) () -> mAppMenuHandler.showAppMenu(null, false)); CriteriaHelper.pollUiThread(new Criteria("AppMenu did not show") { @Override public boolean isSatisfied() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/DataSaverAppMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/DataSaverAppMenuTest.java index 69f05afe..5be8175 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/DataSaverAppMenuTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/DataSaverAppMenuTest.java
@@ -62,14 +62,10 @@ @Before public void setUp() throws Exception { ChromeTabbedActivity.setAppMenuHandlerFactoryForTesting( - new ChromeTabbedActivity.AppMenuHandlerFactory() { - @Override - public AppMenuHandler get(Activity activity, AppMenuPropertiesDelegate delegate, - int menuResourceId) { - mAppMenuHandler = - new AppMenuHandlerForTest(activity, delegate, menuResourceId); - return mAppMenuHandler; - } + (activity, delegate, menuResourceId) -> { + mAppMenuHandler = + new AppMenuHandlerForTest(activity, delegate, menuResourceId); + return mAppMenuHandler; }); mActivityTestRule.startMainActivityOnBlankPage(); @@ -83,15 +79,12 @@ @CommandLineFlags.Add("disable-field-trial-config") @Feature({"Browser", "Main"}) public void testMenuDataSaverNoFeature() throws Throwable { - mActivityTestRule.runOnUiThread(new Runnable() { - @Override - public void run() { - ContextUtils.getAppSharedPreferences().edit().clear().apply(); - Assert.assertEquals(0, mAppMenuHandler.getDelegate().getFooterResourceId()); - DataReductionProxySettings.getInstance().setDataReductionProxyEnabled( - mActivityTestRule.getActivity().getApplicationContext(), true); - Assert.assertEquals(0, mAppMenuHandler.getDelegate().getFooterResourceId()); - } + mActivityTestRule.runOnUiThread((Runnable) () -> { + ContextUtils.getAppSharedPreferences().edit().clear().apply(); + Assert.assertEquals(0, mAppMenuHandler.getDelegate().getFooterResourceId()); + DataReductionProxySettings.getInstance().setDataReductionProxyEnabled( + mActivityTestRule.getActivity().getApplicationContext(), true); + Assert.assertEquals(0, mAppMenuHandler.getDelegate().getFooterResourceId()); }); } @@ -104,24 +97,21 @@ "disable-field-trial-config"}) @Feature({"Browser", "Main"}) public void testMenuDataSaver() throws Throwable { - mActivityTestRule.runOnUiThread(new Runnable() { - @Override - public void run() { - ContextUtils.getAppSharedPreferences().edit().clear().apply(); - // Data Saver hasn't been turned on, the footer shouldn't show. - Assert.assertEquals(0, mAppMenuHandler.getDelegate().getFooterResourceId()); + mActivityTestRule.runOnUiThread((Runnable) () -> { + ContextUtils.getAppSharedPreferences().edit().clear().apply(); + // Data Saver hasn't been turned on, the footer shouldn't show. + Assert.assertEquals(0, mAppMenuHandler.getDelegate().getFooterResourceId()); - // Turn Data Saver on, the footer should show. - DataReductionProxySettings.getInstance().setDataReductionProxyEnabled( - mActivityTestRule.getActivity().getApplicationContext(), true); - Assert.assertEquals(R.layout.data_reduction_main_menu_footer, - mAppMenuHandler.getDelegate().getFooterResourceId()); + // Turn Data Saver on, the footer should show. + DataReductionProxySettings.getInstance().setDataReductionProxyEnabled( + mActivityTestRule.getActivity().getApplicationContext(), true); + Assert.assertEquals(R.layout.data_reduction_main_menu_footer, + mAppMenuHandler.getDelegate().getFooterResourceId()); - // Ensure the footer is removed if the proxy is turned off. - DataReductionProxySettings.getInstance().setDataReductionProxyEnabled( - mActivityTestRule.getActivity().getApplicationContext(), false); - Assert.assertEquals(0, mAppMenuHandler.getDelegate().getFooterResourceId()); - } + // Ensure the footer is removed if the proxy is turned off. + DataReductionProxySettings.getInstance().setDataReductionProxyEnabled( + mActivityTestRule.getActivity().getApplicationContext(), false); + Assert.assertEquals(0, mAppMenuHandler.getDelegate().getFooterResourceId()); }); } @@ -138,25 +128,22 @@ "disable-field-trial-config"}) @Feature({"Browser", "Main"}) public void testMenuDataSaverPersistent() throws Throwable { - mActivityTestRule.runOnUiThread(new Runnable() { - @Override - public void run() { - ContextUtils.getAppSharedPreferences().edit().clear().apply(); - // Data Saver hasn't been turned on, the footer shouldn't show. - Assert.assertEquals(0, mAppMenuHandler.getDelegate().getFooterResourceId()); + mActivityTestRule.runOnUiThread((Runnable) () -> { + ContextUtils.getAppSharedPreferences().edit().clear().apply(); + // Data Saver hasn't been turned on, the footer shouldn't show. + Assert.assertEquals(0, mAppMenuHandler.getDelegate().getFooterResourceId()); - // Turn Data Saver on, the footer should show. - DataReductionProxySettings.getInstance().setDataReductionProxyEnabled( - mActivityTestRule.getActivity().getApplicationContext(), true); - Assert.assertEquals(R.layout.data_reduction_main_menu_footer, - mAppMenuHandler.getDelegate().getFooterResourceId()); + // Turn Data Saver on, the footer should show. + DataReductionProxySettings.getInstance().setDataReductionProxyEnabled( + mActivityTestRule.getActivity().getApplicationContext(), true); + Assert.assertEquals(R.layout.data_reduction_main_menu_footer, + mAppMenuHandler.getDelegate().getFooterResourceId()); - // Ensure the footer remains if the proxy is turned off. - DataReductionProxySettings.getInstance().setDataReductionProxyEnabled( - mActivityTestRule.getActivity().getApplicationContext(), false); - Assert.assertEquals(R.layout.data_reduction_main_menu_footer, - mAppMenuHandler.getDelegate().getFooterResourceId()); - } + // Ensure the footer remains if the proxy is turned off. + DataReductionProxySettings.getInstance().setDataReductionProxyEnabled( + mActivityTestRule.getActivity().getApplicationContext(), false); + Assert.assertEquals(R.layout.data_reduction_main_menu_footer, + mAppMenuHandler.getDelegate().getFooterResourceId()); }); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillKeyboardAccessoryTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillKeyboardAccessoryTest.java index 6895523e..08afdb01 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillKeyboardAccessoryTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillKeyboardAccessoryTest.java
@@ -33,7 +33,6 @@ import org.chromium.content_public.browser.WebContents; import org.chromium.ui.UiUtils; -import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReference; @@ -91,16 +90,13 @@ + "Doooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooe", "Acme Inc", "1 Main\nApt A", "CA", "San Francisco", "", "94102", "", "US", "(415) 999-0000", "jane@acme.inc", "en")); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mViewCoreRef.set(mActivityTestRule.getActivity().getCurrentContentViewCore()); - mWebContentsRef.set(mViewCoreRef.get().getWebContents()); - mContainerRef.set(mViewCoreRef.get().getContainerView()); - mKeyboardAccessoryRef.set(mActivityTestRule.getActivity() - .getWindowAndroid() - .getKeyboardAccessoryView()); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + mViewCoreRef.set(mActivityTestRule.getActivity().getCurrentContentViewCore()); + mWebContentsRef.set(mViewCoreRef.get().getWebContents()); + mContainerRef.set(mViewCoreRef.get().getContainerView()); + mKeyboardAccessoryRef.set(mActivityTestRule.getActivity() + .getWindowAndroid() + .getKeyboardAccessoryView()); }); DOMUtils.waitForNonZeroNodeBounds(mWebContentsRef.get(), "fn"); } @@ -116,12 +112,8 @@ loadTestPage(false); Assert.assertTrue("Keyboard accessory should be hidden.", ThreadUtils - .runOnUiThreadBlocking(new Callable<Boolean>() { - @Override - public Boolean call() { - return mKeyboardAccessoryRef.get().getVisibility() == View.GONE; - } - }) + .runOnUiThreadBlocking( + () -> mKeyboardAccessoryRef.get().getVisibility() == View.GONE) .booleanValue()); } @@ -144,12 +136,8 @@ }); Assert.assertTrue("Keyboard accessory should be showing.", ThreadUtils - .runOnUiThreadBlocking(new Callable<Boolean>() { - @Override - public Boolean call() { - return mKeyboardAccessoryRef.get().getVisibility() == View.VISIBLE; - } - }) + .runOnUiThreadBlocking( + () -> mKeyboardAccessoryRef.get().getVisibility() == View.VISIBLE) .booleanValue()); } @@ -170,12 +158,8 @@ mActivityTestRule.getActivity(), mContainerRef.get()); } }); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - ((HorizontalScrollView) mKeyboardAccessoryRef.get()).scrollTo(2000, 0); - } - }); + ThreadUtils.runOnUiThreadBlocking( + () -> ((HorizontalScrollView) mKeyboardAccessoryRef.get()).scrollTo(2000, 0)); CriteriaHelper.pollUiThread( new Criteria("First suggestion should be off the screen after manual scroll.") { @Override @@ -223,12 +207,8 @@ mActivityTestRule.getActivity(), mContainerRef.get()); } }); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - ((HorizontalScrollView) mKeyboardAccessoryRef.get()).scrollTo(0, 0); - } - }); + ThreadUtils.runOnUiThreadBlocking( + () -> ((HorizontalScrollView) mKeyboardAccessoryRef.get()).scrollTo(0, 0)); CriteriaHelper.pollUiThread( new Criteria("Last suggestion should be on the screen after manual scroll.") { @Override @@ -278,13 +258,10 @@ mActivityTestRule.getActivity(), mContainerRef.get()); } }); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - View suggestion = getSuggestionAt(0); - if (suggestion != null) { - suggestion.performClick(); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + View suggestion = getSuggestionAt(0); + if (suggestion != null) { + suggestion.performClick(); } }); CriteriaHelper.pollUiThread(new Criteria("Keyboard should be hidden.") { @@ -296,12 +273,8 @@ }); Assert.assertTrue("Keyboard accessory should be hidden.", ThreadUtils - .runOnUiThreadBlocking(new Callable<Boolean>() { - @Override - public Boolean call() { - return mKeyboardAccessoryRef.get().getVisibility() == View.GONE; - } - }) + .runOnUiThreadBlocking( + () -> mKeyboardAccessoryRef.get().getVisibility() == View.GONE) .booleanValue()); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupTest.java index 9c4540d..a41275d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupTest.java
@@ -37,7 +37,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; @@ -141,12 +140,7 @@ public void setUp() throws Exception { mAutofillLoggedEntries = new ArrayList<AutofillLogger.LogEntry>(); AutofillLogger.setLoggerForTesting( - new AutofillLogger.Logger() { - @Override - public void didFillField(AutofillLogger.LogEntry logEntry) { - mAutofillLoggedEntries.add(logEntry); - } - } + logEntry -> mAutofillLoggedEntries.add(logEntry) ); } @@ -184,12 +178,7 @@ final ChromiumBaseInputConnection inputConnection = viewCore.getImeAdapterForTest().getInputConnectionForTest(); - inputConnection.getHandler().post(new Runnable() { - @Override - public void run() { - inputConnection.setComposingText(inputText, 1); - } - }); + inputConnection.getHandler().post(() -> inputConnection.setComposingText(inputText, 1)); waitForAnchorViewAdd(view); View anchorView = view.findViewById(R.id.dropdown_popup_window); @@ -317,12 +306,7 @@ private void waitForKeyboardShowRequest(final TestInputMethodManagerWrapper immw, final int count) { CriteriaHelper.pollUiThread( - Criteria.equals(count, new Callable<Integer>() { - @Override - public Integer call() { - return immw.getShowSoftInputCounter(); - } - })); + Criteria.equals(count, () -> immw.getShowSoftInputCounter())); } private void waitForAnchorViewAdd(final ViewGroup view) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupWithKeyboardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupWithKeyboardTest.java index 448aa1cc..32ac0b8 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupWithKeyboardTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupWithKeyboardTest.java
@@ -31,7 +31,6 @@ import org.chromium.ui.R; import org.chromium.ui.UiUtils; -import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReference; @@ -82,13 +81,10 @@ final AtomicReference<ContentViewCore> viewCoreRef = new AtomicReference<ContentViewCore>(); final AtomicReference<WebContents> webContentsRef = new AtomicReference<WebContents>(); final AtomicReference<ViewGroup> viewRef = new AtomicReference<ViewGroup>(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - viewCoreRef.set(mActivityTestRule.getActivity().getCurrentContentViewCore()); - webContentsRef.set(viewCoreRef.get().getWebContents()); - viewRef.set(viewCoreRef.get().getContainerView()); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + viewCoreRef.set(mActivityTestRule.getActivity().getCurrentContentViewCore()); + webContentsRef.set(viewCoreRef.get().getWebContents()); + viewRef.set(viewCoreRef.get().getContainerView()); }); DOMUtils.waitForNonZeroNodeBounds(webContentsRef.get(), "fn"); @@ -116,12 +112,8 @@ return viewRef.get().findViewById(R.id.dropdown_popup_window) != null; } }); - Object popupObject = ThreadUtils.runOnUiThreadBlocking(new Callable<Object>() { - @Override - public Object call() { - return viewRef.get().findViewById(R.id.dropdown_popup_window).getTag(); - } - }); + Object popupObject = ThreadUtils.runOnUiThreadBlocking( + () -> viewRef.get().findViewById(R.id.dropdown_popup_window).getTag()); Assert.assertTrue(popupObject instanceof AutofillPopup); final AutofillPopup popup = (AutofillPopup) popupObject; CriteriaHelper.pollUiThread(new Criteria("Autofill Popup was never shown.") {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillTest.java index 8a7d9e1..f8a44bce 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillTest.java
@@ -66,19 +66,16 @@ ViewAndroidDelegate.createBasicDelegate( activity.getCurrentContentViewCore().getContainerView()); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - View anchorView = viewDelegate.acquireView(); - viewDelegate.setViewPosition(anchorView, 50f, 500f, 500f, 500f, 1f, 10, 10); + ThreadUtils.runOnUiThreadBlocking(() -> { + View anchorView = viewDelegate.acquireView(); + viewDelegate.setViewPosition(anchorView, 50f, 500f, 500f, 500f, 1f, 10, 10); - mWindowAndroid = new ActivityWindowAndroid(activity); - mAutofillPopup = new AutofillPopup(activity, anchorView, mMockAutofillCallback); - mAutofillPopup.filterAndShow(new AutofillSuggestion[0], false /* isRtl */, - Color.TRANSPARENT /* backgroundColor */, - Color.TRANSPARENT /* dividerColor */, 0 /* dropdownItemHeight */, - 0 /* margin */); - } + mWindowAndroid = new ActivityWindowAndroid(activity); + mAutofillPopup = new AutofillPopup(activity, anchorView, mMockAutofillCallback); + mAutofillPopup.filterAndShow(new AutofillSuggestion[0], false /* isRtl */, + Color.TRANSPARENT /* backgroundColor */, + Color.TRANSPARENT /* dividerColor */, 0 /* dropdownItemHeight */, + 0 /* margin */); }); } @@ -143,15 +140,11 @@ } public void openAutofillPopupAndWaitUntilReady(final AutofillSuggestion[] suggestions) { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mAutofillPopup.filterAndShow(suggestions, false /* isRtl */, + ThreadUtils.runOnUiThreadBlocking( + () -> mAutofillPopup.filterAndShow(suggestions, false /* isRtl */, Color.TRANSPARENT /* backgroundColor */, Color.TRANSPARENT /* dividerColor */, 0 /* dropdownItemHeight */, - 0 /* margin */); - } - }); + 0 /* margin */)); CriteriaHelper.pollInstrumentationThread(new Criteria() { @Override public boolean isSatisfied() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillTestHelper.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillTestHelper.java index ef11eb9..ac32f3d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillTestHelper.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillTestHelper.java
@@ -8,10 +8,8 @@ import org.chromium.base.test.util.CallbackHelper; import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard; -import org.chromium.chrome.browser.autofill.PersonalDataManager.PersonalDataManagerObserver; import java.util.List; -import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; @@ -28,40 +26,24 @@ } void setRequestTimeoutForTesting() { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - PersonalDataManager.getInstance().setRequestTimeoutForTesting(0); - } - }); + ThreadUtils.runOnUiThreadBlocking( + () -> PersonalDataManager.getInstance().setRequestTimeoutForTesting(0)); } AutofillProfile getProfile(final String guid) throws ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<AutofillProfile>() { - @Override - public AutofillProfile call() { - return PersonalDataManager.getInstance().getProfile(guid); - } - }); + return ThreadUtils.runOnUiThreadBlocking( + () -> PersonalDataManager.getInstance().getProfile(guid)); } List<AutofillProfile> getProfilesToSuggest(final boolean includeNameInLabel) throws ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<List<AutofillProfile>>() { - @Override - public List<AutofillProfile> call() { - return PersonalDataManager.getInstance().getProfilesToSuggest(includeNameInLabel); - } - }); + return ThreadUtils.runOnUiThreadBlocking( + () -> PersonalDataManager.getInstance().getProfilesToSuggest(includeNameInLabel)); } List<AutofillProfile> getProfilesForSettings() throws ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<List<AutofillProfile>>() { - @Override - public List<AutofillProfile> call() { - return PersonalDataManager.getInstance().getProfilesForSettings(); - } - }); + return ThreadUtils.runOnUiThreadBlocking( + () -> PersonalDataManager.getInstance().getProfilesForSettings()); } int getNumberOfProfilesToSuggest() throws ExecutionException { @@ -75,52 +57,32 @@ public String setProfile(final AutofillProfile profile) throws InterruptedException, ExecutionException, TimeoutException { int callCount = mOnPersonalDataChangedHelper.getCallCount(); - String guid = ThreadUtils.runOnUiThreadBlocking(new Callable<String>() { - @Override - public String call() { - return PersonalDataManager.getInstance().setProfile(profile); - } - }); + String guid = ThreadUtils.runOnUiThreadBlocking( + () -> PersonalDataManager.getInstance().setProfile(profile)); mOnPersonalDataChangedHelper.waitForCallback(callCount); return guid; } public void deleteProfile(final String guid) throws InterruptedException, TimeoutException { int callCount = mOnPersonalDataChangedHelper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - PersonalDataManager.getInstance().deleteProfile(guid); - } - }); + ThreadUtils.runOnUiThreadBlocking( + () -> PersonalDataManager.getInstance().deleteProfile(guid)); mOnPersonalDataChangedHelper.waitForCallback(callCount); } public CreditCard getCreditCard(final String guid) throws ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<CreditCard>() { - @Override - public CreditCard call() { - return PersonalDataManager.getInstance().getCreditCard(guid); - } - }); + return ThreadUtils.runOnUiThreadBlocking( + () -> PersonalDataManager.getInstance().getCreditCard(guid)); } List<CreditCard> getCreditCardsToSuggest() throws ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<List<CreditCard>>() { - @Override - public List<CreditCard> call() { - return PersonalDataManager.getInstance().getCreditCardsToSuggest(); - } - }); + return ThreadUtils.runOnUiThreadBlocking( + () -> PersonalDataManager.getInstance().getCreditCardsToSuggest()); } List<CreditCard> getCreditCardsForSettings() throws ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<List<CreditCard>>() { - @Override - public List<CreditCard> call() { - return PersonalDataManager.getInstance().getCreditCardsForSettings(); - } - }); + return ThreadUtils.runOnUiThreadBlocking( + () -> PersonalDataManager.getInstance().getCreditCardsForSettings()); } int getNumberOfCreditCardsToSuggest() throws ExecutionException { @@ -134,12 +96,8 @@ public String setCreditCard(final CreditCard card) throws InterruptedException, ExecutionException, TimeoutException { int callCount = mOnPersonalDataChangedHelper.getCallCount(); - String guid = ThreadUtils.runOnUiThreadBlocking(new Callable<String>() { - @Override - public String call() { - return PersonalDataManager.getInstance().setCreditCard(card); - } - }); + String guid = ThreadUtils.runOnUiThreadBlocking( + () -> PersonalDataManager.getInstance().setCreditCard(card)); mOnPersonalDataChangedHelper.waitForCallback(callCount); return guid; } @@ -147,23 +105,15 @@ public void addServerCreditCard(final CreditCard card) throws InterruptedException, ExecutionException, TimeoutException { int callCount = mOnPersonalDataChangedHelper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - PersonalDataManager.getInstance().addServerCreditCardForTest(card); - } - }); + ThreadUtils.runOnUiThreadBlocking( + () -> PersonalDataManager.getInstance().addServerCreditCardForTest(card)); mOnPersonalDataChangedHelper.waitForCallback(callCount); } void deleteCreditCard(final String guid) throws InterruptedException, TimeoutException { int callCount = mOnPersonalDataChangedHelper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - PersonalDataManager.getInstance().deleteCreditCard(guid); - } - }); + ThreadUtils.runOnUiThreadBlocking( + () -> PersonalDataManager.getInstance().deleteCreditCard(guid)); mOnPersonalDataChangedHelper.waitForCallback(callCount); } @@ -176,12 +126,8 @@ */ void recordAndLogProfileUse(final String guid) throws InterruptedException, TimeoutException { int callCount = mOnPersonalDataChangedHelper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - PersonalDataManager.getInstance().recordAndLogProfileUse(guid); - } - }); + ThreadUtils.runOnUiThreadBlocking( + () -> PersonalDataManager.getInstance().recordAndLogProfileUse(guid)); mOnPersonalDataChangedHelper.waitForCallback(callCount); } @@ -199,12 +145,9 @@ public void setProfileUseStatsForTesting(final String guid, final int count, final long date) throws InterruptedException, TimeoutException { int callCount = mOnPersonalDataChangedHelper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - PersonalDataManager.getInstance().setProfileUseStatsForTesting(guid, count, date); - } - }); + ThreadUtils.runOnUiThreadBlocking( + () -> PersonalDataManager.getInstance().setProfileUseStatsForTesting(guid, count, + date)); mOnPersonalDataChangedHelper.waitForCallback(callCount); } @@ -216,12 +159,8 @@ */ public int getProfileUseCountForTesting(final String guid) throws InterruptedException, ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() { - @Override - public Integer call() { - return PersonalDataManager.getInstance().getProfileUseCountForTesting(guid); - } - }); + return ThreadUtils.runOnUiThreadBlocking( + () -> PersonalDataManager.getInstance().getProfileUseCountForTesting(guid)); } /** @@ -234,12 +173,8 @@ */ public long getProfileUseDateForTesting(final String guid) throws InterruptedException, ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<Long>() { - @Override - public Long call() { - return PersonalDataManager.getInstance().getProfileUseDateForTesting(guid); - } - }); + return ThreadUtils.runOnUiThreadBlocking( + () -> PersonalDataManager.getInstance().getProfileUseDateForTesting(guid)); } /** @@ -252,12 +187,8 @@ public void recordAndLogCreditCardUse(final String guid) throws InterruptedException, TimeoutException { int callCount = mOnPersonalDataChangedHelper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - PersonalDataManager.getInstance().recordAndLogCreditCardUse(guid); - } - }); + ThreadUtils.runOnUiThreadBlocking( + () -> PersonalDataManager.getInstance().recordAndLogCreditCardUse(guid)); mOnPersonalDataChangedHelper.waitForCallback(callCount); } @@ -275,13 +206,9 @@ public void setCreditCardUseStatsForTesting(final String guid, final int count, final long date) throws InterruptedException, TimeoutException { int callCount = mOnPersonalDataChangedHelper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - PersonalDataManager.getInstance().setCreditCardUseStatsForTesting( - guid, count, date); - } - }); + ThreadUtils.runOnUiThreadBlocking( + () -> PersonalDataManager.getInstance().setCreditCardUseStatsForTesting( + guid, count, date)); mOnPersonalDataChangedHelper.waitForCallback(callCount); } @@ -293,12 +220,8 @@ */ public int getCreditCardUseCountForTesting(final String guid) throws InterruptedException, ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() { - @Override - public Integer call() { - return PersonalDataManager.getInstance().getCreditCardUseCountForTesting(guid); - } - }); + return ThreadUtils.runOnUiThreadBlocking( + () -> PersonalDataManager.getInstance().getCreditCardUseCountForTesting(guid)); } /** @@ -311,12 +234,8 @@ */ public long getCreditCardUseDateForTesting(final String guid) throws InterruptedException, ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<Long>() { - @Override - public Long call() { - return PersonalDataManager.getInstance().getCreditCardUseDateForTesting(guid); - } - }); + return ThreadUtils.runOnUiThreadBlocking( + () -> PersonalDataManager.getInstance().getCreditCardUseDateForTesting(guid)); } /** @@ -327,29 +246,16 @@ * For more details see the comment header in time.h. */ public long getCurrentDateForTesting() throws InterruptedException, ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<Long>() { - @Override - public Long call() { - return PersonalDataManager.getInstance().getCurrentDateForTesting(); - } - }); + return ThreadUtils.runOnUiThreadBlocking( + () -> PersonalDataManager.getInstance().getCurrentDateForTesting()); } private void registerDataObserver() { try { int callCount = mOnPersonalDataChangedHelper.getCallCount(); - boolean isDataLoaded = ThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() { - @Override - public Boolean call() { - return PersonalDataManager.getInstance().registerDataObserver( - new PersonalDataManagerObserver() { - @Override - public void onPersonalDataChanged() { - mOnPersonalDataChangedHelper.notifyCalled(); - } - }); - } - }); + boolean isDataLoaded = ThreadUtils.runOnUiThreadBlocking( + () -> PersonalDataManager.getInstance().registerDataObserver( + () -> mOnPersonalDataChangedHelper.notifyCalled())); if (isDataLoaded) return; mOnPersonalDataChangedHelper.waitForCallback(callCount); } catch (TimeoutException | InterruptedException | ExecutionException e) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java index f9d50e2..b7e33118 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
@@ -3113,7 +3113,7 @@ @Test @SmallTest @Feature({"ContextualSearch"}) - public void testLongPressHidesFindInPageOverlay() throws Exception { + public void testTriggeringContextualSearchHidesFindInPageOverlay() throws Exception { MenuUtils.invokeCustomMenuActionSync(InstrumentationRegistry.getInstrumentation(), mActivityTestRule.getActivity(), R.id.find_in_page_id); @@ -3133,7 +3133,7 @@ View findToolbar = mActivityTestRule.getActivity().findViewById(R.id.find_toolbar); Assert.assertTrue(findToolbar.isShown()); - longPressNode("states"); + simulateTapSearch("search"); waitForPanelToPeek(); Assert.assertFalse(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java index dc4da257..8539873 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java
@@ -28,13 +28,13 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.CommandLineFlags; -import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.EnormousTest; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.base.test.util.RetryOnFailure; import org.chromium.base.test.util.ScalableTimeout; import org.chromium.base.test.util.parameter.CommandLineParameter; +import org.chromium.base.test.util.parameter.SkipCommandLineParameterization; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeFeatureList; @@ -597,8 +597,8 @@ * Test to verify that the security icon is present when visiting http:// URLs. */ @Test - //@MediumTest - @DisabledTest(message = "crbug.com/754723") + @MediumTest + @SkipCommandLineParameterization public void testSecurityIconOnHTTP() throws InterruptedException { EmbeddedTestServer testServer = EmbeddedTestServer.createAndStartServer( InstrumentationRegistry.getInstrumentation().getContext()); @@ -613,8 +613,15 @@ (LocationBarLayout) mActivityTestRule.getActivity().findViewById( R.id.location_bar); boolean securityIcon = locationBar.isSecurityButtonShown(); - Assert.assertFalse("Omnibox should not have a Security icon", securityIcon); - Assert.assertFalse(securityButton.isShown()); + if (DeviceFormFactor.isTablet()) { + Assert.assertTrue("Omnibox should have a Security icon", securityIcon); + Assert.assertTrue(securityButton.isShown()); + Assert.assertEquals( + R.drawable.omnibox_info, locationBar.getSecurityIconResourceId()); + } else { + Assert.assertFalse("Omnibox should not have a Security icon", securityIcon); + Assert.assertFalse(securityButton.isShown()); + } } finally { testServer.stopAndDestroyServer(); } @@ -625,6 +632,7 @@ */ @Test @MediumTest + @SkipCommandLineParameterization public void testSecurityIconOnHTTPS() throws InterruptedException { EmbeddedTestServer httpsTestServer = EmbeddedTestServer.createAndStartHTTPSServer( InstrumentationRegistry.getInstrumentation().getContext(), @@ -645,6 +653,8 @@ Assert.assertEquals("security_button with wrong resource-id", R.id.security_button, securityButton.getId()); Assert.assertTrue(securityButton.isShown()); + Assert.assertEquals( + R.drawable.omnibox_https_valid, locationBar.getSecurityIconResourceId()); } finally { httpsTestServer.stopAndDestroyServer(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderTest.java index f793e32..0318a131 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderTest.java
@@ -1077,15 +1077,10 @@ } private void findApps(final Set<String> methodNames) throws Throwable { - mRule.runOnUiThread(new Runnable() { - @Override - public void run() { - AndroidPaymentAppFinder.find( - mRule.getActivity().getCurrentContentViewCore().getWebContents(), - methodNames, new PaymentManifestWebDataService(), mDownloader, mParser, - mPackageManager, AndroidPaymentAppFinderTest.this); - } - }); + mRule.runOnUiThread((Runnable) () -> AndroidPaymentAppFinder.find( + mRule.getActivity().getCurrentContentViewCore().getWebContents(), + methodNames, new PaymentManifestWebDataService(), mDownloader, mParser, + mPackageManager, AndroidPaymentAppFinderTest.this)); CriteriaHelper.pollInstrumentationThread(new Criteria() { @Override public boolean isSatisfied() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentManifestDownloaderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentManifestDownloaderTest.java index 55868a9..592e8283 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentManifestDownloaderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentManifestDownloaderTest.java
@@ -94,13 +94,10 @@ mRule.startMainActivityOnBlankPage(); mServer = EmbeddedTestServer.createAndStartServer( InstrumentationRegistry.getInstrumentation().getContext()); - mRule.runOnUiThread(new Runnable() { - @Override - public void run() { - mDownloader.initialize( - mRule.getActivity().getCurrentContentViewCore().getWebContents()); - mDownloader.allowHttpForTest(); - } + mRule.runOnUiThread((Runnable) () -> { + mDownloader.initialize( + mRule.getActivity().getCurrentContentViewCore().getWebContents()); + mDownloader.allowHttpForTest(); }); mDownloadComplete = false; mDownloadPaymentMethodManifestSuccess = false; @@ -112,12 +109,7 @@ @After public void tearDown() throws Throwable { - mRule.runOnUiThread(new Runnable() { - @Override - public void run() { - mDownloader.destroy(); - } - }); + mRule.runOnUiThread((Runnable) () -> mDownloader.destroy()); mServer.stopAndDestroyServer(); } @@ -126,12 +118,8 @@ public void testDownloadWebAppManifest() throws Throwable { final URI uri = new URI(mServer.getURL("/components/test/data/payments/bobpay.com/app.json")); - mRule.runOnUiThread(new Runnable() { - @Override - public void run() { - mDownloader.downloadWebAppManifest(uri, PaymentManifestDownloaderTest.this); - } - }); + mRule.runOnUiThread((Runnable) () -> mDownloader.downloadWebAppManifest(uri, + PaymentManifestDownloaderTest.this)); CriteriaHelper.pollInstrumentationThread(new Criteria() { @Override public boolean isSatisfied() { @@ -148,12 +136,8 @@ @Feature({"Payments"}) public void testUnableToDownloadWebAppManifest() throws Throwable { final URI uri = new URI(mServer.getURL("/no-such-app.json")); - mRule.runOnUiThread(new Runnable() { - @Override - public void run() { - mDownloader.downloadWebAppManifest(uri, PaymentManifestDownloaderTest.this); - } - }); + mRule.runOnUiThread((Runnable) () -> mDownloader.downloadWebAppManifest(uri, + PaymentManifestDownloaderTest.this)); CriteriaHelper.pollInstrumentationThread(new Criteria() { @Override public boolean isSatisfied() { @@ -168,12 +152,8 @@ @Feature({"Payments"}) public void testDownloadPaymentMethodManifest() throws Throwable { final URI uri = new URI(mServer.getURL("/components/test/data/payments/bobpay.com/webpay")); - mRule.runOnUiThread(new Runnable() { - @Override - public void run() { - mDownloader.downloadPaymentMethodManifest(uri, PaymentManifestDownloaderTest.this); - } - }); + mRule.runOnUiThread((Runnable) () -> mDownloader.downloadPaymentMethodManifest(uri, + PaymentManifestDownloaderTest.this)); CriteriaHelper.pollInstrumentationThread(new Criteria() { @Override public boolean isSatisfied() { @@ -190,12 +170,8 @@ @Feature({"Payments"}) public void testUnableToDownloadPaymentMethodManifest() throws Throwable { final URI uri = new URI(mServer.getURL("/no-such-payment-method-name")); - mRule.runOnUiThread(new Runnable() { - @Override - public void run() { - mDownloader.downloadPaymentMethodManifest(uri, PaymentManifestDownloaderTest.this); - } - }); + mRule.runOnUiThread((Runnable) () -> mDownloader.downloadPaymentMethodManifest(uri, + PaymentManifestDownloaderTest.this)); CriteriaHelper.pollInstrumentationThread(new Criteria() { @Override public boolean isSatisfied() { @@ -216,16 +192,13 @@ final URI webAppUri1 = new URI(mServer.getURL("/no-such-app.json")); final URI webAppUri2 = new URI(mServer.getURL("/components/test/data/payments/bobpay.com/app.json")); - mRule.runOnUiThread(new Runnable() { - @Override - public void run() { - mDownloader.downloadPaymentMethodManifest( - paymentMethodUri1, PaymentManifestDownloaderTest.this); - mDownloader.downloadPaymentMethodManifest( - paymentMethodUri2, PaymentManifestDownloaderTest.this); - mDownloader.downloadWebAppManifest(webAppUri1, PaymentManifestDownloaderTest.this); - mDownloader.downloadWebAppManifest(webAppUri2, PaymentManifestDownloaderTest.this); - } + mRule.runOnUiThread((Runnable) () -> { + mDownloader.downloadPaymentMethodManifest( + paymentMethodUri1, PaymentManifestDownloaderTest.this); + mDownloader.downloadPaymentMethodManifest( + paymentMethodUri2, PaymentManifestDownloaderTest.this); + mDownloader.downloadWebAppManifest(webAppUri1, PaymentManifestDownloaderTest.this); + mDownloader.downloadWebAppManifest(webAppUri2, PaymentManifestDownloaderTest.this); }); CriteriaHelper.pollInstrumentationThread(new Criteria() { @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentManifestParserTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentManifestParserTest.java index 2e41989..4116aa2f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentManifestParserTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentManifestParserTest.java
@@ -70,12 +70,7 @@ @Before public void setUp() throws Throwable { mRule.startMainActivityOnBlankPage(); - mRule.runOnUiThread(new Runnable() { - @Override - public void run() { - mParser.startUtilityProcess(); - } - }); + mRule.runOnUiThread((Runnable) () -> mParser.startUtilityProcess()); mWebAppManifestUris = null; mSupportedOrigins = null; mAllOriginsSupported = false; @@ -87,25 +82,15 @@ @After public void tearDown() throws Throwable { - mRule.runOnUiThread(new Runnable() { - @Override - public void run() { - mParser.stopUtilityProcess(); - } - }); + mRule.runOnUiThread((Runnable) () -> mParser.stopUtilityProcess()); } @Test @MediumTest @Feature({"Payments"}) public void testParseInvalidPaymentMethodManifest() throws Throwable { - mRule.runOnUiThread(new Runnable() { - @Override - public void run() { - mParser.parsePaymentMethodManifest( - "invalid payment method manifest", PaymentManifestParserTest.this); - } - }); + mRule.runOnUiThread((Runnable) () -> mParser.parsePaymentMethodManifest( + "invalid payment method manifest", PaymentManifestParserTest.this)); CriteriaHelper.pollInstrumentationThread(new Criteria() { @Override public boolean isSatisfied() { @@ -118,22 +103,17 @@ @MediumTest @Feature({"Payments"}) public void testParsePaymentMethodManifest() throws Throwable { - mRule.runOnUiThread(new Runnable() { - @Override - public void run() { - mParser.parsePaymentMethodManifest("{" - + " \"default_applications\": [" - + " \"https://bobpay.com/app.json\"," - + " \"https://alicepay.com/app.json\"" - + " ]," - + " \"supported_origins\": [" - + " \"https://charliepay.com\"," - + " \"https://evepay.com\"" - + " ]" - + "}", - PaymentManifestParserTest.this); - } - }); + mRule.runOnUiThread((Runnable) () -> mParser.parsePaymentMethodManifest("{" + + " \"default_applications\": [" + + " \"https://bobpay.com/app.json\"," + + " \"https://alicepay.com/app.json\"" + + " ]," + + " \"supported_origins\": [" + + " \"https://charliepay.com\"," + + " \"https://evepay.com\"" + + " ]" + + "}", + PaymentManifestParserTest.this)); CriteriaHelper.pollInstrumentationThread(new Criteria() { @Override public boolean isSatisfied() { @@ -155,13 +135,8 @@ @MediumTest @Feature({"Payments"}) public void testParsePaymentMethodManifestWithAllOriginsSupported() throws Throwable { - mRule.runOnUiThread(new Runnable() { - @Override - public void run() { - mParser.parsePaymentMethodManifest( - "{\"supported_origins\": \"*\"}", PaymentManifestParserTest.this); - } - }); + mRule.runOnUiThread((Runnable) () -> mParser.parsePaymentMethodManifest( + "{\"supported_origins\": \"*\"}", PaymentManifestParserTest.this)); CriteriaHelper.pollInstrumentationThread(new Criteria() { @Override public boolean isSatisfied() { @@ -179,13 +154,8 @@ @MediumTest @Feature({"Payments"}) public void testParseInvalidWebAppManifest() throws Throwable { - mRule.runOnUiThread(new Runnable() { - @Override - public void run() { - mParser.parseWebAppManifest( - "invalid web app manifest", PaymentManifestParserTest.this); - } - }); + mRule.runOnUiThread((Runnable) () -> mParser.parseWebAppManifest( + "invalid web app manifest", PaymentManifestParserTest.this)); CriteriaHelper.pollInstrumentationThread(new Criteria() { @Override public boolean isSatisfied() { @@ -198,26 +168,21 @@ @MediumTest @Feature({"Payments"}) public void testParseWebAppManifest() throws Throwable { - mRule.runOnUiThread(new Runnable() { - @Override - public void run() { - mParser.parseWebAppManifest("{" - + " \"related_applications\": [{" - + " \"platform\": \"play\", " - + " \"id\": \"com.bobpay.app\", " - + " \"min_version\": \"1\", " - + " \"fingerprints\": [{" - + " \"type\": \"sha256_cert\", " - + " \"value\": \"" - + "00:01:02:03:04:05:06:07:08:09:" - + "A0:A1:A2:A3:A4:A5:A6:A7:A8:A9:" - + "B0:B1:B2:B3:B4:B5:B6:B7:B8:B9:C0:C1\"" - + " }]" - + " }]" - + "}", - PaymentManifestParserTest.this); - } - }); + mRule.runOnUiThread((Runnable) () -> mParser.parseWebAppManifest("{" + + " \"related_applications\": [{" + + " \"platform\": \"play\", " + + " \"id\": \"com.bobpay.app\", " + + " \"min_version\": \"1\", " + + " \"fingerprints\": [{" + + " \"type\": \"sha256_cert\", " + + " \"value\": \"" + + "00:01:02:03:04:05:06:07:08:09:" + + "A0:A1:A2:A3:A4:A5:A6:A7:A8:A9:" + + "B0:B1:B2:B3:B4:B5:B6:B7:B8:B9:C0:C1\"" + + " }]" + + " }]" + + "}", + PaymentManifestParserTest.this)); CriteriaHelper.pollInstrumentationThread(new Criteria() { @Override public boolean isSatisfied() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentMetricsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentMetricsTest.java index d79613c8..4f020bf 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentMetricsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentMetricsTest.java
@@ -68,17 +68,15 @@ // Press the back button. int callCount = mPaymentRequestTestRule.getDismissed().getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mPaymentRequestTestRule.getPaymentRequestUI().getDialogForTest().onBackPressed(); - } - }); + ThreadUtils.runOnUiThreadBlocking( + () -> mPaymentRequestTestRule.getPaymentRequestUI().getDialogForTest() + .onBackPressed()); mPaymentRequestTestRule.getDismissed().waitForCallback(callCount); mPaymentRequestTestRule.expectResultContains(new String[] {"Request cancelled"}); // Make sure the canMakePayment events were logged correctly. - int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.CAN_MAKE_PAYMENT_FALSE; + int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.CAN_MAKE_PAYMENT_FALSE + | Event.REQUEST_METHOD_BASIC_CARD | Event.REQUEST_METHOD_OTHER; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -118,7 +116,8 @@ // Make sure the canMakePayment events were logged correctly. int expectedSample = Event.SHOWN | Event.PAY_CLICKED | Event.RECEIVED_INSTRUMENT_DETAILS - | Event.COMPLETED | Event.CAN_MAKE_PAYMENT_FALSE; + | Event.COMPLETED | Event.CAN_MAKE_PAYMENT_FALSE | Event.REQUEST_METHOD_BASIC_CARD + | Event.REQUEST_METHOD_OTHER; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -147,7 +146,8 @@ // Make sure the canMakePayment events were logged correctly. int expectedSample = Event.SHOWN | Event.OTHER_ABORTED | Event.HAD_INITIAL_FORM_OF_PAYMENT - | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.CAN_MAKE_PAYMENT_TRUE; + | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.CAN_MAKE_PAYMENT_TRUE + | Event.REQUEST_METHOD_BASIC_CARD | Event.REQUEST_METHOD_OTHER; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -175,7 +175,8 @@ // Make sure the canMakePayment events were logged correctly. int expectedSample = Event.SHOWN | Event.PAY_CLICKED | Event.RECEIVED_INSTRUMENT_DETAILS | Event.COMPLETED | Event.HAD_INITIAL_FORM_OF_PAYMENT - | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.CAN_MAKE_PAYMENT_TRUE; + | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.CAN_MAKE_PAYMENT_TRUE + | Event.REQUEST_METHOD_BASIC_CARD | Event.REQUEST_METHOD_OTHER; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -196,17 +197,15 @@ // Press the back button. int callCount = mPaymentRequestTestRule.getDismissed().getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mPaymentRequestTestRule.getPaymentRequestUI().getDialogForTest().onBackPressed(); - } - }); + ThreadUtils.runOnUiThreadBlocking( + () -> mPaymentRequestTestRule.getPaymentRequestUI().getDialogForTest() + .onBackPressed()); mPaymentRequestTestRule.getDismissed().waitForCallback(callCount); mPaymentRequestTestRule.expectResultContains(new String[] {"Request cancelled"}); // Make sure no canMakePayment events were logged. - int expectedSample = Event.SHOWN | Event.USER_ABORTED; + int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.REQUEST_METHOD_BASIC_CARD + | Event.REQUEST_METHOD_OTHER; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -233,7 +232,8 @@ // Make sure no canMakePayment events were logged. int expectedSample = Event.SHOWN | Event.PAY_CLICKED | Event.RECEIVED_INSTRUMENT_DETAILS | Event.COMPLETED | Event.HAD_INITIAL_FORM_OF_PAYMENT - | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS; + | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_METHOD_BASIC_CARD + | Event.REQUEST_METHOD_OTHER; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCardEditorAutoAdvanceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCardEditorAutoAdvanceTest.java index 54bf1ae..1c138d5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCardEditorAutoAdvanceTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCardEditorAutoAdvanceTest.java
@@ -87,12 +87,7 @@ Assert.assertTrue(mPaymentRequestTestRule.getCardEditorFocusedView() != focusedChildView); // Request focus to card number field after auto advancing above. - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - focusedChildView.requestFocus(); - } - }); + ThreadUtils.runOnUiThreadBlocking((Runnable) () -> focusedChildView.requestFocus()); mPaymentRequestTestRule.setTextInCardEditorAndWait( new String[] {"3056 9309 0259 041"}, mPaymentRequestTestRule.getEditorTextUpdate()); Assert.assertTrue(mPaymentRequestTestRule.getCardEditorFocusedView() == focusedChildView); @@ -127,12 +122,7 @@ Assert.assertTrue(mPaymentRequestTestRule.getCardEditorFocusedView() != focusedChildView); // Request focus to card number field after auto advancing above. - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - focusedChildView.requestFocus(); - } - }); + ThreadUtils.runOnUiThreadBlocking((Runnable) () -> focusedChildView.requestFocus()); mPaymentRequestTestRule.setTextInCardEditorAndWait(new String[] {"3782 822463 10005 1"}, mPaymentRequestTestRule.getEditorTextUpdate()); Assert.assertTrue(mPaymentRequestTestRule.getCardEditorFocusedView() == focusedChildView); @@ -177,12 +167,7 @@ Assert.assertTrue(mPaymentRequestTestRule.getCardEditorFocusedView() != focusedChildView); // Request focus to card number field after auto advancing above. - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - focusedChildView.requestFocus(); - } - }); + ThreadUtils.runOnUiThreadBlocking((Runnable) () -> focusedChildView.requestFocus()); mPaymentRequestTestRule.setTextInCardEditorAndWait(new String[] {"4012 8888 8888 1881 1"}, mPaymentRequestTestRule.getEditorTextUpdate()); Assert.assertTrue(mPaymentRequestTestRule.getCardEditorFocusedView() == focusedChildView); @@ -226,12 +211,7 @@ Assert.assertTrue(mPaymentRequestTestRule.getCardEditorFocusedView() != focusedChildView); // Request focus to card number field after auto advancing above. - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - focusedChildView.requestFocus(); - } - }); + ThreadUtils.runOnUiThreadBlocking((Runnable) () -> focusedChildView.requestFocus()); mPaymentRequestTestRule.setTextInCardEditorAndWait( new String[] {"6212 3456 7890 0000 0031"}, mPaymentRequestTestRule.getEditorTextUpdate());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsAndFreeShippingTest.java index a2138b2..ed619ff 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsAndFreeShippingTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsAndFreeShippingTest.java
@@ -103,7 +103,8 @@ int expectedSample = Event.SHOWN | Event.PAY_CLICKED | Event.RECEIVED_INSTRUMENT_DETAILS | Event.COMPLETED | Event.HAD_INITIAL_FORM_OF_PAYMENT | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_PAYER_PHONE - | Event.REQUEST_PAYER_EMAIL | Event.REQUEST_PAYER_NAME | Event.REQUEST_SHIPPING; + | Event.REQUEST_PAYER_EMAIL | Event.REQUEST_PAYER_NAME | Event.REQUEST_SHIPPING + | Event.REQUEST_METHOD_BASIC_CARD | Event.REQUEST_METHOD_OTHER; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsTest.java index df69312..210f44f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsTest.java
@@ -143,18 +143,15 @@ // Quickly press on "add contact info" and then [X]. int callCount = mPaymentRequestTestRule.getReadyToEdit().getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mPaymentRequestTestRule.getPaymentRequestUI() - .getContactDetailsSectionForTest() - .findViewById(R.id.payments_add_option_button) - .performClick(); - mPaymentRequestTestRule.getPaymentRequestUI() - .getDialogForTest() - .findViewById(R.id.close_button) - .performClick(); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + mPaymentRequestTestRule.getPaymentRequestUI() + .getContactDetailsSectionForTest() + .findViewById(R.id.payments_add_option_button) + .performClick(); + mPaymentRequestTestRule.getPaymentRequestUI() + .getDialogForTest() + .findViewById(R.id.close_button) + .performClick(); }); mPaymentRequestTestRule.getReadyToEdit().waitForCallback(callCount); @@ -177,18 +174,15 @@ // Quickly press on [X] and then "add contact info." int callCount = mPaymentRequestTestRule.getDismissed().getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mPaymentRequestTestRule.getPaymentRequestUI() - .getDialogForTest() - .findViewById(R.id.close_button) - .performClick(); - mPaymentRequestTestRule.getPaymentRequestUI() - .getContactDetailsSectionForTest() - .findViewById(R.id.payments_add_option_button) - .performClick(); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + mPaymentRequestTestRule.getPaymentRequestUI() + .getDialogForTest() + .findViewById(R.id.close_button) + .performClick(); + mPaymentRequestTestRule.getPaymentRequestUI() + .getContactDetailsSectionForTest() + .findViewById(R.id.payments_add_option_button) + .performClick(); }); mPaymentRequestTestRule.getDismissed().waitForCallback(callCount); @@ -249,18 +243,15 @@ // Quickly press on "add contact info" and then "cancel." int callCount = mPaymentRequestTestRule.getReadyToEdit().getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mPaymentRequestTestRule.getPaymentRequestUI() - .getContactDetailsSectionForTest() - .findViewById(R.id.payments_add_option_button) - .performClick(); - mPaymentRequestTestRule.getPaymentRequestUI() - .getDialogForTest() - .findViewById(R.id.button_secondary) - .performClick(); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + mPaymentRequestTestRule.getPaymentRequestUI() + .getContactDetailsSectionForTest() + .findViewById(R.id.payments_add_option_button) + .performClick(); + mPaymentRequestTestRule.getPaymentRequestUI() + .getDialogForTest() + .findViewById(R.id.button_secondary) + .performClick(); }); mPaymentRequestTestRule.getReadyToEdit().waitForCallback(callCount); @@ -283,18 +274,15 @@ // Quickly press on "cancel" and then "add contact info." int callCount = mPaymentRequestTestRule.getDismissed().getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mPaymentRequestTestRule.getPaymentRequestUI() - .getDialogForTest() - .findViewById(R.id.button_secondary) - .performClick(); - mPaymentRequestTestRule.getPaymentRequestUI() - .getContactDetailsSectionForTest() - .findViewById(R.id.payments_add_option_button) - .performClick(); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + mPaymentRequestTestRule.getPaymentRequestUI() + .getDialogForTest() + .findViewById(R.id.button_secondary) + .performClick(); + mPaymentRequestTestRule.getPaymentRequestUI() + .getContactDetailsSectionForTest() + .findViewById(R.id.payments_add_option_button) + .performClick(); }); mPaymentRequestTestRule.getDismissed().waitForCallback(callCount); @@ -335,7 +323,8 @@ int expectedSample = Event.SHOWN | Event.COMPLETED | Event.PAY_CLICKED | Event.HAD_INITIAL_FORM_OF_PAYMENT | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.RECEIVED_INSTRUMENT_DETAILS | Event.REQUEST_PAYER_EMAIL - | Event.REQUEST_PAYER_PHONE | Event.REQUEST_PAYER_NAME; + | Event.REQUEST_PAYER_PHONE | Event.REQUEST_PAYER_NAME + | Event.REQUEST_METHOD_BASIC_CARD | Event.REQUEST_METHOD_OTHER; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java index a8cca016..3a60612 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java
@@ -229,18 +229,15 @@ // Quickly press "add address" and then [X]. int callCount = mPaymentRequestTestRule.getReadyToEdit().getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mPaymentRequestTestRule.getPaymentRequestUI() - .getShippingAddressSectionForTest() - .findViewById(R.id.payments_add_option_button) - .performClick(); - mPaymentRequestTestRule.getPaymentRequestUI() - .getDialogForTest() - .findViewById(R.id.close_button) - .performClick(); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + mPaymentRequestTestRule.getPaymentRequestUI() + .getShippingAddressSectionForTest() + .findViewById(R.id.payments_add_option_button) + .performClick(); + mPaymentRequestTestRule.getPaymentRequestUI() + .getDialogForTest() + .findViewById(R.id.close_button) + .performClick(); }); mPaymentRequestTestRule.getReadyToEdit().waitForCallback(callCount); @@ -263,18 +260,15 @@ // Quickly press [X] and then "add address." int callCount = mPaymentRequestTestRule.getDismissed().getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mPaymentRequestTestRule.getPaymentRequestUI() - .getDialogForTest() - .findViewById(R.id.close_button) - .performClick(); - mPaymentRequestTestRule.getPaymentRequestUI() - .getShippingAddressSectionForTest() - .findViewById(R.id.payments_add_option_button) - .performClick(); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + mPaymentRequestTestRule.getPaymentRequestUI() + .getDialogForTest() + .findViewById(R.id.close_button) + .performClick(); + mPaymentRequestTestRule.getPaymentRequestUI() + .getShippingAddressSectionForTest() + .findViewById(R.id.payments_add_option_button) + .performClick(); }); mPaymentRequestTestRule.getDismissed().waitForCallback(callCount); @@ -293,18 +287,15 @@ // Quickly press "add address" and then "cancel." int callCount = mPaymentRequestTestRule.getReadyToEdit().getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mPaymentRequestTestRule.getPaymentRequestUI() - .getShippingAddressSectionForTest() - .findViewById(R.id.payments_add_option_button) - .performClick(); - mPaymentRequestTestRule.getPaymentRequestUI() - .getDialogForTest() - .findViewById(R.id.button_secondary) - .performClick(); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + mPaymentRequestTestRule.getPaymentRequestUI() + .getShippingAddressSectionForTest() + .findViewById(R.id.payments_add_option_button) + .performClick(); + mPaymentRequestTestRule.getPaymentRequestUI() + .getDialogForTest() + .findViewById(R.id.button_secondary) + .performClick(); }); mPaymentRequestTestRule.getReadyToEdit().waitForCallback(callCount); @@ -327,18 +318,15 @@ // Quickly press on "cancel" and then "add address." int callCount = mPaymentRequestTestRule.getDismissed().getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mPaymentRequestTestRule.getPaymentRequestUI() - .getDialogForTest() - .findViewById(R.id.button_secondary) - .performClick(); - mPaymentRequestTestRule.getPaymentRequestUI() - .getShippingAddressSectionForTest() - .findViewById(R.id.payments_add_option_button) - .performClick(); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + mPaymentRequestTestRule.getPaymentRequestUI() + .getDialogForTest() + .findViewById(R.id.button_secondary) + .performClick(); + mPaymentRequestTestRule.getPaymentRequestUI() + .getShippingAddressSectionForTest() + .findViewById(R.id.payments_add_option_button) + .performClick(); }); mPaymentRequestTestRule.getDismissed().waitForCallback(callCount);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndFreeShippingTest.java index ea2454771..d356eaa 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndFreeShippingTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndFreeShippingTest.java
@@ -89,7 +89,7 @@ int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.HAD_INITIAL_FORM_OF_PAYMENT | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_PAYER_EMAIL - | Event.REQUEST_SHIPPING; + | Event.REQUEST_SHIPPING | Event.REQUEST_METHOD_BASIC_CARD; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndPhoneTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndPhoneTest.java index 3a07cee..9d991b6 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndPhoneTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndPhoneTest.java
@@ -161,7 +161,8 @@ int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.HAD_INITIAL_FORM_OF_PAYMENT | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_PAYER_EMAIL - | Event.REQUEST_PAYER_PHONE; + | Event.REQUEST_PAYER_PHONE | Event.REQUEST_METHOD_BASIC_CARD + | Event.REQUEST_METHOD_OTHER; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailTest.java index 275e152..4fc1a0b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailTest.java
@@ -159,7 +159,8 @@ int expectedSample = Event.SHOWN | Event.COMPLETED | Event.PAY_CLICKED | Event.HAD_INITIAL_FORM_OF_PAYMENT | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS - | Event.RECEIVED_INSTRUMENT_DETAILS | Event.REQUEST_PAYER_EMAIL; + | Event.RECEIVED_INSTRUMENT_DETAILS | Event.REQUEST_PAYER_EMAIL + | Event.REQUEST_METHOD_BASIC_CARD | Event.REQUEST_METHOD_OTHER; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java index 0973925..2677700 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java
@@ -169,18 +169,15 @@ // Quickly press on "add address" and then [X]. int callCount = mPaymentRequestTestRule.getReadyToEdit().getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mPaymentRequestTestRule.getPaymentRequestUI() - .getShippingAddressSectionForTest() - .findViewById(R.id.payments_add_option_button) - .performClick(); - mPaymentRequestTestRule.getPaymentRequestUI() - .getDialogForTest() - .findViewById(R.id.close_button) - .performClick(); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + mPaymentRequestTestRule.getPaymentRequestUI() + .getShippingAddressSectionForTest() + .findViewById(R.id.payments_add_option_button) + .performClick(); + mPaymentRequestTestRule.getPaymentRequestUI() + .getDialogForTest() + .findViewById(R.id.close_button) + .performClick(); }); mPaymentRequestTestRule.getReadyToEdit().waitForCallback(callCount); @@ -203,18 +200,15 @@ // Quickly press on [X] and then "add address." int callCount = mPaymentRequestTestRule.getDismissed().getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mPaymentRequestTestRule.getPaymentRequestUI() - .getDialogForTest() - .findViewById(R.id.close_button) - .performClick(); - mPaymentRequestTestRule.getPaymentRequestUI() - .getShippingAddressSectionForTest() - .findViewById(R.id.payments_add_option_button) - .performClick(); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + mPaymentRequestTestRule.getPaymentRequestUI() + .getDialogForTest() + .findViewById(R.id.close_button) + .performClick(); + mPaymentRequestTestRule.getPaymentRequestUI() + .getShippingAddressSectionForTest() + .findViewById(R.id.payments_add_option_button) + .performClick(); }); mPaymentRequestTestRule.getDismissed().waitForCallback(callCount); @@ -234,18 +228,15 @@ // Quickly press on "add address" and then "cancel." int callCount = mPaymentRequestTestRule.getReadyToEdit().getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mPaymentRequestTestRule.getPaymentRequestUI() - .getShippingAddressSectionForTest() - .findViewById(R.id.payments_add_option_button) - .performClick(); - mPaymentRequestTestRule.getPaymentRequestUI() - .getDialogForTest() - .findViewById(R.id.button_secondary) - .performClick(); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + mPaymentRequestTestRule.getPaymentRequestUI() + .getShippingAddressSectionForTest() + .findViewById(R.id.payments_add_option_button) + .performClick(); + mPaymentRequestTestRule.getPaymentRequestUI() + .getDialogForTest() + .findViewById(R.id.button_secondary) + .performClick(); }); mPaymentRequestTestRule.getReadyToEdit().waitForCallback(callCount); @@ -268,18 +259,15 @@ // Quickly press on "cancel" and then "add address." int callCount = mPaymentRequestTestRule.getDismissed().getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mPaymentRequestTestRule.getPaymentRequestUI() - .getDialogForTest() - .findViewById(R.id.button_secondary) - .performClick(); - mPaymentRequestTestRule.getPaymentRequestUI() - .getShippingAddressSectionForTest() - .findViewById(R.id.payments_add_option_button) - .performClick(); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + mPaymentRequestTestRule.getPaymentRequestUI() + .getDialogForTest() + .findViewById(R.id.button_secondary) + .performClick(); + mPaymentRequestTestRule.getPaymentRequestUI() + .getShippingAddressSectionForTest() + .findViewById(R.id.payments_add_option_button) + .performClick(); }); mPaymentRequestTestRule.getDismissed().waitForCallback(callCount); @@ -302,7 +290,8 @@ mPaymentRequestTestRule.expectResultContains(new String[] {"Request cancelled"}); int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.HAD_INITIAL_FORM_OF_PAYMENT - | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING; + | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING + | Event.REQUEST_METHOD_BASIC_CARD; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java index 774b983..d901f34 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java
@@ -578,7 +578,8 @@ // Make sure the events were logged correctly. int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.HAD_INITIAL_FORM_OF_PAYMENT - | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING; + | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING + | Event.REQUEST_METHOD_BASIC_CARD; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -611,7 +612,7 @@ // Make sure the events were logged correctly. int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.HAD_INITIAL_FORM_OF_PAYMENT - | Event.REQUEST_SHIPPING; + | Event.REQUEST_SHIPPING | Event.REQUEST_METHOD_BASIC_CARD; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -644,7 +645,7 @@ // Make sure the events were logged correctly. int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.HAD_INITIAL_FORM_OF_PAYMENT - | Event.REQUEST_SHIPPING; + | Event.REQUEST_SHIPPING | Event.REQUEST_METHOD_BASIC_CARD; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -676,7 +677,8 @@ mPaymentRequestTestRule.expectResultContains(new String[] {"Request cancelled"}); // Make sure the events were logged correctly. - int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.REQUEST_SHIPPING; + int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.REQUEST_SHIPPING + | Event.REQUEST_METHOD_BASIC_CARD; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -706,7 +708,8 @@ mPaymentRequestTestRule.expectResultContains(new String[] {"Request cancelled"}); // Make sure the events were logged correctly. - int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.REQUEST_SHIPPING; + int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.REQUEST_SHIPPING + | Event.REQUEST_METHOD_BASIC_CARD; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -736,7 +739,8 @@ mPaymentRequestTestRule.expectResultContains(new String[] {"Request cancelled"}); // Make sure the events were logged correctly. - int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.REQUEST_SHIPPING; + int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.REQUEST_SHIPPING + | Event.REQUEST_METHOD_BASIC_CARD | Event.REQUEST_METHOD_OTHER; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -767,7 +771,8 @@ // Make sure the events were logged correctly. int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.HAD_INITIAL_FORM_OF_PAYMENT - | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING; + | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING + | Event.REQUEST_METHOD_BASIC_CARD | Event.REQUEST_METHOD_OTHER; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -800,7 +805,8 @@ // Make sure the events were logged correctly. int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.HAD_INITIAL_FORM_OF_PAYMENT - | Event.REQUEST_SHIPPING; + | Event.REQUEST_SHIPPING | Event.REQUEST_METHOD_BASIC_CARD + | Event.REQUEST_METHOD_OTHER; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -834,7 +840,8 @@ // Make sure the events were logged correctly. int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.HAD_INITIAL_FORM_OF_PAYMENT - | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING; + | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING + | Event.REQUEST_METHOD_BASIC_CARD | Event.REQUEST_METHOD_OTHER; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -866,7 +873,8 @@ // Make sure the events were logged correctly. int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.HAD_INITIAL_FORM_OF_PAYMENT - | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING; + | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING + | Event.REQUEST_METHOD_BASIC_CARD | Event.REQUEST_METHOD_OTHER; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -901,7 +909,8 @@ // Make sure the events were logged correctly. int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.HAD_INITIAL_FORM_OF_PAYMENT - | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING; + | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING + | Event.REQUEST_METHOD_BASIC_CARD | Event.REQUEST_METHOD_OTHER; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -930,7 +939,8 @@ mPaymentRequestTestRule.expectResultContains(new String[] {"Request cancelled"}); // Make sure the events were logged correctly. - int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.REQUEST_SHIPPING; + int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.REQUEST_SHIPPING + | Event.REQUEST_METHOD_BASIC_CARD | Event.REQUEST_METHOD_OTHER; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -1030,10 +1040,20 @@ Assert.assertEquals(2, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.NumberOfSelectionEdits.ShippingAddress.Completed", 0)); + + // Make sure the events were logged correctly. + int expectedSample = Event.SHOWN | Event.COMPLETED | Event.REQUEST_SHIPPING + | Event.REQUEST_METHOD_BASIC_CARD | Event.HAD_INITIAL_FORM_OF_PAYMENT + | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.RECEIVED_INSTRUMENT_DETAILS + | Event.PAY_CLICKED; + Assert.assertEquals(2, + RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.Events", expectedSample)); } /** - * Expect that no journey metrics are logged if the payment request was not shown to the user. + * Expect that only some journey metrics are logged if the payment request was not shown to the + * user. */ @Test @MediumTest
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java index 1021786e..ccfea79 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java
@@ -90,7 +90,8 @@ // Make sure the events were logged correctly. int expectedSample = Event.SHOWN | Event.PAY_CLICKED | Event.RECEIVED_INSTRUMENT_DETAILS | Event.COMPLETED | Event.HAD_INITIAL_FORM_OF_PAYMENT - | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING; + | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING + | Event.REQUEST_METHOD_BASIC_CARD; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -112,15 +113,11 @@ // Cancel the Payment Request. int callCount = mPaymentRequestTestRule.getDismissed().getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mPaymentRequestTestRule.getPaymentRequestUI() + ThreadUtils.runOnUiThreadBlocking( + (Runnable) () -> mPaymentRequestTestRule.getPaymentRequestUI() .getDialogForTest() .findViewById(R.id.button_secondary) - .performClick(); - } - }); + .performClick()); mPaymentRequestTestRule.getDismissed().waitForCallback(callCount); mPaymentRequestTestRule.expectResultContains(new String[] {"Request cancelled"}); @@ -128,7 +125,8 @@ // Make sure the events were logged correctly. int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.HAD_INITIAL_FORM_OF_PAYMENT - | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING; + | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING + | Event.REQUEST_METHOD_BASIC_CARD; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -157,7 +155,8 @@ // Make sure the events were logged correctly. int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.HAD_INITIAL_FORM_OF_PAYMENT - | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING; + | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING + | Event.REQUEST_METHOD_BASIC_CARD; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -179,12 +178,9 @@ // Press the back button. int callCount = mPaymentRequestTestRule.getDismissed().getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mPaymentRequestTestRule.getPaymentRequestUI().getDialogForTest().onBackPressed(); - } - }); + ThreadUtils.runOnUiThreadBlocking( + () -> mPaymentRequestTestRule.getPaymentRequestUI().getDialogForTest() + .onBackPressed()); mPaymentRequestTestRule.getDismissed().waitForCallback(callCount); mPaymentRequestTestRule.expectResultContains(new String[] {"Request cancelled"}); @@ -192,7 +188,8 @@ // Make sure the events were logged correctly. int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.HAD_INITIAL_FORM_OF_PAYMENT - | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING; + | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING + | Event.REQUEST_METHOD_BASIC_CARD; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -221,7 +218,8 @@ // Make sure the events were logged correctly. int expectedSample = Event.SHOWN | Event.OTHER_ABORTED | Event.HAD_INITIAL_FORM_OF_PAYMENT - | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING; + | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING + | Event.REQUEST_METHOD_BASIC_CARD; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -248,7 +246,8 @@ // Make sure the events were logged correctly. int expectedSample = Event.SHOWN | Event.OTHER_ABORTED | Event.HAD_INITIAL_FORM_OF_PAYMENT - | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING; + | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING + | Event.REQUEST_METHOD_BASIC_CARD; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -382,7 +381,8 @@ // Make sure the events were logged correctly. int expectedSample = Event.SKIPPED_SHOW | Event.PAY_CLICKED | Event.RECEIVED_INSTRUMENT_DETAILS | Event.COMPLETED - | Event.HAD_INITIAL_FORM_OF_PAYMENT | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS; + | Event.HAD_INITIAL_FORM_OF_PAYMENT | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS + | Event.REQUEST_METHOD_GOOGLE; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -412,7 +412,7 @@ // Make sure the events were logged correctly. int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.HAD_INITIAL_FORM_OF_PAYMENT - | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS; + | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_METHOD_GOOGLE; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample)); @@ -447,9 +447,12 @@ R.id.close_button, mPaymentRequestTestRule.getDismissed()); mPaymentRequestTestRule.expectResultContains(new String[] {"Request cancelled"}); - // Make sure only one set of events was logged. - Assert.assertEquals( - 1, RecordHistogram.getHistogramTotalCountForTesting("PaymentRequest.Events")); + // Make sure the events were logged correctly. + int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.HAD_INITIAL_FORM_OF_PAYMENT + | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_METHOD_BASIC_CARD; + Assert.assertEquals(1, + RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.Events", expectedSample)); } /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameAndFreeShippingTest.java index 7bd2ab2..bfe8611 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameAndFreeShippingTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameAndFreeShippingTest.java
@@ -89,7 +89,7 @@ int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.HAD_INITIAL_FORM_OF_PAYMENT | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_SHIPPING - | Event.REQUEST_PAYER_NAME; + | Event.REQUEST_PAYER_NAME | Event.REQUEST_METHOD_BASIC_CARD; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameTest.java index 469b9ed..ed0c70f0a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameTest.java
@@ -171,7 +171,8 @@ int expectedSample = Event.SHOWN | Event.PAY_CLICKED | Event.RECEIVED_INSTRUMENT_DETAILS | Event.COMPLETED | Event.HAD_INITIAL_FORM_OF_PAYMENT - | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_PAYER_NAME; + | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_PAYER_NAME + | Event.REQUEST_METHOD_BASIC_CARD; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java index 6c55b0db..4c5e7463bd 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java
@@ -283,18 +283,15 @@ // Quickly press on "add card" and then [X]. int callCount = mPaymentRequestTestRule.getReadyToEdit().getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mPaymentRequestTestRule.getPaymentRequestUI() - .getPaymentMethodSectionForTest() - .findViewById(R.id.payments_add_option_button) - .performClick(); - mPaymentRequestTestRule.getPaymentRequestUI() - .getDialogForTest() - .findViewById(R.id.close_button) - .performClick(); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + mPaymentRequestTestRule.getPaymentRequestUI() + .getPaymentMethodSectionForTest() + .findViewById(R.id.payments_add_option_button) + .performClick(); + mPaymentRequestTestRule.getPaymentRequestUI() + .getDialogForTest() + .findViewById(R.id.close_button) + .performClick(); }); mPaymentRequestTestRule.getReadyToEdit().waitForCallback(callCount); @@ -317,18 +314,15 @@ // Quickly press on [X] and then "add card." int callCount = mPaymentRequestTestRule.getDismissed().getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mPaymentRequestTestRule.getPaymentRequestUI() - .getDialogForTest() - .findViewById(R.id.close_button) - .performClick(); - mPaymentRequestTestRule.getPaymentRequestUI() - .getPaymentMethodSectionForTest() - .findViewById(R.id.payments_add_option_button) - .performClick(); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + mPaymentRequestTestRule.getPaymentRequestUI() + .getDialogForTest() + .findViewById(R.id.close_button) + .performClick(); + mPaymentRequestTestRule.getPaymentRequestUI() + .getPaymentMethodSectionForTest() + .findViewById(R.id.payments_add_option_button) + .performClick(); }); mPaymentRequestTestRule.getDismissed().waitForCallback(callCount); @@ -347,18 +341,15 @@ // Quickly press on "add card" and then "cancel." int callCount = mPaymentRequestTestRule.getReadyToEdit().getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mPaymentRequestTestRule.getPaymentRequestUI() - .getPaymentMethodSectionForTest() - .findViewById(R.id.payments_add_option_button) - .performClick(); - mPaymentRequestTestRule.getPaymentRequestUI() - .getDialogForTest() - .findViewById(R.id.button_secondary) - .performClick(); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + mPaymentRequestTestRule.getPaymentRequestUI() + .getPaymentMethodSectionForTest() + .findViewById(R.id.payments_add_option_button) + .performClick(); + mPaymentRequestTestRule.getPaymentRequestUI() + .getDialogForTest() + .findViewById(R.id.button_secondary) + .performClick(); }); mPaymentRequestTestRule.getReadyToEdit().waitForCallback(callCount); @@ -381,18 +372,15 @@ // Quickly press on "cancel" and then "add card." int callCount = mPaymentRequestTestRule.getDismissed().getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mPaymentRequestTestRule.getPaymentRequestUI() - .getDialogForTest() - .findViewById(R.id.button_secondary) - .performClick(); - mPaymentRequestTestRule.getPaymentRequestUI() - .getPaymentMethodSectionForTest() - .findViewById(R.id.payments_add_option_button) - .performClick(); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + mPaymentRequestTestRule.getPaymentRequestUI() + .getDialogForTest() + .findViewById(R.id.button_secondary) + .performClick(); + mPaymentRequestTestRule.getPaymentRequestUI() + .getPaymentMethodSectionForTest() + .findViewById(R.id.payments_add_option_button) + .performClick(); }); mPaymentRequestTestRule.getDismissed().waitForCallback(callCount); @@ -412,15 +400,12 @@ // Quickly dismiss and then press on "pay." int callCount = mPaymentRequestTestRule.getDismissed().getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mPaymentRequestTestRule.getPaymentRequestUI().getDialogForTest().onBackPressed(); - mPaymentRequestTestRule.getPaymentRequestUI() - .getDialogForTest() - .findViewById(R.id.button_primary) - .performClick(); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + mPaymentRequestTestRule.getPaymentRequestUI().getDialogForTest().onBackPressed(); + mPaymentRequestTestRule.getPaymentRequestUI() + .getDialogForTest() + .findViewById(R.id.button_primary) + .performClick(); }); mPaymentRequestTestRule.getDismissed().waitForCallback(callCount); @@ -440,15 +425,12 @@ // Quickly dismiss and then press on [X]. int callCount = mPaymentRequestTestRule.getDismissed().getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mPaymentRequestTestRule.getPaymentRequestUI().getDialogForTest().onBackPressed(); - mPaymentRequestTestRule.getPaymentRequestUI() - .getDialogForTest() - .findViewById(R.id.close_button) - .performClick(); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + mPaymentRequestTestRule.getPaymentRequestUI().getDialogForTest().onBackPressed(); + mPaymentRequestTestRule.getPaymentRequestUI() + .getDialogForTest() + .findViewById(R.id.close_button) + .performClick(); }); mPaymentRequestTestRule.getDismissed().waitForCallback(callCount); @@ -468,15 +450,12 @@ // Quickly press on [X] and then dismiss. int callCount = mPaymentRequestTestRule.getDismissed().getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mPaymentRequestTestRule.getPaymentRequestUI() - .getDialogForTest() - .findViewById(R.id.close_button) - .performClick(); - mPaymentRequestTestRule.getPaymentRequestUI().getDialogForTest().onBackPressed(); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + mPaymentRequestTestRule.getPaymentRequestUI() + .getDialogForTest() + .findViewById(R.id.close_button) + .performClick(); + mPaymentRequestTestRule.getPaymentRequestUI().getDialogForTest().onBackPressed(); }); mPaymentRequestTestRule.getDismissed().waitForCallback(callCount); @@ -500,7 +479,7 @@ mPaymentRequestTestRule.expectResultContains(new String[] {"Request cancelled"}); int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.HAD_INITIAL_FORM_OF_PAYMENT - | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS; + | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_METHOD_BASIC_CARD; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppTest.java index 556da561..afa071a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppTest.java
@@ -21,14 +21,10 @@ import org.chromium.base.test.util.Feature; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeSwitches; -import org.chromium.chrome.browser.payments.PaymentAppFactory.PaymentAppCreatedCallback; -import org.chromium.chrome.browser.payments.PaymentAppFactory.PaymentAppFactoryAddition; import org.chromium.chrome.browser.payments.PaymentRequestTestCommon.TestPay; import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -import org.chromium.content_public.browser.WebContents; -import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; @@ -96,23 +92,15 @@ public void testPaymentWithInstrumentsAppResponseAfterDismissShouldNotCrash() throws InterruptedException, ExecutionException, TimeoutException { final TestPay app = new TestPay("https://bobpay.com", HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE); - PaymentAppFactory.getInstance().addAdditionalFactory(new PaymentAppFactoryAddition() { - @Override - public void create(WebContents webContents, Set<String> methodNames, - PaymentAppFactory.PaymentAppCreatedCallback callback) { - callback.onPaymentAppCreated(app); - callback.onAllPaymentAppsCreated(); - } - }); + PaymentAppFactory.getInstance().addAdditionalFactory( + (webContents, methodNames, callback) -> { + callback.onPaymentAppCreated(app); + callback.onAllPaymentAppsCreated(); + }); mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyForInput()); mPaymentRequestTestRule.clickAndWait( R.id.close_button, mPaymentRequestTestRule.getDismissed()); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - app.respond(); - } - }); + ThreadUtils.runOnUiThreadBlocking(() -> app.respond()); mPaymentRequestTestRule.expectResultContains( new String[] {"show() rejected", "Request cancelled"}); } @@ -126,21 +114,13 @@ public void testPaymentAppNoInstrumentsResponseAfterDismissShouldNotCrash() throws InterruptedException, ExecutionException, TimeoutException { final TestPay app = new TestPay("https://bobpay.com", NO_INSTRUMENTS, IMMEDIATE_RESPONSE); - PaymentAppFactory.getInstance().addAdditionalFactory(new PaymentAppFactoryAddition() { - @Override - public void create(WebContents webContents, Set<String> methodNames, - PaymentAppCreatedCallback callback) { - callback.onPaymentAppCreated(app); - callback.onAllPaymentAppsCreated(); - } - }); + PaymentAppFactory.getInstance().addAdditionalFactory( + (webContents, methodNames, callback) -> { + callback.onPaymentAppCreated(app); + callback.onAllPaymentAppsCreated(); + }); mPaymentRequestTestRule.openPageAndClickBuyAndWait(mPaymentRequestTestRule.getShowFailed()); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - app.respond(); - } - }); + ThreadUtils.runOnUiThreadBlocking(() -> app.respond()); mPaymentRequestTestRule.expectResultContains( new String[] {"show() rejected", "The payment method is not supported"}); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppsSortingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppsSortingTest.java index 54ea441..61e2038 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppsSortingTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppsSortingTest.java
@@ -22,15 +22,11 @@ import org.chromium.chrome.browser.autofill.CardType; import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard; -import org.chromium.chrome.browser.payments.PaymentAppFactory.PaymentAppCreatedCallback; -import org.chromium.chrome.browser.payments.PaymentAppFactory.PaymentAppFactoryAddition; import org.chromium.chrome.browser.payments.PaymentRequestTestCommon.TestPay; import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback; import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -import org.chromium.content_public.browser.WebContents; -import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; @@ -72,16 +68,13 @@ new TestPay("https://bobpay.com", HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE); final TestPay appC = new TestPay("https://charliepay.com", HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE); - PaymentAppFactory.getInstance().addAdditionalFactory(new PaymentAppFactoryAddition() { - @Override - public void create(WebContents webContents, Set<String> methodNames, - PaymentAppCreatedCallback callback) { - callback.onPaymentAppCreated(appA); - callback.onPaymentAppCreated(appB); - callback.onPaymentAppCreated(appC); - callback.onAllPaymentAppsCreated(); - } - }); + PaymentAppFactory.getInstance().addAdditionalFactory( + (webContents, methodNames, callback) -> { + callback.onPaymentAppCreated(appA); + callback.onPaymentAppCreated(appB); + callback.onPaymentAppCreated(appC); + callback.onAllPaymentAppsCreated(); + }); String alicePayId = appA.getAppIdentifier() + "https://alicepay.com"; String bobPayId = appB.getAppIdentifier() + "https://bobpay.com"; String charliePayId = appC.getAppIdentifier() + "https://charliepay.com";
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneAndFreeShippingTest.java index 1fe1867..de300066 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneAndFreeShippingTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneAndFreeShippingTest.java
@@ -96,7 +96,7 @@ int expectedSample = Event.SHOWN | Event.PAY_CLICKED | Event.RECEIVED_INSTRUMENT_DETAILS | Event.COMPLETED | Event.HAD_INITIAL_FORM_OF_PAYMENT | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_PAYER_PHONE - | Event.REQUEST_SHIPPING; + | Event.REQUEST_SHIPPING | Event.REQUEST_METHOD_BASIC_CARD; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneTest.java index a49b0384..cee5599 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneTest.java
@@ -158,7 +158,8 @@ mPaymentRequestTestRule.expectResultContains(new String[] {"Request cancelled"}); int expectedSample = Event.SHOWN | Event.USER_ABORTED | Event.HAD_INITIAL_FORM_OF_PAYMENT - | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_PAYER_PHONE; + | Event.HAD_NECESSARY_COMPLETE_SUGGESTIONS | Event.REQUEST_PAYER_PHONE + | Event.REQUEST_METHOD_BASIC_CARD | Event.REQUEST_METHOD_OTHER; Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "PaymentRequest.Events", expectedSample));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java index 97b9a03..59addaa9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java
@@ -15,9 +15,7 @@ import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -import org.chromium.content_public.browser.WebContents; -import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; @@ -41,19 +39,15 @@ */ private void installMockServiceWorkerPaymentApp(final boolean hasSupportedMethods) { PaymentAppFactory.getInstance().addAdditionalFactory( - new PaymentAppFactory.PaymentAppFactoryAddition() { - @Override - public void create(WebContents webContents, Set<String> methodNames, - PaymentAppFactory.PaymentAppCreatedCallback callback) { - String[] supportedMethodNames = {"https://bobpay.com", "basic-card"}; - callback.onPaymentAppCreated(new ServiceWorkerPaymentApp(webContents, - 0 /* registrationId */, "BobPay" /* label */, - "https://bobpay.com" /* sublabel */, null /* icon */, - hasSupportedMethods ? supportedMethodNames - : new String[0] /* methodNames */, - new String[0] /* preferredRelatedApplicationIds */)); - callback.onAllPaymentAppsCreated(); - } + (webContents, methodNames, callback) -> { + String[] supportedMethodNames = {"https://bobpay.com", "basic-card"}; + callback.onPaymentAppCreated(new ServiceWorkerPaymentApp(webContents, + 0 /* registrationId */, "BobPay" /* label */, + "https://bobpay.com" /* sublabel */, null /* icon */, + hasSupportedMethods ? supportedMethodNames + : new String[0] /* methodNames */, + new String[0] /* preferredRelatedApplicationIds */)); + callback.onAllPaymentAppsCreated(); }); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTabTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTabTest.java index b51c625e..3dae6f24 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTabTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTabTest.java
@@ -66,13 +66,10 @@ throws InterruptedException, ExecutionException, TimeoutException { mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyForInput()); Assert.assertEquals(0, mPaymentRequestTestRule.getDismissed().getCallCount()); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mPaymentRequestTestRule.getActivity().getTabCreator(false).createNewTab( - new LoadUrlParams("about:blank"), TabLaunchType.FROM_CHROME_UI, null); - } - }); + ThreadUtils.runOnUiThreadBlocking( + (Runnable) () -> mPaymentRequestTestRule.getActivity().getTabCreator( + false).createNewTab( + new LoadUrlParams("about:blank"), TabLaunchType.FROM_CHROME_UI, null)); mPaymentRequestTestRule.getDismissed().waitForCallback(0); } @@ -86,12 +83,9 @@ throws InterruptedException, ExecutionException, TimeoutException { mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyForInput()); Assert.assertEquals(0, mPaymentRequestTestRule.getDismissed().getCallCount()); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - TabModel currentModel = mPaymentRequestTestRule.getActivity().getCurrentTabModel(); - TabModelUtils.closeCurrentTab(currentModel); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + TabModel currentModel = mPaymentRequestTestRule.getActivity().getCurrentTabModel(); + TabModelUtils.closeCurrentTab(currentModel); }); mPaymentRequestTestRule.getDismissed().waitForCallback(0); } @@ -104,12 +98,9 @@ throws InterruptedException, ExecutionException, TimeoutException { mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyForInput()); Assert.assertEquals(0, mPaymentRequestTestRule.getDismissed().getCallCount()); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - TabModel currentModel = mPaymentRequestTestRule.getActivity().getCurrentTabModel(); - TabModelUtils.getCurrentTab(currentModel).loadUrl(new LoadUrlParams("about:blank")); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + TabModel currentModel = mPaymentRequestTestRule.getActivity().getCurrentTabModel(); + TabModelUtils.getCurrentTab(currentModel).loadUrl(new LoadUrlParams("about:blank")); }); mPaymentRequestTestRule.getDismissed().waitForCallback(0); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestCommon.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestCommon.java index 112218e..7e2d48a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestCommon.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestCommon.java
@@ -23,7 +23,6 @@ import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.autofill.CardUnmaskPrompt; import org.chromium.chrome.browser.autofill.CardUnmaskPrompt.CardUnmaskObserverForTest; -import org.chromium.chrome.browser.payments.PaymentAppFactory.PaymentAppFactoryAddition; import org.chromium.chrome.browser.payments.PaymentRequestImpl.PaymentRequestServiceObserverForTest; import org.chromium.chrome.browser.payments.ui.EditorTextField; import org.chromium.chrome.browser.payments.ui.PaymentRequestSection.OptionSection; @@ -141,15 +140,12 @@ private void openPage() throws InterruptedException, ExecutionException, TimeoutException { mCallback.onMainActivityStarted(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mViewCoreRef.set(mCallback.getActivity().getCurrentContentViewCore()); - mWebContentsRef.set(mViewCoreRef.get().getWebContents()); - PaymentRequestUI.setObserverForTest(PaymentRequestTestCommon.this); - PaymentRequestImpl.setObserverForTest(PaymentRequestTestCommon.this); - CardUnmaskPrompt.setObserverForTest(PaymentRequestTestCommon.this); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + mViewCoreRef.set(mCallback.getActivity().getCurrentContentViewCore()); + mWebContentsRef.set(mViewCoreRef.get().getWebContents()); + PaymentRequestUI.setObserverForTest(PaymentRequestTestCommon.this); + PaymentRequestImpl.setObserverForTest(PaymentRequestTestCommon.this); + CardUnmaskPrompt.setObserverForTest(PaymentRequestTestCommon.this); }); mCallback.assertWaitForPageScaleFactorMatch(1); } @@ -200,86 +196,62 @@ protected void clickAndWait(final int resourceId, CallbackHelper helper) throws InterruptedException, TimeoutException { int callCount = helper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mUI.getDialogForTest().findViewById(resourceId).performClick(); - } - }); + ThreadUtils.runOnUiThreadBlocking( + (Runnable) () -> mUI.getDialogForTest().findViewById(resourceId).performClick()); helper.waitForCallback(callCount); } protected void clickInShippingAddressAndWait(final int resourceId, CallbackHelper helper) throws InterruptedException, TimeoutException { int callCount = helper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mUI.getShippingAddressSectionForTest().findViewById(resourceId).performClick(); - } - }); + ThreadUtils.runOnUiThreadBlocking( + (Runnable) () -> mUI.getShippingAddressSectionForTest().findViewById( + resourceId).performClick()); helper.waitForCallback(callCount); } protected void clickInPaymentMethodAndWait(final int resourceId, CallbackHelper helper) throws InterruptedException, TimeoutException { int callCount = helper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mUI.getPaymentMethodSectionForTest().findViewById(resourceId).performClick(); - } - }); + ThreadUtils.runOnUiThreadBlocking( + (Runnable) () -> mUI.getPaymentMethodSectionForTest().findViewById( + resourceId).performClick()); helper.waitForCallback(callCount); } protected void clickInContactInfoAndWait(final int resourceId, CallbackHelper helper) throws InterruptedException, TimeoutException { int callCount = helper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mUI.getContactDetailsSectionForTest().findViewById(resourceId).performClick(); - } - }); + ThreadUtils.runOnUiThreadBlocking( + (Runnable) () -> mUI.getContactDetailsSectionForTest().findViewById( + resourceId).performClick()); helper.waitForCallback(callCount); } protected void clickInCardEditorAndWait(final int resourceId, CallbackHelper helper) throws InterruptedException, TimeoutException { int callCount = helper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mUI.getCardEditorDialog().findViewById(resourceId).performClick(); - } - }); + ThreadUtils.runOnUiThreadBlocking( + (Runnable) () -> mUI.getCardEditorDialog().findViewById(resourceId).performClick()); helper.waitForCallback(callCount); } protected void clickInEditorAndWait(final int resourceId, CallbackHelper helper) throws InterruptedException, TimeoutException { int callCount = helper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mUI.getEditorDialog().findViewById(resourceId).performClick(); - } - }); + ThreadUtils.runOnUiThreadBlocking( + (Runnable) () -> mUI.getEditorDialog().findViewById(resourceId).performClick()); helper.waitForCallback(callCount); } protected void clickAndroidBackButtonInEditorAndWait(CallbackHelper helper) throws InterruptedException, TimeoutException { int callCount = helper.getCallCount(); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - mUI.getEditorDialog().dispatchKeyEvent( - new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK)); - mUI.getEditorDialog().dispatchKeyEvent( - new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK)); - } + ThreadUtils.runOnUiThread(() -> { + mUI.getEditorDialog().dispatchKeyEvent( + new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK)); + mUI.getEditorDialog().dispatchKeyEvent( + new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK)); }); helper.waitForCallback(callCount); } @@ -287,152 +259,98 @@ protected void clickCardUnmaskButtonAndWait(final int dialogButtonId, CallbackHelper helper) throws InterruptedException, TimeoutException { int callCount = helper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mCardUnmaskPrompt.getDialogForTest().getButton(dialogButtonId).performClick(); - } - }); + ThreadUtils.runOnUiThreadBlocking( + (Runnable) () -> mCardUnmaskPrompt.getDialogForTest().getButton( + dialogButtonId).performClick()); helper.waitForCallback(callCount); } protected int getShippingAddressSectionButtonState() throws ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() { - @Override - public Integer call() { - return mUI.getShippingAddressSectionForTest().getEditButtonState(); - } - }); + return ThreadUtils.runOnUiThreadBlocking( + () -> mUI.getShippingAddressSectionForTest().getEditButtonState()); } protected int getContactDetailsButtonState() throws ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() { - @Override - public Integer call() { - return mUI.getContactDetailsSectionForTest().getEditButtonState(); - } - }); + return ThreadUtils.runOnUiThreadBlocking( + () -> mUI.getContactDetailsSectionForTest().getEditButtonState()); } protected String getPaymentInstrumentLabel(final int index) throws ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() { - @Override - public String call() { - return ((OptionSection) mUI.getPaymentMethodSectionForTest()) + return ThreadUtils.runOnUiThreadBlocking( + () -> ((OptionSection) mUI.getPaymentMethodSectionForTest()) .getOptionLabelsForTest(index) .getText() - .toString(); - } - }); + .toString()); } protected String getSelectedPaymentInstrumentLabel() throws ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() { - @Override - public String call() { - OptionSection section = ((OptionSection) mUI.getPaymentMethodSectionForTest()); - int size = section.getNumberOfOptionLabelsForTest(); - for (int i = 0; i < size; i++) { - if (section.getOptionRowAtIndex(i).isChecked()) { - return section.getOptionRowAtIndex(i).getLabelText().toString(); - } + return ThreadUtils.runOnUiThreadBlocking(() -> { + OptionSection section = ((OptionSection) mUI.getPaymentMethodSectionForTest()); + int size = section.getNumberOfOptionLabelsForTest(); + for (int i = 0; i < size; i++) { + if (section.getOptionRowAtIndex(i).isChecked()) { + return section.getOptionRowAtIndex(i).getLabelText().toString(); } - return null; } + return null; }); } protected String getOrderSummaryTotal() throws ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() { - @Override - public String call() { - return mUI.getOrderSummaryTotalTextViewForTest().getText().toString(); - } - }); + return ThreadUtils.runOnUiThreadBlocking( + () -> mUI.getOrderSummaryTotalTextViewForTest().getText().toString()); } protected String getContactDetailsSuggestionLabel(final int suggestionIndex) throws ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() { - @Override - public String call() { - return ((OptionSection) mUI.getContactDetailsSectionForTest()) + return ThreadUtils.runOnUiThreadBlocking( + () -> ((OptionSection) mUI.getContactDetailsSectionForTest()) .getOptionLabelsForTest(suggestionIndex) .getText() - .toString(); - } - }); + .toString()); } protected int getNumberOfPaymentInstruments() throws ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() { - @Override - public Integer call() { - return ((OptionSection) mUI.getPaymentMethodSectionForTest()) - .getNumberOfOptionLabelsForTest(); - } - }); + return ThreadUtils.runOnUiThreadBlocking( + () -> ((OptionSection) mUI.getPaymentMethodSectionForTest()) + .getNumberOfOptionLabelsForTest()); } protected int getNumberOfContactDetailSuggestions() throws ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() { - @Override - public Integer call() { - return ((OptionSection) mUI.getContactDetailsSectionForTest()) - .getNumberOfOptionLabelsForTest(); - } - }); + return ThreadUtils.runOnUiThreadBlocking( + () -> ((OptionSection) mUI.getContactDetailsSectionForTest()) + .getNumberOfOptionLabelsForTest()); } protected String getShippingAddressSuggestionLabel(final int suggestionIndex) throws ExecutionException { Assert.assertTrue(suggestionIndex < getNumberOfShippingAddressSuggestions()); - return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() { - @Override - public String call() { - return mUI.getShippingAddressSectionForTest() - .getOptionLabelsForTest(suggestionIndex) - .getText() - .toString(); - } - }); + return ThreadUtils.runOnUiThreadBlocking(() -> mUI.getShippingAddressSectionForTest() + .getOptionLabelsForTest(suggestionIndex) + .getText() + .toString()); } protected String getShippingAddressSummary() throws ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() { - @Override - public String call() { - return mUI.getShippingAddressSectionForTest() - .getLeftSummaryLabelForTest() - .getText() - .toString(); - } - }); + return ThreadUtils.runOnUiThreadBlocking(() -> mUI.getShippingAddressSectionForTest() + .getLeftSummaryLabelForTest() + .getText() + .toString()); } protected String getShippingOptionSummary() throws ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() { - @Override - public String call() { - return mUI.getShippingOptionSectionForTest() - .getLeftSummaryLabelForTest() - .getText() - .toString(); - } - }); + return ThreadUtils.runOnUiThreadBlocking(() -> mUI.getShippingOptionSectionForTest() + .getLeftSummaryLabelForTest() + .getText() + .toString()); } protected String getShippingOptionCostSummaryOnBottomSheet() throws ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() { - @Override - public String call() { - return mUI.getShippingOptionSectionForTest() - .getRightSummaryLabelForTest() - .getText() - .toString(); - } - }); + return ThreadUtils.runOnUiThreadBlocking(() -> mUI.getShippingOptionSectionForTest() + .getRightSummaryLabelForTest() + .getText() + .toString()); } protected View getCardEditorFocusedView() { @@ -445,14 +363,10 @@ Assert.assertTrue(suggestionIndex < getNumberOfShippingAddressSuggestions()); int callCount = helper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - ((OptionSection) mUI.getShippingAddressSectionForTest()) + ThreadUtils.runOnUiThreadBlocking( + (Runnable) () -> ((OptionSection) mUI.getShippingAddressSectionForTest()) .getOptionLabelsForTest(suggestionIndex) - .performClick(); - } - }); + .performClick()); helper.waitForCallback(callCount); } @@ -462,14 +376,10 @@ Assert.assertTrue(suggestionIndex < getNumberOfPaymentInstruments()); int callCount = helper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - ((OptionSection) mUI.getPaymentMethodSectionForTest()) + ThreadUtils.runOnUiThreadBlocking( + (Runnable) () -> ((OptionSection) mUI.getPaymentMethodSectionForTest()) .getOptionLabelsForTest(suggestionIndex) - .performClick(); - } - }); + .performClick()); helper.waitForCallback(callCount); } @@ -479,14 +389,10 @@ Assert.assertTrue(suggestionIndex < getNumberOfContactDetailSuggestions()); int callCount = helper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - ((OptionSection) mUI.getContactDetailsSectionForTest()) + ThreadUtils.runOnUiThreadBlocking( + (Runnable) () -> ((OptionSection) mUI.getContactDetailsSectionForTest()) .getOptionLabelsForTest(suggestionIndex) - .performClick(); - } - }); + .performClick()); helper.waitForCallback(callCount); } @@ -496,78 +402,51 @@ Assert.assertTrue(suggestionIndex < getNumberOfPaymentInstruments()); int callCount = helper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - ((OptionSection) mUI.getPaymentMethodSectionForTest()) + ThreadUtils.runOnUiThreadBlocking( + (Runnable) () -> ((OptionSection) mUI.getPaymentMethodSectionForTest()) .getOptionRowAtIndex(suggestionIndex) .getEditIconForTest() - .performClick(); - } - }); + .performClick()); helper.waitForCallback(callCount); } protected int getNumberOfShippingAddressSuggestions() throws ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() { - @Override - public Integer call() { - return ((OptionSection) mUI.getShippingAddressSectionForTest()) - .getNumberOfOptionLabelsForTest(); - } - }); + return ThreadUtils.runOnUiThreadBlocking( + () -> ((OptionSection) mUI.getShippingAddressSectionForTest()) + .getNumberOfOptionLabelsForTest()); } protected OptionRow getShippingAddressOptionRowAtIndex(final int index) throws ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<OptionRow>() { - @Override - public OptionRow call() { - return ((OptionSection) mUI.getShippingAddressSectionForTest()) - .getOptionRowAtIndex(index); - } - }); + return ThreadUtils.runOnUiThreadBlocking( + () -> ((OptionSection) mUI.getShippingAddressSectionForTest()) + .getOptionRowAtIndex(index)); } protected String getSpinnerSelectionTextInCardEditor(final int dropdownIndex) throws ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() { - @Override - public String call() { - return mUI.getCardEditorDialog() - .getDropdownFieldsForTest() - .get(dropdownIndex) - .getSelectedItem() - .toString(); - } - }); + return ThreadUtils.runOnUiThreadBlocking(() -> mUI.getCardEditorDialog() + .getDropdownFieldsForTest() + .get(dropdownIndex) + .getSelectedItem() + .toString()); } protected String getSpinnerTextAtPositionInCardEditor( final int dropdownIndex, final int itemPosition) throws ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() { - @Override - public String call() { - return mUI.getCardEditorDialog() - .getDropdownFieldsForTest() - .get(dropdownIndex) - .getItemAtPosition(itemPosition) - .toString(); - } - }); + return ThreadUtils.runOnUiThreadBlocking(() -> mUI.getCardEditorDialog() + .getDropdownFieldsForTest() + .get(dropdownIndex) + .getItemAtPosition(itemPosition) + .toString()); } protected int getSpinnerItemCountInCardEditor(final int dropdownIndex) throws ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() { - @Override - public Integer call() { - return mUI.getCardEditorDialog() - .getDropdownFieldsForTest() - .get(dropdownIndex) - .getCount(); - } - }); + return ThreadUtils.runOnUiThreadBlocking(() -> mUI.getCardEditorDialog() + .getDropdownFieldsForTest() + .get(dropdownIndex) + .getCount()); } protected String getUnmaskPromptErrorMessage() { @@ -577,13 +456,10 @@ protected void setSpinnerSelectionsInCardEditorAndWait(final int[] selections, CallbackHelper helper) throws InterruptedException, TimeoutException { int callCount = helper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - List<Spinner> fields = mUI.getCardEditorDialog().getDropdownFieldsForTest(); - for (int i = 0; i < selections.length && i < fields.size(); i++) { - fields.get(i).setSelection(selections[i]); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + List<Spinner> fields = mUI.getCardEditorDialog().getDropdownFieldsForTest(); + for (int i = 0; i < selections.length && i < fields.size(); i++) { + fields.get(i).setSelection(selections[i]); } }); helper.waitForCallback(callCount); @@ -592,30 +468,23 @@ protected void setSpinnerSelectionInEditorAndWait(final int selection, CallbackHelper helper) throws InterruptedException, TimeoutException { int callCount = helper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - ((Spinner) mUI.getEditorDialog().findViewById(R.id.spinner)) - .setSelection(selection); - } - }); + ThreadUtils.runOnUiThreadBlocking(() -> ((Spinner) mUI.getEditorDialog().findViewById( + R.id.spinner)) + .setSelection(selection)); helper.waitForCallback(callCount); } protected void setTextInCardEditorAndWait(final String[] values, CallbackHelper helper) throws InterruptedException, TimeoutException { int callCount = helper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - ViewGroup contents = - (ViewGroup) mUI.getCardEditorDialog().findViewById(R.id.contents); - Assert.assertNotNull(contents); - for (int i = 0, j = 0; i < contents.getChildCount() && j < values.length; i++) { - View view = contents.getChildAt(i); - if (view instanceof EditorTextField) { - ((EditorTextField) view).getEditText().setText(values[j++]); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + ViewGroup contents = + (ViewGroup) mUI.getCardEditorDialog().findViewById(R.id.contents); + Assert.assertNotNull(contents); + for (int i = 0, j = 0; i < contents.getChildCount() && j < values.length; i++) { + View view = contents.getChildAt(i); + if (view instanceof EditorTextField) { + ((EditorTextField) view).getEditText().setText(values[j++]); } } }); @@ -625,13 +494,10 @@ protected void setTextInEditorAndWait(final String[] values, CallbackHelper helper) throws InterruptedException, TimeoutException { int callCount = helper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - List<EditText> fields = mUI.getEditorDialog().getEditableTextFieldsForTest(); - for (int i = 0; i < values.length; i++) { - fields.get(i).setText(values[i]); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + List<EditText> fields = mUI.getEditorDialog().getEditableTextFieldsForTest(); + for (int i = 0; i < values.length; i++) { + fields.get(i).setText(values[i]); } }); helper.waitForCallback(callCount); @@ -640,27 +506,20 @@ protected void selectCheckboxAndWait(final int resourceId, final boolean isChecked, CallbackHelper helper) throws InterruptedException, TimeoutException { int callCount = helper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - ((CheckBox) mUI.getCardEditorDialog().findViewById(resourceId)) - .setChecked(isChecked); - } - }); + ThreadUtils.runOnUiThreadBlocking(() -> ((CheckBox) mUI.getCardEditorDialog().findViewById( + resourceId)) + .setChecked(isChecked)); helper.waitForCallback(callCount); } protected void setTextInCardUnmaskDialogAndWait(final int resourceId, final String input, CallbackHelper helper) throws InterruptedException, TimeoutException { int callCount = helper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - EditText editText = - ((EditText) mCardUnmaskPrompt.getDialogForTest().findViewById(resourceId)); - editText.setText(input); - editText.getOnFocusChangeListener().onFocusChange(null, false); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + EditText editText = + ((EditText) mCardUnmaskPrompt.getDialogForTest().findViewById(resourceId)); + editText.setText(input); + editText.getOnFocusChangeListener().onFocusChange(null, false); }); helper.waitForCallback(callCount); } @@ -670,16 +529,13 @@ throws InterruptedException, TimeoutException { assert resourceIds.length == values.length; int callCount = helper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - for (int i = 0; i < resourceIds.length; ++i) { - EditText editText = - ((EditText) mCardUnmaskPrompt.getDialogForTest().findViewById( - resourceIds[i])); - editText.setText(values[i]); - editText.getOnFocusChangeListener().onFocusChange(null, false); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + for (int i = 0; i < resourceIds.length; ++i) { + EditText editText = + ((EditText) mCardUnmaskPrompt.getDialogForTest().findViewById( + resourceIds[i])); + editText.setText(values[i]); + editText.getOnFocusChangeListener().onFocusChange(null, false); } }); helper.waitForCallback(callCount); @@ -688,14 +544,11 @@ /* package */ void hitSoftwareKeyboardSubmitButtonAndWait(final int resourceId, CallbackHelper helper) throws InterruptedException, TimeoutException { int callCount = helper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - EditText editText = - (EditText) mCardUnmaskPrompt.getDialogForTest().findViewById(resourceId); - editText.requestFocus(); - editText.onEditorAction(EditorInfo.IME_ACTION_DONE); - } + ThreadUtils.runOnUiThreadBlocking(() -> { + EditText editText = + (EditText) mCardUnmaskPrompt.getDialogForTest().findViewById(resourceId); + editText.requestFocus(); + editText.onEditorAction(EditorInfo.IME_ACTION_DONE); }); helper.waitForCallback(callCount); } @@ -794,13 +647,9 @@ } /* package */ View getCardUnmaskView() throws Throwable { - return ThreadUtils.runOnUiThreadBlocking(new Callable<View>() { - @Override - public View call() { - return mCardUnmaskPrompt.getDialogForTest().findViewById( - R.id.autofill_card_unmask_prompt); - } - }); + return ThreadUtils.runOnUiThreadBlocking( + () -> mCardUnmaskPrompt.getDialogForTest().findViewById( + R.id.autofill_card_unmask_prompt)); } @Override @@ -937,25 +786,20 @@ void installPaymentApp(final String appMethodName, final int instrumentPresence, final int responseSpeed, final int creationSpeed) { - PaymentAppFactory.getInstance().addAdditionalFactory(new PaymentAppFactoryAddition() { - @Override - public void create(WebContents webContents, Set<String> methodNames, - final PaymentAppFactory.PaymentAppCreatedCallback callback) { - final TestPay app = new TestPay(appMethodName, instrumentPresence, responseSpeed); - if (creationSpeed == IMMEDIATE_CREATION) { - callback.onPaymentAppCreated(app); - callback.onAllPaymentAppsCreated(); - } else { - new Handler().postDelayed(new Runnable() { - @Override - public void run() { + PaymentAppFactory.getInstance().addAdditionalFactory( + (webContents, methodNames, callback) -> { + final TestPay app = new TestPay(appMethodName, instrumentPresence, + responseSpeed); + if (creationSpeed == IMMEDIATE_CREATION) { + callback.onPaymentAppCreated(app); + callback.onAllPaymentAppsCreated(); + } else { + new Handler().postDelayed(() -> { callback.onPaymentAppCreated(app); callback.onAllPaymentAppsCreated(); - } - }, 100); - } - } - }); + }, 100); + } + }); } /** A payment app implementation for test. */ @@ -985,12 +829,9 @@ instruments.add(new TestPayInstrument( getAppIdentifier(), mDefaultMethodName, mDefaultMethodName)); } - Runnable instrumentsReady = new Runnable() { - @Override - public void run() { - ThreadUtils.assertOnUiThread(); - mCallback.onInstrumentsReady(TestPay.this, instruments); - } + Runnable instrumentsReady = () -> { + ThreadUtils.assertOnUiThread(); + mCallback.onInstrumentsReady(TestPay.this, instruments); }; if (mResponseSpeed == IMMEDIATE_RESPONSE) { instrumentsReady.run();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTransitionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTransitionTest.java index c9051fa3..ac306b7 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTransitionTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTransitionTest.java
@@ -59,6 +59,23 @@ } /** + * Tests that WebVR is not exposed if the flag is not on and the page does + * not have an origin trial token. + */ + @Test + @MediumTest + @CommandLineFlags.Remove({"enable-webvr"}) + public void testWebVrDisabledWithoutFlagSet() throws InterruptedException { + // TODO(bsheedy): Remove this test once WebVR is on by default without + // requiring an origin trial. + mVrTestRule.loadUrlAndAwaitInitialization( + VrTestRule.getHtmlTestFile("test_webvr_disabled_without_flag_set"), + PAGE_LOAD_TIMEOUT_S); + mVrTestRule.waitOnJavaScriptStep(mVrTestRule.getFirstTabWebContents()); + mVrTestRule.endTest(mVrTestRule.getFirstTabWebContents()); + } + + /** * Tests that scanning the Daydream View NFC tag on supported devices fires the * vrdisplayactivate event. */
diff --git a/chrome/app/media_router_strings.grdp b/chrome/app/media_router_strings.grdp index 6f6b689..78db4368 100644 --- a/chrome/app/media_router_strings.grdp +++ b/chrome/app/media_router_strings.grdp
@@ -169,6 +169,12 @@ <message name="IDS_MEDIA_ROUTER_ROUTE_DETAILS_VOLUME_TITLE" desc="The title label for a volume control bar for media contents."> Volume </message> + <message name="IDS_MEDIA_ROUTER_ROUTE_DETAILS_CURRENT_TIME_LABEL" desc="The label for the current time position of media contents."> + Current time + </message> + <message name="IDS_MEDIA_ROUTER_ROUTE_DETAILS_DURATION_LABEL" desc="The label for the total duration of media contents."> + Duration + </message> <!-- Sink List --> <message name="IDS_MEDIA_ROUTER_DESTINATION_MISSING" desc="Link to display when no Cast destinations are found which, on click, opens a page to the Chromecast help center explaining possible reasons why none are detected.">
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 509d1d97..ed0a6ef 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -924,9 +924,6 @@ <message name="IDS_SETTINGS_PRINTING_CUPS_PRINTERS_ADD_PRINTER" desc="In CUPS printing settings subpage, text for the link adding a new CUPS printer."> Add Printer </message> - <message name="IDS_SETTINGS_PRINTING_CUPS_PRINTERS_DETAILS" desc="Text for the drop down menu which allows the user to see the printer details."> - Details - </message> <message name="IDS_SETTINGS_PRINTING_CUPS_PRINTERS_EDIT" desc="Text for the drop down menu which allows the user to edit the printer details."> Edit </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index b1f3d01..f8f04b38 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -3693,10 +3693,16 @@ if ((is_linux && !is_chromeos) || is_win) { sources += [ + "feature_engagement/feature_tracker.cc", + "feature_engagement/feature_tracker.h", "feature_engagement/new_tab/new_tab_tracker.cc", "feature_engagement/new_tab/new_tab_tracker.h", "feature_engagement/new_tab/new_tab_tracker_factory.cc", "feature_engagement/new_tab/new_tab_tracker_factory.h", + "feature_engagement/session_duration_updater.cc", + "feature_engagement/session_duration_updater.h", + "feature_engagement/session_duration_updater_factory.cc", + "feature_engagement/session_duration_updater_factory.h", ] }
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index 1251b2d..2d8234d 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS
@@ -151,7 +151,29 @@ # are commonly referenced by renderer-side and browser-side code, and # does not use Blink types like WTF. "+third_party/WebKit/common", + + # The following restrictions are for ChromeOS and in particular mus/mash where + # Ozone does not run in process. If the linux build transitions to Ozone then + # we likely need to make these restrictions applicable only to ChromeOS files. + "-ui/events/ozone", + "-ui/ozone", + "+ui/ozone/public/ozone_switches.h", + # ui/events/devices is tied with ozone, which is controlled by mus, and + # shouldn't be used by Chrome directly. + "-ui/events/devices", + # Enums and supporting classes or observers that are safe (should be moved to + # services/ui/public/cpp). http://crbug.com/747544. + "+ui/events/devices/device_hotplug_event_observer.h", + "+ui/events/devices/input_device.h", + "+ui/events/devices/input_device_event_observer.h", + "+ui/events/devices/stylus_state.h", + "+ui/events/devices/touchscreen_device.h", + "+ui/events/devices/input_device_manager.h", + + # Only used by X11 (non-ChromeOS) code, which can use X directly. + "+ui/events/devices/x11", ] + specific_include_rules = { # TODO(mash): Remove. http://crbug.com/678705 "fullscreen_chromeos\.cc": [
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 0d6c1c459..c30ae496 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -2973,7 +2973,7 @@ FEATURE_VALUE_TYPE(omnibox::kOmniboxTailSuggestions)}, {"enable-new-app-menu-icon", flag_descriptions::kEnableNewAppMenuIconName, flag_descriptions::kEnableNewAppMenuIconDescription, kOsDesktop, - SINGLE_VALUE_TYPE(switches::kEnableNewAppMenuIcon)}, + FEATURE_VALUE_TYPE(features::kAnimatedAppMenuIcon)}, #endif // defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN) #if defined(OS_ANDROID)
diff --git a/chrome/browser/android/instantapps/instant_apps_infobar_delegate.cc b/chrome/browser/android/instantapps/instant_apps_infobar_delegate.cc index 4d3fc0c..459795c 100644 --- a/chrome/browser/android/instantapps/instant_apps_infobar_delegate.cc +++ b/chrome/browser/android/instantapps/instant_apps_infobar_delegate.cc
@@ -78,6 +78,17 @@ } } +bool InstantAppsInfoBarDelegate::ShouldExpire( + const NavigationDetails& details) const { + content::WebContents* web_contents = + InfoBarService::WebContentsFromInfoBar(infobar()); + bool navigation_url_is_launch_url = + web_contents != NULL && + web_contents->GetURL().EqualsIgnoringRef(GURL(url_)); + return !navigation_url_is_launch_url && + ConfirmInfoBarDelegate::ShouldExpire(details); +} + void Launch(JNIEnv* env, const base::android::JavaParamRef<jclass>& clazz, const base::android::JavaParamRef<jobject>& jweb_contents,
diff --git a/chrome/browser/android/instantapps/instant_apps_infobar_delegate.h b/chrome/browser/android/instantapps/instant_apps_infobar_delegate.h index c9933a9..cdf20ea8 100644 --- a/chrome/browser/android/instantapps/instant_apps_infobar_delegate.h +++ b/chrome/browser/android/instantapps/instant_apps_infobar_delegate.h
@@ -24,6 +24,9 @@ base::android::ScopedJavaGlobalRef<jobject> data() { return data_; } + // ConfirmInfoBarDelegate: + bool ShouldExpire(const NavigationDetails& details) const override; + // WebContentsObserver: void DidFinishNavigation( content::NavigationHandle* navigation_handle) override;
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc index 3358114..e011d41 100644 --- a/chrome/browser/apps/guest_view/web_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -62,6 +62,7 @@ #include "content/public/common/child_process_host.h" #include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" +#include "content/public/common/url_constants.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/download_test_observer.h" #include "content/public/test/fake_speech_recognition_manager.h" @@ -79,6 +80,7 @@ #include "extensions/common/extensions_client.h" #include "extensions/test/extension_test_message_listener.h" #include "media/base/media_switches.h" +#include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" @@ -4222,3 +4224,164 @@ chrome::CloseTab(browser()); } #endif + +// This test class makes "isolated.com" an isolated origin, to be used in +// testing isolated origins inside of a WebView. +class IsolatedOriginWebViewTest : public WebViewTest { + public: + IsolatedOriginWebViewTest() {} + ~IsolatedOriginWebViewTest() override {} + + protected: + void SetUpCommandLine(base::CommandLine* command_line) override { + ASSERT_TRUE(embedded_test_server()->InitializeAndListen()); + + std::string origin = + embedded_test_server()->GetURL("isolated.com", "/").spec(); + command_line->AppendSwitchASCII(switches::kIsolateOrigins, origin); + WebViewTest::SetUpCommandLine(command_line); + } + + void SetUpOnMainThread() override { + host_resolver()->AddRule("*", "127.0.0.1"); + embedded_test_server()->StartAcceptingConnections(); + WebViewTest::SetUpOnMainThread(); + } +}; +INSTANTIATE_TEST_CASE_P(WebViewTests, + IsolatedOriginWebViewTest, + testing::Bool()); + +// Test isolated origins inside a WebView, and make sure that loading an +// isolated origin in a regular tab's subframe doesn't reuse a WebView process +// that had loaded it previously, which would result in renderer kills. See +// https://crbug.com/751916 and https://crbug.com/751920. +IN_PROC_BROWSER_TEST_P(IsolatedOriginWebViewTest, IsolatedOriginInWebview) { + LoadAppWithGuest("web_view/simple"); + content::WebContents* guest = GetGuestWebContents(); + + // Navigate <webview> to an isolated origin. + GURL isolated_url( + embedded_test_server()->GetURL("isolated.com", "/title1.html")); + { + content::TestNavigationObserver load_observer(guest); + EXPECT_TRUE( + ExecuteScript(guest, "location.href = '" + isolated_url.spec() + "';")); + load_observer.Wait(); + } + + // TODO(alexmos, creis): The isolated origin currently has to use the + // chrome-guest:// SiteInstance, rather than a SiteInstance with its own + // meaningful site URL. This should be fixed as part of + // https://crbug.com/734722. + EXPECT_TRUE(guest->GetMainFrame()->GetSiteInstance()->GetSiteURL().SchemeIs( + content::kGuestScheme)); + + // Now, navigate <webview> to a regular page with a subframe. + GURL foo_url(embedded_test_server()->GetURL("foo.com", "/iframe.html")); + { + content::TestNavigationObserver load_observer(guest); + EXPECT_TRUE( + ExecuteScript(guest, "location.href = '" + foo_url.spec() + "';")); + load_observer.Wait(); + } + + // Navigate subframe in <webview> to an isolated origin. + EXPECT_TRUE(NavigateIframeToURL(guest, "test", isolated_url)); + + // TODO(alexmos, creis): Unfortunately, the subframe currently has to stay in + // the guest process. The expectations here should change once WebViews + // can support OOPIFs. See https://crbug.com/614463. + content::RenderFrameHost* webview_subframe = + ChildFrameAt(guest->GetMainFrame(), 0); + EXPECT_EQ(webview_subframe->GetProcess(), + guest->GetMainFrame()->GetProcess()); + EXPECT_EQ(webview_subframe->GetSiteInstance(), + guest->GetMainFrame()->GetSiteInstance()); + + // Load a page with subframe in a regular tab. + AddTabAtIndex(0, foo_url, ui::PAGE_TRANSITION_TYPED); + content::WebContents* tab = + browser()->tab_strip_model()->GetActiveWebContents(); + + // Navigate that subframe to an isolated origin. This should not join the + // WebView process, which has isolated.foo.com committed in a different + // storage partition. + EXPECT_TRUE(NavigateIframeToURL(tab, "test", isolated_url)); + content::RenderFrameHost* subframe = ChildFrameAt(tab->GetMainFrame(), 0); + EXPECT_NE(guest->GetMainFrame()->GetProcess(), subframe->GetProcess()); + + // Check that the guest process hasn't crashed. + EXPECT_TRUE(guest->GetMainFrame()->IsRenderFrameLive()); + + // Check that accessing a foo.com cookie from the WebView doesn't result in a + // renderer kill. This might happen if we erroneously applied an isolated.com + // origin lock to the WebView process when committing isolated.com. + bool cookie_is_correct = false; + EXPECT_TRUE(ExecuteScriptAndExtractBool( + guest, + "document.cookie = 'foo=bar';\n" + "window.domAutomationController.send(document.cookie == 'foo=bar');\n", + &cookie_is_correct)); + EXPECT_TRUE(cookie_is_correct); +} + +// This test is similar to IsolatedOriginInWebview above, but loads an isolated +// origin in a <webview> subframe *after* loading the same isolated origin in a +// regular tab's subframe. The isolated origin's subframe in the <webview> +// subframe should not reuse the regular tab's subframe process. See +// https://crbug.com/751916 and https://crbug.com/751920. +IN_PROC_BROWSER_TEST_P(IsolatedOriginWebViewTest, + LoadIsolatedOriginInWebviewAfterLoadingInRegularTab) { + LoadAppWithGuest("web_view/simple"); + content::WebContents* guest = GetGuestWebContents(); + + // Load a page with subframe in a regular tab. + GURL foo_url(embedded_test_server()->GetURL("foo.com", "/iframe.html")); + AddTabAtIndex(0, foo_url, ui::PAGE_TRANSITION_TYPED); + content::WebContents* tab = + browser()->tab_strip_model()->GetActiveWebContents(); + + // Navigate that subframe to an isolated origin. + GURL isolated_url( + embedded_test_server()->GetURL("isolated.com", "/title1.html")); + EXPECT_TRUE(NavigateIframeToURL(tab, "test", isolated_url)); + content::RenderFrameHost* subframe = ChildFrameAt(tab->GetMainFrame(), 0); + EXPECT_NE(tab->GetMainFrame()->GetProcess(), subframe->GetProcess()); + + // Navigate <webview> to a regular page with an isolated origin subframe. + { + content::TestNavigationObserver load_observer(guest); + EXPECT_TRUE( + ExecuteScript(guest, "location.href = '" + foo_url.spec() + "';")); + load_observer.Wait(); + } + EXPECT_TRUE(NavigateIframeToURL(guest, "test", isolated_url)); + + // TODO(alexmos, creis): The subframe currently has to stay in the guest + // process. The expectations here should change once WebViews can support + // OOPIFs. See https://crbug.com/614463. + content::RenderFrameHost* webview_subframe = + ChildFrameAt(guest->GetMainFrame(), 0); + EXPECT_EQ(webview_subframe->GetProcess(), + guest->GetMainFrame()->GetProcess()); + EXPECT_EQ(webview_subframe->GetSiteInstance(), + guest->GetMainFrame()->GetSiteInstance()); + EXPECT_NE(webview_subframe->GetProcess(), subframe->GetProcess()); + + // Check that the guest and regular tab processes haven't crashed. + EXPECT_TRUE(guest->GetMainFrame()->IsRenderFrameLive()); + EXPECT_TRUE(tab->GetMainFrame()->IsRenderFrameLive()); + EXPECT_TRUE(subframe->IsRenderFrameLive()); + + // Check that accessing a foo.com cookie from the WebView doesn't result in a + // renderer kill. This might happen if we erroneously applied an isolated.com + // origin lock to the WebView process when committing isolated.com. + bool cookie_is_correct = false; + EXPECT_TRUE(ExecuteScriptAndExtractBool( + guest, + "document.cookie = 'foo=bar';\n" + "window.domAutomationController.send(document.cookie == 'foo=bar');\n", + &cookie_is_correct)); + EXPECT_TRUE(cookie_is_correct); +}
diff --git a/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc b/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc index 6ec3b8e..943de7f 100644 --- a/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc
@@ -47,7 +47,7 @@ #include "extensions/test/extension_test_message_listener.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "ui/base/ime/composition_text.h" -#include "ui/base/ime/composition_underline.h" +#include "ui/base/ime/ime_text_span.h" #include "ui/base/ime/text_input_client.h" #include "ui/base/test/ui_controls.h" #include "ui/events/keycodes/keyboard_codes.h" @@ -1724,7 +1724,7 @@ target_web_contents->GetRenderWidgetHostView()->GetRenderWidgetHost(); content::SendImeCommitTextToWidget( target_rwh_for_input, base::UTF8ToUTF16("C"), - std::vector<ui::CompositionUnderline>(), gfx::Range(4, 5), 0); + std::vector<ui::ImeTextSpan>(), gfx::Range(4, 5), 0); input_listener.WaitUntilSatisfied(); // Get the input value from the guest. @@ -1790,7 +1790,7 @@ CompositionRangeUpdateObserver observer(embedder_web_contents); content::SendImeSetCompositionTextToWidget( target_web_contents->GetRenderWidgetHostView()->GetRenderWidgetHost(), - base::UTF8ToUTF16("ABC"), std::vector<ui::CompositionUnderline>(), + base::UTF8ToUTF16("ABC"), std::vector<ui::ImeTextSpan>(), gfx::Range::InvalidRange(), 0, 3); observer.WaitForCompositionRangeLength(3U); }
diff --git a/chrome/browser/chrome_service.cc b/chrome/browser/chrome_service.cc index 372235e..e90a954 100644 --- a/chrome/browser/chrome_service.cc +++ b/chrome/browser/chrome_service.cc
@@ -12,10 +12,10 @@ } ChromeService::ChromeService() { +#if defined(OS_CHROMEOS) #if defined(USE_OZONE) input_device_controller_.AddInterface(®istry_); #endif -#if defined(OS_CHROMEOS) registry_.AddInterface( base::Bind(&chromeos::Launchable::Bind, base::Unretained(&launchable_))); #endif
diff --git a/chrome/browser/chrome_service.h b/chrome/browser/chrome_service.h index ffc1f9f..2c7e8eb 100644 --- a/chrome/browser/chrome_service.h +++ b/chrome/browser/chrome_service.h
@@ -10,10 +10,10 @@ #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/launchable.h" -#endif #if defined(USE_OZONE) #include "services/ui/public/cpp/input_devices/input_device_controller.h" #endif +#endif class ChromeService : public service_manager::Service { public: @@ -32,10 +32,10 @@ #if defined(OS_CHROMEOS) chromeos::Launchable launchable_; -#endif #if defined(USE_OZONE) ui::InputDeviceController input_device_controller_; #endif +#endif DISALLOW_COPY_AND_ASSIGN(ChromeService); };
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index b31a4a0..dcd48c4e 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -782,6 +782,8 @@ "lock_screen_apps/app_manager.h", "lock_screen_apps/app_manager_impl.cc", "lock_screen_apps/app_manager_impl.h", + "lock_screen_apps/app_window_metrics_tracker.cc", + "lock_screen_apps/app_window_metrics_tracker.h", "lock_screen_apps/focus_cycler_delegate.h", "lock_screen_apps/state_controller.cc", "lock_screen_apps/state_controller.h",
diff --git a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.cc b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.cc index a2a2c17..ebeb068 100644 --- a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.cc +++ b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.cc
@@ -283,7 +283,16 @@ void ArcVoiceInteractionFrameworkService::SetVoiceInteractionRunning( bool running) { - ash::Shell::Get()->NotifyVoiceInteractionStatusChanged(running); + ash::Shell::Get()->NotifyVoiceInteractionStatusChanged( + running ? ash::VoiceInteractionState::RUNNING + : ash::VoiceInteractionState::STOPPED); +} + +void ArcVoiceInteractionFrameworkService::SetVoiceInteractionState( + ash::VoiceInteractionState state) { + DCHECK_NE(state_, state); + state_ = state; + ash::Shell::Get()->NotifyVoiceInteractionStatusChanged(state); } void ArcVoiceInteractionFrameworkService::OnMetalayerClosed() { @@ -414,6 +423,12 @@ return; } + if (state_ == ash::VoiceInteractionState::NOT_READY) { + // If the container side is not ready, we will be waiting for a while. + ash::Shell::Get()->NotifyVoiceInteractionStatusChanged( + ash::VoiceInteractionState::NOT_READY); + } + if (!arc_bridge_service_->voice_interaction_framework()->has_instance()) { VLOG(1) << "Instance not ready."; SetArcCpuRestriction(false);
diff --git a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.h b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.h index 7335e00a..507e264 100644 --- a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.h +++ b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.h
@@ -62,6 +62,7 @@ void OnMetalayerClosed() override; void SetMetalayerEnabled(bool enabled) override; void SetVoiceInteractionRunning(bool running) override; + void SetVoiceInteractionState(ash::VoiceInteractionState state) override; bool IsMetalayerSupported(); void ShowMetalayer(const base::Closure& closed); @@ -117,6 +118,12 @@ // Whether there is a pending request to start voice interaction. bool is_request_pending_ = false; + // The current state voice interaction service is. There is usually a long + // delay after boot before the service is ready. We wait for the container + // to tell us if it is ready to quickly serve voice interaction requests. + // We also give user proper feedback based on the state. + ash::VoiceInteractionState state_ = ash::VoiceInteractionState::NOT_READY; + // The time when a user initated an interaction. base::TimeTicks user_interaction_start_time_;
diff --git a/chrome/browser/chromeos/feedback_util.cc b/chrome/browser/chromeos/feedback_util.cc index c629cd6..4c8eb3b 100644 --- a/chrome/browser/chromeos/feedback_util.cc +++ b/chrome/browser/chromeos/feedback_util.cc
@@ -6,10 +6,11 @@ #include "base/bind.h" #include "base/callback.h" -#include "base/logging.h" #include "chrome/browser/extensions/api/feedback_private/feedback_private_api.h" #include "chrome/browser/extensions/api/feedback_private/feedback_service.h" +#include "chrome/browser/feedback/system_logs/chrome_system_logs_fetcher.h" #include "chrome/browser/profiles/profile.h" +#include "components/feedback/system_logs/system_logs_fetcher.h" using feedback::FeedbackData; @@ -34,7 +35,7 @@ feedback_data->set_description(description); feedback_data->SetAndCompressSystemInfo(std::move(sys_info)); - GetFeedbackService(profile)->SendFeedback(profile, feedback_data, callback); + GetFeedbackService(profile)->SendFeedback(feedback_data, callback); } } // namespace @@ -42,7 +43,10 @@ void SendSysLogFeedback(Profile* profile, const std::string& description, const SendSysLogFeedbackCallback& callback) { - GetFeedbackService(profile)->GetSystemInformation( + // |fetcher| deletes itself after calling its callback. + system_logs::SystemLogsFetcher* fetcher = + system_logs::BuildChromeSystemLogsFetcher(); + fetcher->Fetch( base::Bind(&OnGetSystemInformation, profile, description, callback)); }
diff --git a/chrome/browser/chromeos/file_manager/external_filesystem_apitest.cc b/chrome/browser/chromeos/file_manager/external_filesystem_apitest.cc index 150f3500..928d1c5 100644 --- a/chrome/browser/chromeos/file_manager/external_filesystem_apitest.cc +++ b/chrome/browser/chromeos/file_manager/external_filesystem_apitest.cc
@@ -467,9 +467,12 @@ // DriveIntegrationService factory function for this test. drive::DriveIntegrationService* CreateDriveIntegrationService( Profile* profile) { - // Ignore signin profile. - if (profile->GetPath() == chromeos::ProfileHelper::GetSigninProfileDir()) + // Ignore signin and lock screen apps profile. + if (profile->GetPath() == chromeos::ProfileHelper::GetSigninProfileDir() || + profile->GetPath() == + chromeos::ProfileHelper::GetLockScreenAppProfilePath()) { return nullptr; + } // DriveFileSystemExtensionApiTest doesn't expect that several user profiles // could exist simultaneously.
diff --git a/chrome/browser/chromeos/first_run/first_run.cc b/chrome/browser/chromeos/first_run/first_run.cc index 9b211159..c288005 100644 --- a/chrome/browser/chromeos/first_run/first_run.cc +++ b/chrome/browser/chromeos/first_run/first_run.cc
@@ -14,6 +14,8 @@ #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/policy/profile_policy_connector.h" +#include "chrome/browser/policy/profile_policy_connector_factory.h" #include "chrome/browser/prefs/pref_service_syncable_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/signin_manager_factory.h" @@ -72,6 +74,10 @@ return; } + if (policy::ProfilePolicyConnectorFactory::GetForBrowserContext(profile) + ->IsManaged()) + return; + if (command_line->HasSwitch(::switches::kTestType)) return;
diff --git a/chrome/browser/chromeos/first_run/goodies_displayer_browsertest.cc b/chrome/browser/chromeos/first_run/goodies_displayer_browsertest.cc index e19be6e..1915915b 100644 --- a/chrome/browser/chromeos/first_run/goodies_displayer_browsertest.cc +++ b/chrome/browser/chromeos/first_run/goodies_displayer_browsertest.cc
@@ -2,9 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "chrome/browser/chromeos/first_run/goodies_displayer.h" + #include "base/command_line.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/chromeos/first_run/goodies_displayer.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" @@ -84,6 +85,13 @@ // InProcessBrowserTest overrides. void SetUpDefaultCommandLine(base::CommandLine* command_line) override { base::CommandLine default_command_line(base::CommandLine::NO_PROGRAM); + if (command_line->HasSwitch(switches::kMus)) { + default_command_line.AppendSwitch(switches::kMus); + } else if (command_line->HasSwitch(switches::kMusConfig)) { + default_command_line.AppendSwitchASCII( + switches::kMusConfig, + command_line->GetSwitchValueASCII(switches::kMusConfig)); + } InProcessBrowserTest::SetUpDefaultCommandLine(&default_command_line); if (NoFirstRunSpecified()) { // --no-first-run is present by default. *command_line = default_command_line;
diff --git a/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc b/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc index 37740abc..2ccc952 100644 --- a/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc +++ b/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc
@@ -563,20 +563,20 @@ const ui::CompositionText& composition_text = mock_input_context->last_update_composition_arg().composition_text; EXPECT_EQ(base::UTF8ToUTF16("COMPOSITION_TEXT"), composition_text.text); - const ui::CompositionUnderlines underlines = composition_text.underlines; + const ui::ImeTextSpans ime_text_spans = composition_text.ime_text_spans; - ASSERT_EQ(2U, underlines.size()); + ASSERT_EQ(2U, ime_text_spans.size()); // single underline - EXPECT_EQ(SK_ColorBLACK, underlines[0].color); - EXPECT_FALSE(underlines[0].thick); - EXPECT_EQ(0U, underlines[0].start_offset); - EXPECT_EQ(5U, underlines[0].end_offset); + EXPECT_EQ(SK_ColorBLACK, ime_text_spans[0].color); + EXPECT_FALSE(ime_text_spans[0].thick); + EXPECT_EQ(0U, ime_text_spans[0].start_offset); + EXPECT_EQ(5U, ime_text_spans[0].end_offset); // double underline - EXPECT_EQ(SK_ColorBLACK, underlines[1].color); - EXPECT_TRUE(underlines[1].thick); - EXPECT_EQ(6U, underlines[1].start_offset); - EXPECT_EQ(10U, underlines[1].end_offset); + EXPECT_EQ(SK_ColorBLACK, ime_text_spans[1].color); + EXPECT_TRUE(ime_text_spans[1].thick); + EXPECT_EQ(6U, ime_text_spans[1].start_offset); + EXPECT_EQ(10U, ime_text_spans[1].end_offset); } { SCOPED_TRACE("clearComposition test"); @@ -1027,14 +1027,14 @@ const ui::CompositionText& composition_text = mock_input_context->last_update_composition_arg().composition_text; EXPECT_EQ(base::UTF8ToUTF16("us"), composition_text.text); - const ui::CompositionUnderlines underlines = composition_text.underlines; + const ui::ImeTextSpans ime_text_spans = composition_text.ime_text_spans; - ASSERT_EQ(1U, underlines.size()); + ASSERT_EQ(1U, ime_text_spans.size()); // single underline - EXPECT_EQ(SK_ColorBLACK, underlines[0].color); - EXPECT_FALSE(underlines[0].thick); - EXPECT_EQ(0U, underlines[0].start_offset); - EXPECT_EQ(1U, underlines[0].end_offset); + EXPECT_EQ(SK_ColorBLACK, ime_text_spans[0].color); + EXPECT_FALSE(ime_text_spans[0].thick); + EXPECT_EQ(0U, ime_text_spans[0].start_offset); + EXPECT_EQ(1U, ime_text_spans[0].end_offset); EXPECT_TRUE(mock_input_context->last_commit_text().empty()); InputMethodManager::Get()->GetActiveIMEState()->ChangeInputMethod(
diff --git a/chrome/browser/chromeos/input_method/textinput_surroundingtext_browsertest.cc b/chrome/browser/chromeos/input_method/textinput_surroundingtext_browsertest.cc index d8ac3f04..f03a9a1 100644 --- a/chrome/browser/chromeos/input_method/textinput_surroundingtext_browsertest.cc +++ b/chrome/browser/chromeos/input_method/textinput_surroundingtext_browsertest.cc
@@ -10,7 +10,6 @@ #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/ime/composition_underline.h" namespace chromeos {
diff --git a/chrome/browser/chromeos/lock_screen_apps/app_manager_impl.cc b/chrome/browser/chromeos/lock_screen_apps/app_manager_impl.cc index 92181d0..5c96c03 100644 --- a/chrome/browser/chromeos/lock_screen_apps/app_manager_impl.cc +++ b/chrome/browser/chromeos/lock_screen_apps/app_manager_impl.cc
@@ -15,9 +15,11 @@ #include "base/files/scoped_temp_dir.h" #include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" +#include "base/metrics/histogram_macros.h" #include "base/sequenced_task_runner.h" #include "base/strings/string16.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/tick_clock.h" #include "chrome/browser/chromeos/note_taking_helper.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/extensions/extension_assets_manager.h" @@ -40,6 +42,38 @@ using ExtensionCallback = base::Callback<void( const scoped_refptr<const extensions::Extension>& extension)>; +// The lock screen note taking availability state. +// Used to report UMA histograms - the values should map to +// LockScreenActionAvailability UMA enum values, and the values assigned to +// enum states should NOT be changed. +enum class ActionAvailability { + kAvailable = 0, + kNoActionHandlerApp = 1, + kAppNotSupportingLockScreen = 2, + kActionNotEnabledOnLockScreen = 3, + kDisallowedByPolicy = 4, + kCount, +}; + +ActionAvailability GetLockScreenNoteTakingAvailability( + chromeos::NoteTakingAppInfo* app_info) { + if (!app_info || !app_info->preferred) + return ActionAvailability::kNoActionHandlerApp; + + switch (app_info->lock_screen_support) { + case chromeos::NoteTakingLockScreenSupport::kNotSupported: + return ActionAvailability::kAppNotSupportingLockScreen; + case chromeos::NoteTakingLockScreenSupport::kSupported: + return ActionAvailability::kActionNotEnabledOnLockScreen; + case chromeos::NoteTakingLockScreenSupport::kNotAllowedByPolicy: + return ActionAvailability::kDisallowedByPolicy; + case chromeos::NoteTakingLockScreenSupport::kEnabled: + return ActionAvailability::kAvailable; + } + + return ActionAvailability::kAppNotSupportingLockScreen; +} + void InvokeCallbackOnTaskRunner( const ExtensionCallback& callback, const scoped_refptr<base::SequencedTaskRunner>& task_runner, @@ -113,8 +147,9 @@ } // namespace -AppManagerImpl::AppManagerImpl() - : extensions_observer_(this), +AppManagerImpl::AppManagerImpl(base::TickClock* tick_clock) + : tick_clock_(tick_clock), + extensions_observer_(this), note_taking_helper_observer_(this), weak_ptr_factory_(this) {} @@ -264,12 +299,15 @@ std::unique_ptr<chromeos::NoteTakingAppInfo> note_taking_app = chromeos::NoteTakingHelper::Get()->GetPreferredChromeAppInfo( primary_profile_); + ActionAvailability availability = + GetLockScreenNoteTakingAvailability(note_taking_app.get()); - if (!note_taking_app || !note_taking_app->preferred || - note_taking_app->lock_screen_support != - chromeos::NoteTakingLockScreenSupport::kEnabled) { + UMA_HISTOGRAM_ENUMERATION( + "Apps.LockScreen.NoteTakingApp.AvailabilityOnScreenLock", availability, + ActionAvailability::kCount); + + if (availability != ActionAvailability::kAvailable) return std::string(); - } return note_taking_app->app_id; } @@ -325,14 +363,20 @@ lock_screen_service->install_directory(), lock_screen_profile_, base::Bind(&InvokeCallbackOnTaskRunner, base::Bind(&AppManagerImpl::CompleteLockScreenAppInstall, - weak_ptr_factory_.GetWeakPtr(), install_count_), + weak_ptr_factory_.GetWeakPtr(), install_count_, + tick_clock_->NowTicks()), base::ThreadTaskRunnerHandle::Get()))); return State::kActivating; } void AppManagerImpl::CompleteLockScreenAppInstall( int install_id, + base::TimeTicks install_start_time, const scoped_refptr<const extensions::Extension>& app) { + UMA_HISTOGRAM_TIMES( + "Apps.LockScreen.NoteTakingApp.LockScreenInstallationDuration", + tick_clock_->NowTicks() - install_start_time); + // Bail out if the app manager is no longer waiting for this app's // installation - the copied resources will be cleaned up when the (ephemeral) // lock screen profile is destroyed.
diff --git a/chrome/browser/chromeos/lock_screen_apps/app_manager_impl.h b/chrome/browser/chromeos/lock_screen_apps/app_manager_impl.h index 4f658cd..61a230e 100644 --- a/chrome/browser/chromeos/lock_screen_apps/app_manager_impl.h +++ b/chrome/browser/chromeos/lock_screen_apps/app_manager_impl.h
@@ -11,12 +11,17 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/scoped_observer.h" +#include "base/time/time.h" #include "chrome/browser/chromeos/lock_screen_apps/app_manager.h" #include "chrome/browser/chromeos/note_taking_helper.h" #include "extensions/browser/extension_registry_observer.h" class Profile; +namespace base { +class TickClock; +} + namespace extensions { class Extension; class ExtensionRegistry; @@ -29,7 +34,7 @@ public chromeos::NoteTakingHelper::Observer, public extensions::ExtensionRegistryObserver { public: - AppManagerImpl(); + explicit AppManagerImpl(base::TickClock* tick_clock); ~AppManagerImpl() override; // AppManager implementation: @@ -77,6 +82,7 @@ // installation failed. void CompleteLockScreenAppInstall( int install_id, + base::TimeTicks install_start_time, const scoped_refptr<const extensions::Extension>& app); // Installs app to the lock screen profile's extension service and enables @@ -106,6 +112,8 @@ State state_ = State::kNotInitialized; std::string lock_screen_app_id_; + base::TickClock* tick_clock_; + ScopedObserver<extensions::ExtensionRegistry, extensions::ExtensionRegistryObserver> extensions_observer_;
diff --git a/chrome/browser/chromeos/lock_screen_apps/app_manager_impl_unittest.cc b/chrome/browser/chromeos/lock_screen_apps/app_manager_impl_unittest.cc index 4ff90d6e..d459dd5c 100644 --- a/chrome/browser/chromeos/lock_screen_apps/app_manager_impl_unittest.cc +++ b/chrome/browser/chromeos/lock_screen_apps/app_manager_impl_unittest.cc
@@ -14,6 +14,7 @@ #include "base/json/json_file_value_serializer.h" #include "base/memory/ptr_util.h" #include "base/test/scoped_command_line.h" +#include "base/test/simple_test_tick_clock.h" #include "base/values.h" #include "chrome/browser/chromeos/arc/arc_session_manager.h" #include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h" @@ -358,7 +359,9 @@ AppManager* app_manager() { return app_manager_.get(); } - void ResetAppManager() { app_manager_ = base::MakeUnique<AppManagerImpl>(); } + void ResetAppManager() { + app_manager_ = base::MakeUnique<AppManagerImpl>(&tick_clock_); + } int note_taking_changed_count() const { return note_taking_changed_count_; } @@ -378,6 +381,9 @@ int NoteTakingChangedCountOnStart() { return IsInstallAsync() ? 1 : 0; } + protected: + base::SimpleTestTickClock tick_clock_; + private: void OnNoteTakingChanged() { ++note_taking_changed_count_; }
diff --git a/chrome/browser/chromeos/lock_screen_apps/app_window_metrics_tracker.cc b/chrome/browser/chromeos/lock_screen_apps/app_window_metrics_tracker.cc new file mode 100644 index 0000000..2f82e60 --- /dev/null +++ b/chrome/browser/chromeos/lock_screen_apps/app_window_metrics_tracker.cc
@@ -0,0 +1,172 @@ +// 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 "chrome/browser/chromeos/lock_screen_apps/app_window_metrics_tracker.h" + +#include "base/metrics/histogram_macros.h" +#include "base/time/tick_clock.h" +#include "base/time/time.h" +#include "extensions/browser/app_window/app_window.h" + +namespace { + +// Name of the count histogram used to keep track of (1-indexed) app launch +// request ordinal number in a lock screen session. +const char kAppLaunchOrdinalNumberInLockSession[] = + "Apps.LockScreen.NoteTakingApp.LaunchRequestOrdinalNumber"; + +// Name of the histogram that tracks total amount of time an app window was +// active for a single launch event - i.e. time from app window being shown to +// app window closure. +const char kTotalAppWindowSessionTime[] = + "Apps.LockScreen.NoteTakingApp.AppWindowLifeTime.TotalActive"; + +// Name of the histogram that tracks amount of time an app window was in +// foreground, on top the lock screen. +const char kTimeAppWindowInForeground[] = + "Apps.LockScreen.NoteTakingApp.AppWindowLifeTime.Foreground"; + +// Name of the histogram that track amount of time an app window was in +// background, behind the lock screen. +const char kTimeAppWindowInBackground[] = + "Apps.LockScreen.NoteTakingApp.AppWindowLifeTime.Background"; + +// Name of the histogram that tracks the amount time needed to show an app +// window (the window render view being created) after the app launch was +// requested. +const char kTimeFromLaunchToWindowBeingShown[] = + "Apps.LockScreen.NoteTakingApp.TimeToShowWindow"; + +// Name of the histogram that tracks the amount of time needed to load the an +// app window contents after the app launch was requested. +const char kTimeToLoadAppWindowContents[] = + "Apps.LockScreen.NoteTakingApp.TimeToLoadAppWindowContents"; + +// The name of the histogram that tracks the amount of time the app was in +// launching state when the launch got canceled. +const char kLaunchDurationAtLaunchCancel[] = + "Apps.LockScreen.NoteTakingApp.LaunchDurationAtLaunchCancel"; + +// The name of the histogram that track the app state when the app lock screen +// ends. +const char kAppWindowStateOnRemoval[] = + "Apps.LockScreen.NoteTakingApp.FinalAppSessionState"; + +} // namespace + +namespace lock_screen_apps { + +AppWindowMetricsTracker::AppWindowMetricsTracker(base::TickClock* clock) + : clock_(clock) {} + +AppWindowMetricsTracker::~AppWindowMetricsTracker() = default; + +void AppWindowMetricsTracker::AppLaunchRequested() { + DCHECK_EQ(State::kInitial, state_); + SetState(State::kLaunchRequested); + + ++app_launch_count_; + UMA_HISTOGRAM_COUNTS_100(kAppLaunchOrdinalNumberInLockSession, + app_launch_count_); +} + +void AppWindowMetricsTracker::MovedToForeground() { + DCHECK_NE(State::kInitial, state_); + + if (state_ == State::kForeground) + return; + + if (state_ == State::kBackground) { + SetState(State::kForeground); + return; + } + + // Not expected to be in a state different than foreground or background + // after |state_after_window_contents_load_| is reset. + DCHECK(state_after_window_contents_load_.has_value()); + state_after_window_contents_load_ = State::kForeground; +} + +void AppWindowMetricsTracker::MovedToBackground() { + DCHECK_NE(State::kInitial, state_); + + if (state_ == State::kBackground) + return; + + if (state_ == State::kForeground) { + SetState(State::kBackground); + return; + } + + // Not expected to be in a state different than foreground or background + // after |state_after_window_contents_load_| is reset. + DCHECK(state_after_window_contents_load_.has_value()); + state_after_window_contents_load_ = State::kBackground; +} + +void AppWindowMetricsTracker::AppWindowCreated( + extensions::AppWindow* app_window) { + Observe(app_window->web_contents()); + + SetState(State::kWindowCreated); +} + +void AppWindowMetricsTracker::Reset() { + if (state_ == State::kInitial) + return; + + UMA_HISTOGRAM_ENUMERATION(kAppWindowStateOnRemoval, state_, State::kCount); + + if (state_ != State::kLaunchRequested && state_ != State::kWindowCreated) { + UMA_HISTOGRAM_LONG_TIMES( + kTotalAppWindowSessionTime, + clock_->NowTicks() - time_stamps_[State::kWindowShown]); + } else { + UMA_HISTOGRAM_TIMES( + kLaunchDurationAtLaunchCancel, + clock_->NowTicks() - time_stamps_[State::kLaunchRequested]); + } + + SetState(State::kInitial); + + state_after_window_contents_load_ = State::kForeground; + + time_stamps_.clear(); +} + +void AppWindowMetricsTracker::RenderViewCreated( + content::RenderViewHost* render_view_host) { + SetState(State::kWindowShown); + + UMA_HISTOGRAM_TIMES( + kTimeFromLaunchToWindowBeingShown, + clock_->NowTicks() - time_stamps_[State::kLaunchRequested]); +} + +void AppWindowMetricsTracker::DocumentOnLoadCompletedInMainFrame() { + State next_state = state_after_window_contents_load_.value(); + state_after_window_contents_load_.reset(); + SetState(next_state); + + UMA_HISTOGRAM_TIMES(kTimeToLoadAppWindowContents, + clock_->NowTicks() - time_stamps_[State::kWindowShown]); +} + +void AppWindowMetricsTracker::SetState(State state) { + if (state_ == state) + return; + + if (state_ == State::kForeground) { + UMA_HISTOGRAM_MEDIUM_TIMES(kTimeAppWindowInForeground, + clock_->NowTicks() - time_stamps_[state_]); + } else if (state_ == State::kBackground) { + UMA_HISTOGRAM_MEDIUM_TIMES(kTimeAppWindowInBackground, + clock_->NowTicks() - time_stamps_[state_]); + } + + state_ = state; + time_stamps_[state] = clock_->NowTicks(); +} + +} // namespace lock_screen_apps
diff --git a/chrome/browser/chromeos/lock_screen_apps/app_window_metrics_tracker.h b/chrome/browser/chromeos/lock_screen_apps/app_window_metrics_tracker.h new file mode 100644 index 0000000..a5c95ab --- /dev/null +++ b/chrome/browser/chromeos/lock_screen_apps/app_window_metrics_tracker.h
@@ -0,0 +1,86 @@ +// 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 CHROME_BROWSER_CHROMEOS_LOCK_SCREEN_APPS_APP_WINDOW_METRICS_TRACKER_H_ +#define CHROME_BROWSER_CHROMEOS_LOCK_SCREEN_APPS_APP_WINDOW_METRICS_TRACKER_H_ + +#include <map> + +#include "base/macros.h" +#include "base/optional.h" +#include "base/time/time.h" +#include "content/public/browser/web_contents_observer.h" + +namespace base { +class TickClock; +} + +namespace extensions { +class AppWindow; +} + +namespace lock_screen_apps { + +// Helper for tracking metrics for lock screen app window launches. +class AppWindowMetricsTracker : public content::WebContentsObserver { + public: + explicit AppWindowMetricsTracker(base::TickClock* clock); + ~AppWindowMetricsTracker() override; + + // Register app launch request. + void AppLaunchRequested(); + + // Registers the app window created for lock screen action - the class + // will begin observing the app window state as a result. + void AppWindowCreated(extensions::AppWindow* app_window); + + // Updates metrics state for app window being moved to foreground. + void MovedToForeground(); + + // Updates metrics state for app window being moved to background. + void MovedToBackground(); + + // Stops tracking current app window state, and resets collected timestamps. + void Reset(); + + // content::WebContentsObserver: + void RenderViewCreated(content::RenderViewHost* render_view_host) override; + void DocumentOnLoadCompletedInMainFrame() override; + + private: + // NOTE: Used in histograms - do not change order, or remove entries. + // Also, update LockScreenAppSessionState enum. + enum class State { + kInitial = 0, + kLaunchRequested = 1, + kWindowCreated = 2, + kWindowShown = 3, + kForeground = 4, + kBackground = 5, + kCount + }; + + void SetState(State state); + + base::TickClock* clock_; + + State state_ = State::kInitial; + + // Maps states to their last occurrence time. + std::map<State, base::TimeTicks> time_stamps_; + + // Number of times app launch was requested during the + int app_launch_count_ = 0; + + // The state to which the metrics tracker should move after + // the window contents is loaded. + // Should be either kForeground or kBackground. + base::Optional<State> state_after_window_contents_load_ = State::kForeground; + + DISALLOW_COPY_AND_ASSIGN(AppWindowMetricsTracker); +}; + +} // namespace lock_screen_apps + +#endif // CHROME_BROWSER_CHROMEOS_LOCK_SCREEN_APPS_APP_WINDOW_METRICS_TRACKER_H_
diff --git a/chrome/browser/chromeos/lock_screen_apps/state_controller.cc b/chrome/browser/chromeos/lock_screen_apps/state_controller.cc index 843225e6..18b8f214 100644 --- a/chrome/browser/chromeos/lock_screen_apps/state_controller.cc +++ b/chrome/browser/chromeos/lock_screen_apps/state_controller.cc
@@ -11,10 +11,13 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/memory/ptr_util.h" +#include "base/metrics/histogram_macros.h" #include "base/path_service.h" #include "base/strings/string16.h" +#include "base/time/default_tick_clock.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/lock_screen_apps/app_manager_impl.h" +#include "chrome/browser/chromeos/lock_screen_apps/app_window_metrics_tracker.h" #include "chrome/browser/chromeos/lock_screen_apps/focus_cycler_delegate.h" #include "chrome/browser/chromeos/note_taking_helper.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" @@ -25,6 +28,7 @@ #include "chromeos/dbus/dbus_thread_manager.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" +#include "components/safe_browsing/common/safe_browsing_prefs.h" #include "components/session_manager/core/session_manager.h" #include "content/public/browser/web_contents.h" #include "content/public/common/service_manager_connection.h" @@ -118,6 +122,8 @@ } void StateController::Initialize() { + tick_clock_ = base::MakeUnique<base::DefaultTickClock>(); + // The tray action ptr might be set previously if the client was being created // for testing. if (!tray_action_ptr_) { @@ -144,7 +150,8 @@ lock_screen_data_.reset(); if (app_manager_) { app_manager_->Stop(); - ResetNoteTakingWindowAndMoveToNextState(true /*close_window*/); + ResetNoteTakingWindowAndMoveToNextState(true /*close_window*/, + NoteTakingExitReason::kShutdown); app_manager_.reset(); } focus_cycler_delegate_ = nullptr; @@ -159,8 +166,15 @@ Profile::CreateStatus status) { // Ignore CREATED status - wait for profile to be initialized before // continuing. - if (status == Profile::CREATE_STATUS_CREATED) + if (status == Profile::CREATE_STATUS_CREATED) { + // Disable safe browsing for the profile to avoid activating + // SafeBrowsingService when the user has safe browsing disabled (reasoning + // similar to http://crbug.com/461493). + // TODO(tbarzic): Revisit this if webviews get enabled for lock screen apps. + lock_screen_profile->GetPrefs()->SetBoolean(prefs::kSafeBrowsingEnabled, + false); return; + } // On error, bail out - this will cause the lock screen apps to remain // unavailable on the device. @@ -219,7 +233,7 @@ // App manager might have been set previously by a test. if (!app_manager_) - app_manager_ = base::MakeUnique<AppManagerImpl>(); + app_manager_ = base::MakeUnique<AppManagerImpl>(tick_clock_.get()); app_manager_->Initialize(profile, lock_screen_profile_->GetOriginalProfile()); input_devices_observer_.Add(ui::InputDeviceManager::GetInstance()); @@ -262,23 +276,19 @@ } void StateController::RequestNewLockScreenNote() { - if (lock_screen_note_state_ != TrayActionState::kAvailable) - return; - - DCHECK(app_manager_->IsNoteTakingAppAvailable()); - - // Update state to launching even if app fails to launch - this is to notify - // listeners that a lock screen note request was handled. - UpdateLockScreenNoteState(TrayActionState::kLaunching); - if (!app_manager_->LaunchNoteTaking()) - UpdateLockScreenNoteState(TrayActionState::kAvailable); + HandleNewNoteRequest(NewNoteRequestType::kTrayAction); } void StateController::OnSessionStateChanged() { if (!session_manager::SessionManager::Get()->IsScreenLocked()) { lock_screen_data_->SetSessionLocked(false); app_manager_->Stop(); - ResetNoteTakingWindowAndMoveToNextState(true /*close_window*/); + if (lock_screen_note_state_ == TrayActionState::kBackground) { + RecordLockScreenAppUnlockAction(LockScreenUnlockAction::kSessionUnlocked); + } + ResetNoteTakingWindowAndMoveToNextState( + true /*close_window*/, NoteTakingExitReason::kSessionUnlock); + note_app_window_metrics_.reset(); return; } @@ -288,14 +298,23 @@ app_manager_->Start( base::Bind(&StateController::OnNoteTakingAvailabilityChanged, base::Unretained(this))); + note_app_window_metrics_ = + base::MakeUnique<AppWindowMetricsTracker>(tick_clock_.get()); lock_screen_data_->SetSessionLocked(true); OnNoteTakingAvailabilityChanged(); } +void StateController::OnAppWindowAdded(extensions::AppWindow* app_window) { + if (note_app_window_ != app_window) + return; + note_app_window_metrics_->AppWindowCreated(app_window); +} + void StateController::OnAppWindowRemoved(extensions::AppWindow* app_window) { if (note_app_window_ != app_window) return; - ResetNoteTakingWindowAndMoveToNextState(false /*close_window*/); + ResetNoteTakingWindowAndMoveToNextState( + false /*close_window*/, NoteTakingExitReason::kAppWindowClosed); } void StateController::OnStylusStateChanged(ui::StylusState state) { @@ -303,16 +322,19 @@ return; if (state == ui::StylusState::REMOVED) - RequestNewLockScreenNote(); + HandleNewNoteRequest(NewNoteRequestType::kStylusEject); } void StateController::BrightnessChanged(int level, bool user_initiated) { - if (level == 0 && !user_initiated) - ResetNoteTakingWindowAndMoveToNextState(true /*close_window*/); + if (level == 0 && !user_initiated) { + ResetNoteTakingWindowAndMoveToNextState( + true /*close_window*/, NoteTakingExitReason::kScreenDimmed); + } } void StateController::SuspendImminent() { - ResetNoteTakingWindowAndMoveToNextState(true /*close_window*/); + ResetNoteTakingWindowAndMoveToNextState(true /*close_window*/, + NoteTakingExitReason::kSuspend); } extensions::AppWindow* StateController::CreateAppWindowForLockScreenAction( @@ -362,8 +384,10 @@ void StateController::MoveToBackground() { if (GetLockScreenNoteState() == TrayActionState::kLaunching) { + note_app_window_metrics_->Reset(); UpdateLockScreenNoteState(TrayActionState::kAvailable); } else if (GetLockScreenNoteState() == TrayActionState::kActive) { + note_app_window_metrics_->MovedToBackground(); UpdateLockScreenNoteState(TrayActionState::kBackground); } } @@ -371,14 +395,58 @@ void StateController::MoveToForeground() { if (GetLockScreenNoteState() != TrayActionState::kBackground) return; + + RecordLockScreenAppUnlockAction(LockScreenUnlockAction::kUnlockCancelled); + + note_app_window_metrics_->MovedToForeground(); UpdateLockScreenNoteState(TrayActionState::kActive); } +void StateController::HandleNewNoteRequestFromLockScreen( + NewNoteRequestType type) { + DCHECK(type == NewNoteRequestType::kLockScreenUiTap || + type == NewNoteRequestType::kLockScreenUiSwipe || + type == NewNoteRequestType::kLockScreenUiKeyboard); + + HandleNewNoteRequest(type); +} + +void StateController::RecordLockScreenAppUnlockAction( + LockScreenUnlockAction action) { + if (lock_screen_note_state_ != TrayActionState::kBackground) + return; + + UMA_HISTOGRAM_ENUMERATION("Apps.LockScreen.NoteTakingApp.UnlockUIAction", + action, LockScreenUnlockAction::kCount); +} + +void StateController::HandleNewNoteRequest(NewNoteRequestType type) { + if (lock_screen_note_state_ != TrayActionState::kAvailable) + return; + + DCHECK(app_manager_->IsNoteTakingAppAvailable()); + + UMA_HISTOGRAM_ENUMERATION("Apps.LockScreen.NoteTakingApp.LaunchRequestReason", + type, NewNoteRequestType::kCount); + + // Update state to launching even if app fails to launch - this is to notify + // listeners that a lock screen note request was handled. + UpdateLockScreenNoteState(TrayActionState::kLaunching); + if (!app_manager_->LaunchNoteTaking()) { + UpdateLockScreenNoteState(TrayActionState::kAvailable); + return; + } + + note_app_window_metrics_->AppLaunchRequested(); +} + void StateController::OnNoteTakingAvailabilityChanged() { if (!app_manager_->IsNoteTakingAppAvailable() || (note_app_window_ && note_app_window_->GetExtension()->id() != app_manager_->GetNoteTakingAppId())) { - ResetNoteTakingWindowAndMoveToNextState(true /*close_window*/); + ResetNoteTakingWindowAndMoveToNextState( + true /*close_window*/, + NoteTakingExitReason::kAppLockScreenSupportDisabled); return; } @@ -407,9 +475,20 @@ } void StateController::ResetNoteTakingWindowAndMoveToNextState( - bool close_window) { + bool close_window, + NoteTakingExitReason exit_reason) { app_window_observer_.RemoveAll(); + if (note_app_window_metrics_) + note_app_window_metrics_->Reset(); + + if (lock_screen_note_state_ != TrayActionState::kAvailable && + lock_screen_note_state_ != TrayActionState::kNotAvailable) { + UMA_HISTOGRAM_ENUMERATION( + "Apps.LockScreen.NoteTakingApp.NoteTakingExitReason", exit_reason, + NoteTakingExitReason::kCount); + } + if (note_app_window_) { if (focus_cycler_delegate_) focus_cycler_delegate_->UnregisterLockScreenAppFocusHandler();
diff --git a/chrome/browser/chromeos/lock_screen_apps/state_controller.h b/chrome/browser/chromeos/lock_screen_apps/state_controller.h index a1ee49c..715366c 100644 --- a/chrome/browser/chromeos/lock_screen_apps/state_controller.h +++ b/chrome/browser/chromeos/lock_screen_apps/state_controller.h
@@ -25,6 +25,10 @@ class PrefRegistrySimple; +namespace base { +class TickClock; +} + namespace content { class BrowserContext; } @@ -49,6 +53,7 @@ namespace lock_screen_apps { +class AppWindowMetricsTracker; class FocusCyclerDelegate; class StateObserver; @@ -61,6 +66,47 @@ public ui::InputDeviceEventObserver, public chromeos::PowerManagerClient::Observer { public: + // Type of action that triggered a request for new note. + // Used in histograms - should be kept in sync with + // NewLockScreenNoteRequestType histogram enum, and assigned values should + // never be changed. + enum class NewNoteRequestType { + kTrayAction = 0, + kLockScreenUiTap = 1, + kLockScreenUiSwipe = 2, + kLockScreenUiKeyboard = 3, + kStylusEject = 4, + kCount, + }; + + // Reason for resetting note taking app window, and exiting note taking app. + // Used primarily for metrics reporting. + // IMPORTANT: The values should be kept in sync with + // LockScreenNoteTakingExitReason histogram enum, and assigned values should + // never be changed. + enum class NoteTakingExitReason { + kSessionUnlock = 0, + kShutdown = 1, + kScreenDimmed = 2, + kSuspend = 3, + kAppWindowClosed = 4, + kAppLockScreenSupportDisabled = 5, + kCount + }; + + // Action taken by the user on lock screen when a lock screen app window was + // in the background - used primarily for metrics reporting. + // IMPORTANT: The values should be kept in sync with + // LockScreenNoteTakingUnlockUIAction, and assigned values should never be + // changed. + enum class LockScreenUnlockAction { + kSessionUnlocked = 0, + kUnlockCancelled = 1, + kShutdown = 2, + kSignOut = 3, + kCount + }; + // Returns whether the StateController is enabled - it is currently guarded by // a feature flag. If not enabled, |StateController| instance is not allowed // to be created. |Get| will still work, but it will return nullptr. @@ -122,6 +168,7 @@ void OnSessionStateChanged() override; // extensions::AppWindowRegistry::Observer: + void OnAppWindowAdded(extensions::AppWindow* app_window) override; void OnAppWindowRemoved(extensions::AppWindow* app_window) override; // ui::InputDeviceEventObserver: @@ -157,6 +204,14 @@ // windows back to foreground (i.e. visible over lock screen UI). void MoveToForeground(); + // Handles new note requests that come from lock screen UI. + void HandleNewNoteRequestFromLockScreen(NewNoteRequestType type); + + // Records the user action taken on lock screen when the lock screen app + // unlock UI is shown - i.e. when lock UI is shown on top of backgrounded + // lock screen app window. + void RecordLockScreenAppUnlockAction(LockScreenUnlockAction action); + private: // Called when profiles needed to run lock screen apps are ready - i.e. when // primary user profile was set using |SetPrimaryProfile| and the profile in @@ -178,6 +233,9 @@ // lock screen context. void InitializeWithCryptoKey(Profile* profile, const std::string& crypto_key); + // Handles request to launch a new-note lock screen flow. + void HandleNewNoteRequest(NewNoteRequestType type); + // Called when app manager reports that note taking availability has changed. void OnNoteTakingAvailabilityChanged(); @@ -185,7 +243,9 @@ // on lock screen, unregisters the window, and closes is if |close_window| is // set. It changes the current state to kAvailable or kNotAvailable, depending // on whether lock screen note taking action can still be handled. - void ResetNoteTakingWindowAndMoveToNextState(bool close_window); + void ResetNoteTakingWindowAndMoveToNextState( + bool close_window, + NoteTakingExitReason exit_reason); // Requests lock screen note action state change to |state|. // Returns whether the action state has changed. @@ -218,6 +278,11 @@ FocusCyclerDelegate* focus_cycler_delegate_ = nullptr; extensions::AppWindow* note_app_window_ = nullptr; + // Used to track metrics for app window launches - it is set when the user + // session is locked (and reset on unlock). Note that a single instance + // should not be reused for different lock sessions - it tracks number of app + // launches per lock screen. + std::unique_ptr<AppWindowMetricsTracker> note_app_window_metrics_; ScopedObserver<extensions::AppWindowRegistry, extensions::AppWindowRegistry::Observer> @@ -237,6 +302,10 @@ // to session / app manager changes. base::Closure ready_callback_; + // The clock used to keep track of time, for example to report app window + // lifetime metrics. + std::unique_ptr<base::TickClock> tick_clock_; + base::WeakPtrFactory<StateController> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(StateController);
diff --git a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc index 75f6af9..577eda73 100644 --- a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc +++ b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc
@@ -855,6 +855,13 @@ // for the first time. Tell the UserImageManager that this user is not new to // prevent the avatar from getting changed. GetUserImageManager(user->GetAccountId())->UserLoggedIn(false, true); + + // For public account, it's possible that the user-policy controlled wallpaper + // was fetched/cleared at the login screen (while for a regular user it was + // always fetched/cleared inside a user session), in the case the user-policy + // controlled wallpaper was cached/cleared by not updated in the login screen, + // so we need to update the wallpaper after the public user logged in. + WallpaperManager::Get()->SetUserWallpaperNow(user->GetAccountId()); WallpaperManager::Get()->EnsureLoggedInUserWallpaperLoaded(); SetPublicAccountDelegates();
diff --git a/chrome/browser/chromeos/login/users/default_user_image/default_user_images.cc b/chrome/browser/chromeos/login/users/default_user_image/default_user_images.cc index ff776ec0..96c0000 100644 --- a/chrome/browser/chromeos/login/users/default_user_image/default_user_images.cc +++ b/chrome/browser/chromeos/login/users/default_user_image/default_user_images.cc
@@ -91,6 +91,14 @@ IDR_LOGIN_DEFAULT_USER_55, IDR_LOGIN_DEFAULT_USER_56, IDR_LOGIN_DEFAULT_USER_57, + IDR_LOGIN_DEFAULT_USER_58, + IDR_LOGIN_DEFAULT_USER_59, + IDR_LOGIN_DEFAULT_USER_60, + IDR_LOGIN_DEFAULT_USER_61, + IDR_LOGIN_DEFAULT_USER_62, + IDR_LOGIN_DEFAULT_USER_63, + IDR_LOGIN_DEFAULT_USER_64, + IDR_LOGIN_DEFAULT_USER_65, }; const int kDefaultImagesCount = arraysize(kDefaultImageResourceIDs); @@ -250,6 +258,14 @@ IDS_LOGIN_DEFAULT_USER_DESC_55, IDS_LOGIN_DEFAULT_USER_DESC_56, IDS_LOGIN_DEFAULT_USER_DESC_57, + IDS_LOGIN_DEFAULT_USER_DESC_58, + IDS_LOGIN_DEFAULT_USER_DESC_59, + IDS_LOGIN_DEFAULT_USER_DESC_60, + IDS_LOGIN_DEFAULT_USER_DESC_61, + IDS_LOGIN_DEFAULT_USER_DESC_62, + IDS_LOGIN_DEFAULT_USER_DESC_63, + IDS_LOGIN_DEFAULT_USER_DESC_64, + IDS_LOGIN_DEFAULT_USER_DESC_65, }; const int kDefaultImageDescriptionsMaxID = arraysize(kDefaultImageDescriptions);
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc index 8f376eb..82cda76 100644 --- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc +++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc
@@ -1011,10 +1011,14 @@ if (!wallpaper_files_id.is_valid()) LOG(FATAL) << "Wallpaper flies id if invalid!"; + // If we're at the login screen, do not change the wallpaper to the user + // policy controlled wallpaper but only update the cache. It will be later + // updated after the user logs in. SetCustomWallpaper(account_id, wallpaper_files_id, "policy-controlled.jpeg", wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED, wallpaper::POLICY, user_image->image(), - true /* update wallpaper */); + user_manager::UserManager::Get() + ->IsUserLoggedIn() /* update wallpaper */); } void WallpaperManager::OnDeviceWallpaperPolicyChanged() {
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_policy_browsertest.cc b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_policy_browsertest.cc index 6dfaae3..41191b9b 100644 --- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_policy_browsertest.cc +++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_policy_browsertest.cc
@@ -51,6 +51,7 @@ #include "components/policy/proto/cloud_policy.pb.h" #include "components/user_manager/user.h" #include "components/user_manager/user_manager.h" +#include "components/user_manager/user_names.h" #include "content/public/test/browser_test_utils.h" #include "crypto/rsa_private_key.h" #include "net/test/embedded_test_server/embedded_test_server.h" @@ -287,6 +288,27 @@ store->validation_status()); } + // Inject |filename| as the device wallpaper policy. Set empty |filename| to + // clear policy. + void InjectDevicePolicy(const std::string& filename) { + if (!filename.empty()) { + device_policy_.payload() + .mutable_device_wallpaper_image() + ->set_device_wallpaper_image(ConstructPolicy(filename)); + } else { + device_policy_.payload().Clear(); + } + device_policy_.Build(); + fake_session_manager_client_->set_device_policy(device_policy_.GetBlob()); + fake_session_manager_client_->OnPropertyChangeComplete(true /* success */); + } + + bool ShouldSetDeviceWallpaper(const AccountId& account_id) { + std::string url, hash; + return WallpaperManager::Get()->ShouldSetDeviceWallpaper(account_id, &url, + &hash); + } + // Obtain WallpaperInfo for |user_number| from WallpaperManager. void GetUserWallpaperInfo(int user_number, wallpaper::WallpaperInfo* wallpaper_info) { @@ -441,4 +463,41 @@ ASSERT_EQ(kRedImageColor, GetAverageWallpaperColor()); } +IN_PROC_BROWSER_TEST_F(WallpaperManagerPolicyTest, PRE_DevicePolicyTest) { + SetSystemSalt(); + RegisterUser(testUsers_[0].GetUserEmail()); + StartupUtils::MarkOobeCompleted(); +} + +// Test that if device policy wallpaper and user policy wallpaper are both +// specified, the device policy wallpaper is used in the login screen and the +// user policy wallpaper is used inside of a user session. +IN_PROC_BROWSER_TEST_F(WallpaperManagerPolicyTest, DevicePolicyTest) { + SetSystemSalt(); + + // Wait until default wallpaper has been loaded in the login screen. + RunUntilWallpaperChangeCount(1); + + // Set the device wallpaper policy. Test that the device policy controlled + // wallpaper shows up in the login screen. + InjectDevicePolicy(kRedImageFileName); + RunUntilWallpaperChangeCount(2); + EXPECT_TRUE(ShouldSetDeviceWallpaper(user_manager::SignInAccountId())); + EXPECT_EQ(kRedImageColor, GetAverageWallpaperColor()); + + // Log in a test user and set the user wallpaper policy. The user policy + // controlled wallpaper shows up in the user session. + LoginUser(testUsers_[0].GetUserEmail()); + InjectPolicy(0, kGreenImageFileName); + RunUntilWallpaperChangeCount(3); + EXPECT_EQ(kGreenImageColor, GetAverageWallpaperColor()); + + // Set the device wallpaper policy inside the user session. That that the + // user wallpaper doesn't change. + InjectDevicePolicy(kBlueImageFileName); + EXPECT_FALSE(ShouldSetDeviceWallpaper( + user_manager::UserManager::Get()->GetActiveUser()->GetAccountId())); + EXPECT_EQ(kGreenImageColor, GetAverageWallpaperColor()); +} + } // namespace chromeos
diff --git a/chrome/browser/chromeos/policy/blocking_login_browsertest.cc b/chrome/browser/chromeos/policy/blocking_login_browsertest.cc index 15a0484..aa9e1895 100644 --- a/chrome/browser/chromeos/policy/blocking_login_browsertest.cc +++ b/chrome/browser/chromeos/policy/blocking_login_browsertest.cc
@@ -18,6 +18,7 @@ #include "chrome/browser/chromeos/login/ui/webui_login_display.h" #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/settings/install_attributes.h" #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h" #include "chrome/common/chrome_switches.h" @@ -124,6 +125,10 @@ const content::NotificationSource& source, const content::NotificationDetails& details) override { ASSERT_EQ(chrome::NOTIFICATION_PROFILE_ADDED, type); + if (chromeos::ProfileHelper::IsLockScreenAppProfile( + content::Source<Profile>(source).ptr())) { + return; + } ASSERT_FALSE(profile_added_); profile_added_ = content::Source<Profile>(source).ptr(); }
diff --git a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc index 66ec6d60..b3533f4 100644 --- a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc +++ b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
@@ -61,6 +61,7 @@ #include "chrome/browser/chromeos/policy/device_policy_builder.h" #include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h" #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/updater/chromeos_extension_cache_delegate.h" @@ -833,6 +834,9 @@ DCHECK_EQ(chrome::NOTIFICATION_PROFILE_CREATED, type); Profile* profile = content::Source<Profile>(source).ptr(); + // Ignore lock screen apps profile. + if (chromeos::ProfileHelper::IsLockScreenAppProfile(profile)) + return; registry_ = extensions::ExtensionRegistry::Get(profile); // Check if extension is already installed with newly created profile.
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc index 52e9b6c..363f8ef 100644 --- a/chrome/browser/chromeos/preferences.cc +++ b/chrome/browser/chromeos/preferences.cc
@@ -584,9 +584,9 @@ if (reason != REASON_PREF_CHANGED || pref_name == prefs::kUnifiedDesktopEnabledByDefault) { const bool enabled = unified_desktop_enabled_by_default_.GetValue(); - // TODO: this needs to work in Config::MUS. http://crbug.com/705591. + // TODO: this needs to work in Config::MASH. http://crbug.com/705591. if (ash::Shell::HasInstance() && - chromeos::GetAshConfig() == ash::Config::CLASSIC) { + chromeos::GetAshConfig() != ash::Config::MASH) { ash::Shell::Get()->display_manager()->SetUnifiedDesktopEnabled(enabled); } }
diff --git a/chrome/browser/chromeos/profiles/profile_helper.cc b/chrome/browser/chromeos/profiles/profile_helper.cc index bd4bb1b..55a41b3 100644 --- a/chrome/browser/chromeos/profiles/profile_helper.cc +++ b/chrome/browser/chromeos/profiles/profile_helper.cc
@@ -357,6 +357,11 @@ const user_manager::User* ProfileHelper::GetUserByProfile( const Profile* profile) const { + if (ProfileHelper::IsSigninProfile(profile) || + ProfileHelper::IsLockScreenAppProfile(profile)) { + return nullptr; + } + // This map is non-empty only in tests. if (enable_profile_to_user_testing || !user_list_for_testing_.empty()) { if (always_return_primary_user_for_testing) @@ -378,10 +383,6 @@ DCHECK(!content::BrowserThread::IsThreadInitialized( content::BrowserThread::UI) || content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - if (ProfileHelper::IsSigninProfile(profile) || - ProfileHelper::IsLockScreenAppProfile(profile)) { - return nullptr; - } user_manager::UserManager* user_manager = user_manager::UserManager::Get();
diff --git a/chrome/browser/chromeos/profiles/profile_util.cc b/chrome/browser/chromeos/profiles/profile_util.cc index ed4fa10..66550e4 100644 --- a/chrome/browser/chromeos/profiles/profile_util.cc +++ b/chrome/browser/chromeos/profiles/profile_util.cc
@@ -25,6 +25,8 @@ // not try to access the sign-in profile. if (profile->GetPath() == ProfileHelper::GetSigninProfileDir()) return false; + if (profile->GetPath() == ProfileHelper::GetLockScreenAppProfilePath()) + return false; return true; }
diff --git a/chrome/browser/conflicts/installed_programs_win.cc b/chrome/browser/conflicts/installed_programs_win.cc index a6a8dbc37..0e82fce 100644 --- a/chrome/browser/conflicts/installed_programs_win.cc +++ b/chrome/browser/conflicts/installed_programs_win.cc
@@ -8,6 +8,7 @@ #include "base/callback.h" #include "base/memory/ptr_util.h" +#include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/task_scheduler/post_task.h" #include "base/win/registry.h" @@ -113,7 +114,7 @@ // Ignore Microsoft programs. base::string16 publisher; if (GetValue(candidate, L"Publisher", &publisher) && - publisher == L"Microsoft Corporation") { + base::StartsWith(publisher, L"Microsoft", base::CompareCase::SENSITIVE)) { return; }
diff --git a/chrome/browser/devtools/chrome_devtools_manager_delegate.cc b/chrome/browser/devtools/chrome_devtools_manager_delegate.cc index 53337dd..8d5bc7ca 100644 --- a/chrome/browser/devtools/chrome_devtools_manager_delegate.cc +++ b/chrome/browser/devtools/chrome_devtools_manager_delegate.cc
@@ -365,9 +365,9 @@ if (method == chrome::devtools::Page::disable::kName) TogglePageEnable(false /* enable */, agent_host); - if (agent_host->GetType() == DevToolsAgentHost::kTypeBrowser && - method.find("Browser.") == 0) - return HandleBrowserCommand(id, method, params).release(); + auto* result = HandleBrowserCommand(id, method, params).release(); + if (result) + return result; if (method == chrome::devtools::Page::setAdBlockingEnabled::kName) return SetAdBlockingEnabled(agent_host, id, params).release();
diff --git a/chrome/browser/devtools/devtools_ui_bindings.cc b/chrome/browser/devtools/devtools_ui_bindings.cc index 9a2fedaa..c409fcc 100644 --- a/chrome/browser/devtools/devtools_ui_bindings.cc +++ b/chrome/browser/devtools/devtools_ui_bindings.cc
@@ -226,6 +226,7 @@ void ReadyForTest() override {} InfoBarService* GetInfoBarService() override; void RenderProcessGone(bool crashed) override {} + void ShowCertificateViewer(const std::string& cert_chain) override{}; content::WebContents* web_contents_; DISALLOW_COPY_AND_ASSIGN(DefaultBindingsDelegate); @@ -864,49 +865,7 @@ } void DevToolsUIBindings::ShowCertificateViewer(const std::string& cert_chain) { - std::unique_ptr<base::Value> value = - base::JSONReader::Read(cert_chain); - if (!value || value->GetType() != base::Value::Type::LIST) { - NOTREACHED(); - return; - } - - std::unique_ptr<base::ListValue> list = - base::ListValue::From(std::move(value)); - std::vector<std::string> decoded; - for (size_t i = 0; i < list->GetSize(); ++i) { - base::Value* item; - if (!list->Get(i, &item) || item->GetType() != base::Value::Type::STRING) { - NOTREACHED(); - return; - } - std::string temp; - if (!item->GetAsString(&temp)) { - NOTREACHED(); - return; - } - if (!base::Base64Decode(temp, &temp)) { - NOTREACHED(); - return; - } - decoded.push_back(temp); - } - - std::vector<base::StringPiece> cert_string_piece; - for (const auto& str : decoded) - cert_string_piece.push_back(str); - scoped_refptr<net::X509Certificate> cert = - net::X509Certificate::CreateFromDERCertChain(cert_string_piece); - if (!cert) { - NOTREACHED(); - return; - } - - if (!agent_host_ || !agent_host_->GetWebContents()) - return; - content::WebContents* inspected_wc = agent_host_->GetWebContents(); - web_contents_->GetDelegate()->ShowCertificateViewerInDevTools( - inspected_wc, cert.get()); + delegate_->ShowCertificateViewer(cert_chain); } void DevToolsUIBindings::ZoomIn() {
diff --git a/chrome/browser/devtools/devtools_ui_bindings.h b/chrome/browser/devtools/devtools_ui_bindings.h index 4dd51b7..827d8f07 100644 --- a/chrome/browser/devtools/devtools_ui_bindings.h +++ b/chrome/browser/devtools/devtools_ui_bindings.h
@@ -65,6 +65,7 @@ virtual void ReadyForTest() = 0; virtual InfoBarService* GetInfoBarService() = 0; virtual void RenderProcessGone(bool crashed) = 0; + virtual void ShowCertificateViewer(const std::string& cert_chain) = 0; }; explicit DevToolsUIBindings(content::WebContents* web_contents);
diff --git a/chrome/browser/devtools/devtools_window.cc b/chrome/browser/devtools/devtools_window.cc index dc0dfd6..3bda5f78 100644 --- a/chrome/browser/devtools/devtools_window.cc +++ b/chrome/browser/devtools/devtools_window.cc
@@ -7,6 +7,7 @@ #include <algorithm> #include <utility> +#include "base/base64.h" #include "base/command_line.h" #include "base/json/json_reader.h" #include "base/macros.h" @@ -997,18 +998,6 @@ return main_web_contents_; } -void DevToolsWindow::ShowCertificateViewer( - scoped_refptr<net::X509Certificate> certificate) { - WebContents* inspected_contents = is_docked_ ? - GetInspectedWebContents() : main_web_contents_; - Browser* browser = NULL; - int tab = 0; - if (!FindInspectedBrowserAndTabIndex(inspected_contents, &browser, &tab)) - return; - gfx::NativeWindow parent = browser->window()->GetNativeWindow(); - ::ShowCertificateViewer(inspected_contents, parent, certificate.get()); -} - void DevToolsWindow::ActivateContents(WebContents* contents) { if (is_docked_) { WebContents* inspected_tab = GetInspectedWebContents(); @@ -1154,12 +1143,6 @@ return blink::WebInputEvent::IsPinchGestureEventType(event.GetType()); } -void DevToolsWindow::ShowCertificateViewerInDevTools( - content::WebContents* web_contents, - scoped_refptr<net::X509Certificate> certificate) { - ShowCertificateViewer(certificate); -} - void DevToolsWindow::ActivateWindow() { if (life_stage_ != kLoadCompleted) return; @@ -1297,6 +1280,54 @@ } } +void DevToolsWindow::ShowCertificateViewer(const std::string& cert_chain) { + std::unique_ptr<base::Value> value = base::JSONReader::Read(cert_chain); + if (!value || value->GetType() != base::Value::Type::LIST) { + NOTREACHED(); + return; + } + + std::unique_ptr<base::ListValue> list = + base::ListValue::From(std::move(value)); + std::vector<std::string> decoded; + for (size_t i = 0; i < list->GetSize(); ++i) { + base::Value* item; + if (!list->Get(i, &item) || item->GetType() != base::Value::Type::STRING) { + NOTREACHED(); + return; + } + std::string temp; + if (!item->GetAsString(&temp)) { + NOTREACHED(); + return; + } + if (!base::Base64Decode(temp, &temp)) { + NOTREACHED(); + return; + } + decoded.push_back(temp); + } + + std::vector<base::StringPiece> cert_string_piece; + for (const auto& str : decoded) + cert_string_piece.push_back(str); + scoped_refptr<net::X509Certificate> cert = + net::X509Certificate::CreateFromDERCertChain(cert_string_piece); + if (!cert) { + NOTREACHED(); + return; + } + + WebContents* inspected_contents = + is_docked_ ? GetInspectedWebContents() : main_web_contents_; + Browser* browser = NULL; + int tab = 0; + if (!FindInspectedBrowserAndTabIndex(inspected_contents, &browser, &tab)) + return; + gfx::NativeWindow parent = browser->window()->GetNativeWindow(); + ::ShowCertificateViewer(inspected_contents, parent, cert.get()); +} + void DevToolsWindow::OnLoadCompleted() { // First seed inspected tab id for extension APIs. WebContents* inspected_web_contents = GetInspectedWebContents();
diff --git a/chrome/browser/devtools/devtools_window.h b/chrome/browser/devtools/devtools_window.h index ca3e0ef..c9c7121 100644 --- a/chrome/browser/devtools/devtools_window.h +++ b/chrome/browser/devtools/devtools_window.h
@@ -127,8 +127,6 @@ content::WebContents* source, const content::OpenURLParams& params) override; - void ShowCertificateViewer(scoped_refptr<net::X509Certificate> certificate); - // BeforeUnload interception //////////////////////////////////////////////// // In order to preserve any edits the user may have made in devtools, the @@ -315,9 +313,6 @@ const content::FileChooserParams& params) override; bool PreHandleGestureEvent(content::WebContents* source, const blink::WebGestureEvent& event) override; - void ShowCertificateViewerInDevTools( - content::WebContents* web_contents, - scoped_refptr<net::X509Certificate> certificate) override; // content::DevToolsUIBindings::Delegate overrides void ActivateWindow() override; @@ -335,6 +330,7 @@ void ReadyForTest() override; InfoBarService* GetInfoBarService() override; void RenderProcessGone(bool crashed) override; + void ShowCertificateViewer(const std::string& cert_viewer) override; void ColorPickedInEyeDropper(int r, int g, int b, int a); void CreateDevToolsBrowser();
diff --git a/chrome/browser/download/DEPS b/chrome/browser/download/DEPS index dba1ce6..32d7dc9 100644 --- a/chrome/browser/download/DEPS +++ b/chrome/browser/download/DEPS
@@ -1,4 +1,4 @@ include_rules = [ "+components/drive/drive_pref_names.h", - "+components/safe_browsing/csd.pb.h", + "+components/safe_browsing/proto/csd.pb.h", ]
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc index b3d47ee..dc37e2a 100644 --- a/chrome/browser/download/download_browsertest.cc +++ b/chrome/browser/download/download_browsertest.cc
@@ -83,7 +83,7 @@ #include "components/infobars/core/infobar.h" #include "components/prefs/pref_service.h" #include "components/safe_browsing/common/safe_browsing_prefs.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "content/public/browser/download_danger_type.h" #include "content/public/browser/download_interrupt_reasons.h" #include "content/public/browser/download_item.h" @@ -502,6 +502,12 @@ return GetDownloadDirectory(browser).Append(file.BaseName()); } + base::FilePath TemporaryFile(const base::FilePath& file) { + base::FilePath tmp; + base::GetTempDir(&tmp); + return tmp.Append(file.BaseName()); + } + // Must be called after browser creation. Creates a temporary // directory for downloads that is auto-deleted on destruction. // Returning false indicates a failure of the function, and should be asserted @@ -2025,7 +2031,7 @@ // As long as we're here, confirmed everything else is good. EXPECT_EQ(1, browser()->tab_strip_model()->count()); - CheckDownload(browser(), file, file); + CheckDownloadFullPaths(browser(), TemporaryFile(file), OriginFile(file)); } // Download an extension. Expect a dangerous download warning.
diff --git a/chrome/browser/download/download_commands.cc b/chrome/browser/download/download_commands.cc index a4a6040e..40baa91 100644 --- a/chrome/browser/download/download_commands.cc +++ b/chrome/browser/download/download_commands.cc
@@ -28,7 +28,7 @@ #include "chrome/common/url_constants.h" #include "chrome/grit/theme_resources.h" #include "components/google/core/browser/google_util.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "net/base/url_util.h" #include "ui/base/clipboard/scoped_clipboard_writer.h" #include "ui/base/resource/resource_bundle.h"
diff --git a/chrome/browser/download/download_danger_prompt.h b/chrome/browser/download/download_danger_prompt.h index 55fa38e7a7..10331bed 100644 --- a/chrome/browser/download/download_danger_prompt.h +++ b/chrome/browser/download/download_danger_prompt.h
@@ -6,7 +6,7 @@ #define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_DANGER_PROMPT_H_ #include "base/callback_forward.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" namespace content { class DownloadItem;
diff --git a/chrome/browser/download/download_danger_prompt_browsertest.cc b/chrome/browser/download/download_danger_prompt_browsertest.cc index 82eab21..dbc0f6f 100644 --- a/chrome/browser/download/download_danger_prompt_browsertest.cc +++ b/chrome/browser/download/download_danger_prompt_browsertest.cc
@@ -18,7 +18,7 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "components/safe_browsing_db/database_manager.h" #include "content/public/test/mock_download_item.h" #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/download/download_prefs.cc b/chrome/browser/download/download_prefs.cc index c6b31c58..f7a60c11 100644 --- a/chrome/browser/download/download_prefs.cc +++ b/chrome/browser/download/download_prefs.cc
@@ -79,6 +79,7 @@ class DefaultDownloadDirectory { public: const base::FilePath& path() const { return path_; } + const base::FilePath& temp_path() const { return temp_path_; } private: friend struct base::LazyInstanceTraitsBase<DefaultDownloadDirectory>; @@ -87,6 +88,11 @@ if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &path_)) { NOTREACHED(); } + + if (!base::GetTempDir(&temp_path_)) { + NOTREACHED(); + } + if (DownloadPathIsDangerous(path_)) { // This is only useful on platforms that support // DIR_DEFAULT_DOWNLOADS_SAFE. @@ -97,6 +103,7 @@ } base::FilePath path_; + base::FilePath temp_path_; DISALLOW_COPY_AND_ASSIGN(DefaultDownloadDirectory); }; @@ -238,6 +245,11 @@ } // static +const base::FilePath& DownloadPrefs::GetTempDownloadDirectory() { + return g_default_download_directory.Get().temp_path(); +} + +// static DownloadPrefs* DownloadPrefs::FromDownloadManager( DownloadManager* download_manager) { ChromeDownloadManagerDelegate* delegate =
diff --git a/chrome/browser/download/download_prefs.h b/chrome/browser/download/download_prefs.h index 0499d71..58855983 100644 --- a/chrome/browser/download/download_prefs.h +++ b/chrome/browser/download/download_prefs.h
@@ -40,6 +40,9 @@ static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); + // Returns the download directory for temporary files. + static const base::FilePath& GetTempDownloadDirectory(); + // Returns the default download directory. static const base::FilePath& GetDefaultDownloadDirectory();
diff --git a/chrome/browser/download/download_target_determiner.cc b/chrome/browser/download/download_target_determiner.cc index d3677b9..faca8fe6 100644 --- a/chrome/browser/download/download_target_determiner.cc +++ b/chrome/browser/download/download_target_determiner.cc
@@ -220,7 +220,14 @@ // If the user is going to be prompted and the user has been prompted // before, then always prefer the last directory that the user selected. target_directory = download_prefs_->SaveFilePath(); + } else if (download_prefs_->IsAutoOpenEnabledBasedOnExtension( + generated_filename)) { + // If we do not need user confirmation and we are going to auto-open the + // file, just download it to the system temp directory. + target_directory = download_prefs_->GetTempDownloadDirectory(); } else { + // The user has not configured this file to be auto-opened. Download it to + // the standard location. target_directory = download_prefs_->DownloadPath(); } virtual_path_ = target_directory.Append(generated_filename);
diff --git a/chrome/browser/download/download_target_determiner_unittest.cc b/chrome/browser/download/download_target_determiner_unittest.cc index 5398afe7..32476fe4 100644 --- a/chrome/browser/download/download_target_determiner_unittest.cc +++ b/chrome/browser/download/download_target_determiner_unittest.cc
@@ -10,6 +10,7 @@ #include "base/at_exit.h" #include "base/files/file_path.h" +#include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/location.h" #include "base/macros.h" @@ -123,6 +124,10 @@ // marked interrupted or cancelled. }; +// Used with DownloadTestCase. Whether the file is expected to be downloaded to +// the default download directory or the system-wide temp directory. +enum TestCaseExpectDirectory { DEFAULT_DIRECTORY, TEMP_DIRECTORY }; + // Typical download test case. Used with // DownloadTargetDeterminerTest::RunTestCase(). struct DownloadTestCase { @@ -154,6 +159,9 @@ // Type of intermediate path to expect. TestCaseExpectIntermediate expected_intermediate; + + // The destination directory where the file is expected to be downloaded to. + TestCaseExpectDirectory expected_directory; }; class MockDownloadTargetDeterminerDelegate @@ -238,10 +246,19 @@ // Set the kPromptForDownload user preference to |prompt|. void SetPromptForDownload(bool prompt); + // Utility function to get the full path for |relative_path| within + // |base_path|. + base::FilePath GetPathInDir(const base::FilePath::StringType& relative_path, + const base::FilePath& base_path); + // Given the relative path |path|, returns the full path under the temporary // downloads directory. base::FilePath GetPathInDownloadDir(const base::FilePath::StringType& path); + // Given the relative path |path|, returns the full path under the system + // temporary directory where auto-open files are saved. + base::FilePath GetPathInTempDir(const base::FilePath::StringType& path); + // Run |test_case| using |item|. void RunTestCase(const DownloadTestCase& test_case, const base::FilePath& initial_virtual_path, @@ -273,6 +290,8 @@ return test_virtual_dir_; } + const base::FilePath& test_temp_dir() const { return test_temp_dir_; } + MockDownloadTargetDeterminerDelegate* delegate() { return &delegate_; } @@ -289,6 +308,7 @@ NullWebContentsDelegate web_contents_delegate_; base::ScopedTempDir test_download_dir_; base::FilePath test_virtual_dir_; + base::FilePath test_temp_dir_; safe_browsing::FileTypePoliciesTestOverlay file_type_configuration_; }; @@ -299,6 +319,7 @@ web_contents()->SetDelegate(&web_contents_delegate_); ASSERT_TRUE(test_download_dir_.CreateUniqueTempDir()); test_virtual_dir_ = test_download_dir().Append(FILE_PATH_LITERAL("virtual")); + ASSERT_TRUE(base::GetTempDir(&test_temp_dir_)); download_prefs_->SetDownloadPath(test_download_dir()); delegate_.SetupDefaults(); SetUpFileTypePolicies(); @@ -384,14 +405,25 @@ SetBoolean(prefs::kPromptForDownload, prompt); } -base::FilePath DownloadTargetDeterminerTest::GetPathInDownloadDir( - const base::FilePath::StringType& relative_path) { +base::FilePath DownloadTargetDeterminerTest::GetPathInDir( + const base::FilePath::StringType& relative_path, + const base::FilePath& base_path) { if (relative_path.empty()) return base::FilePath(); - base::FilePath full_path(test_download_dir().Append(relative_path)); + base::FilePath full_path(base_path.Append(relative_path)); return full_path.NormalizePathSeparators(); } +base::FilePath DownloadTargetDeterminerTest::GetPathInDownloadDir( + const base::FilePath::StringType& relative_path) { + return GetPathInDir(relative_path, test_download_dir()); +} + +base::FilePath DownloadTargetDeterminerTest::GetPathInTempDir( + const base::FilePath::StringType& relative_path) { + return GetPathInDir(relative_path, test_temp_dir()); +} + void DownloadTargetDeterminerTest::RunTestCase( const DownloadTestCase& test_case, const base::FilePath& initial_virtual_path, @@ -439,8 +471,16 @@ void DownloadTargetDeterminerTest::VerifyDownloadTarget( const DownloadTestCase& test_case, const DownloadTargetInfo* target_info) { - base::FilePath expected_local_path( - GetPathInDownloadDir(test_case.expected_local_path)); + base::FilePath expected_local_path; + switch (test_case.expected_directory) { + case DEFAULT_DIRECTORY: + expected_local_path = GetPathInDownloadDir(test_case.expected_local_path); + break; + case TEMP_DIRECTORY: + expected_local_path = GetPathInTempDir(test_case.expected_local_path); + break; + } + EXPECT_EQ(expected_local_path.value(), target_info->target_path.value()); EXPECT_EQ(test_case.expected_disposition, target_info->target_disposition); EXPECT_EQ(test_case.expected_danger_type, target_info->danger_type); @@ -561,7 +601,7 @@ FILE_PATH_LITERAL("foo.txt"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_CRDOWNLOAD}, + EXPECT_CRDOWNLOAD, DEFAULT_DIRECTORY}, {// Save_As Safe SAVE_AS, content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, @@ -570,7 +610,7 @@ FILE_PATH_LITERAL("foo.txt"), DownloadItem::TARGET_DISPOSITION_PROMPT, - EXPECT_CRDOWNLOAD}, + EXPECT_CRDOWNLOAD, DEFAULT_DIRECTORY}, {// Automatic Dangerous AUTOMATIC, content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE, @@ -580,7 +620,7 @@ FILE_PATH_LITERAL("foo.kindabad"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_UNCONFIRMED}, + EXPECT_UNCONFIRMED, DEFAULT_DIRECTORY}, {// Forced Safe FORCED, content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, @@ -590,7 +630,7 @@ FILE_PATH_LITERAL("forced-foo.txt"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_LOCAL_PATH}, + EXPECT_LOCAL_PATH, DEFAULT_DIRECTORY}, }; // The test assumes that .kindabad files have a danger level of @@ -610,7 +650,7 @@ FILE_PATH_LITERAL(""), DownloadItem::TARGET_DISPOSITION_PROMPT, - EXPECT_LOCAL_PATH}}; + EXPECT_LOCAL_PATH, DEFAULT_DIRECTORY}}; ON_CALL(*delegate(), RequestConfirmation(_, _, _, _)) .WillByDefault(WithArg<3>(ScheduleCallback2( DownloadConfirmationResult::CANCELED, base::FilePath()))); @@ -629,7 +669,7 @@ FILE_PATH_LITERAL("foo.txt"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_UNCONFIRMED}, + EXPECT_UNCONFIRMED, DEFAULT_DIRECTORY}, {// 1: Save As Dangerous URL SAVE_AS, content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL, @@ -638,7 +678,7 @@ FILE_PATH_LITERAL("foo.txt"), DownloadItem::TARGET_DISPOSITION_PROMPT, - EXPECT_UNCONFIRMED}, + EXPECT_UNCONFIRMED, DEFAULT_DIRECTORY}, {// 2: Forced Dangerous URL FORCED, content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL, @@ -648,7 +688,7 @@ FILE_PATH_LITERAL("forced-foo.txt"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_UNCONFIRMED}, + EXPECT_UNCONFIRMED, DEFAULT_DIRECTORY}, {// 3: Automatic Dangerous URL + Dangerous file. Dangerous URL takes // precedence. @@ -659,7 +699,7 @@ FILE_PATH_LITERAL("foo.html"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_UNCONFIRMED}, + EXPECT_UNCONFIRMED, DEFAULT_DIRECTORY}, {// 4: Save As Dangerous URL + Dangerous file SAVE_AS, content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL, @@ -668,7 +708,7 @@ FILE_PATH_LITERAL("foo.html"), DownloadItem::TARGET_DISPOSITION_PROMPT, - EXPECT_UNCONFIRMED}, + EXPECT_UNCONFIRMED, DEFAULT_DIRECTORY}, {// 5: Forced Dangerous URL + Dangerous file FORCED, content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL, @@ -678,7 +718,7 @@ FILE_PATH_LITERAL("forced-foo.html"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_UNCONFIRMED}, + EXPECT_UNCONFIRMED, DEFAULT_DIRECTORY}, }; ON_CALL(*delegate(), CheckDownloadUrl(_, _, _)) @@ -698,7 +738,8 @@ "http://phishing.example.com/foo.kindabad", "", FILE_PATH_LITERAL(""), FILE_PATH_LITERAL("foo.kindabad"), - DownloadItem::TARGET_DISPOSITION_OVERWRITE, EXPECT_UNCONFIRMED}, + DownloadItem::TARGET_DISPOSITION_OVERWRITE, EXPECT_UNCONFIRMED, + DEFAULT_DIRECTORY}, {// 1: Automatic Maybe dangerous content with DANGEROUS type. AUTOMATIC, content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, @@ -706,7 +747,7 @@ FILE_PATH_LITERAL(""), FILE_PATH_LITERAL("foo.bad"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_UNCONFIRMED}, + EXPECT_UNCONFIRMED, DEFAULT_DIRECTORY}, {// 2: Save As Maybe dangerous content SAVE_AS, content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, @@ -716,7 +757,7 @@ FILE_PATH_LITERAL("foo.kindabad"), DownloadItem::TARGET_DISPOSITION_PROMPT, - EXPECT_UNCONFIRMED}, + EXPECT_UNCONFIRMED, DEFAULT_DIRECTORY}, {// 3: Forced Maybe dangerous content FORCED, content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, @@ -727,7 +768,7 @@ FILE_PATH_LITERAL("forced-foo.kindabad"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_UNCONFIRMED}}; + EXPECT_UNCONFIRMED, DEFAULT_DIRECTORY}}; // Test assumptions: ASSERT_EQ(DownloadFileType::ALLOW_ON_USER_GESTURE, @@ -755,7 +796,7 @@ FILE_PATH_LITERAL("foo.txt"), DownloadItem::TARGET_DISPOSITION_PROMPT, - EXPECT_CRDOWNLOAD}}; + EXPECT_CRDOWNLOAD, DEFAULT_DIRECTORY}}; // These test cases are run with a last save path set to a non-emtpy local // download directory. @@ -769,7 +810,7 @@ FILE_PATH_LITERAL("foo/foo.txt"), DownloadItem::TARGET_DISPOSITION_PROMPT, - EXPECT_CRDOWNLOAD}, + EXPECT_CRDOWNLOAD, DEFAULT_DIRECTORY}, {// 1: Start an automatic download. This should be saved to the user's // default download directory and not the last used Save As directory. @@ -779,7 +820,7 @@ FILE_PATH_LITERAL("foo.txt"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_CRDOWNLOAD}, + EXPECT_CRDOWNLOAD, DEFAULT_DIRECTORY}, }; // This test case is run with the last save path set to a non-empty virtual @@ -791,7 +832,7 @@ FILE_PATH_LITERAL("bar.txt"), DownloadItem::TARGET_DISPOSITION_PROMPT, - EXPECT_LOCAL_PATH}, + EXPECT_LOCAL_PATH, DEFAULT_DIRECTORY}, }; { @@ -857,7 +898,8 @@ FILE_PATH_LITERAL("foo-local.txt"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_LOCAL_PATH}; + EXPECT_LOCAL_PATH, + DEFAULT_DIRECTORY}; EXPECT_CALL(*delegate(), DetermineLocalPath(_, _, _)) .WillOnce(WithArg<2>(ScheduleCallback( GetPathInDownloadDir(FILE_PATH_LITERAL("foo-local.txt"))))); @@ -877,7 +919,8 @@ FILE_PATH_LITERAL("foo-local.txt"), DownloadItem::TARGET_DISPOSITION_PROMPT, - EXPECT_LOCAL_PATH}; + EXPECT_LOCAL_PATH, + DEFAULT_DIRECTORY}; EXPECT_CALL(*delegate(), DetermineLocalPath(_, _, _)) .WillOnce(WithArg<2>(ScheduleCallback( GetPathInDownloadDir(FILE_PATH_LITERAL("foo-local.txt"))))); @@ -904,7 +947,8 @@ FILE_PATH_LITERAL("foo-x.txt"), DownloadItem::TARGET_DISPOSITION_PROMPT, - EXPECT_CRDOWNLOAD}; + EXPECT_CRDOWNLOAD, + DEFAULT_DIRECTORY}; EXPECT_CALL(*delegate(), RequestConfirmation( _, test_virtual_dir().AppendASCII("bar.txt"), DownloadConfirmationReason::SAVE_AS, _)) @@ -927,7 +971,8 @@ FILE_PATH_LITERAL("forced-foo.txt"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_LOCAL_PATH}; + EXPECT_LOCAL_PATH, + DEFAULT_DIRECTORY}; RunTestCasesWithActiveItem(&kForcedSafe, 1); } } @@ -944,7 +989,8 @@ FILE_PATH_LITERAL(""), FILE_PATH_LITERAL("foo.txt"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_CRDOWNLOAD}; + EXPECT_CRDOWNLOAD, + DEFAULT_DIRECTORY}; const struct { TestCaseType type; @@ -988,7 +1034,8 @@ FILE_PATH_LITERAL("bar.txt"), DownloadItem::TARGET_DISPOSITION_PROMPT, - EXPECT_CRDOWNLOAD}; + EXPECT_CRDOWNLOAD, + DEFAULT_DIRECTORY}; struct TestCase { PathValidationResult result; @@ -1039,7 +1086,7 @@ FILE_PATH_LITERAL(""), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_LOCAL_PATH}, + EXPECT_LOCAL_PATH, DEFAULT_DIRECTORY}, }; // The default download directory is the virtual path. @@ -1068,7 +1115,7 @@ FILE_PATH_LITERAL("foo.kindabad"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_CRDOWNLOAD}, + EXPECT_CRDOWNLOAD, DEFAULT_DIRECTORY}, {// 1: Dangerous due to not having visited referrer before. AUTOMATIC, content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE, @@ -1079,7 +1126,7 @@ FILE_PATH_LITERAL("foo.kindabad"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_UNCONFIRMED}, + EXPECT_UNCONFIRMED, DEFAULT_DIRECTORY}, {// 2: Safe because the user is being prompted. SAVE_AS, content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, @@ -1090,7 +1137,7 @@ FILE_PATH_LITERAL("foo.kindabad"), DownloadItem::TARGET_DISPOSITION_PROMPT, - EXPECT_CRDOWNLOAD}, + EXPECT_CRDOWNLOAD, DEFAULT_DIRECTORY}, {// 3: Safe because of forced path. FORCED, content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, @@ -1101,7 +1148,7 @@ FILE_PATH_LITERAL("foo.kindabad"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_LOCAL_PATH}, + EXPECT_LOCAL_PATH, DEFAULT_DIRECTORY}, }; // This test assumes that the danger level of .kindabad files is @@ -1140,7 +1187,8 @@ FILE_PATH_LITERAL("foo.txt"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_CRDOWNLOAD}; + EXPECT_CRDOWNLOAD, + DEFAULT_DIRECTORY}; const DownloadTestCase kAllowOnUserGesture = { AUTOMATIC, @@ -1153,7 +1201,8 @@ FILE_PATH_LITERAL("foo.kindabad"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_UNCONFIRMED}; + EXPECT_UNCONFIRMED, + DEFAULT_DIRECTORY}; const DownloadTestCase kDangerousFile = { AUTOMATIC, @@ -1166,7 +1215,8 @@ FILE_PATH_LITERAL("foo.bad"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_UNCONFIRMED}; + EXPECT_UNCONFIRMED, + DEFAULT_DIRECTORY}; const struct { ui::PageTransition page_transition; @@ -1263,7 +1313,8 @@ FILE_PATH_LITERAL("automatic.txt"), DownloadItem::TARGET_DISPOSITION_PROMPT, - EXPECT_CRDOWNLOAD}; + EXPECT_CRDOWNLOAD, + DEFAULT_DIRECTORY}; SetPromptForDownload(true); EXPECT_CALL(*delegate(), @@ -1286,7 +1337,8 @@ FILE_PATH_LITERAL("save-as.txt"), DownloadItem::TARGET_DISPOSITION_PROMPT, - EXPECT_CRDOWNLOAD}; + EXPECT_CRDOWNLOAD, + DEFAULT_DIRECTORY}; SetPromptForDownload(true); EXPECT_CALL(*delegate(), @@ -1309,7 +1361,8 @@ FILE_PATH_LITERAL("foo.txt"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_LOCAL_PATH}; + EXPECT_LOCAL_PATH, + DEFAULT_DIRECTORY}; SetPromptForDownload(true); RunTestCasesWithActiveItem(&kSafeForced, 1); @@ -1329,13 +1382,56 @@ FILE_PATH_LITERAL("foo.dummy"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_CRDOWNLOAD}; + EXPECT_CRDOWNLOAD, + TEMP_DIRECTORY}; SetPromptForDownload(true); EnableAutoOpenBasedOnExtension( base::FilePath(FILE_PATH_LITERAL("dummy.dummy"))); RunTestCasesWithActiveItem(&kAutoOpen, 1); } +// In an automatic download, auto-opened files should be saved to a temp +// directory. +TEST_F(DownloadTargetDeterminerTest, AutoOpen_Automatic) { + const DownloadTestCase kTestCase = { + AUTOMATIC, + content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, + DownloadFileType::NOT_DANGEROUS, + "http://example.com/foo.dummy", + "", + FILE_PATH_LITERAL(""), + + FILE_PATH_LITERAL("foo.dummy"), + DownloadItem::TARGET_DISPOSITION_OVERWRITE, + + EXPECT_CRDOWNLOAD, + TEMP_DIRECTORY}; + EnableAutoOpenBasedOnExtension( + base::FilePath(FILE_PATH_LITERAL("dummy.dummy"))); + RunTestCasesWithActiveItem(&kTestCase, 1); +} + +// Even if we are set to auto-open this file, save the file to a permanent +// location if triggered by a Save As. +TEST_F(DownloadTargetDeterminerTest, AutoOpen_SaveAs) { + const DownloadTestCase kTestCase = { + SAVE_AS, + content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, + DownloadFileType::NOT_DANGEROUS, + "http://example.com/foo.dummy", + "", + FILE_PATH_LITERAL(""), + + FILE_PATH_LITERAL("foo.dummy"), + DownloadItem::TARGET_DISPOSITION_PROMPT, + + EXPECT_CRDOWNLOAD, + DEFAULT_DIRECTORY}; + EnableAutoOpenBasedOnExtension( + base::FilePath(FILE_PATH_LITERAL("dummy.dummy"))); + RunTestCasesWithActiveItem(&kTestCase, 1); +} + // If an embedder responds to a RequestConfirmation with a new path and a // CONTINUE_WITHOUT_CONFIRMATION, then we shouldn't consider the file as safe. TEST_F(DownloadTargetDeterminerTest, ContinueWithoutConfirmation_SaveAs) { @@ -1350,7 +1446,8 @@ FILE_PATH_LITERAL("foo.kindabad"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_UNCONFIRMED}; + EXPECT_UNCONFIRMED, + DEFAULT_DIRECTORY}; EXPECT_CALL( *delegate(), @@ -1378,7 +1475,8 @@ FILE_PATH_LITERAL("foo.kindabad"), DownloadItem::TARGET_DISPOSITION_PROMPT, - EXPECT_CRDOWNLOAD}; + EXPECT_CRDOWNLOAD, + DEFAULT_DIRECTORY}; EXPECT_CALL( *delegate(), @@ -1408,7 +1506,7 @@ FILE_PATH_LITERAL("foo.kindabad"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_UNCONFIRMED}, + EXPECT_UNCONFIRMED, DEFAULT_DIRECTORY}, {// 1: Automatic User Script - Shouldn't prompt for user script downloads // even if "Prompt for download" preference is set. @@ -1419,7 +1517,7 @@ FILE_PATH_LITERAL("foo.user.js"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_CRDOWNLOAD}, + EXPECT_CRDOWNLOAD, DEFAULT_DIRECTORY}, }; SetPromptForDownload(true); @@ -1439,7 +1537,7 @@ FILE_PATH_LITERAL("foo.txt"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_CRDOWNLOAD}, + EXPECT_CRDOWNLOAD, DEFAULT_DIRECTORY}, {// 1: Save_As Safe SAVE_AS, content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, @@ -1448,7 +1546,7 @@ FILE_PATH_LITERAL("foo.txt"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_CRDOWNLOAD}, + EXPECT_CRDOWNLOAD, DEFAULT_DIRECTORY}, }; SetManagedDownloadPath(test_download_dir()); @@ -1469,7 +1567,7 @@ FILE_PATH_LITERAL("overridden/foo.txt"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_CRDOWNLOAD}, + EXPECT_CRDOWNLOAD, DEFAULT_DIRECTORY}, {// 1: Save_As Safe SAVE_AS, content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, @@ -1479,7 +1577,7 @@ FILE_PATH_LITERAL("overridden/foo.txt"), DownloadItem::TARGET_DISPOSITION_PROMPT, - EXPECT_CRDOWNLOAD}, + EXPECT_CRDOWNLOAD, DEFAULT_DIRECTORY}, {// 2: Automatic Dangerous AUTOMATIC, content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE, @@ -1489,7 +1587,7 @@ FILE_PATH_LITERAL("overridden/foo.kindabad"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_UNCONFIRMED}, + EXPECT_UNCONFIRMED, DEFAULT_DIRECTORY}, {// 3: Forced Safe FORCED, content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, @@ -1499,7 +1597,7 @@ FILE_PATH_LITERAL("forced-foo.txt"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_LOCAL_PATH}, + EXPECT_LOCAL_PATH, DEFAULT_DIRECTORY}, }; ON_CALL(*delegate(), NotifyExtensions(_, _, _)) @@ -1522,7 +1620,8 @@ FILE_PATH_LITERAL("overridden/foo.kindabad"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_UNCONFIRMED}; + EXPECT_UNCONFIRMED, + DEFAULT_DIRECTORY}; const DownloadTestCase kHandledBySafeBrowsing = { AUTOMATIC, @@ -1535,7 +1634,8 @@ FILE_PATH_LITERAL("overridden/foo.kindabad"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_UNCONFIRMED}; + EXPECT_UNCONFIRMED, + DEFAULT_DIRECTORY}; ON_CALL(*delegate(), NotifyExtensions(_, _, _)) .WillByDefault(Invoke(&NotifyExtensionsOverridePath)); @@ -1561,7 +1661,8 @@ FILE_PATH_LITERAL("overridden/foo.txt"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_CRDOWNLOAD}; + EXPECT_CRDOWNLOAD, + DEFAULT_DIRECTORY}; const DownloadTestCase& test_case = kNotifyExtensionsTestCase; std::unique_ptr<content::MockDownloadItem> item = @@ -1610,7 +1711,8 @@ FILE_PATH_LITERAL("overridden/foo.txt"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_CRDOWNLOAD}; + EXPECT_CRDOWNLOAD, + DEFAULT_DIRECTORY}; const DownloadTestCase& test_case = kNotifyExtensionsTestCase; std::unique_ptr<content::MockDownloadItem> item = @@ -1647,7 +1749,8 @@ kInitialPath, DownloadItem::TARGET_DISPOSITION_PROMPT, - EXPECT_CRDOWNLOAD}; + EXPECT_CRDOWNLOAD, + DEFAULT_DIRECTORY}; const DownloadTestCase& test_case = kInitialPathTestCase; std::unique_ptr<content::MockDownloadItem> item = @@ -1680,7 +1783,7 @@ FILE_PATH_LITERAL("foo.txt"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_CRDOWNLOAD}, + EXPECT_CRDOWNLOAD, DEFAULT_DIRECTORY}, {// 1: Save_As Safe: Initial path used. SAVE_AS, content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, @@ -1689,7 +1792,7 @@ kInitialPath, DownloadItem::TARGET_DISPOSITION_PROMPT, - EXPECT_CRDOWNLOAD}, + EXPECT_CRDOWNLOAD, DEFAULT_DIRECTORY}, {// 2: Automatic Dangerous: Initial path is ignored since the user hasn't // been prompted before. @@ -1700,7 +1803,7 @@ FILE_PATH_LITERAL("foo.kindabad"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_UNCONFIRMED}, + EXPECT_UNCONFIRMED, DEFAULT_DIRECTORY}, {// 3: Forced Safe: Initial path is ignored due to the forced path. FORCED, content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, @@ -1710,7 +1813,7 @@ FILE_PATH_LITERAL("forced-foo.txt"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_LOCAL_PATH}, + EXPECT_LOCAL_PATH, DEFAULT_DIRECTORY}, }; // The test assumes that .kindabad files have a danger level of @@ -1759,7 +1862,8 @@ FILE_PATH_LITERAL("forced-foo.txt"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_LOCAL_PATH}; + EXPECT_LOCAL_PATH, + DEFAULT_DIRECTORY}; const DownloadTestCase& test_case = kResumedForcedDownload; base::FilePath expected_path = @@ -1804,27 +1908,24 @@ kInitialPath, DownloadItem::TARGET_DISPOSITION_PROMPT, - EXPECT_CRDOWNLOAD}, + EXPECT_CRDOWNLOAD, DEFAULT_DIRECTORY}, - { - // 2: Automatic Dangerous - AUTOMATIC, content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, - DownloadFileType::NOT_DANGEROUS, "http://example.com/foo.kindabad", - "", FILE_PATH_LITERAL(""), + {// 2: Automatic Dangerous + AUTOMATIC, content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, + DownloadFileType::NOT_DANGEROUS, "http://example.com/foo.kindabad", "", + FILE_PATH_LITERAL(""), - FILE_PATH_LITERAL("foo.kindabad"), - DownloadItem::TARGET_DISPOSITION_PROMPT, EXPECT_CRDOWNLOAD, - }, + FILE_PATH_LITERAL("foo.kindabad"), + DownloadItem::TARGET_DISPOSITION_PROMPT, EXPECT_CRDOWNLOAD, + DEFAULT_DIRECTORY}, - { - // 3: Automatic Dangerous - AUTOMATIC, content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, - DownloadFileType::NOT_DANGEROUS, "http://example.com/foo.bad", "", - FILE_PATH_LITERAL(""), + {// 3: Automatic Dangerous + AUTOMATIC, content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, + DownloadFileType::NOT_DANGEROUS, "http://example.com/foo.bad", "", + FILE_PATH_LITERAL(""), - FILE_PATH_LITERAL("foo.bad"), DownloadItem::TARGET_DISPOSITION_PROMPT, - EXPECT_CRDOWNLOAD, - }, + FILE_PATH_LITERAL("foo.bad"), DownloadItem::TARGET_DISPOSITION_PROMPT, + EXPECT_CRDOWNLOAD, DEFAULT_DIRECTORY}, }; ASSERT_EQ(DownloadFileType::ALLOW_ON_USER_GESTURE, @@ -1878,7 +1979,7 @@ FILE_PATH_LITERAL("foo.txt"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_CRDOWNLOAD}, + EXPECT_CRDOWNLOAD, DEFAULT_DIRECTORY}, FILE_PATH_LITERAL("bar.txt.crdownload"), FILE_PATH_LITERAL("foo.txt.crdownload")}, @@ -1889,7 +1990,7 @@ kInitialPath, DownloadItem::TARGET_DISPOSITION_PROMPT, - EXPECT_CRDOWNLOAD}, + EXPECT_CRDOWNLOAD, DEFAULT_DIRECTORY}, FILE_PATH_LITERAL("foo.txt.crdownload"), FILE_PATH_LITERAL("some_path/bar.txt.crdownload")}, @@ -1901,7 +2002,7 @@ FILE_PATH_LITERAL("foo.kindabad"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_UNCONFIRMED}, + EXPECT_UNCONFIRMED, DEFAULT_DIRECTORY}, FILE_PATH_LITERAL("Unconfirmed abcd.crdownload"), FILE_PATH_LITERAL("Unconfirmed abcd.crdownload")}, @@ -1913,7 +2014,7 @@ FILE_PATH_LITERAL("foo.kindabad"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_UNCONFIRMED}, + EXPECT_UNCONFIRMED, DEFAULT_DIRECTORY}, FILE_PATH_LITERAL("other_path/Unconfirmed abcd.crdownload"), // Rely on the EXPECT_UNCONFIRMED check in the general test settings. A // new intermediate path of the form "Unconfirmed <number>.crdownload" @@ -1929,7 +2030,7 @@ FILE_PATH_LITERAL("forced-foo.txt"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_LOCAL_PATH}, + EXPECT_LOCAL_PATH, DEFAULT_DIRECTORY}, FILE_PATH_LITERAL("forced-foo.txt"), FILE_PATH_LITERAL("forced-foo.txt")}, }; @@ -1988,7 +2089,7 @@ FILE_PATH_LITERAL("foo.png"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_CRDOWNLOAD}, + EXPECT_CRDOWNLOAD, DEFAULT_DIRECTORY}, "image/png"}, {{// 1: Empty MIME type in response. AUTOMATIC, content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, @@ -1998,7 +2099,7 @@ FILE_PATH_LITERAL("foo.png"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_CRDOWNLOAD}, + EXPECT_CRDOWNLOAD, DEFAULT_DIRECTORY}, "image/png"}, {{// 2: Forced path. FORCED, content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, @@ -2008,7 +2109,7 @@ FILE_PATH_LITERAL("foo.png"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_CRDOWNLOAD}, + EXPECT_CRDOWNLOAD, DEFAULT_DIRECTORY}, "image/png"}, {{// 3: Unknown file type. AUTOMATIC, content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, @@ -2018,7 +2119,7 @@ FILE_PATH_LITERAL("foo.notarealext"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_CRDOWNLOAD}, + EXPECT_CRDOWNLOAD, DEFAULT_DIRECTORY}, ""}, {{// 4: Unknown file type. AUTOMATIC, content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, @@ -2028,7 +2129,7 @@ FILE_PATH_LITERAL("foo.notarealext"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_CRDOWNLOAD}, + EXPECT_CRDOWNLOAD, DEFAULT_DIRECTORY}, ""}, {{// 5: x-x509-user-cert mime-type. AUTOMATIC, content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, @@ -2038,7 +2139,7 @@ FILE_PATH_LITERAL("user.crt"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_CRDOWNLOAD}, + EXPECT_CRDOWNLOAD, DEFAULT_DIRECTORY}, ""}, }; @@ -2075,7 +2176,8 @@ FILE_PATH_LITERAL(""), FILE_PATH_LITERAL("foo.crx"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_CRDOWNLOAD}; + EXPECT_CRDOWNLOAD, + DEFAULT_DIRECTORY}; const DownloadTestCase& test_case = kUserValidatedTestCase; std::unique_ptr<content::MockDownloadItem> item( @@ -2227,7 +2329,8 @@ FILE_PATH_LITERAL("foo.fakeext"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_CRDOWNLOAD}; + EXPECT_CRDOWNLOAD, + DEFAULT_DIRECTORY}; content::PluginService* plugin_service = content::PluginService::GetInstance(); @@ -2296,7 +2399,8 @@ FILE_PATH_LITERAL("foo.fakeext"), DownloadItem::TARGET_DISPOSITION_OVERWRITE, - EXPECT_CRDOWNLOAD}; + EXPECT_CRDOWNLOAD, + DEFAULT_DIRECTORY}; content::PluginService* plugin_service = content::PluginService::GetInstance();
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc index c8a2423..44d26a7 100644 --- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc +++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -902,6 +902,7 @@ PackExtensionJob::StandardSuccessMessage(crx_file, pem_file)); response.status = developer::PACK_STATUS_SUCCESS; Respond(OneArgument(response.ToValue())); + pack_job_.reset(); Release(); // Balanced in Run(). } @@ -919,6 +920,7 @@ response.status = developer::PACK_STATUS_ERROR; } Respond(OneArgument(response.ToValue())); + pack_job_.reset(); Release(); // Balanced in Run(). } @@ -958,8 +960,8 @@ AddRef(); // Balanced in OnPackSuccess / OnPackFailure. - // TODO(devlin): Why is PackExtensionJob ref-counted? - pack_job_ = new PackExtensionJob(this, root_directory, key_file, flags); + pack_job_ = + base::MakeUnique<PackExtensionJob>(this, root_directory, key_file, flags); pack_job_->Start(); return RespondLater(); }
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.h b/chrome/browser/extensions/api/developer_private/developer_private_api.h index 7580156..84e0e8c 100644 --- a/chrome/browser/extensions/api/developer_private/developer_private_api.h +++ b/chrome/browser/extensions/api/developer_private/developer_private_api.h
@@ -466,7 +466,7 @@ ResponseAction Run() override; private: - scoped_refptr<PackExtensionJob> pack_job_; + std::unique_ptr<PackExtensionJob> pack_job_; std::string item_path_str_; std::string key_path_str_; };
diff --git a/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc b/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc index 13c4e52..3e925eae 100644 --- a/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc +++ b/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc
@@ -9,7 +9,9 @@ #include "base/memory/ptr_util.h" #include "base/values.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/feedback/system_logs/chrome_system_logs_fetcher.h" #include "chrome/grit/generated_resources.h" +#include "components/feedback/system_logs/system_logs_fetcher.h" #include "components/strings/grit/components_strings.h" #include "content/public/browser/browser_context.h" #include "ui/base/l10n/l10n_util.h" @@ -86,4 +88,10 @@ return dict; } +system_logs::SystemLogsFetcher* +ChromeFeedbackPrivateDelegate::CreateSystemLogsFetcher( + content::BrowserContext* context) const { + return system_logs::BuildChromeSystemLogsFetcher(); +} + } // namespace extensions
diff --git a/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.h b/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.h index 0e02e5b..27a881e 100644 --- a/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.h +++ b/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.h
@@ -22,6 +22,8 @@ std::unique_ptr<base::DictionaryValue> GetStrings( content::BrowserContext* browser_context, bool from_crash) const override; + system_logs::SystemLogsFetcher* CreateSystemLogsFetcher( + content::BrowserContext* context) const override; private: DISALLOW_COPY_AND_ASSIGN(ChromeFeedbackPrivateDelegate);
diff --git a/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc b/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc index 534533b..993f9dc 100644 --- a/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc +++ b/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc
@@ -27,6 +27,7 @@ #include "chrome/common/extensions/api/feedback_private.h" #include "chrome/common/extensions/extension_constants.h" #include "chrome/grit/generated_resources.h" +#include "components/feedback/system_logs/system_logs_fetcher.h" #include "components/feedback/tracing_manager.h" #include "components/signin/core/browser/signin_manager.h" #include "extensions/browser/api/extensions_api_client.h" @@ -92,9 +93,9 @@ FeedbackPrivateAPI::FeedbackPrivateAPI(content::BrowserContext* context) : browser_context_(context), #if !defined(OS_CHROMEOS) - service_(new FeedbackService()) { + service_(new FeedbackService(context)) { #else - service_(new FeedbackService()), + service_(new FeedbackService(context)), log_source_access_manager_(new LogSourceAccessManager(context)){ #endif // defined(OS_CHROMEOS) } @@ -211,13 +212,16 @@ ExtensionFunction::ResponseAction FeedbackPrivateGetSystemInformationFunction::Run() { - FeedbackService* service = FeedbackPrivateAPI::GetFactoryInstance() - ->Get(browser_context()) - ->GetService(); - DCHECK(service); - service->GetSystemInformation( - base::Bind( - &FeedbackPrivateGetSystemInformationFunction::OnCompleted, this)); + FeedbackPrivateDelegate* feedback_private_delegate = + ExtensionsAPIClient::Get()->GetFeedbackPrivateDelegate(); + DCHECK(feedback_private_delegate); + + // Self-deleting object. + system_logs::SystemLogsFetcher* fetcher = + feedback_private_delegate->CreateSystemLogsFetcher(browser_context()); + fetcher->Fetch(base::Bind( + &FeedbackPrivateGetSystemInformationFunction::OnCompleted, this)); + return RespondLater(); } @@ -329,7 +333,7 @@ } service->SendFeedback( - browser_context(), feedback_data, + feedback_data, base::Bind(&FeedbackPrivateSendFeedbackFunction::OnCompleted, this)); return RespondLater();
diff --git a/chrome/browser/extensions/api/feedback_private/feedback_service.cc b/chrome/browser/extensions/api/feedback_private/feedback_service.cc index 8d1fcef..7baa7cfd 100644 --- a/chrome/browser/extensions/api/feedback_private/feedback_service.cc +++ b/chrome/browser/extensions/api/feedback_private/feedback_service.cc
@@ -9,7 +9,6 @@ #include "base/callback.h" #include "base/memory/weak_ptr.h" #include "base/strings/string_number_conversions.h" -#include "chrome/browser/feedback/system_logs/chrome_system_logs_fetcher.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "extensions/browser/blob_reader.h" @@ -22,14 +21,13 @@ namespace extensions { -FeedbackService::FeedbackService() { -} +FeedbackService::FeedbackService(content::BrowserContext* browser_context) + : browser_context_(browser_context) {} FeedbackService::~FeedbackService() { } -void FeedbackService::SendFeedback(content::BrowserContext* browser_context, - scoped_refptr<FeedbackData> feedback_data, +void FeedbackService::SendFeedback(scoped_refptr<FeedbackData> feedback_data, const SendFeedbackCallback& callback) { feedback_data->set_locale( ExtensionsBrowserClient::Get()->GetApplicationLocale()); @@ -38,7 +36,7 @@ if (!feedback_data->attached_file_uuid().empty()) { // Self-deleting object. BlobReader* attached_file_reader = - new BlobReader(browser_context, feedback_data->attached_file_uuid(), + new BlobReader(browser_context_, feedback_data->attached_file_uuid(), base::Bind(&FeedbackService::AttachedFileCallback, AsWeakPtr(), feedback_data, callback)); attached_file_reader->Start(); @@ -47,7 +45,7 @@ if (!feedback_data->screenshot_uuid().empty()) { // Self-deleting object. BlobReader* screenshot_reader = - new BlobReader(browser_context, feedback_data->screenshot_uuid(), + new BlobReader(browser_context_, feedback_data->screenshot_uuid(), base::Bind(&FeedbackService::ScreenshotCallback, AsWeakPtr(), feedback_data, callback)); screenshot_reader->Start(); @@ -56,14 +54,6 @@ CompleteSendFeedback(feedback_data, callback); } -void FeedbackService::GetSystemInformation( - const system_logs::SysLogsFetcherCallback& callback) { - // Self-deleting object. - system_logs::SystemLogsFetcher* fetcher = - system_logs::BuildChromeSystemLogsFetcher(); - fetcher->Fetch(callback); -} - void FeedbackService::AttachedFileCallback( scoped_refptr<feedback::FeedbackData> feedback_data, const SendFeedbackCallback& callback,
diff --git a/chrome/browser/extensions/api/feedback_private/feedback_service.h b/chrome/browser/extensions/api/feedback_private/feedback_service.h index d51ca86f..f6530de 100644 --- a/chrome/browser/extensions/api/feedback_private/feedback_service.h +++ b/chrome/browser/extensions/api/feedback_private/feedback_service.h
@@ -13,11 +13,10 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "components/feedback/feedback_data.h" -#include "components/feedback/system_logs/system_logs_fetcher.h" namespace content { class BrowserContext; -} +} // namespace content namespace extensions { @@ -32,19 +31,13 @@ // offline). using SendFeedbackCallback = base::Callback<void(bool)>; - FeedbackService(); + explicit FeedbackService(content::BrowserContext* browser_context); virtual ~FeedbackService(); // Sends a feedback report. - void SendFeedback(content::BrowserContext* browser_context, - scoped_refptr<feedback::FeedbackData> feedback_data, + void SendFeedback(scoped_refptr<feedback::FeedbackData> feedback_data, const SendFeedbackCallback& callback); - // Start to gather system information. - // The |callback| will be invoked once the query is completed. - void GetSystemInformation( - const system_logs::SysLogsFetcherCallback& callback); - private: // Callbacks to receive blob data. void AttachedFileCallback(scoped_refptr<feedback::FeedbackData> feedback_data, @@ -61,6 +54,8 @@ void CompleteSendFeedback(scoped_refptr<feedback::FeedbackData> feedback_data, const SendFeedbackCallback& callback); + content::BrowserContext* browser_context_; + DISALLOW_COPY_AND_ASSIGN(FeedbackService); };
diff --git a/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc b/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc index 103a946..cf7da48 100644 --- a/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc +++ b/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc
@@ -152,8 +152,11 @@ drive::DriveIntegrationService* CreateDriveIntegrationService( Profile* profile) { // Ignore signin profile. - if (profile->GetPath() == chromeos::ProfileHelper::GetSigninProfileDir()) + if (profile->GetPath() == chromeos::ProfileHelper::GetSigninProfileDir() || + profile->GetPath() == + chromeos::ProfileHelper::GetLockScreenAppProfilePath()) { return nullptr; + } // FileSystemApiTestForDrive doesn't expect that several user profiles could // exist simultaneously.
diff --git a/chrome/browser/extensions/extension_context_menu_browsertest.cc b/chrome/browser/extensions/extension_context_menu_browsertest.cc index ec76b112..30e3ef8 100644 --- a/chrome/browser/extensions/extension_context_menu_browsertest.cc +++ b/chrome/browser/extensions/extension_context_menu_browsertest.cc
@@ -76,13 +76,11 @@ const extensions::ExtensionSet& extensions = extensions::ExtensionRegistry::Get( browser()->profile())->enabled_extensions(); - for (extensions::ExtensionSet::const_iterator i = extensions.begin(); - i != extensions.end(); ++i) { - if ((*i)->name() == name) { - return i->get(); - } + for (const auto& ext : extensions) { + if (ext->name() == name) + return ext.get(); } - return NULL; + return nullptr; } // This gets all the items that any extension has registered for possible @@ -178,10 +176,8 @@ bool MenuHasExtensionItemWithLabel(TestRenderViewContextMenu* menu, const std::string& label) { base::string16 label16 = base::UTF8ToUTF16(label); - std::map<int, MenuItem::Id>::iterator i; - for (i = menu->extension_items().extension_item_map_.begin(); - i != menu->extension_items().extension_item_map_.end(); ++i) { - const MenuItem::Id& id = i->second; + for (const auto& it : menu->extension_items().extension_item_map_) { + const MenuItem::Id& id = it.second; base::string16 tmp_label; EXPECT_TRUE(GetItemLabel(menu, id, &tmp_label)); if (tmp_label == label16) @@ -195,12 +191,12 @@ // false. bool GetItemLabel(TestRenderViewContextMenu* menu, const MenuItem::Id& id, - base::string16* result) { + base::string16* result) const { int command_id = 0; if (!FindCommandId(menu, id, &command_id)) return false; - MenuModel* model = NULL; + MenuModel* model = nullptr; int index = -1; if (!menu->GetMenuModelAndItemIndex(command_id, &model, &index)) { return false; @@ -213,12 +209,10 @@ // in the menu. bool FindCommandId(TestRenderViewContextMenu* menu, const MenuItem::Id& id, - int* command_id) { - std::map<int, MenuItem::Id>::const_iterator i; - for (i = menu->extension_items().extension_item_map_.begin(); - i != menu->extension_items().extension_item_map_.end(); ++i) { - if (i->second == id) { - *command_id = i->first; + int* command_id) const { + for (const auto& it : menu->extension_items().extension_item_map_) { + if (it.second == id) { + *command_id = it.first; return true; } } @@ -312,8 +306,8 @@ ASSERT_TRUE(listener_update2.WaitUntilSatisfied()); // Rebuild the context menu and click on the second extension item. - menu.reset(TestRenderViewContextMenu::Create(GetWebContents(), page_url, - GURL(), GURL())); + menu = TestRenderViewContextMenu::Create(GetWebContents(), page_url, GURL(), + GURL()); id.string_uid = "id2"; ASSERT_TRUE(FindCommandId(menu.get(), id, &command_id)); menu->ExecuteCommand(command_id, 0); @@ -542,7 +536,7 @@ TestRenderViewContextMenu::Create(GetWebContents(), url, GURL(), GURL())); int index = 0; - MenuModel* model = NULL; + MenuModel* model = nullptr; ASSERT_TRUE(menu->GetMenuModelAndItemIndex( ContextMenuMatcher::ConvertToExtensionsCustomCommandId(0), @@ -612,7 +606,7 @@ // Load the extension. ASSERT_TRUE(LoadContextMenuExtension("separators")); const extensions::Extension* extension = GetExtensionNamed("Separators Test"); - ASSERT_TRUE(extension != NULL); + ASSERT_TRUE(extension); // Navigate to test1.html inside the extension, which should create a bunch // of items at the top-level (but they'll get pushed into an auto-generated @@ -628,7 +622,7 @@ // The top-level item should be an "automagic parent" with the extension's // name. - MenuModel* model = NULL; + MenuModel* model = nullptr; int index = 0; base::string16 label; ASSERT_TRUE(menu->GetMenuModelAndItemIndex( @@ -640,7 +634,7 @@ // Get the submenu and verify the items there. MenuModel* submenu = model->GetSubmenuModelAt(index); - ASSERT_TRUE(submenu != NULL); + ASSERT_TRUE(submenu); VerifyMenuForSeparatorsTest(*submenu); // Now run our second test - navigate to test2.html which creates an explicit @@ -649,15 +643,15 @@ ui_test_utils::NavigateToURL(browser(), GURL(extension->GetResourceURL("test2.html"))); listener2.WaitUntilSatisfied(); - menu.reset( - TestRenderViewContextMenu::Create(GetWebContents(), url, GURL(), GURL())); + menu = + TestRenderViewContextMenu::Create(GetWebContents(), url, GURL(), GURL()); ASSERT_TRUE(menu->GetMenuModelAndItemIndex( ContextMenuMatcher::ConvertToExtensionsCustomCommandId(0), &model, &index)); EXPECT_EQ(base::UTF8ToUTF16("parent"), model->GetLabelAt(index)); submenu = model->GetSubmenuModelAt(index); - ASSERT_TRUE(submenu != NULL); + ASSERT_TRUE(submenu); VerifyMenuForSeparatorsTest(*submenu); }
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc index 9be8d26..07c82e0 100644 --- a/chrome/browser/extensions/extension_service_unittest.cc +++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -1912,18 +1912,20 @@ temp_dir.GetPath().Append(expected_private_key_names[i]); PackExtensionTestClient pack_client(expected_crx_path, expected_private_key_path); - scoped_refptr<extensions::PackExtensionJob> packer( - new extensions::PackExtensionJob(&pack_client, output_dir, - base::FilePath(), - ExtensionCreator::kOverwriteCRX)); - packer->Start(); + { + extensions::PackExtensionJob packer(&pack_client, output_dir, + base::FilePath(), + ExtensionCreator::kOverwriteCRX); + packer.Start(); - // The packer will post a notification task to the current thread's message - // loop when it is finished. We manually run the loop here so that we - // block and catch the notification; otherwise, the process would exit. - // This call to |Run()| is matched by a call to |Quit()| in the - // |PackExtensionTestClient|'s notification handling code. - base::RunLoop().Run(); + // The packer will post a notification task to the current thread's + // message loop when it is finished. We manually run the loop here so + // that we block and catch the notification; otherwise, the process would + // exit. + // This call to |Run()| is matched by a call to |Quit()| in the + // |PackExtensionTestClient|'s notification handling code. + base::RunLoop().Run(); + } if (HasFatalFailure()) return;
diff --git a/chrome/browser/extensions/pack_extension_job.cc b/chrome/browser/extensions/pack_extension_job.cc index 330b028..87d07d9 100644 --- a/chrome/browser/extensions/pack_extension_job.cc +++ b/chrome/browser/extensions/pack_extension_job.cc
@@ -8,8 +8,11 @@ #include "base/message_loop/message_loop.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "chrome/browser/extensions/extension_creator.h" #include "chrome/grit/generated_resources.h" +#include "content/public/browser/browser_thread.h" +#include "extensions/browser/extension_file_task_runner.h" #include "extensions/common/constants.h" #include "ui/base/l10n/l10n_util.h" @@ -21,70 +24,92 @@ const base::FilePath& root_directory, const base::FilePath& key_file, int run_flags) - : client_(client), key_file_(key_file), asynchronous_(true), + : client_(client), + key_file_(key_file), run_flags_(run_flags | ExtensionCreator::kRequireModernManifestVersion) { root_directory_ = root_directory.StripTrailingSeparators(); - CHECK(BrowserThread::GetCurrentThreadIdentifier(&client_thread_id_)); -} - -void PackExtensionJob::Start() { - if (asynchronous_) { - BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, - base::BindOnce(&PackExtensionJob::Run, this)); - } else { - Run(); - } -} - -void PackExtensionJob::ClearClient() { - client_ = NULL; } PackExtensionJob::~PackExtensionJob() {} -void PackExtensionJob::Run() { - crx_file_out_ = base::FilePath(root_directory_.value() + - kExtensionFileExtension); +void PackExtensionJob::Start() { + if (run_mode_ == RunMode::ASYNCHRONOUS) { + scoped_refptr<base::SequencedTaskRunner> task_runner = + base::SequencedTaskRunnerHandle::Get(); + GetExtensionFileTaskRunner()->PostTask( + FROM_HERE, + base::BindOnce(&PackExtensionJob::Run, + // See class level comments for why Unretained is safe. + base::Unretained(this), std::move(task_runner))); + } else { + DCHECK_EQ(RunMode::SYNCHRONOUS, run_mode_); + Run(nullptr); + } +} - if (key_file_.empty()) - key_file_out_ = base::FilePath(root_directory_.value() + - kExtensionKeyFileExtension); +void PackExtensionJob::Run( + scoped_refptr<base::SequencedTaskRunner> async_reply_task_runner) { + DCHECK_EQ(!!async_reply_task_runner, run_mode_ == RunMode::ASYNCHRONOUS) + << "Provide task runner iff we are running in asynchronous mode."; + // TODO(lazyboy): Use root_directory_.AddExtension(kExtensionFileExtension). + auto crx_file_out = base::MakeUnique<base::FilePath>(root_directory_.value() + + kExtensionFileExtension); + + auto key_file_out = base::MakeUnique<base::FilePath>(); + if (key_file_.empty()) { + // TODO(lazyboy): Use + // root_directory_.AddExtension(kExtensionKeyFileExtension). + *key_file_out = + base::FilePath(root_directory_.value() + kExtensionKeyFileExtension); + } // TODO(aa): Need to internationalize the errors that ExtensionCreator // returns. See bug 20734. ExtensionCreator creator; - if (creator.Run(root_directory_, crx_file_out_, key_file_, key_file_out_, + if (creator.Run(root_directory_, *crx_file_out, key_file_, *key_file_out, run_flags_)) { - if (asynchronous_) { - BrowserThread::PostTask( - client_thread_id_, FROM_HERE, - base::BindOnce(&PackExtensionJob::ReportSuccessOnClientThread, this)); + if (run_mode_ == RunMode::ASYNCHRONOUS) { + async_reply_task_runner->PostTask( + FROM_HERE, + base::BindOnce(&PackExtensionJob::ReportSuccessOnClientSequence, + // See class level comments for why Unretained is safe. + base::Unretained(this), std::move(crx_file_out), + std::move(key_file_out))); + } else { - ReportSuccessOnClientThread(); + ReportSuccessOnClientSequence(std::move(crx_file_out), + std::move(key_file_out)); } } else { - if (asynchronous_) { - BrowserThread::PostTask( - client_thread_id_, FROM_HERE, - base::BindOnce(&PackExtensionJob::ReportFailureOnClientThread, this, - creator.error_message(), creator.error_type())); + if (run_mode_ == RunMode::ASYNCHRONOUS) { + async_reply_task_runner->PostTask( + FROM_HERE, + base::BindOnce(&PackExtensionJob::ReportFailureOnClientSequence, + // See class level comments for why Unretained is safe. + base::Unretained(this), creator.error_message(), + creator.error_type())); } else { - ReportFailureOnClientThread(creator.error_message(), - creator.error_type()); + DCHECK_EQ(RunMode::SYNCHRONOUS, run_mode_); + ReportFailureOnClientSequence(creator.error_message(), + creator.error_type()); } } } -void PackExtensionJob::ReportSuccessOnClientThread() { - if (client_) - client_->OnPackSuccess(crx_file_out_, key_file_out_); +void PackExtensionJob::ReportSuccessOnClientSequence( + std::unique_ptr<base::FilePath> crx_file_out, + std::unique_ptr<base::FilePath> key_file_out) { + DCHECK(client_); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + client_->OnPackSuccess(*crx_file_out, *key_file_out); } -void PackExtensionJob::ReportFailureOnClientThread( +void PackExtensionJob::ReportFailureOnClientSequence( const std::string& error, ExtensionCreator::ErrorType error_type) { - if (client_) - client_->OnPackFailure(error, error_type); + DCHECK(client_); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + client_->OnPackFailure(error, error_type); } // static
diff --git a/chrome/browser/extensions/pack_extension_job.h b/chrome/browser/extensions/pack_extension_job.h index 7d663b0f..62fdc254 100644 --- a/chrome/browser/extensions/pack_extension_job.h +++ b/chrome/browser/extensions/pack_extension_job.h
@@ -9,16 +9,20 @@ #include "base/files/file_path.h" #include "base/macros.h" -#include "base/memory/ref_counted.h" +#include "base/memory/ptr_util.h" +#include "base/sequenced_task_runner.h" #include "base/strings/string16.h" #include "chrome/browser/extensions/extension_creator.h" -#include "content/public/browser/browser_thread.h" namespace extensions { // Manages packing an extension on the file thread and reporting the result // back to the UI. -class PackExtensionJob : public base::RefCountedThreadSafe<PackExtensionJob> { +// Ownership note: In "asynchronous" mode, |Client| has to make sure this +// class's instances are kept alive until OnPackSuccess|OnPackFailure is called. +// Therefore this class assumes that posting task with base::Unretained(this) +// is safe. +class PackExtensionJob { public: // Interface for people who want to use PackExtensionJob to implement. class Client { @@ -36,41 +40,38 @@ const base::FilePath& root_directory, const base::FilePath& key_file, int run_flags); + ~PackExtensionJob(); // Starts the packing job. void Start(); - // The client should call this when it is destroyed to prevent - // PackExtensionJob from attempting to access it. - void ClearClient(); - // The standard packing success message. static base::string16 StandardSuccessMessage(const base::FilePath& crx_file, const base::FilePath& key_file); - void set_asynchronous(bool async) { asynchronous_ = async; } + void set_synchronous() { run_mode_ = RunMode::SYNCHRONOUS; } private: - friend class base::RefCountedThreadSafe<PackExtensionJob>; + enum class RunMode { SYNCHRONOUS, ASYNCHRONOUS }; - virtual ~PackExtensionJob(); + // If |run_mode_| is SYNCHRONOUS, this is run on whichever thread calls it. + void Run(scoped_refptr<base::SequencedTaskRunner> async_reply_task_runner); + void ReportSuccessOnClientSequence( + std::unique_ptr<base::FilePath> crx_file_out, + std::unique_ptr<base::FilePath> key_file_out); + void ReportFailureOnClientSequence(const std::string& error, + ExtensionCreator::ErrorType error_type); - // If |asynchronous_| is false, this is run on whichever thread calls it. - void Run(); - void ReportSuccessOnClientThread(); - void ReportFailureOnClientThread(const std::string& error, - ExtensionCreator::ErrorType error_type); - - content::BrowserThread::ID client_thread_id_; - Client* client_; + Client* const client_; // Owns us. base::FilePath root_directory_; base::FilePath key_file_; - base::FilePath crx_file_out_; - base::FilePath key_file_out_; - bool asynchronous_; + RunMode run_mode_ = RunMode::ASYNCHRONOUS; int run_flags_; // Bitset of ExtensionCreator::RunFlags values - we always // assume kRequireModernManifestVersion, though. + // Used to check methods that run on |client_|'s sequence. + SEQUENCE_CHECKER(sequence_checker_); + DISALLOW_COPY_AND_ASSIGN(PackExtensionJob); };
diff --git a/chrome/browser/extensions/startup_helper.cc b/chrome/browser/extensions/startup_helper.cc index fef26b7..4bfaaa1 100644 --- a/chrome/browser/extensions/startup_helper.cc +++ b/chrome/browser/extensions/startup_helper.cc
@@ -62,12 +62,12 @@ private_key_path = cmd_line.GetSwitchValuePath(switches::kPackExtensionKey); } - // Launch a job to perform the packing on the file thread. Ignore warnings - // from the packing process. (e.g. Overwrite any existing crx file.) - pack_job_ = new PackExtensionJob(this, src_dir, private_key_path, - ExtensionCreator::kOverwriteCRX); - pack_job_->set_asynchronous(false); - pack_job_->Start(); + // Launch a job to perform the packing on the blocking thread. Ignore + // warnings from the packing process. (e.g. Overwrite any existing crx file.) + PackExtensionJob pack_job(this, src_dir, private_key_path, + ExtensionCreator::kOverwriteCRX); + pack_job.set_synchronous(); + pack_job.Start(); return pack_job_succeeded_; } @@ -186,9 +186,6 @@ return success; } -StartupHelper::~StartupHelper() { - if (pack_job_.get()) - pack_job_->ClearClient(); -} +StartupHelper::~StartupHelper() {} } // namespace extensions
diff --git a/chrome/browser/extensions/startup_helper.h b/chrome/browser/extensions/startup_helper.h index 43a0d2e..f1f8e37 100644 --- a/chrome/browser/extensions/startup_helper.h +++ b/chrome/browser/extensions/startup_helper.h
@@ -37,7 +37,6 @@ bool ValidateCrx(const base::CommandLine& cmd_line, std::string* error); private: - scoped_refptr<PackExtensionJob> pack_job_; bool pack_job_succeeded_; DISALLOW_COPY_AND_ASSIGN(StartupHelper);
diff --git a/chrome/browser/feature_engagement/feature_tracker.cc b/chrome/browser/feature_engagement/feature_tracker.cc new file mode 100644 index 0000000..f98a607 --- /dev/null +++ b/chrome/browser/feature_engagement/feature_tracker.cc
@@ -0,0 +1,54 @@ +// 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 "chrome/browser/feature_engagement/feature_tracker.h" + +#include "base/time/time.h" +#include "chrome/browser/feature_engagement/tracker_factory.h" +#include "components/feature_engagement/public/event_constants.h" +#include "components/feature_engagement/public/feature_constants.h" +#include "components/feature_engagement/public/tracker.h" + +namespace feature_engagement { + +FeatureTracker::FeatureTracker(Profile* profile, + SessionDurationUpdater* session_duration_updater) + : profile_(profile), + session_duration_updater_(session_duration_updater), + session_duration_observer_(this) { + AddSessionDurationObserver(); +} + +FeatureTracker::~FeatureTracker() = default; + +void FeatureTracker::AddSessionDurationObserver() { + session_duration_observer_.Add(session_duration_updater_); +} + +void FeatureTracker::RemoveSessionDurationObserver() { + session_duration_observer_.Remove(session_duration_updater_); +} + +bool FeatureTracker::IsObserving() { + return session_duration_observer_.IsObserving(session_duration_updater_); +} + +Tracker* FeatureTracker::GetTracker() const { + return TrackerFactory::GetForBrowserContext(profile_); +} + +void FeatureTracker::OnSessionEnded(base::TimeDelta total_session_time) { + if (HasEnoughSessionTimeElapsed(total_session_time)) { + OnSessionTimeMet(); + RemoveSessionDurationObserver(); + } +} + +bool FeatureTracker::HasEnoughSessionTimeElapsed( + base::TimeDelta total_session_time) { + return total_session_time.InMinutes() >= + GetSessionTimeRequiredToShowInMinutes(); +} + +} // namespace feature_engagement
diff --git a/chrome/browser/feature_engagement/feature_tracker.h b/chrome/browser/feature_engagement/feature_tracker.h new file mode 100644 index 0000000..295f8c3 --- /dev/null +++ b/chrome/browser/feature_engagement/feature_tracker.h
@@ -0,0 +1,81 @@ +// 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 CHROME_BROWSER_FEATURE_ENGAGEMENT_FEATURE_TRACKER_H_ +#define CHROME_BROWSER_FEATURE_ENGAGEMENT_FEATURE_TRACKER_H_ + +#include "base/scoped_observer.h" +#include "chrome/browser/feature_engagement/session_duration_updater.h" +#include "chrome/browser/profiles/profile.h" +#include "components/keyed_service/core/keyed_service.h" + +namespace feature_engagement { + +class Tracker; + +// The rFeatureTracker provides a backend for displaying in-product help for the +// various features by collecting all common funcitonality. All subclasses of +// FeatureTracker's factories depend on +// SessionDurationUpdaterFactory::GetInstance() as SessionDurationUpdater is +// responsible for letting all FeatureTrackers know how much active session time +// has passed. +// +// SessionDurationUpdater keeps track of the observed session time and, upon +// each session ending, updates all of the FeatureTrackers with the new total +// observed session time. Once the observed session time exceeds the time +// requirement provided by GetSessionTimeRequiredToShowInMinutes(), the +// FeatureTracker unregisters itself as an obsever of SessionDurationUpdater. +// SessionDurationUpdater stops updating the observed session time if no +// features are observing it, and will start tracking the observed sesion time +// again if another feature is added as an observer later. +class FeatureTracker : public SessionDurationUpdater::Observer, + public KeyedService { + public: + FeatureTracker(Profile* profile, + SessionDurationUpdater* session_duration_updater); + + // Adds the SessionDurationUpdater observer. + void AddSessionDurationObserver(); + // Removes the SessionDurationUpdater observer. + void RemoveSessionDurationObserver(); + + // Returns the whether |session_duration_observer_| is observing sources for + // testing purposes. + bool IsObserving(); + + // SessionDurationUpdater::Observer: + void OnSessionEnded(base::TimeDelta total_session_time) override; + + protected: + ~FeatureTracker() override; + // Returns the required session time in minutes for the FeatureTracker's + // subclass to show its promo. + virtual int GetSessionTimeRequiredToShowInMinutes() = 0; + // Alerts the feature tracker that the session time is up. + virtual void OnSessionTimeMet() = 0; + // Returns the Tracker associated with this FeatureTracker. + virtual Tracker* GetTracker() const; + + private: + // Returns whether the active session time of a user has elapsed more than the + // required active session time for the feature. + bool HasEnoughSessionTimeElapsed(base::TimeDelta total_session_time); + + // Owned by the ProfileManager. + Profile* const profile_; + + // Singleton instance of KeyedService. + SessionDurationUpdater* const session_duration_updater_; + + // Observes the SessionDurationUpdater and notifies when a desktop session + // starts and ends. + ScopedObserver<SessionDurationUpdater, SessionDurationUpdater::Observer> + session_duration_observer_; + + DISALLOW_COPY_AND_ASSIGN(FeatureTracker); +}; + +} // namespace feature_engagement + +#endif // CHROME_BROWSER_FEATURE_ENGAGEMENT_FEATURE_TRACKER_H_
diff --git a/chrome/browser/feature_engagement/feature_tracker_unittest.cc b/chrome/browser/feature_engagement/feature_tracker_unittest.cc new file mode 100644 index 0000000..85ef03d --- /dev/null +++ b/chrome/browser/feature_engagement/feature_tracker_unittest.cc
@@ -0,0 +1,131 @@ +// 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 "chrome/browser/feature_engagement/feature_tracker.h" + +#include "base/feature_list.h" +#include "base/metrics/field_trial.h" +#include "base/metrics/field_trial_param_associator.h" +#include "base/metrics/field_trial_params.h" +#include "base/run_loop.h" +#include "base/sequenced_task_runner.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/feature_engagement/session_duration_updater.h" +#include "chrome/browser/feature_engagement/session_duration_updater_factory.h" +#include "chrome/browser/metrics/desktop_session_duration/desktop_session_duration_tracker.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "components/feature_engagement/public/event_constants.h" +#include "components/feature_engagement/public/feature_constants.h" +#include "components/sync_preferences/testing_pref_service_syncable.h" +#include "components/variations/variations_params_manager.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace feature_engagement { + +namespace { + +const int kTestTimeInMinutes = 100; +const int kTestTimeSufficentInMinutes = 110; +const int kTestTimeInsufficientInMinutes = 90; +const char kTestProfileName[] = "test-profile"; + +class TestFeatureTracker : public FeatureTracker { + public: + explicit TestFeatureTracker(Profile* profile) + : FeatureTracker( + profile, + feature_engagement::SessionDurationUpdaterFactory::GetInstance() + ->GetForProfile(profile)), + pref_service_( + base::MakeUnique<sync_preferences::TestingPrefServiceSyncable>()) { + SessionDurationUpdater::RegisterProfilePrefs(pref_service_->registry()); + } + + int GetSessionTimeRequiredToShowInMinutes() override { + return kTestTimeInMinutes; + } + + void OnSessionTimeMet() override {} + + private: + const std::unique_ptr<sync_preferences::TestingPrefServiceSyncable> + pref_service_; +}; + +class MockTestFeatureTracker : public TestFeatureTracker { + public: + explicit MockTestFeatureTracker(Profile* profile) + : TestFeatureTracker(profile) {} + MOCK_METHOD0(OnSessionTimeMet, void()); +}; + +class FeatureTrackerTest : public testing::Test { + public: + FeatureTrackerTest() = default; + ~FeatureTrackerTest() override = default; + + // testing::Test: + void SetUp() override { + // Start the DesktopSessionDurationTracker to track active session time. + metrics::DesktopSessionDurationTracker::Initialize(); + testing_profile_manager_ = base::MakeUnique<TestingProfileManager>( + TestingBrowserProcess::GetGlobal()); + ASSERT_TRUE(testing_profile_manager_->SetUp()); + mock_feature_tracker_ = + base::MakeUnique<testing::StrictMock<MockTestFeatureTracker>>( + testing_profile_manager_->CreateTestingProfile(kTestProfileName)); + } + + void TearDown() override { + metrics::DesktopSessionDurationTracker::CleanupForTesting(); + testing_profile_manager_.reset(); + } + + protected: + std::unique_ptr<TestingProfileManager> testing_profile_manager_; + std::unique_ptr<MockTestFeatureTracker> mock_feature_tracker_; + + private: + content::TestBrowserThreadBundle thread_bundle_; + + DISALLOW_COPY_AND_ASSIGN(FeatureTrackerTest); +}; + +// If OnSessionEnded parameter is greater than HasEnoughSessionTimeElapsed +// then OnSessionTimeMet should be called. +// +// Note: in this case, RemoveSessionDurationObserver is called inside of +// OnSessionTimeMet, so it doesn't need to be called after the fact. +TEST_F(FeatureTrackerTest, TestExpectOnSessionTimeMet) { + EXPECT_CALL(*mock_feature_tracker_, OnSessionTimeMet()); + mock_feature_tracker_.get()->OnSessionEnded( + base::TimeDelta::FromMinutes(kTestTimeSufficentInMinutes)); +} + +// If OnSessionEnded parameter is less than than HasEnoughSessionTimeElapsed +// then OnSessionTimeMet should not be called. +TEST_F(FeatureTrackerTest, TestDontExpectOnSessionTimeMet) { + mock_feature_tracker_.get()->OnSessionEnded( + base::TimeDelta::FromMinutes(kTestTimeInsufficientInMinutes)); + mock_feature_tracker_.get()->RemoveSessionDurationObserver(); +} + +// The FeatureTracker should be observing sources until the +// RemoveSessionDurationObserver is called. +TEST_F(FeatureTrackerTest, TestAddAndRemoveObservers) { + // AddSessionDurationObserver is called on initialization. + ASSERT_TRUE(mock_feature_tracker_->IsObserving()); + + mock_feature_tracker_.get()->RemoveSessionDurationObserver(); + + EXPECT_FALSE(mock_feature_tracker_->IsObserving()); +} + +} // namespace + +} // namespace feature_engagement
diff --git a/chrome/browser/feature_engagement/new_tab/new_tab_tracker.cc b/chrome/browser/feature_engagement/new_tab/new_tab_tracker.cc index e735dde..fc57d4f0 100644 --- a/chrome/browser/feature_engagement/new_tab/new_tab_tracker.cc +++ b/chrome/browser/feature_engagement/new_tab/new_tab_tracker.cc
@@ -14,8 +14,6 @@ #include "components/feature_engagement/public/event_constants.h" #include "components/feature_engagement/public/feature_constants.h" #include "components/feature_engagement/public/tracker.h" -#include "components/pref_registry/pref_registry_syncable.h" -#include "components/prefs/pref_service.h" namespace { @@ -25,31 +23,21 @@ namespace feature_engagement { -NewTabTracker::NewTabTracker(Profile* profile) - : profile_(profile), duration_tracker_observer_(this) { - AddDurationTrackerObserver(); -} +NewTabTracker::NewTabTracker(Profile* profile, + SessionDurationUpdater* session_duration_updater) + : FeatureTracker(profile, session_duration_updater) {} -NewTabTracker::NewTabTracker() : NewTabTracker(nullptr) {} +NewTabTracker::NewTabTracker(SessionDurationUpdater* session_duration_updater) + : NewTabTracker(nullptr, session_duration_updater) {} NewTabTracker::~NewTabTracker() = default; -// static -void NewTabTracker::RegisterProfilePrefs( - user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterIntegerPref(prefs::kSessionTimeTotal, 0); -} - void NewTabTracker::OnNewTabOpened() { - GetFeatureTracker()->NotifyEvent(events::kNewTabOpened); + GetTracker()->NotifyEvent(events::kNewTabOpened); } void NewTabTracker::OnOmniboxNavigation() { - GetFeatureTracker()->NotifyEvent(events::kOmniboxInteraction); -} - -void NewTabTracker::OnSessionTimeMet() { - GetFeatureTracker()->NotifyEvent(events::kSessionTime); + GetTracker()->NotifyEvent(events::kOmniboxInteraction); } void NewTabTracker::OnOmniboxFocused() { @@ -58,61 +46,23 @@ } void NewTabTracker::OnPromoClosed() { - GetFeatureTracker()->Dismissed(kIPHNewTabFeature); + GetTracker()->Dismissed(kIPHNewTabFeature); } bool NewTabTracker::ShouldShowPromo() { - return GetFeatureTracker()->ShouldTriggerHelpUI(kIPHNewTabFeature); + return GetTracker()->ShouldTriggerHelpUI(kIPHNewTabFeature); } -void NewTabTracker::AddDurationTrackerObserver() { - duration_tracker_observer_.Add(metrics::DesktopSessionDurationTracker::Get()); +void NewTabTracker::OnSessionTimeMet() { + GetTracker()->NotifyEvent(events::kNewTabSessionTimeMet); } -void NewTabTracker::RemoveDurationTrackerObserver() { - duration_tracker_observer_.Remove( - metrics::DesktopSessionDurationTracker::Get()); -} - -bool NewTabTracker::HasEnoughSessionTimeElapsed() { - return GetPrefs()->GetInteger(prefs::kSessionTimeTotal) >= kTwoHoursInMinutes; +int NewTabTracker::GetSessionTimeRequiredToShowInMinutes() { + return kTwoHoursInMinutes; } void NewTabTracker::ShowPromo() { NewTabButton::ShowPromoForLastActiveBrowser(); } -Tracker* NewTabTracker::GetFeatureTracker() { - return TrackerFactory::GetForBrowserContext(profile_); -} - -PrefService* NewTabTracker::GetPrefs() { - return profile_->GetPrefs(); -} - -void NewTabTracker::UpdateSessionTime(base::TimeDelta elapsed) { - // Session time does not need to be tracked anymore if the - // in-product help has been shown already. - // This prevents unnecessary interaction with prefs. - if (GetFeatureTracker()->GetTriggerState(kIPHNewTabFeature) == - Tracker::TriggerState::HAS_BEEN_DISPLAYED) { - return; - } - - base::TimeDelta elapsed_session_time; - elapsed_session_time += base::TimeDelta::FromMinutes(GetPrefs()->GetInteger( - prefs::kSessionTimeTotal)) + - elapsed; - GetPrefs()->SetInteger(prefs::kSessionTimeTotal, - elapsed_session_time.InMinutes()); -} - -void NewTabTracker::OnSessionEnded(base::TimeDelta delta) { - UpdateSessionTime(delta); - if (HasEnoughSessionTimeElapsed()) { - OnSessionTimeMet(); - RemoveDurationTrackerObserver(); - } -} - } // namespace feature_engagement
diff --git a/chrome/browser/feature_engagement/new_tab/new_tab_tracker.h b/chrome/browser/feature_engagement/new_tab/new_tab_tracker.h index 5cb02f8..19d8f7cc 100644 --- a/chrome/browser/feature_engagement/new_tab/new_tab_tracker.h +++ b/chrome/browser/feature_engagement/new_tab/new_tab_tracker.h
@@ -5,33 +5,34 @@ #ifndef CHROME_BROWSER_FEATURE_ENGAGEMENT_NEW_TAB_NEW_TAB_TRACKER_H_ #define CHROME_BROWSER_FEATURE_ENGAGEMENT_NEW_TAB_NEW_TAB_TRACKER_H_ -#include "base/scoped_observer.h" -#include "chrome/browser/metrics/desktop_session_duration/desktop_session_duration_tracker.h" -#include "chrome/browser/profiles/profile.h" -#include "components/feature_engagement/public/tracker.h" -#include "components/keyed_service/core/keyed_service.h" +#include "chrome/browser/feature_engagement/feature_tracker.h" -namespace user_prefs { -class PrefRegistrySyncable; -} // namespace user_prefs +#include "chrome/browser/feature_engagement/session_duration_updater.h" +#include "chrome/browser/feature_engagement/session_duration_updater_factory.h" namespace feature_engagement { -// The NewTabTracker provides a backend for displaying -// in-product help for the new tab button. -class NewTabTracker : public metrics::DesktopSessionDurationTracker::Observer, - public KeyedService { +// The NewTabTracker provides a backend for displaying in-product help for the +// new tab button. NewTabTracker is the interface through which the event +// constants for the NewTab feature can be be altered. Once all of the event +// constants are met, NewTabTracker calls for the NewTabPromo to be shown, along +// with recording when the NewTabPromo is dimissed. The requirements to show +// the NewTabPromo are as follows: +// +// - At least two hours of observed session time have elapsed. +// - The user has never opened another tab through any means. +// - The user has navigated away from the start home screen. +// - The omnibox is in focus, which implies the user is intending on navigating +// to a new page. +class NewTabTracker : public FeatureTracker { public: - explicit NewTabTracker(Profile* profile); - - static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); + NewTabTracker(Profile* profile, + SessionDurationUpdater* session_duration_updater); // Alerts the new tab tracker that a new tab was opened. void OnNewTabOpened(); // Alerts the new tab tracker that the omnibox has been used. void OnOmniboxNavigation(); - // Alerts the new tab tracker that the session time is up. - void OnSessionTimeMet(); // Checks if the promo should be displayed since the omnibox is on focus. void OnOmniboxFocused(); // Clears the flag for whether there is any in-product help being displayed. @@ -39,44 +40,24 @@ // Returns whether or not the promo should be displayed. bool ShouldShowPromo(); - // Adding the DesktopSessionDurationTracker observer. - void AddDurationTrackerObserver(); - // Removing the DesktopSessionDurationTracker observer. - void RemoveDurationTrackerObserver(); - protected: - NewTabTracker(); + // Alternate constructor to support unit testing. + explicit NewTabTracker(SessionDurationUpdater* session_duration_updater); ~NewTabTracker() override; private: - // Returns whether the active session time of a user has elapsed - // more than two hours. - bool HasEnoughSessionTimeElapsed(); + FRIEND_TEST_ALL_PREFIXES(NewTabTrackerEventTest, TestOnSessionTimeMet); + FRIEND_TEST_ALL_PREFIXES(NewTabTrackerTest, TestShouldNotShowPromo); + FRIEND_TEST_ALL_PREFIXES(NewTabTrackerTest, TestShouldShowPromo); + FRIEND_TEST_ALL_PREFIXES(NewTabTrackerBrowserTest, TestShowPromo); + + // FeatureTracker: + int GetSessionTimeRequiredToShowInMinutes() override; + void OnSessionTimeMet() override; // Sets the NewTabInProductHelp pref to true and calls the New Tab Promo. void ShowPromo(); - // Virtual to support mocking by unit tests. - virtual Tracker* GetFeatureTracker(); - - virtual PrefService* GetPrefs(); - - // Updates the pref that stores active session time per user unless the - // new tab in-product help has been displayed already. - void UpdateSessionTime(base::TimeDelta elapsed); - - // metrics::DesktopSessionDurationTracker::Observer:: - void OnSessionEnded(base::TimeDelta delta) override; - - // Owned by ProfileManager. - Profile* const profile_; - - // Observes the DesktopSessionDurationTracker and notifies when a desktop - // session starts and ends. - ScopedObserver<metrics::DesktopSessionDurationTracker, - metrics::DesktopSessionDurationTracker::Observer> - duration_tracker_observer_; - DISALLOW_COPY_AND_ASSIGN(NewTabTracker); };
diff --git a/chrome/browser/feature_engagement/new_tab/new_tab_tracker_browsertest.cc b/chrome/browser/feature_engagement/new_tab/new_tab_tracker_browsertest.cc index 9c638fb..ca4c502 100644 --- a/chrome/browser/feature_engagement/new_tab/new_tab_tracker_browsertest.cc +++ b/chrome/browser/feature_engagement/new_tab/new_tab_tracker_browsertest.cc
@@ -89,7 +89,8 @@ IN_PROC_BROWSER_TEST_F(NewTabTrackerBrowserTest, TestShowPromo) { // Bypassing the 2 hour active session time requirement. - EXPECT_CALL(*feature_engagement_tracker_, NotifyEvent(events::kSessionTime)); + EXPECT_CALL(*feature_engagement_tracker_, + NotifyEvent(events::kNewTabSessionTimeMet)); NewTabTrackerFactory::GetInstance() ->GetForProfile(browser()->profile()) ->OnSessionTimeMet();
diff --git a/chrome/browser/feature_engagement/new_tab/new_tab_tracker_factory.cc b/chrome/browser/feature_engagement/new_tab/new_tab_tracker_factory.cc index 91f85ea..1f48ca5 100644 --- a/chrome/browser/feature_engagement/new_tab/new_tab_tracker_factory.cc +++ b/chrome/browser/feature_engagement/new_tab/new_tab_tracker_factory.cc
@@ -6,6 +6,8 @@ #include "base/memory/singleton.h" #include "chrome/browser/feature_engagement/new_tab/new_tab_tracker.h" +#include "chrome/browser/feature_engagement/session_duration_updater.h" +#include "chrome/browser/feature_engagement/session_duration_updater_factory.h" #include "chrome/browser/feature_engagement/tracker_factory.h" #include "chrome/browser/profiles/incognito_helpers.h" #include "chrome/browser/profiles/profile.h" @@ -28,6 +30,7 @@ : BrowserContextKeyedServiceFactory( "NewTabTracker", BrowserContextDependencyManager::GetInstance()) { + DependsOn(SessionDurationUpdaterFactory::GetInstance()); DependsOn(TrackerFactory::GetInstance()); } @@ -35,7 +38,10 @@ KeyedService* NewTabTrackerFactory::BuildServiceInstanceFor( content::BrowserContext* context) const { - return new NewTabTracker(Profile::FromBrowserContext(context)); + return new NewTabTracker( + Profile::FromBrowserContext(context), + feature_engagement::SessionDurationUpdaterFactory::GetInstance() + ->GetForProfile(Profile::FromBrowserContext(context))); } content::BrowserContext* NewTabTrackerFactory::GetBrowserContextToUse(
diff --git a/chrome/browser/feature_engagement/new_tab/new_tab_tracker_unittest.cc b/chrome/browser/feature_engagement/new_tab/new_tab_tracker_unittest.cc index d5e12872..c838edf 100644 --- a/chrome/browser/feature_engagement/new_tab/new_tab_tracker_unittest.cc +++ b/chrome/browser/feature_engagement/new_tab/new_tab_tracker_unittest.cc
@@ -11,8 +11,14 @@ #include "base/run_loop.h" #include "base/sequenced_task_runner.h" #include "base/test/scoped_feature_list.h" +#include "chrome/browser/feature_engagement/feature_tracker.h" +#include "chrome/browser/feature_engagement/session_duration_updater.h" +#include "chrome/browser/feature_engagement/session_duration_updater_factory.h" #include "chrome/browser/metrics/desktop_session_duration/desktop_session_duration_tracker.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/common/pref_names.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile_manager.h" #include "components/feature_engagement/public/event_constants.h" #include "components/feature_engagement/public/feature_constants.h" #include "components/feature_engagement/public/tracker.h" @@ -29,6 +35,7 @@ const char kGroupName[] = "Enabled"; const char kNewTabTrialName[] = "NewTabTrial"; +const char kTestProfileName[] = "test-profile"; class MockTracker : public Tracker { public: @@ -44,17 +51,20 @@ class FakeNewTabTracker : public NewTabTracker { public: - explicit FakeNewTabTracker(Tracker* feature_tracker) - : feature_tracker_(feature_tracker), + FakeNewTabTracker(Tracker* feature_tracker, Profile* profile) + : NewTabTracker( + feature_engagement::SessionDurationUpdaterFactory::GetInstance() + ->GetForProfile(profile)), + feature_tracker_(feature_tracker), pref_service_( base::MakeUnique<sync_preferences::TestingPrefServiceSyncable>()) { - NewTabTracker::RegisterProfilePrefs(pref_service_->registry()); + SessionDurationUpdater::RegisterProfilePrefs(pref_service_->registry()); } - // feature_engagement::NewTabTracker:: - Tracker* GetFeatureTracker() override { return feature_tracker_; } + PrefService* GetPrefs() { return pref_service_.get(); } - PrefService* GetPrefs() override { return pref_service_.get(); } + // feature_engagement::NewTabTracker: + Tracker* GetTracker() const override { return feature_tracker_; } private: Tracker* const feature_tracker_; @@ -71,18 +81,25 @@ void SetUp() override { // Start the DesktopSessionDurationTracker to track active session time. metrics::DesktopSessionDurationTracker::Initialize(); + testing_profile_manager_ = base::MakeUnique<TestingProfileManager>( + TestingBrowserProcess::GetGlobal()); + ASSERT_TRUE(testing_profile_manager_->SetUp()); mock_tracker_ = base::MakeUnique<testing::StrictMock<MockTracker>>(); - new_tab_tracker_ = base::MakeUnique<FakeNewTabTracker>(mock_tracker_.get()); + new_tab_tracker_ = base::MakeUnique<FakeNewTabTracker>( + mock_tracker_.get(), + testing_profile_manager_->CreateTestingProfile(kTestProfileName)); } void TearDown() override { - new_tab_tracker_->RemoveDurationTrackerObserver(); + new_tab_tracker_->RemoveSessionDurationObserver(); metrics::DesktopSessionDurationTracker::CleanupForTesting(); + testing_profile_manager_.reset(); } protected: - std::unique_ptr<FakeNewTabTracker> new_tab_tracker_; + std::unique_ptr<TestingProfileManager> testing_profile_manager_; std::unique_ptr<MockTracker> mock_tracker_; + std::unique_ptr<FakeNewTabTracker> new_tab_tracker_; private: content::TestBrowserThreadBundle thread_bundle_; @@ -111,7 +128,7 @@ // If OnSessionTimeMet() is called, the feature_engagement::Tracker // receives the kSessionTime event. TEST_F(NewTabTrackerEventTest, TestOnSessionTimeMet) { - EXPECT_CALL(*mock_tracker_, NotifyEvent(events::kSessionTime)); + EXPECT_CALL(*mock_tracker_, NotifyEvent(events::kNewTabSessionTimeMet)); new_tab_tracker_->OnSessionTimeMet(); } @@ -144,8 +161,8 @@ "name:new_tab_opened;comparator:==0;window:3650;storage:3650"; new_tab_params["event_omnibox_used"] = "name:omnibox_used;comparator:>=1;window:3650;storage:3650"; - new_tab_params["event_session_time"] = - "name:session_time;comparator:>=1;window:3650;storage:3650"; + new_tab_params["event_new_tab_session_time_met"] = + "name:new_tab_session_time_met;comparator:>=1;window:3650;storage:3650"; new_tab_params["event_trigger"] = "name:new_tab_trigger;comparator:any;window:3650;storage:3650"; new_tab_params["event_used"] = @@ -158,10 +175,15 @@ // Start the DesktopSessionDurationTracker to track active session time. metrics::DesktopSessionDurationTracker::Initialize(); + testing_profile_manager_ = base::MakeUnique<TestingProfileManager>( + TestingBrowserProcess::GetGlobal()); + ASSERT_TRUE(testing_profile_manager_->SetUp()); + feature_engagement_tracker_ = CreateTestTracker(); - new_tab_tracker_ = - base::MakeUnique<FakeNewTabTracker>(feature_engagement_tracker_.get()); + new_tab_tracker_ = base::MakeUnique<FakeNewTabTracker>( + feature_engagement_tracker_.get(), + testing_profile_manager_->CreateTestingProfile(kTestProfileName)); // The feature engagement tracker does async initialization. base::RunLoop().RunUntilIdle(); @@ -169,7 +191,8 @@ } void TearDown() override { - new_tab_tracker_->RemoveDurationTrackerObserver(); + new_tab_tracker_->RemoveSessionDurationObserver(); + testing_profile_manager_->DeleteTestingProfile(kTestProfileName); metrics::DesktopSessionDurationTracker::CleanupForTesting(); // This is required to ensure each test can define its own params. @@ -194,6 +217,7 @@ variations::testing::VariationParamsManager params_manager_; private: + std::unique_ptr<TestingProfileManager> testing_profile_manager_; base::test::ScopedFeatureList scoped_feature_list_; content::TestBrowserThreadBundle thread_bundle_; std::map<std::string, base::FieldTrial*> trials_; @@ -232,22 +256,4 @@ EXPECT_TRUE(new_tab_tracker_->ShouldShowPromo()); } -// Test that the correct duration of session is being recorded. -TEST_F(NewTabTrackerTest, TestOnSessionEnded) { - metrics::DesktopSessionDurationTracker::Observer* observer = - dynamic_cast<FakeNewTabTracker*>(new_tab_tracker_.get()); - - // Simulate passing 30 active minutes. - observer->OnSessionEnded(base::TimeDelta::FromMinutes(30)); - - EXPECT_EQ(30, - new_tab_tracker_->GetPrefs()->GetInteger(prefs::kSessionTimeTotal)); - - // Simulate passing 50 minutes. - observer->OnSessionEnded(base::TimeDelta::FromMinutes(50)); - - EXPECT_EQ(80, - new_tab_tracker_->GetPrefs()->GetInteger(prefs::kSessionTimeTotal)); -} - } // namespace feature_engagement
diff --git a/chrome/browser/feature_engagement/session_duration_updater.cc b/chrome/browser/feature_engagement/session_duration_updater.cc new file mode 100644 index 0000000..46468ac --- /dev/null +++ b/chrome/browser/feature_engagement/session_duration_updater.cc
@@ -0,0 +1,85 @@ +// 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 "chrome/browser/feature_engagement/session_duration_updater.h" + +#include "base/observer_list.h" +#include "base/time/time.h" +#include "chrome/browser/feature_engagement/tracker_factory.h" +#include "chrome/common/pref_names.h" +#include "components/feature_engagement/public/event_constants.h" +#include "components/feature_engagement/public/feature_constants.h" +#include "components/pref_registry/pref_registry_syncable.h" +#include "components/prefs/pref_service.h" + +namespace feature_engagement { + +SessionDurationUpdater::SessionDurationUpdater(PrefService* pref_service) + : duration_tracker_observer_(this), pref_service_(pref_service) { + AddDurationTrackerObserver(); +} + +SessionDurationUpdater::~SessionDurationUpdater() = default; + +// static +void SessionDurationUpdater::RegisterProfilePrefs( + user_prefs::PrefRegistrySyncable* registry) { + registry->RegisterIntegerPref(prefs::kObservedSessionTime, 0); +} + +void SessionDurationUpdater::AddObserver(Observer* observer) { + observer_list_.AddObserver(observer); + + // Re-adds SessionDurationUpdater as an observer of + // DesktopSessionDurationTracker if another feature is added after + // SessionDurationUpdater was removed. + if (!duration_tracker_observer_.IsObserving( + metrics::DesktopSessionDurationTracker::Get())) + AddDurationTrackerObserver(); +} + +void SessionDurationUpdater::RemoveObserver(Observer* observer) { + observer_list_.RemoveObserver(observer); + // If all the observer Features have removed themselves due to their active + // time limits have been reached, the SessionDurationUpdater removes itself + // as an observer of DesktopSessionDurationTracker. + if (!observer_list_.might_have_observers()) + RemoveDurationTrackerObserver(); +} + +void SessionDurationUpdater::OnSessionEnded(base::TimeDelta elapsed) { + // This case is only used during testing as that is the only case that + // DesktopSessionDurationTracker isn't calling this on its observer. + if (!duration_tracker_observer_.IsObserving( + metrics::DesktopSessionDurationTracker::Get())) { + return; + } + + base::TimeDelta elapsed_session_time; + + elapsed_session_time += + base::TimeDelta::FromMinutes( + pref_service_->GetInteger(prefs::kObservedSessionTime)) + + elapsed; + pref_service_->SetInteger(prefs::kObservedSessionTime, + elapsed_session_time.InMinutes()); + + for (Observer& observer : observer_list_) + observer.OnSessionEnded(elapsed_session_time); +} + +void SessionDurationUpdater::AddDurationTrackerObserver() { + duration_tracker_observer_.Add(metrics::DesktopSessionDurationTracker::Get()); +} + +void SessionDurationUpdater::RemoveDurationTrackerObserver() { + duration_tracker_observer_.Remove( + metrics::DesktopSessionDurationTracker::Get()); +} + +PrefService* SessionDurationUpdater::GetPrefs() { + return pref_service_; +} + +} // namespace feature_engagement
diff --git a/chrome/browser/feature_engagement/session_duration_updater.h b/chrome/browser/feature_engagement/session_duration_updater.h new file mode 100644 index 0000000..df41ac31 --- /dev/null +++ b/chrome/browser/feature_engagement/session_duration_updater.h
@@ -0,0 +1,87 @@ +// 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 CHROME_BROWSER_FEATURE_ENGAGEMENT_SESSION_DURATION_UPDATER_H_ +#define CHROME_BROWSER_FEATURE_ENGAGEMENT_SESSION_DURATION_UPDATER_H_ + +#include "base/scoped_observer.h" +#include "chrome/browser/metrics/desktop_session_duration/desktop_session_duration_tracker.h" +#include "components/keyed_service/core/keyed_service.h" +#include "components/prefs/pref_service.h" + +namespace user_prefs { +class PrefRegistrySyncable; +} // namespace user_prefs + +namespace feature_engagement { + +// The SessionDurationUpdater tracks the total amount of observed time across +// Chrome restarts. Observed time in this context is active session time that +// occurs while there is a FeatureTracker whose active session time requirement +// has not been satisfied. This allows subclasses of FeatureTracker to check how +// much active time has passed, and decide whether to show their respective +// promos accordingly. +// +// When an active session is closed, DesktopSessionDurationTracker calls +// OnSessionEnded and the observed time is incremented and persisted. Then, +// OnSessionEnded is called on all of Features observing SessionDurationUpdater. +// If the feature has its time limit exceeded, it should remove itself as an +// observer of SessionDurationUpdater. If SessionDurationUpdater has no +// observers, it means that the time limits of all the observing features has +// been exceeded, so the SessionDurationUpdater removes itself as an observer of +// DesktopSessionDurationTracker and stops updating observed session time. +// +// If all observers are removed, SessionDurationUpdater doesn't continue +// updating the observed session time. However, if another feature is added as +// an observer later, SessionDurationUpdater starts incrementing the observed +// session time again. + +class SessionDurationUpdater + : public metrics::DesktopSessionDurationTracker::Observer, + public KeyedService { + public: + // The methods for the observer will be called on the UI thread. + class Observer { + public: + virtual ~Observer() = default; + virtual void OnSessionEnded(base::TimeDelta total_session_time) = 0; + }; + + explicit SessionDurationUpdater(PrefService* pref_service); + ~SessionDurationUpdater() override; + + static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); + + // For observing the status of the session tracker. + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + + // metrics::DesktopSessionDurationtracker::Observer: + void OnSessionEnded(base::TimeDelta delta) override; + + private: + // Adds the DesktopSessionDurationTracker observer. + void AddDurationTrackerObserver(); + // Removes the DesktopSessionDurationTracker observer. + void RemoveDurationTrackerObserver(); + // Returns the pref service associated with this SessionDurationUpdater. + virtual PrefService* GetPrefs(); + + // Observes the DesktopSessionDurationTracker and notifies when a desktop + // session starts and ends. + ScopedObserver<metrics::DesktopSessionDurationTracker, + metrics::DesktopSessionDurationTracker::Observer> + duration_tracker_observer_; + + // Owned by Profile manager. + PrefService* const pref_service_; + + base::ObserverList<Observer> observer_list_; + + DISALLOW_COPY_AND_ASSIGN(SessionDurationUpdater); +}; + +} // namespace feature_engagement + +#endif // CHROME_BROWSER_FEATURE_ENGAGEMENT_SESSION_DURATION_UPDATER_H_
diff --git a/chrome/browser/feature_engagement/session_duration_updater_factory.cc b/chrome/browser/feature_engagement/session_duration_updater_factory.cc new file mode 100644 index 0000000..8e78ac8c --- /dev/null +++ b/chrome/browser/feature_engagement/session_duration_updater_factory.cc
@@ -0,0 +1,46 @@ +// 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 "chrome/browser/feature_engagement/session_duration_updater_factory.h" + +#include "base/memory/singleton.h" +#include "chrome/browser/feature_engagement/session_duration_updater.h" +#include "chrome/browser/feature_engagement/tracker_factory.h" +#include "chrome/browser/profiles/incognito_helpers.h" +#include "chrome/browser/profiles/profile.h" +#include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "content/public/browser/browser_context.h" + +namespace feature_engagement { + +// static +SessionDurationUpdaterFactory* SessionDurationUpdaterFactory::GetInstance() { + return base::Singleton<SessionDurationUpdaterFactory>::get(); +} + +SessionDurationUpdater* SessionDurationUpdaterFactory::GetForProfile( + Profile* profile) { + return static_cast<SessionDurationUpdater*>( + GetInstance()->GetServiceForBrowserContext(profile, true)); +} + +SessionDurationUpdaterFactory::SessionDurationUpdaterFactory() + : BrowserContextKeyedServiceFactory( + "SessionDurationUpdater", + BrowserContextDependencyManager::GetInstance()) {} + +SessionDurationUpdaterFactory::~SessionDurationUpdaterFactory() = default; + +KeyedService* SessionDurationUpdaterFactory::BuildServiceInstanceFor( + content::BrowserContext* context) const { + return new SessionDurationUpdater( + Profile::FromBrowserContext(context)->GetPrefs()); +} + +content::BrowserContext* SessionDurationUpdaterFactory::GetBrowserContextToUse( + content::BrowserContext* context) const { + return chrome::GetBrowserContextRedirectedInIncognito(context); +} + +} // namespace feature_engagement
diff --git a/chrome/browser/feature_engagement/session_duration_updater_factory.h b/chrome/browser/feature_engagement/session_duration_updater_factory.h new file mode 100644 index 0000000..55f1f2be --- /dev/null +++ b/chrome/browser/feature_engagement/session_duration_updater_factory.h
@@ -0,0 +1,53 @@ +// 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 CHROME_BROWSER_FEATURE_ENGAGEMENT_SESSION_DURATION_UPDATER_FACTORY_H_ +#define CHROME_BROWSER_FEATURE_ENGAGEMENT_SESSION_DURATION_UPDATER_FACTORY_H_ + +#include "base/macros.h" +#include "components/keyed_service/content/browser_context_keyed_service_factory.h" + +class Profile; + +namespace base { +template <typename T> +struct DefaultSingletonTraits; +} // namespace base + +namespace content { +class BrowserContext; +} // namespace content + +namespace feature_engagement { + +class SessionDurationUpdater; + +// SessionDurationUpdaterFactory is the main client class for interaction with +// the SessionDurationUpdater component. +class SessionDurationUpdaterFactory : public BrowserContextKeyedServiceFactory { + public: + // Returns singleton instance of SessionDurationUpdaterFactory. + static SessionDurationUpdaterFactory* GetInstance(); + + // Returns the SessionDurationUpdater associated with the profile. + SessionDurationUpdater* GetForProfile(Profile* profile); + + private: + friend struct base::DefaultSingletonTraits<SessionDurationUpdaterFactory>; + + SessionDurationUpdaterFactory(); + ~SessionDurationUpdaterFactory() override; + + // BrowserContextKeyedServiceFactory overrides: + KeyedService* BuildServiceInstanceFor( + content::BrowserContext* context) const override; + content::BrowserContext* GetBrowserContextToUse( + content::BrowserContext* context) const override; + + DISALLOW_COPY_AND_ASSIGN(SessionDurationUpdaterFactory); +}; + +} // namespace feature_engagement + +#endif // CHROME_BROWSER_FEATURE_ENGAGEMENT_SESSION_DURATION_UPDATER_FACTORY_H_
diff --git a/chrome/browser/feature_engagement/session_duration_updater_unittest.cc b/chrome/browser/feature_engagement/session_duration_updater_unittest.cc new file mode 100644 index 0000000..b0740cb5 --- /dev/null +++ b/chrome/browser/feature_engagement/session_duration_updater_unittest.cc
@@ -0,0 +1,146 @@ +// 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 "chrome/browser/feature_engagement/session_duration_updater.h" + +#include "base/feature_list.h" +#include "base/metrics/field_trial.h" +#include "base/metrics/field_trial_param_associator.h" +#include "base/metrics/field_trial_params.h" +#include "base/run_loop.h" +#include "base/sequenced_task_runner.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/feature_engagement/feature_tracker.h" +#include "chrome/browser/feature_engagement/session_duration_updater.h" +#include "chrome/browser/feature_engagement/session_duration_updater_factory.h" +#include "chrome/browser/metrics/desktop_session_duration/desktop_session_duration_tracker.h" +#include "chrome/common/pref_names.h" +#include "chrome/test/base/testing_browser_process.h" +#include "components/feature_engagement/public/event_constants.h" +#include "components/feature_engagement/public/feature_constants.h" +#include "components/feature_engagement/test/test_tracker.h" +#include "components/pref_registry/pref_registry_syncable.h" +#include "components/prefs/pref_service.h" +#include "components/sync_preferences/testing_pref_service_syncable.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace feature_engagement { + +namespace { + +class TestObserver : public SessionDurationUpdater::Observer { + public: + TestObserver() + : pref_service_( + base::MakeUnique<sync_preferences::TestingPrefServiceSyncable>()), + session_duration_updater_( + new SessionDurationUpdater(pref_service_.get())), + session_duration_observer_(this) { + SessionDurationUpdater::RegisterProfilePrefs(pref_service_->registry()); + } + + void AddSessionDurationObserver() { + session_duration_observer_.Add(session_duration_updater_.get()); + } + + void RemoveSessionDurationObserver() { + session_duration_observer_.Remove(session_duration_updater_.get()); + } + + // SessionDurationUpdater::Observer: + void OnSessionEnded(base::TimeDelta total_session_time) override {} + + PrefService* GetPrefs() { return pref_service_.get(); } + + SessionDurationUpdater* GetSessionDurationUpdater() { + return session_duration_updater_.get(); + } + + private: + const std::unique_ptr<sync_preferences::TestingPrefServiceSyncable> + pref_service_; + std::unique_ptr<SessionDurationUpdater> session_duration_updater_; + ScopedObserver<SessionDurationUpdater, SessionDurationUpdater::Observer> + session_duration_observer_; + + DISALLOW_COPY_AND_ASSIGN(TestObserver); +}; + +class SessionDurationUpdaterTest : public testing::Test { + public: + SessionDurationUpdaterTest() = default; + ~SessionDurationUpdaterTest() override = default; + + // testing::Test: + void SetUp() override { + // Start the DesktopSessionDurationTracker to track active session time. + metrics::DesktopSessionDurationTracker::Initialize(); + + test_observer_ = base::MakeUnique<TestObserver>(); + test_observer_->AddSessionDurationObserver(); + } + + void TearDown() override { + test_observer_->RemoveSessionDurationObserver(); + metrics::DesktopSessionDurationTracker::CleanupForTesting(); + } + + protected: + std::unique_ptr<TestObserver> test_observer_; + + private: + content::TestBrowserThreadBundle thread_bundle_; + + DISALLOW_COPY_AND_ASSIGN(SessionDurationUpdaterTest); +}; + +} // namespace + +// kObservedSessionTime should be 0 on initalization and 50 after simulation. +TEST_F(SessionDurationUpdaterTest, TestTimeAdded) { + // Tests the pref is registered to 0 before any session time passes. + EXPECT_EQ( + 0, test_observer_->GetPrefs()->GetInteger(prefs::kObservedSessionTime)); + + // Tests 50 minutes passing with an observer added. + test_observer_->GetSessionDurationUpdater()->OnSessionEnded( + base::TimeDelta::FromMinutes(50)); + + EXPECT_EQ( + 50, test_observer_->GetPrefs()->GetInteger(prefs::kObservedSessionTime)); +} + +// kObservedSessionTime should not be updated when SessionDurationUpdater has +// no observers, but should start updating again if another observer is added. +TEST_F(SessionDurationUpdaterTest, TestAddingAndRemovingObservers) { + // Tests 50 minutes passing with an observer added. + test_observer_->GetSessionDurationUpdater()->OnSessionEnded( + base::TimeDelta::FromMinutes(50)); + + EXPECT_EQ( + 50, test_observer_->GetPrefs()->GetInteger(prefs::kObservedSessionTime)); + + // Tests 50 minutes passing without any observers. No time should be added to + // the pref in this case. + test_observer_->RemoveSessionDurationObserver(); + + test_observer_->GetSessionDurationUpdater()->OnSessionEnded( + base::TimeDelta::FromMinutes(50)); + + EXPECT_EQ( + 50, test_observer_->GetPrefs()->GetInteger(prefs::kObservedSessionTime)); + + // Tests 50 minutes passing with an observer re-added. Time should be added + // again now. + test_observer_->AddSessionDurationObserver(); + + test_observer_->GetSessionDurationUpdater()->OnSessionEnded( + base::TimeDelta::FromMinutes(50)); + + EXPECT_EQ( + 100, test_observer_->GetPrefs()->GetInteger(prefs::kObservedSessionTime)); +} + +} // namespace feature_engagement
diff --git a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.cc b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.cc index 26cf335..20d322b 100644 --- a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.cc +++ b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.cc
@@ -171,8 +171,7 @@ void CastMediaSinkServiceImpl::OnDialSinkAdded(const MediaSinkInternal& sink) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - auto ip_address = sink.dial_data().ip_address; - net::IPEndPoint ip_endpoint(ip_address, kCastControlPort); + net::IPEndPoint ip_endpoint(sink.dial_data().ip_address, kCastControlPort); if (base::ContainsKey(current_service_ip_endpoints_, ip_endpoint)) { DVLOG(2) << "Sink discovered by mDNS, skip adding [name]: "
diff --git a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl_unittest.cc b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl_unittest.cc index bb28759..64f974c 100644 --- a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl_unittest.cc +++ b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl_unittest.cc
@@ -284,10 +284,6 @@ media_sink_service_impl_.current_sinks_by_mdns_[ip_endpoint1] = cast_sink1; media_sink_service_impl_.current_sinks_by_mdns_[ip_endpoint2] = cast_sink2; // Cast sink 2, 3 from dial discovery - auto extra_data = cast_sink2.cast_data(); - extra_data.discovered_by_dial = true; - extra_data.model_name += " dial"; - media_sink_service_impl_.current_sinks_by_dial_[ip_endpoint2] = cast_sink2; media_sink_service_impl_.current_sinks_by_dial_[ip_endpoint3] = cast_sink3;
diff --git a/chrome/browser/net/system_network_context_manager.cc b/chrome/browser/net/system_network_context_manager.cc index 997fd1b8..748615af 100644 --- a/chrome/browser/net/system_network_context_manager.cc +++ b/chrome/browser/net/system_network_context_manager.cc
@@ -70,7 +70,6 @@ content::mojom::NetworkContextParamsPtr* network_context_params, bool* is_quic_allowed) { SystemNetworkContextManager* manager = GetInstance(); - DCHECK(!manager->io_thread_network_context_); *network_context_request = mojo::MakeRequest(&manager->io_thread_network_context_); *network_context_params = CreateNetworkContextParams();
diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc index 2ee854e..5ae70ff 100644 --- a/chrome/browser/password_manager/password_manager_browsertest.cc +++ b/chrome/browser/password_manager/password_manager_browsertest.cc
@@ -30,6 +30,7 @@ #include "chrome/browser/ui/login/login_handler_test_utils.h" #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/browser/ui/test/test_browser_dialog.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/ui_test_utils.h" @@ -57,6 +58,7 @@ #include "net/url_request/test_url_fetcher_factory.h" #include "testing/gmock/include/gmock/gmock.h" #include "third_party/WebKit/public/platform/WebInputEvent.h" +#include "ui/base/ui_base_switches.h" #include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/geometry/point.h" @@ -3270,4 +3272,50 @@ histograms.ExpectTotalCount(kHistogram, 0); } +// Harness for showing dialogs as part of the DialogBrowserTest suite. Allows +// the dialogs to be shown interactively when invoked with, e.g., +// browser_tests --gtest_filter=BrowserDialogTest.Invoke --interactive +// --dialog=PasswordManagerDialogBrowserTest.InvokeDialog_normal. +class PasswordManagerDialogBrowserTest + : public SupportsTestDialog<PasswordManagerBrowserTestBase> { + public: + PasswordManagerDialogBrowserTest() = default; + + // content::BrowserTestBase: + void SetUpCommandLine(base::CommandLine* command_line) override { + // BrowserDialogTest only works on Mac with --secondary-ui-md. + command_line->AppendSwitch(switches::kExtendMdToSecondaryUi); + } + + void ShowDialog(const std::string& name) override { + // Note regarding flakiness: LocationBarBubbleDelegateView::ShowForReason() + // uses ShowInactive() unless the bubble is invoked with reason == + // USER_GESTURE. This means that, so long as these dialogs are not triggered + // by gesture, the dialog does not attempt to take focus, and so should + // never _lose_ focus in the test, which could cause flakes when tests are + // run in parallel. LocationBarBubbles also dismiss on other events, but + // only events in the WebContents. E.g. Rogue mouse clicks should not cause + // the dialog to dismiss since they won't be sent via WebContents. + // A user gesture is determined in browser_commands.cc by checking + // ManagePasswordsUIController::IsAutomaticallyOpeningBubble(), but that's + // set and cleared immediately while showing the bubble, so it can't be + // checked here. + NavigateToFile("/password/password_form.html"); + NavigationObserver observer(WebContents()); + std::string fill_and_submit = + "document.getElementById('username_field').value = 'temp';" + "document.getElementById('password_field').value = 'random';" + "document.getElementById('input_submit_button').click()"; + ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit)); + observer.Wait(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(PasswordManagerDialogBrowserTest); +}; + +IN_PROC_BROWSER_TEST_F(PasswordManagerDialogBrowserTest, InvokeDialog_normal) { + RunDialog(); +} + } // namespace password_manager
diff --git a/chrome/browser/payments/android/journey_logger_android.cc b/chrome/browser/payments/android/journey_logger_android.cc index 5d50b90..644cf50 100644 --- a/chrome/browser/payments/android/journey_logger_android.cc +++ b/chrome/browser/payments/android/journey_logger_android.cc
@@ -111,6 +111,16 @@ requested_phone, requested_name); } +void JourneyLoggerAndroid::SetRequestedPaymentMethodTypes( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcaller, + jboolean requested_basic_card, + jboolean requested_method_google, + jboolean requested_method_other) { + journey_logger_.SetRequestedPaymentMethodTypes( + requested_basic_card, requested_method_google, requested_method_other); +} + void JourneyLoggerAndroid::SetCompleted( JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller) {
diff --git a/chrome/browser/payments/android/journey_logger_android.h b/chrome/browser/payments/android/journey_logger_android.h index 4fbb5496..3d89ee1 100644 --- a/chrome/browser/payments/android/journey_logger_android.h +++ b/chrome/browser/payments/android/journey_logger_android.h
@@ -57,6 +57,12 @@ jboolean requested_email, jboolean requested_phone, jboolean requested_name); + void SetRequestedPaymentMethodTypes( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcaller, + jboolean requested_basic_card, + jboolean requested_method_google, + jboolean requested_method_other); void SetCompleted(JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller); void SetAborted(JNIEnv* env,
diff --git a/chrome/browser/predictors/OWNERS b/chrome/browser/predictors/OWNERS index 538cb20..791f6ad 100644 --- a/chrome/browser/predictors/OWNERS +++ b/chrome/browser/predictors/OWNERS
@@ -1,4 +1,3 @@ alexilin@chromium.org lizeb@chromium.org pasko@chromium.org -zhenw@chromium.org
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index aed9e942..082ad59 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -263,9 +263,8 @@ #endif #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) && !defined(OS_MACOSX) -#include "chrome/browser/feature_engagement/new_tab/new_tab_tracker.h" +#include "chrome/browser/feature_engagement/session_duration_updater.h" #endif - #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) #include "chrome/browser/ui/startup/default_browser_prompt.h" #endif @@ -587,7 +586,7 @@ #endif #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) && !defined(OS_MACOSX) - feature_engagement::NewTabTracker::RegisterProfilePrefs(registry); + feature_engagement::SessionDurationUpdater::RegisterProfilePrefs(registry); #endif #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc index 157df68..0ff4e1c 100644 --- a/chrome/browser/profiles/profile_manager.cc +++ b/chrome/browser/profiles/profile_manager.cc
@@ -993,6 +993,9 @@ g_browser_process->platform_part() ->profile_helper() ->GetSigninProfileDir() != profile->GetPath() && + g_browser_process->platform_part() + ->profile_helper() + ->GetLockScreenAppProfilePath() != profile->GetPath() && #endif command_line->HasSwitch(switches::kSupervisedUserId); if (force_supervised_user_id) {
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc index 2e8532b..a1a4cb9 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
@@ -115,9 +115,9 @@ params.writing_direction_default = 0; params.writing_direction_left_to_right = 0; params.writing_direction_right_to_left = 0; -#endif // OS_MACOSX - std::unique_ptr<TestRenderViewContextMenu> menu( - new TestRenderViewContextMenu(web_contents->GetMainFrame(), params)); +#endif + auto menu = base::MakeUnique<TestRenderViewContextMenu>( + web_contents->GetMainFrame(), params); menu->Init(); return menu; } @@ -135,7 +135,8 @@ class PdfPluginContextMenuBrowserTest : public InProcessBrowserTest { public: - PdfPluginContextMenuBrowserTest() {} + PdfPluginContextMenuBrowserTest() = default; + ~PdfPluginContextMenuBrowserTest() override = default; void SetUpOnMainThread() override { guest_view::GuestViewManager::set_factory_for_testing(&factory_); @@ -648,8 +649,8 @@ void AttemptImageSearch() { // |menu_observer_| will cause the search-by-image menu item to be clicked. - menu_observer_.reset(new ContextMenuNotificationObserver( - IDC_CONTENT_CONTEXT_SEARCHWEBFORIMAGE)); + menu_observer_ = base::MakeUnique<ContextMenuNotificationObserver>( + IDC_CONTENT_CONTEXT_SEARCHWEBFORIMAGE); RightClickImage(); } @@ -818,7 +819,7 @@ return; requests_to_wait_for_ = requests_to_wait_for; - run_loop_.reset(new base::RunLoop()); + run_loop_ = base::MakeUnique<base::RunLoop>(); run_loop_->Run(); run_loop_.reset(); requests_to_wait_for_ = -1; @@ -882,8 +883,8 @@ void AttemptLoadImage() { // Right-click where the image should be. // |menu_observer_| will cause the "Load image" menu item to be clicked. - menu_observer_.reset(new ContextMenuNotificationObserver( - IDC_CONTENT_CONTEXT_LOAD_ORIGINAL_IMAGE)); + menu_observer_ = base::MakeUnique<ContextMenuNotificationObserver>( + IDC_CONTENT_CONTEXT_LOAD_ORIGINAL_IMAGE); content::WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); content::SimulateMouseClickAt(tab, 0, blink::WebMouseEvent::Button::kRight,
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.cc index 7b3cfc60..dea0eac 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.cc
@@ -20,7 +20,7 @@ TestRenderViewContextMenu::~TestRenderViewContextMenu() {} // static -TestRenderViewContextMenu* TestRenderViewContextMenu::Create( +std::unique_ptr<TestRenderViewContextMenu> TestRenderViewContextMenu::Create( content::WebContents* web_contents, const GURL& page_url, const GURL& link_url, @@ -29,18 +29,19 @@ params.page_url = page_url; params.link_url = link_url; params.frame_url = frame_url; - TestRenderViewContextMenu* menu = - new TestRenderViewContextMenu(web_contents->GetMainFrame(), params); + auto menu = base::MakeUnique<TestRenderViewContextMenu>( + web_contents->GetMainFrame(), params); menu->Init(); return menu; } -bool TestRenderViewContextMenu::IsItemPresent(int command_id) { +bool TestRenderViewContextMenu::IsItemPresent(int command_id) const { return menu_model_.GetIndexOfCommandId(command_id) != -1; } -bool TestRenderViewContextMenu::IsItemInRangePresent(int command_id_first, - int command_id_last) { +bool TestRenderViewContextMenu::IsItemInRangePresent( + int command_id_first, + int command_id_last) const { DCHECK_LE(command_id_first, command_id_last); for (int command_id = command_id_first; command_id <= command_id_last; ++command_id) { @@ -65,7 +66,8 @@ *found_model = model; *found_index = i; return true; - } else if (model->GetTypeAt(i) == MenuModel::TYPE_SUBMENU) { + } + if (model->GetTypeAt(i) == MenuModel::TYPE_SUBMENU) { models_to_search.push_back(model->GetSubmenuModelAt(i)); } } @@ -75,11 +77,12 @@ } int TestRenderViewContextMenu::GetCommandIDByProfilePath( - const base::FilePath& path) { + const base::FilePath& path) const { size_t count = profile_link_paths_.size(); - for (size_t i = 0; i < count; ++i) + for (size_t i = 0; i < count; ++i) { if (profile_link_paths_[i] == path) return IDC_OPEN_LINK_IN_PROFILE_FIRST + static_cast<int>(i); + } return -1; }
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h b/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h index 7dd050c7..ea9f5b8 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h +++ b/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h
@@ -7,6 +7,8 @@ #include <stddef.h> +#include <memory> + #include "base/files/file_path.h" #include "base/macros.h" #include "chrome/browser/renderer_context_menu/render_view_context_menu.h" @@ -34,20 +36,21 @@ // This is a lightweight method to create a test RenderViewContextMenu // instance. // Use the constructor if you want to create menu with fine-grained params. - static TestRenderViewContextMenu* Create(content::WebContents* web_contents, - const GURL& page_url, - const GURL& link_url, - const GURL& frame_url); + static std::unique_ptr<TestRenderViewContextMenu> Create( + content::WebContents* web_contents, + const GURL& page_url, + const GURL& link_url, + const GURL& frame_url); // Returns true if the command specified by |command_id| is present // in the menu. // A list of command ids can be found in chrome/app/chrome_command_ids.h. - bool IsItemPresent(int command_id); + bool IsItemPresent(int command_id) const; // Returns true if a command specified by any command id between // |command_id_first| and |command_id_last| (inclusive) is present in the // menu. - bool IsItemInRangePresent(int command_id_first, int command_id_last); + bool IsItemInRangePresent(int command_id_first, int command_id_last) const; // Searches for an menu item with |command_id|. If it's found, the return // value is true and the model and index where it appears in that model are @@ -57,7 +60,7 @@ int* found_index); // Returns the command id of the menu item with the specified |path|. - int GetCommandIDByProfilePath(const base::FilePath& path); + int GetCommandIDByProfilePath(const base::FilePath& path) const; #if BUILDFLAG(ENABLE_EXTENSIONS) extensions::ContextMenuMatcher& extension_items() { return extension_items_; }
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc index 5f9fdf29..f6b4d1bc 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc
@@ -89,8 +89,8 @@ ProtocolHandlerRegistry* registry) { content::ContextMenuParams params = CreateParams(MenuItem::LINK); params.unfiltered_link_url = params.link_url; - std::unique_ptr<TestRenderViewContextMenu> menu( - new TestRenderViewContextMenu(web_contents->GetMainFrame(), params)); + auto menu = base::MakeUnique<TestRenderViewContextMenu>( + web_contents->GetMainFrame(), params); menu->set_protocol_handler_registry(registry); menu->Init(); return menu; @@ -317,7 +317,7 @@ void SetUp() override { RenderViewContextMenuTest::SetUp(); // TestingProfile does not provide a protocol registry. - registry_.reset(new ProtocolHandlerRegistry(profile(), nullptr)); + registry_ = base::MakeUnique<ProtocolHandlerRegistry>(profile(), nullptr); } void TearDown() override { @@ -376,7 +376,7 @@ void SetUp() override { ChromeRenderViewHostTestHarness::SetUp(); - registry_.reset(new ProtocolHandlerRegistry(profile(), nullptr)); + registry_ = base::MakeUnique<ProtocolHandlerRegistry>(profile(), nullptr); } void TearDown() override { @@ -393,8 +393,8 @@ std::unique_ptr<TestRenderViewContextMenu> CreateContextMenuOnChromeLink() { content::ContextMenuParams params = CreateParams(MenuItem::LINK); params.unfiltered_link_url = params.link_url = GURL("chrome://settings"); - std::unique_ptr<TestRenderViewContextMenu> menu( - new TestRenderViewContextMenu(web_contents()->GetMainFrame(), params)); + auto menu = base::MakeUnique<TestRenderViewContextMenu>( + web_contents()->GetMainFrame(), params); menu->set_protocol_handler_registry(registry_.get()); menu->Init(); return menu; @@ -501,9 +501,8 @@ content::ContextMenuParams params = CreateParams(MenuItem::IMAGE); params.unfiltered_link_url = params.link_url; - content::WebContents* wc = web_contents(); - std::unique_ptr<TestRenderViewContextMenu> menu( - new TestRenderViewContextMenu(wc->GetMainFrame(), params)); + auto menu = base::MakeUnique<TestRenderViewContextMenu>( + web_contents()->GetMainFrame(), params); menu->ExecuteCommand(IDC_CONTENT_CONTEXT_SAVEIMAGEAS, 0); @@ -523,9 +522,8 @@ content::ContextMenuParams params = CreateParams(MenuItem::IMAGE); params.unfiltered_link_url = params.link_url; - content::WebContents* wc = web_contents(); - std::unique_ptr<TestRenderViewContextMenu> menu( - new TestRenderViewContextMenu(wc->GetMainFrame(), params)); + auto menu = base::MakeUnique<TestRenderViewContextMenu>( + web_contents()->GetMainFrame(), params); menu->ExecuteCommand(IDC_CONTENT_CONTEXT_SAVEIMAGEAS, 0); @@ -547,9 +545,8 @@ data_reduction_proxy::chrome_proxy_content_transform_header()] = data_reduction_proxy::empty_image_directive(); params.unfiltered_link_url = params.link_url; - content::WebContents* wc = web_contents(); - std::unique_ptr<TestRenderViewContextMenu> menu( - new TestRenderViewContextMenu(wc->GetMainFrame(), params)); + auto menu = base::MakeUnique<TestRenderViewContextMenu>( + web_contents()->GetMainFrame(), params); AppendImageItems(menu.get()); ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_LOAD_ORIGINAL_IMAGE));
diff --git a/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc b/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc index 736216a..ff5c0806 100644 --- a/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc +++ b/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc
@@ -26,7 +26,7 @@ #include "content/public/test/text_input_test_utils.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" -#include "ui/base/ime/composition_underline.h" +#include "ui/base/ime/ime_text_span.h" #include "ui/base/ime/text_edit_commands.h" #include "ui/base/ime/text_input_client.h" #include "ui/base/ime/text_input_mode.h" @@ -820,8 +820,8 @@ // Commit some text for this frame. content::SendImeCommitTextToWidget( frames[index]->GetView()->GetRenderWidgetHost(), - base::UTF8ToUTF16(sample_text[index]), - std::vector<ui::CompositionUnderline>(), gfx::Range(), 0); + base::UTF8ToUTF16(sample_text[index]), std::vector<ui::ImeTextSpan>(), + gfx::Range(), 0); // Verify that the text we committed is now selected by listening to a // selection update from a RenderWidgetHostView which has the expected
diff --git a/chrome/browser/resource_coordinator/tab_manager.cc b/chrome/browser/resource_coordinator/tab_manager.cc index cac302a..bec1740 100644 --- a/chrome/browser/resource_coordinator/tab_manager.cc +++ b/chrome/browser/resource_coordinator/tab_manager.cc
@@ -602,6 +602,25 @@ return GetWebContentsData(web_contents)->is_restored_in_foreground(); } +bool TabManager::IsLoadingBackgroundTabs() const { + if (IsSessionRestoreLoadingTabs()) + return false; + + if (!pending_navigations_.empty()) + return true; + + // Excluding session restore above leaves only background opening tabs in + // |loading_contents_|. As long as they still remain in background, we are + // still loading background tabs, even after we emptied our pending navigation + // list. + for (const content::WebContents* tab : loading_contents_) { + if (!tab->IsVisible()) + return true; + } + + return false; +} + /////////////////////////////////////////////////////////////////////////////// // TabManager, private: @@ -1132,7 +1151,9 @@ content::NavigationThrottle::ThrottleCheckResult TabManager::MaybeThrottleNavigation(BackgroundTabNavigationThrottle* throttle) { content::NavigationHandle* navigation_handle = throttle->navigation_handle(); - if (CanLoadNextTab()) { + if (!base::FeatureList::IsEnabled( + features::kStaggeredBackgroundTabOpenExperiment) || + CanLoadNextTab()) { loading_contents_.insert(navigation_handle->GetWebContents()); return content::NavigationThrottle::PROCEED; }
diff --git a/chrome/browser/resource_coordinator/tab_manager.h b/chrome/browser/resource_coordinator/tab_manager.h index 5a74ffc1..f2531898 100644 --- a/chrome/browser/resource_coordinator/tab_manager.h +++ b/chrome/browser/resource_coordinator/tab_manager.h
@@ -226,6 +226,11 @@ // foreground. bool IsTabRestoredInForeground(content::WebContents* web_contents) const; + // Returns whether the tab manager is currently loading background tabs. This + // always returns false during an ongoing session restore, even if background + // tabs are being loaded, in order to separate the two activities. + bool IsLoadingBackgroundTabs() const; + private: FRIEND_TEST_ALL_PREFIXES(TabManagerTest, PurgeBackgroundRenderer); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ActivateTabResetPurgeState); @@ -257,6 +262,9 @@ FRIEND_TEST_ALL_PREFIXES(TabManagerTest, BackgroundTabLoadingMode); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, BackgroundTabLoadingSlots); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, BackgroundTabsLoadingOrdering); + FRIEND_TEST_ALL_PREFIXES(TabManagerTest, IsLoadingBackgroundTabs); + FRIEND_TEST_ALL_PREFIXES(TabManagerWithExperimentDisabledTest, + IsLoadingBackgroundTabs); FRIEND_TEST_ALL_PREFIXES(TabManagerStatsCollectorTest, HistogramsSessionRestoreSwitchToTab); FRIEND_TEST_ALL_PREFIXES(TabManagerTest,
diff --git a/chrome/browser/resource_coordinator/tab_manager_unittest.cc b/chrome/browser/resource_coordinator/tab_manager_unittest.cc index 2a0d49f8..cce45cc2 100644 --- a/chrome/browser/resource_coordinator/tab_manager_unittest.cc +++ b/chrome/browser/resource_coordinator/tab_manager_unittest.cc
@@ -15,6 +15,7 @@ #include "base/metrics/field_trial.h" #include "base/strings/string16.h" #include "base/test/mock_entropy_provider.h" +#include "base/test/scoped_feature_list.h" #include "base/test/simple_test_tick_clock.h" #include "base/time/time.h" #include "build/build_config.h" @@ -152,6 +153,10 @@ contents2_ = nav_handle2_->GetWebContents(); contents3_ = nav_handle3_->GetWebContents(); + contents1_->WasShown(); + contents2_->WasHidden(); + contents3_->WasHidden(); + throttle1_ = base::MakeUnique<NonResumingBackgroundTabNavigationThrottle>( nav_handle1_.get()); throttle2_ = base::MakeUnique<NonResumingBackgroundTabNavigationThrottle>( @@ -166,6 +171,14 @@ NavigationThrottle::ThrottleCheckResult result3 = tab_manager->MaybeThrottleNavigation(throttle3_.get()); + CheckThrottleResults(result1, result2, result3, loading_slots); + } + + virtual void CheckThrottleResults( + NavigationThrottle::ThrottleCheckResult result1, + NavigationThrottle::ThrottleCheckResult result2, + NavigationThrottle::ThrottleCheckResult result3, + size_t loading_slots) { // First tab starts navigation right away because there is no tab loading. EXPECT_EQ(content::NavigationThrottle::PROCEED, result1); switch (loading_slots) { @@ -198,6 +211,27 @@ WebContents* contents3_; }; +class TabManagerWithExperimentDisabledTest : public TabManagerTest { + public: + void SetUp() override { + scoped_feature_list_.InitAndDisableFeature( + features::kStaggeredBackgroundTabOpenExperiment); + ChromeRenderViewHostTestHarness::SetUp(); + } + + void CheckThrottleResults(NavigationThrottle::ThrottleCheckResult result1, + NavigationThrottle::ThrottleCheckResult result2, + NavigationThrottle::ThrottleCheckResult result3, + size_t loading_slots) override { + EXPECT_EQ(content::NavigationThrottle::PROCEED, result1); + EXPECT_EQ(content::NavigationThrottle::PROCEED, result2); + EXPECT_EQ(content::NavigationThrottle::PROCEED, result3); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + // TODO(georgesak): Add tests for protection to tabs with form input and // playing audio; @@ -976,6 +1010,81 @@ EXPECT_FALSE(tab_manager->IsNavigationDelayedForTest(nav_handle3_.get())); } +TEST_F(TabManagerTest, IsLoadingBackgroundTabs) { + TabManager* tab_manager = g_browser_process->GetTabManager(); + tab_manager->ResetMemoryPressureListenerForTest(); + EXPECT_FALSE(tab_manager->IsLoadingBackgroundTabs()); + + MaybeThrottleNavigations(tab_manager); + tab_manager->GetWebContentsData(contents1_) + ->DidStartNavigation(nav_handle1_.get()); + EXPECT_TRUE(tab_manager->IsLoadingBackgroundTabs()); + + tab_manager->GetWebContentsData(contents1_)->DidStopLoading(); + EXPECT_TRUE(tab_manager->IsLoadingBackgroundTabs()); + + tab_manager->GetWebContentsData(contents2_)->DidStopLoading(); + EXPECT_TRUE(tab_manager->IsLoadingBackgroundTabs()); + + contents3_->WasShown(); + EXPECT_FALSE(tab_manager->IsLoadingBackgroundTabs()); + + contents3_->WasHidden(); + EXPECT_TRUE(tab_manager->IsLoadingBackgroundTabs()); + + tab_manager->GetWebContentsData(contents3_)->DidStopLoading(); + EXPECT_FALSE(tab_manager->IsLoadingBackgroundTabs()); +} + +TEST_F(TabManagerWithExperimentDisabledTest, IsLoadingBackgroundTabs) { + EXPECT_FALSE(base::FeatureList::IsEnabled( + features::kStaggeredBackgroundTabOpenExperiment)); + + TabManager* tab_manager = g_browser_process->GetTabManager(); + tab_manager->ResetMemoryPressureListenerForTest(); + EXPECT_FALSE(tab_manager->IsLoadingBackgroundTabs()); + + MaybeThrottleNavigations(tab_manager); + tab_manager->GetWebContentsData(contents1_) + ->DidStartNavigation(nav_handle1_.get()); + tab_manager->GetWebContentsData(contents2_) + ->DidStartNavigation(nav_handle1_.get()); + tab_manager->GetWebContentsData(contents3_) + ->DidStartNavigation(nav_handle1_.get()); + + EXPECT_TRUE(tab_manager->IsTabLoadingForTest(contents1_)); + EXPECT_TRUE(tab_manager->IsTabLoadingForTest(contents2_)); + EXPECT_TRUE(tab_manager->IsTabLoadingForTest(contents3_)); + EXPECT_FALSE(tab_manager->IsNavigationDelayedForTest(nav_handle1_.get())); + EXPECT_FALSE(tab_manager->IsNavigationDelayedForTest(nav_handle2_.get())); + EXPECT_FALSE(tab_manager->IsNavigationDelayedForTest(nav_handle3_.get())); + EXPECT_TRUE(tab_manager->IsLoadingBackgroundTabs()); + + tab_manager->GetWebContentsData(contents1_)->DidStopLoading(); + EXPECT_FALSE(tab_manager->IsTabLoadingForTest(contents1_)); + EXPECT_TRUE(tab_manager->IsTabLoadingForTest(contents2_)); + EXPECT_TRUE(tab_manager->IsTabLoadingForTest(contents3_)); + EXPECT_TRUE(tab_manager->IsLoadingBackgroundTabs()); + + tab_manager->GetWebContentsData(contents2_)->DidStopLoading(); + EXPECT_FALSE(tab_manager->IsTabLoadingForTest(contents1_)); + EXPECT_FALSE(tab_manager->IsTabLoadingForTest(contents2_)); + EXPECT_TRUE(tab_manager->IsTabLoadingForTest(contents3_)); + EXPECT_TRUE(tab_manager->IsLoadingBackgroundTabs()); + + contents3_->WasShown(); + EXPECT_FALSE(tab_manager->IsLoadingBackgroundTabs()); + + contents3_->WasHidden(); + EXPECT_TRUE(tab_manager->IsLoadingBackgroundTabs()); + + tab_manager->GetWebContentsData(contents3_)->DidStopLoading(); + EXPECT_FALSE(tab_manager->IsTabLoadingForTest(contents1_)); + EXPECT_FALSE(tab_manager->IsTabLoadingForTest(contents2_)); + EXPECT_FALSE(tab_manager->IsTabLoadingForTest(contents3_)); + EXPECT_FALSE(tab_manager->IsLoadingBackgroundTabs()); +} + TEST_F(TabManagerTest, IsTabRestoredInForeground) { TabManager* tab_manager = g_browser_process->GetTabManager();
diff --git a/chrome/browser/resources/chromeos/arc_support/playstore.js b/chrome/browser/resources/chromeos/arc_support/playstore.js index a0d052dd..0bde6ca 100644 --- a/chrome/browser/resources/chromeos/arc_support/playstore.js +++ b/chrome/browser/resources/chromeos/arc_support/playstore.js
@@ -3,54 +3,65 @@ // found in the LICENSE file. /** + * Analyzes current document and tries to find the link to the Play Store ToS + * that matches requested |language| and |countryCode|. Once found, navigate + * to this link and returns True. If no match was found then returns False. + */ +function navigateToLanguageAndCountryCode(language, countryCode) { + var doc = document; + var selectLangZoneTerms = + doc.getElementById('play-footer').getElementsByTagName('select')[0]; + + var applyTermsForLangAndZone = function(termsLang) { + var matchByLangZone = + '/intl/' + termsLang + '_' + countryCode + '/about/play-terms.html'; + for (var i = selectLangZoneTerms.options.length - 1; i >= 0; --i) { + var option = selectLangZoneTerms.options[i]; + if (option.value == matchByLangZone) { + window.location.href = option.value; + return true; + } + } + return false; + }; + + // Try two versions of the language, full and short (if it exists, for + // example en-GB -> en). Note, terms may contain entries for both types, for + // example: en_ie, es-419_ar, es_as, pt-PT_pt. + if (applyTermsForLangAndZone(language)) { + return true; + } + var langSegments = language.split('-'); + if (langSegments.length == 2 && applyTermsForLangAndZone(langSegments[0])) { + return true; + } + + return false; +} + +/** * Processes select tag that contains list of available terms for different * languages and zones. In case of initial load, tries to find terms that match * exactly current language and country code and automatically redirects the * view in case such terms are found. Leaves terms in select tag that only match * current language or country code or default English variant or currently - * selected. Note that document.countryCode must be set before calling this - * function. + * selected. + * + * @return {boolean} True. */ -function processLangZoneTerms() { - var doc = document; - var selectLangZoneTerms = - doc.getElementById('play-footer').getElementsByTagName('select')[0]; - - var initialLoad = - window.location.href == 'https://play.google.com/about/play-terms.html'; - var langSegments = navigator.language.split('-'); - if (initialLoad) { - var applyTermsForLangAndZone = function(termsLang) { - var matchByLangZone = '/intl/' + termsLang + '_' + document.countryCode + - '/about/play-terms.html'; - for (var i = selectLangZoneTerms.options.length - 1; i >= 0; --i) { - var option = selectLangZoneTerms.options[i]; - if (option.value == matchByLangZone) { - window.location.href = option.value; - return true; - } - } - return false; - }; - - // Try two versions of the language, full and short (if it exists, for - // example en-GB -> en). Note, terms may contain entries for both types, for - // example: en_ie, es-419_ar, es_as, pt-PT_pt. - if (applyTermsForLangAndZone(navigator.language)) { - return; - } - if (langSegments.length == 2 && applyTermsForLangAndZone(langSegments[0])) { - return; - } +function processLangZoneTerms(initialLoad, language, countryCode) { + var langSegments = language.split('-'); + if (initialLoad && navigateToLanguageAndCountryCode(language, countryCode)) { + return true; } - var matchByLang = '/intl/' + navigator.language + '_'; + var matchByLang = '/intl/' + language + '_'; var matchByLangShort = null; if (langSegments.length == 2) { matchByLangShort = '/intl/' + langSegments[0] + '_'; } - var matchByZone = '_' + document.countryCode + '/about/play-terms.html'; + var matchByZone = '_' + countryCode + '/about/play-terms.html'; var matchByDefault = '/intl/en/about/play-terms.html'; // We are allowed to display terms by default only in language that matches @@ -58,6 +69,9 @@ var langMatch = false; var defaultExist = false; + var doc = document; + var selectLangZoneTerms = + doc.getElementById('play-footer').getElementsByTagName('select')[0]; for (var i = selectLangZoneTerms.options.length - 1; i >= 0; --i) { var option = selectLangZoneTerms.options[i]; if (selectLangZoneTerms.selectedIndex == i) { @@ -69,19 +83,20 @@ defaultExist = true; continue; } - if (!option.value.startsWith(matchByLang) && + + option.hidden = !option.value.startsWith(matchByLang) && !option.value.endsWith(matchByZone) && !(matchByLangShort && option.value.startsWith(matchByLangShort)) && - option.text != 'English') { - selectLangZoneTerms.removeChild(option); - } + option.text != 'English'; } + if (initialLoad && !langMatch && defaultExist) { window.location.href = matchByDefault; } else { // Show content once we reached target url. document.body.hidden = false; } + return true; } /** @@ -131,5 +146,26 @@ return 'https://www.google.com/policies/privacy/'; } -formatDocument(); -processLangZoneTerms(); +/** + * Processes the current document by applying required formatting and selected + * right PlayStore ToS. + * Note that document.countryCode must be set before calling this function. + */ +function processDocument() { + if (document.wasProcessed) { + return; + } + formatDocument(); + + var initialLoad = + window.location.href == 'https://play.google.com/about/play-terms.html'; + var language = document.language; + if (!language) { + language = navigator.language; + } + + processLangZoneTerms(initialLoad, language, document.countryCode); + document.wasProcessed = true; +} + +processDocument();
diff --git a/chrome/browser/resources/chromeos/login/images/1x/updating_1x.png b/chrome/browser/resources/chromeos/login/images/1x/updating_1x.png new file mode 100644 index 0000000..758e0e3 --- /dev/null +++ b/chrome/browser/resources/chromeos/login/images/1x/updating_1x.png Binary files differ
diff --git a/chrome/browser/resources/chromeos/login/images/2x/updating_2x.png b/chrome/browser/resources/chromeos/login/images/2x/updating_2x.png new file mode 100644 index 0000000..da1f440 --- /dev/null +++ b/chrome/browser/resources/chromeos/login/images/2x/updating_2x.png Binary files differ
diff --git a/chrome/browser/resources/chromeos/login/md_header_bar.js b/chrome/browser/resources/chromeos/login/md_header_bar.js index 927d568..67ba4cca 100644 --- a/chrome/browser/resources/chromeos/login/md_header_bar.js +++ b/chrome/browser/resources/chromeos/login/md_header_bar.js
@@ -8,6 +8,16 @@ cr.define('login', function() { /** + * Enum for user actions taken from lock screen header while a lock screen + * app is in background. + * @enum {string} + */ + var LOCK_SCREEN_APPS_UNLOCK_ACTION = { + SIGN_OUT: 'LOCK_SCREEN_APPS_UNLOCK_ACTION.SIGN_OUT', + SHUTDOWN: 'LOCK_SCREEN_APPS_UNLOCK_ACTION.SHUTDOWN' + }; + + /** * Creates a header bar element. * * @constructor @@ -50,11 +60,13 @@ decorate: function() { document.addEventListener('click', this.handleClick_.bind(this)); $('shutdown-header-bar-item') - .addEventListener('click', this.handleShutdownClick_); - $('shutdown-button').addEventListener('click', this.handleShutdownClick_); + .addEventListener('click', this.handleShutdownClick_.bind(this)); + $('shutdown-button') + .addEventListener('click', this.handleShutdownClick_.bind(this)); $('restart-header-bar-item') - .addEventListener('click', this.handleShutdownClick_); - $('restart-button').addEventListener('click', this.handleShutdownClick_); + .addEventListener('click', this.handleShutdownClick_.bind(this)); + $('restart-button') + .addEventListener('click', this.handleShutdownClick_.bind(this)); $('add-user-button').addEventListener('click', this.handleAddUserClick_); $('more-settings-button') .addEventListener('click', this.handleMoreSettingsClick_.bind(this)); @@ -62,7 +74,7 @@ .addEventListener('click', this.handleGuestClick_); $('guest-user-button').addEventListener('click', this.handleGuestClick_); $('sign-out-user-button') - .addEventListener('click', this.handleSignoutClick_); + .addEventListener('click', this.handleSignoutClick_.bind(this)); $('cancel-multiple-sign-in-button') .addEventListener('click', this.handleCancelMultipleSignInClick_); $('unlock-user-button') @@ -184,6 +196,12 @@ */ handleSignoutClick_: function(e) { this.disabled = true; + if (this.lockScreenAppsState_ == LOCK_SCREEN_APPS_STATE.BACKGROUND) { + chrome.send( + 'recordLockScreenAppUnlockAction', + [LOCK_SCREEN_APPS_UNLOCK_ACTION.SIGN_OUT]); + } + chrome.send('signOutUser'); e.stopPropagation(); }, @@ -194,6 +212,11 @@ * @private */ handleShutdownClick_: function(e) { + if (this.lockScreenAppsState_ == LOCK_SCREEN_APPS_STATE.BACKGROUND) { + chrome.send( + 'recordLockScreenAppUnlockAction', + [LOCK_SCREEN_APPS_UNLOCK_ACTION.SHUTDOWN]); + } chrome.send('shutdownSystem'); e.stopPropagation(); },
diff --git a/chrome/browser/resources/chromeos/login/md_top_header_bar.html b/chrome/browser/resources/chromeos/login/md_top_header_bar.html index 0fc2608..056bc034 100644 --- a/chrome/browser/resources/chromeos/login/md_top_header_bar.html +++ b/chrome/browser/resources/chromeos/login/md_top_header_bar.html
@@ -3,7 +3,7 @@ <defs> <g id="action-icon" fill="none" fill-rule="evenodd"> <path d="M0 0h16v16H0"></path> - <path fill="#FFF" fill-rule="nonzero" d="M9.333 1.333H4c-.737 0-1.327.597-1.327 1.334l-.006 10.666c0 .737.59 1.334 1.326 1.334H12c.737 0 1.333-.597 1.333-1.334v-8l-4-4zm1.334 9.334h-2v2H7.333v-2h-2V9.333h2v-2h1.334v2h2v1.334zM8.667 6V2.333L12.333 6H8.667z"></path> + <path fill="#FFF" fill-rule="nonzero" d="M8.993 1.007h-4.67c-.734 0-1.327.6-1.327 1.333L2.99 13.69c0 .734.592 1.31 1.326 1.31h7.362c.733 0 1.333-.576 1.333-1.31V4.984L8.994 1.007zM9 6V2.535L12.542 6H9z"></path> </g> </defs> </svg>
diff --git a/chrome/browser/resources/chromeos/login/md_top_header_bar.js b/chrome/browser/resources/chromeos/login/md_top_header_bar.js index 7108c2e..3a11efa 100644 --- a/chrome/browser/resources/chromeos/login/md_top_header_bar.js +++ b/chrome/browser/resources/chromeos/login/md_top_header_bar.js
@@ -11,6 +11,15 @@ */ cr.define('login', function() { + /** + * The new note request type. + * @enum {string} + */ + var NEW_NOTE_REQUEST = { + TAP: 'NEW_NOTE_REQUEST.TAP', + SWIPE: 'NEW_NOTE_REQUEST.SWIPE', + KEYBOARD: 'NEW_NOTE_REQUEST.KEYBOARD' + }; /** * Calculates diagonal length of a rectangle with the provided sides. @@ -349,7 +358,7 @@ /** override */ decorate: function() { $('new-note-action') - .addEventListener('click', this.activateNoteAction_.bind(this)); + .addEventListener('click', this.handleNewNoteActionClick_.bind(this)); $('new-note-action') .addEventListener( 'keydown', this.handleNewNoteActionKeyDown_.bind(this)); @@ -416,6 +425,14 @@ }, /** + * Handler for clicks on note action element. + * @private + */ + handleNewNoteActionClick_: function() { + this.activateNoteAction_(NEW_NOTE_REQUEST.TAP); + }, + + /** * Handler for key down event. * @param {!KeyboardEvent} evt The key down event. * @private @@ -423,7 +440,7 @@ handleNewNoteActionKeyDown_: function(evt) { if (evt.code != 'Enter') return; - this.activateNoteAction_(); + this.activateNoteAction_(NEW_NOTE_REQUEST.KEYBOARD); }, /** @@ -442,13 +459,15 @@ if (diag(velocity.x, velocity.y) < MIN_SWIPE_VELOCITY) return; - this.activateNoteAction_(); + this.activateNoteAction_(NEW_NOTE_REQUEST.SWIPE); }, /** + * @param {!NEW_NOTE_REQUEST} requestType The type of request that triggered + * new note action. * @private */ - activateNoteAction_: function() { + activateNoteAction_: function(requestType) { $('new-note-action').classList.toggle('disabled', true); $('new-note-action-icon').hidden = true; $('top-header-bar').classList.toggle('version-labels-unset', true); @@ -457,9 +476,7 @@ (function() { if (this.lockScreenAppsState_ != LOCK_SCREEN_APPS_STATE.AVAILABLE) return; - chrome.send( - 'setLockScreenAppsState', - [LOCK_SCREEN_APPS_STATE.LAUNCH_REQUESTED]); + chrome.send('requestNewLockScreenNote', [requestType]); }).bind(this)); var container = $('new-note-action-container');
diff --git a/chrome/browser/resources/chromeos/login/oobe_change_picture.html b/chrome/browser/resources/chromeos/login/oobe_change_picture.html index 89ff91b0..c2fc0ad0 100644 --- a/chrome/browser/resources/chromeos/login/oobe_change_picture.html +++ b/chrome/browser/resources/chromeos/login/oobe_change_picture.html
@@ -26,7 +26,8 @@ --cr-picture-image-size: 192px; -webkit-margin-end: 28px; flex-shrink: 0; - margin-top: 48px; + height: 288px; + position: relative; width: 288px; }
diff --git a/chrome/browser/resources/chromeos/login/oobe_update.css b/chrome/browser/resources/chromeos/login/oobe_update.css index d85623c8..f90d743 100644 --- a/chrome/browser/resources/chromeos/login/oobe_update.css +++ b/chrome/browser/resources/chromeos/login/oobe_update.css
@@ -20,6 +20,10 @@ padding: 0; } +.update-illustration { + padding-bottom: 10px; +} + paper-progress { --paper-progress-active-color: var(--google-blue-500); --paper-progress-secondary-color: var(--google-blue-100);
diff --git a/chrome/browser/resources/chromeos/login/oobe_update.html b/chrome/browser/resources/chromeos/login/oobe_update.html index c0909ab..ee2328e 100644 --- a/chrome/browser/resources/chromeos/login/oobe_update.html +++ b/chrome/browser/resources/chromeos/login/oobe_update.html
@@ -38,6 +38,10 @@ </div> <div class="footer flex layout vertical"> <paper-progress id="checking-progress" indeterminate></paper-progress> + <div class="flex"></div> + <img class="update-illustration" + srcset="images/1x/updating_1x.png 1x, + images/2x/updating_2x.png 2x"> </div> </oobe-dialog> <oobe-dialog hidden="[[checkingForUpdate]]" tabindex="0" @@ -58,6 +62,10 @@ hidden="[[!estimatedTimeLeftShown]]">[[estimatedTimeLeft]]</div> <div id="progress-message" class="progress-message" hidden="[[!progressMessageShown]]">[[progressMessage]]</div> + <div class="flex"></div> + <img class="update-illustration" + srcset="images/1x/updating_1x.png 1x, + images/2x/updating_2x.png 2x"> </div> </oobe-dialog> </template>
diff --git a/chrome/browser/resources/chromeos/login/screen_arc_terms_of_service.js b/chrome/browser/resources/chromeos/login/screen_arc_terms_of_service.js index edd6873e..2d2f103 100644 --- a/chrome/browser/resources/chromeos/login/screen_arc_terms_of_service.js +++ b/chrome/browser/resources/chromeos/login/screen_arc_terms_of_service.js
@@ -10,12 +10,40 @@ return { EXTERNAL_API: [ 'setMetricsMode', 'setBackupAndRestoreMode', 'setLocationServicesMode', - 'setCountryCode' + 'loadPlayStoreToS' ], /** @override */ decorate: function(element) { // Valid newOobeUI is not available at this time. + this.countryCode_ = null; + this.language_ = null; + }, + + /** + * Returns current language that can be updated in OOBE flow. If OOBE flow + * does not exist then use navigator.language. + * + * @private + */ + getCurrentLanguage_: function() { + var languageList = loadTimeData.getValue('languageList'); + if (languageList) { + var language = Oobe.getSelectedValue(languageList); + if (language) { + return language; + } + } + return navigator.language; + }, + + /** + * Returns true if page was intialized. + * + * @private + */ + isPageReady_: function() { + return typeof this.useMDOobe !== 'undefined'; }, /** @@ -25,8 +53,7 @@ */ setMDMode_: function() { var useMDOobe = (loadTimeData.getString('newOobeUI') == 'on'); - if (typeof this.useMDOobe !== 'undefined' && - this.useMDOobe == useMDOobe) { + if (this.isPageReady_() && this.useMDOobe == useMDOobe) { return; } @@ -75,17 +102,8 @@ typeof results[0] == 'string') { self.showUrlOverlay(results[0]); } else { - // currentLanguage can be updated in OOBE but not in Login page. - // languageList exists in OOBE otherwise use navigator.language. - var currentLanguage; - var languageList = loadTimeData.getValue('languageList'); - if (languageList) { - currentLanguage = Oobe.getSelectedValue(languageList); - } else { - currentLanguage = navigator.language; - } var defaultLink = 'https://www.google.com/intl/' + - currentLanguage + '/policies/privacy/'; + self.getCurrentLanguage_() + '/policies/privacy/'; self.showUrlOverlay(defaultLink); } }); @@ -148,15 +166,35 @@ }, /** - * Sets current country code for ToS. + * Loads Play Store ToS in case country code has been changed or previous + * attempt failed. * @param {string} countryCode Country code based on current timezone. */ - setCountryCode: function(countryCode) { + loadPlayStoreToS: function(countryCode) { + // Make sure page is initialized for login mode. For OOBE mode, page is + // initialized as result of handling updateLocalizedContent. + this.setMDMode_(); + + var language = this.getCurrentLanguage_(); + countryCode = countryCode.toLowerCase(); + + if (this.language_ && this.language_ == language && this.countryCode_ && + this.countryCode_ == countryCode && + !this.classList.contains('error')) { + return; + } + + // Store current ToS parameters. + this.language_ = language; + this.countryCode_ = countryCode; + var scriptSetParameters = - 'document.countryCode = \'' + countryCode.toLowerCase() + '\';'; + 'document.countryCode = \'' + countryCode + '\';'; + scriptSetParameters += 'document.language = \'' + language + '\';'; if (this.useMDOobe) { scriptSetParameters += 'document.viewMode = \'large-view\';'; } + var termsView = this.getElement_('arc-tos-view'); termsView.removeContentScripts(['preProcess']); termsView.addContentScripts([{ @@ -166,9 +204,21 @@ run_at: 'document_start' }]); - if (!$('arc-tos').hidden) { - this.reloadPlayStore(); + // Try to use currently loaded document first. + var self = this; + if (termsView.src != '' && this.classList.contains('arc-tos-loaded')) { + var navigateScript = 'processLangZoneTerms(true, \'' + language + + '\', \'' + countryCode + '\');'; + termsView.executeScript({code: navigateScript}, function(results) { + if (!results || results.length != 1 || + typeof results[0] !== 'boolean' || !results[0]) { + self.reloadPlayStoreToS(); + } + }); + } else { + this.reloadPlayStoreToS(); } + }, /** @@ -191,7 +241,7 @@ retryButton.id = 'arc-tos-retry-button'; retryButton.textContent = loadTimeData.getString('arcTermsOfServiceRetryButton'); - retryButton.addEventListener('click', this.reloadPlayStore.bind(this)); + retryButton.addEventListener('click', this.reloadPlayStoreToS.bind(this)); buttons.push(retryButton); var acceptButton = this.ownerDocument.createElement('button'); @@ -288,9 +338,9 @@ }, /** - * Reloads Play Store. + * Reloads Play Store ToS. */ - reloadPlayStore: function() { + reloadPlayStoreToS: function() { this.termsError = false; var termsView = this.getElement_('arc-tos-view'); termsView.src = 'https://play.google.com/about/play-terms.html'; @@ -372,7 +422,6 @@ * @param {object} data Screen init payload. */ onBeforeShow: function(data) { - this.setMDMode_(); this.setLearnMoreHandlers_(); Oobe.getInstance().headerHidden = true; @@ -383,7 +432,6 @@ 'https://play.google.com/about/images/play_logo.png'; this.hideOverlay(); - this.reloadPlayStore(); }, /** @@ -406,6 +454,11 @@ updateLocalizedContent: function() { this.setMDMode_(); this.setLearnMoreHandlers_(); + + // We might need to reload Play Store ToS in case language was changed. + if (this.countryCode_) { + this.loadPlayStoreToS(this.countryCode_); + } }, /**
diff --git a/chrome/browser/resources/chromeos/login/screen_error_message.css b/chrome/browser/resources/chromeos/login/screen_error_message.css index b85da668..8b6db95 100644 --- a/chrome/browser/resources/chromeos/login/screen_error_message.css +++ b/chrome/browser/resources/chromeos/login/screen_error_message.css
@@ -42,10 +42,6 @@ display: block; } -#oobe.error-message #step-logo { - z-index: 1; -} - .error-header { background-clip: padding-box; background-color: white;
diff --git a/chrome/browser/resources/chromeos/login/screen_error_message.html b/chrome/browser/resources/chromeos/login/screen_error_message.html index ec7fd9c..43047ec 100644 --- a/chrome/browser/resources/chromeos/login/screen_error_message.html +++ b/chrome/browser/resources/chromeos/login/screen_error_message.html
@@ -1,6 +1,6 @@ <link rel="import" href="chrome://oobe/custom_elements.html"> -<div id="error-message" class="step hidden show-offline-error" hidden> +<div id="error-message" class="step hidden show-offline-error no-logo" hidden> <div class="step-contents"> <div class="error-header" aria-live="assertive"> <img alt class="error-icon" src="chrome://theme/IDR_ERROR_NETWORK_OFFLINE">
diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js index 4040aca7..fd94782 100644 --- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js +++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
@@ -664,7 +664,8 @@ (this.screenMode_ == ScreenMode.SAML_INTERSTITIAL); params.menuGuestMode = data.guestSignin; params.menuKeyboardOptions = false; - params.menuEnterpriseEnrollment = true; + params.menuEnterpriseEnrollment = + !(data.enterpriseManagedDevice || data.hasDeviceOwner); this.gaiaAuthParams_ = params;
diff --git a/chrome/browser/resources/md_bookmarks/BUILD.gn b/chrome/browser/resources/md_bookmarks/BUILD.gn index e0b81a21e..16e7498 100644 --- a/chrome/browser/resources/md_bookmarks/BUILD.gn +++ b/chrome/browser/resources/md_bookmarks/BUILD.gn
@@ -1,22 +1,12 @@ import("../vulcanize.gni") -vulcanized_unbuilt = "vulcanized.unbuilt.html" - -vulcanize("vulcanize") { +vulcanize("build") { host = "bookmarks" html_in_files = [ "bookmarks.html" ] - html_out_files = [ vulcanized_unbuilt ] + html_out_files = [ "vulcanized.html" ] input = rebase_path(".", root_build_dir) js_out_files = [ "crisper.js" ] deps = [] } - -polymer_css_build("build") { - input_files = [ vulcanized_unbuilt ] - output_files = [ "vulcanized.html" ] - deps = [ - ":vulcanize", - ] -}
diff --git a/chrome/browser/resources/md_downloads/BUILD.gn b/chrome/browser/resources/md_downloads/BUILD.gn index 923b8e8..1b340e3 100644 --- a/chrome/browser/resources/md_downloads/BUILD.gn +++ b/chrome/browser/resources/md_downloads/BUILD.gn
@@ -1,21 +1,11 @@ import("../vulcanize.gni") -vulcanized_unbuilt = "vulcanized.unbuilt.html" - -vulcanize("vulcanize") { +vulcanize("build") { deps = [] host = "downloads" html_in_files = [ "downloads.html" ] - html_out_files = [ vulcanized_unbuilt ] + html_out_files = [ "vulcanized.html" ] input = rebase_path(".", root_build_dir) insert_in_head = "<base href=chrome://downloads>" js_out_files = [ "crisper.js" ] } - -polymer_css_build("build") { - input_files = [ vulcanized_unbuilt ] - output_files = [ "vulcanized.html" ] - deps = [ - ":vulcanize", - ] -}
diff --git a/chrome/browser/resources/md_history/BUILD.gn b/chrome/browser/resources/md_history/BUILD.gn index f6ab0e0..2625f11 100644 --- a/chrome/browser/resources/md_history/BUILD.gn +++ b/chrome/browser/resources/md_history/BUILD.gn
@@ -1,17 +1,14 @@ import("../vulcanize.gni") -app_unbuilt = "app.vulcanized.unbuilt.html" -lazy_load_unbuilt = "lazy_load.vulcanized.unbuilt.html" - -vulcanize("vulcanize_app") { +vulcanize("build") { host = "history" html_in_files = [ "app.html", "lazy_load.html", ] html_out_files = [ - app_unbuilt, - lazy_load_unbuilt, + "app.vulcanized.html", + "lazy_load.vulcanized.html", ] input = rebase_path(".", root_build_dir) @@ -27,17 +24,3 @@ deps = [] } - -polymer_css_build("build") { - input_files = [ - app_unbuilt, - lazy_load_unbuilt, - ] - output_files = [ - "app.vulcanized.html", - "lazy_load.vulcanized.html", - ] - deps = [ - ":vulcanize_app", - ] -}
diff --git a/chrome/browser/resources/media_router/elements/route_controls/route_controls.html b/chrome/browser/resources/media_router/elements/route_controls/route_controls.html index 3f0ae9c4..0885042 100644 --- a/chrome/browser/resources/media_router/elements/route_controls/route_controls.html +++ b/chrome/browser/resources/media_router/elements/route_controls/route_controls.html
@@ -17,6 +17,7 @@ <div> <div id="route-time-controls" hidden="[[!routeStatus.canSeek]]"> <paper-slider + aria-valuetext$="[[getTimeSliderValueText_(displayedCurrentTime_)]]" dir="ltr" id="route-time-slider" on-change="onSeekComplete_" @@ -25,10 +26,12 @@ title="[[i18n('seekTitle')]]" value="[[displayedCurrentTime_]]"></paper-slider> <div id="timeline"> - <span id="current-time"> + <span id="current-time" + aria-label$="[[getCurrentTimeLabel_(displayedCurrentTime_)]]"> [[getFormattedTime_(displayedCurrentTime_)]] </span> - <span id="duration"> + <span id="duration" + aria-label$="[[getDurationLabel_(routeStatus.duration)]]"> [[getFormattedTime_(routeStatus.duration)]] </span> </div>
diff --git a/chrome/browser/resources/media_router/elements/route_controls/route_controls.js b/chrome/browser/resources/media_router/elements/route_controls/route_controls.js index 7dde729..510ac91d 100644 --- a/chrome/browser/resources/media_router/elements/route_controls/route_controls.js +++ b/chrome/browser/resources/media_router/elements/route_controls/route_controls.js
@@ -134,6 +134,30 @@ }, /** + * Creates an accessibility label for the element showing the media's current + * time. + * @param {number} displayedCurrentTime + * @return {string} + * @private + */ + getCurrentTimeLabel_: function(displayedCurrentTime) { + return `${ + this.i18n('currentTimeLabel') + } ${this.getFormattedTime_(displayedCurrentTime)}`; + }, + + /** + * Creates an accessibility label for the element showing the media's + * duration. + * @param {number} duration + * @return {string} + * @private + */ + getDurationLabel_: function(duration) { + return `${this.i18n('durationLabel')} ${this.getFormattedTime_(duration)}`; + }, + + /** * Converts a number representing an interval of seconds to a string with * HH:MM:SS format. * @param {number} timeInSec Must be non-negative. Intervals longer than 100 @@ -148,8 +172,9 @@ var hours = Math.floor(timeInSec / 3600); var minutes = Math.floor(timeInSec / 60) % 60; var seconds = Math.floor(timeInSec) % 60; - return ('0' + hours).substr(-2) + ':' + ('0' + minutes).substr(-2) + ':' + - ('0' + seconds).substr(-2); + // Show the hours only if it is nonzero. + return (hours ? ('0' + hours).substr(-2) + ':' : '') + + ('0' + minutes).substr(-2) + ':' + ('0' + seconds).substr(-2); }, /** @@ -194,6 +219,15 @@ this.i18n('pauseTitle'); }, + getTimeSliderValueText_: function(displayedCurrentTime) { + if (!this.routeStatus) { + return ''; + } + return `${ + this.getFormattedTime_(displayedCurrentTime) + } / ${this.getFormattedTime_(this.routeStatus.duration)}`; + }, + /** * Checks whether the media is still playing, and if so, sends a media status * update incrementing the current time and schedules another call for a
diff --git a/chrome/browser/resources/polymer_css_build_gn.py b/chrome/browser/resources/polymer_css_build_gn.py deleted file mode 100755 index 14fe7c5..0000000 --- a/chrome/browser/resources/polymer_css_build_gn.py +++ /dev/null
@@ -1,41 +0,0 @@ -#!/usr/bin/env python -# 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. - -import argparse -import os -import sys - -_HERE_PATH = os.path.dirname(__file__) -_SRC_PATH = os.path.normpath(os.path.join(_HERE_PATH, '..', '..', '..')) -_CWD = os.getcwd() - -sys.path.append(os.path.join(_SRC_PATH, 'third_party', 'node')) -import node -import node_modules - -def _css_build(out_folder, input_files, output_files): - out_path = os.path.join(_CWD, out_folder) - in_paths = map(lambda f: os.path.join(out_path, f), input_files) - out_paths = map(lambda f: os.path.join(out_path, f), output_files) - - args = ['--no-inline-includes', '-f'] + in_paths + ['-o'] + out_paths - node.RunNode([node_modules.PathToPolymerCssBuild()] + args) - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('--out_folder') - parser.add_argument('--input_files', nargs='+') - parser.add_argument('--output_files', nargs='+') - args = parser.parse_args() - - _css_build( - args.out_folder, - input_files=args.input_files, - output_files=args.output_files) - - -if __name__ == '__main__': - main()
diff --git a/chrome/browser/resources/print_preview/settings/scaling_settings.js b/chrome/browser/resources/print_preview/settings/scaling_settings.js index 99d752c..2db68ad 100644 --- a/chrome/browser/resources/print_preview/settings/scaling_settings.js +++ b/chrome/browser/resources/print_preview/settings/scaling_settings.js
@@ -121,11 +121,13 @@ /** * Display the fit to page scaling in the scaling field if there is a valid - * fit to page scaling value. If not, make the field blank. + * fit to page scaling value. If not, make the field blank. The fit to page + * value is always considered valid, so remove the hint if it is displayed. * @private */ displayFitToPageScaling: function() { this.inputField_.value = this.fitToPageScaling_ || ''; + this.removeHint_(); }, /** @@ -151,17 +153,24 @@ }, /** + * Removes the error message and red background from the input. + * @private + */ + removeHint_: function() { + this.inputField_.classList.remove('invalid'); + fadeOutElement(this.getChildElement('.hint')); + }, + + /** * Updates the state of the scaling settings UI controls. * @private */ updateState_: function() { if (this.isAvailable()) { - var displayedValue = this.getInputAsNumber(); // If fit to page is selected and the display matches, mark valid // and return. if (this.isFitToPageSelected() && this.displayMatchesFitToPage()) { - this.inputField_.classList.remove('invalid'); - fadeOutElement(this.getChildElement('.hint')); + this.removeHint_(); this.updateUiStateInternal(); return; } @@ -174,8 +183,7 @@ } this.inputField_.value = this.scalingTicketItem_.getValue(); - this.inputField_.classList.remove('invalid'); - fadeOutElement(this.getChildElement('.hint')); + this.removeHint_(); } this.updateUiStateInternal(); }, @@ -191,9 +199,11 @@ this.displayFitToPageScaling(); } else if ( this.fitToPageTicketItem_.isCapabilityAvailable() && - this.displayMatchesFitToPage()) { + (this.displayMatchesFitToPage() || + !this.inputField_.validity.valid)) { // Fit to page unchecked. Return to last scaling. this.inputField_.value = this.scalingTicketItem_.getValue(); + this.removeHint_(); } }, @@ -207,7 +217,8 @@ this.updateState_(); return; } - if (this.isFitToPageSelected() && !this.displayMatchesFitToPage()) { + if (this.isFitToPageSelected() && !this.displayMatchesFitToPage() && + this.inputField_.value != '') { // User modified value away from fit to page. this.fitToPageTicketItem_.updateValue(false); } @@ -262,12 +273,12 @@ if (this.inputField_.value == '' && this.inputField_.validity.valid) { if (this.isFitToPageSelected()) { this.displayFitToPageScaling(); + } else if (this.scalingTicketItem_.getValue() == '100') { + // No need to update the ticket, but change the display to match. + this.inputField_.value = '100'; + this.removeHint_(); } else { - if (this.scalingTicketItem_.getValue() == '100') - // No need to update the ticket, but change the display to match. - this.inputField_.value = '100'; - else - this.scalingTicketItem_.updateValue('100'); + this.scalingTicketItem_.updateValue('100'); } } },
diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resources/settings/BUILD.gn index 4b7895a..af4bf1d 100644 --- a/chrome/browser/resources/settings/BUILD.gn +++ b/chrome/browser/resources/settings/BUILD.gn
@@ -2,20 +2,18 @@ import("//tools/grit/grit_rule.gni") import("//chrome/common/features.gni") -app_unbuilt = "vulcanized.unbuilt.html" -lazy_load_unbuilt = "lazy_load.vulcanized.unbuilt.html" settings_pak_file = "settings_resources.pak" unpak_folder = "settings_resources.unpak" -vulcanize("vulcanize_app") { +vulcanize("build") { host = "settings" html_in_files = [ "settings.html", "lazy_load.html", ] html_out_files = [ - app_unbuilt, - lazy_load_unbuilt, + "vulcanized.html", + "lazy_load.vulcanized.html", ] insert_in_head = "<base href=\"chrome://\$i18n{hostname}\">" input = rebase_path("$target_gen_dir/$unpak_folder", root_build_dir) @@ -38,20 +36,6 @@ ] } -polymer_css_build("build") { - input_files = [ - app_unbuilt, - lazy_load_unbuilt, - ] - output_files = [ - "vulcanized.html", - "lazy_load.vulcanized.html", - ] - deps = [ - ":vulcanize_app", - ] -} - grit("flattened_resources") { source = "settings_resources.grd"
diff --git a/chrome/browser/resources/settings/people_page/change_picture.html b/chrome/browser/resources/settings/people_page/change_picture.html index 8d0c573..c8e093f38 100644 --- a/chrome/browser/resources/settings/people_page/change_picture.html +++ b/chrome/browser/resources/settings/people_page/change_picture.html
@@ -30,7 +30,8 @@ --cr-picture-image-size: 192px; -webkit-margin-end: 24px; flex-shrink: 0; - margin-top: 48px; + height: 288px; + position: relative; width: 288px; }
diff --git a/chrome/browser/resources/vulcanize_gn.py b/chrome/browser/resources/vulcanize_gn.py index 5b1d517b..78e37ad 100755 --- a/chrome/browser/resources/vulcanize_gn.py +++ b/chrome/browser/resources/vulcanize_gn.py
@@ -180,26 +180,33 @@ f.close() try: + crisper_html_out_paths = [] for index, html_in_file in enumerate(args.html_in_files): - html_out_file = args.html_out_files[index] + crisper_html_out_paths.append( + os.path.join(tmp_out_dir, args.html_out_files[index])) js_out_file = args.js_out_files[index] # Run crisper to separate the JS from the HTML file. node.RunNode([node_modules.PathToCrisper(), '--source', os.path.join(tmp_out_dir, html_in_file), '--script-in-head', 'false', - '--html', os.path.join(tmp_out_dir, html_out_file), + '--html', crisper_html_out_paths[index], '--js', os.path.join(tmp_out_dir, js_out_file)]) - # Move the HTML file to its final destination. - shutil.copy(os.path.join(tmp_out_dir, html_out_file), out_path) - # Pass the JS file through Uglify and write the output to its final # destination. node.RunNode([node_modules.PathToUglify(), os.path.join(tmp_out_dir, js_out_file), '--comments', '"/Copyright|license|LICENSE|\<\/?if/"', '--output', os.path.join(out_path, js_out_file)]) + + # Run polymer-css-build and write the output HTML files to their final + # destination. + pcb_html_out_paths = [ + os.path.join(out_path, f) for f in args.html_out_files] + node.RunNode([node_modules.PathToPolymerCssBuild()] + + ['--no-inline-includes', '-f'] + + crisper_html_out_paths + ['-o'] + pcb_html_out_paths) finally: shutil.rmtree(tmp_out_dir) return manifest_out_path
diff --git a/chrome/browser/safe_browsing/browser_feature_extractor.cc b/chrome/browser/safe_browsing/browser_feature_extractor.cc index bbabc07..d627b039 100644 --- a/chrome/browser/safe_browsing/browser_feature_extractor.cc +++ b/chrome/browser/safe_browsing/browser_feature_extractor.cc
@@ -24,7 +24,7 @@ #include "chrome/browser/safe_browsing/client_side_detection_host.h" #include "components/history/core/browser/history_service.h" #include "components/history/core/browser/history_types.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "components/safe_browsing_db/database_manager.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_controller.h"
diff --git a/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc b/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc index 83958d9..76253cc 100644 --- a/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc +++ b/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc
@@ -24,7 +24,7 @@ #include "chrome/test/base/testing_profile.h" #include "components/history/core/browser/history_backend.h" #include "components/history/core/browser/history_service.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "components/safe_browsing_db/database_manager.h" #include "components/safe_browsing_db/test_database_manager.h" #include "content/public/browser/navigation_controller.h"
diff --git a/chrome/browser/safe_browsing/client_side_detection_host.cc b/chrome/browser/safe_browsing/client_side_detection_host.cc index b5ba16f..15d9191 100644 --- a/chrome/browser/safe_browsing/client_side_detection_host.cc +++ b/chrome/browser/safe_browsing/client_side_detection_host.cc
@@ -23,7 +23,7 @@ #include "components/prefs/pref_service.h" #include "components/safe_browsing/common/safe_browsing_prefs.h" #include "components/safe_browsing/common/safebrowsing_messages.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "components/safe_browsing_db/database_manager.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_controller.h"
diff --git a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc index 7559c39..4ee5678 100644 --- a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc +++ b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
@@ -23,7 +23,7 @@ #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/testing_profile.h" #include "components/safe_browsing/common/safebrowsing_messages.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "components/safe_browsing_db/database_manager.h" #include "components/safe_browsing_db/test_database_manager.h" #include "content/public/browser/navigation_entry.h"
diff --git a/chrome/browser/safe_browsing/client_side_detection_service.cc b/chrome/browser/safe_browsing/client_side_detection_service.cc index 30743b7..4d97ebf9 100644 --- a/chrome/browser/safe_browsing/client_side_detection_service.cc +++ b/chrome/browser/safe_browsing/client_side_detection_service.cc
@@ -25,7 +25,7 @@ #include "components/prefs/pref_service.h" #include "components/safe_browsing/common/safe_browsing_prefs.h" #include "components/safe_browsing/common/safebrowsing_messages.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_types.h"
diff --git a/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc b/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc index 62a43d3..ecea7d38 100644 --- a/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc +++ b/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc
@@ -22,7 +22,7 @@ #include "base/strings/string_number_conversions.h" #include "base/time/time.h" #include "chrome/common/safe_browsing/client_model.pb.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "components/variations/variations_associated_data.h" #include "content/public/test/test_browser_thread_bundle.h" #include "crypto/sha2.h"
diff --git a/chrome/browser/safe_browsing/client_side_model_loader.cc b/chrome/browser/safe_browsing/client_side_model_loader.cc index b598044..c1da018 100644 --- a/chrome/browser/safe_browsing/client_side_model_loader.cc +++ b/chrome/browser/safe_browsing/client_side_model_loader.cc
@@ -19,7 +19,7 @@ #include "components/data_use_measurement/core/data_use_user_data.h" #include "components/safe_browsing/common/safebrowsing_messages.h" #include "components/safe_browsing/common/safebrowsing_switches.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "components/variations/variations_associated_data.h" #include "net/base/load_flags.h" #include "net/http/http_response_headers.h"
diff --git a/chrome/browser/safe_browsing/client_side_model_loader_unittest.cc b/chrome/browser/safe_browsing/client_side_model_loader_unittest.cc index f30d5590..237b83ad 100644 --- a/chrome/browser/safe_browsing/client_side_model_loader_unittest.cc +++ b/chrome/browser/safe_browsing/client_side_model_loader_unittest.cc
@@ -17,7 +17,7 @@ #include "base/strings/string_number_conversions.h" #include "base/time/time.h" #include "chrome/common/safe_browsing/client_model.pb.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "components/variations/variations_associated_data.h" #include "content/public/test/test_browser_thread_bundle.h" #include "net/http/http_status_code.h"
diff --git a/chrome/browser/safe_browsing/download_feedback.cc b/chrome/browser/safe_browsing/download_feedback.cc index b0be578..08e1563a 100644 --- a/chrome/browser/safe_browsing/download_feedback.cc +++ b/chrome/browser/safe_browsing/download_feedback.cc
@@ -10,7 +10,7 @@ #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "base/task_runner.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "content/public/browser/browser_thread.h" #include "net/base/net_errors.h"
diff --git a/chrome/browser/safe_browsing/download_feedback_unittest.cc b/chrome/browser/safe_browsing/download_feedback_unittest.cc index 8bd291f..301f49b 100644 --- a/chrome/browser/safe_browsing/download_feedback_unittest.cc +++ b/chrome/browser/safe_browsing/download_feedback_unittest.cc
@@ -12,7 +12,7 @@ #include "base/single_thread_task_runner.h" #include "base/task_scheduler/post_task.h" #include "chrome/browser/safe_browsing/two_phase_uploader.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "content/public/browser/browser_thread.h" #include "content/public/test/test_browser_thread_bundle.h" #include "content/public/test/test_utils.h"
diff --git a/chrome/browser/safe_browsing/download_protection_service.cc b/chrome/browser/safe_browsing/download_protection_service.cc index 82fd1dd..18ecd68 100644 --- a/chrome/browser/safe_browsing/download_protection_service.cc +++ b/chrome/browser/safe_browsing/download_protection_service.cc
@@ -58,7 +58,7 @@ #include "components/safe_browsing/common/safe_browsing_prefs.h" #include "components/safe_browsing/common/safebrowsing_switches.h" #include "components/safe_browsing/common/utils.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/download_item.h" #include "content/public/browser/page_navigator.h"
diff --git a/chrome/browser/safe_browsing/download_protection_service_unittest.cc b/chrome/browser/safe_browsing/download_protection_service_unittest.cc index 39a7ccd..9f88de2 100644 --- a/chrome/browser/safe_browsing/download_protection_service_unittest.cc +++ b/chrome/browser/safe_browsing/download_protection_service_unittest.cc
@@ -41,7 +41,7 @@ #include "components/prefs/pref_service.h" #include "components/safe_browsing/common/safe_browsing_prefs.h" #include "components/safe_browsing/common/safebrowsing_switches.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "components/safe_browsing_db/database_manager.h" #include "components/safe_browsing_db/test_database_manager.h" #include "components/safe_browsing_db/v4_protocol_manager_util.h"
diff --git a/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer.cc b/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer.cc index bf35ec2..c78d52f9 100644 --- a/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer.cc +++ b/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer.cc
@@ -20,7 +20,7 @@ #include "chrome/browser/safe_browsing/incident_reporting/binary_integrity_incident.h" #include "chrome/browser/safe_browsing/incident_reporting/incident_receiver.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" namespace safe_browsing {
diff --git a/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer_mac.cc b/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer_mac.cc index 0d619b9..7f4331e 100644 --- a/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer_mac.cc +++ b/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer_mac.cc
@@ -14,7 +14,7 @@ #include "chrome/browser/safe_browsing/incident_reporting/binary_integrity_incident.h" #include "chrome/browser/safe_browsing/incident_reporting/incident_receiver.h" #include "chrome/browser/safe_browsing/signature_evaluator_mac.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" namespace safe_browsing {
diff --git a/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer_mac_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer_mac_unittest.cc index a6f371b..01b9e0d5 100644 --- a/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer_mac_unittest.cc +++ b/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer_mac_unittest.cc
@@ -16,7 +16,7 @@ #include "chrome/browser/safe_browsing/incident_reporting/incident.h" #include "chrome/browser/safe_browsing/incident_reporting/mock_incident_receiver.h" #include "chrome/common/chrome_paths.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer_win.cc b/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer_win.cc index 3b6e7ca..e05eb2b 100644 --- a/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer_win.cc +++ b/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer_win.cc
@@ -18,7 +18,7 @@ #include "chrome/browser/safe_browsing/incident_reporting/incident_receiver.h" #include "chrome/common/chrome_version.h" #include "chrome/common/safe_browsing/binary_feature_extractor.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" namespace safe_browsing {
diff --git a/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer_win_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer_win_unittest.cc index 2c17aa4..5c9f26116 100644 --- a/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer_win_unittest.cc +++ b/chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer_win_unittest.cc
@@ -16,7 +16,7 @@ #include "chrome/browser/safe_browsing/incident_reporting/mock_incident_receiver.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_version.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/safe_browsing/incident_reporting/binary_integrity_incident.cc b/chrome/browser/safe_browsing/incident_reporting/binary_integrity_incident.cc index a914bfba..a20a8e4 100644 --- a/chrome/browser/safe_browsing/incident_reporting/binary_integrity_incident.cc +++ b/chrome/browser/safe_browsing/incident_reporting/binary_integrity_incident.cc
@@ -6,7 +6,7 @@ #include "base/logging.h" #include "chrome/browser/safe_browsing/incident_reporting/incident_handler_util.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" namespace safe_browsing {
diff --git a/chrome/browser/safe_browsing/incident_reporting/binary_integrity_incident_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/binary_integrity_incident_unittest.cc index bb86600..061d7e7 100644 --- a/chrome/browser/safe_browsing/incident_reporting/binary_integrity_incident_unittest.cc +++ b/chrome/browser/safe_browsing/incident_reporting/binary_integrity_incident_unittest.cc
@@ -11,7 +11,7 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "testing/gtest/include/gtest/gtest.h" namespace safe_browsing {
diff --git a/chrome/browser/safe_browsing/incident_reporting/blacklist_load_analyzer_win.cc b/chrome/browser/safe_browsing/incident_reporting/blacklist_load_analyzer_win.cc index 4349fc84..52be87a0 100644 --- a/chrome/browser/safe_browsing/incident_reporting/blacklist_load_analyzer_win.cc +++ b/chrome/browser/safe_browsing/incident_reporting/blacklist_load_analyzer_win.cc
@@ -22,7 +22,7 @@ #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/common/safe_browsing/binary_feature_extractor.h" #include "chrome_elf/blacklist/blacklist.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" namespace safe_browsing {
diff --git a/chrome/browser/safe_browsing/incident_reporting/blacklist_load_incident.cc b/chrome/browser/safe_browsing/incident_reporting/blacklist_load_incident.cc index c62e2b6f..b757e746 100644 --- a/chrome/browser/safe_browsing/incident_reporting/blacklist_load_incident.cc +++ b/chrome/browser/safe_browsing/incident_reporting/blacklist_load_incident.cc
@@ -6,7 +6,7 @@ #include "base/logging.h" #include "chrome/browser/safe_browsing/incident_reporting/incident_handler_util.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" namespace safe_browsing {
diff --git a/chrome/browser/safe_browsing/incident_reporting/blacklist_load_incident_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/blacklist_load_incident_unittest.cc index cd88c8c..9f92cf4 100644 --- a/chrome/browser/safe_browsing/incident_reporting/blacklist_load_incident_unittest.cc +++ b/chrome/browser/safe_browsing/incident_reporting/blacklist_load_incident_unittest.cc
@@ -8,7 +8,7 @@ #include <utility> #include "base/memory/ptr_util.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "testing/gtest/include/gtest/gtest.h" namespace safe_browsing {
diff --git a/chrome/browser/safe_browsing/incident_reporting/download_metadata_manager.cc b/chrome/browser/safe_browsing/incident_reporting/download_metadata_manager.cc index 53b518d..6c5cd38e 100644 --- a/chrome/browser/safe_browsing/incident_reporting/download_metadata_manager.cc +++ b/chrome/browser/safe_browsing/incident_reporting/download_metadata_manager.cc
@@ -22,7 +22,7 @@ #include "base/sequenced_task_runner.h" #include "base/task_scheduler/post_task.h" #include "base/task_scheduler/task_traits.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/download_item.h"
diff --git a/chrome/browser/safe_browsing/incident_reporting/download_metadata_manager_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/download_metadata_manager_unittest.cc index 23b85b6..ede70704 100644 --- a/chrome/browser/safe_browsing/incident_reporting/download_metadata_manager_unittest.cc +++ b/chrome/browser/safe_browsing/incident_reporting/download_metadata_manager_unittest.cc
@@ -16,7 +16,7 @@ #include "base/run_loop.h" #include "base/sequenced_task_runner.h" #include "chrome/test/base/testing_profile.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/download_manager.h" #include "content/public/test/mock_download_item.h"
diff --git a/chrome/browser/safe_browsing/incident_reporting/environment_data_collection.cc b/chrome/browser/safe_browsing/incident_reporting/environment_data_collection.cc index 06e02ec4..2001009 100644 --- a/chrome/browser/safe_browsing/incident_reporting/environment_data_collection.cc +++ b/chrome/browser/safe_browsing/incident_reporting/environment_data_collection.cc
@@ -11,7 +11,7 @@ #include "base/threading/thread_restrictions.h" #include "build/build_config.h" #include "chrome/common/channel_info.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "components/version_info/version_info.h" namespace safe_browsing {
diff --git a/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win.cc b/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win.cc index ccbd5df..9a7dd8e 100644 --- a/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win.cc +++ b/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win.cc
@@ -26,7 +26,7 @@ #include "chrome/browser/safe_browsing/path_sanitizer.h" #include "chrome/common/safe_browsing/binary_feature_extractor.h" #include "chrome_elf/chrome_elf_constants.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "components/variations/variations_associated_data.h" namespace safe_browsing {
diff --git a/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win_unittest.cc index 2013471..69deb08 100644 --- a/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win_unittest.cc +++ b/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win_unittest.cc
@@ -21,7 +21,7 @@ #include "chrome/browser/safe_browsing/incident_reporting/module_integrity_verifier_win.h" #include "chrome/browser/safe_browsing/path_sanitizer.h" #include "chrome_elf/chrome_elf_constants.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "net/base/winsock_init.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/safe_browsing/incident_reporting/extension_data_collection.cc b/chrome/browser/safe_browsing/incident_reporting/extension_data_collection.cc index d60f976..6471ded 100644 --- a/chrome/browser/safe_browsing/incident_reporting/extension_data_collection.cc +++ b/chrome/browser/safe_browsing/incident_reporting/extension_data_collection.cc
@@ -12,7 +12,7 @@ #include "chrome/browser/extensions/install_signer.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_prefs_factory.h" #include "extensions/browser/extension_registry.h"
diff --git a/chrome/browser/safe_browsing/incident_reporting/extension_data_collection_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/extension_data_collection_unittest.cc index 8378b6c..cfd373e 100644 --- a/chrome/browser/safe_browsing/incident_reporting/extension_data_collection_unittest.cc +++ b/chrome/browser/safe_browsing/incident_reporting/extension_data_collection_unittest.cc
@@ -21,7 +21,7 @@ #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" #include "components/safe_browsing/common/safe_browsing_prefs.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "components/sync_preferences/testing_pref_service_syncable.h" #include "content/public/test/test_browser_thread_bundle.h" #include "content/public/test/test_utils.h"
diff --git a/chrome/browser/safe_browsing/incident_reporting/incident.cc b/chrome/browser/safe_browsing/incident_reporting/incident.cc index 21d0b1b8..6c9bfc1 100644 --- a/chrome/browser/safe_browsing/incident_reporting/incident.cc +++ b/chrome/browser/safe_browsing/incident_reporting/incident.cc
@@ -8,7 +8,7 @@ #include "base/logging.h" #include "base/time/time.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" namespace safe_browsing {
diff --git a/chrome/browser/safe_browsing/incident_reporting/incident_report_uploader_impl.cc b/chrome/browser/safe_browsing/incident_reporting/incident_report_uploader_impl.cc index 358e0f32..5b344d2 100644 --- a/chrome/browser/safe_browsing/incident_reporting/incident_report_uploader_impl.cc +++ b/chrome/browser/safe_browsing/incident_reporting/incident_report_uploader_impl.cc
@@ -8,7 +8,7 @@ #include "base/metrics/histogram_macros.h" #include "components/data_use_measurement/core/data_use_user_data.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "google_apis/google_api_keys.h" #include "net/base/escape.h" #include "net/base/load_flags.h"
diff --git a/chrome/browser/safe_browsing/incident_reporting/incident_report_uploader_impl_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/incident_report_uploader_impl_unittest.cc index f50fdc44..6639f0d 100644 --- a/chrome/browser/safe_browsing/incident_reporting/incident_report_uploader_impl_unittest.cc +++ b/chrome/browser/safe_browsing/incident_reporting/incident_report_uploader_impl_unittest.cc
@@ -8,7 +8,7 @@ #include <utility> #include "base/test/test_simple_task_runner.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "net/base/load_flags.h" #include "net/http/http_status_code.h" #include "net/url_request/test_url_fetcher_factory.h"
diff --git a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc index e95b976..b794818 100644 --- a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc +++ b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc
@@ -37,7 +37,7 @@ #include "chrome/common/pref_names.h" #include "components/prefs/pref_service.h" #include "components/safe_browsing/common/safe_browsing_prefs.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "components/safe_browsing_db/database_manager.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_service.h"
diff --git a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service_unittest.cc index 9d4d540..4f0c73fb 100644 --- a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service_unittest.cc +++ b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service_unittest.cc
@@ -35,7 +35,7 @@ #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" #include "components/safe_browsing/common/safe_browsing_prefs.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "components/sync_preferences/testing_pref_service_syncable.h" #include "content/public/test/test_browser_thread_bundle.h" #include "extensions/browser/quota_service.h"
diff --git a/chrome/browser/safe_browsing/incident_reporting/last_download_finder.cc b/chrome/browser/safe_browsing/incident_reporting/last_download_finder.cc index 96d6612a..5d36b8b 100644 --- a/chrome/browser/safe_browsing/incident_reporting/last_download_finder.cc +++ b/chrome/browser/safe_browsing/incident_reporting/last_download_finder.cc
@@ -28,7 +28,7 @@ #include "components/history/core/browser/download_constants.h" #include "components/history/core/browser/history_service.h" #include "components/prefs/pref_service.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_source.h"
diff --git a/chrome/browser/safe_browsing/incident_reporting/last_download_finder_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/last_download_finder_unittest.cc index d3cf2fd1e..8b031fbe 100644 --- a/chrome/browser/safe_browsing/incident_reporting/last_download_finder_unittest.cc +++ b/chrome/browser/safe_browsing/incident_reporting/last_download_finder_unittest.cc
@@ -44,7 +44,7 @@ #include "components/history/core/browser/history_database_params.h" #include "components/history/core/browser/history_service.h" #include "components/safe_browsing/common/safe_browsing_prefs.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "components/sync_preferences/testing_pref_service_syncable.h" #include "content/public/test/test_browser_thread_bundle.h" #include "content/public/test/test_utils.h"
diff --git a/chrome/browser/safe_browsing/incident_reporting/module_integrity_verifier_win.cc b/chrome/browser/safe_browsing/incident_reporting/module_integrity_verifier_win.cc index c1d99e9..7e24fcc 100644 --- a/chrome/browser/safe_browsing/incident_reporting/module_integrity_verifier_win.cc +++ b/chrome/browser/safe_browsing/incident_reporting/module_integrity_verifier_win.cc
@@ -17,7 +17,7 @@ #include "base/scoped_native_library.h" #include "base/strings/utf_string_conversions.h" #include "base/win/pe_image.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" namespace safe_browsing {
diff --git a/chrome/browser/safe_browsing/incident_reporting/module_integrity_verifier_win_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/module_integrity_verifier_win_unittest.cc index 9d91af9a..452c520 100644 --- a/chrome/browser/safe_browsing/incident_reporting/module_integrity_verifier_win_unittest.cc +++ b/chrome/browser/safe_browsing/incident_reporting/module_integrity_verifier_win_unittest.cc
@@ -21,7 +21,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/win/pe_image.h" #include "chrome/browser/safe_browsing/incident_reporting/module_integrity_unittest_util_win.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "testing/gtest/include/gtest/gtest.h" namespace safe_browsing {
diff --git a/chrome/browser/safe_browsing/incident_reporting/module_load_analyzer_win.cc b/chrome/browser/safe_browsing/incident_reporting/module_load_analyzer_win.cc index eea5a41..de02bf8 100644 --- a/chrome/browser/safe_browsing/incident_reporting/module_load_analyzer_win.cc +++ b/chrome/browser/safe_browsing/incident_reporting/module_load_analyzer_win.cc
@@ -22,7 +22,7 @@ #include "chrome/browser/safe_browsing/incident_reporting/suspicious_module_incident.h" #include "chrome/browser/safe_browsing/path_sanitizer.h" #include "chrome/common/safe_browsing/binary_feature_extractor.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "content/public/browser/browser_thread.h" #if defined(SAFE_BROWSING_DB_LOCAL)
diff --git a/chrome/browser/safe_browsing/incident_reporting/module_load_analyzer_win_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/module_load_analyzer_win_unittest.cc index 344194f2..56998c2 100644 --- a/chrome/browser/safe_browsing/incident_reporting/module_load_analyzer_win_unittest.cc +++ b/chrome/browser/safe_browsing/incident_reporting/module_load_analyzer_win_unittest.cc
@@ -15,7 +15,7 @@ #include "chrome/browser/safe_browsing/incident_reporting/incident.h" #include "chrome/browser/safe_browsing/incident_reporting/incident_receiver.h" #include "chrome/browser/safe_browsing/incident_reporting/mock_incident_receiver.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "components/safe_browsing_db/database_manager.h" #include "components/safe_browsing_db/test_database_manager.h" #include "content/public/test/test_browser_thread_bundle.h"
diff --git a/chrome/browser/safe_browsing/incident_reporting/preference_validation_delegate.cc b/chrome/browser/safe_browsing/incident_reporting/preference_validation_delegate.cc index d871351..6bd74eb 100644 --- a/chrome/browser/safe_browsing/incident_reporting/preference_validation_delegate.cc +++ b/chrome/browser/safe_browsing/incident_reporting/preference_validation_delegate.cc
@@ -12,7 +12,7 @@ #include "base/memory/ptr_util.h" #include "chrome/browser/safe_browsing/incident_reporting/incident_receiver.h" #include "chrome/browser/safe_browsing/incident_reporting/tracked_preference_incident.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "services/preferences/public/interfaces/tracked_preference_validation_delegate.mojom.h" namespace safe_browsing {
diff --git a/chrome/browser/safe_browsing/incident_reporting/preference_validation_delegate_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/preference_validation_delegate_unittest.cc index 0aa2d823..0ea185a6 100644 --- a/chrome/browser/safe_browsing/incident_reporting/preference_validation_delegate_unittest.cc +++ b/chrome/browser/safe_browsing/incident_reporting/preference_validation_delegate_unittest.cc
@@ -17,7 +17,7 @@ #include "base/values.h" #include "chrome/browser/safe_browsing/incident_reporting/incident.h" #include "chrome/browser/safe_browsing/incident_reporting/mock_incident_receiver.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/safe_browsing/incident_reporting/resource_request_detector.cc b/chrome/browser/safe_browsing/incident_reporting/resource_request_detector.cc index 30fed1f..9885c5f 100644 --- a/chrome/browser/safe_browsing/incident_reporting/resource_request_detector.cc +++ b/chrome/browser/safe_browsing/incident_reporting/resource_request_detector.cc
@@ -10,7 +10,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/safe_browsing/incident_reporting/incident_receiver.h" #include "chrome/browser/safe_browsing/incident_reporting/resource_request_incident.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h"
diff --git a/chrome/browser/safe_browsing/incident_reporting/resource_request_detector_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/resource_request_detector_unittest.cc index e52c8132..83431bf 100644 --- a/chrome/browser/safe_browsing/incident_reporting/resource_request_detector_unittest.cc +++ b/chrome/browser/safe_browsing/incident_reporting/resource_request_detector_unittest.cc
@@ -12,7 +12,7 @@ #include "chrome/browser/safe_browsing/incident_reporting/incident.h" #include "chrome/browser/safe_browsing/incident_reporting/incident_receiver.h" #include "chrome/browser/safe_browsing/incident_reporting/mock_incident_receiver.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "components/safe_browsing_db/test_database_manager.h" #include "content/public/browser/resource_request_info.h" #include "content/public/common/previews_state.h"
diff --git a/chrome/browser/safe_browsing/incident_reporting/resource_request_incident.cc b/chrome/browser/safe_browsing/incident_reporting/resource_request_incident.cc index 109b499..a08df8f 100644 --- a/chrome/browser/safe_browsing/incident_reporting/resource_request_incident.cc +++ b/chrome/browser/safe_browsing/incident_reporting/resource_request_incident.cc
@@ -6,7 +6,7 @@ #include "base/logging.h" #include "chrome/browser/safe_browsing/incident_reporting/incident_handler_util.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" namespace safe_browsing {
diff --git a/chrome/browser/safe_browsing/incident_reporting/suspicious_module_incident.cc b/chrome/browser/safe_browsing/incident_reporting/suspicious_module_incident.cc index 2f5589e..78fcd0a7 100644 --- a/chrome/browser/safe_browsing/incident_reporting/suspicious_module_incident.cc +++ b/chrome/browser/safe_browsing/incident_reporting/suspicious_module_incident.cc
@@ -6,7 +6,7 @@ #include "base/logging.h" #include "chrome/browser/safe_browsing/incident_reporting/incident_handler_util.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" namespace safe_browsing {
diff --git a/chrome/browser/safe_browsing/incident_reporting/suspicious_module_incident_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/suspicious_module_incident_unittest.cc index 27450a5..04b050b 100644 --- a/chrome/browser/safe_browsing/incident_reporting/suspicious_module_incident_unittest.cc +++ b/chrome/browser/safe_browsing/incident_reporting/suspicious_module_incident_unittest.cc
@@ -8,7 +8,7 @@ #include <utility> #include "base/memory/ptr_util.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "testing/gtest/include/gtest/gtest.h" namespace safe_browsing {
diff --git a/chrome/browser/safe_browsing/incident_reporting/tracked_preference_incident.cc b/chrome/browser/safe_browsing/incident_reporting/tracked_preference_incident.cc index bc999fe..63ad14c 100644 --- a/chrome/browser/safe_browsing/incident_reporting/tracked_preference_incident.cc +++ b/chrome/browser/safe_browsing/incident_reporting/tracked_preference_incident.cc
@@ -6,7 +6,7 @@ #include "base/logging.h" #include "chrome/browser/safe_browsing/incident_reporting/incident_handler_util.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" namespace safe_browsing {
diff --git a/chrome/browser/safe_browsing/incident_reporting/tracked_preference_incident_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/tracked_preference_incident_unittest.cc index c5a9e33..1ad07e0b 100644 --- a/chrome/browser/safe_browsing/incident_reporting/tracked_preference_incident_unittest.cc +++ b/chrome/browser/safe_browsing/incident_reporting/tracked_preference_incident_unittest.cc
@@ -8,7 +8,7 @@ #include <utility> #include "base/memory/ptr_util.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "testing/gtest/include/gtest/gtest.h" namespace safe_browsing {
diff --git a/chrome/browser/safe_browsing/incident_reporting/variations_seed_signature_analyzer.cc b/chrome/browser/safe_browsing/incident_reporting/variations_seed_signature_analyzer.cc index c35c1af..842d0d5 100644 --- a/chrome/browser/safe_browsing/incident_reporting/variations_seed_signature_analyzer.cc +++ b/chrome/browser/safe_browsing/incident_reporting/variations_seed_signature_analyzer.cc
@@ -14,7 +14,7 @@ #include "chrome/browser/safe_browsing/incident_reporting/incident_receiver.h" #include "chrome/browser/safe_browsing/incident_reporting/variations_seed_signature_incident.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "components/variations/service/variations_service.h" #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/safe_browsing/incident_reporting/variations_seed_signature_incident.cc b/chrome/browser/safe_browsing/incident_reporting/variations_seed_signature_incident.cc index abd66c1..f358d0f 100644 --- a/chrome/browser/safe_browsing/incident_reporting/variations_seed_signature_incident.cc +++ b/chrome/browser/safe_browsing/incident_reporting/variations_seed_signature_incident.cc
@@ -6,7 +6,7 @@ #include "base/logging.h" #include "chrome/browser/safe_browsing/incident_reporting/incident_handler_util.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" namespace safe_browsing {
diff --git a/chrome/browser/safe_browsing/incident_reporting/variations_seed_signature_incident_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/variations_seed_signature_incident_unittest.cc index 07b0261..46a3f6a 100644 --- a/chrome/browser/safe_browsing/incident_reporting/variations_seed_signature_incident_unittest.cc +++ b/chrome/browser/safe_browsing/incident_reporting/variations_seed_signature_incident_unittest.cc
@@ -8,7 +8,7 @@ #include <utility> #include "base/memory/ptr_util.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "testing/gtest/include/gtest/gtest.h" namespace safe_browsing {
diff --git a/chrome/browser/safe_browsing/notification_image_reporter.cc b/chrome/browser/safe_browsing/notification_image_reporter.cc index ae292b09..dcca406 100644 --- a/chrome/browser/safe_browsing/notification_image_reporter.cc +++ b/chrome/browser/safe_browsing/notification_image_reporter.cc
@@ -19,7 +19,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "components/safe_browsing/common/safe_browsing_prefs.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "components/safe_browsing_db/database_manager.h" #include "components/variations/variations_associated_data.h" #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/safe_browsing/notification_image_reporter_unittest.cc b/chrome/browser/safe_browsing/notification_image_reporter_unittest.cc index 5a3774af..5cdb126 100644 --- a/chrome/browser/safe_browsing/notification_image_reporter_unittest.cc +++ b/chrome/browser/safe_browsing/notification_image_reporter_unittest.cc
@@ -14,7 +14,7 @@ #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "components/safe_browsing/common/safe_browsing_prefs.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "components/safe_browsing_db/test_database_manager.h" #include "content/public/browser/browser_thread.h" #include "content/public/test/test_browser_thread_bundle.h"
diff --git a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.h b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.h index 473cb52..9767f57 100644 --- a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.h +++ b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.h
@@ -8,7 +8,7 @@ #include <deque> #include "base/feature_list.h" #include "base/supports_user_data.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "content/public/browser/web_contents_observer.h" #include "third_party/protobuf/src/google/protobuf/repeated_field.h" #include "url/gurl.h"
diff --git a/chrome/browser/safe_browsing/signature_evaluator_mac.mm b/chrome/browser/safe_browsing/signature_evaluator_mac.mm index 9ffcb66..a3d3968 100644 --- a/chrome/browser/safe_browsing/signature_evaluator_mac.mm +++ b/chrome/browser/safe_browsing/signature_evaluator_mac.mm
@@ -19,7 +19,7 @@ #include "base/strings/sys_string_conversions.h" #include "chrome/common/safe_browsing/binary_feature_extractor.h" #include "chrome/common/safe_browsing/mach_o_image_reader_mac.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" namespace safe_browsing {
diff --git a/chrome/browser/safe_browsing/signature_evaluator_mac_unittest.cc b/chrome/browser/safe_browsing/signature_evaluator_mac_unittest.cc index 3041104..aa3f72d 100644 --- a/chrome/browser/safe_browsing/signature_evaluator_mac_unittest.cc +++ b/chrome/browser/safe_browsing/signature_evaluator_mac_unittest.cc
@@ -22,7 +22,7 @@ #include "chrome/browser/safe_browsing/incident_reporting/incident.h" #include "chrome/browser/safe_browsing/incident_reporting/mock_incident_receiver.h" #include "chrome/common/chrome_paths.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "testing/gmock/include/gmock/gmock-matchers.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/safe_browsing/threat_details_unittest.cc b/chrome/browser/safe_browsing/threat_details_unittest.cc index d7da5a4..8788a47 100644 --- a/chrome/browser/safe_browsing/threat_details_unittest.cc +++ b/chrome/browser/safe_browsing/threat_details_unittest.cc
@@ -23,7 +23,7 @@ #include "components/safe_browsing/browser/threat_details.h" #include "components/safe_browsing/browser/threat_details_history.h" #include "components/safe_browsing/common/safebrowsing_messages.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" #include "content/public/test/test_renderer_host.h"
diff --git a/chrome/browser/ssl/security_state_tab_helper_browser_tests.cc b/chrome/browser/ssl/security_state_tab_helper_browser_tests.cc index c3588664..29f1274 100644 --- a/chrome/browser/ssl/security_state_tab_helper_browser_tests.cc +++ b/chrome/browser/ssl/security_state_tab_helper_browser_tests.cc
@@ -160,7 +160,7 @@ ->GetSSL() .certificate.get(); EXPECT_TRUE(cert->Equals(expected_cert)); - EXPECT_TRUE(expired_explanation.insecure_explanations[0].has_certificate); + EXPECT_TRUE(!!expired_explanation.insecure_explanations[0].certificate); } // Checks that the given |explanation| contains an appropriate @@ -184,7 +184,7 @@ ->GetSSL() .certificate.get(); EXPECT_TRUE(cert->Equals(expected_cert)); - EXPECT_TRUE(explanation.has_certificate); + EXPECT_TRUE(!!explanation.certificate); } // Checks that the given |explanation| contains an appropriate
diff --git a/chrome/browser/sync/DEPS b/chrome/browser/sync/DEPS index a2eaea2..88800dc 100644 --- a/chrome/browser/sync/DEPS +++ b/chrome/browser/sync/DEPS
@@ -5,14 +5,3 @@ "+components/sync_wifi", "+google/cacheinvalidation", ] -specific_include_rules = { - "sync_error_notifier_ash\.cc": [ - "+ash/system/system_notifier.h", - ], - "sync_error_notifier_factory_ash\.cc": [ - "+ash/shell.h", - ], - ".*_unittest\.cc": [ - "+ash/test/ash_test_base.h", - ] -}
diff --git a/chrome/browser/sync/sync_error_notifier_ash.cc b/chrome/browser/sync/sync_error_notifier_ash.cc index 5ca2dce0b..e6c2929 100644 --- a/chrome/browser/sync/sync_error_notifier_ash.cc +++ b/chrome/browser/sync/sync_error_notifier_ash.cc
@@ -4,10 +4,11 @@ #include "chrome/browser/sync/sync_error_notifier_ash.h" -#include "ash/system/system_notifier.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/chromeos/login/user_flow.h" +#include "chrome/browser/chromeos/login/users/chrome_user_manager.h" #include "chrome/browser/notifications/notification.h" #include "chrome/browser/notifications/notification_ui_manager.h" #include "chrome/browser/profiles/profile.h" @@ -20,17 +21,12 @@ #include "chrome/grit/generated_resources.h" #include "chrome/grit/theme_resources.h" #include "components/signin/core/account_id/account_id.h" +#include "components/user_manager/user_manager.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/message_center/notification.h" #include "ui/message_center/notification_delegate.h" -#if defined(OS_CHROMEOS) -#include "chrome/browser/chromeos/login/user_flow.h" -#include "chrome/browser/chromeos/login/users/chrome_user_manager.h" -#include "components/user_manager/user_manager.h" -#endif - namespace { const char kProfileSyncNotificationId[] = "chrome://settings/sync/"; @@ -137,7 +133,6 @@ return; } -#if defined(OS_CHROMEOS) if (user_manager::UserManager::IsInitialized()) { chromeos::UserFlow* user_flow = chromeos::ChromeUserManager::Get()->GetCurrentUserFlow(); @@ -148,7 +143,6 @@ if (!user_flow->ShouldLaunchBrowser()) return; } -#endif // Error state just got triggered. There shouldn't be previous notification. // Let's display one.
diff --git a/chrome/browser/sync/sync_error_notifier_ash_unittest.cc b/chrome/browser/sync/sync_error_notifier_ash_unittest.cc index 41d7a43..4b34e58 100644 --- a/chrome/browser/sync/sync_error_notifier_ash_unittest.cc +++ b/chrome/browser/sync/sync_error_notifier_ash_unittest.cc
@@ -8,7 +8,6 @@ #include <memory> -#include "ash/test/ash_test_base.h" #include "base/memory/ptr_util.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/login/users/mock_user_manager.h" @@ -19,6 +18,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/webui/signin/login_ui_service.h" #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" +#include "chrome/test/base/browser_with_test_window_test.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" @@ -32,8 +32,6 @@ using ::testing::ReturnRef; using ::testing::_; -namespace ash { - namespace { const char kTestAccountId[] = "testuser@test.com"; @@ -67,7 +65,7 @@ return base::MakeUnique<FakeLoginUIService>(); } -class SyncErrorNotifierTest : public AshTestBase { +class SyncErrorNotifierTest : public BrowserWithTestWindowTest { public: SyncErrorNotifierTest() {} ~SyncErrorNotifierTest() override {} @@ -75,7 +73,7 @@ void SetUp() override { DCHECK(TestingBrowserProcess::GetGlobal()); - AshTestBase::SetUp(); + BrowserWithTestWindowTest::SetUp(); profile_manager_ = base::MakeUnique<TestingProfileManager>( TestingBrowserProcess::GetGlobal()); @@ -104,7 +102,7 @@ service_.reset(); profile_manager_.reset(); - AshTestBase::TearDown(); + BrowserWithTestWindowTest::TearDown(); } protected: @@ -148,8 +146,6 @@ DISALLOW_COPY_AND_ASSIGN(SyncErrorNotifierTest); }; -} // namespace - // Test that SyncErrorNotifier shows an notification if a passphrase is // required. TEST_F(SyncErrorNotifierTest, PassphraseNotification) { @@ -209,4 +205,4 @@ } } -} // namespace ash +} // namespace
diff --git a/chrome/browser/sync/sync_error_notifier_factory_ash.cc b/chrome/browser/sync/sync_error_notifier_factory_ash.cc index 2af253c..2ab7418 100644 --- a/chrome/browser/sync/sync_error_notifier_factory_ash.cc +++ b/chrome/browser/sync/sync_error_notifier_factory_ash.cc
@@ -4,7 +4,6 @@ #include "chrome/browser/sync/sync_error_notifier_factory_ash.h" -#include "ash/shell.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/profile_sync_service_factory.h" @@ -35,9 +34,6 @@ KeyedService* SyncErrorNotifierFactory::BuildServiceInstanceFor( content::BrowserContext* context) const { - if (!ash::Shell::HasInstance()) - return nullptr; - Profile* profile = static_cast<Profile*>(context); browser_sync::ProfileSyncService* profile_sync_service = ProfileSyncServiceFactory::GetForProfile(profile);
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 996ebba..2c7ae1f4 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -3056,6 +3056,8 @@ "cocoa/restart_browser.mm", "cocoa/screen_capture_notification_ui_cocoa.h", "cocoa/screen_capture_notification_ui_cocoa.mm", + "cocoa/separate_fullscreen_window.h", + "cocoa/separate_fullscreen_window.mm", "cocoa/session_crashed_bubble.mm", "cocoa/simple_message_box_bridge_views.mm", "cocoa/simple_message_box_cocoa.h",
diff --git a/chrome/browser/ui/app_list/search/search_controller_factory.cc b/chrome/browser/ui/app_list/search/search_controller_factory.cc index 8bd8e2c..e1792c0 100644 --- a/chrome/browser/ui/app_list/search/search_controller_factory.cc +++ b/chrome/browser/ui/app_list/search/search_controller_factory.cc
@@ -78,17 +78,18 @@ model->search_box(), model->results(), HistoryFactory::GetForBrowserContext(profile)); - // Add mixer groups. There are three main groups: apps, webstore and - // omnibox. Each group has a "soft" maximum number of results. However, if + // Add mixer groups. There are four main groups: answer card, apps, webstore + // and omnibox. Each group has a "soft" maximum number of results. However, if // a query turns up very few results, the mixer may take more than this // maximum from a particular group. - // Multiplier 100 is used because the answer card is designed to be the most - // relevant result and must be on the top of the result list. - size_t answer_card_group_id = controller->AddGroup(1, 100.0); - size_t apps_group_id = controller->AddGroup(kMaxAppsGroupResults, 1.0); - size_t omnibox_group_id = controller->AddGroup(kMaxOmniboxResults, 1.0); - size_t webstore_group_id = controller->AddGroup(kMaxWebstoreResults, 0.4); + size_t answer_card_group_id = controller->AddGroup(1, 1.0, 10.0); + size_t apps_group_id = + controller->AddGroup(kMaxAppsGroupResults, 1.0, + features::IsFullscreenAppListEnabled() ? 5.0 : 0.0); + size_t omnibox_group_id = controller->AddGroup(kMaxOmniboxResults, 1.0, 0.0); + size_t webstore_group_id = + controller->AddGroup(kMaxWebstoreResults, 0.4, 0.0); // Add search providers. controller->AddProvider( @@ -112,7 +113,7 @@ } if (IsSuggestionsSearchProviderEnabled()) { size_t suggestions_group_id = - controller->AddGroup(kMaxSuggestionsResults, 1.0); + controller->AddGroup(kMaxSuggestionsResults, 1.0, 0.0); controller->AddProvider( suggestions_group_id, base::MakeUnique<SuggestionsSearchProvider>(profile, list_controller)); @@ -123,7 +124,7 @@ if (app_list::switches::IsDriveSearchInChromeLauncherEnabled() && !profile->IsGuestSession()) { size_t search_api_group_id = - controller->AddGroup(kMaxLauncherSearchResults, 1.0); + controller->AddGroup(kMaxLauncherSearchResults, 1.0, 0.0); controller->AddProvider(search_api_group_id, base::MakeUnique<LauncherSearchProvider>(profile)); } @@ -131,7 +132,7 @@ #if defined(OS_CHROMEOS) if (features::IsPlayStoreAppSearchEnabled()) { size_t playstore_api_group_id = - controller->AddGroup(kMaxPlayStoreResults, 1.0); + controller->AddGroup(kMaxPlayStoreResults, 1.0, 0.0); controller->AddProvider( playstore_api_group_id, base::MakeUnique<ArcPlayStoreSearchProvider>(kMaxPlayStoreResults,
diff --git a/chrome/browser/ui/ash/app_list/app_list_presenter_service.cc b/chrome/browser/ui/ash/app_list/app_list_presenter_service.cc index a5ba98b..c08458dc 100644 --- a/chrome/browser/ui/ash/app_list/app_list_presenter_service.cc +++ b/chrome/browser/ui/ash/app_list/app_list_presenter_service.cc
@@ -9,13 +9,20 @@ #include "ash/public/interfaces/constants.mojom.h" #include "chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.h" #include "chrome/browser/ui/ash/app_list/app_list_service_ash.h" +#include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" #include "content/public/common/service_manager_connection.h" #include "services/service_manager/public/cpp/connector.h" #include "ui/app_list/presenter/app_list_presenter_impl.h" #include "ui/gfx/geometry/rect.h" -AppListPresenterService::AppListPresenterService(Profile* profile) - : profile_(profile), binding_(this) { +AppListPresenterService::AppListPresenterService() : binding_(this) {} + +AppListPresenterService::~AppListPresenterService() {} + +void AppListPresenterService::Init() { + if (binding_.is_bound()) + return; + content::ServiceManagerConnection* connection = content::ServiceManagerConnection::GetForProcess(); if (connection && connection->GetConnector()) { @@ -32,8 +39,6 @@ } } -AppListPresenterService::~AppListPresenterService() {} - void AppListPresenterService::Show(int64_t display_id) { GetPresenter()->Show(display_id); } @@ -48,7 +53,8 @@ void AppListPresenterService::StartVoiceInteractionSession() { auto* service = - arc::ArcVoiceInteractionFrameworkService::GetForBrowserContext(profile_); + arc::ArcVoiceInteractionFrameworkService::GetForBrowserContext( + ChromeLauncherController::instance()->profile()); if (service) service->StartSessionFromUserInteraction(gfx::Rect()); }
diff --git a/chrome/browser/ui/ash/app_list/app_list_presenter_service.h b/chrome/browser/ui/ash/app_list/app_list_presenter_service.h index 759db7d..2151a32 100644 --- a/chrome/browser/ui/ash/app_list/app_list_presenter_service.h +++ b/chrome/browser/ui/ash/app_list/app_list_presenter_service.h
@@ -9,8 +9,6 @@ #include "mojo/public/cpp/bindings/binding.h" #include "ui/app_list/presenter/app_list_presenter.mojom.h" -class Profile; - namespace app_list { class AppListPresenterImpl; } @@ -18,9 +16,12 @@ // A service providing the Mojo interface to manipulate the App List. class AppListPresenterService : public app_list::mojom::AppListPresenter { public: - explicit AppListPresenterService(Profile* profile); + AppListPresenterService(); ~AppListPresenterService() override; + // Initialize service and mojo bindings. + void Init(); + // app_list::mojom::AppListPresenter: void Show(int64_t display_id) override; void Dismiss() override; @@ -33,7 +34,6 @@ private: app_list::AppListPresenterImpl* GetPresenter(); - Profile* const profile_; // Owned by ProfileManager. mojo::Binding<app_list::mojom::AppListPresenter> binding_; DISALLOW_COPY_AND_ASSIGN(AppListPresenterService);
diff --git a/chrome/browser/ui/ash/app_list/app_list_service_ash.cc b/chrome/browser/ui/ash/app_list/app_list_service_ash.cc index 2eaaee6..365f09f 100644 --- a/chrome/browser/ui/ash/app_list/app_list_service_ash.cc +++ b/chrome/browser/ui/ash/app_list/app_list_service_ash.cc
@@ -100,6 +100,7 @@ base::MakeUnique<app_list::AppListPresenterImpl>(std::move(factory)); controller_delegate_ = base::MakeUnique<AppListControllerDelegateAsh>(app_list_presenter_.get()); + app_list_presenter_service_ = base::MakeUnique<AppListPresenterService>(); } AppListServiceAsh::~AppListServiceAsh() {} @@ -109,11 +110,7 @@ } void AppListServiceAsh::Init(Profile* initial_profile) { - // The AppListPresenterService ctor calls AppListServiceAsh::GetInstance(), - // which isn't available in the AppListServiceAsh constructor, so init here. - // This establishes the mojo connections between the app list and presenter. - app_list_presenter_service_ = - base::MakeUnique<AppListPresenterService>(initial_profile); + app_list_presenter_service_->Init(); // Ensure the StartPageService is created here. This early initialization is // necessary to allow the WebContents to load before the app list is shown.
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index f84a6a1..ba9d08f 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -1337,15 +1337,6 @@ security_style_explanations); } -void Browser::ShowCertificateViewerInDevTools( - content::WebContents* web_contents, - scoped_refptr<net::X509Certificate> certificate) { - DevToolsWindow* devtools_window = - DevToolsWindow::GetInstanceForInspectedWebContents(web_contents); - if (devtools_window) - devtools_window->ShowCertificateViewer(certificate); -} - std::unique_ptr<content::BluetoothChooser> Browser::RunBluetoothChooser( content::RenderFrameHost* frame, const content::BluetoothChooser::EventHandler& event_handler) {
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h index 9825121..df8a86b 100644 --- a/chrome/browser/ui/browser.h +++ b/chrome/browser/ui/browser.h
@@ -491,9 +491,6 @@ blink::WebSecurityStyle GetSecurityStyle( content::WebContents* web_contents, content::SecurityStyleExplanations* security_style_explanations) override; - void ShowCertificateViewerInDevTools( - content::WebContents* web_contents, - scoped_refptr<net::X509Certificate> certificate) override; std::unique_ptr<content::BluetoothChooser> RunBluetoothChooser( content::RenderFrameHost* frame, const content::BluetoothChooser::EventHandler& event_handler) override;
diff --git a/chrome/browser/ui/browser_command_controller_interactive_browsertest.cc b/chrome/browser/ui/browser_command_controller_interactive_browsertest.cc index 9bec796..86fef1f 100644 --- a/chrome/browser/ui/browser_command_controller_interactive_browsertest.cc +++ b/chrome/browser/ui/browser_command_controller_interactive_browsertest.cc
@@ -14,10 +14,10 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/ui/tabs/tab_strip_model_observer.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/interactive_test_utils.h" #include "content/public/browser/notification_service.h" +#include "content/public/common/browser_side_navigation_policy.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_utils.h" #include "ui/events/keycodes/dom/keycode_converter.h" @@ -31,6 +31,7 @@ #endif namespace { + // The html file to receive key events, prevent defaults and export all the // events with "getKeyEventReport()" function. It has two magic keys: pressing // "S" to enter fullscreen mode; pressing "X" to indicate the end of all the @@ -53,8 +54,8 @@ ~BrowserCommandControllerInteractiveTest() override = default; protected: - // Starts the test page and waits for it to be loaded. - void StartTestPage(); + // Starts |kFullscreenKeyboardLockHTML| in a new tab and waits for load. + void StartFullscreenLockPage(); // Sends a control or command + |key| shortcut to the focused window. Shift // modifier will be added if |shift| is true. @@ -78,13 +79,91 @@ // for the operation to take effect. void SendEscapeAndWaitForExitingFullscreen(); - // Sends a set of preventable shortcuts to the web page. - void SendShortcutsInFullscreen(); + // Sends a set of preventable shortcuts to the web page and expects them to be + // prevented. + void SendShortcutsAndExpectPrevented(); + + // Sends a set of preventable shortcuts to the web page and expects them to + // not be prevented. If |js_fullscreen| is true, the test will use + // SendJsFullscreenShortcutAndWait() to trigger the fullscreen mode. Otherwise + // SendFullscreenShortcutAndWait() will be used. + void SendShortcutsAndExpectNotPrevented(bool js_fullscreen); // Sends a magic KeyX to the focused window to stop the test case, receives // the result and verifies if it is equal to |expected_result_|. void FinishTestAndVerifyResult(); + // Returns whether the active tab is in html fullscreen mode. + bool IsActiveTabFullscreen() const { + auto* contents = GetActiveWebContents(); + return contents->GetDelegate()->IsFullscreenForTabOrPending(contents); + } + + // Returns whether the GetActiveBrowser() is in browser fullscreen mode. + bool IsInBrowserFullscreen() const { + return GetActiveBrowser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->IsFullscreenForBrowser(); + } + + content::WebContents* GetActiveWebContents() const { + return GetActiveBrowser()->tab_strip_model()->GetActiveWebContents(); + } + + // Gets the current active tab index. + int GetActiveTabIndex() const { + return GetActiveBrowser()->tab_strip_model()->active_index(); + } + + // Gets the count of tabs in current browser. + int GetTabCount() const { + return GetActiveBrowser()->tab_strip_model()->count(); + } + + // Gets the count of browser instances. + size_t GetBrowserCount() const { + return BrowserList::GetInstance()->size(); + } + + // Gets the last active Browser instance. + Browser* GetActiveBrowser() const { + return BrowserList::GetInstance()->GetLastActive(); + } + + // Ensures GetActiveBrowser() is focused. + void FocusOnLastActiveBrowser() { + ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront( + GetActiveBrowser())); + } + + // Waits until the count of Browser instances becomes |expected|. + void WaitForBrowserCount(size_t expected) { + while (GetBrowserCount() != expected) + content::RunAllPendingInMessageLoop(); + } + + // Waits until the count of the tabs in active Browser instance becomes + // |expected|. + void WaitForTabCount(int expected) { + while (GetTabCount() != expected) + content::RunAllPendingInMessageLoop(); + } + + // Waits until the index of active tab in active Browser instance becomes + // |expected|. + void WaitForActiveTabIndex(int expected) { + while (GetActiveTabIndex() != expected) + content::RunAllPendingInMessageLoop(); + } + + // Waits until the index of active tab in active Browser instance is not + // |expected|. + void WaitForInactiveTabIndex(int expected) { + while (GetActiveTabIndex() == expected) + content::RunAllPendingInMessageLoop(); + } + private: void SetUpOnMainThread() override; @@ -95,19 +174,21 @@ DISALLOW_COPY_AND_ASSIGN(BrowserCommandControllerInteractiveTest); }; -void BrowserCommandControllerInteractiveTest::StartTestPage() { - ASSERT_TRUE(embedded_test_server()->Start()); +void BrowserCommandControllerInteractiveTest::StartFullscreenLockPage() { // Ensures the initial states. - ASSERT_EQ(1, browser()->tab_strip_model()->count()); - ASSERT_EQ(0, browser()->tab_strip_model()->active_index()); - ASSERT_EQ(1U, BrowserList::GetInstance()->size()); + ASSERT_EQ(1, GetTabCount()); + ASSERT_EQ(0, GetActiveTabIndex()); + ASSERT_EQ(1U, GetBrowserCount()); // Add a second tab for counting and focus purposes. AddTabAtIndex(1, GURL(url::kAboutBlankURL), ui::PAGE_TRANSITION_LINK); - ASSERT_EQ(2, browser()->tab_strip_model()->count()); - ASSERT_EQ(1U, BrowserList::GetInstance()->size()); + ASSERT_EQ(2, GetTabCount()); + ASSERT_EQ(1U, GetBrowserCount()); + if (!embedded_test_server()->Started()) + ASSERT_TRUE(embedded_test_server()->Start()); ui_test_utils::NavigateToURLWithDisposition( - browser(), embedded_test_server()->GetURL(kFullscreenKeyboardLockHTML), + GetActiveBrowser(), + embedded_test_server()->GetURL(kFullscreenKeyboardLockHTML), WindowOpenDisposition::CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); } @@ -122,8 +203,9 @@ const bool control_modifier = true; const bool command_modifier = false; #endif - ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), key, control_modifier, - shift, false, command_modifier)); + ASSERT_TRUE(ui_test_utils::SendKeyPressSync( + GetActiveBrowser(), key, control_modifier, shift, false, + command_modifier)); expected_result_ += ui::KeycodeConverter::DomCodeToCodeString( ui::UsLayoutKeyboardCodeToDomCode(key)); @@ -151,15 +233,15 @@ // Enter fullscreen. #if defined(OS_MACOSX) // On MACOSX, Command + Control + F is used. - ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_F, true, - false, false, true)); + ASSERT_TRUE(ui_test_utils::SendKeyPressSync( + GetActiveBrowser(), ui::VKEY_F, true, false, false, true)); #elif defined(OS_CHROMEOS) // A dedicated fullscreen key is used on Chrome OS, so send a fullscreen // command directly instead, to avoid constructing the key press. - ASSERT_TRUE(chrome::ExecuteCommand(browser(), IDC_FULLSCREEN)); + ASSERT_TRUE(chrome::ExecuteCommand(GetActiveBrowser(), IDC_FULLSCREEN)); #else - ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_F11, false, - false, false, false)); + ASSERT_TRUE(ui_test_utils::SendKeyPressSync( + GetActiveBrowser(), ui::VKEY_F11, false, false, false, false)); #endif observer.Wait(); @@ -170,15 +252,16 @@ content::WindowedNotificationObserver observer( chrome::NOTIFICATION_FULLSCREEN_CHANGED, content::NotificationService::AllSources()); - ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_S, false, - false, false, false)); + ASSERT_TRUE(ui_test_utils::SendKeyPressSync( + GetActiveBrowser(), ui::VKEY_S, false, false, false, false)); expected_result_ += "KeyS ctrl:false shift:false alt:false meta:false\n"; observer.Wait(); + ASSERT_TRUE(IsActiveTabFullscreen()); } void BrowserCommandControllerInteractiveTest::SendEscape() { - ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_ESCAPE, false, - false, false, false)); + ASSERT_TRUE(ui_test_utils::SendKeyPressSync( + GetActiveBrowser(), ui::VKEY_ESCAPE, false, false, false, false)); expected_result_ += "Escape ctrl:false shift:false alt:false meta:false\n"; } @@ -187,43 +270,143 @@ content::WindowedNotificationObserver observer( chrome::NOTIFICATION_FULLSCREEN_CHANGED, content::NotificationService::AllSources()); - ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_ESCAPE, false, - false, false, false)); + ASSERT_TRUE(ui_test_utils::SendKeyPressSync( + GetActiveBrowser(), ui::VKEY_ESCAPE, false, false, false, false)); observer.Wait(); + ASSERT_FALSE(IsActiveTabFullscreen()); } -void BrowserCommandControllerInteractiveTest::SendShortcutsInFullscreen() { - const int initial_active_index = browser()->tab_strip_model()->active_index(); - const int initial_tab_count = browser()->tab_strip_model()->count(); - const size_t initial_browser_count = BrowserList::GetInstance()->size(); +void BrowserCommandControllerInteractiveTest:: + SendShortcutsAndExpectPrevented() { + const int initial_active_index = GetActiveTabIndex(); + const int initial_tab_count = GetTabCount(); + const size_t initial_browser_count = GetBrowserCount(); // The tab should not be closed. ASSERT_NO_FATAL_FAILURE(SendShortcut(ui::VKEY_W)); - ASSERT_EQ(initial_tab_count, browser()->tab_strip_model()->count()); + ASSERT_EQ(initial_tab_count, GetTabCount()); // The window should not be closed. ASSERT_NO_FATAL_FAILURE(SendShiftShortcut(ui::VKEY_W)); - ASSERT_EQ(initial_browser_count, BrowserList::GetInstance()->size()); + ASSERT_EQ(initial_browser_count, GetBrowserCount()); // TODO(zijiehe): ChromeOS incorrectly handles these; // see http://crbug.com/737307. #if !defined(OS_CHROMEOS) // A new tab should not be created. ASSERT_NO_FATAL_FAILURE(SendShortcut(ui::VKEY_T)); - ASSERT_EQ(initial_tab_count, browser()->tab_strip_model()->count()); + ASSERT_EQ(initial_tab_count, GetTabCount()); // A new window should not be created. ASSERT_NO_FATAL_FAILURE(SendShortcut(ui::VKEY_N)); - ASSERT_EQ(initial_browser_count, BrowserList::GetInstance()->size()); + ASSERT_EQ(initial_browser_count, GetBrowserCount()); // A new incognito window should not be created. ASSERT_NO_FATAL_FAILURE(SendShiftShortcut(ui::VKEY_N)); - ASSERT_EQ(initial_browser_count, BrowserList::GetInstance()->size()); + ASSERT_EQ(initial_browser_count, GetBrowserCount()); // Last closed tab should not be restored. ASSERT_NO_FATAL_FAILURE(SendShiftShortcut(ui::VKEY_T)); - ASSERT_EQ(initial_tab_count, browser()->tab_strip_model()->count()); + ASSERT_EQ(initial_tab_count, GetTabCount()); #endif // Browser should not switch to the next tab. ASSERT_NO_FATAL_FAILURE(SendShortcut(ui::VKEY_TAB)); - ASSERT_EQ(initial_active_index, browser()->tab_strip_model()->active_index()); + ASSERT_EQ(initial_active_index, GetActiveTabIndex()); // Browser should not switch to the previous tab. ASSERT_NO_FATAL_FAILURE(SendShiftShortcut(ui::VKEY_TAB)); - ASSERT_EQ(initial_active_index, browser()->tab_strip_model()->active_index()); + ASSERT_EQ(initial_active_index, GetActiveTabIndex()); +} + +void BrowserCommandControllerInteractiveTest:: + SendShortcutsAndExpectNotPrevented(bool js_fullscreen) { + const int initial_active_index = GetActiveTabIndex(); + const int initial_tab_count = GetTabCount(); + const size_t initial_browser_count = GetBrowserCount(); + const auto enter_fullscreen = [this, js_fullscreen]() { + ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront( + this->GetActiveBrowser())); + if (js_fullscreen) { + if (!this->IsActiveTabFullscreen()) { + const std::string page = + "<html><head><script>" + "document.addEventListener('keydown', " + " () => { document.body.webkitRequestFullscreen(); });" + "</script></head><body></body></html>"; + ui_test_utils::NavigateToURLWithDisposition( + this->GetActiveBrowser(), + GURL("data:text/html," + page), + WindowOpenDisposition::CURRENT_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); + content::WindowedNotificationObserver observer( + chrome::NOTIFICATION_FULLSCREEN_CHANGED, + content::NotificationService::AllSources()); + ASSERT_NO_FATAL_FAILURE(this->SendJsFullscreenShortcutAndWait()); + observer.Wait(); + ASSERT_TRUE(this->IsActiveTabFullscreen()); + } + } else { + if (!this->IsInBrowserFullscreen()) { + ASSERT_NO_FATAL_FAILURE(this->SendFullscreenShortcutAndWait()); + } + ASSERT_TRUE(this->IsInBrowserFullscreen()); + } + }; + + ASSERT_NO_FATAL_FAILURE(enter_fullscreen()); + + // A new tab should be created and focused. + ASSERT_NO_FATAL_FAILURE(SendShortcut(ui::VKEY_T)); + WaitForTabCount(initial_tab_count + 1); + ASSERT_NE(initial_active_index, GetActiveTabIndex()); + + ASSERT_NO_FATAL_FAILURE(enter_fullscreen()); + + // The newly created tab should be closed. + ASSERT_NO_FATAL_FAILURE(SendShortcut(ui::VKEY_W)); + WaitForTabCount(initial_tab_count); + ASSERT_EQ(initial_active_index, GetActiveTabIndex()); + + ASSERT_NO_FATAL_FAILURE(enter_fullscreen()); + + // A new tab should be created and focused. + ASSERT_NO_FATAL_FAILURE(SendShortcut(ui::VKEY_T)); + WaitForTabCount(initial_tab_count + 1); + ASSERT_NE(initial_active_index, GetActiveTabIndex()); + + ASSERT_NO_FATAL_FAILURE(enter_fullscreen()); + + // The previous tab should be focused. + ASSERT_TRUE(ui_test_utils::SendKeyPressSync( + GetActiveBrowser(), ui::VKEY_TAB, true, true, false, false)); + WaitForActiveTabIndex(initial_active_index); + ASSERT_EQ(initial_active_index, GetActiveTabIndex()); + + ASSERT_NO_FATAL_FAILURE(enter_fullscreen()); + + // The newly created tab should be focused. + ASSERT_TRUE(ui_test_utils::SendKeyPressSync( + GetActiveBrowser(), ui::VKEY_TAB, true, false, false, false)); + WaitForInactiveTabIndex(initial_active_index); + ASSERT_NE(initial_active_index, GetActiveTabIndex()); + + ASSERT_NO_FATAL_FAILURE(enter_fullscreen()); + + // The newly created tab should be closed. + ASSERT_NO_FATAL_FAILURE(SendShortcut(ui::VKEY_W)); + WaitForTabCount(initial_tab_count); + ASSERT_EQ(initial_active_index, GetActiveTabIndex()); + + ASSERT_NO_FATAL_FAILURE(enter_fullscreen()); + + // A new window should be created and focused. + ASSERT_NO_FATAL_FAILURE(SendShortcut(ui::VKEY_N)); + WaitForBrowserCount(initial_browser_count + 1); + ASSERT_EQ(initial_browser_count + 1, GetBrowserCount()); + + ASSERT_NO_FATAL_FAILURE(enter_fullscreen()); + + // The newly created window should be closed. + ASSERT_NO_FATAL_FAILURE(SendShiftShortcut(ui::VKEY_W)); + WaitForBrowserCount(initial_browser_count); + + ASSERT_EQ(initial_browser_count, GetBrowserCount()); + ASSERT_EQ(initial_active_index, GetActiveTabIndex()); + + ASSERT_NO_FATAL_FAILURE(enter_fullscreen()); } void BrowserCommandControllerInteractiveTest::FinishTestAndVerifyResult() { @@ -232,12 +415,12 @@ // sent. So we sent a KeyX to the webpage to indicate the end of the test // case. After processing this key event, web page is safe to send the record // back through window.domAutomationController. - EXPECT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_X, false, - false, false, false)); + EXPECT_TRUE(ui_test_utils::SendKeyPressSync( + GetActiveBrowser(), ui::VKEY_X, false, false, false, false)); expected_result_ += "KeyX ctrl:false shift:false alt:false meta:false"; std::string result; EXPECT_TRUE(content::ExecuteScriptAndExtractString( - browser()->tab_strip_model()->GetActiveWebContents()->GetRenderViewHost(), + GetActiveWebContents()->GetRenderViewHost(), "getKeyEventReport();", &result)); NormalizeMetaKeyForMacOS(&result); NormalizeMetaKeyForMacOS(&expected_result_); @@ -246,30 +429,28 @@ } void BrowserCommandControllerInteractiveTest::SetUpOnMainThread() { - ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); + ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(GetActiveBrowser())); } IN_PROC_BROWSER_TEST_F(BrowserCommandControllerInteractiveTest, ShortcutsShouldTakeEffectInWindowMode) { - ASSERT_EQ(1, browser()->tab_strip_model()->count()); + ASSERT_EQ(1, GetTabCount()); ASSERT_NO_FATAL_FAILURE(SendShortcut(ui::VKEY_T)); - ASSERT_EQ(2, browser()->tab_strip_model()->count()); + ASSERT_EQ(2, GetTabCount()); ASSERT_NO_FATAL_FAILURE(SendShortcut(ui::VKEY_T)); - ASSERT_EQ(3, browser()->tab_strip_model()->count()); + ASSERT_EQ(3, GetTabCount()); ASSERT_NO_FATAL_FAILURE(SendShortcut(ui::VKEY_W)); - ASSERT_EQ(2, browser()->tab_strip_model()->count()); + ASSERT_EQ(2, GetTabCount()); ASSERT_NO_FATAL_FAILURE(SendShortcut(ui::VKEY_W)); - ASSERT_EQ(1, browser()->tab_strip_model()->count()); + ASSERT_EQ(1, GetTabCount()); ASSERT_NO_FATAL_FAILURE(SendFullscreenShortcutAndWait()); - ASSERT_TRUE(browser() - ->exclusive_access_manager() - ->fullscreen_controller() - ->IsFullscreenForBrowser()); + ASSERT_TRUE(IsInBrowserFullscreen()); + ASSERT_FALSE(IsActiveTabFullscreen()); } IN_PROC_BROWSER_TEST_F(BrowserCommandControllerInteractiveTest, UnpreservedShortcutsShouldBePreventable) { - ASSERT_NO_FATAL_FAILURE(StartTestPage()); + ASSERT_NO_FATAL_FAILURE(StartFullscreenLockPage()); // The browser print function should be blocked by the web page. ASSERT_NO_FATAL_FAILURE(SendShortcut(ui::VKEY_P)); @@ -290,23 +471,29 @@ IN_PROC_BROWSER_TEST_F( BrowserCommandControllerInteractiveTest, MAYBE_KeyEventsShouldBeConsumedByWebPageInBrowserFullscreen) { - ASSERT_NO_FATAL_FAILURE(StartTestPage()); + ASSERT_NO_FATAL_FAILURE(StartFullscreenLockPage()); ASSERT_NO_FATAL_FAILURE(SendFullscreenShortcutAndWait()); - ASSERT_NO_FATAL_FAILURE(SendShortcutsInFullscreen()); + ASSERT_FALSE(IsActiveTabFullscreen()); + ASSERT_TRUE(IsInBrowserFullscreen()); + ASSERT_NO_FATAL_FAILURE(SendShortcutsAndExpectPrevented()); // Current page should not exit browser fullscreen mode. ASSERT_NO_FATAL_FAILURE(SendEscape()); ASSERT_NO_FATAL_FAILURE(FinishTestAndVerifyResult()); + + ASSERT_NO_FATAL_FAILURE(SendFullscreenShortcutAndWait()); + ASSERT_FALSE(IsActiveTabFullscreen()); + ASSERT_FALSE(IsInBrowserFullscreen()); } IN_PROC_BROWSER_TEST_F( BrowserCommandControllerInteractiveTest, KeyEventsShouldBeConsumedByWebPageInJsFullscreenExceptForEsc) { - ASSERT_NO_FATAL_FAILURE(StartTestPage()); + ASSERT_NO_FATAL_FAILURE(StartFullscreenLockPage()); ASSERT_NO_FATAL_FAILURE(SendJsFullscreenShortcutAndWait()); - ASSERT_NO_FATAL_FAILURE(SendShortcutsInFullscreen()); + ASSERT_NO_FATAL_FAILURE(SendShortcutsAndExpectPrevented()); // Current page should exit HTML fullscreen mode. ASSERT_NO_FATAL_FAILURE(SendEscapeAndWaitForExitingFullscreen()); @@ -316,21 +503,70 @@ IN_PROC_BROWSER_TEST_F( BrowserCommandControllerInteractiveTest, KeyEventsShouldBeConsumedByWebPageInJsFullscreenExceptForF11) { - ASSERT_NO_FATAL_FAILURE(StartTestPage()); + ASSERT_NO_FATAL_FAILURE(StartFullscreenLockPage()); ASSERT_NO_FATAL_FAILURE(SendJsFullscreenShortcutAndWait()); - ASSERT_NO_FATAL_FAILURE(SendShortcutsInFullscreen()); + ASSERT_NO_FATAL_FAILURE(SendShortcutsAndExpectPrevented()); #if defined(OS_MACOSX) // On 10.9 or earlier, sending the exit fullscreen shortcut will crash the // binary. See http://crbug.com/740250. if (base::mac::IsAtLeastOS10_10()) { // Current page should exit browser fullscreen mode. ASSERT_NO_FATAL_FAILURE(SendFullscreenShortcutAndWait()); + ASSERT_FALSE(IsActiveTabFullscreen()); + ASSERT_FALSE(IsInBrowserFullscreen()); } #else // Current page should exit browser fullscreen mode. ASSERT_NO_FATAL_FAILURE(SendFullscreenShortcutAndWait()); + ASSERT_FALSE(IsActiveTabFullscreen()); + ASSERT_FALSE(IsInBrowserFullscreen()); #endif ASSERT_NO_FATAL_FAILURE(FinishTestAndVerifyResult()); } + +#if defined(OS_MACOSX) +// TODO(zijiehe): Figure out why this test crashes on Mac OSX. The suspicious +// command is "SendFullscreenShortcutAndWait()". See, http://crbug.com/738949. +#define MAYBE_ShortcutsShouldTakeEffectInBrowserFullscreen \ + DISABLED_ShortcutsShouldTakeEffectInBrowserFullscreen +#else +#define MAYBE_ShortcutsShouldTakeEffectInBrowserFullscreen \ + ShortcutsShouldTakeEffectInBrowserFullscreen +#endif +IN_PROC_BROWSER_TEST_F(BrowserCommandControllerInteractiveTest, + MAYBE_ShortcutsShouldTakeEffectInBrowserFullscreen) { +#if defined(OS_MACOSX) + // On 10.9 or earlier, sending the exit fullscreen shortcut will crash the + // binary. See http://crbug.com/740250. + if (base::mac::IsAtMostOS10_9()) + return; +#endif + ASSERT_NO_FATAL_FAILURE(SendShortcutsAndExpectNotPrevented(false)); +} + +#if !defined(OS_MACOSX) +// HTML fullscreen is automatically exited after some commands are executed, +// such as Ctrl + T (new tab). But some commands won't have this effect, such as +// Ctrl + N (new window). +// On Mac OSX, AppKit implementation is used for HTML fullscreen mode. Entering +// and exiting AppKit fullscreen mode triggers an animation. A +// FullscreenChangeObserver is needed to ensure the animation is finished. But +// the FullscreenChangeObserver won't finish if the command actually won't cause +// the page to exit fullscreen mode. So we need to maintain a list of exiting / +// non-exiting commands, which is not the goal of this test. + +#if defined(OS_CHROMEOS) +// This test is flaky on ChromeOS, see bug http://crbug.com/754878. +#define MAYBE_ShortcutsShouldTakeEffectInJsFullscreen \ + DISABLED_ShortcutsShouldTakeEffectInJsFullscreen +#else +#define MAYBE_ShortcutsShouldTakeEffectInJsFullscreen \ + ShortcutsShouldTakeEffectInJsFullscreen +#endif +IN_PROC_BROWSER_TEST_F(BrowserCommandControllerInteractiveTest, + MAYBE_ShortcutsShouldTakeEffectInJsFullscreen) { + ASSERT_NO_FATAL_FAILURE(SendShortcutsAndExpectNotPrevented(true)); +} +#endif
diff --git a/chrome/browser/ui/chrome_pages.cc b/chrome/browser/ui/chrome_pages.cc index 22789838..f8ca4ec 100644 --- a/chrome/browser/ui/chrome_pages.cc +++ b/chrome/browser/ui/chrome_pages.cc
@@ -245,12 +245,6 @@ return GURL(std::string(kChromeUISettingsURL) + sub_page); } -bool IsSettingsSubPage(const GURL& url, const std::string& sub_page) { - return (url.SchemeIs(content::kChromeUIScheme) && - (url.host_piece() == chrome::kChromeUISettingsHost) && - url.path_piece() == "/" + sub_page); -} - bool IsTrustedPopupWindowWithScheme(const Browser* browser, const std::string& scheme) { if (!browser->is_type_popup() || !browser->is_trusted_source())
diff --git a/chrome/browser/ui/chrome_pages.h b/chrome/browser/ui/chrome_pages.h index 9c0031f..92a4fde 100644 --- a/chrome/browser/ui/chrome_pages.h +++ b/chrome/browser/ui/chrome_pages.h
@@ -78,9 +78,6 @@ // Constructs a settings GURL for the specified |sub_page|. GURL GetSettingsUrl(const std::string& sub_page); -// Returns true if |url| is the URL for the settings subpage |sub_page|. -bool IsSettingsSubPage(const GURL& url, const std::string& sub_page); - // Returns true if |browser| is a trusted popup window containing a page with // matching |scheme| (or any trusted popup if |scheme| is empty). bool IsTrustedPopupWindowWithScheme(const Browser* browser,
diff --git a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h index 594a3f7..a3a729a 100644 --- a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h +++ b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h
@@ -129,7 +129,7 @@ bool IsFullscreenOrPending() const override; void UpdateWindowIcon() override; void UpdateWindowTitle() override; - void UpdateShape(std::unique_ptr<SkRegion> region) override; + void UpdateShape(std::unique_ptr<ShapeRects> rects) override; void UpdateDraggableRegions( const std::vector<extensions::DraggableRegion>& regions) override; SkRegion* GetDraggableRegion() override;
diff --git a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm index 595af1d..ae8dece3 100644 --- a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm +++ b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm
@@ -540,7 +540,7 @@ [window() setTitle:base::SysUTF16ToNSString(title)]; } -void NativeAppWindowCocoa::UpdateShape(std::unique_ptr<SkRegion> region) { +void NativeAppWindowCocoa::UpdateShape(std::unique_ptr<ShapeRects> rects) { NOTIMPLEMENTED(); }
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm index 198b67c..7c3565a 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller.mm
@@ -2003,34 +2003,6 @@ display::Screen* screen = display::Screen::GetScreen(); BOOL hasMultipleMonitors = screen && screen->GetNumDisplays() > 1; - if (base::FeatureList::IsEnabled(features::kContentFullscreen)) { - // Getting the current's window view and its boundaries. - NSWindow* window = [self window]; - WebContents* contents = browser_->tab_strip_model()->GetActiveWebContents(); - NSView* view = contents->GetNativeView(); - NSRect windowFrame = window.frame; - NSRect viewFrame = [view convertRect:view.bounds toView:nil]; - - // Moving the origin from the lower-left corner to the upper-left corner of - // the view and cropping out the scrollbar - viewFrame.origin.y = NSHeight(windowFrame) - NSMaxY(viewFrame); - viewFrame.size.width -= gfx::scrollbar_size(); - - // Taking a screenshot of the view and creating the custom view to display - CGImageRef windowScreenshot = (CGImageRef)[(id)CGWindowListCreateImage( - CGRectZero, kCGWindowListOptionIncludingWindow, [window windowNumber], - kCGWindowImageBoundsIgnoreFraming) autorelease]; - CGImageRef viewScreenshot = (CGImageRef)[(id)CGImageCreateWithImageInRect( - windowScreenshot, [window convertRectToBacking:viewFrame]) autorelease]; - FullscreenPlaceholderView* screenshotView = - [[[FullscreenPlaceholderView alloc] - initWithFrame:[[self tabContentArea] bounds] - image:viewScreenshot] autorelease]; - screenshotView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; - - [[self tabContentArea] addSubview:screenshotView]; - } - if (base::mac::IsAtLeastOS10_10() && !(hasMultipleMonitors && ![NSScreen screensHaveSeparateSpaces])) { [self enterAppKitFullscreen];
diff --git a/chrome/browser/ui/cocoa/separate_fullscreen_window.h b/chrome/browser/ui/cocoa/separate_fullscreen_window.h new file mode 100644 index 0000000..d6b211a --- /dev/null +++ b/chrome/browser/ui/cocoa/separate_fullscreen_window.h
@@ -0,0 +1,20 @@ +// Copyright (c) 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 CHROME_BROWSER_UI_COCOA_SEPARATE_FULLSCREEN_WINDOW_H_ +#define CHROME_BROWSER_UI_COCOA_SEPARATE_FULLSCREEN_WINDOW_H_ + +#import <Cocoa/Cocoa.h> + +#include "ui/base/cocoa/touch_bar_forward_declarations.h" + +@interface SeparateFullscreenWindow : NSWindow +// This window class is instantiated to display a WebContentsViewCocoa as its +// subview in fullscreen mode as part of ContentFullscreen to enable users to +// interact with the main browser window and its tab when they're displaying +// content in this separate window. Related types include +// FullscreenLowPowerWindow. +@end + +#endif // CHROME_BROWSER_UI_COCOA_SEPARATE_FULLSCREEN_WINDOW_H_
diff --git a/chrome/browser/ui/cocoa/separate_fullscreen_window.mm b/chrome/browser/ui/cocoa/separate_fullscreen_window.mm new file mode 100644 index 0000000..89f07cf5 --- /dev/null +++ b/chrome/browser/ui/cocoa/separate_fullscreen_window.mm
@@ -0,0 +1,17 @@ +// Copyright (c) 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. + +#import "chrome/browser/ui/cocoa/separate_fullscreen_window.h" + +@implementation SeparateFullscreenWindow + +- (BOOL)canBecomeKeyWindow { + return YES; +} + +- (BOOL)canBecomeMainWindow { + return YES; +} + +@end
diff --git a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h index f04b529..7fe6d64 100644 --- a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h +++ b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h
@@ -47,6 +47,13 @@ // Set to true if the window is a popup. BOOL isPopup_; + // Reference to the FullscreenPlaceholderView displayed in the main window + // for the tab when our WebContentsView is in the SeparateFullscreenWindow. + NSView* fullscreenPlaceholderView_; + // Reference to the fullscreen window created to display the WebContents + // view separately. + NSWindow* separateFullscreenWindow_; + base::scoped_nsobject<WebTextfieldTouchBarController> touchBarController_; } @property(readonly, nonatomic) content::WebContents* webContents;
diff --git a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm index 359e1a97..5ba9768 100644 --- a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm +++ b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm
@@ -8,15 +8,20 @@ #include <utility> +#include "base/feature_list.h" #include "base/mac/scoped_cftyperef.h" #include "base/mac/scoped_nsobject.h" #include "base/macros.h" #include "chrome/browser/devtools/devtools_window.h" #import "chrome/browser/themes/theme_properties.h" #import "chrome/browser/themes/theme_service.h" +#include "chrome/browser/ui/cocoa/fullscreen_placeholder_view.h" +#include "chrome/browser/ui/cocoa/separate_fullscreen_window.h" #import "chrome/browser/ui/cocoa/themed_window.h" #import "chrome/browser/ui/cocoa/web_textfield_touch_bar_controller.h" +#include "chrome/browser/ui/exclusive_access/fullscreen_within_tab_helper.h" #include "chrome/browser/ui/view_ids.h" +#include "chrome/common/chrome_features.h" #include "chrome/grit/theme_resources.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host.h" @@ -27,6 +32,7 @@ #include "ui/base/cocoa/animation_utils.h" #import "ui/base/cocoa/touch_bar_forward_declarations.h" #include "ui/gfx/geometry/rect.h" +#include "ui/gfx/scrollbar_size.h" using content::WebContents; using content::WebContentsObserver; @@ -62,7 +68,7 @@ void DidToggleFullscreenModeForTab(bool entered_fullscreen, bool will_cause_resize) override { - [controller_ toggleFullscreenWidget:YES]; + [controller_ toggleFullscreenWidget:entered_fullscreen]; } private: @@ -204,6 +210,15 @@ @end // @implementation TabContentsContainerView +@interface TabContentsController ( + SeparateFullscreenWindowDelegate)<NSWindowDelegate> + +- (NSView*)createScreenshotView; + +- (NSWindow*)createSeparateWindowForTab:(content::WebContents*)separatedTab; + +@end + @implementation TabContentsController @synthesize webContents = contents_; @synthesize blockFullscreenResize = blockFullscreenResize_; @@ -249,7 +264,9 @@ content::RenderWidgetHostView* const fullscreenView = isEmbeddingFullscreenWidget_ ? contents_->GetFullscreenRenderWidgetHostView() : NULL; - if (fullscreenView) { + if (fullscreenPlaceholderView_) { + contentsNativeView = fullscreenPlaceholderView_; + } else if (fullscreenView) { contentsNativeView = fullscreenView->GetNativeView(); } else { isEmbeddingFullscreenWidget_ = NO; @@ -344,6 +361,17 @@ - (void)toggleFullscreenWidget:(BOOL)enterFullscreen { isEmbeddingFullscreenWidget_ = enterFullscreen && contents_ && contents_->GetFullscreenRenderWidgetHostView(); + if (base::FeatureList::IsEnabled(features::kContentFullscreen)) { + if (enterFullscreen) { + fullscreenPlaceholderView_ = [self createScreenshotView]; + separateFullscreenWindow_ = [self createSeparateWindowForTab:contents_]; + + [separateFullscreenWindow_ makeKeyAndOrderFront:nil]; + [separateFullscreenWindow_ toggleFullScreen:nil]; + } else { + [separateFullscreenWindow_ close]; + } + } [self ensureContentsVisibleInSuperview:[[self view] superview]]; } @@ -411,3 +439,85 @@ } @end + +@implementation TabContentsController (SeparateFullscreenWindowDelegate) + +- (void)windowDidEnterFullScreen:(NSNotification*)notification { + // Make the RenderWidgetHostViewCocoa the firstResponder for the + // SeparateFullscreenWindow. + contents_->Focus(); +} + +- (void)windowWillExitFullScreen:(NSNotification*)notification { + // Remove the screenshot view so that the WebContentsViewCocoa is + // retrieved and displayed again in the original window. + fullscreenPlaceholderView_ = nil; + [self ensureContentsVisibleInSuperview:[[self view] superview]]; + + // When exiting through the title bar Exit Fullscreen Window button, the + // WebContents must be notified of the change in fullscreen (like in + // FullscreenController::HandleUserPressedEscape). + contents_->ExitFullscreen(true); +} + +- (void)windowDidExitFullScreen:(NSNotification*)notification { + // When exiting through the title bar Exit Fullscreen Window button, the + // SeparateFullscreenWindow doesn't close, so make sure it's closed. + [separateFullscreenWindow_ close]; + separateFullscreenWindow_ = nil; +} + +- (NSView*)createScreenshotView { + // Getting the current's window view and its boundaries. + NSWindow* window = [contents_->GetNativeView() window]; + NSView* view = contents_->GetNativeView(); + NSRect windowFrame = window.frame; + NSRect viewFrame = [view convertRect:view.bounds toView:nil]; + + // Moving the origin from the lower-left corner to the upper-left corner of + // the view and cropping out the scrollbar + viewFrame.origin.y = NSHeight(windowFrame) - NSMaxY(viewFrame); + viewFrame.size.width -= gfx::scrollbar_size(); + + // Taking a screenshot of the view and creating the custom view to display + CGImageRef windowScreenshot = (CGImageRef)[(id)CGWindowListCreateImage( + CGRectZero, kCGWindowListOptionIncludingWindow, [window windowNumber], + kCGWindowImageBoundsIgnoreFraming) autorelease]; + CGImageRef viewScreenshot = (CGImageRef)[(id)CGImageCreateWithImageInRect( + windowScreenshot, [window convertRectToBacking:viewFrame]) autorelease]; + FullscreenPlaceholderView* screenshotView = + [[[FullscreenPlaceholderView alloc] initWithFrame:[[self view] bounds] + image:viewScreenshot] + autorelease]; + screenshotView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; + + return screenshotView; +} + +// Creates a new window with the tab without detaching it from its source +// window. +- (NSWindow*)createSeparateWindowForTab:(WebContents*)separatedTab { + DCHECK(separatedTab->GetNativeView()); + + NSView* separatedTabView = separatedTab->GetNativeView(); + NSWindow* sourceWindow = [separatedTabView window]; + NSRect windowRect = + [separatedTabView convertRect:[separatedTabView bounds] toView:nil]; + SeparateFullscreenWindow* separateWindow = [[SeparateFullscreenWindow alloc] + initWithContentRect:[sourceWindow convertRectToScreen:windowRect] + styleMask:NSResizableWindowMask + backing:NSBackingStoreBuffered + defer:NO]; + + [separateWindow setDelegate:self]; + [[separateWindow contentView] addSubview:separatedTabView]; + [separateWindow + setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary]; + + // Make TabContentsContainerView the first responder now as + // WebContentsViewCocoa is now in a separate window. + [sourceWindow makeFirstResponder:[self view]]; + + return separateWindow; +} +@end
diff --git a/chrome/browser/ui/cocoa/toolbar/app_toolbar_button.mm b/chrome/browser/ui/cocoa/toolbar/app_toolbar_button.mm index ddc0eb5..99ff818c 100644 --- a/chrome/browser/ui/cocoa/toolbar/app_toolbar_button.mm +++ b/chrome/browser/ui/cocoa/toolbar/app_toolbar_button.mm
@@ -4,7 +4,6 @@ #import "chrome/browser/ui/cocoa/toolbar/app_toolbar_button.h" -#include "base/command_line.h" #include "base/macros.h" #include "chrome/app/vector_icons/vector_icons.h" #import "chrome/browser/themes/theme_properties.h" @@ -12,7 +11,7 @@ #include "chrome/browser/ui/cocoa/animated_icon.h" #import "chrome/browser/ui/cocoa/themed_window.h" #import "chrome/browser/ui/cocoa/view_id_util.h" -#include "chrome/common/chrome_switches.h" +#include "chrome/common/chrome_features.h" #include "chrome/grit/chromium_strings.h" #include "ui/base/l10n/l10n_util_mac.h" #include "ui/base/material_design/material_design_controller.h" @@ -33,8 +32,7 @@ if ((self = [super initWithFrame:frame])) { [self commonInit]; - base::CommandLine* commandLine = base::CommandLine::ForCurrentProcess(); - if (commandLine->HasSwitch(switches::kEnableNewAppMenuIcon)) { + if (base::FeatureList::IsEnabled(features::kAnimatedAppMenuIcon)) { animatedIcon_.reset(new AnimatedIcon(kBrowserToolsAnimatedIcon, self)); [self updateAnimatedIconColor];
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller.cc index dace90e..fab299d 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller.cc
@@ -32,7 +32,10 @@ #include "content/public/browser/web_contents.h" #include "extensions/common/extension.h" -#if !defined(OS_MACOSX) +#if defined(OS_MACOSX) +#include "base/feature_list.h" +#include "chrome/common/chrome_features.h" +#else #include "chrome/common/pref_names.h" #include "components/prefs/pref_service.h" #endif @@ -96,7 +99,7 @@ bool FullscreenController::IsFullscreenForTabOrPending( const WebContents* web_contents) const { - if (IsFullscreenForCapturedTab(web_contents)) + if (IsFullscreenWithinTab(web_contents)) return true; if (web_contents == exclusive_access_tab()) { DCHECK(web_contents == @@ -114,7 +117,7 @@ const GURL& origin) { DCHECK(web_contents); - if (MaybeToggleFullscreenForCapturedTab(web_contents, true)) { + if (MaybeToggleFullscreenWithinTab(web_contents, true)) { // During tab capture of fullscreen-within-tab views, the browser window // fullscreen state is unchanged, so return now. return; @@ -158,7 +161,7 @@ } void FullscreenController::ExitFullscreenModeForTab(WebContents* web_contents) { - if (MaybeToggleFullscreenForCapturedTab(web_contents, false)) { + if (MaybeToggleFullscreenWithinTab(web_contents, false)) { // During tab capture of fullscreen-within-tab views, the browser window // fullscreen state is unchanged, so return now. return; @@ -199,7 +202,7 @@ } void FullscreenController::OnTabDetachedFromView(WebContents* old_contents) { - if (!IsFullscreenForCapturedTab(old_contents)) + if (!IsFullscreenWithinTab(old_contents)) return; // A fullscreen-within-tab view undergoing screen capture has been detached @@ -231,7 +234,7 @@ } void FullscreenController::OnTabClosing(WebContents* web_contents) { - if (IsFullscreenForCapturedTab(web_contents)) + if (IsFullscreenWithinTab(web_contents)) web_contents->ExitFullscreen( /* will_cause_resize */ IsFullscreenCausedByTab()); else @@ -264,7 +267,7 @@ bool FullscreenController::HandleUserPressedEscape() { WebContents* const active_web_contents = exclusive_access_manager()->context()->GetActiveWebContents(); - if (IsFullscreenForCapturedTab(active_web_contents)) { + if (IsFullscreenWithinTab(active_web_contents)) { active_web_contents->ExitFullscreen( /* will_cause_resize */ IsFullscreenCausedByTab()); return true; @@ -415,17 +418,22 @@ is_privileged_fullscreen_for_testing_ = is_privileged; } -bool FullscreenController::MaybeToggleFullscreenForCapturedTab( - WebContents* web_contents, bool enter_fullscreen) { +bool FullscreenController::MaybeToggleFullscreenWithinTab( + WebContents* web_contents, + bool enter_fullscreen) { if (enter_fullscreen) { - if (web_contents->GetCapturerCount() > 0) { + if (web_contents->GetCapturerCount() > 0 +#if defined(OS_MACOSX) + || base::FeatureList::IsEnabled(features::kContentFullscreen) +#endif + ) { FullscreenWithinTabHelper::CreateForWebContents(web_contents); - FullscreenWithinTabHelper::FromWebContents(web_contents)-> - SetIsFullscreenForCapturedTab(true); + FullscreenWithinTabHelper::FromWebContents(web_contents) + ->SetIsFullscreenWithinTab(true); return true; } } else { - if (IsFullscreenForCapturedTab(web_contents)) { + if (IsFullscreenWithinTab(web_contents)) { FullscreenWithinTabHelper::RemoveForWebContents(web_contents); return true; } @@ -434,7 +442,7 @@ return false; } -bool FullscreenController::IsFullscreenForCapturedTab( +bool FullscreenController::IsFullscreenWithinTab( const WebContents* web_contents) const { // Note: On Mac, some of the OnTabXXX() methods get called with a nullptr // value @@ -442,7 +450,7 @@ const FullscreenWithinTabHelper* const helper = web_contents ? FullscreenWithinTabHelper::FromWebContents(web_contents) : nullptr; - if (helper && helper->is_fullscreen_for_captured_tab()) { + if (helper && helper->is_fullscreen_within_tab()) { DCHECK_NE(exclusive_access_tab(), web_contents); return true; }
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller.h b/chrome/browser/ui/exclusive_access/fullscreen_controller.h index 1edfeac..2449dec4 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller.h +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller.h
@@ -37,15 +37,25 @@ // FullscreenWithinTab Note: // All fullscreen widgets are displayed within the tab contents area, and // FullscreenController will expand the browser window so that the tab contents -// area fills the entire screen. However, special behavior applies when a tab is -// being screen-captured. First, the browser window will not be -// fullscreened. This allows the user to retain control of their desktop to work -// in other browser tabs or applications while the fullscreen view is displayed -// on a remote screen. Second, FullscreenController will auto-resize fullscreen -// widgets to that of the capture video resolution when they are hidden (e.g., -// when a user has switched to another tab). This is both a performance and -// quality improvement since scaling and letterboxing steps can be skipped in -// the capture pipeline. +// area fills the entire screen. +// However, special behavior applies when a tab is screen-captured or the +// content fullscreen feature is active. +// +// Screen-captured: +// First, the browser window will not be fullscreened. This allows the user to +// retain control of their desktop to work in other browser tabs or applications +// while the fullscreen view is displayed on a remote screen. Second, +// FullscreenController will auto-resize fullscreen widgets to that of the +// capture video resolution when they are hidden (e.g., when a user has +// switched to another tab). This is both a performance and quality improvement +// since scaling and letterboxing steps can be skipped in the capture pipeline. +// +// Content-fullscreen (for macOS only): +// First, the browser window will not be fullscreened. Second, the WebContents's +// view will not be displayed in the browser window but rather in a +// separate window, SeparateFullscreenWindow, which will be fullscreened and +// moved to a new space. This enables the user to have both the browser window +// and the fullscreen content displayed separately at the same time. // This class implements fullscreen behaviour. class FullscreenController : public ExclusiveAccessControllerBase { @@ -155,13 +165,13 @@ void SetPrivilegedFullscreenForTesting(bool is_privileged); // Returns true if |web_contents| was toggled into/out of fullscreen mode as a - // screen-captured tab. See 'FullscreenWithinTab Note'. - bool MaybeToggleFullscreenForCapturedTab(content::WebContents* web_contents, - bool enter_fullscreen); + // screen-captured tab or as a content-fullscreen tab. + // See 'FullscreenWithinTab Note'. + bool MaybeToggleFullscreenWithinTab(content::WebContents* web_contents, + bool enter_fullscreen); // Returns true if |web_contents| is in fullscreen mode as a screen-captured // tab. See 'FullscreenWithinTab Note'. - bool IsFullscreenForCapturedTab(const content::WebContents* web_contents) - const; + bool IsFullscreenWithinTab(const content::WebContents* web_contents) const; // Helper methods that should be used in a TAB context. GURL GetRequestingOrigin() const;
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_within_tab_helper.cc b/chrome/browser/ui/exclusive_access/fullscreen_within_tab_helper.cc index 374318a..2101c35 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_within_tab_helper.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_within_tab_helper.cc
@@ -8,7 +8,7 @@ FullscreenWithinTabHelper::FullscreenWithinTabHelper( content::WebContents* ignored) - : is_fullscreen_for_captured_tab_(false) {} + : is_fullscreen_within_tab_(false) {} FullscreenWithinTabHelper::~FullscreenWithinTabHelper() {}
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_within_tab_helper.h b/chrome/browser/ui/exclusive_access/fullscreen_within_tab_helper.h index e201bb79..37e91b4 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_within_tab_helper.h +++ b/chrome/browser/ui/exclusive_access/fullscreen_within_tab_helper.h
@@ -24,12 +24,10 @@ public: ~FullscreenWithinTabHelper() override; - bool is_fullscreen_for_captured_tab() const { - return is_fullscreen_for_captured_tab_; - } + bool is_fullscreen_within_tab() const { return is_fullscreen_within_tab_; } - void SetIsFullscreenForCapturedTab(bool is_fullscreen) { - is_fullscreen_for_captured_tab_ = is_fullscreen; + void SetIsFullscreenWithinTab(bool is_fullscreen) { + is_fullscreen_within_tab_ = is_fullscreen; } // Immediately remove and destroy the FullscreenWithinTabHelper instance @@ -40,7 +38,7 @@ friend class content::WebContentsUserData<FullscreenWithinTabHelper>; explicit FullscreenWithinTabHelper(content::WebContents* ignored); - bool is_fullscreen_for_captured_tab_; + bool is_fullscreen_within_tab_; DISALLOW_COPY_AND_ASSIGN(FullscreenWithinTabHelper); };
diff --git a/chrome/browser/ui/input_method/input_method_engine.cc b/chrome/browser/ui/input_method/input_method_engine.cc index 8ebbd4b..9bb8ca7 100644 --- a/chrome/browser/ui/input_method/input_method_engine.cc +++ b/chrome/browser/ui/input_method/input_method_engine.cc
@@ -138,10 +138,10 @@ composition_.CopyFrom(composition_text); // Use a black thin underline by default. - if (composition_.underlines.empty()) { - composition_.underlines.push_back( - ui::CompositionUnderline(0, composition_.text.length(), SK_ColorBLACK, - false /* thick */, SK_ColorTRANSPARENT)); + if (composition_.ime_text_spans.empty()) { + composition_.ime_text_spans.push_back( + ui::ImeTextSpan(0, composition_.text.length(), SK_ColorBLACK, + false /* thick */, SK_ColorTRANSPARENT)); } ui::IMEInputContextHandlerInterface* input_context =
diff --git a/chrome/browser/ui/input_method/input_method_engine_base.cc b/chrome/browser/ui/input_method/input_method_engine_base.cc index b030117..120c0440 100644 --- a/chrome/browser/ui/input_method/input_method_engine_base.cc +++ b/chrome/browser/ui/input_method/input_method_engine_base.cc
@@ -210,26 +210,26 @@ // TODO: Add support for displaying selected text in the composition string. for (std::vector<SegmentInfo>::const_iterator segment = segments.begin(); segment != segments.end(); ++segment) { - ui::CompositionUnderline underline; + ui::ImeTextSpan ime_text_span; switch (segment->style) { case SEGMENT_STYLE_UNDERLINE: - underline.color = SK_ColorBLACK; + ime_text_span.color = SK_ColorBLACK; break; case SEGMENT_STYLE_DOUBLE_UNDERLINE: - underline.color = SK_ColorBLACK; - underline.thick = true; + ime_text_span.color = SK_ColorBLACK; + ime_text_span.thick = true; break; case SEGMENT_STYLE_NO_UNDERLINE: - underline.color = SK_ColorTRANSPARENT; + ime_text_span.color = SK_ColorTRANSPARENT; break; default: continue; } - underline.start_offset = segment->start; - underline.end_offset = segment->end; - composition_text_->underlines.push_back(underline); + ime_text_span.start_offset = segment->start; + ime_text_span.end_offset = segment->end; + composition_text_->ime_text_spans.push_back(ime_text_span); } // TODO(nona): Makes focus out mode configuable, if necessary.
diff --git a/chrome/browser/ui/views/accessibility/invert_bubble_view.cc b/chrome/browser/ui/views/accessibility/invert_bubble_view.cc index 5e58c77..441bbec 100644 --- a/chrome/browser/ui/views/accessibility/invert_bubble_view.cc +++ b/chrome/browser/ui/views/accessibility/invert_bubble_view.cc
@@ -33,7 +33,7 @@ const char kHighContrastExtensionUrl[] = "https://chrome.google.com/webstore/detail/djcfdncoelnlbldjfhinnjlhdjlikmph"; const char kDarkThemeSearchUrl[] = - "https://chrome.google.com/webstore/search-themes/dark"; + "https://chrome.google.com/webstore/category/collection/dark_themes"; const char kLearnMoreUrl[] = "https://groups.google.com/a/googleproductforums.com/d/topic/chrome/Xrco2HsXS-8/discussion";
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views.cc b/chrome/browser/ui/views/apps/chrome_native_app_window_views.cc index af8347b..92bf067b 100644 --- a/chrome/browser/ui/views/apps/chrome_native_app_window_views.cc +++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views.cc
@@ -23,6 +23,7 @@ #include "components/zoom/zoom_controller.h" #include "extensions/browser/app_window/app_delegate.h" #include "ui/gfx/image/image_skia_operations.h" +#include "ui/gfx/skia_util.h" #include "ui/views/controls/webview/webview.h" #include "ui/views/widget/widget.h" @@ -357,7 +358,17 @@ return widget()->IsFullscreen(); } -void ChromeNativeAppWindowViews::UpdateShape(std::unique_ptr<SkRegion> region) { +void ChromeNativeAppWindowViews::UpdateShape( + std::unique_ptr<ShapeRects> rects) { + shape_rects_ = std::move(rects); + + // Build a region from the list of rects when it is supplied. + std::unique_ptr<SkRegion> region; + if (shape_rects_) { + region = base::MakeUnique<SkRegion>(); + for (const gfx::Rect& input_rect : *shape_rects_.get()) + region->op(gfx::RectToSkIRect(input_rect), SkRegion::kUnion_Op); + } shape_ = std::move(region); widget()->SetShape(shape() ? base::MakeUnique<SkRegion>(*shape()) : nullptr); widget()->OnSizeConstraintsChanged();
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views.h b/chrome/browser/ui/views/apps/chrome_native_app_window_views.h index 3234213..4e0679c 100644 --- a/chrome/browser/ui/views/apps/chrome_native_app_window_views.h +++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views.h
@@ -21,6 +21,7 @@ ~ChromeNativeAppWindowViews() override; SkRegion* shape() { return shape_.get(); } + ShapeRects* shape_rects() { return shape_rects_.get(); } protected: // Called before views::Widget::Init() in InitializeDefaultWindow() to allow @@ -60,7 +61,7 @@ // NativeAppWindow implementation. void SetFullscreen(int fullscreen_types) override; bool IsFullscreenOrPending() const override; - void UpdateShape(std::unique_ptr<SkRegion> region) override; + void UpdateShape(std::unique_ptr<ShapeRects> rects) override; bool HasFrameColor() const override; SkColor ActiveFrameColor() const override; SkColor InactiveFrameColor() const override; @@ -81,6 +82,8 @@ // default shape, usually rectangular. std::unique_ptr<SkRegion> shape_; + std::unique_ptr<ShapeRects> shape_rects_; + bool has_frame_color_; SkColor active_frame_color_; SkColor inactive_frame_color_;
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura.cc b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura.cc index 8efa79e..09a14e5 100644 --- a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura.cc +++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura.cc
@@ -110,10 +110,10 @@ } void ChromeNativeAppWindowViewsAura::UpdateShape( - std::unique_ptr<SkRegion> region) { + std::unique_ptr<ShapeRects> rects) { bool had_shape = !!shape(); - ChromeNativeAppWindowViews::UpdateShape(std::move(region)); + ChromeNativeAppWindowViews::UpdateShape(std::move(rects)); aura::Window* native_window = widget()->GetNativeWindow(); if (shape() && !had_shape) {
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura.h b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura.h index 9c84e8f..229eeb1 100644 --- a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura.h +++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura.h
@@ -36,7 +36,7 @@ bool IsAlwaysOnTop() const override; // NativeAppWindow implementation. - void UpdateShape(std::unique_ptr<SkRegion> region) override; + void UpdateShape(std::unique_ptr<ShapeRects> rects) override; private: FRIEND_TEST_ALL_PREFIXES(ShapedAppWindowTargeterTest,
diff --git a/chrome/browser/ui/views/apps/shaped_app_window_targeter.cc b/chrome/browser/ui/views/apps/shaped_app_window_targeter.cc index 6f0e7cd..ec273d2 100644 --- a/chrome/browser/ui/views/apps/shaped_app_window_targeter.cc +++ b/chrome/browser/ui/views/apps/shaped_app_window_targeter.cc
@@ -21,6 +21,9 @@ if (!shape) return false; + // TODO(varkha): Use app_window_->shape_rects() to obtain a list of hit-test + // rectangles. Use the rectangles directly rather than a mask which should + // allow this class to inherit directly from WindowTargeter. shape->getBoundaryPath(mask); return true; }
diff --git a/chrome/browser/ui/views/apps/shaped_app_window_targeter_unittest.cc b/chrome/browser/ui/views/apps/shaped_app_window_targeter_unittest.cc index 416cd077a..8eb38820 100644 --- a/chrome/browser/ui/views/apps/shaped_app_window_targeter_unittest.cc +++ b/chrome/browser/ui/views/apps/shaped_app_window_targeter_unittest.cc
@@ -20,6 +20,8 @@ #include "ui/wm/core/default_activation_client.h" #include "ui/wm/core/easy_resize_window_targeter.h" +using extensions::AppWindow; + class ShapedAppWindowTargeterTest : public aura::test::AuraTestBase { public: ShapedAppWindowTargeterTest() @@ -85,9 +87,9 @@ EXPECT_EQ(window, move.target()); } - std::unique_ptr<SkRegion> region(new SkRegion); - region->op(SkIRect::MakeXYWH(0, 0, 0, 0), SkRegion::kUnion_Op); - app_window()->UpdateShape(std::move(region)); + auto rects = base::MakeUnique<AppWindow::ShapeRects>(); + rects->emplace_back(); + app_window()->UpdateShape(std::move(rects)); { // With an empty custom shape, all events within the window should fall // through to the root window. @@ -108,10 +110,10 @@ // 90 +--------+ +---------+ // | | // 130 +-----+ - region.reset(new SkRegion); - region->op(SkIRect::MakeXYWH(40, 0, 20, 100), SkRegion::kUnion_Op); - region->op(SkIRect::MakeXYWH(0, 40, 100, 20), SkRegion::kUnion_Op); - app_window()->UpdateShape(std::move(region)); + rects = base::MakeUnique<AppWindow::ShapeRects>(); + rects->emplace_back(40, 0, 20, 100); + rects->emplace_back(0, 40, 100, 20); + app_window()->UpdateShape(std::move(rects)); { // With the custom shape, the events that don't fall within the custom shape // will go through to the root window. @@ -178,10 +180,10 @@ EXPECT_EQ(window, move.target()); } - std::unique_ptr<SkRegion> region(new SkRegion); - region->op(SkIRect::MakeXYWH(40, 0, 20, 100), SkRegion::kUnion_Op); - region->op(SkIRect::MakeXYWH(0, 40, 100, 20), SkRegion::kUnion_Op); - app_window()->UpdateShape(std::move(region)); + auto rects = base::MakeUnique<AppWindow::ShapeRects>(); + rects->emplace_back(40, 0, 20, 100); + rects->emplace_back(0, 40, 100, 20); + app_window()->UpdateShape(std::move(rects)); { // With the custom shape, the events that don't fall within the custom shape // will go through to the root window. @@ -193,7 +195,7 @@ // Remove the custom shape. This should restore the behaviour of targeting the // app window for events just outside its bounds (for a resizable window). - app_window()->UpdateShape(std::unique_ptr<SkRegion>()); + app_window()->UpdateShape(std::unique_ptr<AppWindow::ShapeRects>()); SetWindowResizable(true); { ui::MouseEvent move(move_outside);
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views.cc b/chrome/browser/ui/views/autofill/save_card_bubble_views.cc index 172c67a..18b14d3 100644 --- a/chrome/browser/ui/views/autofill/save_card_bubble_views.cc +++ b/chrome/browser/ui/views/autofill/save_card_bubble_views.cc
@@ -161,13 +161,6 @@ base::string16 SaveCardBubbleViews::GetDialogButtonLabel( ui::DialogButton button) const { - if (!IsAutofillUpstreamShowNewUiExperimentEnabled()) { - // New UI experiment disabled: - return l10n_util::GetStringUTF16(button == ui::DIALOG_BUTTON_OK - ? IDS_AUTOFILL_SAVE_CARD_PROMPT_ACCEPT - : IDS_NO_THANKS); - } - // New UI experiment enabled: switch (GetCurrentFlowStep()) { // Local save has two buttons: case LOCAL_SAVE_ONLY_STEP: @@ -176,14 +169,17 @@ : IDS_NO_THANKS); // Upload save has one button but it can say three different things: case UPLOAD_SAVE_ONLY_STEP: - DCHECK(button == ui::DIALOG_BUTTON_OK); - return l10n_util::GetStringUTF16(IDS_AUTOFILL_SAVE_CARD_PROMPT_ACCEPT); + return l10n_util::GetStringUTF16( + button == ui::DIALOG_BUTTON_OK ? IDS_AUTOFILL_SAVE_CARD_PROMPT_ACCEPT + : IDS_NO_THANKS); case UPLOAD_SAVE_CVC_FIX_FLOW_STEP_1_OFFER_UPLOAD: - DCHECK(button == ui::DIALOG_BUTTON_OK); - return l10n_util::GetStringUTF16(IDS_AUTOFILL_SAVE_CARD_PROMPT_NEXT); + return l10n_util::GetStringUTF16(button == ui::DIALOG_BUTTON_OK + ? IDS_AUTOFILL_SAVE_CARD_PROMPT_NEXT + : IDS_NO_THANKS); case UPLOAD_SAVE_CVC_FIX_FLOW_STEP_2_REQUEST_CVC: - DCHECK(button == ui::DIALOG_BUTTON_OK); - return l10n_util::GetStringUTF16(IDS_AUTOFILL_SAVE_CARD_PROMPT_CONFIRM); + return l10n_util::GetStringUTF16( + button == ui::DIALOG_BUTTON_OK ? IDS_AUTOFILL_SAVE_CARD_PROMPT_CONFIRM + : IDS_NO_THANKS); default: NOTREACHED(); return base::string16(); @@ -315,17 +311,17 @@ views::CreateSolidBorder(1, SkColorSetA(SK_ColorBLACK, 10))); description_view->AddChildView(card_type_icon); - // Old UI shows last four digits and expiration. New UI shows network and - // last four digits, but no expiration. + // Old UI shows last four digits and expiration. New UI shows network, last + // four digits, and expiration. if (IsAutofillUpstreamShowNewUiExperimentEnabled()) { description_view->AddChildView( new views::Label(card.NetworkAndLastFourDigits())); } else { description_view->AddChildView(new views::Label( base::string16(kMidlineEllipsis) + card.LastFourDigits())); - description_view->AddChildView( - new views::Label(card.AbbreviatedExpirationDateForDisplay())); } + description_view->AddChildView( + new views::Label(card.AbbreviatedExpirationDateForDisplay())); // If applicable, add the upload explanation label. Appears below the card // info when new UI experiment is disabled.
diff --git a/chrome/browser/ui/views/first_run_bubble_browsertest.cc b/chrome/browser/ui/views/first_run_bubble_browsertest.cc new file mode 100644 index 0000000..997cb49a --- /dev/null +++ b/chrome/browser/ui/views/first_run_bubble_browsertest.cc
@@ -0,0 +1,29 @@ +// 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 "chrome/browser/ui/views/first_run_bubble.h" + +#include <string> + +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/test/test_browser_dialog.h" + +class FirstRunBubbleBrowserTest : public DialogBrowserTest { + public: + FirstRunBubbleBrowserTest() {} + + // DialogBrowserTest: + void ShowDialog(const std::string& name) override { + FirstRunBubble::Show(browser()); + } + + private: + DISALLOW_COPY_AND_ASSIGN(FirstRunBubbleBrowserTest); +}; + +// Invokes a dialog that tells the user they can type into the omnibox to search +// with Google. See test_browser_dialog.h. +IN_PROC_BROWSER_TEST_F(FirstRunBubbleBrowserTest, InvokeDialog_default) { + RunDialog(); +}
diff --git a/chrome/browser/ui/views/ime/input_ime_apitest_nonchromeos.cc b/chrome/browser/ui/views/ime/input_ime_apitest_nonchromeos.cc index 43d7fefa..4ff7555e 100644 --- a/chrome/browser/ui/views/ime/input_ime_apitest_nonchromeos.cc +++ b/chrome/browser/ui/views/ime/input_ime_apitest_nonchromeos.cc
@@ -90,9 +90,9 @@ // Test the input.ime.setComposition API. ui::CompositionText composition; composition.text = base::UTF8ToUTF16("test_set_composition"); - composition.underlines.push_back( - ui::CompositionUnderline(0, composition.text.length(), SK_ColorBLACK, - false /* thick */, SK_ColorTRANSPARENT)); + composition.ime_text_spans.push_back( + ui::ImeTextSpan(0, composition.text.length(), SK_ColorBLACK, + false /* thick */, SK_ColorTRANSPARENT)); composition.selection = gfx::Range(2, 2); const std::vector<ui::CompositionText>& composition_history = client->composition_history();
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc index 5bb4f0a..e97fa6d 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
@@ -478,7 +478,9 @@ g_bottom_shadow.Get().height()); ui::ClipRecorder clip_recorder(paint_info.context()); - clip_recorder.ClipRect(contents_bounds); + clip_recorder.ClipRect(gfx::ScaleToRoundedRect( + contents_bounds, paint_info.paint_recording_scale_x(), + paint_info.paint_recording_scale_y())); { ui::PaintRecorder recorder(paint_info.context(), size()); SkColor background_color = result_view_at(0)->GetColor(
diff --git a/chrome/browser/ui/views/payments/payment_request_journey_logger_browsertest.cc b/chrome/browser/ui/views/payments/payment_request_journey_logger_browsertest.cc index fa54754..527dab5 100644 --- a/chrome/browser/ui/views/payments/payment_request_journey_logger_browsertest.cc +++ b/chrome/browser/ui/views/payments/payment_request_journey_logger_browsertest.cc
@@ -71,6 +71,9 @@ EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_FALSE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_TRUE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } class PaymentRequestJourneyLoggerNoSupportedPaymentMethodTest @@ -99,8 +102,31 @@ "PaymentRequest.CheckoutFunnel.NoShow", JourneyLogger::NOT_SHOWN_REASON_NO_SUPPORTED_PAYMENT_METHOD, 1); - // Make sure that no events were logged. - histogram_tester.ExpectTotalCount("PaymentRequest.Events", 0); + // Make sure the correct events were logged. + std::vector<base::Bucket> buckets = + histogram_tester.GetAllSamples("PaymentRequest.Events"); + ASSERT_EQ(1U, buckets.size()); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_SHOWN); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_PAY_CLICKED); + EXPECT_FALSE(buckets[0].min & + JourneyLogger::EVENT_RECEIVED_INSTRUMENT_DETAILS); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_SKIPPED_SHOW); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_COMPLETED); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_USER_ABORTED); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_OTHER_ABORTED); + EXPECT_FALSE(buckets[0].min & + JourneyLogger::EVENT_HAD_INITIAL_FORM_OF_PAYMENT); + EXPECT_FALSE(buckets[0].min & + JourneyLogger::EVENT_HAD_NECESSARY_COMPLETE_SUGGESTIONS); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_SHIPPING); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_NAME); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_PHONE); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_FALSE); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_TRUE); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } class PaymentRequestJourneyLoggerMultipleShowTest @@ -165,6 +191,9 @@ EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_FALSE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_TRUE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } IN_PROC_BROWSER_TEST_F(PaymentRequestJourneyLoggerMultipleShowTest, @@ -205,7 +234,7 @@ // Make sure the correct events were logged. std::vector<base::Bucket> buckets = histogram_tester.GetAllSamples("PaymentRequest.Events"); - ASSERT_EQ(1U, buckets.size()); + ASSERT_EQ(2U, buckets.size()); EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_SHOWN); EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_PAY_CLICKED); EXPECT_TRUE(buckets[0].min & @@ -224,6 +253,31 @@ EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_FALSE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_TRUE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); + // We log the exact same events again. + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_SHOWN); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_PAY_CLICKED); + EXPECT_TRUE(buckets[0].min & + JourneyLogger::EVENT_RECEIVED_INSTRUMENT_DETAILS); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_SKIPPED_SHOW); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_COMPLETED); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_USER_ABORTED); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_OTHER_ABORTED); + EXPECT_TRUE(buckets[0].min & + JourneyLogger::EVENT_HAD_INITIAL_FORM_OF_PAYMENT); + EXPECT_TRUE(buckets[0].min & + JourneyLogger::EVENT_HAD_NECESSARY_COMPLETE_SUGGESTIONS); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_SHIPPING); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_NAME); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_PHONE); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_FALSE); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_TRUE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } class PaymentRequestJourneyLoggerAllSectionStatsTest @@ -289,6 +343,9 @@ EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_FALSE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_TRUE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } // Tests that the correct number of suggestions shown for each section is logged @@ -343,6 +400,9 @@ EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_FALSE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_TRUE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } class PaymentRequestJourneyLoggerNoShippingSectionStatsTest @@ -410,6 +470,9 @@ EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_FALSE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_TRUE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } // Tests that the correct number of suggestions shown for each section is logged @@ -465,6 +528,9 @@ EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_FALSE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_TRUE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } class PaymentRequestJourneyLoggerNoContactDetailSectionStatsTest @@ -534,6 +600,9 @@ EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_FALSE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_TRUE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } // Tests that the correct number of suggestions shown for each section is logged @@ -593,6 +662,9 @@ EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_TRUE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_FALSE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_TRUE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } class PaymentRequestNotShownTest : public PaymentRequestBrowserTestBase { @@ -623,7 +695,9 @@ ASSERT_EQ(1U, buckets.size()); // Only USER_ABORTED and CAN_MAKE_PAYMENT_FALSE should be logged. EXPECT_EQ(JourneyLogger::EVENT_USER_ABORTED | - JourneyLogger::EVENT_CAN_MAKE_PAYMENT_FALSE, + JourneyLogger::EVENT_CAN_MAKE_PAYMENT_FALSE | + JourneyLogger::EVENT_REQUEST_METHOD_OTHER | + JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD, buckets[0].min); // Make sure that the metrics that required the Payment Request to be shown @@ -686,6 +760,9 @@ EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_FALSE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_TRUE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } IN_PROC_BROWSER_TEST_F(PaymentRequestCompleteSuggestionsForEverythingTest, @@ -723,6 +800,9 @@ EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_FALSE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_TRUE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } IN_PROC_BROWSER_TEST_F( @@ -766,6 +846,9 @@ EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_FALSE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_TRUE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } } // namespace payments
diff --git a/chrome/browser/ui/views/toolbar/app_menu_button.cc b/chrome/browser/ui/views/toolbar/app_menu_button.cc index 025e164..75eb9aa 100644 --- a/chrome/browser/ui/views/toolbar/app_menu_button.cc +++ b/chrome/browser/ui/views/toolbar/app_menu_button.cc
@@ -4,7 +4,6 @@ #include "chrome/browser/ui/views/toolbar/app_menu_button.h" -#include "base/command_line.h" #include "base/location.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" @@ -26,7 +25,7 @@ #include "chrome/browser/ui/views/toolbar/app_menu.h" #include "chrome/browser/ui/views/toolbar/toolbar_button.h" #include "chrome/browser/ui/views/toolbar/toolbar_view.h" -#include "chrome/common/chrome_switches.h" +#include "chrome/common/chrome_features.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/theme_provider.h" #include "ui/gfx/canvas.h" @@ -53,8 +52,7 @@ SetInkDropMode(InkDropMode::ON); SetFocusPainter(nullptr); - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(switches::kEnableNewAppMenuIcon)) { + if (base::FeatureList::IsEnabled(features::kAnimatedAppMenuIcon)) { toolbar_view_->browser()->tab_strip_model()->AddObserver(this); should_use_new_icon_ = true; }
diff --git a/chrome/browser/ui/webui/chromeos/login/DEPS b/chrome/browser/ui/webui/chromeos/login/DEPS new file mode 100644 index 0000000..d7ca3f3 --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/login/DEPS
@@ -0,0 +1,6 @@ +specific_include_rules = { + # TODO(mash): Remove. http://crbug.com/720917. + "oobe_display_chooser\.*": [ + "+ui/events/devices/device_data_manager.h", + ] +}
diff --git a/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.cc index 2acd08b..13491ab1 100644 --- a/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.h" +#include "base/command_line.h" #include "base/i18n/timezone.h" #include "chrome/browser/chromeos/arc/optin/arc_optin_preference_handler.h" #include "chrome/browser/chromeos/login/screens/arc_terms_of_service_screen_view_observer.h" @@ -12,6 +13,10 @@ #include "chrome/browser/profiles/profile_manager.h" #include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" +#include "chromeos/chromeos_switches.h" +#include "chromeos/network/network_handler.h" +#include "chromeos/network/network_state.h" +#include "chromeos/network/network_state_handler.h" #include "components/login/localized_values_builder.h" #include "components/prefs/pref_service.h" #include "content/public/browser/web_contents.h" @@ -26,12 +31,15 @@ namespace chromeos { -ArcTermsOfServiceScreenHandler::ArcTermsOfServiceScreenHandler() - : BaseScreenHandler(kScreenId) { +ArcTermsOfServiceScreenHandler::ArcTermsOfServiceScreenHandler(OobeUI* owner) + : BaseScreenHandler(kScreenId), owner_(owner) { set_call_js_prefix(kJsScreenPath); } ArcTermsOfServiceScreenHandler::~ArcTermsOfServiceScreenHandler() { + owner_->RemoveObserver(this); + chromeos::NetworkHandler::Get()->network_state_handler()->RemoveObserver( + this, FROM_HERE); system::TimezoneSettings::GetInstance()->RemoveObserver(this); for (auto& observer : observer_list_) observer.OnViewDestroyed(this); @@ -44,17 +52,42 @@ &ArcTermsOfServiceScreenHandler::HandleAccept); } -void ArcTermsOfServiceScreenHandler::UpdateTimeZone() { - const std::string country_code = base::CountryCodeForCurrentTimezone(); - if (country_code == last_applied_contry_code_) +void ArcTermsOfServiceScreenHandler::MaybeLoadPlayStoreToS( + bool ignore_network_state) { + const chromeos::NetworkState* default_network = + chromeos::NetworkHandler::Get() + ->network_state_handler() + ->DefaultNetwork(); + if (!ignore_network_state && !default_network) return; - last_applied_contry_code_ = country_code; - CallJS("setCountryCode", country_code); + const std::string country_code = base::CountryCodeForCurrentTimezone(); + CallJS("loadPlayStoreToS", country_code); +} + +void ArcTermsOfServiceScreenHandler::OnCurrentScreenChanged( + OobeScreen current_screen, + OobeScreen new_screen) { + if (new_screen != OobeScreen::SCREEN_GAIA_SIGNIN) + return; + + const base::CommandLine* command_line = + base::CommandLine::ForCurrentProcess(); + if (!command_line->HasSwitch(chromeos::switches::kEnableArcOOBEOptIn)) + return; + + owner_->RemoveObserver(this); + MaybeLoadPlayStoreToS(false); + StartNetworkAndTimeZoneObserving(); } void ArcTermsOfServiceScreenHandler::TimezoneChanged( const icu::TimeZone& timezone) { - UpdateTimeZone(); + MaybeLoadPlayStoreToS(false); +} + +void ArcTermsOfServiceScreenHandler::DefaultNetworkChanged( + const NetworkState* network) { + MaybeLoadPlayStoreToS(false); } void ArcTermsOfServiceScreenHandler::DeclareLocalizedValues( @@ -140,10 +173,24 @@ pref_handler_.reset(); } -void ArcTermsOfServiceScreenHandler::Initialize() { - if (!show_on_init_) +void ArcTermsOfServiceScreenHandler::StartNetworkAndTimeZoneObserving() { + if (network_time_zone_observing_) return; + chromeos::NetworkHandler::Get()->network_state_handler()->AddObserver( + this, FROM_HERE); + system::TimezoneSettings::GetInstance()->AddObserver(this); + network_time_zone_observing_ = true; +} + +void ArcTermsOfServiceScreenHandler::Initialize() { + if (!show_on_init_) { + // Send time zone information as soon as possible to able to pre-load the + // Play Store ToS. + owner_->AddObserver(this); + return; + } + Show(); show_on_init_ = false; } @@ -158,11 +205,11 @@ // ToS then prefs::kArcEnabled is automatically reset in ArcSessionManager. profile->GetPrefs()->SetBoolean(prefs::kArcEnabled, true); - system::TimezoneSettings::GetInstance()->AddObserver(this); - ShowScreen(kScreenId); - UpdateTimeZone(); + MaybeLoadPlayStoreToS(true); + StartNetworkAndTimeZoneObserving(); + pref_handler_.reset(new arc::ArcOptInPreferenceHandler( this, profile->GetPrefs())); pref_handler_->Start();
diff --git a/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.h index f37747ee..4500256 100644 --- a/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.h
@@ -13,6 +13,8 @@ #include "chrome/browser/chromeos/arc/optin/arc_optin_preference_handler_observer.h" #include "chrome/browser/chromeos/login/screens/arc_terms_of_service_screen_view.h" #include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h" +#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" +#include "chromeos/network/network_state_handler_observer.h" #include "chromeos/settings/timezone_settings.h" namespace arc { @@ -26,9 +28,11 @@ : public BaseScreenHandler, public ArcTermsOfServiceScreenView, public arc::ArcOptInPreferenceHandlerObserver, - public system::TimezoneSettings::Observer { + public OobeUI::Observer, + public system::TimezoneSettings::Observer, + public chromeos::NetworkStateHandlerObserver { public: - ArcTermsOfServiceScreenHandler(); + explicit ArcTermsOfServiceScreenHandler(OobeUI* owner); ~ArcTermsOfServiceScreenHandler() override; // content::WebUIMessageHandler: @@ -44,9 +48,16 @@ void Show() override; void Hide() override; + // OobeUI::Observer: + void OnCurrentScreenChanged(OobeScreen current_screen, + OobeScreen new_screen) override; + // system::TimezoneSettings::Observer: void TimezoneChanged(const icu::TimeZone& timezone) override; + // chromeos::NetworkStateHandlerObserver: + void DefaultNetworkChanged(const NetworkState* network) override; + private: // BaseScreenHandler: void Initialize() override; @@ -55,7 +66,11 @@ void HandleSkip(); void HandleAccept(bool enable_backup_restore, bool enable_location_services); - void UpdateTimeZone(); + // Loads Play Store ToS content in case default network exists. If + // |ignore_network_state| is set then network state is not checked. + void MaybeLoadPlayStoreToS(bool ignore_network_state); + + void StartNetworkAndTimeZoneObserving(); // arc::ArcOptInPreferenceHandlerObserver: void OnMetricsModeChanged(bool enabled, bool managed) override; @@ -64,11 +79,14 @@ base::ObserverList<ArcTermsOfServiceScreenViewObserver, true> observer_list_; + // Unowned pointer; + OobeUI* const owner_; + // Whether the screen should be shown right after initialization. bool show_on_init_ = false; - // To prevent redundant updates, keep last country code used for update. - std::string last_applied_contry_code_; + // Indicates that we already started network and time zone observing. + bool network_time_zone_observing_ = false; std::unique_ptr<arc::ArcOptInPreferenceHandler> pref_handler_;
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc index 810cc0b..4359367 100644 --- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -331,6 +331,13 @@ params.SetString("enterpriseEnrollmentDomain", enterprise_enrollment_domain); } + params.SetBoolean("enterpriseManagedDevice", + g_browser_process->platform_part() + ->browser_policy_connector_chromeos() + ->IsEnterpriseManaged()); + params.SetBoolean( + "hasDeviceOwner", + user_manager::UserManager::Get()->GetOwnerAccountId().is_valid()); params.SetString("chromeType", GetChromeType()); params.SetString("clientId",
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc index ccefe00..75d4680 100644 --- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc +++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -291,7 +291,7 @@ AddScreenHandler( base::MakeUnique<TermsOfServiceScreenHandler>(core_handler_)); - AddScreenHandler(base::MakeUnique<ArcTermsOfServiceScreenHandler>()); + AddScreenHandler(base::MakeUnique<ArcTermsOfServiceScreenHandler>(this)); AddScreenHandler(base::MakeUnique<UserImageScreenHandler>());
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 89c8f21..10588b0 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -132,8 +132,18 @@ const char kBackgroundLockScreenApps[] = "LOCK_SCREEN_APPS_STATE.BACKGROUND"; const char kForegroundLockScreenApps[] = "LOCK_SCREEN_APPS_STATE.FOREGROUND"; const char kAvailableLockScreenApps[] = "LOCK_SCREEN_APPS_STATE.AVAILABLE"; -const char kLaunchRequestedLockScreenApps[] = - "LOCK_SCREEN_APPS_STATE.LAUNCH_REQUESTED"; + +// Constants for new lock screen note request type. +const char kNewNoteRequestTap[] = "NEW_NOTE_REQUEST.TAP"; +const char kNewNoteRequestSwipe[] = "NEW_NOTE_REQUEST.SWIPE"; +const char kNewNoteRequestKeyboard[] = "NEW_NOTE_REQUEST.KEYBOARD"; + +// Constants for reporting action taken on lock screen UI when lock screen app +// window was in background. +const char kRequestShutdownFromLockScreenAppUnlockUi[] = + "LOCK_SCREEN_APPS_UNLOCK_ACTION.SHUTDOWN"; +const char kRequestSignoutFromLockScreenAppUnlockUi[] = + "LOCK_SCREEN_APPS_UNLOCK_ACTION.SIGN_OUT"; ash::WallpaperController* GetWallpaperController() { if (!ash::Shell::HasInstance()) @@ -546,6 +556,10 @@ &SigninScreenHandler::HandleLaunchArcKioskApp); AddCallback("setLockScreenAppsState", &SigninScreenHandler::HandleSetLockScreenAppsState); + AddCallback("recordLockScreenAppUnlockAction", + &SigninScreenHandler::HandleRecordLockScreenAppUnlockUIAction); + AddCallback("requestNewLockScreenNote", + &SigninScreenHandler::HandleRequestNewNoteAction); } void SigninScreenHandler::Show(const LoginScreenContext& context) { @@ -1519,6 +1533,44 @@ weak_factory_.GetWeakPtr())); } +void SigninScreenHandler::HandleRequestNewNoteAction( + const std::string& request_type) { + lock_screen_apps::StateController* state_controller = + lock_screen_apps::StateController::Get(); + + if (request_type == kNewNoteRequestTap) { + state_controller->HandleNewNoteRequestFromLockScreen( + lock_screen_apps::StateController::NewNoteRequestType:: + kLockScreenUiTap); + } else if (request_type == kNewNoteRequestSwipe) { + state_controller->HandleNewNoteRequestFromLockScreen( + lock_screen_apps::StateController::NewNoteRequestType:: + kLockScreenUiSwipe); + } else if (request_type == kNewNoteRequestKeyboard) { + state_controller->HandleNewNoteRequestFromLockScreen( + lock_screen_apps::StateController::NewNoteRequestType:: + kLockScreenUiKeyboard); + } else { + NOTREACHED() << "Unknown request type " << request_type; + } +} + +void SigninScreenHandler::HandleRecordLockScreenAppUnlockUIAction( + const std::string& action) { + lock_screen_apps::StateController* state_controller = + lock_screen_apps::StateController::Get(); + + if (action == kRequestShutdownFromLockScreenAppUnlockUi) { + state_controller->RecordLockScreenAppUnlockAction( + lock_screen_apps::StateController::LockScreenUnlockAction::kShutdown); + } else if (action == kRequestSignoutFromLockScreenAppUnlockUi) { + state_controller->RecordLockScreenAppUnlockAction( + lock_screen_apps::StateController::LockScreenUnlockAction::kSignOut); + } else { + NOTREACHED() << "Unknown action " << action; + } +} + void SigninScreenHandler::HandleSetLockScreenAppsState( const std::string& state) { lock_screen_apps::StateController* state_controller = @@ -1528,8 +1580,6 @@ state_controller->MoveToBackground(); } else if (state == kForegroundLockScreenApps) { state_controller->MoveToForeground(); - } else if (state == kLaunchRequestedLockScreenApps) { - state_controller->RequestNewLockScreenNote(); } }
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 6c2cad9..1a1a349 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
@@ -426,6 +426,8 @@ void HandleFirstIncorrectPasswordAttempt(const AccountId& account_id); void HandleMaxIncorrectPasswordAttempts(const AccountId& account_id); void HandleSendFeedbackAndResyncUserData(); + void HandleRequestNewNoteAction(const std::string& request_type); + void HandleRecordLockScreenAppUnlockUIAction(const std::string& action); void HandleSetLockScreenAppsState(const std::string& state); // Sends the list of |keyboard_layouts| available for the |locale| that is
diff --git a/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc b/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc index 3db6e62..a327c58 100644 --- a/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc +++ b/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc
@@ -63,8 +63,13 @@ CrosSettings::Initialize(); NetworkHandler::Initialize(); + base::RunLoop().RunUntilIdle(); + } + + void SetEthernetService() { ShillServiceClient::TestInterface* service_test = DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface(); + service_test->ClearServices(); service_test->AddService("/service/eth", "eth" /* guid */, "eth", @@ -73,6 +78,16 @@ base::RunLoop().RunUntilIdle(); } + void SetCellularService() { + ShillServiceClient::TestInterface* service_test = + DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface(); + service_test->ClearServices(); + service_test->AddService("/service/cell", "cell" /* guid */, "cell", + shill::kTypeCellular, shill::kStateOnline, + true /* visible */); + base::RunLoop().RunUntilIdle(); + } + void TearDown() override { NetworkHandler::Shutdown(); @@ -101,6 +116,7 @@ // 4. When update engine becomes idle downloading of the stable channel is // initiated. TEST_F(VersionUpdaterCrosTest, TwoOverlappingSetChannelRequests) { + SetEthernetService(); version_updater_->SetChannel("beta-channel", true); { @@ -152,4 +168,27 @@ EXPECT_EQ(2, fake_update_engine_client_->request_update_check_call_count()); } +// Test that when interactively checking for update, cellular connection is +// allowed in Chrome by default, so that the request will be sent to Update +// Engine. +TEST_F(VersionUpdaterCrosTest, InteractiveCellularUpdateAllowed) { + SetCellularService(); + EXPECT_EQ(0, fake_update_engine_client_->request_update_check_call_count()); + version_updater_->CheckForUpdate(base::Bind(&CheckNotification), + VersionUpdater::PromoteCallback()); + EXPECT_EQ(1, fake_update_engine_client_->request_update_check_call_count()); +} + +// Test that after update over cellular one time permission is set successfully, +// an update check will be triggered. +TEST_F(VersionUpdaterCrosTest, CellularUpdateOneTimePermission) { + SetCellularService(); + EXPECT_EQ(0, fake_update_engine_client_->request_update_check_call_count()); + const std::string& update_version = "9999.0.0"; + const int64_t update_size = 99999; + version_updater_->SetUpdateOverCellularOneTimePermission( + base::Bind(&CheckNotification), update_version, update_size); + EXPECT_EQ(1, fake_update_engine_client_->request_update_check_call_count()); +} + } // namespace chromeos
diff --git a/chrome/browser/ui/webui/media_router/media_router_localized_strings_provider.cc b/chrome/browser/ui/webui/media_router/media_router_localized_strings_provider.cc index 17af03a..416111a 100644 --- a/chrome/browser/ui/webui/media_router/media_router_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/media_router/media_router_localized_strings_provider.cc
@@ -49,6 +49,10 @@ IDS_MEDIA_ROUTER_ROUTE_DETAILS_SEEK_TITLE); html_source->AddLocalizedString("volumeTitle", IDS_MEDIA_ROUTER_ROUTE_DETAILS_VOLUME_TITLE); + html_source->AddLocalizedString( + "currentTimeLabel", IDS_MEDIA_ROUTER_ROUTE_DETAILS_CURRENT_TIME_LABEL); + html_source->AddLocalizedString( + "durationLabel", IDS_MEDIA_ROUTER_ROUTE_DETAILS_DURATION_LABEL); } void AddIssuesStrings(content::WebUIDataSource* html_source) {
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc index 7e3fbe8..d0325e68 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -617,6 +617,11 @@ "grantExtensionPrinterAccess", base::Bind(&PrintPreviewHandler::HandleGrantExtensionPrinterAccess, base::Unretained(this))); +} + +void PrintPreviewHandler::OnJavascriptAllowed() { + // Now that the UI is initialized, any future account changes will require + // a printer list refresh. RegisterForGaiaCookieChanges(); } @@ -624,6 +629,7 @@ // Normally the handler and print preview will be destroyed together, but // this is necessary for refresh or navigation from the chrome://print page. weak_factory_.InvalidateWeakPtrs(); + UnregisterForGaiaCookieChanges(); } WebContents* PrintPreviewHandler::preview_web_contents() const { @@ -1439,7 +1445,7 @@ } void PrintPreviewHandler::OnPrintPreviewReady(int preview_uid, int request_id) { - if (request_id < 0 || preview_callbacks_.empty()) { + if (request_id < 0 || preview_callbacks_.empty() || !IsJavascriptAllowed()) { // invalid ID or extra message BadMessageReceived(); return; @@ -1451,7 +1457,7 @@ } void PrintPreviewHandler::OnPrintPreviewFailed() { - if (preview_callbacks_.empty()) { + if (preview_callbacks_.empty() || !IsJavascriptAllowed()) { BadMessageReceived(); return; } @@ -1466,7 +1472,7 @@ } void PrintPreviewHandler::OnInvalidPrinterSettings() { - if (preview_callbacks_.empty()) { + if (preview_callbacks_.empty() || !IsJavascriptAllowed()) { BadMessageReceived(); return; } @@ -1479,6 +1485,11 @@ void PrintPreviewHandler::SendPrintPresetOptions(bool disable_scaling, int copies, int duplex) { + if (preview_callbacks_.empty() || !IsJavascriptAllowed()) { + BadMessageReceived(); + return; + } + FireWebUIListener("print-preset-options", base::Value(disable_scaling), base::Value(copies), base::Value(duplex)); } @@ -1486,6 +1497,11 @@ void PrintPreviewHandler::SendPageCountReady(int page_count, int request_id, int fit_to_page_scaling) { + if (preview_callbacks_.empty() || !IsJavascriptAllowed()) { + BadMessageReceived(); + return; + } + FireWebUIListener("page-count-ready", base::Value(page_count), base::Value(request_id), base::Value(fit_to_page_scaling)); } @@ -1493,6 +1509,11 @@ void PrintPreviewHandler::SendPageLayoutReady( const base::DictionaryValue& layout, bool has_custom_page_size_style) { + if (preview_callbacks_.empty() || !IsJavascriptAllowed()) { + BadMessageReceived(); + return; + } + FireWebUIListener("page-layout-ready", layout, base::Value(has_custom_page_size_style)); } @@ -1500,12 +1521,17 @@ void PrintPreviewHandler::SendPagePreviewReady(int page_index, int preview_uid, int preview_response_id) { + if (!IsJavascriptAllowed()) { + BadMessageReceived(); + return; + } + FireWebUIListener("page-preview-ready", base::Value(page_index), base::Value(preview_uid), base::Value(preview_response_id)); } void PrintPreviewHandler::OnPrintPreviewCancelled() { - if (preview_callbacks_.empty()) { + if (preview_callbacks_.empty() || !IsJavascriptAllowed()) { BadMessageReceived(); return; }
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.h b/chrome/browser/ui/webui/print_preview/print_preview_handler.h index 72654d9a..9cf1bd3e 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler.h +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.h
@@ -54,7 +54,7 @@ // WebUIMessageHandler implementation. void RegisterMessages() override; - + void OnJavascriptAllowed() override; void OnJavascriptDisallowed() override; // SelectFileDialog::Listener implementation.
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc index e6f86a8..f482fab 100644 --- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -1497,7 +1497,6 @@ {"cupsPrintersLearnMoreLabel", IDS_SETTINGS_PRINTING_CUPS_PRINTERS_LEARN_MORE_LABEL}, {"addCupsPrinter", IDS_SETTINGS_PRINTING_CUPS_PRINTERS_ADD_PRINTER}, - {"cupsPrinterDetails", IDS_SETTINGS_PRINTING_CUPS_PRINTERS_DETAILS}, {"editPrinter", IDS_SETTINGS_PRINTING_CUPS_PRINTERS_EDIT}, {"removePrinter", IDS_SETTINGS_PRINTING_CUPS_PRINTERS_REMOVE}, {"searchLabel", IDS_SETTINGS_PRINTING_CUPS_SEARCH_LABEL},
diff --git a/chrome/common/DEPS b/chrome/common/DEPS index f50eedd..a715de2c 100644 --- a/chrome/common/DEPS +++ b/chrome/common/DEPS
@@ -24,7 +24,7 @@ "+components/password_manager/core/common", "+components/policy/core/common", "+components/printing/common", - "+components/safe_browsing/csd.pb.h", + "+components/safe_browsing/proto/csd.pb.h", "+components/safe_browsing/web_ui/constants.h", "+components/signin/core/common", "+components/translate/core/common",
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index e113fad..2dd561d 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -35,6 +35,8 @@ #endif // defined(OS_MACOSX) #if !defined(OS_ANDROID) +const base::Feature kAnimatedAppMenuIcon{"AnimatedAppMenuIcon", + base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kAppBanners { "AppBanners", #if defined(OS_CHROMEOS) @@ -382,6 +384,12 @@ // foreground tab's user experience. const base::Feature kStaggeredBackgroundTabOpen{ "StaggeredBackgroundTabOpen", base::FEATURE_DISABLED_BY_DEFAULT}; + +// This controls whether we are running experiment with staggered background +// tab open. For control group, this should be disabled. This depends on +// |kStaggeredBackgroundTabOpen| above. +const base::Feature kStaggeredBackgroundTabOpenExperiment{ + "StaggeredBackgroundTabOpenExperiment", base::FEATURE_ENABLED_BY_DEFAULT}; #endif // Enables or disables the creation of (legacy) supervised users. Does not
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index 0405db6..64a25d55 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -30,6 +30,7 @@ #endif // defined(OS_MACOSX) #if !defined(OS_ANDROID) +extern const base::Feature kAnimatedAppMenuIcon; extern const base::Feature kAppBanners; #endif // !defined(OS_ANDROID) @@ -197,6 +198,7 @@ #if !defined(OS_ANDROID) extern const base::Feature kStaggeredBackgroundTabOpen; +extern const base::Feature kStaggeredBackgroundTabOpenExperiment; #endif extern const base::Feature kSupervisedUserCreation;
diff --git a/chrome/common/extensions/api/common_extension_api_unittest.cc b/chrome/common/extensions/api/common_extension_api_unittest.cc index 94b67b94c..711e1fb 100644 --- a/chrome/common/extensions/api/common_extension_api_unittest.cc +++ b/chrome/common/extensions/api/common_extension_api_unittest.cc
@@ -252,7 +252,8 @@ .Set("manifest_version", 2) .Build()) .Build(); - Feature* test_feature = api_feature_provider.GetFeature("alias_api_source"); + const Feature* test_feature = + api_feature_provider.GetFeature("alias_api_source"); ASSERT_TRUE(test_feature); ASSERT_FALSE(api.IsAnyFeatureAvailableToContext( *test_feature, extension.get(), Feature::UNBLESSED_EXTENSION_CONTEXT, @@ -327,7 +328,7 @@ api.add_fake_schema(key); ExtensionAPI::OverrideSharedInstanceForTest scope(&api); - Feature* test_feature = + const Feature* test_feature = api_feature_provider.GetFeature(test_data[i].api_full_name); ASSERT_TRUE(test_feature); EXPECT_EQ(test_data[i].expect_is_available, @@ -753,18 +754,19 @@ std::unique_ptr<ExtensionAPI> api( ExtensionAPI::CreateWithDefaultConfiguration()); - SimpleFeature* browser_action = static_cast<SimpleFeature*>( + const SimpleFeature* browser_action = static_cast<const SimpleFeature*>( api->GetFeatureDependency("api:browserAction")); - SimpleFeature* browser_action_set_title = static_cast<SimpleFeature*>( - api->GetFeatureDependency("api:browserAction.setTitle")); + const SimpleFeature* browser_action_set_title = + static_cast<const SimpleFeature*>( + api->GetFeatureDependency("api:browserAction.setTitle")); struct { - SimpleFeature* feature; + const SimpleFeature* feature; // TODO(aa): More stuff to test over time. } test_data[] = {{browser_action}, {browser_action_set_title}}; for (size_t i = 0; i < arraysize(test_data); ++i) { - SimpleFeature* feature = test_data[i].feature; + const SimpleFeature* feature = test_data[i].feature; ASSERT_TRUE(feature) << i; EXPECT_TRUE(feature->whitelist().empty());
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 3b455db41..62df9387 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -144,8 +144,9 @@ // shutdown. Used to determine the exit type the last time the profile was open. const char kSessionExitType[] = "profile.exit_type"; -// Stores the total amount of active session time for the user. -const char kSessionTimeTotal[] = "profile.total_time"; +// Stores the total amount of observed active session time for the user. +// Observed time is active session time. +const char kObservedSessionTime[] = "profile.observed_time"; // The last time that the site engagement service recorded an engagement event // for this profile for any URL. Recorded only during shutdown. Used to prevent
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index f4928d6..da46f99f 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -56,7 +56,7 @@ extern const char kRestoreOnStartup[]; extern const char kSessionExitedCleanly[]; extern const char kSessionExitType[]; -extern const char kSessionTimeTotal[]; +extern const char kObservedSessionTime[]; extern const char kSiteEngagementLastUpdateTime[]; extern const char kSupervisedUserApprovedExtensions[]; extern const char kSupervisedUserCustodianEmail[];
diff --git a/chrome/common/safe_browsing/archive_analyzer_results.h b/chrome/common/safe_browsing/archive_analyzer_results.h index a9635aa..b0c6e110 100644 --- a/chrome/common/safe_browsing/archive_analyzer_results.h +++ b/chrome/common/safe_browsing/archive_analyzer_results.h
@@ -12,7 +12,7 @@ #include "base/files/file_path.h" #include "build/build_config.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" namespace safe_browsing { @@ -33,4 +33,4 @@ } // namespace safe_browsing -#endif // CHROME_COMMON_SAFE_BROWSING_ARCHIVE_ANALYZER_RESULTS_H_ \ No newline at end of file +#endif // CHROME_COMMON_SAFE_BROWSING_ARCHIVE_ANALYZER_RESULTS_H_
diff --git a/chrome/common/safe_browsing/binary_feature_extractor.cc b/chrome/common/safe_browsing/binary_feature_extractor.cc index 538a81e..896768a6 100644 --- a/chrome/common/safe_browsing/binary_feature_extractor.cc +++ b/chrome/common/safe_browsing/binary_feature_extractor.cc
@@ -10,7 +10,7 @@ #include "base/files/file.h" #include "base/files/file_path.h" #include "base/files/memory_mapped_file.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "crypto/secure_hash.h" #include "crypto/sha2.h"
diff --git a/chrome/common/safe_browsing/binary_feature_extractor_mac.cc b/chrome/common/safe_browsing/binary_feature_extractor_mac.cc index 7d64fae..9edb648 100644 --- a/chrome/common/safe_browsing/binary_feature_extractor_mac.cc +++ b/chrome/common/safe_browsing/binary_feature_extractor_mac.cc
@@ -8,7 +8,7 @@ #include <stdint.h> #include "chrome/common/safe_browsing/mach_o_image_reader_mac.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" namespace safe_browsing {
diff --git a/chrome/common/safe_browsing/binary_feature_extractor_mac_unittest.cc b/chrome/common/safe_browsing/binary_feature_extractor_mac_unittest.cc index ec29387..f4fa75f 100644 --- a/chrome/common/safe_browsing/binary_feature_extractor_mac_unittest.cc +++ b/chrome/common/safe_browsing/binary_feature_extractor_mac_unittest.cc
@@ -7,7 +7,7 @@ #include "base/files/file_path.h" #include "base/path_service.h" #include "chrome/common/chrome_paths.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "testing/gtest/include/gtest/gtest.h" namespace safe_browsing {
diff --git a/chrome/common/safe_browsing/binary_feature_extractor_unittest.cc b/chrome/common/safe_browsing/binary_feature_extractor_unittest.cc index 48b1847..8cc9823 100644 --- a/chrome/common/safe_browsing/binary_feature_extractor_unittest.cc +++ b/chrome/common/safe_browsing/binary_feature_extractor_unittest.cc
@@ -13,7 +13,7 @@ #include "base/files/file.h" #include "base/files/scoped_temp_dir.h" #include "base/path_service.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "crypto/sha2.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/common/safe_browsing/binary_feature_extractor_win.cc b/chrome/common/safe_browsing/binary_feature_extractor_win.cc index ffdb9186..52a11373 100644 --- a/chrome/common/safe_browsing/binary_feature_extractor_win.cc +++ b/chrome/common/safe_browsing/binary_feature_extractor_win.cc
@@ -13,7 +13,7 @@ #include "base/files/file_path.h" #include "base/logging.h" #include "chrome/common/safe_browsing/pe_image_reader_win.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" namespace safe_browsing {
diff --git a/chrome/common/safe_browsing/binary_feature_extractor_win_unittest.cc b/chrome/common/safe_browsing/binary_feature_extractor_win_unittest.cc index 63974925..e72c7382 100644 --- a/chrome/common/safe_browsing/binary_feature_extractor_win_unittest.cc +++ b/chrome/common/safe_browsing/binary_feature_extractor_win_unittest.cc
@@ -12,7 +12,7 @@ #include "base/memory/ref_counted.h" #include "base/path_service.h" #include "chrome/common/chrome_paths.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "net/cert/x509_cert_types.h" #include "net/cert/x509_certificate.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/common/safe_browsing/download_protection_util.h b/chrome/common/safe_browsing/download_protection_util.h index dedc286..d2e4579 100644 --- a/chrome/common/safe_browsing/download_protection_util.h +++ b/chrome/common/safe_browsing/download_protection_util.h
@@ -6,7 +6,7 @@ #define CHROME_COMMON_SAFE_BROWSING_DOWNLOAD_PROTECTION_UTIL_H_ #include "base/files/file_path.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" namespace safe_browsing { namespace download_protection_util {
diff --git a/chrome/common/safe_browsing/zip_analyzer.cc b/chrome/common/safe_browsing/zip_analyzer.cc index 0d31d080..29f625b 100644 --- a/chrome/common/safe_browsing/zip_analyzer.cc +++ b/chrome/common/safe_browsing/zip_analyzer.cc
@@ -19,7 +19,7 @@ #include "chrome/common/safe_browsing/binary_feature_extractor.h" #include "chrome/common/safe_browsing/download_protection_util.h" #include "chrome/common/safe_browsing/file_type_policies.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "crypto/secure_hash.h" #include "crypto/sha2.h" #include "third_party/zlib/google/zip_reader.h"
diff --git a/chrome/common/safe_browsing/zip_analyzer.h b/chrome/common/safe_browsing/zip_analyzer.h index 5b3c009..2e2a965ad 100644 --- a/chrome/common/safe_browsing/zip_analyzer.h +++ b/chrome/common/safe_browsing/zip_analyzer.h
@@ -9,7 +9,7 @@ #define CHROME_COMMON_SAFE_BROWSING_ZIP_ANALYZER_H_ #include "base/files/file.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" namespace safe_browsing {
diff --git a/chrome/installer/zucchini/BUILD.gn b/chrome/installer/zucchini/BUILD.gn index 805ae5f..fe66f3d 100644 --- a/chrome/installer/zucchini/BUILD.gn +++ b/chrome/installer/zucchini/BUILD.gn
@@ -3,6 +3,7 @@ # found in the LICENSE file. import("//chrome/process_version_rc_template.gni") +import("//testing/libfuzzer/fuzzer_test.gni") import("//testing/test.gni") static_library("zucchini_lib") { @@ -79,6 +80,16 @@ } } +fuzzer_test("zucchini_patch_fuzzer") { + sources = [ + "patch_fuzzer.cc", + ] + deps = [ + ":zucchini_lib", + "//base", + ] +} + test("zucchini_unittests") { sources = [ "buffer_sink_unittest.cc",
diff --git a/chrome/installer/zucchini/patch_fuzzer.cc b/chrome/installer/zucchini/patch_fuzzer.cc new file mode 100644 index 0000000..e4d61c1 --- /dev/null +++ b/chrome/installer/zucchini/patch_fuzzer.cc
@@ -0,0 +1,19 @@ +// 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 <stddef.h> +#include <stdint.h> + +#include "base/optional.h" +#include "chrome/installer/zucchini/buffer_view.h" +#include "chrome/installer/zucchini/patch_reader.h" + +// Entry point for LibFuzzer. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + logging::SetMinLogLevel(3); // Disable console spamming. + zucchini::ConstBufferView patch(data, size); + base::Optional<zucchini::EnsemblePatchReader> patch_reader = + zucchini::EnsemblePatchReader::Create(patch); + return 0; +}
diff --git a/chrome/profiling/BUILD.gn b/chrome/profiling/BUILD.gn index 01b0589c..d6b1f49 100644 --- a/chrome/profiling/BUILD.gn +++ b/chrome/profiling/BUILD.gn
@@ -40,7 +40,9 @@ deps = [ "//base", "//chrome/common", + "//content/public/child", "//mojo/edk/system", + "//services/resource_coordinator/public/cpp:resource_coordinator_cpp", ] }
diff --git a/chrome/profiling/DEPS b/chrome/profiling/DEPS index 08bf5f3..a79c379 100644 --- a/chrome/profiling/DEPS +++ b/chrome/profiling/DEPS
@@ -1,5 +1,6 @@ -include_rules = [ - "+content/public/child", - "+mojo/edk/embedder", - "+services/service_manager/public/cpp", -] +include_rules = [ + "+content/public/child", + "+mojo/edk/embedder", + "+services/resource_coordinator/public", + "+services/service_manager/public/cpp", +]
diff --git a/chrome/profiling/json_exporter.cc b/chrome/profiling/json_exporter.cc index 9e0bf06..e490fa6 100644 --- a/chrome/profiling/json_exporter.cc +++ b/chrome/profiling/json_exporter.cc
@@ -7,6 +7,8 @@ #include <map> #include "base/strings/string_number_conversions.h" +#include "base/trace_event/trace_event_argument.h" +#include "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.h" namespace profiling { @@ -54,21 +56,38 @@ << "\"args\":{\"name\":\"Browser process\"}}"; } -// Writes the dictionary keys to preceed a "heaps_v2" trace argument. This is -// "v2" heap dump format. -void WriteHeapsV2Header(int pid, std::ostream& out) { +// Writes the dictionary keys to preceed a "dumps" trace argument. +void WriteDumpsHeader(int pid, std::ostream& out) { out << "{ \"pid\":" << pid << ","; out << "\"ph\":\"v\","; out << "\"name\":\"periodic_interval\","; out << "\"args\":{"; - out << "\"dumps\":{"; - out << "\"level_of_detail\":\"detailed\","; + out << "\"dumps\":{\n"; +} + +void WriteDumpsFooter(std::ostream& out) { + out << "}}}"; // dumps, args, event +} + +// Writes the dictionary keys to preceed a "heaps_v2" trace argument inside a +// "dumps". This is "v2" heap dump format. +void WriteHeapsV2Header(std::ostream& out) { + out << "\"level_of_detail\":\"detailed\",\n"; out << "\"heaps_v2\": {\n"; } // Closes the dictionaries from the WriteHeapsV2Header function above. void WriteHeapsV2Footer(std::ostream& out) { - out << "}}}}"; // heaps_v2, dumps, args, event + out << "}"; // heaps_v2 +} + +void WriteMemoryMaps( + const std::vector<memory_instrumentation::mojom::VmRegionPtr>& maps, + std::ostream& out) { + base::trace_event::TracedValue traced_value; + memory_instrumentation::TracingObserver::MemoryMapsAsValueInto(maps, + &traced_value); + out << "\"process_mmaps\":" << traced_value.ToString(); } // Inserts or retrieves the ID for a string in the string table. @@ -200,13 +219,20 @@ } // namespace -void ExportAllocationEventSetToJSON(int pid, - const AllocationEventSet& event_set, - std::ostream& out) { +void ExportAllocationEventSetToJSON( + int pid, + const AllocationEventSet& event_set, + const std::vector<memory_instrumentation::mojom::VmRegionPtr>& maps, + std::ostream& out) { out << "{ \"traceEvents\": ["; WriteProcessName(pid, out); out << ",\n"; - WriteHeapsV2Header(pid, out); + WriteDumpsHeader(pid, out); + + WriteMemoryMaps(maps, out); + out << ",\n"; + + WriteHeapsV2Header(out); StringTable string_table; @@ -261,6 +287,7 @@ out << "}}\n"; // End of allocators section. WriteHeapsV2Footer(out); + WriteDumpsFooter(out); out << "]}\n"; }
diff --git a/chrome/profiling/json_exporter.h b/chrome/profiling/json_exporter.h index 6f7ac767..fc5791c 100644 --- a/chrome/profiling/json_exporter.h +++ b/chrome/profiling/json_exporter.h
@@ -6,14 +6,18 @@ #define CHROME_PROFILING_JSON_EXPORTER_H_ #include <iosfwd> +#include <vector> #include "chrome/profiling/allocation_event.h" +#include "services/resource_coordinator/public/interfaces/memory_instrumentation/memory_instrumentation.mojom.h" namespace profiling { -void ExportAllocationEventSetToJSON(int pid, - const AllocationEventSet& set, - std::ostream& out); +void ExportAllocationEventSetToJSON( + int pid, + const AllocationEventSet& set, + const std::vector<memory_instrumentation::mojom::VmRegionPtr>& maps, + std::ostream& out); } // namespace profiling
diff --git a/chrome/profiling/json_exporter_unittest.cc b/chrome/profiling/json_exporter_unittest.cc index 2f469ee..ffd1367 100644 --- a/chrome/profiling/json_exporter_unittest.cc +++ b/chrome/profiling/json_exporter_unittest.cc
@@ -6,15 +6,20 @@ #include <sstream> +#include "base/gtest_prod_util.h" #include "base/json/json_reader.h" +#include "base/process/process.h" #include "base/values.h" #include "chrome/profiling/backtrace_storage.h" +#include "services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h" #include "testing/gtest/include/gtest/gtest.h" namespace profiling { namespace { +using MemoryMap = std::vector<memory_instrumentation::mojom::VmRegionPtr>; + // Finds the first period_interval trace event in the given JSON trace. // Returns null on failure. const base::Value* FindFirstPeriodicInterval(const base::Value& root) { @@ -33,6 +38,37 @@ return nullptr; } +// Finds the first vm region in the given periodic interval. Returns null on +// failure. +const base::Value* FindFirstRegionWithAnyName( + const base::Value* periodic_interval) { + auto found_args = + periodic_interval->FindKeyOfType("args", base::Value::Type::DICTIONARY); + if (found_args == periodic_interval->DictEnd()) + return nullptr; + auto found_dumps = + found_args->second.FindKeyOfType("dumps", base::Value::Type::DICTIONARY); + if (found_dumps == found_args->second.DictEnd()) + return nullptr; + auto found_mmaps = found_dumps->second.FindKeyOfType( + "process_mmaps", base::Value::Type::DICTIONARY); + if (found_mmaps == found_dumps->second.DictEnd()) + return nullptr; + auto found_regions = + found_mmaps->second.FindKeyOfType("vm_regions", base::Value::Type::LIST); + if (found_regions == found_mmaps->second.DictEnd()) + return nullptr; + + for (const base::Value& cur : found_regions->second.GetList()) { + auto found_name = cur.FindKeyOfType("mf", base::Value::Type::STRING); + if (found_name == cur.DictEnd()) + return nullptr; + if (found_name->second.GetString() != "") + return &cur; + } + return nullptr; +} + } // namespace TEST(ProfilingJsonExporter, Simple) { @@ -53,7 +89,7 @@ events.insert(AllocationEvent(Address(0x3), 16, bt1)); std::ostringstream stream; - ExportAllocationEventSetToJSON(1234, events, stream); + ExportAllocationEventSetToJSON(1234, events, MemoryMap(), stream); std::string json = stream.str(); // JSON should parse. @@ -84,4 +120,38 @@ counts->GetList()[1].GetInt() == 1)); } +TEST(ProfilingJsonExporterTest, MemoryMaps) { + AllocationEventSet events; + std::vector<memory_instrumentation::mojom::VmRegionPtr> memory_maps = + memory_instrumentation::OSMetrics::GetProcessMemoryMaps( + base::Process::Current().Pid()); + ASSERT_GT(memory_maps.size(), 2u); + + std::ostringstream stream; + ExportAllocationEventSetToJSON(1234, events, memory_maps, stream); + std::string json = stream.str(); + + // JSON should parse. + base::JSONReader reader(base::JSON_PARSE_RFC); + std::unique_ptr<base::Value> root = reader.ReadToValue(stream.str()); + ASSERT_EQ(base::JSONReader::JSON_NO_ERROR, reader.error_code()) + << reader.GetErrorMessage(); + ASSERT_TRUE(root.get()); + + const base::Value* periodic_interval = FindFirstPeriodicInterval(*root); + ASSERT_TRUE(periodic_interval) << "Array contains no periodic_interval"; + const base::Value* region = FindFirstRegionWithAnyName(periodic_interval); + ASSERT_TRUE(region) << "Array contains no named vm regions"; + + auto start_address = region->FindKeyOfType("sa", base::Value::Type::STRING); + ASSERT_NE(start_address, region->DictEnd()); + EXPECT_NE(start_address->second.GetString(), ""); + EXPECT_NE(start_address->second.GetString(), "0"); + + auto size = region->FindKeyOfType("sz", base::Value::Type::STRING); + ASSERT_NE(size, region->DictEnd()); + EXPECT_NE(size->second.GetString(), ""); + EXPECT_NE(size->second.GetString(), "0"); +} + } // namespace profiling
diff --git a/chrome/profiling/memlog_connection_manager.cc b/chrome/profiling/memlog_connection_manager.cc index f1e5d70..ce3f9ba 100644 --- a/chrome/profiling/memlog_connection_manager.cc +++ b/chrome/profiling/memlog_connection_manager.cc
@@ -91,8 +91,10 @@ base::Unretained(this), pid)); } -void MemlogConnectionManager::DumpProcess(base::ProcessId pid, - base::File output_file) { +void MemlogConnectionManager::DumpProcess( + base::ProcessId pid, + const std::vector<memory_instrumentation::mojom::VmRegionPtr>& maps, + base::File output_file) { base::AutoLock l(connections_lock_); // Lock all connections to prevent deallocations of atoms from @@ -114,7 +116,8 @@ Connection* connection = it->second.get(); std::ostringstream oss; - ExportAllocationEventSetToJSON(pid, connection->tracker.live_allocs(), oss); + ExportAllocationEventSetToJSON(pid, connection->tracker.live_allocs(), maps, + oss); std::string reply = oss.str(); output_file.WriteAtCurrentPos(reply.c_str(), reply.size()); }
diff --git a/chrome/profiling/memlog_connection_manager.h b/chrome/profiling/memlog_connection_manager.h index 4339d0f..26e4635 100644 --- a/chrome/profiling/memlog_connection_manager.h +++ b/chrome/profiling/memlog_connection_manager.h
@@ -6,6 +6,7 @@ #define CHROME_PROFILING_MEMLOG_CONNECTION_MANAGER_H_ #include <string> +#include <vector> #include "base/containers/flat_map.h" #include "base/files/file.h" @@ -15,11 +16,14 @@ #include "base/synchronization/lock.h" #include "build/build_config.h" #include "chrome/profiling/backtrace_storage.h" +#include "services/resource_coordinator/public/interfaces/memory_instrumentation/memory_instrumentation.mojom.h" namespace base { + class SequencedTaskRunner; class SingleThreadTaskRunner; -} + +} // namespace base namespace profiling { @@ -36,8 +40,13 @@ BacktraceStorage* backtrace_storage); ~MemlogConnectionManager(); - // Dumps the memory log for the given process into |output_file|. - void DumpProcess(base::ProcessId pid, base::File output_file); + // Dumps the memory log for the given process into |output_file|. This must + // be provided the memory map for the given process since that is not tracked + // as part of the normal allocation process. + void DumpProcess( + base::ProcessId pid, + const std::vector<memory_instrumentation::mojom::VmRegionPtr>& maps, + base::File output_file); void OnNewConnection(base::ScopedPlatformFile file, base::ProcessId pid);
diff --git a/chrome/profiling/memlog_impl.cc b/chrome/profiling/memlog_impl.cc index 8b61c672..cc772e8 100644 --- a/chrome/profiling/memlog_impl.cc +++ b/chrome/profiling/memlog_impl.cc
@@ -4,9 +4,12 @@ #include "chrome/profiling/memlog_impl.h" +#include "base/trace_event/memory_dump_request_args.h" #include "chrome/profiling/memlog_receiver_pipe.h" #include "content/public/child/child_thread.h" +#include "content/public/common/service_names.mojom.h" #include "mojo/public/cpp/system/platform_handle.h" +#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h" namespace profiling { @@ -14,7 +17,8 @@ : io_runner_(content::ChildThread::Get()->GetIOTaskRunner()), connection_manager_( new MemlogConnectionManager(io_runner_, &backtrace_storage_), - DeleteOnRunner(FROM_HERE, io_runner_.get())) {} + DeleteOnRunner(FROM_HERE, io_runner_.get())), + weak_factory_(this) {} MemlogImpl::~MemlogImpl() {} @@ -42,10 +46,48 @@ return; } base::File file(platform_file); + + // Need a memory map to make sense of the dump. The dump will be triggered + // in the memory map global dump callback. + // TODO(brettw) this should be a OnceCallback to avoid base::Passed. + memory_instrumentation::MemoryInstrumentation::GetInstance() + ->GetVmRegionsForHeapProfiler(base::Bind( + &MemlogImpl::OnGetVmRegionsComplete, weak_factory_.GetWeakPtr(), pid, + base::Passed(std::move(file)))); +} + +void MemlogImpl::OnGetVmRegionsComplete( + base::ProcessId pid, + base::File file, + bool success, + memory_instrumentation::mojom::GlobalMemoryDumpPtr dump) { + if (!success) { + LOG(ERROR) << "Global dump failed"; + return; + } + + // Find the process's memory dump we want. + // TODO(bug 752621) we should be asking and getting the memory map of only + // the process we want rather than querying all processes and filtering. + memory_instrumentation::mojom::ProcessMemoryDump* process_dump = nullptr; + for (const auto& proc : dump->process_dumps) { + if (proc->pid == pid) { + process_dump = &*proc; + break; + } + } + if (!process_dump) { + LOG(ERROR) << "Don't have a memory dump for PID " << pid; + return; + } + io_runner_->PostTask( - FROM_HERE, base::BindOnce(&MemlogConnectionManager::DumpProcess, - base::Unretained(connection_manager_.get()), - pid, std::move(file))); + FROM_HERE, + base::BindOnce( + &MemlogConnectionManager::DumpProcess, + base::Unretained(connection_manager_.get()), pid, + std::move(process_dump->os_dump->memory_maps_for_heap_profiler), + std::move(file))); } } // namespace profiling
diff --git a/chrome/profiling/memlog_impl.h b/chrome/profiling/memlog_impl.h index 50cafa7..4a8d8919 100644 --- a/chrome/profiling/memlog_impl.h +++ b/chrome/profiling/memlog_impl.h
@@ -5,12 +5,15 @@ #ifndef CHROME_PROFILING_MEMLOG_IMPL_H_ #define CHROME_PROFILING_MEMLOG_IMPL_H_ +#include "base/files/file.h" #include "base/files/platform_file.h" #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "chrome/common/profiling/memlog.mojom.h" #include "chrome/profiling/backtrace_storage.h" #include "chrome/profiling/memlog_connection_manager.h" #include "mojo/public/cpp/bindings/binding.h" +#include "services/resource_coordinator/public/interfaces/memory_instrumentation/memory_instrumentation.mojom.h" #include "services/service_manager/public/cpp/service_context_ref.h" namespace profiling { @@ -46,10 +49,19 @@ base::SequencedTaskRunner* runner; }; + void OnGetVmRegionsComplete( + base::ProcessId pid, + base::File file, + bool success, + memory_instrumentation::mojom::GlobalMemoryDumpPtr dump); + scoped_refptr<base::SequencedTaskRunner> io_runner_; BacktraceStorage backtrace_storage_; std::unique_ptr<MemlogConnectionManager, DeleteOnRunner> connection_manager_; + // Must be last. + base::WeakPtrFactory<MemlogImpl> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(MemlogImpl); };
diff --git a/chrome/profiling/profiling_service.h b/chrome/profiling/profiling_service.h index 9724fbb..fabc75e 100644 --- a/chrome/profiling/profiling_service.h +++ b/chrome/profiling/profiling_service.h
@@ -21,7 +21,7 @@ // ServiceManager) to set manage the global state as well as the bound // interface. // -// Currently the servcie only manages a memlog interface, but there could be +// Currently the service only manages a memlog interface, but there could be // more in the future. // // The expectation is each memlog sender will bind a connection to this service
diff --git a/chrome/renderer/safe_browsing/DEPS b/chrome/renderer/safe_browsing/DEPS index 4db2367..5f5942167 100644 --- a/chrome/renderer/safe_browsing/DEPS +++ b/chrome/renderer/safe_browsing/DEPS
@@ -1,6 +1,6 @@ include_rules = [ "+components/safe_browsing/common", - "+components/safe_browsing/csd.pb.h", + "+components/safe_browsing/proto/csd.pb.h", "+components/safe_browsing/renderer", "+components/safe_browsing/features.h", "+third_party/smhasher",
diff --git a/chrome/renderer/safe_browsing/phishing_classifier.cc b/chrome/renderer/safe_browsing/phishing_classifier.cc index 9c793c16..b4c21b47 100644 --- a/chrome/renderer/safe_browsing/phishing_classifier.cc +++ b/chrome/renderer/safe_browsing/phishing_classifier.cc
@@ -22,7 +22,7 @@ #include "chrome/renderer/safe_browsing/phishing_term_feature_extractor.h" #include "chrome/renderer/safe_browsing/phishing_url_feature_extractor.h" #include "chrome/renderer/safe_browsing/scorer.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "content/public/renderer/render_frame.h" #include "crypto/sha2.h" #include "third_party/WebKit/public/platform/WebURL.h"
diff --git a/chrome/renderer/safe_browsing/phishing_classifier_browsertest.cc b/chrome/renderer/safe_browsing/phishing_classifier_browsertest.cc index 148fcec..3bac8333 100644 --- a/chrome/renderer/safe_browsing/phishing_classifier_browsertest.cc +++ b/chrome/renderer/safe_browsing/phishing_classifier_browsertest.cc
@@ -18,7 +18,7 @@ #include "chrome/renderer/safe_browsing/murmurhash3_util.h" #include "chrome/renderer/safe_browsing/scorer.h" #include "chrome/test/base/chrome_render_view_test.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_view.h" #include "crypto/sha2.h"
diff --git a/chrome/renderer/safe_browsing/phishing_classifier_delegate.cc b/chrome/renderer/safe_browsing/phishing_classifier_delegate.cc index 4149a7e..61406c8 100644 --- a/chrome/renderer/safe_browsing/phishing_classifier_delegate.cc +++ b/chrome/renderer/safe_browsing/phishing_classifier_delegate.cc
@@ -16,7 +16,7 @@ #include "chrome/renderer/safe_browsing/phishing_classifier.h" #include "chrome/renderer/safe_browsing/scorer.h" #include "components/safe_browsing/common/safebrowsing_messages.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "content/public/renderer/document_state.h" #include "content/public/renderer/navigation_state.h" #include "content/public/renderer/render_frame.h"
diff --git a/chrome/renderer/safe_browsing/phishing_classifier_delegate_browsertest.cc b/chrome/renderer/safe_browsing/phishing_classifier_delegate_browsertest.cc index 03783b5a..552a4a1 100644 --- a/chrome/renderer/safe_browsing/phishing_classifier_delegate_browsertest.cc +++ b/chrome/renderer/safe_browsing/phishing_classifier_delegate_browsertest.cc
@@ -13,7 +13,7 @@ #include "chrome/test/base/chrome_render_view_test.h" #include "chrome/test/base/chrome_unit_test_suite.h" #include "components/safe_browsing/common/safebrowsing_messages.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_view.h" #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index efc312a35..eb7e033b 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -2071,6 +2071,7 @@ "../browser/ui/views/bookmarks/bookmark_editor_view_browsertest.cc", "../browser/ui/views/extensions/extension_message_bubble_view_browsertest.cc", "../browser/ui/views/external_protocol_dialog_browsertest.cc", + "../browser/ui/views/first_run_bubble_browsertest.cc", "../browser/ui/views/frame/browser_non_client_frame_view_browsertest_win.cc", "../browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc", "../browser/ui/views/importer/import_lock_dialog_view_browsertest.cc", @@ -2352,6 +2353,7 @@ "//services/preferences/public/interfaces", "//services/service_manager/public/cpp", "//ui/login:resources", + "//url", ] if (use_dbus) { @@ -3873,8 +3875,11 @@ } if ((is_linux && !is_chromeos) || is_win) { - sources += - [ "../browser/feature_engagement/new_tab/new_tab_tracker_unittest.cc" ] + sources += [ + "../browser/feature_engagement/feature_tracker_unittest.cc", + "../browser/feature_engagement/new_tab/new_tab_tracker_unittest.cc", + "../browser/feature_engagement/session_duration_updater_unittest.cc", + ] deps += [ "//components/feature_engagement/test:test_support" ] }
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py index a99fb82..ae18082 100755 --- a/chrome/test/chromedriver/test/run_py_tests.py +++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -106,7 +106,10 @@ # Xvfb doesn't support maximization. 'ChromeDriverTest.testWindowMaximize', ] -_OS_SPECIFIC_FILTER['mac'] = [] +_OS_SPECIFIC_FILTER['mac'] = [ + # https://bugs.chromium.org/p/chromedriver/issues/detail?id=1927 + 'MobileEmulationCapabilityTest.testTapElement', +] _DESKTOP_NEGATIVE_FILTER = [ # Desktop doesn't support touch (without --touch-events).
diff --git a/chrome/test/data/android/webvr_instrumentation/html/test_webvr_disabled_without_flag_set.html b/chrome/test/data/android/webvr_instrumentation/html/test_webvr_disabled_without_flag_set.html new file mode 100644 index 0000000..598cded --- /dev/null +++ b/chrome/test/data/android/webvr_instrumentation/html/test_webvr_disabled_without_flag_set.html
@@ -0,0 +1,23 @@ +<!doctype html> +<!-- +Tests that the WebVR API is not present if the flag to enable it is not set. +--> +<html> + <head> + <link rel="stylesheet" type="text/css" href="../resources/webvr_e2e.css"> + </head> + <body> + <canvas id="webgl-canvas"></canvas> + <script src="../../../../../../third_party/WebKit/LayoutTests/resources/testharness.js"></script> + <script src="../resources/webvr_e2e.js"></script> + </body> + <script> + var t = async_test("WebVR API is not visible"); + if (navigator.getVRDisplays) { + t.step( () => { + assert_unreached("API is visible"); + }); + } + t.done(); + </script> +</html>
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn index 39bca75..20e8069 100644 --- a/chrome/test/data/webui/BUILD.gn +++ b/chrome/test/data/webui/BUILD.gn
@@ -77,6 +77,7 @@ "ntp4.js", "polymer_browser_test_base.js", "sandboxstatus_browsertest.js", + "settings/about_a11y_test.js", "settings/accessibility_audit_rules.js", "settings/accessibility_browsertest.js", "settings/accessibility_test.js",
diff --git a/chrome/test/data/webui/settings/about_a11y_test.js b/chrome/test/data/webui/settings/about_a11y_test.js new file mode 100644 index 0000000..33b42a7 --- /dev/null +++ b/chrome/test/data/webui/settings/about_a11y_test.js
@@ -0,0 +1,48 @@ +// 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. + +/** + * @fileoverview Define accessibility tests for the ABOUT route. + */ + +/** @const {string} Path to root from chrome/test/data/webui/settings/. */ +var ROOT_PATH = '../../../../../'; + +// SettingsAccessibilityTest fixture. +GEN_INCLUDE([ + ROOT_PATH + 'chrome/test/data/webui/settings/accessibility_browsertest.js', +]); + +AccessibilityTest.define('SettingsAccessibilityTest', { + /** @override */ + name: 'ABOUT', + /** @override */ + axeOptions: { + 'rules': { + // TODO(hcarmona): enable 'region' after addressing violation. + 'region': {enabled: false}, + } + }, + /** @override */ + setup: function() { + settings.router.navigateTo(settings.routes.ABOUT); + Polymer.dom.flush(); + }, + /** @override */ + tests: { + 'Accessible with No Changes': function() {} + }, + /** @override */ + violationFilter: { + // TODO(quacht): remove this exception once the color contrast issue is + // solved. + // http://crbug.com/748608 + 'color-contrast': function(nodeResult) { + return nodeResult.element.id === 'prompt'; + }, + 'aria-valid-attr': function(nodeResult) { + return nodeResult.element.hasAttribute('aria-active-attribute'); + }, + } +}); \ No newline at end of file
diff --git a/chrome/test/data/webui/settings/accessibility_test.js b/chrome/test/data/webui/settings/accessibility_test.js index cb6865dc..cd87ea6 100644 --- a/chrome/test/data/webui/settings/accessibility_test.js +++ b/chrome/test/data/webui/settings/accessibility_test.js
@@ -121,8 +121,10 @@ axeOptions.runOnly.values : AccessibilityTest.ruleIds; rules.forEach((ruleId) => { // Skip rules disabled in axeOptions. - if (ruleId in axeOptions.rules && !axeOptions.rules[ruleId].enabled) + if (axeOptions.rules && ruleId in axeOptions.rules && + !axeOptions.rules[ruleId].enabled) { return; + } let newTestDef = Object.assign({}, testDef); newTestDef.name += '_' + ruleId;
diff --git a/chrome/tools/safe_browsing/DEPS b/chrome/tools/safe_browsing/DEPS index 322a686..5574d3b4 100644 --- a/chrome/tools/safe_browsing/DEPS +++ b/chrome/tools/safe_browsing/DEPS
@@ -1,3 +1,3 @@ include_rules = [ - "+components/safe_browsing/csd.pb.h", + "+components/safe_browsing/proto/csd.pb.h", ]
diff --git a/chrome/tools/safe_browsing/sb_sigutil.cc b/chrome/tools/safe_browsing/sb_sigutil.cc index c33ffa7..81973a4 100644 --- a/chrome/tools/safe_browsing/sb_sigutil.cc +++ b/chrome/tools/safe_browsing/sb_sigutil.cc
@@ -16,7 +16,7 @@ #include "base/logging.h" #include "base/memory/ref_counted.h" #include "chrome/common/safe_browsing/binary_feature_extractor.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" // Command-line switch for the executable to extract a signature from. static const char kExecutable[] = "executable";
diff --git a/chrome/utility/safe_browsing/mac/DEPS b/chrome/utility/safe_browsing/mac/DEPS index 322a686..5574d3b4 100644 --- a/chrome/utility/safe_browsing/mac/DEPS +++ b/chrome/utility/safe_browsing/mac/DEPS
@@ -1,3 +1,3 @@ include_rules = [ - "+components/safe_browsing/csd.pb.h", + "+components/safe_browsing/proto/csd.pb.h", ]
diff --git a/chrome/utility/safe_browsing/mac/dmg_analyzer.cc b/chrome/utility/safe_browsing/mac/dmg_analyzer.cc index 6ba4e583..00d8ad6 100644 --- a/chrome/utility/safe_browsing/mac/dmg_analyzer.cc +++ b/chrome/utility/safe_browsing/mac/dmg_analyzer.cc
@@ -16,7 +16,7 @@ #include "chrome/common/safe_browsing/mach_o_image_reader_mac.h" #include "chrome/utility/safe_browsing/mac/dmg_iterator.h" #include "chrome/utility/safe_browsing/mac/read_stream.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "crypto/secure_hash.h" #include "crypto/sha2.h"
diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsActivity.java b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsActivity.java index 2903ad2..d911508 100644 --- a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsActivity.java +++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsActivity.java
@@ -258,8 +258,11 @@ if (DEBUG) Log.d(TAG, "onWindowFocusChanged(%b)", hasFocus); super.onWindowFocusChanged(hasFocus); if (hasFocus) { + // switch to fullscreen (immersive) mode getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN); + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); } }
diff --git a/chromecast/media/audio/cast_audio_output_stream_unittest.cc b/chromecast/media/audio/cast_audio_output_stream_unittest.cc index 1a66c0293..e62e493a 100644 --- a/chromecast/media/audio/cast_audio_output_stream_unittest.cc +++ b/chromecast/media/audio/cast_audio_output_stream_unittest.cc
@@ -518,6 +518,7 @@ EXPECT_TRUE(audio_device); EXPECT_EQ(FakeMediaPipelineBackend::kStateRunning, GetBackend()->state()); + stream->Stop(); stream->Close(); }
diff --git a/chromecast/media/cma/backend/BUILD.gn b/chromecast/media/cma/backend/BUILD.gn index 3d4b52e..f2b0134 100644 --- a/chromecast/media/cma/backend/BUILD.gn +++ b/chromecast/media/cma/backend/BUILD.gn
@@ -8,6 +8,8 @@ source_set("backend") { sources = [ + "audio_decoder_wrapper.cc", + "audio_decoder_wrapper.h", "media_pipeline_backend_factory.h", "media_pipeline_backend_factory_impl.cc", "media_pipeline_backend_factory_impl.h",
diff --git a/chromecast/media/cma/backend/alsa/stream_mixer_alsa_input.h b/chromecast/media/cma/backend/alsa/stream_mixer_alsa_input.h index 2d77008c5..918c4a2 100644 --- a/chromecast/media/cma/backend/alsa/stream_mixer_alsa_input.h +++ b/chromecast/media/cma/backend/alsa/stream_mixer_alsa_input.h
@@ -70,8 +70,10 @@ // will continue to play sound while this input is paused. void SetPaused(bool paused); - // Sets the volume multiplier for this input. If |multiplier| is outside the - // range [0.0, 1.0], it is clamped to that range. + // Sets the volume multiplier for this input. If |multiplier| is less than 0, + // it is clamped to 0. Volume multipliers greater than 1.0 are allowed, but + // the total volume for the stream (including stream type volume) is clamped + // to 1.0. void SetVolumeMultiplier(float multiplier); private:
diff --git a/chromecast/media/cma/backend/alsa/stream_mixer_alsa_input_impl.cc b/chromecast/media/cma/backend/alsa/stream_mixer_alsa_input_impl.cc index 34d95f26..92aa527 100644 --- a/chromecast/media/cma/backend/alsa/stream_mixer_alsa_input_impl.cc +++ b/chromecast/media/cma/backend/alsa/stream_mixer_alsa_input_impl.cc
@@ -561,19 +561,19 @@ void StreamMixerAlsaInputImpl::SetVolumeMultiplier(float multiplier) { RUN_ON_MIXER_THREAD(SetVolumeMultiplier, multiplier); DCHECK(!IsDeleting()); - stream_volume_multiplier_ = std::max(0.0f, std::min(multiplier, 1.0f)); + stream_volume_multiplier_ = std::max(0.0f, multiplier); + float effective_volume = EffectiveVolume(); LOG(INFO) << device_id_ << "(" << this << "): stream volume = " << stream_volume_multiplier_ - << ", effective multiplier = " << EffectiveVolume(); + << ", effective multiplier = " << effective_volume; slew_volume_.SetMaxSlewTimeMs(kDefaultSlewTimeMs); - slew_volume_.SetVolume(EffectiveVolume()); + slew_volume_.SetVolume(effective_volume); } void StreamMixerAlsaInputImpl::SetContentTypeVolume(float volume, int fade_ms) { DCHECK(mixer_task_runner_->BelongsToCurrentThread()); type_volume_multiplier_ = std::max(0.0f, std::min(volume, 1.0f)); - float effective_volume = stream_volume_multiplier_ * type_volume_multiplier_ * - mute_volume_multiplier_; + float effective_volume = EffectiveVolume(); LOG(INFO) << device_id_ << "(" << this << "): type volume = " << type_volume_multiplier_ << ", effective multiplier = " << effective_volume; @@ -589,8 +589,7 @@ void StreamMixerAlsaInputImpl::SetMuted(bool muted) { DCHECK(mixer_task_runner_->BelongsToCurrentThread()); mute_volume_multiplier_ = muted ? 0.0f : 1.0f; - float effective_volume = stream_volume_multiplier_ * type_volume_multiplier_ * - mute_volume_multiplier_; + float effective_volume = EffectiveVolume(); LOG(INFO) << device_id_ << "(" << this << "): mute volume = " << mute_volume_multiplier_ << ", effective multiplier = " << effective_volume; @@ -599,8 +598,9 @@ } float StreamMixerAlsaInputImpl::EffectiveVolume() { - return stream_volume_multiplier_ * type_volume_multiplier_ * - mute_volume_multiplier_; + float volume = stream_volume_multiplier_ * type_volume_multiplier_ * + mute_volume_multiplier_; + return std::max(0.0f, std::min(volume, 1.0f)); } void StreamMixerAlsaInputImpl::VolumeScaleAccumulate(bool repeat_transition,
diff --git a/chromecast/media/cma/backend/alsa/stream_mixer_alsa_input_impl.h b/chromecast/media/cma/backend/alsa/stream_mixer_alsa_input_impl.h index a85b858c..5daf21d 100644 --- a/chromecast/media/cma/backend/alsa/stream_mixer_alsa_input_impl.h +++ b/chromecast/media/cma/backend/alsa/stream_mixer_alsa_input_impl.h
@@ -107,8 +107,7 @@ void SetPaused(bool paused); // Sets the volume multiplier for this stream. If |multiplier| < 0, sets the - // volume multiplier to 0. If |multiplier| > 1, sets the volume multiplier - // to 1. + // volume multiplier to 0. void SetVolumeMultiplier(float multiplier); // Prevents any further calls to the delegate (ie, called when the delegate
diff --git a/chromecast/media/cma/backend/audio_decoder_wrapper.cc b/chromecast/media/cma/backend/audio_decoder_wrapper.cc new file mode 100644 index 0000000..7aea08d --- /dev/null +++ b/chromecast/media/cma/backend/audio_decoder_wrapper.cc
@@ -0,0 +1,65 @@ +// 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 "chromecast/media/cma/backend/audio_decoder_wrapper.h" + +#include "base/logging.h" +#include "chromecast/media/cma/backend/media_pipeline_backend_manager.h" + +namespace chromecast { +namespace media { + +AudioDecoderWrapper::AudioDecoderWrapper( + MediaPipelineBackendManager* backend_manager, + AudioDecoder* decoder, + AudioContentType type) + : backend_manager_(backend_manager), + decoder_(decoder), + content_type_(type), + global_volume_multiplier_(1.0f), + stream_volume_multiplier_(1.0f) { + DCHECK(backend_manager_); + DCHECK(decoder_); + + backend_manager_->AddAudioDecoder(this); +} + +AudioDecoderWrapper::~AudioDecoderWrapper() { + backend_manager_->RemoveAudioDecoder(this); +} + +void AudioDecoderWrapper::SetGlobalVolumeMultiplier(float multiplier) { + global_volume_multiplier_ = multiplier; + decoder_->SetVolume(stream_volume_multiplier_ * global_volume_multiplier_); +} + +void AudioDecoderWrapper::SetDelegate(Delegate* delegate) { + decoder_->SetDelegate(delegate); +} + +MediaPipelineBackend::BufferStatus AudioDecoderWrapper::PushBuffer( + CastDecoderBuffer* buffer) { + return decoder_->PushBuffer(buffer); +} + +bool AudioDecoderWrapper::SetConfig(const AudioConfig& config) { + return decoder_->SetConfig(config); +} + +bool AudioDecoderWrapper::SetVolume(float multiplier) { + stream_volume_multiplier_ = std::max(0.0f, std::min(multiplier, 1.0f)); + return decoder_->SetVolume(stream_volume_multiplier_ * + global_volume_multiplier_); +} + +AudioDecoderWrapper::RenderingDelay AudioDecoderWrapper::GetRenderingDelay() { + return decoder_->GetRenderingDelay(); +} + +void AudioDecoderWrapper::GetStatistics(Statistics* statistics) { + decoder_->GetStatistics(statistics); +} + +} // namespace media +} // namespace chromecast
diff --git a/chromecast/media/cma/backend/audio_decoder_wrapper.h b/chromecast/media/cma/backend/audio_decoder_wrapper.h new file mode 100644 index 0000000..f1929d8 --- /dev/null +++ b/chromecast/media/cma/backend/audio_decoder_wrapper.h
@@ -0,0 +1,50 @@ +// 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 CHROMECAST_MEDIA_CMA_BACKEND_AUDIO_DECODER_WRAPPER_H_ +#define CHROMECAST_MEDIA_CMA_BACKEND_AUDIO_DECODER_WRAPPER_H_ + +#include "base/macros.h" +#include "chromecast/public/media/media_pipeline_backend.h" + +namespace chromecast { +namespace media { + +enum class AudioContentType; +class MediaPipelineBackendManager; + +class AudioDecoderWrapper : public MediaPipelineBackend::AudioDecoder { + public: + AudioDecoderWrapper(MediaPipelineBackendManager* backend_manager, + MediaPipelineBackend::AudioDecoder* decoder, + AudioContentType type); + ~AudioDecoderWrapper() override; + + void SetGlobalVolumeMultiplier(float multiplier); + + AudioContentType content_type() const { return content_type_; } + + private: + // MediaPipelineBackend::AudioDecoder implementation: + void SetDelegate(Delegate* delegate) override; + BufferStatus PushBuffer(CastDecoderBuffer* buffer) override; + bool SetConfig(const AudioConfig& config) override; + bool SetVolume(float multiplier) override; + RenderingDelay GetRenderingDelay() override; + void GetStatistics(Statistics* statistics) override; + + MediaPipelineBackendManager* const backend_manager_; + MediaPipelineBackend::AudioDecoder* const decoder_; + const AudioContentType content_type_; + + float global_volume_multiplier_; + float stream_volume_multiplier_; + + DISALLOW_COPY_AND_ASSIGN(AudioDecoderWrapper); +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_MEDIA_CMA_BACKEND_AUDIO_DECODER_WRAPPER_H_
diff --git a/chromecast/media/cma/backend/media_pipeline_backend_manager.cc b/chromecast/media/cma/backend/media_pipeline_backend_manager.cc index f3807ce..4d6c6b5e 100644 --- a/chromecast/media/cma/backend/media_pipeline_backend_manager.cc +++ b/chromecast/media/cma/backend/media_pipeline_backend_manager.cc
@@ -7,10 +7,13 @@ #include <algorithm> #include <limits> +#include "base/bind.h" #include "base/location.h" #include "base/memory/ptr_util.h" #include "chromecast/chromecast_features.h" +#include "chromecast/media/cma/backend/audio_decoder_wrapper.h" #include "chromecast/media/cma/backend/media_pipeline_backend_wrapper.h" +#include "chromecast/public/volume_control.h" namespace chromecast { namespace media { @@ -27,13 +30,19 @@ : media_task_runner_(std::move(media_task_runner)), playing_noneffects_audio_streams_count_(0), allow_volume_feedback_observers_( - new base::ObserverListThreadSafe<AllowVolumeFeedbackObserver>()) { + new base::ObserverListThreadSafe<AllowVolumeFeedbackObserver>()), + global_volume_multipliers_({{AudioContentType::kMedia, 1.0f}, + {AudioContentType::kAlarm, 1.0f}, + {AudioContentType::kCommunication, 1.0f}}, + base::KEEP_FIRST_OF_DUPES), + weak_factory_(this) { for (int i = 0; i < NUM_DECODER_TYPES; ++i) { decoder_count_[i] = 0; } } MediaPipelineBackendManager::~MediaPipelineBackendManager() { + DCHECK(media_task_runner_->BelongsToCurrentThread()); } std::unique_ptr<MediaPipelineBackend> @@ -103,5 +112,38 @@ wrapper->LogicalResume(); } +void MediaPipelineBackendManager::SetGlobalVolumeMultiplier( + AudioContentType type, + float multiplier) { + if (!media_task_runner_->BelongsToCurrentThread()) { + media_task_runner_->PostTask( + FROM_HERE, + base::Bind(&MediaPipelineBackendManager::SetGlobalVolumeMultiplier, + weak_factory_.GetWeakPtr(), type, multiplier)); + return; + } + + DCHECK_GE(multiplier, 0.0f); + global_volume_multipliers_[type] = multiplier; + for (auto* a : audio_decoders_) { + if (a->content_type() == type) { + a->SetGlobalVolumeMultiplier(multiplier); + } + } +} + +void MediaPipelineBackendManager::AddAudioDecoder( + AudioDecoderWrapper* decoder) { + DCHECK(decoder); + audio_decoders_.insert(decoder); + decoder->SetGlobalVolumeMultiplier( + global_volume_multipliers_[decoder->content_type()]); +} + +void MediaPipelineBackendManager::RemoveAudioDecoder( + AudioDecoderWrapper* decoder) { + audio_decoders_.erase(decoder); +} + } // namespace media } // namespace chromecast
diff --git a/chromecast/media/cma/backend/media_pipeline_backend_manager.h b/chromecast/media/cma/backend/media_pipeline_backend_manager.h index e112b54..f8d1693b 100644 --- a/chromecast/media/cma/backend/media_pipeline_backend_manager.h +++ b/chromecast/media/cma/backend/media_pipeline_backend_manager.h
@@ -9,8 +9,11 @@ #include <memory> #include <vector> +#include "base/containers/flat_map.h" +#include "base/containers/flat_set.h" #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" #include "base/observer_list_threadsafe.h" #include "base/single_thread_task_runner.h" #include "chromecast/public/media/media_pipeline_backend.h" @@ -19,6 +22,9 @@ namespace chromecast { namespace media { +enum class AudioContentType; +class AudioDecoderWrapper; + // This class tracks all created media backends, tracking whether or not volume // feedback sounds should be enabled based on the currently active backends. // Volume feedback sounds are only enabled when there are no active audio @@ -53,20 +59,30 @@ return media_task_runner_.get(); } - // Adds/removes an observer for when folume feedback sounds are allowed. + // Adds/removes an observer for when volume feedback sounds are allowed. // An observer must be removed on the same thread that added it. void AddAllowVolumeFeedbackObserver(AllowVolumeFeedbackObserver* observer); void RemoveAllowVolumeFeedbackObserver(AllowVolumeFeedbackObserver* observer); - // Logically pause/resume a backend instance, without actually pausing or + // Logically pauses/resumes a backend instance, without actually pausing or // resuming it. This is used by multiroom output to avoid playback stutter on // resume. |backend| must have been created via a call to this instance's // CreateMediaPipelineBackend(). void LogicalPause(MediaPipelineBackend* backend); void LogicalResume(MediaPipelineBackend* backend); + // Sets a global multiplier for output volume for streams fo the given |type|. + // The multiplier may be any value >= 0; if the resulting volume for an + // individual stream would be > 1.0, that stream's volume is clamped to 1.0. + // The default multiplier is 1.0. May be called on any thread. + void SetGlobalVolumeMultiplier(AudioContentType type, float multiplier); + private: friend class MediaPipelineBackendWrapper; + friend class AudioDecoderWrapper; + + void AddAudioDecoder(AudioDecoderWrapper* decoder); + void RemoveAudioDecoder(AudioDecoderWrapper* decoder); // Backend wrapper instances must use these APIs when allocating and releasing // decoder objects, so we can enforce global limit on #concurrent decoders. @@ -87,6 +103,11 @@ scoped_refptr<base::ObserverListThreadSafe<AllowVolumeFeedbackObserver>> allow_volume_feedback_observers_; + base::flat_set<AudioDecoderWrapper*> audio_decoders_; + base::flat_map<AudioContentType, float> global_volume_multipliers_; + + base::WeakPtrFactory<MediaPipelineBackendManager> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(MediaPipelineBackendManager); };
diff --git a/chromecast/media/cma/backend/media_pipeline_backend_wrapper.cc b/chromecast/media/cma/backend/media_pipeline_backend_wrapper.cc index 7ea3f9a..462ab2d 100644 --- a/chromecast/media/cma/backend/media_pipeline_backend_wrapper.cc +++ b/chromecast/media/cma/backend/media_pipeline_backend_wrapper.cc
@@ -6,6 +6,7 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" +#include "chromecast/media/cma/backend/audio_decoder_wrapper.h" #include "chromecast/media/cma/backend/media_pipeline_backend_manager.h" #include "chromecast/public/cast_media_shlib.h" @@ -20,9 +21,9 @@ : backend_(base::WrapUnique( media::CastMediaShlib::CreateMediaPipelineBackend(params))), backend_manager_(backend_manager), + content_type_(params.content_type), sfx_backend_(params.audio_type == media::MediaPipelineDeviceParams::kAudioStreamSoundEffects), - have_audio_decoder_(false), have_video_decoder_(false), playing_(false) { DCHECK(backend_); @@ -30,7 +31,7 @@ } MediaPipelineBackendWrapper::~MediaPipelineBackendWrapper() { - if (have_audio_decoder_) + if (audio_decoder_) backend_manager_->DecrementDecoderCount( sfx_backend_ ? DecoderType::SFX_DECODER : DecoderType::AUDIO_DECODER); if (have_video_decoder_) @@ -38,7 +39,7 @@ if (playing_) { LOG(WARNING) << "Destroying media backend while still in 'playing' state"; - if (have_audio_decoder_ && !sfx_backend_) { + if (audio_decoder_ && !sfx_backend_) { backend_manager_->UpdatePlayingAudioCount(-1); } } @@ -54,14 +55,19 @@ MediaPipelineBackend::AudioDecoder* MediaPipelineBackendWrapper::CreateAudioDecoder() { - DCHECK(!have_audio_decoder_); + DCHECK(!audio_decoder_); if (!backend_manager_->IncrementDecoderCount( sfx_backend_ ? DecoderType::SFX_DECODER : DecoderType::AUDIO_DECODER)) return nullptr; - have_audio_decoder_ = true; - - return backend_->CreateAudioDecoder(); + MediaPipelineBackend::AudioDecoder* real_decoder = + backend_->CreateAudioDecoder(); + if (!real_decoder) { + return nullptr; + } + audio_decoder_ = base::MakeUnique<AudioDecoderWrapper>( + backend_manager_, real_decoder, content_type_); + return audio_decoder_.get(); } MediaPipelineBackend::VideoDecoder* @@ -121,7 +127,7 @@ return; } playing_ = playing; - if (have_audio_decoder_ && !sfx_backend_) { + if (audio_decoder_ && !sfx_backend_) { backend_manager_->UpdatePlayingAudioCount(playing_ ? 1 : -1); } }
diff --git a/chromecast/media/cma/backend/media_pipeline_backend_wrapper.h b/chromecast/media/cma/backend/media_pipeline_backend_wrapper.h index 848c7ce..879063e 100644 --- a/chromecast/media/cma/backend/media_pipeline_backend_wrapper.h +++ b/chromecast/media/cma/backend/media_pipeline_backend_wrapper.h
@@ -18,6 +18,8 @@ namespace chromecast { namespace media { +enum class AudioContentType; +class AudioDecoderWrapper; class MediaPipelineBackendManager; class MediaPipelineBackendWrapper : public MediaPipelineBackend { @@ -45,9 +47,11 @@ const std::unique_ptr<MediaPipelineBackend> backend_; MediaPipelineBackendManager* const backend_manager_; + const AudioContentType content_type_; + + std::unique_ptr<AudioDecoderWrapper> audio_decoder_; bool sfx_backend_; - bool have_audio_decoder_; bool have_video_decoder_; bool playing_;
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn index 6d58162..4e49ab5 100644 --- a/chromeos/BUILD.gn +++ b/chromeos/BUILD.gn
@@ -130,6 +130,8 @@ "cryptohome/system_salt_getter.h", "dbus/arc_obb_mounter_client.cc", "dbus/arc_obb_mounter_client.h", + "dbus/arc_oemcrypto_client.cc", + "dbus/arc_oemcrypto_client.h", "dbus/audio_node.cc", "dbus/audio_node.h", "dbus/auth_policy_client.cc", @@ -161,6 +163,8 @@ "dbus/easy_unlock_client.h", "dbus/fake_arc_obb_mounter_client.cc", "dbus/fake_arc_obb_mounter_client.h", + "dbus/fake_arc_oemcrypto_client.cc", + "dbus/fake_arc_oemcrypto_client.h", "dbus/fake_auth_policy_client.cc", "dbus/fake_auth_policy_client.h", "dbus/fake_cras_audio_client.cc",
diff --git a/chromeos/dbus/arc_oemcrypto_client.cc b/chromeos/dbus/arc_oemcrypto_client.cc new file mode 100644 index 0000000..a54ba140 --- /dev/null +++ b/chromeos/dbus/arc_oemcrypto_client.cc
@@ -0,0 +1,73 @@ +// 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 "chromeos/dbus/arc_oemcrypto_client.h" + +#include <utility> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/callback.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_proxy.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace chromeos { + +namespace { + +class ArcOemCryptoClientImpl : public ArcOemCryptoClient { + public: + ArcOemCryptoClientImpl() : weak_ptr_factory_(this) {} + ~ArcOemCryptoClientImpl() override {} + + // ArcOemCryptoClient override: + void BootstrapMojoConnection(base::ScopedFD fd, + VoidDBusMethodCallback callback) override { + dbus::MethodCall method_call(arc_oemcrypto::kArcOemCryptoServiceInterface, + arc_oemcrypto::kBootstrapMojoConnection); + dbus::MessageWriter writer(&method_call); + writer.AppendFileDescriptor(fd.release()); + proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&ArcOemCryptoClientImpl::OnVoidDBusMethod, + weak_ptr_factory_.GetWeakPtr(), + base::Passed(std::move(callback)))); + } + + protected: + // DBusClient override. + void Init(dbus::Bus* bus) override { + proxy_ = bus->GetObjectProxy( + arc_oemcrypto::kArcOemCryptoServiceName, + dbus::ObjectPath(arc_oemcrypto::kArcOemCryptoServicePath)); + } + + private: + // Runs the callback with the method call result. + void OnVoidDBusMethod(VoidDBusMethodCallback callback, + dbus::Response* response) { + std::move(callback).Run(response ? DBUS_METHOD_CALL_SUCCESS + : DBUS_METHOD_CALL_FAILURE); + } + + dbus::ObjectProxy* proxy_ = nullptr; + + base::WeakPtrFactory<ArcOemCryptoClientImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(ArcOemCryptoClientImpl); +}; + +} // namespace + +ArcOemCryptoClient::ArcOemCryptoClient() {} + +ArcOemCryptoClient::~ArcOemCryptoClient() {} + +// static +ArcOemCryptoClient* ArcOemCryptoClient::Create() { + return new ArcOemCryptoClientImpl(); +} + +} // namespace chromeos
diff --git a/chromeos/dbus/arc_oemcrypto_client.h b/chromeos/dbus/arc_oemcrypto_client.h new file mode 100644 index 0000000..5b6cb60 --- /dev/null +++ b/chromeos/dbus/arc_oemcrypto_client.h
@@ -0,0 +1,42 @@ +// 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 CHROMEOS_DBUS_ARC_OEMCRYPTO_CLIENT_H_ +#define CHROMEOS_DBUS_ARC_OEMCRYPTO_CLIENT_H_ + +#include <stdint.h> + +#include <string> + +#include "base/callback_forward.h" +#include "base/files/scoped_file.h" +#include "base/macros.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/dbus_client.h" +#include "chromeos/dbus/dbus_method_call_status.h" + +namespace chromeos { + +// ArcOemCryptoClient is used to communicate with the ArcOemCrypto service +// which performs Widevine L1 DRM operations for ARC. The only purpose of +// the D-Bus service is to bootstrap a Mojo IPC connection. +// All methods should be called from the origin thread (UI thread) which +// initializes the DBusThreadManager instance. +class CHROMEOS_EXPORT ArcOemCryptoClient : public DBusClient { + public: + ArcOemCryptoClient(); + ~ArcOemCryptoClient() override; + + // Factory function, creates a new instance and returns ownership. + // For normal usage, access the singleton via DBusThreadManager::Get(). + static ArcOemCryptoClient* Create(); + + // Bootstraps the Mojo IPC connection between Chrome and the service daemon. + // This should pass in the child end of a Mojo pipe. + virtual void BootstrapMojoConnection(base::ScopedFD fd, + VoidDBusMethodCallback callback) = 0; +}; +} // namespace chromeos + +#endif // CHROMEOS_DBUS_ARC_OEMCRYPTO_CLIENT_H_
diff --git a/chromeos/dbus/dbus_clients_browser.cc b/chromeos/dbus/dbus_clients_browser.cc index d5a5486..93353d7 100644 --- a/chromeos/dbus/dbus_clients_browser.cc +++ b/chromeos/dbus/dbus_clients_browser.cc
@@ -6,6 +6,7 @@ #include "base/logging.h" #include "chromeos/dbus/arc_obb_mounter_client.h" +#include "chromeos/dbus/arc_oemcrypto_client.h" #include "chromeos/dbus/auth_policy_client.h" #include "chromeos/dbus/cros_disks_client.h" #include "chromeos/dbus/dbus_client_implementation_type.h" @@ -13,6 +14,7 @@ #include "chromeos/dbus/debug_daemon_client.h" #include "chromeos/dbus/easy_unlock_client.h" #include "chromeos/dbus/fake_arc_obb_mounter_client.h" +#include "chromeos/dbus/fake_arc_oemcrypto_client.h" #include "chromeos/dbus/fake_auth_policy_client.h" #include "chromeos/dbus/fake_debug_daemon_client.h" #include "chromeos/dbus/fake_easy_unlock_client.h" @@ -36,6 +38,11 @@ arc_obb_mounter_client_.reset(new FakeArcObbMounterClient); if (use_real_clients) + arc_oemcrypto_client_.reset(ArcOemCryptoClient::Create()); + else + arc_oemcrypto_client_.reset(new FakeArcOemCryptoClient); + + if (use_real_clients) auth_policy_client_.reset(AuthPolicyClient::Create()); else auth_policy_client_.reset(new FakeAuthPolicyClient); @@ -86,6 +93,7 @@ DCHECK(DBusThreadManager::IsInitialized()); arc_obb_mounter_client_->Init(system_bus); + arc_oemcrypto_client_->Init(system_bus); auth_policy_client_->Init(system_bus); cros_disks_client_->Init(system_bus); debug_daemon_client_->Init(system_bus);
diff --git a/chromeos/dbus/dbus_clients_browser.h b/chromeos/dbus/dbus_clients_browser.h index a484eed..340f65e 100644 --- a/chromeos/dbus/dbus_clients_browser.h +++ b/chromeos/dbus/dbus_clients_browser.h
@@ -17,6 +17,7 @@ namespace chromeos { class ArcObbMounterClient; +class ArcOemCryptoClient; class AuthPolicyClient; class CrosDisksClient; class DebugDaemonClient; @@ -43,6 +44,7 @@ friend class DBusThreadManagerSetter; std::unique_ptr<ArcObbMounterClient> arc_obb_mounter_client_; + std::unique_ptr<ArcOemCryptoClient> arc_oemcrypto_client_; std::unique_ptr<AuthPolicyClient> auth_policy_client_; std::unique_ptr<CrosDisksClient> cros_disks_client_; std::unique_ptr<DebugDaemonClient> debug_daemon_client_;
diff --git a/chromeos/dbus/dbus_thread_manager.cc b/chromeos/dbus/dbus_thread_manager.cc index 88571830..9112f42 100644 --- a/chromeos/dbus/dbus_thread_manager.cc +++ b/chromeos/dbus/dbus_thread_manager.cc
@@ -13,6 +13,7 @@ #include "base/threading/thread.h" #include "chromeos/chromeos_switches.h" #include "chromeos/dbus/arc_obb_mounter_client.h" +#include "chromeos/dbus/arc_oemcrypto_client.h" #include "chromeos/dbus/auth_policy_client.h" #include "chromeos/dbus/biod/biod_client.h" #include "chromeos/dbus/cras_audio_client.h" @@ -115,6 +116,11 @@ : nullptr; } +ArcOemCryptoClient* DBusThreadManager::GetArcOemCryptoClient() { + return clients_browser_ ? clients_browser_->arc_oemcrypto_client_.get() + : nullptr; +} + AuthPolicyClient* DBusThreadManager::GetAuthPolicyClient() { return clients_browser_ ? clients_browser_->auth_policy_client_.get() : nullptr;
diff --git a/chromeos/dbus/dbus_thread_manager.h b/chromeos/dbus/dbus_thread_manager.h index b16c9eeb..33fd70b 100644 --- a/chromeos/dbus/dbus_thread_manager.h +++ b/chromeos/dbus/dbus_thread_manager.h
@@ -25,6 +25,7 @@ // Style Note: Clients are sorted by names. class ArcObbMounterClient; +class ArcOemCryptoClient; class AuthPolicyClient; class BiodClient; class CrasAudioClient; @@ -121,6 +122,7 @@ // TODO(jamescook): Replace this with calls to FooClient::Get(). // http://crbug.com/647367 ArcObbMounterClient* GetArcObbMounterClient(); + ArcOemCryptoClient* GetArcOemCryptoClient(); AuthPolicyClient* GetAuthPolicyClient(); BiodClient* GetBiodClient(); CrasAudioClient* GetCrasAudioClient();
diff --git a/chromeos/dbus/dbus_thread_manager_unittest.cc b/chromeos/dbus/dbus_thread_manager_unittest.cc index ba141028..201de8e6 100644 --- a/chromeos/dbus/dbus_thread_manager_unittest.cc +++ b/chromeos/dbus/dbus_thread_manager_unittest.cc
@@ -21,6 +21,7 @@ // Clients were created. EXPECT_TRUE(manager->GetArcObbMounterClient()); + EXPECT_TRUE(manager->GetArcOemCryptoClient()); EXPECT_TRUE(manager->GetCrasAudioClient()); EXPECT_TRUE(manager->GetCrosDisksClient()); EXPECT_TRUE(manager->GetCryptohomeClient()); @@ -73,6 +74,7 @@ // Clients for the browser were created. EXPECT_TRUE(manager->GetArcObbMounterClient()); + EXPECT_TRUE(manager->GetArcOemCryptoClient()); EXPECT_TRUE(manager->GetCrosDisksClient()); EXPECT_TRUE(manager->GetDebugDaemonClient()); EXPECT_TRUE(manager->GetEasyUnlockClient()); @@ -108,6 +110,7 @@ // Clients for other processes were not created. EXPECT_FALSE(manager->GetArcObbMounterClient()); + EXPECT_FALSE(manager->GetArcOemCryptoClient()); EXPECT_FALSE(manager->GetCrosDisksClient()); EXPECT_FALSE(manager->GetDebugDaemonClient()); EXPECT_FALSE(manager->GetEasyUnlockClient());
diff --git a/chromeos/dbus/fake_arc_oemcrypto_client.cc b/chromeos/dbus/fake_arc_oemcrypto_client.cc new file mode 100644 index 0000000..4716d75 --- /dev/null +++ b/chromeos/dbus/fake_arc_oemcrypto_client.cc
@@ -0,0 +1,28 @@ +// 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 "chromeos/dbus/fake_arc_oemcrypto_client.h" + +#include <utility> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/threading/thread_task_runner_handle.h" + +namespace chromeos { + +FakeArcOemCryptoClient::FakeArcOemCryptoClient() {} + +FakeArcOemCryptoClient::~FakeArcOemCryptoClient() {} + +void FakeArcOemCryptoClient::Init(dbus::Bus* bus) {} + +void FakeArcOemCryptoClient::BootstrapMojoConnection( + base::ScopedFD fd, + VoidDBusMethodCallback callback) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), DBUS_METHOD_CALL_FAILURE)); +} + +} // namespace chromeos
diff --git a/chromeos/dbus/fake_arc_oemcrypto_client.h b/chromeos/dbus/fake_arc_oemcrypto_client.h new file mode 100644 index 0000000..183fa94 --- /dev/null +++ b/chromeos/dbus/fake_arc_oemcrypto_client.h
@@ -0,0 +1,31 @@ +// 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 CHROMEOS_DBUS_FAKE_ARC_OEMCRYPTO_CLIENT_H_ +#define CHROMEOS_DBUS_FAKE_ARC_OEMCRYPTO_CLIENT_H_ + +#include "chromeos/dbus/arc_oemcrypto_client.h" + +namespace chromeos { + +// A fake implementation of ArcOemCryptoClient. +class CHROMEOS_EXPORT FakeArcOemCryptoClient : public ArcOemCryptoClient { + public: + FakeArcOemCryptoClient(); + ~FakeArcOemCryptoClient() override; + + // DBusClient override: + void Init(dbus::Bus* bus) override; + + // ArcOemCryptoClient override: + void BootstrapMojoConnection(base::ScopedFD fd, + VoidDBusMethodCallback callback) override; + + private: + DISALLOW_COPY_AND_ASSIGN(FakeArcOemCryptoClient); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_FAKE_ARC_OEMCRYPTO_CLIENT_H_
diff --git a/chromeos/dbus/fake_update_engine_client.cc b/chromeos/dbus/fake_update_engine_client.cc index 1ab1ab3..db0a9c3 100644 --- a/chromeos/dbus/fake_update_engine_client.cc +++ b/chromeos/dbus/fake_update_engine_client.cc
@@ -102,7 +102,9 @@ void FakeUpdateEngineClient::SetUpdateOverCellularOneTimePermission( const std::string& target_version, int64_t target_size, - const UpdateOverCellularOneTimePermissionCallback& callback) {} + const UpdateOverCellularOneTimePermissionCallback& callback) { + callback.Run(true); +} void FakeUpdateEngineClient::set_default_status( const UpdateEngineClient::Status& status) {
diff --git a/components/arc/common/typemaps.gni b/components/arc/common/typemaps.gni index 32ca073c..8902a9b 100644 --- a/components/arc/common/typemaps.gni +++ b/components/arc/common/typemaps.gni
@@ -11,5 +11,6 @@ "//components/arc/common/intent_helper.typemap", "//components/arc/common/video_common.typemap", "//components/arc/common/video_encode_accelerator.typemap", + "//components/arc/common/voice_interaction_framework.typemap", "//components/arc/common/volume_mounter.typemap", ]
diff --git a/components/arc/common/voice_interaction_framework.mojom b/components/arc/common/voice_interaction_framework.mojom index ad26b90..192e543 100644 --- a/components/arc/common/voice_interaction_framework.mojom +++ b/components/arc/common/voice_interaction_framework.mojom
@@ -2,14 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// Next MinVersion: 8 +// Next MinVersion: 9 module arc.mojom; import "screen_rect.mojom"; +[Extensible] +enum VoiceInteractionState { + NOT_READY = 0, + STOPPED, + RUNNING +}; + // Handles voice interaction queries from Android. -// Next method ID: 5 +// Next method ID: 6 interface VoiceInteractionFrameworkHost { // Returns a screenshot of currently focused window or empty array if // no window is focused. |data| represents the image encoded in JPEG @@ -28,6 +35,9 @@ // Notifies Chrome whether voice interaction session is running. [MinVersion=6]SetVoiceInteractionRunning@4(bool running); + + // Notifies Chrome the state of voice interaction session. + [MinVersion=8]SetVoiceInteractionState@5(VoiceInteractionState state); }; // Indicates voice interaction configuration status. @@ -69,6 +79,6 @@ [MinVersion=5] StartVoiceInteractionSetupWizard@6(); // Queries voice interaction settings status. - [MinVersion=7] GetVoiceInteractionSettings@7() => + [MinVersion=7] GetVoiceInteractionSettings@7() => (VoiceInteractionStatus status); -}; \ No newline at end of file +};
diff --git a/components/arc/common/voice_interaction_framework.typemap b/components/arc/common/voice_interaction_framework.typemap new file mode 100644 index 0000000..8254719 --- /dev/null +++ b/components/arc/common/voice_interaction_framework.typemap
@@ -0,0 +1,13 @@ +# 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. + +mojom = "//components/arc/common/voice_interaction_framework.mojom" +public_headers = [ "//ash/public/cpp/voice_interaction_state.h" ] +public_deps = [ + "//ash/public/cpp:ash_public_cpp", +] +traits_headers = + [ "//components/arc/voice_interaction/voice_interaction_struct_traits.h" ] +sources = [] +type_mappings = [ "arc.mojom.VoiceInteractionState=ash::VoiceInteractionState" ]
diff --git a/components/arc/ime/arc_ime_bridge_impl.cc b/components/arc/ime/arc_ime_bridge_impl.cc index c7f17e2..304788b 100644 --- a/components/arc/ime/arc_ime_bridge_impl.cc +++ b/components/arc/ime/arc_ime_bridge_impl.cc
@@ -59,14 +59,14 @@ std::vector<mojom::CompositionSegmentPtr> ConvertSegments( const ui::CompositionText& composition) { std::vector<mojom::CompositionSegmentPtr> segments; - for (const ui::CompositionUnderline& underline : composition.underlines) { + for (const ui::ImeTextSpan& ime_text_span : composition.ime_text_spans) { mojom::CompositionSegmentPtr segment = mojom::CompositionSegment::New(); - segment->start_offset = underline.start_offset; - segment->end_offset = underline.end_offset; + segment->start_offset = ime_text_span.start_offset; + segment->end_offset = ime_text_span.end_offset; segment->emphasized = - (underline.thick || - (composition.selection.start() == underline.start_offset && - composition.selection.end() == underline.end_offset)); + (ime_text_span.thick || + (composition.selection.start() == ime_text_span.start_offset && + composition.selection.end() == ime_text_span.end_offset)); segments.push_back(std::move(segment)); } return segments;
diff --git a/components/arc/voice_interaction/OWNERS b/components/arc/voice_interaction/OWNERS new file mode 100644 index 0000000..bb65116 --- /dev/null +++ b/components/arc/voice_interaction/OWNERS
@@ -0,0 +1,2 @@ +per-file *_struct_traits*.*=set noparent +per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/components/arc/voice_interaction/voice_interaction_struct_traits.h b/components/arc/voice_interaction/voice_interaction_struct_traits.h new file mode 100644 index 0000000..c519f96 --- /dev/null +++ b/components/arc/voice_interaction/voice_interaction_struct_traits.h
@@ -0,0 +1,53 @@ +// 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_ARC_VOICE_INTERACTION_VOICE_INTERACTION_STRUCT_TRAITS_H_ +#define COMPONENTS_ARC_VOICE_INTERACTION_VOICE_INTERACTION_STRUCT_TRAITS_H_ + +#include "ash/public/cpp/voice_interaction_state.h" +#include "components/arc/common/voice_interaction_framework.mojom.h" + +namespace mojo { + +template <> +struct EnumTraits<arc::mojom::VoiceInteractionState, + ash::VoiceInteractionState> { + static arc::mojom::VoiceInteractionState ToMojom( + ash::VoiceInteractionState state) { + switch (state) { + case ash::VoiceInteractionState::NOT_READY: + return arc::mojom::VoiceInteractionState::NOT_READY; + case ash::VoiceInteractionState::STOPPED: + return arc::mojom::VoiceInteractionState::STOPPED; + case ash::VoiceInteractionState::RUNNING: + return arc::mojom::VoiceInteractionState::RUNNING; + } + + NOTREACHED() << "Invalid state: " << static_cast<int>(state); + return arc::mojom::VoiceInteractionState::NOT_READY; + } + + static bool FromMojom(arc::mojom::VoiceInteractionState mojom_state, + ash::VoiceInteractionState* state) { + switch (mojom_state) { + case arc::mojom::VoiceInteractionState::NOT_READY: + *state = ash::VoiceInteractionState::NOT_READY; + return true; + case arc::mojom::VoiceInteractionState::STOPPED: + *state = ash::VoiceInteractionState::STOPPED; + return true; + case arc::mojom::VoiceInteractionState::RUNNING: + *state = ash::VoiceInteractionState::RUNNING; + return true; + } + + NOTREACHED() << "Invalid state: " << static_cast<int>(mojom_state); + *state = ash::VoiceInteractionState::NOT_READY; + return false; + } +}; + +} // namespace mojo + +#endif // COMPONENTS_ARC_VOICE_INTERACTION_VOICE_INTERACTION_STRUCT_TRAITS_H_
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index be8c652..dbb5b23 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -17,6 +17,8 @@ "address_rewriter.cc", "address_rewriter.h", "address_rewriter_rules.cc", + "address_validation_util.cc", + "address_validation_util.h", "autocomplete_history_manager.cc", "autocomplete_history_manager.h", "autofill-inl.h", @@ -56,6 +58,8 @@ "autofill_profile.h", "autofill_profile_comparator.cc", "autofill_profile_comparator.h", + "autofill_profile_validator.cc", + "autofill_profile_validator.h", "autofill_provider.cc", "autofill_provider.h", "autofill_scanner.cc", @@ -321,6 +325,7 @@ "address_i18n_unittest.cc", "address_rewriter_unittest.cc", "address_unittest.cc", + "address_validation_util_unittest.cc", "autocomplete_history_manager_unittest.cc", "autofill_country_unittest.cc", "autofill_data_model_unittest.cc", @@ -335,6 +340,7 @@ "autofill_metrics_unittest.cc", "autofill_profile_comparator_unittest.cc", "autofill_profile_unittest.cc", + "autofill_profile_validator_unittest.cc", "autofill_type_unittest.cc", "contact_info_unittest.cc", "country_combobox_model_unittest.cc",
diff --git a/components/autofill/core/browser/address_validation_util.cc b/components/autofill/core/browser/address_validation_util.cc new file mode 100644 index 0000000..76b056dc --- /dev/null +++ b/components/autofill/core/browser/address_validation_util.cc
@@ -0,0 +1,155 @@ +// 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/autofill/core/browser/address_validation_util.h" + +#include <utility> + +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "base/stl_util.h" +#include "base/strings/utf_string_conversions.h" +#include "components/autofill/core/browser/address_i18n.h" +#include "components/autofill/core/browser/country_data.h" +#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h" +#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_validator.h" + +namespace autofill { + +namespace { + +using ::i18n::addressinput::COUNTRY; +using ::i18n::addressinput::ADMIN_AREA; +using ::i18n::addressinput::LOCALITY; +using ::i18n::addressinput::DEPENDENT_LOCALITY; +using ::i18n::addressinput::SORTING_CODE; +using ::i18n::addressinput::POSTAL_CODE; +using ::i18n::addressinput::STREET_ADDRESS; +using ::i18n::addressinput::RECIPIENT; + +using ::i18n::addressinput::AddressData; +using ::i18n::addressinput::AddressField; +using ::i18n::addressinput::AddressProblem; +using ::i18n::addressinput::FieldProblemMap; + +using ::i18n::addressinput::INVALID_FORMAT; +using ::i18n::addressinput::MISMATCHING_VALUE; +using ::i18n::addressinput::MISSING_REQUIRED_FIELD; +using ::i18n::addressinput::UNEXPECTED_FIELD; +using ::i18n::addressinput::UNKNOWN_VALUE; + +const AddressField kFields[] = {COUNTRY, ADMIN_AREA, POSTAL_CODE}; +const AddressProblem kProblems[] = {UNEXPECTED_FIELD, MISSING_REQUIRED_FIELD, + UNKNOWN_VALUE, INVALID_FORMAT, + MISMATCHING_VALUE}; + +// If the |address_field| is valid, set the validity state of the +// |address_field| in the |profile| to the |state| and return true. +// Otherwise, return false. +bool SetValidityStateForAddressField(AutofillProfile* profile, + AddressField address_field, + AutofillProfile::ValidityState state) { + ServerFieldType server_field = i18n::TypeForField(address_field, + /*billing=*/false); + if (server_field == UNKNOWN_TYPE) + return false; + DCHECK(profile); + profile->SetValidityState(server_field, state); + return true; +} + +// Set the validity state of all address fields in the |profile| to |state|. +void SetAllValidityStates(AutofillProfile* profile, + AutofillProfile::ValidityState state) { + DCHECK(profile); + for (auto field : kFields) + SetValidityStateForAddressField(profile, field, state); +} + +// Returns all relevant pairs of (field, problem), where field is in +// |kFields|, and problem is in |kProblems|. +FieldProblemMap* CreateFieldProblemMap() { + FieldProblemMap* filter = new FieldProblemMap(); + for (auto field : kFields) { + for (auto problem : kProblems) { + filter->insert(std::make_pair(field, problem)); + } + } + return filter; +} + +// GetFilter() will make sure that the validation only returns problems that +// are relevant. +const FieldProblemMap* GetFilter() { + static const FieldProblemMap* const filter = CreateFieldProblemMap(); + return filter; +} + +// Initializes |address| data from the address info in the |profile|. +void InitializeAddressFromProfile(const AutofillProfile& profile, + AddressData* address) { + address->region_code = + base::UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY)); + address->administrative_area = + base::UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_STATE)); + address->postal_code = + base::UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_ZIP)); +} + +} // namespace + +namespace address_validation_util { + +AutofillProfile::ValidityState ValidateAddress( + AutofillProfile* profile, + AddressValidator* address_validator) { + DCHECK(address_validator); + if (!profile) + return AutofillProfile::UNVALIDATED; + + if (!base::ContainsValue( + CountryDataMap::GetInstance()->country_codes(), + base::UTF16ToUTF8(profile->GetRawInfo(ADDRESS_HOME_COUNTRY)))) { + // If the country code is not in the database, the country code and the + // profile are invalid, and other fields cannot be validated, because it is + // unclear which, if any, rule should apply. + SetAllValidityStates(profile, AutofillProfile::UNVALIDATED); + SetValidityStateForAddressField(profile, COUNTRY, AutofillProfile::INVALID); + return AutofillProfile::INVALID; + } + + AddressData address; + InitializeAddressFromProfile(*profile, &address); + + AutofillProfile::ValidityState profile_validity; + FieldProblemMap problems; + // status denotes if the rule was successfully loaded before validation. + AddressValidator::Status status = + address_validator->ValidateAddress(address, GetFilter(), &problems); + + if (status == AddressValidator::SUCCESS) { + // The rules were found and applied. Initialize all fields to VALID here and + // update the fields with problems below. + profile_validity = AutofillProfile::VALID; + SetAllValidityStates(profile, AutofillProfile::VALID); + } else { + // If the rules are not yet available, ValidateAddress can still check for + // MISSING_REQUIRED_FIELD. In this case, the address fields will be either + // UNVALIDATED or INVALID. + profile_validity = AutofillProfile::UNVALIDATED; + SetAllValidityStates(profile, AutofillProfile::UNVALIDATED); + SetValidityStateForAddressField(profile, COUNTRY, AutofillProfile::VALID); + } + + for (auto problem : problems) { + if (SetValidityStateForAddressField(profile, problem.first, + AutofillProfile::INVALID)) { + profile_validity = AutofillProfile::INVALID; + } + } + return profile_validity; +} + +} // namespace address_validation_util +} // namespace autofill
diff --git a/components/autofill/core/browser/address_validation_util.h b/components/autofill/core/browser/address_validation_util.h new file mode 100644 index 0000000..c58c6959 --- /dev/null +++ b/components/autofill/core/browser/address_validation_util.h
@@ -0,0 +1,23 @@ +// 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_AUTOFILL_CORE_BROWSER_ADDRESS_VALIDATION_UTIL_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_VALIDATION_UTIL_H_ + +#include "components/autofill/core/browser/autofill_profile.h" +#include "third_party/libaddressinput/chromium/chrome_address_validator.h" + +namespace autofill { +namespace address_validation_util { + +// Validates the address fields of the |profile|. +// Returns the ValidityState of the |profile| according to its address fields. +AutofillProfile::ValidityState ValidateAddress( + AutofillProfile* profile, + AddressValidator* address_validator); + +} // namespace address_validation_util +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_VALIDATION_UTIL_H_
diff --git a/components/autofill/core/browser/address_validation_util_unittest.cc b/components/autofill/core/browser/address_validation_util_unittest.cc new file mode 100644 index 0000000..c45f682 --- /dev/null +++ b/components/autofill/core/browser/address_validation_util_unittest.cc
@@ -0,0 +1,235 @@ +// 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/autofill/core/browser/address_validation_util.h" + +#include <memory> +#include <string> + +#include "base/bind.h" +#include "base/guid.h" +#include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_task_environment.h" +#include "components/autofill/core/browser/autofill_test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/libaddressinput/src/cpp/include/libaddressinput/null_storage.h" +#include "third_party/libaddressinput/src/cpp/test/testdata_source.h" + +namespace autofill { + +using ::i18n::addressinput::Source; +using ::i18n::addressinput::Storage; +using ::i18n::addressinput::NullStorage; +using ::i18n::addressinput::TestdataSource; + +// Used to load region rules for this test. +class ValidationTestDataSource : public TestdataSource { + public: + ValidationTestDataSource() : TestdataSource(true) {} + + ~ValidationTestDataSource() override {} + + void Get(const std::string& key, const Callback& data_ready) const override { + data_ready( + true, key, + new std::string( + "{" + "\"data/CA\": " + "{\"lang\": \"en\", \"upper\": \"ACNOSZ\", " + "\"zipex\": \"H3Z 2Y7,V8X 3X4,T0L 1K0,T0H 1A0\", " + "\"name\": \"CANADA\", " + "\"fmt\": \"%N%n%O%n%A%n%C %S %Z\", \"id\": \"data/CA\", " + "\"languages\": \"en~fr\", \"sub_keys\": \"NB~QC\", \"key\": " + "\"CA\", " + "\"require\": \"ACSZ\", \"sub_names\": \"New Brunswick~Quebec\", " + "\"sub_zips\": \"E~G|H|J\"}, " + "\"data/CA--fr\": " + "{\"lang\": \"fr\", \"upper\": \"ACNOSZ\", " + "\"zipex\": \"H3Z 2Y7,V8X 3X4,T0L 1K0,T0H 1A0\", " + "\"name\": \"CANADA\", " + "\"fmt\": \"%N%n%O%n%A%n%C %S %Z\", \"require\": \"ACSZ\", " + "\"sub_keys\": \"NB~QC\", \"key\": \"CA\", " + "\"id\": \"data/CA--fr\", " + "\"sub_names\":\"Nouveau-Brunswick~Québec\"," + "\"sub_zips\": \"E~G|H|J\"}, " + "\"data/CA/QC\": " + "{\"lang\": \"en\", \"key\": \"QC\", " + "\"id\": \"data/CA/QC\", \"zip\": \"G|H|J\", \"name\": \"Quebec\"}," + "\"data/CA/QC--fr\": " + "{\"lang\": \"fr\", \"key\": \"QC\", \"id\": \"data/CA/QC--fr\", " + "\"zip\": \"G|H|J\", \"name\": \"Québec\"}, " + "\"data/CA/NB\": " + "{\"lang\": \"en\", \"key\": \"NB\", \"id\": \"data/CA/NB\", " + "\"zip\": \"E\", \"name\": \"New Brunswick\"}, " + "\"data/CA/NB--fr\": " + "{\"lang\": \"fr\", \"key\": \"NB\", \"id\": \"data/CA/NB--fr\", " + "\"zip\": \"E\", \"name\": \"Nouveau-Brunswick\"}" + "}")); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ValidationTestDataSource); +}; + +class AutofillAddressValidationTest : public testing::Test, LoadRulesListener { + public: + AutofillAddressValidationTest() + : validator_(std::unique_ptr<Source>(new ValidationTestDataSource()), + std::unique_ptr<Storage>(new NullStorage), + this) { + validator_.LoadRules("CA"); + } + + AutofillProfile::ValidityState ValidateAddressTest(AutofillProfile* profile) { + return address_validation_util::ValidateAddress(profile, &validator_); + } + + ~AutofillAddressValidationTest() override {} + + private: + AddressValidator validator_; + + // LoadRulesListener implementation. + void OnAddressValidationRulesLoaded(const std::string& country_code, + bool success) override {} + + DISALLOW_COPY_AND_ASSIGN(AutofillAddressValidationTest); +}; + +TEST_F(AutofillAddressValidationTest, ValidateNULLProfile) { + EXPECT_EQ(AutofillProfile::UNVALIDATED, ValidateAddressTest(nullptr)); +} + +TEST_F(AutofillAddressValidationTest, ValidateFullValidProfile) { + // This is a valid profile according to the rules in ValidationTestDataSource: + // Address Line 1: "666 Notre-Dame Ouest", + // Address Line 2: "Apt 8", City: "Montreal", Province: "QC", + // Postal Code: "H3B 2T9", Country Code: "CA", + AutofillProfile profile(autofill::test::GetFullValidProfile()); + EXPECT_EQ(AutofillProfile::VALID, ValidateAddressTest(&profile)); + EXPECT_EQ(AutofillProfile::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY)); + EXPECT_EQ(AutofillProfile::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE)); + EXPECT_EQ(AutofillProfile::VALID, profile.GetValidityState(ADDRESS_HOME_ZIP)); +} + +TEST_F(AutofillAddressValidationTest, ValidateFullProfile_CountryCodeNotExist) { + // This is a profile with invalid country code, therefore it cannot be + // validated according to ValidationTestDataSource. + const std::string country_code = "PP"; + AutofillProfile profile(autofill::test::GetFullValidProfile()); + profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16(country_code)); + EXPECT_EQ(AutofillProfile::INVALID, ValidateAddressTest(&profile)); + EXPECT_EQ(AutofillProfile::INVALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY)); + EXPECT_EQ(AutofillProfile::UNVALIDATED, + profile.GetValidityState(ADDRESS_HOME_STATE)); + EXPECT_EQ(AutofillProfile::UNVALIDATED, + profile.GetValidityState(ADDRESS_HOME_ZIP)); +} + +TEST_F(AutofillAddressValidationTest, ValidateFullProfile_RuleNotAvailable) { + // This is a profile with valid country code, but the rule is not available in + // the ValidationTestDataSource. + const std::string country_code = "US"; + AutofillProfile profile(autofill::test::GetFullValidProfile()); + profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16(country_code)); + EXPECT_EQ(AutofillProfile::UNVALIDATED, ValidateAddressTest(&profile)); + EXPECT_EQ(AutofillProfile::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY)); + EXPECT_EQ(AutofillProfile::UNVALIDATED, + profile.GetValidityState(ADDRESS_HOME_STATE)); + EXPECT_EQ(AutofillProfile::UNVALIDATED, + profile.GetValidityState(ADDRESS_HOME_ZIP)); +} + +TEST_F(AutofillAddressValidationTest, ValidateAddress_AdminAreaNotExists) { + const std::string admin_area_code = "QQ"; + AutofillProfile profile(autofill::test::GetFullValidProfile()); + profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16(admin_area_code)); + + EXPECT_EQ(AutofillProfile::INVALID, ValidateAddressTest(&profile)); + EXPECT_EQ(AutofillProfile::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY)); + EXPECT_EQ(AutofillProfile::INVALID, + profile.GetValidityState(ADDRESS_HOME_STATE)); + EXPECT_EQ(AutofillProfile::VALID, profile.GetValidityState(ADDRESS_HOME_ZIP)); +} + +TEST_F(AutofillAddressValidationTest, ValidateAddress_AdminAreaFullName) { + const std::string admin_area = "Quebec"; + AutofillProfile profile(autofill::test::GetFullValidProfile()); + profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16(admin_area)); + + EXPECT_EQ(AutofillProfile::VALID, ValidateAddressTest(&profile)); + EXPECT_EQ(AutofillProfile::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY)); + EXPECT_EQ(AutofillProfile::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE)); + EXPECT_EQ(AutofillProfile::VALID, profile.GetValidityState(ADDRESS_HOME_ZIP)); +} + +TEST_F(AutofillAddressValidationTest, ValidateAddress_AdminAreaSmallCode) { + const std::string admin_area = "qc"; + AutofillProfile profile(autofill::test::GetFullValidProfile()); + profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16(admin_area)); + + EXPECT_EQ(AutofillProfile::VALID, ValidateAddressTest(&profile)); + EXPECT_EQ(AutofillProfile::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY)); + EXPECT_EQ(AutofillProfile::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE)); + EXPECT_EQ(AutofillProfile::VALID, profile.GetValidityState(ADDRESS_HOME_ZIP)); +} + +TEST_F(AutofillAddressValidationTest, ValidateAddress_AdminAreaSpecialLetter) { + const std::string admin_area = "Québec"; + AutofillProfile profile(autofill::test::GetFullValidProfile()); + profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16(admin_area)); + + EXPECT_EQ(AutofillProfile::VALID, ValidateAddressTest(&profile)); + EXPECT_EQ(AutofillProfile::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY)); + EXPECT_EQ(AutofillProfile::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE)); + EXPECT_EQ(AutofillProfile::VALID, profile.GetValidityState(ADDRESS_HOME_ZIP)); +} + +TEST_F(AutofillAddressValidationTest, ValidateAddress_ValidZipNoSpace) { + // TODO(crbug/752614): postal codes in lower case letters should also be + // considered as valid. Now, they are considered as INVALID. + const std::string postal_code = "H3C6S3"; + AutofillProfile profile(autofill::test::GetFullValidProfile()); + profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16(postal_code)); + + EXPECT_EQ(AutofillProfile::VALID, ValidateAddressTest(&profile)); + EXPECT_EQ(AutofillProfile::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY)); + EXPECT_EQ(AutofillProfile::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE)); + EXPECT_EQ(AutofillProfile::VALID, profile.GetValidityState(ADDRESS_HOME_ZIP)); +} + +TEST_F(AutofillAddressValidationTest, ValidateAddress_InvalidZip) { + const std::string postal_code = "ABC 123"; + AutofillProfile profile(autofill::test::GetFullValidProfile()); + profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16(postal_code)); + + EXPECT_EQ(AutofillProfile::INVALID, ValidateAddressTest(&profile)); + EXPECT_EQ(AutofillProfile::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY)); + EXPECT_EQ(AutofillProfile::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE)); + EXPECT_EQ(AutofillProfile::INVALID, + profile.GetValidityState(ADDRESS_HOME_ZIP)); +} + +// TODO(crbug/754727): add tests for a non-default language. +// Ex: Nouveau-Brunswick for Canada. + +// TODO(crbug/754729): Add tests for a country whose default language is a +// non-Western one, such as China. + +} // namespace autofill
diff --git a/components/autofill/core/browser/autofill_profile_validator.cc b/components/autofill/core/browser/autofill_profile_validator.cc new file mode 100644 index 0000000..5fd3b327 --- /dev/null +++ b/components/autofill/core/browser/autofill_profile_validator.cc
@@ -0,0 +1,129 @@ +// 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/autofill/core/browser/autofill_profile_validator.h" + +#include <utility> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/cancelable_callback.h" +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "base/strings/utf_string_conversions.h" +#include "base/threading/sequenced_task_runner_handle.h" +#include "base/time/time.h" +#include "components/autofill/core/browser/address_validation_util.h" +#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h" +#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_validator.h" + +namespace autofill { +namespace { + +using ::i18n::addressinput::COUNTRY; +using ::i18n::addressinput::ADMIN_AREA; +using ::i18n::addressinput::LOCALITY; +using ::i18n::addressinput::DEPENDENT_LOCALITY; +using ::i18n::addressinput::SORTING_CODE; +using ::i18n::addressinput::POSTAL_CODE; +using ::i18n::addressinput::STREET_ADDRESS; +using ::i18n::addressinput::RECIPIENT; + +const int kRulesLoadingTimeoutSeconds = 5; + +} // namespace + +AutofillProfileValidator::ValidationRequest::ValidationRequest( + AutofillProfile* profile, + autofill::AddressValidator* validator, + AutofillProfileValidatorCallback on_validated) + : profile_(profile), + validator_(validator), + on_validated_(std::move(on_validated)), + has_responded_(false), + on_timeout_(base::Bind(&ValidationRequest::OnRulesLoaded, + base::Unretained(this))) { + DCHECK(profile_); + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, on_timeout_.callback(), + base::TimeDelta::FromSeconds(kRulesLoadingTimeoutSeconds)); +} + +AutofillProfileValidator::ValidationRequest::~ValidationRequest() { + on_timeout_.Cancel(); +} + +void AutofillProfileValidator::ValidationRequest::OnRulesLoaded() { + on_timeout_.Cancel(); + // Check if the timeout happened before the rules were loaded. + if (has_responded_) + return; + has_responded_ = true; + AutofillProfile::ValidityState profile_validity = + address_validation_util::ValidateAddress(profile_, validator_); + std::move(on_validated_).Run(profile_validity); +} + +AutofillProfileValidator::AutofillProfileValidator( + std::unique_ptr<Source> source, + std::unique_ptr<Storage> storage) + : address_validator_(std::move(source), std::move(storage), this) {} + +AutofillProfileValidator::~AutofillProfileValidator() {} + +void AutofillProfileValidator::ValidateProfile( + AutofillProfile* profile, + AutofillProfileValidatorCallback cb) { + if (!profile) { + // An null profile is an unvalidated profile. + std::move(cb).Run(AutofillProfile::UNVALIDATED); + return; + } + std::unique_ptr<ValidationRequest> request( + base::MakeUnique<ValidationRequest>(profile, &address_validator_, + std::move(cb))); + + // If the |region_code| is not a valid code according to our source, calling + // LoadRules would result in calling OnAddressValidationRulesLoaded with + // success = false. Thus, we can handle illegitimate |region_code|'s as well. + std::string region_code = + base::UTF16ToUTF8(profile->GetRawInfo(ADDRESS_HOME_COUNTRY)); + if (address_validator_.AreRulesLoadedForRegion(region_code)) { + request->OnRulesLoaded(); + } else { + // Setup the variables to start validation when the rules are loaded. + pending_requests_[region_code].push_back(std::move(request)); + + // Start loading the rules for the region. If the rules were already in the + // process of being loaded, this call will do nothing. + address_validator_.LoadRules(region_code); + } +} + +void AutofillProfileValidator::OnAddressValidationRulesLoaded( + const std::string& region_code, + bool success) { + // Even if success = false, we can still validate address partially. We can + // check for missing fields or unexpected fields. + + // Check if there is any request for that region code. + auto it = pending_requests_.find(region_code); + if (it != pending_requests_.end()) { + for (auto& request : it->second) { + request->OnRulesLoaded(); + } + pending_requests_.erase(it); + } +} + +bool AutofillProfileValidator::AreRulesLoadedForRegion( + const std::string& region_code) { + return address_validator_.AreRulesLoadedForRegion(region_code); +} + +void AutofillProfileValidator::LoadRulesForRegion( + const std::string& region_code) { + address_validator_.LoadRules(region_code); +} +} // namespace autofill
diff --git a/components/autofill/core/browser/autofill_profile_validator.h b/components/autofill/core/browser/autofill_profile_validator.h new file mode 100644 index 0000000..e1d4bab --- /dev/null +++ b/components/autofill/core/browser/autofill_profile_validator.h
@@ -0,0 +1,108 @@ +// 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_AUTOFILL_CORE_BROWSER_AUTOFILL_PROFILE_VALIDATOR_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_PROFILE_VALIDATOR_H_ + +#include <stddef.h> + +#include <map> +#include <memory> +#include <string> +#include <vector> + +#include "base/cancelable_callback.h" +#include "base/macros.h" +#include "components/autofill/core/browser/address_i18n.h" +#include "components/autofill/core/browser/address_validation_util.h" +#include "components/autofill/core/browser/autofill_profile.h" +#include "third_party/libaddressinput/chromium/chrome_address_validator.h" +#include "third_party/libaddressinput/src/cpp/include/libaddressinput/preload_supplier.h" +#include "third_party/libaddressinput/src/cpp/include/libaddressinput/source.h" +#include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h" + +namespace autofill { + +using ::i18n::addressinput::BuildCallback; +using ::i18n::addressinput::PreloadSupplier; +using ::i18n::addressinput::Source; +using ::i18n::addressinput::Storage; + +using AutofillProfileValidatorCallback = + base::OnceCallback<void(AutofillProfile::ValidityState)>; + +// AutofillProfileValidator Loads Rules from the server and validates an +// autofill profile. For a given autofill profile, it will set the ValidityState +// of several fields in the profile such as country, administrative area, etc. +// See implementation for more details. +class AutofillProfileValidator : public autofill::LoadRulesListener { + public: + // Takes ownership of |source| and |storage|. + AutofillProfileValidator( + std::unique_ptr<::i18n::addressinput::Source> source, + std::unique_ptr<::i18n::addressinput::Storage> storage); + + ~AutofillProfileValidator() override; + + // If the rule corresponding to the |profile| is loaded, this validates the + // profile, synchronously. If it is not loaded yet, it sets up a + // task to validate the profile when the rule is loaded (asynchronous). If the + // loading has not yet started, it will also start loading the rules. + void ValidateProfile(AutofillProfile* profile, + AutofillProfileValidatorCallback cb); + + private: + // ValidationRequest loads Rules from the server and validates various fields + // in an autofill profile. + class ValidationRequest { + public: + ValidationRequest(AutofillProfile* profile, + autofill::AddressValidator* validator, + AutofillProfileValidatorCallback on_validated); + + ~ValidationRequest(); + + // Validates various fields of the |profile_|, and calls |on_validated_|. + void OnRulesLoaded(); + + private: + // Not owned. Not Null. Outlives this object. + AutofillProfile* profile_; + // Not owned. Outlives this object. + autofill::AddressValidator* validator_; + + AutofillProfileValidatorCallback on_validated_; + + bool has_responded_ = false; + base::CancelableCallback<void()> on_timeout_; + + DISALLOW_COPY_AND_ASSIGN(ValidationRequest); + }; + + friend class AutofillProfileValidatorTest; + + // Returns whether the rules for the specified |region_code| is loaded. + bool AreRulesLoadedForRegion(const std::string& region_code); + + // Starts loading the rules for the specified |region_code|. + void LoadRulesForRegion(const std::string& region_code); + + // Implementation of the LoadRulesListener interface. Called when the address + // rules for the |region_code| have finished loading. + void OnAddressValidationRulesLoaded(const std::string& region_code, + bool success) override; + + // A map of the region code and the pending requests for that region code. + std::map<std::string, std::vector<std::unique_ptr<ValidationRequest>>> + pending_requests_; + + // The address validator used to load rules. + autofill::AddressValidator address_validator_; + + DISALLOW_COPY_AND_ASSIGN(AutofillProfileValidator); +}; + +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_PROFILE_VALIDATOR_H_
diff --git a/components/autofill/core/browser/autofill_profile_validator_unittest.cc b/components/autofill/core/browser/autofill_profile_validator_unittest.cc new file mode 100644 index 0000000..e17c0196 --- /dev/null +++ b/components/autofill/core/browser/autofill_profile_validator_unittest.cc
@@ -0,0 +1,165 @@ +// 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/autofill/core/browser/autofill_profile_validator.h" + +#include <stddef.h> +#include <set> +#include <string> +#include <utility> +#include <vector> + +#include "base/bind.h" +#include "base/guid.h" +#include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_task_environment.h" +#include "components/autofill/core/browser/autofill_test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/libaddressinput/src/cpp/include/libaddressinput/null_storage.h" +#include "third_party/libaddressinput/src/cpp/test/testdata_source.h" + +namespace autofill { + +using ::i18n::addressinput::NullStorage; +using ::i18n::addressinput::TestdataSource; + +using ::i18n::addressinput::COUNTRY; +using ::i18n::addressinput::ADMIN_AREA; +using ::i18n::addressinput::LOCALITY; +using ::i18n::addressinput::DEPENDENT_LOCALITY; +using ::i18n::addressinput::SORTING_CODE; +using ::i18n::addressinput::POSTAL_CODE; +using ::i18n::addressinput::STREET_ADDRESS; +using ::i18n::addressinput::RECIPIENT; + +// Used to load region rules for this test. +class ValidationTestDataSource : public TestdataSource { + public: + ValidationTestDataSource() : TestdataSource(true) {} + + ~ValidationTestDataSource() override {} + + void Get(const std::string& key, const Callback& data_ready) const override { + data_ready( + true, key, + new std::string( + "{" + "\"data/CA\": " + "{\"lang\": \"en\", \"upper\": \"ACNOSZ\", " + "\"zipex\": \"H3Z 2Y7,V8X 3X4,T0L 1K0,T0H 1A0\", " + "\"name\": \"CANADA\", " + "\"fmt\": \"%N%n%O%n%A%n%C %S %Z\", \"id\": \"data/CA\", " + "\"languages\": \"en\", \"sub_keys\": \"QC\", \"key\": " + "\"CA\", " + "\"require\": \"ACSZ\", \"sub_names\": \"Quebec\", " + "\"sub_zips\": \"G|H|J\"}, " + "\"data/CA/QC\": " + "{\"lang\": \"en\", \"key\": \"QC\", " + "\"id\": \"data/CA/QC\", \"zip\": \"G|H|J\", \"name\": \"Quebec\"}" + "}")); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ValidationTestDataSource); +}; + +class AutofillProfileValidatorTest : public testing::Test { + public: + AutofillProfileValidatorTest() + : validator_(new AutofillProfileValidator( + std::unique_ptr<Source>(new ValidationTestDataSource()), + std::unique_ptr<Storage>(new NullStorage))), + onvalidated_cb_( + base::BindOnce(&AutofillProfileValidatorTest::OnValidated, + base::Unretained(this))) {} + + protected: + const std::unique_ptr<AutofillProfileValidator> validator_; + + ~AutofillProfileValidatorTest() override {} + + void OnValidated(AutofillProfile::ValidityState profile_valid) { + EXPECT_EQ(expected_validity_state_, profile_valid); + } + + void set_expected_status(AutofillProfile::ValidityState profile_valid) { + expected_validity_state_ = profile_valid; + } + + bool AreRulesLoadedForRegion(std::string region_code) { + return validator_->AreRulesLoadedForRegion(region_code); + } + + void LoadRulesForRegion(std::string region_code) { + validator_->LoadRulesForRegion(region_code); + } + + AutofillProfileValidatorCallback onvalidated_cb_; + + private: + AutofillProfile::ValidityState expected_validity_state_; + + base::test::ScopedTaskEnvironment scoped_task_scheduler; + + DISALLOW_COPY_AND_ASSIGN(AutofillProfileValidatorTest); +}; + +// Validate a Null profile. +TEST_F(AutofillProfileValidatorTest, ValidateNullProfile) { + set_expected_status(AutofillProfile::UNVALIDATED); + validator_->ValidateProfile(nullptr, std::move(onvalidated_cb_)); +} +// Validate a valid profile, for which the rules are not loaded, yet. +TEST_F(AutofillProfileValidatorTest, ValidateFullValidProfile_RulesNotLoaded) { + // This is a valid profile, and the rules are loaded in the constructors + // Province: "QC", Country: "CA" + AutofillProfile profile(autofill::test::GetFullValidProfile()); + set_expected_status(AutofillProfile::VALID); + + std::string country_code = + base::UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY)); + EXPECT_EQ(false, AreRulesLoadedForRegion(country_code)); + + validator_->ValidateProfile(&profile, std::move(onvalidated_cb_)); +} + +// Validate a Full Profile, for which the rules are already loaded. +TEST_F(AutofillProfileValidatorTest, ValidateAddress_RulesLoaded) { + AutofillProfile profile(autofill::test::GetFullValidProfile()); + set_expected_status(AutofillProfile::VALID); + + std::string country_code = + base::UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY)); + LoadRulesForRegion(country_code); + EXPECT_EQ(true, AreRulesLoadedForRegion(country_code)); + + validator_->ValidateProfile(&profile, std::move(onvalidated_cb_)); +} + +// When country code is invalid, the profile is invalid. +TEST_F(AutofillProfileValidatorTest, ValidateAddress_CountryCodeNotExists) { + const std::string country_code = "PP"; + AutofillProfile profile(autofill::test::GetFullValidProfile()); + profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16(country_code)); + set_expected_status(AutofillProfile::INVALID); + + EXPECT_EQ(false, AreRulesLoadedForRegion(country_code)); + + validator_->ValidateProfile(&profile, std::move(onvalidated_cb_)); +} + +// When country code is valid, but the rule is not in the source, the profile +// is unvalidated. +TEST_F(AutofillProfileValidatorTest, ValidateAddress_RuleNotExists) { + const std::string country_code = "US"; + AutofillProfile profile(autofill::test::GetFullValidProfile()); + profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16(country_code)); + set_expected_status(AutofillProfile::UNVALIDATED); + + EXPECT_EQ(false, AreRulesLoadedForRegion(country_code)); + + validator_->ValidateProfile(&profile, std::move(onvalidated_cb_)); +} + +} // namespace autofill
diff --git a/components/autofill/core/browser/autofill_test_utils.cc b/components/autofill/core/browser/autofill_test_utils.cc index f6a122ef..aa3b5952 100644 --- a/components/autofill/core/browser/autofill_test_utils.cc +++ b/components/autofill/core/browser/autofill_test_utils.cc
@@ -183,6 +183,14 @@ profile->SetRawInfo(type, base::UTF8ToUTF16(value)); } +AutofillProfile GetFullValidProfile() { + AutofillProfile profile(base::GenerateGUID(), "http://www.example.com/"); + SetProfileInfo(&profile, "Alice", "", "Wonderland", "alice@wonderland.ca", + "Fiction", "666 Notre-Dame Ouest", "Apt 8", "Montreal", "QC", + "H3B 2T9", "CA", "15141112233"); + return profile; +} + AutofillProfile GetFullProfile() { AutofillProfile profile(base::GenerateGUID(), "http://www.example.com/"); SetProfileInfo(&profile,
diff --git a/components/autofill/core/browser/autofill_test_utils.h b/components/autofill/core/browser/autofill_test_utils.h index 65817d8..708f3a64 100644 --- a/components/autofill/core/browser/autofill_test_utils.h +++ b/components/autofill/core/browser/autofill_test_utils.h
@@ -65,6 +65,9 @@ void CreateTestAddressFormData(FormData* form, std::vector<ServerFieldTypeSet>* types); +// Returns a full profile with valid info. +AutofillProfile GetFullValidProfile(); + // Returns a profile full of dummy info. AutofillProfile GetFullProfile();
diff --git a/components/crash/content/browser/child_process_crash_observer_android.cc b/components/crash/content/browser/child_process_crash_observer_android.cc index b9ae22bb..b59a0dd 100644 --- a/components/crash/content/browser/child_process_crash_observer_android.cc +++ b/components/crash/content/browser/child_process_crash_observer_android.cc
@@ -45,8 +45,8 @@ FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND}, base::Bind(&CrashDumpManager::ProcessMinidumpFileFromChild, base::Unretained(CrashDumpManager::GetInstance()), - crash_dump_dir_, pid, process_type, termination_status, - app_state)); + crash_dump_dir_, child_process_id, process_type, + termination_status, app_state)); } } // namespace breakpad
diff --git a/components/feature_engagement/public/event_constants.cc b/components/feature_engagement/public/event_constants.cc index 72ea6bd..b2fb65c 100644 --- a/components/feature_engagement/public/event_constants.cc +++ b/components/feature_engagement/public/event_constants.cc
@@ -10,11 +10,11 @@ #if defined(OS_WIN) || defined(OS_LINUX) const char kOmniboxInteraction[] = "omnibox_used"; +const char kNewTabSessionTimeMet[] = "new_tab_session_time_met"; const char kHistoryDeleted[] = "history_deleted"; const char kIncognitoWindowOpened[] = "incognito_window_opened"; -const char kSessionTime[] = "session_time"; #endif // defined(OS_WIN) || defined(OS_LINUX) #if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_IOS)
diff --git a/components/feature_engagement/public/event_constants.h b/components/feature_engagement/public/event_constants.h index 0b93423..e6d514b2 100644 --- a/components/feature_engagement/public/event_constants.h +++ b/components/feature_engagement/public/event_constants.h
@@ -17,6 +17,9 @@ // The user has interacted with the omnibox. extern const char kOmniboxInteraction[]; +// The user has satisfied the session time requirement to show the NewTabPromo +// by accumulating 2 hours of active session time (one-off event). +extern const char kNewTabSessionTimeMet[]; // All the events declared below are the string names // of deferred onboarding events for the Incognito Window @@ -26,12 +29,6 @@ // The user has opened an incognito window. extern const char kIncognitoWindowOpened[]; -// All the events declared below are the string names -// of common deferred onboarding events - -// The user has accumulated 2 hours of active session time (one-off event). -extern const char kSessionTime[]; - #endif // defined(OS_WIN) || defined(OS_LINUX) #if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_IOS)
diff --git a/components/feedback/system_logs/system_logs_fetcher.h b/components/feedback/system_logs/system_logs_fetcher.h index 1799d4f..238bb60 100644 --- a/components/feedback/system_logs/system_logs_fetcher.h +++ b/components/feedback/system_logs/system_logs_fetcher.h
@@ -51,7 +51,8 @@ // Adds a source to use when fetching. void AddSource(std::unique_ptr<SystemLogsSource> source); - // Starts the fetch process. + // Starts the fetch process. After the fetch completes, this instance calls + // |callback|, then schedules itself to be deleted. void Fetch(const SysLogsFetcherCallback& callback); private:
diff --git a/components/infobars/core/infobar_delegate.h b/components/infobars/core/infobar_delegate.h index 1405106..513d447 100644 --- a/components/infobars/core/infobar_delegate.h +++ b/components/infobars/core/infobar_delegate.h
@@ -240,7 +240,7 @@ protected: InfoBarDelegate(); - InfoBar* infobar() { return infobar_; } + InfoBar* infobar() const { return infobar_; } private: // The InfoBar associated with us.
diff --git a/components/omnibox/browser/history_url_provider_unittest.cc b/components/omnibox/browser/history_url_provider_unittest.cc index bbc8e0c..5011aec 100644 --- a/components/omnibox/browser/history_url_provider_unittest.cc +++ b/components/omnibox/browser/history_url_provider_unittest.cc
@@ -1178,9 +1178,7 @@ } autocomplete_->scoring_params_ = test_cases[i].scoring_params; - // Test the experiment (scoring enabled). When scoring is disabled, it uses - // the default experimental scoring. - autocomplete_->scoring_params_.experimental_scoring_enabled = true; + // Test the experimental scoring params. ASSERT_NO_FATAL_FAILURE(RunTest(ASCIIToUTF16(test_cases[i].input), std::string(), false, output, max_matches)); for (int j = 0; j < max_matches; ++j) {
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc index 1413e0d..22e7b00 100644 --- a/components/omnibox/browser/omnibox_field_trial.cc +++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -428,20 +428,11 @@ void OmniboxFieldTrial::GetExperimentalHUPScoringParams( HUPScoringParams* scoring_params) { - scoring_params->experimental_scoring_enabled = false; - VariationParams params; if (!variations::GetVariationParams(kBundledExperimentFieldTrialName, ¶ms)) return; - VariationParams::const_iterator it = params.find(kHUPNewScoringEnabledParam); - if (it != params.end()) { - int enabled = 0; - if (base::StringToInt(it->second, &enabled)) - scoring_params->experimental_scoring_enabled = (enabled != 0); - } - InitializeScoreBuckets(params, kHUPNewScoringTypedCountRelevanceCapParam, kHUPNewScoringTypedCountHalfLifeTimeParam, kHUPNewScoringTypedCountScoreBucketsParam, @@ -757,8 +748,6 @@ const char OmniboxFieldTrial::kPhysicalWebAfterTypingRule[] = "PhysicalWebAfterTyping"; -const char OmniboxFieldTrial::kHUPNewScoringEnabledParam[] = - "HUPExperimentalScoringEnabled"; const char OmniboxFieldTrial::kHUPNewScoringTypedCountRelevanceCapParam[] = "TypedCountRelevanceCap"; const char OmniboxFieldTrial::kHUPNewScoringTypedCountHalfLifeTimeParam[] =
diff --git a/components/omnibox/browser/omnibox_field_trial.h b/components/omnibox/browser/omnibox_field_trial.h index 3dfa3734..bc94a4b 100644 --- a/components/omnibox/browser/omnibox_field_trial.h +++ b/components/omnibox/browser/omnibox_field_trial.h
@@ -109,9 +109,7 @@ bool use_decay_factor_; }; - HUPScoringParams() : experimental_scoring_enabled(false) {} - - bool experimental_scoring_enabled; + HUPScoringParams() {} ScoreBuckets typed_count_buckets; @@ -262,8 +260,7 @@ // bundled omnibox field trial. // Initializes the HUP |scoring_params| based on the active HUP scoring - // experiment. If there is no such experiment, this function simply sets - // |scoring_params|->experimental_scoring_enabled to false. + // experiment. static void GetDefaultHUPScoringParams(HUPScoringParams* scoring_params); static void GetExperimentalHUPScoringParams(HUPScoringParams* scoring_params); @@ -469,7 +466,6 @@ static const char kPhysicalWebAfterTypingRule[]; // Parameter names used by the HUP new scoring experiments. - static const char kHUPNewScoringEnabledParam[]; static const char kHUPNewScoringTypedCountRelevanceCapParam[]; static const char kHUPNewScoringTypedCountHalfLifeTimeParam[]; static const char kHUPNewScoringTypedCountScoreBucketsParam[];
diff --git a/components/omnibox/browser/omnibox_field_trial_unittest.cc b/components/omnibox/browser/omnibox_field_trial_unittest.cc index f4d9183..3890a55 100644 --- a/components/omnibox/browser/omnibox_field_trial_unittest.cc +++ b/components/omnibox/browser/omnibox_field_trial_unittest.cc
@@ -396,7 +396,6 @@ TEST_F(OmniboxFieldTrialTest, HUPNewScoringFieldTrial) { { std::map<std::string, std::string> params; - params[std::string(OmniboxFieldTrial::kHUPNewScoringEnabledParam)] = "1"; params[std::string( OmniboxFieldTrial::kHUPNewScoringTypedCountRelevanceCapParam)] = "56"; params[std::string( @@ -419,7 +418,6 @@ HUPScoringParams scoring_params; OmniboxFieldTrial::GetExperimentalHUPScoringParams(&scoring_params); - EXPECT_TRUE(scoring_params.experimental_scoring_enabled); EXPECT_EQ(56, scoring_params.typed_count_buckets.relevance_cap()); EXPECT_EQ(77, scoring_params.typed_count_buckets.half_life_days()); ASSERT_EQ(3u, scoring_params.typed_count_buckets.buckets().size()); @@ -441,7 +439,6 @@ TEST_F(OmniboxFieldTrialTest, HUPNewScoringFieldTrialWithDecayFactor) { { std::map<std::string, std::string> params; - params[OmniboxFieldTrial::kHUPNewScoringEnabledParam] = "1"; params[OmniboxFieldTrial::kHUPNewScoringTypedCountHalfLifeTimeParam] = "10"; params[OmniboxFieldTrial::kHUPNewScoringTypedCountUseDecayFactorParam] = "1"; @@ -455,7 +452,6 @@ HUPScoringParams scoring_params; OmniboxFieldTrial::GetExperimentalHUPScoringParams(&scoring_params); - EXPECT_TRUE(scoring_params.experimental_scoring_enabled); EXPECT_EQ(10, scoring_params.typed_count_buckets.half_life_days()); ASSERT_EQ(3u, scoring_params.typed_count_buckets.buckets().size()); ASSERT_TRUE(scoring_params.typed_count_buckets.use_decay_factor());
diff --git a/components/payments/content/payment_request.cc b/components/payments/content/payment_request.cc index 6359865..a55f986 100644 --- a/components/payments/content/payment_request.cc +++ b/components/payments/content/payment_request.cc
@@ -8,6 +8,7 @@ #include <utility> #include "base/memory/ptr_util.h" +#include "base/stl_util.h" #include "components/payments/content/can_make_payment_query_factory.h" #include "components/payments/content/origin_security_checker.h" #include "components/payments/content/payment_details_validation.h" @@ -110,6 +111,30 @@ state_ = base::MakeUnique<PaymentRequestState>( spec_.get(), this, delegate_->GetApplicationLocale(), delegate_->GetPersonalDataManager(), delegate_.get(), &journey_logger_); + + journey_logger_.SetRequestedInformation( + spec_->request_shipping(), spec_->request_payer_email(), + spec_->request_payer_phone(), spec_->request_payer_name()); + + // Log metrics around which payment methods are requested by the merchant. + GURL google_pay_url(kGooglePayMethodName); + GURL android_pay_url(kAndroidPayMethodName); + // Looking for payment methods that are NOT google-related payment methods. + auto non_google_it = + std::find_if(spec_->url_payment_method_identifiers().begin(), + spec_->url_payment_method_identifiers().end(), + [google_pay_url, android_pay_url](const GURL& url) { + return url != google_pay_url && url != android_pay_url; + }); + journey_logger_.SetRequestedPaymentMethodTypes( + /*requested_basic_card=*/!spec_->supported_card_networks().empty(), + /*requested_method_google=*/ + base::ContainsValue(spec_->url_payment_method_identifiers(), + google_pay_url) || + base::ContainsValue(spec_->url_payment_method_identifiers(), + android_pay_url), + /*requested_method_other=*/non_google_it != + spec_->url_payment_method_identifiers().end()); } void PaymentRequest::Show() { @@ -124,7 +149,6 @@ LOG(ERROR) << "A PaymentRequest UI is already showing"; journey_logger_.SetNotShown( JourneyLogger::NOT_SHOWN_REASON_CONCURRENT_REQUESTS); - has_recorded_completion_ = true; client_->OnError(mojom::PaymentErrorReason::USER_CANCEL); OnConnectionTerminated(); return; @@ -133,7 +157,6 @@ if (!state_->AreRequestedMethodsSupported()) { journey_logger_.SetNotShown( JourneyLogger::NOT_SHOWN_REASON_NO_SUPPORTED_PAYMENT_METHOD); - has_recorded_completion_ = true; client_->OnError(mojom::PaymentErrorReason::NOT_SUPPORTED); if (observer_for_testing_) observer_for_testing_->OnNotSupportedError(); @@ -142,9 +165,6 @@ } journey_logger_.SetEventOccurred(JourneyLogger::EVENT_SHOWN); - journey_logger_.SetRequestedInformation( - spec_->request_shipping(), spec_->request_payer_email(), - spec_->request_payer_phone(), spec_->request_payer_name()); delegate_->ShowDialog(this); }
diff --git a/components/payments/content/payment_request_spec.cc b/components/payments/content/payment_request_spec.cc index c831329..e328318 100644 --- a/components/payments/content/payment_request_spec.cc +++ b/components/payments/content/payment_request_spec.cc
@@ -129,6 +129,8 @@ } // namespace const char kBasicCardMethodName[] = "basic-card"; +const char kGooglePayMethodName[] = "https://google.com/pay"; +const char kAndroidPayMethodName[] = "https://android.com/pay"; PaymentRequestSpec::PaymentRequestSpec( mojom::PaymentOptionsPtr options,
diff --git a/components/payments/content/payment_request_spec.h b/components/payments/content/payment_request_spec.h index 4745acf..01a9e8cc 100644 --- a/components/payments/content/payment_request_spec.h +++ b/components/payments/content/payment_request_spec.h
@@ -23,8 +23,11 @@ class PaymentInstrument; -// Identifier for the basic card payment method in the PaymentMethodData. +// Identifier for the basic card payment method and google-related payment +// methods in the PaymentMethodData. extern const char kBasicCardMethodName[]; +extern const char kGooglePayMethodName[]; +extern const char kAndroidPayMethodName[]; // The spec contains all the options that the merchant has specified about this // Payment Request. It's a (mostly) read-only view, which can be updated in
diff --git a/components/payments/core/journey_logger.cc b/components/payments/core/journey_logger.cc index 14c89929..1cf94f3 100644 --- a/components/payments/core/journey_logger.cc +++ b/components/payments/core/journey_logger.cc
@@ -136,6 +136,20 @@ SetEventOccurred(EVENT_REQUEST_PAYER_NAME); } +void JourneyLogger::SetRequestedPaymentMethodTypes( + bool requested_basic_card, + bool requested_method_google, + bool requested_method_other) { + if (requested_basic_card) + SetEventOccurred(EVENT_REQUEST_METHOD_BASIC_CARD); + + if (requested_method_google) + SetEventOccurred(EVENT_REQUEST_METHOD_GOOGLE); + + if (requested_method_other) + SetEventOccurred(EVENT_REQUEST_METHOD_OTHER); +} + void JourneyLogger::SetCompleted() { RecordJourneyStatsHistograms(COMPLETION_STATUS_COMPLETED); }
diff --git a/components/payments/core/journey_logger.h b/components/payments/core/journey_logger.h index 6b8104a..779b276 100644 --- a/components/payments/core/journey_logger.h +++ b/components/payments/core/journey_logger.h
@@ -69,23 +69,44 @@ // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.payments // GENERATED_JAVA_CLASS_NAME_OVERRIDE: Event enum Event { + // Initiated means the PaymentRequest object was constructed. EVENT_INITIATED = 0, + // PaymentRequest was triggered via .show() and a native UI was shown. EVENT_SHOWN = 1 << 0, EVENT_PAY_CLICKED = 1 << 1, EVENT_RECEIVED_INSTRUMENT_DETAILS = 1 << 2, + // PaymentRequest was triggered via .show() and no UI was shown because we + // skipped directly to the payment app. EVENT_SKIPPED_SHOW = 1 << 3, + // .complete() was called by the merchant, completing the flow. EVENT_COMPLETED = 1 << 4, + // The user aborted the flow by either dismissing it explicitely, or + // navigating away (if possible). EVENT_USER_ABORTED = 1 << 5, + // Other reasons for aborting include the merchant calling .abort(), the + // merchant triggering a navigation, the tab closing, the browser closing, + // etc. See implementation for details. EVENT_OTHER_ABORTED = 1 << 6, EVENT_HAD_INITIAL_FORM_OF_PAYMENT = 1 << 7, EVENT_HAD_NECESSARY_COMPLETE_SUGGESTIONS = 1 << 8, + // canMakePayment was called with a result of "true" or "false", + // respectively. An absence of both events means canMakePayment was not + // called, or the user was in incognito mode. EVENT_CAN_MAKE_PAYMENT_TRUE = 1 << 9, EVENT_CAN_MAKE_PAYMENT_FALSE = 1 << 10, + // Correspond to the merchant specifying requestShipping, requestPayerName, + // requestPayerEmail, requestPayerPhone. EVENT_REQUEST_SHIPPING = 1 << 11, EVENT_REQUEST_PAYER_NAME = 1 << 12, EVENT_REQUEST_PAYER_EMAIL = 1 << 13, EVENT_REQUEST_PAYER_PHONE = 1 << 14, - EVENT_ENUM_MAX = 32768, + // The merchant requested at least one basic-card method. + EVENT_REQUEST_METHOD_BASIC_CARD = 1 << 15, + // The merchant requested a Google payment method. + EVENT_REQUEST_METHOD_GOOGLE = 1 << 16, + // The merchant requested a non-Google, non-basic-card payment method. + EVENT_REQUEST_METHOD_OTHER = 1 << 17, + EVENT_ENUM_MAX = 262144, }; // The reason why the Payment Request was aborted. @@ -152,6 +173,14 @@ bool requested_phone, bool requested_name); + // Records the requested payment method types. A value should be true if at + // least one payment method in the category (basic-card, google payment method + // or other url-based payment method, respectively) is requested. + // TODO(crbug.com/754811): Add support for non-basic-card, non-URL methods. + void SetRequestedPaymentMethodTypes(bool requested_basic_card, + bool requested_method_google, + bool requested_method_other); + // Records that the Payment Request was completed successfully, and starts the // logging of all the journey metrics. void SetCompleted();
diff --git a/components/payments/core/journey_logger_unittest.cc b/components/payments/core/journey_logger_unittest.cc index acb1e4a..389a2bf7 100644 --- a/components/payments/core/journey_logger_unittest.cc +++ b/components/payments/core/journey_logger_unittest.cc
@@ -338,6 +338,9 @@ logger.SetRequestedInformation( /*requested_shipping=*/false, /*requested_email=*/false, /*requested_phone=*/false, /*requested_name=*/false); + logger.SetRequestedPaymentMethodTypes( + /*requested_basic_card=*/true, /*requested_method_google=*/true, + /*requested_method_other=*/false); // Simulate that the user had suggestions for all the requested sections. logger.SetNumberOfSuggestionsShown(JourneyLogger::SECTION_PAYMENT_METHOD, 1, @@ -364,6 +367,9 @@ EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_NAME); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_PHONE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } // Tests that the completion status metrics based on whether the user had @@ -378,6 +384,9 @@ logger.SetRequestedInformation( /*requested_shipping=*/false, /*requested_email=*/false, /*requested_phone=*/false, /*requested_name=*/false); + logger.SetRequestedPaymentMethodTypes( + /*requested_basic_card=*/true, /*requested_method_google=*/true, + /*requested_method_other=*/false); // Simulate that the user had suggestions for all the requested sections. logger.SetNumberOfSuggestionsShown(JourneyLogger::SECTION_PAYMENT_METHOD, 1, @@ -404,6 +413,9 @@ EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_NAME); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_PHONE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } // Tests that the completion status metrics based on whether the user had @@ -418,6 +430,9 @@ logger.SetRequestedInformation( /*requested_shipping=*/false, /*requested_email=*/false, /*requested_phone=*/false, /*requested_name=*/false); + logger.SetRequestedPaymentMethodTypes( + /*requested_basic_card=*/true, /*requested_method_google=*/true, + /*requested_method_other=*/false); // Simulate that the user had suggestions for all the requested sections. logger.SetNumberOfSuggestionsShown(JourneyLogger::SECTION_PAYMENT_METHOD, 1, @@ -444,6 +459,9 @@ EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_NAME); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_PHONE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } // Tests that the completion status metrics based on whether the user had @@ -459,6 +477,9 @@ logger.SetRequestedInformation( /*requested_shipping=*/false, /*requested_email=*/false, /*requested_phone=*/false, /*requested_name=*/false); + logger.SetRequestedPaymentMethodTypes( + /*requested_basic_card=*/true, /*requested_method_google=*/true, + /*requested_method_other=*/false); // Simulate that the user had suggestions for all the requested sections. logger.SetNumberOfSuggestionsShown(JourneyLogger::SECTION_PAYMENT_METHOD, 1, @@ -485,6 +506,9 @@ EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_NAME); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_PHONE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } // Tests that the completion status metrics based on whether the user had @@ -499,6 +523,9 @@ logger.SetRequestedInformation( /*requested_shipping=*/false, /*requested_email=*/false, /*requested_phone=*/false, /*requested_name=*/false); + logger.SetRequestedPaymentMethodTypes( + /*requested_basic_card=*/true, /*requested_method_google=*/true, + /*requested_method_other=*/false); // Simulate that the user had suggestions for none of the requested sections. logger.SetNumberOfSuggestionsShown(JourneyLogger::SECTION_PAYMENT_METHOD, 0, @@ -525,6 +552,9 @@ EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_NAME); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_PHONE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } // Tests that the completion status metrics based on whether the user had @@ -539,6 +569,9 @@ logger.SetRequestedInformation( /*requested_shipping=*/false, /*requested_email=*/false, /*requested_phone=*/false, /*requested_name=*/false); + logger.SetRequestedPaymentMethodTypes( + /*requested_basic_card=*/true, /*requested_method_google=*/true, + /*requested_method_other=*/false); // Simulate that the user had suggestions for none of the requested sections. logger.SetNumberOfSuggestionsShown(JourneyLogger::SECTION_PAYMENT_METHOD, 0, @@ -565,6 +598,9 @@ EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_NAME); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_PHONE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } // Tests that the completion status metrics based on whether the user had @@ -579,6 +615,9 @@ logger.SetRequestedInformation( /*requested_shipping=*/false, /*requested_email=*/false, /*requested_phone=*/false, /*requested_name=*/false); + logger.SetRequestedPaymentMethodTypes( + /*requested_basic_card=*/true, /*requested_method_google=*/true, + /*requested_method_other=*/false); // Simulate that the user had suggestions for none of the requested sections. logger.SetNumberOfSuggestionsShown(JourneyLogger::SECTION_PAYMENT_METHOD, 0, @@ -605,6 +644,9 @@ EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_NAME); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_PHONE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } // Tests that the completion status metrics based on whether the user had @@ -620,6 +662,9 @@ logger.SetRequestedInformation( /*requested_shipping=*/false, /*requested_email=*/false, /*requested_phone=*/false, /*requested_name=*/false); + logger.SetRequestedPaymentMethodTypes( + /*requested_basic_card=*/true, /*requested_method_google=*/true, + /*requested_method_other=*/false); // Simulate that the user had suggestions for none of the requested sections. logger.SetNumberOfSuggestionsShown(JourneyLogger::SECTION_PAYMENT_METHOD, 0, @@ -646,6 +691,9 @@ EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_NAME); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_PHONE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } // Tests that the completion status metrics based on whether the user had @@ -661,6 +709,9 @@ logger.SetRequestedInformation( /*requested_shipping=*/false, /*requested_email=*/false, /*requested_phone=*/false, /*requested_name=*/false); + logger.SetRequestedPaymentMethodTypes( + /*requested_basic_card=*/true, /*requested_method_google=*/true, + /*requested_method_other=*/false); // Simulate that the user had incomplete suggestions for the requested // sections. @@ -688,6 +739,9 @@ EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_NAME); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_PHONE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } // Tests that the completion status metrics based on whether the user had @@ -703,6 +757,9 @@ logger.SetRequestedInformation( /*requested_shipping=*/true, /*requested_email=*/false, /*requested_phone=*/false, /*requested_name=*/false); + logger.SetRequestedPaymentMethodTypes( + /*requested_basic_card=*/true, /*requested_method_google=*/true, + /*requested_method_other=*/false); // Simulate that the user had incomplete suggestions for one of the requested // sections. @@ -732,6 +789,9 @@ EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_NAME); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_PHONE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } // Tests that the completion status metrics based on whether the user had @@ -747,6 +807,9 @@ logger.SetRequestedInformation( /*requested_shipping=*/true, /*requested_email=*/false, /*requested_phone=*/false, /*requested_name=*/false); + logger.SetRequestedPaymentMethodTypes( + /*requested_basic_card=*/true, /*requested_method_google=*/true, + /*requested_method_other=*/false); // Simulate that the user had incomplete suggestions for one of the requested // sections. @@ -776,6 +839,9 @@ EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_NAME); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_PHONE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } // Tests that the metrics are logged correctly for two simultaneous Payment @@ -792,10 +858,16 @@ logger1.SetRequestedInformation( /*requested_shipping=*/true, /*requested_email=*/true, /*requested_phone=*/false, /*requested_name=*/false); + logger1.SetRequestedPaymentMethodTypes( + /*requested_basic_card=*/true, /*requested_method_google=*/true, + /*requested_method_other=*/true); logger2.SetEventOccurred(JourneyLogger::EVENT_SHOWN); logger2.SetRequestedInformation( /*requested_shipping=*/true, /*requested_email=*/false, /*requested_phone=*/false, /*requested_name=*/false); + logger2.SetRequestedPaymentMethodTypes( + /*requested_basic_card=*/false, /*requested_method_google=*/false, + /*requested_method_other=*/true); logger1.SetCanMakePaymentValue(true); @@ -827,6 +899,9 @@ EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_TRUE); EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_FALSE); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); // logger1 EXPECT_TRUE(buckets[1].min & JourneyLogger::EVENT_SHOWN); EXPECT_FALSE(buckets[1].min & @@ -842,6 +917,9 @@ EXPECT_TRUE(buckets[1].min & JourneyLogger::EVENT_REQUEST_PAYER_EMAIL); EXPECT_TRUE(buckets[1].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_TRUE); EXPECT_FALSE(buckets[1].min & JourneyLogger::EVENT_CAN_MAKE_PAYMENT_FALSE); + EXPECT_TRUE(buckets[1].min & JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD); + EXPECT_TRUE(buckets[1].min & JourneyLogger::EVENT_REQUEST_METHOD_GOOGLE); + EXPECT_TRUE(buckets[1].min & JourneyLogger::EVENT_REQUEST_METHOD_OTHER); } // Tests that the Payment Request UKMs are logged correctly when the user aborts @@ -857,6 +935,9 @@ logger.SetRequestedInformation( /*requested_shipping=*/true, /*requested_email=*/true, /*requested_phone=*/false, /*requested_name=*/false); + logger.SetRequestedPaymentMethodTypes( + /*requested_basic_card=*/true, /*requested_method_google=*/false, + /*requested_method_other=*/false); // Simulate that the user aborts after being shown the Payment Request and // clicking pay. @@ -886,7 +967,8 @@ ASSERT_NE(nullptr, step_metric); EXPECT_EQ(JourneyLogger::EVENT_SHOWN | JourneyLogger::EVENT_PAY_CLICKED | JourneyLogger::EVENT_REQUEST_SHIPPING | - JourneyLogger::EVENT_REQUEST_PAYER_EMAIL, + JourneyLogger::EVENT_REQUEST_PAYER_EMAIL | + JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD, step_metric->value); } @@ -903,6 +985,9 @@ logger.SetRequestedInformation( /*requested_shipping=*/true, /*requested_email=*/true, /*requested_phone=*/false, /*requested_name=*/false); + logger.SetRequestedPaymentMethodTypes( + /*requested_basic_card=*/true, /*requested_method_google=*/false, + /*requested_method_other=*/false); // Simulate that the user aborts after being shown the Payment Request. logger.SetEventOccurred(JourneyLogger::EVENT_SHOWN); @@ -928,7 +1013,8 @@ ukm::TestUkmRecorder::FindMetric(entry, internal::kUKMEventsMetricName); ASSERT_NE(nullptr, step_metric); EXPECT_EQ(JourneyLogger::EVENT_SHOWN | JourneyLogger::EVENT_REQUEST_SHIPPING | - JourneyLogger::EVENT_REQUEST_PAYER_EMAIL, + JourneyLogger::EVENT_REQUEST_PAYER_EMAIL | + JourneyLogger::EVENT_REQUEST_METHOD_BASIC_CARD, step_metric->value); }
diff --git a/components/safe_browsing/BUILD.gn b/components/safe_browsing/BUILD.gn index f09e7c6..41b9f45 100644 --- a/components/safe_browsing/BUILD.gn +++ b/components/safe_browsing/BUILD.gn
@@ -6,7 +6,13 @@ proto_library("csd_proto") { sources = [ - "csd.proto", + "proto/csd.proto", + ] +} + +proto_library("webui_proto") { + sources = [ + "proto/webui.proto", ] }
diff --git a/components/safe_browsing/browser/DEPS b/components/safe_browsing/browser/DEPS index d98a2a4d..b219d834 100644 --- a/components/safe_browsing/browser/DEPS +++ b/components/safe_browsing/browser/DEPS
@@ -1,6 +1,6 @@ include_rules = [ "+components/history/core/browser", - "+components/safe_browsing/csd.pb.h", + "+components/safe_browsing/proto/csd.pb.h", "+content/public/browser", "+ipc/ipc_message.h", "+net/cookies",
diff --git a/components/safe_browsing/browser/threat_details.h b/components/safe_browsing/browser/threat_details.h index 9e6918a..849105c0 100644 --- a/components/safe_browsing/browser/threat_details.h +++ b/components/safe_browsing/browser/threat_details.h
@@ -21,7 +21,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "components/safe_browsing/common/safebrowsing_types.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "components/security_interstitials/content/unsafe_resource.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/web_contents_observer.h"
diff --git a/components/safe_browsing/password_protection/password_protection_service.h b/components/safe_browsing/password_protection/password_protection_service.h index 802fbff..f6ef8d41 100644 --- a/components/safe_browsing/password_protection/password_protection_service.h +++ b/components/safe_browsing/password_protection/password_protection_service.h
@@ -18,7 +18,7 @@ #include "base/task/cancelable_task_tracker.h" #include "base/values.h" #include "components/history/core/browser/history_service_observer.h" -#include "components/safe_browsing/csd.pb.h" +#include "components/safe_browsing/proto/csd.pb.h" #include "components/safe_browsing_db/v4_protocol_manager_util.h" #include "net/url_request/url_request_context_getter.h" #include "third_party/protobuf/src/google/protobuf/repeated_field.h"
diff --git a/components/safe_browsing/csd.proto b/components/safe_browsing/proto/csd.proto similarity index 100% rename from components/safe_browsing/csd.proto rename to components/safe_browsing/proto/csd.proto
diff --git a/components/safe_browsing/web_ui/webui.proto b/components/safe_browsing/proto/webui.proto similarity index 100% rename from components/safe_browsing/web_ui/webui.proto rename to components/safe_browsing/proto/webui.proto
diff --git a/components/safe_browsing/web_ui/BUILD.gn b/components/safe_browsing/web_ui/BUILD.gn index 707f14b6..7bd2a139 100644 --- a/components/safe_browsing/web_ui/BUILD.gn +++ b/components/safe_browsing/web_ui/BUILD.gn
@@ -12,11 +12,11 @@ deps = [ ":constants", - ":webui_proto", "//base", "//components/resources:components_resources_grit", "//components/resources:components_scaled_resources_grit", "//components/safe_browsing:features", + "//components/safe_browsing:webui_proto", "//components/safe_browsing/common:safe_browsing_prefs", "//components/safe_browsing_db:v4_local_database_manager", "//components/strings:components_strings_grit", @@ -33,9 +33,3 @@ "constants.h", ] } - -proto_library("webui_proto") { - sources = [ - "webui.proto", - ] -}
diff --git a/components/safe_browsing/web_ui/safe_browsing_ui.h b/components/safe_browsing/web_ui/safe_browsing_ui.h index 89abc3a..54fef1e 100644 --- a/components/safe_browsing/web_ui/safe_browsing_ui.h +++ b/components/safe_browsing/web_ui/safe_browsing_ui.h
@@ -6,7 +6,7 @@ #define COMPONENTS_SAFE_BROWSING_WEBUI_SAFE_BROWSING_UI_H_ #include "base/macros.h" -#include "components/safe_browsing/web_ui/webui.pb.h" +#include "components/safe_browsing/proto/webui.pb.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui_controller.h" #include "content/public/browser/web_ui_data_source.h"
diff --git a/components/safe_browsing_db/BUILD.gn b/components/safe_browsing_db/BUILD.gn index bedfc8e..f4ac984 100644 --- a/components/safe_browsing_db/BUILD.gn +++ b/components/safe_browsing_db/BUILD.gn
@@ -204,7 +204,7 @@ ":v4_protocol_manager_util", ":v4_store", "//base", - "//components/safe_browsing/web_ui:webui_proto", + "//components/safe_browsing:webui_proto", "//content/public/browser", ] } @@ -233,7 +233,7 @@ ":v4_protocol_manager_util", "//base", "//components/data_use_measurement/core", - "//components/safe_browsing/web_ui:webui_proto", + "//components/safe_browsing:webui_proto", "//content/public/browser", "//net", "//url", @@ -255,7 +255,7 @@ ":v4_protocol_manager_util", ":v4_update_protocol_manager", "//base", - "//components/safe_browsing/web_ui:webui_proto", + "//components/safe_browsing:webui_proto", "//content/public/browser", "//net", "//url", @@ -310,7 +310,7 @@ ":v4_protocol_manager_util", ":v4_rice", "//base", - "//components/safe_browsing/web_ui:webui_proto", + "//components/safe_browsing:webui_proto", "//crypto", ] } @@ -338,8 +338,8 @@ ":v4_protocol_manager_util", "//base", "//components/data_use_measurement/core", + "//components/safe_browsing:webui_proto", "//components/safe_browsing/common:safe_browsing_prefs", - "//components/safe_browsing/web_ui:webui_proto", "//net", "//url", ]
diff --git a/components/safe_browsing_db/DEPS b/components/safe_browsing_db/DEPS index 1c63417..c5e7e01 100644 --- a/components/safe_browsing_db/DEPS +++ b/components/safe_browsing_db/DEPS
@@ -2,7 +2,7 @@ "+components/data_use_measurement/core", "+components/safe_browsing/common/safe_browsing_prefs.h", "+components/safe_browsing/features.h", - "+components/safe_browsing/web_ui/webui.pb.h", + "+components/safe_browsing/proto/webui.pb.h", "+components/variations", "+components/version_info", "+content/public/browser",
diff --git a/components/safe_browsing_db/v4_database.cc b/components/safe_browsing_db/v4_database.cc index 9e8a74f0..f380624 100644 --- a/components/safe_browsing_db/v4_database.cc +++ b/components/safe_browsing_db/v4_database.cc
@@ -11,7 +11,7 @@ #include "base/metrics/histogram_macros.h" #include "base/task_runner_util.h" #include "base/threading/thread_task_runner_handle.h" -#include "components/safe_browsing/web_ui/webui.pb.h" +#include "components/safe_browsing/proto/webui.pb.h" #include "components/safe_browsing_db/v4_database.h" #include "content/public/browser/browser_thread.h"
diff --git a/components/safe_browsing_db/v4_database.h b/components/safe_browsing_db/v4_database.h index 576e894..aea51b0 100644 --- a/components/safe_browsing_db/v4_database.h +++ b/components/safe_browsing_db/v4_database.h
@@ -16,7 +16,7 @@ #include "base/memory/weak_ptr.h" #include "base/sequenced_task_runner.h" #include "base/single_thread_task_runner.h" -#include "components/safe_browsing/web_ui/webui.pb.h" +#include "components/safe_browsing/proto/webui.pb.h" #include "components/safe_browsing_db/v4_protocol_manager_util.h" #include "components/safe_browsing_db/v4_store.h"
diff --git a/components/safe_browsing_db/v4_get_hash_protocol_manager.h b/components/safe_browsing_db/v4_get_hash_protocol_manager.h index 6ae5c302..22510c9c 100644 --- a/components/safe_browsing_db/v4_get_hash_protocol_manager.h +++ b/components/safe_browsing_db/v4_get_hash_protocol_manager.h
@@ -24,7 +24,7 @@ #include "base/time/default_clock.h" #include "base/time/time.h" #include "base/timer/timer.h" -#include "components/safe_browsing/web_ui/webui.pb.h" +#include "components/safe_browsing/proto/webui.pb.h" #include "components/safe_browsing_db/safebrowsing.pb.h" #include "components/safe_browsing_db/util.h" #include "components/safe_browsing_db/v4_protocol_manager_util.h"
diff --git a/components/safe_browsing_db/v4_local_database_manager.h b/components/safe_browsing_db/v4_local_database_manager.h index 29d7544..c2cd94f4 100644 --- a/components/safe_browsing_db/v4_local_database_manager.h +++ b/components/safe_browsing_db/v4_local_database_manager.h
@@ -12,7 +12,7 @@ #include <unordered_set> #include "base/memory/weak_ptr.h" -#include "components/safe_browsing/web_ui/webui.pb.h" +#include "components/safe_browsing/proto/webui.pb.h" #include "components/safe_browsing_db/database_manager.h" #include "components/safe_browsing_db/hit_report.h" #include "components/safe_browsing_db/v4_database.h"
diff --git a/components/safe_browsing_db/v4_store.cc b/components/safe_browsing_db/v4_store.cc index e7bce82..2d51d61c 100644 --- a/components/safe_browsing_db/v4_store.cc +++ b/components/safe_browsing_db/v4_store.cc
@@ -12,7 +12,7 @@ #include "base/metrics/sparse_histogram.h" #include "base/stl_util.h" #include "base/strings/stringprintf.h" -#include "components/safe_browsing/web_ui/webui.pb.h" +#include "components/safe_browsing/proto/webui.pb.h" #include "components/safe_browsing_db/v4_rice.h" #include "components/safe_browsing_db/v4_store.pb.h" #include "crypto/secure_hash.h"
diff --git a/components/safe_browsing_db/v4_store.h b/components/safe_browsing_db/v4_store.h index 3ebd47a..392d841c 100644 --- a/components/safe_browsing_db/v4_store.h +++ b/components/safe_browsing_db/v4_store.h
@@ -13,7 +13,7 @@ #include "base/memory/ref_counted.h" #include "base/sequenced_task_runner.h" #include "base/single_thread_task_runner.h" -#include "components/safe_browsing/web_ui/webui.pb.h" +#include "components/safe_browsing/proto/webui.pb.h" #include "components/safe_browsing_db/v4_protocol_manager_util.h" namespace safe_browsing {
diff --git a/components/safe_browsing_db/v4_update_protocol_manager.h b/components/safe_browsing_db/v4_update_protocol_manager.h index db01b070..73f076f6 100644 --- a/components/safe_browsing_db/v4_update_protocol_manager.h +++ b/components/safe_browsing_db/v4_update_protocol_manager.h
@@ -22,7 +22,7 @@ #include "base/time/time.h" #include "base/timer/timer.h" #include "components/safe_browsing/common/safe_browsing_prefs.h" -#include "components/safe_browsing/web_ui/webui.pb.h" +#include "components/safe_browsing/proto/webui.pb.h" #include "components/safe_browsing_db/safebrowsing.pb.h" #include "components/safe_browsing_db/util.h" #include "components/safe_browsing_db/v4_protocol_manager_util.h"
diff --git a/components/security_state/content/content_utils.cc b/components/security_state/content/content_utils.cc index 37dee4f..c532fc1 100644 --- a/components/security_state/content/content_utils.cc +++ b/components/security_state/content/content_utils.cc
@@ -99,7 +99,7 @@ content::SecurityStyleExplanation( l10n_util::GetStringUTF8(IDS_SHA1), l10n_util::GetStringUTF8(IDS_SHA1_DESCRIPTION), - !!security_info.certificate, + security_info.certificate, blink::WebMixedContentContextType::kNotMixedContent)); } @@ -108,7 +108,7 @@ content::SecurityStyleExplanation( l10n_util::GetStringUTF8(IDS_SUBJECT_ALT_NAME_MISSING), l10n_util::GetStringUTF8(IDS_SUBJECT_ALT_NAME_MISSING_DESCRIPTION), - !!security_info.certificate, + security_info.certificate, blink::WebMixedContentContextType::kNotMixedContent)); } @@ -124,7 +124,7 @@ l10n_util::GetStringUTF8(IDS_CERTIFICATE_CHAIN_ERROR), l10n_util::GetStringFUTF8( IDS_CERTIFICATE_CHAIN_ERROR_DESCRIPTION_FORMAT, error_string), - !!security_info.certificate, + security_info.certificate, blink::WebMixedContentContextType::kNotMixedContent); if (is_cert_status_minor_error) { @@ -155,7 +155,7 @@ l10n_util::GetStringUTF8(IDS_VALID_SERVER_CERTIFICATE), l10n_util::GetStringFUTF8( IDS_VALID_SERVER_CERTIFICATE_DESCRIPTION, issuer_name), - !!security_info.certificate, + security_info.certificate, blink::WebMixedContentContextType::kNotMixedContent)); } } @@ -275,7 +275,7 @@ content::SecurityStyleExplanation( l10n_util::GetStringUTF8(IDS_MIXED_ACTIVE_CONTENT_SUMMARY), l10n_util::GetStringUTF8(IDS_MIXED_ACTIVE_CONTENT_DESCRIPTION), - false, blink::WebMixedContentContextType::kBlockable)); + nullptr, blink::WebMixedContentContextType::kBlockable)); } security_style_explanations->displayed_mixed_content = @@ -289,7 +289,7 @@ content::SecurityStyleExplanation( l10n_util::GetStringUTF8(IDS_MIXED_PASSIVE_CONTENT_SUMMARY), l10n_util::GetStringUTF8(IDS_MIXED_PASSIVE_CONTENT_DESCRIPTION), - false, blink::WebMixedContentContextType::kOptionallyBlockable)); + nullptr, blink::WebMixedContentContextType::kOptionallyBlockable)); } security_style_explanations->contained_mixed_form =
diff --git a/components/security_state/content/content_utils_unittest.cc b/components/security_state/content/content_utils_unittest.cc index e2615b32..d4e30e83 100644 --- a/components/security_state/content/content_utils_unittest.cc +++ b/components/security_state/content/content_utils_unittest.cc
@@ -580,7 +580,7 @@ TEST(SecurityStateContentUtilsTest, DefaultSecurityStyleExplanation) { content::SecurityStyleExplanation explanation("summary", "description"); - EXPECT_EQ(false, explanation.has_certificate); + EXPECT_EQ(false, !!explanation.certificate); EXPECT_EQ(blink::WebMixedContentContextType::kNotMixedContent, explanation.mixed_content_type); }
diff --git a/components/security_state/core/security_state.h b/components/security_state/core/security_state.h index 2a77332..9f4e4fb 100644 --- a/components/security_state/core/security_state.h +++ b/components/security_state/core/security_state.h
@@ -32,8 +32,8 @@ // Describes the overall security state of the page. // -// If you reorder, add, or delete values from this enum, you must also -// update the UI icons in ToolbarModelImpl::GetIconForSecurityLevel. +// If you change this enum, you may need to update the UI icons in +// ToolbarModelImpl::GetVectorIcon and GetIconForSecurityState. // // A Java counterpart will be generated for this enum. // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.security_state @@ -56,7 +56,7 @@ // HTTPS (non-EV) with valid cert. SECURE, - // HTTPS, but with an outdated protocol version. + // Obsolete, do not use. TODO(lgarron): Remove via https://crbug.com/645698. SECURITY_WARNING, // HTTPS, but the certificate verification chain is anchored on a
diff --git a/components/viz/client/client_shared_bitmap_manager.cc b/components/viz/client/client_shared_bitmap_manager.cc index 8c1d51a..63b30e7 100644 --- a/components/viz/client/client_shared_bitmap_manager.cc +++ b/components/viz/client/client_shared_bitmap_manager.cc
@@ -24,7 +24,7 @@ class ClientSharedBitmap : public SharedBitmap { public: ClientSharedBitmap( - scoped_refptr<cc::mojom::ThreadSafeSharedBitmapAllocationNotifierPtr> + scoped_refptr<mojom::ThreadSafeSharedBitmapAllocationNotifierPtr> shared_bitmap_allocation_notifier, base::SharedMemory* shared_memory, const SharedBitmapId& id, @@ -36,7 +36,7 @@ std::move(shared_bitmap_allocation_notifier)) {} ClientSharedBitmap( - scoped_refptr<cc::mojom::ThreadSafeSharedBitmapAllocationNotifierPtr> + scoped_refptr<mojom::ThreadSafeSharedBitmapAllocationNotifierPtr> shared_bitmap_allocation_notifier, std::unique_ptr<base::SharedMemory> shared_memory_holder, const SharedBitmapId& id, @@ -60,7 +60,7 @@ } private: - scoped_refptr<cc::mojom::ThreadSafeSharedBitmapAllocationNotifierPtr> + scoped_refptr<mojom::ThreadSafeSharedBitmapAllocationNotifierPtr> shared_bitmap_allocation_notifier_; std::unique_ptr<base::SharedMemory> shared_memory_holder_; }; @@ -112,7 +112,7 @@ } // namespace ClientSharedBitmapManager::ClientSharedBitmapManager( - scoped_refptr<cc::mojom::ThreadSafeSharedBitmapAllocationNotifierPtr> + scoped_refptr<mojom::ThreadSafeSharedBitmapAllocationNotifierPtr> shared_bitmap_allocation_notifier) : shared_bitmap_allocation_notifier_( std::move(shared_bitmap_allocation_notifier)) {}
diff --git a/components/viz/client/client_shared_bitmap_manager.h b/components/viz/client/client_shared_bitmap_manager.h index 8bb479c..553bb57 100644 --- a/components/viz/client/client_shared_bitmap_manager.h +++ b/components/viz/client/client_shared_bitmap_manager.h
@@ -13,9 +13,9 @@ #include "base/memory/ref_counted.h" #include "base/memory/shared_memory.h" #include "base/synchronization/lock.h" -#include "cc/ipc/shared_bitmap_allocation_notifier.mojom.h" #include "components/viz/common/resources/shared_bitmap_manager.h" #include "mojo/public/cpp/bindings/thread_safe_interface_ptr.h" +#include "services/viz/public/interfaces/compositing/shared_bitmap_allocation_notifier.mojom.h" namespace viz { @@ -25,7 +25,7 @@ class ClientSharedBitmapManager : public SharedBitmapManager { public: explicit ClientSharedBitmapManager( - scoped_refptr<cc::mojom::ThreadSafeSharedBitmapAllocationNotifierPtr> + scoped_refptr<mojom::ThreadSafeSharedBitmapAllocationNotifierPtr> shared_bitmap_allocation_notifier); ~ClientSharedBitmapManager() override; @@ -43,7 +43,7 @@ uint32_t NotifyAllocatedSharedBitmap(base::SharedMemory* memory, const SharedBitmapId& id); - scoped_refptr<cc::mojom::ThreadSafeSharedBitmapAllocationNotifierPtr> + scoped_refptr<mojom::ThreadSafeSharedBitmapAllocationNotifierPtr> shared_bitmap_allocation_notifier_; base::Lock lock_;
diff --git a/components/viz/host/BUILD.gn b/components/viz/host/BUILD.gn index 092768f..be3dc76 100644 --- a/components/viz/host/BUILD.gn +++ b/components/viz/host/BUILD.gn
@@ -8,6 +8,8 @@ defines = [ "VIZ_HOST_IMPLEMENTATION" ] sources = [ + "hit_test/hit_test_query.cc", + "hit_test/hit_test_query.h", "host_frame_sink_client.h", "host_frame_sink_manager.cc", "host_frame_sink_manager.h", @@ -21,6 +23,7 @@ deps = [ "//base", "//cc/ipc:interfaces", + "//components/viz/common", "//gpu/ipc/client", "//gpu/ipc/common", "//services/ui/gpu/interfaces", @@ -36,6 +39,8 @@ "//gpu/command_buffer/client", "//gpu/ipc/host", "//services/viz/compositing/privileged/interfaces", + "//services/viz/public/interfaces/hit_test", + "//ui/gfx/geometry", ] } @@ -43,6 +48,7 @@ testonly = true sources = [ + "hit_test/hit_test_query_unittest.cc", "host_frame_sink_manager_unittests.cc", "server_gpu_memory_buffer_manager_unittest.cc", ] @@ -52,7 +58,6 @@ "//base", "//base/test:test_support", "//cc/ipc:interfaces", - "//components/viz/host/hit_test:unit_tests", "//gpu/ipc/host", "//mojo/public/cpp/bindings", "//services/ui/gpu/interfaces",
diff --git a/components/viz/host/hit_test/BUILD.gn b/components/viz/host/hit_test/BUILD.gn deleted file mode 100644 index aa16214..0000000 --- a/components/viz/host/hit_test/BUILD.gn +++ /dev/null
@@ -1,36 +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. - -import("//components/viz/viz.gni") -import("//testing/test.gni") - -viz_source_set("hit_test") { - sources = [ - "hit_test_query.cc", - "hit_test_query.h", - ] - - public_deps = [ - "//components/viz/common", - "//services/viz/public/interfaces/hit_test", - "//ui/gfx", - "//ui/gfx/geometry", - ] -} - -viz_source_set("unit_tests") { - testonly = true - - sources = [ - "hit_test_query_unittest.cc", - ] - - deps = [ - ":hit_test", - "//base", - "//base/test:test_support", - "//cc:test_support", - "//testing/gtest", - ] -}
diff --git a/components/viz/host/hit_test/hit_test_query.h b/components/viz/host/hit_test/hit_test_query.h index 31221bf..a99f745 100644 --- a/components/viz/host/hit_test/hit_test_query.h +++ b/components/viz/host/hit_test/hit_test_query.h
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "components/viz/common/hit_test/aggregated_hit_test_region.h" +#include "components/viz/host/viz_host_export.h" #include "mojo/public/cpp/system/buffer.h" #include "ui/gfx/geometry/point.h" @@ -26,7 +27,7 @@ // Finds the target for a given location based on the AggregatedHitTestRegion // list aggregated by HitTestAggregator. // TODO(riajiang): Handle 3d space cases correctly. -class HitTestQuery { +class VIZ_HOST_EXPORT HitTestQuery { public: HitTestQuery(); ~HitTestQuery();
diff --git a/components/viz/service/DEPS b/components/viz/service/DEPS index a29ec613..d840a11 100644 --- a/components/viz/service/DEPS +++ b/components/viz/service/DEPS
@@ -2,6 +2,7 @@ "+cc", "-components/viz/common/switches.h", "+components/viz/service", + "+services/viz/public/interfaces", "+third_party/skia", "+ui/gfx", "+ui/gfx/geometry", @@ -12,6 +13,5 @@ ".*_unittest\.cc": [ "+components/viz/test", "+services/compositing/privileged/interfaces", - "+services/viz/public/interfaces/compositing", ] }
diff --git a/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.cc b/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.cc index d320a3d..bc81f59 100644 --- a/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.cc +++ b/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.cc
@@ -21,7 +21,7 @@ } void SharedBitmapAllocationNotifierImpl::Bind( - cc::mojom::SharedBitmapAllocationNotifierRequest request) { + mojom::SharedBitmapAllocationNotifierRequest request) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (binding_.is_bound()) { DLOG(ERROR) << "Only one SharedBitmapAllocationNotifierRequest is "
diff --git a/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h b/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h index 4e9330a..080fece 100644 --- a/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h +++ b/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h
@@ -9,10 +9,10 @@ #include "base/observer_list.h" #include "base/threading/thread_checker.h" -#include "cc/ipc/shared_bitmap_allocation_notifier.mojom.h" #include "components/viz/common/quads/shared_bitmap.h" #include "components/viz/service/viz_service_export.h" #include "mojo/public/cpp/bindings/binding.h" +#include "services/viz/public/interfaces/compositing/shared_bitmap_allocation_notifier.mojom.h" namespace viz { class ServerSharedBitmapManager; @@ -23,7 +23,7 @@ }; class VIZ_SERVICE_EXPORT SharedBitmapAllocationNotifierImpl - : NON_EXPORTED_BASE(public cc::mojom::SharedBitmapAllocationNotifier) { + : NON_EXPORTED_BASE(public mojom::SharedBitmapAllocationNotifier) { public: explicit SharedBitmapAllocationNotifierImpl( ServerSharedBitmapManager* manager); @@ -33,9 +33,9 @@ void AddObserver(SharedBitmapAllocationObserver* observer); void RemoveObserver(SharedBitmapAllocationObserver* observer); - void Bind(cc::mojom::SharedBitmapAllocationNotifierRequest request); + void Bind(mojom::SharedBitmapAllocationNotifierRequest request); - // cc::mojom::SharedBitmapAllocationNotifier overrides: + // mojom::SharedBitmapAllocationNotifier overrides: void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, const SharedBitmapId& id) override; void DidDeleteSharedBitmap(const SharedBitmapId& id) override; @@ -51,7 +51,7 @@ private: THREAD_CHECKER(thread_checker_); ServerSharedBitmapManager* const manager_; - mojo::Binding<cc::mojom::SharedBitmapAllocationNotifier> binding_; + mojo::Binding<mojom::SharedBitmapAllocationNotifier> binding_; std::unordered_set<SharedBitmapId, SharedBitmapIdHash> owned_bitmaps_; base::ObserverList<SharedBitmapAllocationObserver> observers_; uint32_t last_sequence_number_ = 0;
diff --git a/components/viz/service/frame_sinks/DEPS b/components/viz/service/frame_sinks/DEPS index 0216da50..d878155 100644 --- a/components/viz/service/frame_sinks/DEPS +++ b/components/viz/service/frame_sinks/DEPS
@@ -6,5 +6,4 @@ "+gpu/ipc/common", "+mojo/public/cpp/bindings", "+services/viz/compositing/privileged/interfaces", - "+services/viz/public/interfaces/compositing", ]
diff --git a/components/viz/service/hit_test/DEPS b/components/viz/service/hit_test/DEPS index 37540ce..38ff3f7 100644 --- a/components/viz/service/hit_test/DEPS +++ b/components/viz/service/hit_test/DEPS
@@ -1,6 +1,5 @@ include_rules = [ "+components/viz/service/surfaces", - "+services/viz/public/interfaces/hit_test", ] specific_include_rules = {
diff --git a/components/viz/service/hit_test/hit_test_aggregator.cc b/components/viz/service/hit_test/hit_test_aggregator.cc index 301a38e..4b07ea15 100644 --- a/components/viz/service/hit_test/hit_test_aggregator.cc +++ b/components/viz/service/hit_test/hit_test_aggregator.cc
@@ -47,15 +47,16 @@ HitTestAggregator::~HitTestAggregator() = default; void HitTestAggregator::SubmitHitTestRegionList( + const SurfaceId& frame_sink_id, mojom::HitTestRegionListPtr hit_test_region_list) { DCHECK(ValidateHitTestRegionList(hit_test_region_list)); // TODO(gklassen): Runtime validation that hit_test_region_list is valid. // TODO(gklassen): Inform FrameSink that the hit_test_region_list is invalid. // TODO(gklassen): FrameSink needs to inform the host of a difficult renderer. - pending_[hit_test_region_list->surface_id] = std::move(hit_test_region_list); + pending_[frame_sink_id] = std::move(hit_test_region_list); } -void HitTestAggregator::PostTaskAggregate(SurfaceId display_surface_id) { +void HitTestAggregator::PostTaskAggregate(const SurfaceId& display_surface_id) { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&HitTestAggregator::Aggregate, @@ -170,7 +171,7 @@ AggregatedHitTestRegion* regions = static_cast<AggregatedHitTestRegion*>(write_buffer_.get()); - regions[0].frame_sink_id = hit_test_region_list->surface_id.frame_sink_id(); + regions[0].frame_sink_id = surface_id.frame_sink_id(); regions[0].flags = hit_test_region_list->flags; regions[0].rect = hit_test_region_list->bounds; regions[0].transform = hit_test_region_list->transform;
diff --git a/components/viz/service/hit_test/hit_test_aggregator.h b/components/viz/service/hit_test/hit_test_aggregator.h index 787d4a7..9d08d05 100644 --- a/components/viz/service/hit_test/hit_test_aggregator.h +++ b/components/viz/service/hit_test/hit_test_aggregator.h
@@ -30,11 +30,12 @@ // to SubmitCompositorFrame. This is collected in pending_ until // surfaces are aggregated and put on the display. void SubmitHitTestRegionList( + const SurfaceId& surface_id, mojom::HitTestRegionListPtr hit_test_region_list); // Performs the work of Aggregate by creating a PostTask so that // the work is not directly on the call. - void PostTaskAggregate(SurfaceId display_surface_id); + void PostTaskAggregate(const SurfaceId& display_surface_id); // Called after surfaces have been aggregated into the DisplayFrame. // In this call HitTestRegionList structures received from active surfaces
diff --git a/components/viz/service/hit_test/hit_test_aggregator_unittest.cc b/components/viz/service/hit_test/hit_test_aggregator_unittest.cc index 002d50c7..c52abcb 100644 --- a/components/viz/service/hit_test/hit_test_aggregator_unittest.cc +++ b/components/viz/service/hit_test/hit_test_aggregator_unittest.cc
@@ -232,7 +232,6 @@ id++; auto hit_test_region_list = mojom::HitTestRegionList::New(); - hit_test_region_list->surface_id = surface_id; hit_test_region_list->flags = mojom::kHitTestMine; hit_test_region_list->bounds.SetRect(0, 0, 1024, 768); @@ -251,7 +250,7 @@ } GetAggregator(kDisplayFrameSink) - ->SubmitHitTestRegionList(std::move(hit_test_region_list)); + ->SubmitHitTestRegionList(surface_id, std::move(hit_test_region_list)); return id; } @@ -296,11 +295,11 @@ SurfaceId display_surface_id = MakeSurfaceId(kDisplayFrameSink, 1); auto hit_test_region_list = mojom::HitTestRegionList::New(); - hit_test_region_list->surface_id = display_surface_id; hit_test_region_list->flags = mojom::kHitTestMine; hit_test_region_list->bounds.SetRect(0, 0, 1024, 768); - aggregator->SubmitHitTestRegionList(std::move(hit_test_region_list)); + aggregator->SubmitHitTestRegionList(display_surface_id, + std::move(hit_test_region_list)); EXPECT_EQ(aggregator->Count(), 0); EXPECT_EQ(aggregator->GetPendingCount(), 1); @@ -345,10 +344,9 @@ SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1); - auto e_hit_test_data = mojom::HitTestRegionList::New(); - e_hit_test_data->surface_id = e_surface_id; - e_hit_test_data->flags = mojom::kHitTestMine; - e_hit_test_data->bounds.SetRect(0, 0, 1024, 768); + auto e_hit_test_region_list = mojom::HitTestRegionList::New(); + e_hit_test_region_list->flags = mojom::kHitTestMine; + e_hit_test_region_list->bounds.SetRect(0, 0, 1024, 768); auto e_hit_test_region_r1 = mojom::HitTestRegion::New(); e_hit_test_region_r1->surface_id = e_surface_id; @@ -360,14 +358,15 @@ e_hit_test_region_r2->flags = mojom::kHitTestMine; e_hit_test_region_r2->rect.SetRect(400, 100, 300, 400); - e_hit_test_data->regions.push_back(std::move(e_hit_test_region_r1)); - e_hit_test_data->regions.push_back(std::move(e_hit_test_region_r2)); + e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_r1)); + e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_r2)); // Submit mojom::HitTestRegionList. EXPECT_EQ(aggregator->GetPendingCount(), 0); - aggregator->SubmitHitTestRegionList(std::move(e_hit_test_data)); + aggregator->SubmitHitTestRegionList(e_surface_id, + std::move(e_hit_test_region_list)); EXPECT_EQ(aggregator->GetPendingCount(), 1); // Add Surfaces to DisplayFrame in unexpected order. @@ -427,10 +426,9 @@ SurfaceId c1_surface_id = MakeSurfaceId(kDisplayFrameSink, 2); SurfaceId c2_surface_id = MakeSurfaceId(kDisplayFrameSink, 3); - auto e_hit_test_data = mojom::HitTestRegionList::New(); - e_hit_test_data->surface_id = e_surface_id; - e_hit_test_data->flags = mojom::kHitTestMine; - e_hit_test_data->bounds.SetRect(0, 0, 1024, 768); + auto e_hit_test_region_list = mojom::HitTestRegionList::New(); + e_hit_test_region_list->flags = mojom::kHitTestMine; + e_hit_test_region_list->bounds.SetRect(0, 0, 1024, 768); auto e_hit_test_region_c1 = mojom::HitTestRegion::New(); e_hit_test_region_c1->flags = mojom::kHitTestChildSurface; @@ -442,26 +440,27 @@ e_hit_test_region_c2->surface_id = c2_surface_id; e_hit_test_region_c2->rect.SetRect(400, 100, 400, 300); - e_hit_test_data->regions.push_back(std::move(e_hit_test_region_c1)); - e_hit_test_data->regions.push_back(std::move(e_hit_test_region_c2)); + e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_c1)); + e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_c2)); - auto c1_hit_test_data = mojom::HitTestRegionList::New(); - c1_hit_test_data->surface_id = c1_surface_id; + auto c1_hit_test_region_list = mojom::HitTestRegionList::New(); - auto c2_hit_test_data = mojom::HitTestRegionList::New(); - c2_hit_test_data->surface_id = c2_surface_id; + auto c2_hit_test_region_list = mojom::HitTestRegionList::New(); // Submit in unexpected order. EXPECT_EQ(aggregator->GetPendingCount(), 0); - aggregator->SubmitHitTestRegionList(std::move(c1_hit_test_data)); + aggregator->SubmitHitTestRegionList(c1_surface_id, + std::move(c1_hit_test_region_list)); EXPECT_EQ(aggregator->GetPendingCount(), 1); - aggregator->SubmitHitTestRegionList(std::move(e_hit_test_data)); + aggregator->SubmitHitTestRegionList(e_surface_id, + std::move(e_hit_test_region_list)); EXPECT_EQ(aggregator->GetPendingCount(), 2); - aggregator->SubmitHitTestRegionList(std::move(c2_hit_test_data)); + aggregator->SubmitHitTestRegionList(c2_surface_id, + std::move(c2_hit_test_region_list)); EXPECT_EQ(aggregator->GetPendingCount(), 3); // Surfaces added to DisplayFrame in unexpected order. @@ -531,10 +530,9 @@ SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1); SurfaceId c_surface_id = MakeSurfaceId(kDisplayFrameSink, 2); - auto e_hit_test_data = mojom::HitTestRegionList::New(); - e_hit_test_data->surface_id = e_surface_id; - e_hit_test_data->flags = mojom::kHitTestMine; - e_hit_test_data->bounds.SetRect(0, 0, 1024, 768); + auto e_hit_test_region_list = mojom::HitTestRegionList::New(); + e_hit_test_region_list->flags = mojom::kHitTestMine; + e_hit_test_region_list->bounds.SetRect(0, 0, 1024, 768); auto e_hit_test_region_div = mojom::HitTestRegion::New(); e_hit_test_region_div->flags = mojom::kHitTestMine; @@ -546,22 +544,23 @@ e_hit_test_region_c->surface_id = c_surface_id; e_hit_test_region_c->rect.SetRect(100, 100, 200, 500); - e_hit_test_data->regions.push_back(std::move(e_hit_test_region_div)); - e_hit_test_data->regions.push_back(std::move(e_hit_test_region_c)); + e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_div)); + e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_c)); - auto c_hit_test_data = mojom::HitTestRegionList::New(); - c_hit_test_data->surface_id = c_surface_id; - c_hit_test_data->flags = mojom::kHitTestMine; - c_hit_test_data->bounds.SetRect(0, 0, 200, 500); + auto c_hit_test_region_list = mojom::HitTestRegionList::New(); + c_hit_test_region_list->flags = mojom::kHitTestMine; + c_hit_test_region_list->bounds.SetRect(0, 0, 200, 500); // Submit in unexpected order. EXPECT_EQ(aggregator->GetPendingCount(), 0); - aggregator->SubmitHitTestRegionList(std::move(c_hit_test_data)); + aggregator->SubmitHitTestRegionList(c_surface_id, + std::move(c_hit_test_region_list)); EXPECT_EQ(aggregator->GetPendingCount(), 1); - aggregator->SubmitHitTestRegionList(std::move(e_hit_test_data)); + aggregator->SubmitHitTestRegionList(e_surface_id, + std::move(e_hit_test_region_list)); EXPECT_EQ(aggregator->GetPendingCount(), 2); // Surfaces added to DisplayFrame in unexpected order. @@ -629,10 +628,9 @@ SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1); SurfaceId c_surface_id = MakeSurfaceId(kDisplayFrameSink, 2); - auto e_hit_test_data = mojom::HitTestRegionList::New(); - e_hit_test_data->surface_id = e_surface_id; - e_hit_test_data->flags = mojom::kHitTestMine; - e_hit_test_data->bounds.SetRect(0, 0, 1024, 768); + auto e_hit_test_region_list = mojom::HitTestRegionList::New(); + e_hit_test_region_list->flags = mojom::kHitTestMine; + e_hit_test_region_list->bounds.SetRect(0, 0, 1024, 768); auto e_hit_test_region_div = mojom::HitTestRegion::New(); e_hit_test_region_div->flags = mojom::kHitTestMine; @@ -644,22 +642,23 @@ e_hit_test_region_c->surface_id = c_surface_id; e_hit_test_region_c->rect.SetRect(100, 100, 200, 500); - e_hit_test_data->regions.push_back(std::move(e_hit_test_region_c)); - e_hit_test_data->regions.push_back(std::move(e_hit_test_region_div)); + e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_c)); + e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_div)); - auto c_hit_test_data = mojom::HitTestRegionList::New(); - c_hit_test_data->surface_id = c_surface_id; - c_hit_test_data->flags = mojom::kHitTestMine; - c_hit_test_data->bounds.SetRect(0, 0, 200, 500); + auto c_hit_test_region_list = mojom::HitTestRegionList::New(); + c_hit_test_region_list->flags = mojom::kHitTestMine; + c_hit_test_region_list->bounds.SetRect(0, 0, 200, 500); // Submit in unexpected order. EXPECT_EQ(aggregator->GetPendingCount(), 0); - aggregator->SubmitHitTestRegionList(std::move(c_hit_test_data)); + aggregator->SubmitHitTestRegionList(c_surface_id, + std::move(c_hit_test_region_list)); EXPECT_EQ(aggregator->GetPendingCount(), 1); - aggregator->SubmitHitTestRegionList(std::move(e_hit_test_data)); + aggregator->SubmitHitTestRegionList(e_surface_id, + std::move(e_hit_test_region_list)); EXPECT_EQ(aggregator->GetPendingCount(), 2); // Surfaces added to DisplayFrame in unexpected order. @@ -729,10 +728,9 @@ SurfaceId a_surface_id = MakeSurfaceId(kDisplayFrameSink, 3); SurfaceId b_surface_id = MakeSurfaceId(kDisplayFrameSink, 4); - auto e_hit_test_data = mojom::HitTestRegionList::New(); - e_hit_test_data->surface_id = e_surface_id; - e_hit_test_data->flags = mojom::kHitTestMine; - e_hit_test_data->bounds.SetRect(0, 0, 1024, 768); + auto e_hit_test_region_list = mojom::HitTestRegionList::New(); + e_hit_test_region_list->flags = mojom::kHitTestMine; + e_hit_test_region_list->bounds.SetRect(0, 0, 1024, 768); auto e_hit_test_region_c = mojom::HitTestRegion::New(); e_hit_test_region_c->flags = mojom::kHitTestChildSurface; @@ -740,12 +738,11 @@ e_hit_test_region_c->rect.SetRect(300, 100, 1600, 800); e_hit_test_region_c->transform.Translate(200, 100); - e_hit_test_data->regions.push_back(std::move(e_hit_test_region_c)); + e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_c)); - auto c_hit_test_data = mojom::HitTestRegionList::New(); - c_hit_test_data->surface_id = c_surface_id; - c_hit_test_data->flags = mojom::kHitTestIgnore; - c_hit_test_data->bounds.SetRect(0, 0, 1600, 800); + auto c_hit_test_region_list = mojom::HitTestRegionList::New(); + c_hit_test_region_list->flags = mojom::kHitTestIgnore; + c_hit_test_region_list->bounds.SetRect(0, 0, 1600, 800); auto c_hit_test_region_a = mojom::HitTestRegion::New(); c_hit_test_region_a->flags = mojom::kHitTestChildSurface; @@ -757,33 +754,35 @@ c_hit_test_region_b->surface_id = b_surface_id; c_hit_test_region_b->rect.SetRect(0, 100, 800, 600); - c_hit_test_data->regions.push_back(std::move(c_hit_test_region_a)); - c_hit_test_data->regions.push_back(std::move(c_hit_test_region_b)); + c_hit_test_region_list->regions.push_back(std::move(c_hit_test_region_a)); + c_hit_test_region_list->regions.push_back(std::move(c_hit_test_region_b)); - auto a_hit_test_data = mojom::HitTestRegionList::New(); - a_hit_test_data->surface_id = a_surface_id; - a_hit_test_data->flags = mojom::kHitTestMine; - a_hit_test_data->bounds.SetRect(0, 0, 200, 100); + auto a_hit_test_region_list = mojom::HitTestRegionList::New(); + a_hit_test_region_list->flags = mojom::kHitTestMine; + a_hit_test_region_list->bounds.SetRect(0, 0, 200, 100); - auto b_hit_test_data = mojom::HitTestRegionList::New(); - b_hit_test_data->surface_id = b_surface_id; - b_hit_test_data->flags = mojom::kHitTestMine; - b_hit_test_data->bounds.SetRect(0, 100, 800, 600); + auto b_hit_test_region_list = mojom::HitTestRegionList::New(); + b_hit_test_region_list->flags = mojom::kHitTestMine; + b_hit_test_region_list->bounds.SetRect(0, 100, 800, 600); // Submit in unexpected order. EXPECT_EQ(aggregator->GetPendingCount(), 0); - aggregator->SubmitHitTestRegionList(std::move(c_hit_test_data)); + aggregator->SubmitHitTestRegionList(c_surface_id, + std::move(c_hit_test_region_list)); EXPECT_EQ(aggregator->GetPendingCount(), 1); - aggregator->SubmitHitTestRegionList(std::move(a_hit_test_data)); + aggregator->SubmitHitTestRegionList(a_surface_id, + std::move(a_hit_test_region_list)); EXPECT_EQ(aggregator->GetPendingCount(), 2); - aggregator->SubmitHitTestRegionList(std::move(b_hit_test_data)); + aggregator->SubmitHitTestRegionList(b_surface_id, + std::move(b_hit_test_region_list)); EXPECT_EQ(aggregator->GetPendingCount(), 3); - aggregator->SubmitHitTestRegionList(std::move(e_hit_test_data)); + aggregator->SubmitHitTestRegionList(e_surface_id, + std::move(e_hit_test_region_list)); EXPECT_EQ(aggregator->GetPendingCount(), 4); // Surfaces added to DisplayFrame in unexpected order. @@ -871,61 +870,61 @@ SurfaceId c2_surface_id = MakeSurfaceId(kDisplayFrameSink, 3); SurfaceId c3_surface_id = MakeSurfaceId(kDisplayFrameSink, 4); - auto e_hit_test_data = mojom::HitTestRegionList::New(); - e_hit_test_data->surface_id = e_surface_id; - e_hit_test_data->flags = mojom::kHitTestMine; - e_hit_test_data->bounds.SetRect(0, 0, 1024, 768); + auto e_hit_test_region_list = mojom::HitTestRegionList::New(); + e_hit_test_region_list->flags = mojom::kHitTestMine; + e_hit_test_region_list->bounds.SetRect(0, 0, 1024, 768); auto e_hit_test_region_c1 = mojom::HitTestRegion::New(); e_hit_test_region_c1->flags = mojom::kHitTestChildSurface; e_hit_test_region_c1->surface_id = c1_surface_id; e_hit_test_region_c1->rect.SetRect(100, 100, 700, 700); - e_hit_test_data->regions.push_back(std::move(e_hit_test_region_c1)); + e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_c1)); - auto c1_hit_test_data = mojom::HitTestRegionList::New(); - c1_hit_test_data->surface_id = c1_surface_id; - c1_hit_test_data->flags = mojom::kHitTestMine; - c1_hit_test_data->bounds.SetRect(0, 0, 600, 600); + auto c1_hit_test_region_list = mojom::HitTestRegionList::New(); + c1_hit_test_region_list->flags = mojom::kHitTestMine; + c1_hit_test_region_list->bounds.SetRect(0, 0, 600, 600); auto c1_hit_test_region_c2 = mojom::HitTestRegion::New(); c1_hit_test_region_c2->flags = mojom::kHitTestChildSurface; c1_hit_test_region_c2->surface_id = c2_surface_id; c1_hit_test_region_c2->rect.SetRect(100, 100, 500, 500); - c1_hit_test_data->regions.push_back(std::move(c1_hit_test_region_c2)); + c1_hit_test_region_list->regions.push_back(std::move(c1_hit_test_region_c2)); - auto c2_hit_test_data = mojom::HitTestRegionList::New(); - c2_hit_test_data->surface_id = c2_surface_id; - c2_hit_test_data->flags = mojom::kHitTestMine; - c2_hit_test_data->bounds.SetRect(0, 0, 400, 400); + auto c2_hit_test_region_list = mojom::HitTestRegionList::New(); + c2_hit_test_region_list->flags = mojom::kHitTestMine; + c2_hit_test_region_list->bounds.SetRect(0, 0, 400, 400); auto c2_hit_test_region_c3 = mojom::HitTestRegion::New(); c2_hit_test_region_c3->flags = mojom::kHitTestChildSurface; c2_hit_test_region_c3->surface_id = c3_surface_id; c2_hit_test_region_c3->rect.SetRect(100, 100, 300, 300); - c2_hit_test_data->regions.push_back(std::move(c2_hit_test_region_c3)); + c2_hit_test_region_list->regions.push_back(std::move(c2_hit_test_region_c3)); - auto c3_hit_test_data = mojom::HitTestRegionList::New(); - c3_hit_test_data->surface_id = c3_surface_id; - c3_hit_test_data->flags = mojom::kHitTestMine; - c3_hit_test_data->bounds.SetRect(0, 0, 200, 200); + auto c3_hit_test_region_list = mojom::HitTestRegionList::New(); + c3_hit_test_region_list->flags = mojom::kHitTestMine; + c3_hit_test_region_list->bounds.SetRect(0, 0, 200, 200); // Submit in unexpected order. EXPECT_EQ(aggregator->GetPendingCount(), 0); - aggregator->SubmitHitTestRegionList(std::move(c1_hit_test_data)); + aggregator->SubmitHitTestRegionList(c1_surface_id, + std::move(c1_hit_test_region_list)); EXPECT_EQ(aggregator->GetPendingCount(), 1); - aggregator->SubmitHitTestRegionList(std::move(c3_hit_test_data)); + aggregator->SubmitHitTestRegionList(c3_surface_id, + std::move(c3_hit_test_region_list)); EXPECT_EQ(aggregator->GetPendingCount(), 2); - aggregator->SubmitHitTestRegionList(std::move(e_hit_test_data)); + aggregator->SubmitHitTestRegionList(e_surface_id, + std::move(e_hit_test_region_list)); EXPECT_EQ(aggregator->GetPendingCount(), 3); - aggregator->SubmitHitTestRegionList(std::move(c2_hit_test_data)); + aggregator->SubmitHitTestRegionList(c2_surface_id, + std::move(c2_hit_test_region_list)); EXPECT_EQ(aggregator->GetPendingCount(), 4); // Surfaces added to DisplayFrame in unexpected order. @@ -1004,10 +1003,9 @@ SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1); SurfaceId c_surface_id = MakeSurfaceId(kDisplayFrameSink, 2); - auto e_hit_test_data = mojom::HitTestRegionList::New(); - e_hit_test_data->surface_id = e_surface_id; - e_hit_test_data->flags = mojom::kHitTestMine; - e_hit_test_data->bounds.SetRect(0, 0, 1024, 768); + auto e_hit_test_region_list = mojom::HitTestRegionList::New(); + e_hit_test_region_list->flags = mojom::kHitTestMine; + e_hit_test_region_list->bounds.SetRect(0, 0, 1024, 768); auto e_hit_test_region_div = mojom::HitTestRegion::New(); e_hit_test_region_div->flags = mojom::kHitTestMine; @@ -1019,19 +1017,19 @@ e_hit_test_region_c->surface_id = c_surface_id; e_hit_test_region_c->rect.SetRect(100, 100, 200, 500); - e_hit_test_data->regions.push_back(std::move(e_hit_test_region_c)); - e_hit_test_data->regions.push_back(std::move(e_hit_test_region_div)); + e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_c)); + e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_div)); - auto c_hit_test_data = mojom::HitTestRegionList::New(); - c_hit_test_data->surface_id = c_surface_id; - c_hit_test_data->flags = mojom::kHitTestMine; - c_hit_test_data->bounds.SetRect(0, 0, 200, 500); + auto c_hit_test_region_list = mojom::HitTestRegionList::New(); + c_hit_test_region_list->flags = mojom::kHitTestMine; + c_hit_test_region_list->bounds.SetRect(0, 0, 200, 500); // Submit in unexpected order, but not the child. EXPECT_EQ(aggregator->GetPendingCount(), 0); - aggregator->SubmitHitTestRegionList(std::move(e_hit_test_data)); + aggregator->SubmitHitTestRegionList(e_surface_id, + std::move(e_hit_test_region_list)); EXPECT_EQ(aggregator->GetPendingCount(), 1); // Surfaces added to DisplayFrame in unexpected order. @@ -1152,10 +1150,9 @@ SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1); SurfaceId c_surface_id = MakeSurfaceId(kDisplayFrameSink, 2); - auto e_hit_test_data = mojom::HitTestRegionList::New(); - e_hit_test_data->surface_id = e_surface_id; - e_hit_test_data->flags = mojom::kHitTestMine; - e_hit_test_data->bounds.SetRect(0, 0, 1024, 768); + auto e_hit_test_region_list = mojom::HitTestRegionList::New(); + e_hit_test_region_list->flags = mojom::kHitTestMine; + e_hit_test_region_list->bounds.SetRect(0, 0, 1024, 768); auto e_hit_test_region_div = mojom::HitTestRegion::New(); e_hit_test_region_div->flags = mojom::kHitTestMine; @@ -1167,13 +1164,12 @@ e_hit_test_region_c->surface_id = c_surface_id; e_hit_test_region_c->rect.SetRect(100, 100, 200, 500); - e_hit_test_data->regions.push_back(std::move(e_hit_test_region_c)); - e_hit_test_data->regions.push_back(std::move(e_hit_test_region_div)); + e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_c)); + e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_div)); - auto c_hit_test_data = mojom::HitTestRegionList::New(); - c_hit_test_data->surface_id = c_surface_id; - c_hit_test_data->flags = mojom::kHitTestMine; - c_hit_test_data->bounds.SetRect(0, 0, 200, 500); + auto c_hit_test_region_list = mojom::HitTestRegionList::New(); + c_hit_test_region_list->flags = mojom::kHitTestMine; + c_hit_test_region_list->bounds.SetRect(0, 0, 200, 500); EXPECT_EQ(aggregator->GetActiveRegionCount(), 0); @@ -1181,10 +1177,12 @@ EXPECT_EQ(aggregator->GetPendingCount(), 0); - aggregator->SubmitHitTestRegionList(std::move(c_hit_test_data)); + aggregator->SubmitHitTestRegionList(c_surface_id, + std::move(c_hit_test_region_list)); EXPECT_EQ(aggregator->GetPendingCount(), 1); - aggregator->SubmitHitTestRegionList(std::move(e_hit_test_data)); + aggregator->SubmitHitTestRegionList(e_surface_id, + std::move(e_hit_test_region_list)); EXPECT_EQ(aggregator->GetPendingCount(), 2); EXPECT_EQ(aggregator->GetActiveRegionCount(), 0);
diff --git a/components/viz/test/data/background_filter_rotated_sw.png b/components/viz/test/data/background_filter_rotated_sw.png index 94bbb8e6..5b9395f 100644 --- a/components/viz/test/data/background_filter_rotated_sw.png +++ b/components/viz/test/data/background_filter_rotated_sw.png Binary files differ
diff --git a/components/viz/test/data/rotated_drop_shadow_filter_sw.png b/components/viz/test/data/rotated_drop_shadow_filter_sw.png index d7c0cb4..0dd39e27 100644 --- a/components/viz/test/data/rotated_drop_shadow_filter_sw.png +++ b/components/viz/test/data/rotated_drop_shadow_filter_sw.png Binary files differ
diff --git a/components/viz/test/data/rotated_filter_sw.png b/components/viz/test/data/rotated_filter_sw.png index 12b12f0..02bf842 100644 --- a/components/viz/test/data/rotated_filter_sw.png +++ b/components/viz/test/data/rotated_filter_sw.png Binary files differ
diff --git a/components/wallpaper/wallpaper_manager_base.cc b/components/wallpaper/wallpaper_manager_base.cc index 225ffe1..4b33021 100644 --- a/components/wallpaper/wallpaper_manager_base.cc +++ b/components/wallpaper/wallpaper_manager_base.cc
@@ -450,7 +450,11 @@ GetUserWallpaperInfo(account_id, &info); info.type = DEFAULT; SetUserWallpaperInfo(account_id, info, true /* is_persistent */); - SetDefaultWallpaperNow(account_id); + + // If we're at the login screen, do not change the wallpaper but defer it + // until the user logs in to the system. + if (user_manager::UserManager::Get()->IsUserLoggedIn()) + SetDefaultWallpaperNow(account_id); } // static
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 22b9286..de15ce1 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -119,7 +119,8 @@ "//services/file:lib", "//services/file/public/interfaces", "//services/metrics/public/cpp:metrics_cpp", - "//services/network/public/interfaces:interfaces", + "//services/network/public/cpp", + "//services/network/public/interfaces", "//services/resource_coordinator:lib", "//services/resource_coordinator/public/cpp:resource_coordinator_cpp", "//services/service_manager", @@ -187,6 +188,8 @@ ] sources = [ + "$target_gen_dir/devtools/protocol/browser.cc", + "$target_gen_dir/devtools/protocol/browser.h", "$target_gen_dir/devtools/protocol/dom.cc", "$target_gen_dir/devtools/protocol/dom.h", "$target_gen_dir/devtools/protocol/emulation.cc", @@ -546,6 +549,8 @@ "devtools/devtools_url_request_interceptor.h", "devtools/forwarding_agent_host.cc", "devtools/forwarding_agent_host.h", + "devtools/protocol/browser_handler.cc", + "devtools/protocol/browser_handler.h", "devtools/protocol/devtools_domain_handler.cc", "devtools/protocol/devtools_domain_handler.h", "devtools/protocol/dom_handler.cc", @@ -663,6 +668,8 @@ "download/download_request_handle.h", "download/download_resource_handler.cc", "download/download_resource_handler.h", + "download/download_response_handler.cc", + "download/download_response_handler.h", "download/download_stats.cc", "download/download_stats.h", "download/download_task_runner.cc",
diff --git a/content/browser/DEPS b/content/browser/DEPS index 378c891..9ffada4 100644 --- a/content/browser/DEPS +++ b/content/browser/DEPS
@@ -126,13 +126,13 @@ "+third_party/WebKit/public/platform/reporting.mojom.h", "+third_party/WebKit/public/public_features.h", "+third_party/WebKit/public/web/WebAXEnums.h", - "+third_party/WebKit/public/web/WebCompositionUnderline.h", "+third_party/WebKit/public/web/WebConsoleMessage.h", "+third_party/WebKit/public/web/WebContextMenuData.h", "+third_party/WebKit/public/web/WebDeviceEmulationParams.h", "+third_party/WebKit/public/web/WebDragStatus.h", "+third_party/WebKit/public/web/WebFindOptions.h", "+third_party/WebKit/public/web/WebFrameSerializerCacheControlPolicy.h", + "+third_party/WebKit/public/web/WebImeTextSpan.h", "+third_party/WebKit/public/web/WebMediaPlayerAction.h", "+third_party/WebKit/public/web/WebPluginAction.h", "+third_party/WebKit/public/web/WebPopupType.h",
diff --git a/content/browser/android/ime_adapter_android.cc b/content/browser/android/ime_adapter_android.cc index d23bbe9..275e2468 100644 --- a/content/browser/android/ime_adapter_android.cc +++ b/content/browser/android/ime_adapter_android.cc
@@ -27,7 +27,7 @@ #include "jni/ImeAdapter_jni.h" #include "third_party/WebKit/public/platform/WebInputEvent.h" #include "third_party/WebKit/public/platform/WebTextInputType.h" -#include "ui/base/ime/composition_underline.h" +#include "ui/base/ime/ime_text_span.h" using base::android::AttachCurrentThread; using base::android::ConvertJavaStringToUTF16; @@ -73,37 +73,37 @@ } // Callback from Java to convert BackgroundColorSpan data to a -// ui::CompositionUnderline instance, and append it to |underlines_ptr|. +// ui::ImeTextSpan instance, and append it to |ime_text_spans_ptr|. void AppendBackgroundColorSpan(JNIEnv*, const JavaParamRef<jclass>&, - jlong underlines_ptr, + jlong ime_text_spans_ptr, jint start, jint end, jint background_color) { DCHECK_GE(start, 0); DCHECK_GE(end, 0); // Do not check |background_color|. - std::vector<ui::CompositionUnderline>* underlines = - reinterpret_cast<std::vector<ui::CompositionUnderline>*>(underlines_ptr); - underlines->push_back(ui::CompositionUnderline( + std::vector<ui::ImeTextSpan>* ime_text_spans = + reinterpret_cast<std::vector<ui::ImeTextSpan>*>(ime_text_spans_ptr); + ime_text_spans->push_back(ui::ImeTextSpan( static_cast<unsigned>(start), static_cast<unsigned>(end), SK_ColorTRANSPARENT, false, static_cast<unsigned>(background_color))); } // Callback from Java to convert UnderlineSpan data to a -// ui::CompositionUnderline instance, and append it to |underlines_ptr|. +// ui::ImeTextSpan instance, and append it to |ime_text_spans_ptr|. void AppendUnderlineSpan(JNIEnv*, const JavaParamRef<jclass>&, - jlong underlines_ptr, + jlong ime_text_spans_ptr, jint start, jint end) { DCHECK_GE(start, 0); DCHECK_GE(end, 0); - std::vector<ui::CompositionUnderline>* underlines = - reinterpret_cast<std::vector<ui::CompositionUnderline>*>(underlines_ptr); - underlines->push_back(ui::CompositionUnderline( - static_cast<unsigned>(start), static_cast<unsigned>(end), SK_ColorBLACK, - false, SK_ColorTRANSPARENT)); + std::vector<ui::ImeTextSpan>* ime_text_spans = + reinterpret_cast<std::vector<ui::ImeTextSpan>*>(ime_text_spans_ptr); + ime_text_spans->push_back( + ui::ImeTextSpan(static_cast<unsigned>(start), static_cast<unsigned>(end), + SK_ColorBLACK, false, SK_ColorTRANSPARENT)); } ImeAdapterAndroid::ImeAdapterAndroid(JNIEnv* env, @@ -210,13 +210,13 @@ base::string16 text16 = ConvertJavaStringToUTF16(env, text_str); - std::vector<ui::CompositionUnderline> underlines = - GetUnderlinesFromSpans(env, obj, text, text16); + std::vector<ui::ImeTextSpan> ime_text_spans = + GetImeTextSpansFromJava(env, obj, text, text16); // Default to plain underline if we didn't find any span that we care about. - if (underlines.empty()) { - underlines.push_back(ui::CompositionUnderline( - 0, text16.length(), SK_ColorBLACK, false, SK_ColorTRANSPARENT)); + if (ime_text_spans.empty()) { + ime_text_spans.push_back(ui::ImeTextSpan(0, text16.length(), SK_ColorBLACK, + false, SK_ColorTRANSPARENT)); } // relative_cursor_pos is as described in the Android API for @@ -225,7 +225,7 @@ if (relative_cursor_pos > 0) relative_cursor_pos = text16.length() + relative_cursor_pos - 1; - rwhi->ImeSetComposition(text16, underlines, gfx::Range::InvalidRange(), + rwhi->ImeSetComposition(text16, ime_text_spans, gfx::Range::InvalidRange(), relative_cursor_pos, relative_cursor_pos); } @@ -240,8 +240,8 @@ base::string16 text16 = ConvertJavaStringToUTF16(env, text_str); - std::vector<ui::CompositionUnderline> underlines = - GetUnderlinesFromSpans(env, obj, text, text16); + std::vector<ui::ImeTextSpan> ime_text_spans = + GetImeTextSpansFromJava(env, obj, text, text16); // relative_cursor_pos is as described in the Android API for // InputConnection#commitText, whereas the parameters for @@ -251,7 +251,7 @@ else relative_cursor_pos -= text16.length(); - rwhi->ImeCommitText(text16, underlines, gfx::Range::InvalidRange(), + rwhi->ImeCommitText(text16, ime_text_spans, gfx::Range::InvalidRange(), relative_cursor_pos); } @@ -336,12 +336,12 @@ if (!rfh) return; - std::vector<ui::CompositionUnderline> underlines; - underlines.push_back(ui::CompositionUnderline(0, end - start, SK_ColorBLACK, - false, SK_ColorTRANSPARENT)); + std::vector<ui::ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ui::ImeTextSpan(0, end - start, SK_ColorBLACK, false, + SK_ColorTRANSPARENT)); rfh->GetFrameInputHandler()->SetCompositionFromExistingText(start, end, - underlines); + ime_text_spans); } void ImeAdapterAndroid::DeleteSurroundingText(JNIEnv*, @@ -412,22 +412,22 @@ return nullptr; } -std::vector<ui::CompositionUnderline> ImeAdapterAndroid::GetUnderlinesFromSpans( +std::vector<ui::ImeTextSpan> ImeAdapterAndroid::GetImeTextSpansFromJava( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, const base::android::JavaParamRef<jobject>& text, const base::string16& text16) { - std::vector<ui::CompositionUnderline> underlines; + std::vector<ui::ImeTextSpan> ime_text_spans; // Iterate over spans in |text|, dispatch those that we care about (e.g., // BackgroundColorSpan) to a matching callback (e.g., - // AppendBackgroundColorSpan()), and populate |underlines|. - Java_ImeAdapter_populateUnderlinesFromSpans( - env, obj, text, reinterpret_cast<jlong>(&underlines)); + // AppendBackgroundColorSpan()), and populate |ime_text_spans|. + Java_ImeAdapter_populateImeTextSpansFromJava( + env, obj, text, reinterpret_cast<jlong>(&ime_text_spans)); // Sort spans by |.startOffset|. - std::sort(underlines.begin(), underlines.end()); + std::sort(ime_text_spans.begin(), ime_text_spans.end()); - return underlines; + return ime_text_spans; } } // namespace content
diff --git a/content/browser/android/ime_adapter_android.h b/content/browser/android/ime_adapter_android.h index 06bd658..9e591fe 100644 --- a/content/browser/android/ime_adapter_android.h +++ b/content/browser/android/ime_adapter_android.h
@@ -16,7 +16,7 @@ namespace ui { -struct CompositionUnderline; +struct ImeTextSpan; } // namespace ui @@ -113,7 +113,7 @@ private: RenderWidgetHostImpl* GetFocusedWidget(); RenderFrameHost* GetFocusedFrame(); - std::vector<ui::CompositionUnderline> GetUnderlinesFromSpans( + std::vector<ui::ImeTextSpan> GetImeTextSpansFromJava( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, const base::android::JavaParamRef<jobject>& text,
diff --git a/content/browser/appcache/appcache_update_url_loader_request.cc b/content/browser/appcache/appcache_update_url_loader_request.cc index 590bd6f..3d7d8d2 100644 --- a/content/browser/appcache/appcache_update_url_loader_request.cc +++ b/content/browser/appcache/appcache_update_url_loader_request.cc
@@ -40,7 +40,7 @@ } std::string AppCacheUpdateJob::UpdateURLLoaderRequest::GetMimeType() const { - return response_->mime_type; + return response_.mime_type; } void AppCacheUpdateJob::UpdateURLLoaderRequest::SetSiteForCookies( @@ -55,12 +55,12 @@ net::HttpResponseHeaders* AppCacheUpdateJob::UpdateURLLoaderRequest::GetResponseHeaders() const { - return response_->headers.get(); + return response_.headers.get(); } int AppCacheUpdateJob::UpdateURLLoaderRequest::GetResponseCode() const { - if (response_->headers) - return response_->headers->response_code(); + if (response_.headers) + return response_.headers->response_code(); return 0; } @@ -82,7 +82,7 @@ url_loader_ = nullptr; handle_watcher_.Cancel(); handle_.reset(); - response_.reset(nullptr); + response_ = ResourceResponseHead(); http_response_info_.reset(nullptr); read_requested_ = false; return 0; @@ -92,8 +92,7 @@ const ResourceResponseHead& response_head, const base::Optional<net::SSLInfo>& ssl_info, mojom::DownloadedTempFilePtr downloaded_file) { - response_.reset(new ResourceResponseHead()); - *response_ = response_head; + response_ = response_head; // TODO(ananta/michaeln) // Populate other fields in the HttpResponseInfo class. It would be good to @@ -116,7 +115,7 @@ void AppCacheUpdateJob::UpdateURLLoaderRequest::OnReceiveRedirect( const net::RedirectInfo& redirect_info, const ResourceResponseHead& response_head) { - *response_ = response_head; + response_ = response_head; fetcher_->OnReceivedRedirect(redirect_info); } @@ -191,8 +190,8 @@ } uint32_t available = 0; - MojoResult result = - MojoToNetPendingBuffer::BeginRead(&handle_, &pending_read_, &available); + MojoResult result = network::MojoToNetPendingBuffer::BeginRead( + &handle_, &pending_read_, &available); DCHECK_NE(result, MOJO_RESULT_BUSY); if (result == MOJO_RESULT_SHOULD_WAIT) { @@ -215,8 +214,8 @@ int bytes_to_be_read = std::min<int>(buffer_size_, available); - scoped_refptr<MojoToNetIOBuffer> buffer = - new MojoToNetIOBuffer(pending_read_.get(), bytes_to_be_read); + auto buffer = base::MakeRefCounted<network::MojoToNetIOBuffer>( + pending_read_.get(), bytes_to_be_read); fetcher_->OnReadCompleted(buffer.get(), bytes_to_be_read); }
diff --git a/content/browser/appcache/appcache_update_url_loader_request.h b/content/browser/appcache/appcache_update_url_loader_request.h index 185f0ff..ebe478c 100644 --- a/content/browser/appcache/appcache_update_url_loader_request.h +++ b/content/browser/appcache/appcache_update_url_loader_request.h
@@ -11,12 +11,13 @@ #include "base/macros.h" #include "content/browser/appcache/appcache_update_request_base.h" -#include "content/common/net_adapters.h" #include "content/public/common/resource_request.h" +#include "content/public/common/resource_response.h" #include "content/public/common/url_loader.mojom.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/system/simple_watcher.h" #include "net/base/io_buffer.h" +#include "services/network/public/cpp/net_adapters.h" namespace net { class HttpResponseInfo; @@ -26,7 +27,6 @@ class URLLoaderFactoryGetter; struct ResourceRequest; -struct ResourceResponseHead; // URLLoaderClient subclass for the UpdateRequestBase class. Provides // functionality to update the AppCache using functionality provided by the @@ -91,7 +91,7 @@ scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter_; ResourceRequest request_; - std::unique_ptr<ResourceResponseHead> response_; + ResourceResponseHead response_; ResourceRequestCompletionStatus response_status_; // Response details. std::unique_ptr<net::HttpResponseInfo> http_response_info_; @@ -114,7 +114,7 @@ // Please look at the StartReading() function for details. bool read_requested_; // Adapter for transferring data from a mojo data pipe to net. - scoped_refptr<MojoToNetPendingBuffer> pending_read_; + scoped_refptr<network::MojoToNetPendingBuffer> pending_read_; DISALLOW_COPY_AND_ASSIGN(UpdateURLLoaderRequest); };
diff --git a/content/browser/appcache/appcache_url_loader_job.cc b/content/browser/appcache/appcache_url_loader_job.cc index 5679b7a..0e578654 100644 --- a/content/browser/appcache/appcache_url_loader_job.cc +++ b/content/browser/appcache/appcache_url_loader_job.cc
@@ -9,9 +9,9 @@ #include "content/browser/appcache/appcache_subresource_url_factory.h" #include "content/browser/appcache/appcache_url_loader_request.h" #include "content/browser/url_loader_factory_getter.h" -#include "content/common/net_adapters.h" #include "content/public/common/resource_type.h" #include "net/http/http_status_code.h" +#include "services/network/public/cpp/net_adapters.h" namespace content { @@ -393,7 +393,7 @@ uint32_t num_bytes; // TODO: we should use the abstractions in MojoAsyncResourceHandler. - MojoResult result = NetToMojoPendingBuffer::BeginWrite( + MojoResult result = network::NetToMojoPendingBuffer::BeginWrite( &response_body_stream_, &pending_write_, &num_bytes); if (result == MOJO_RESULT_SHOULD_WAIT) { // The pipe is full. We need to wait for it to have more space. @@ -410,8 +410,8 @@ } CHECK_GT(static_cast<uint32_t>(std::numeric_limits<int>::max()), num_bytes); - scoped_refptr<NetToMojoIOBuffer> buffer = - new NetToMojoIOBuffer(pending_write_.get()); + auto buffer = + base::MakeRefCounted<network::NetToMojoIOBuffer>(pending_write_.get()); reader_->ReadData( buffer.get(), info_->response_data_size(),
diff --git a/content/browser/appcache/appcache_url_loader_job.h b/content/browser/appcache/appcache_url_loader_job.h index a1328c9..d696045 100644 --- a/content/browser/appcache/appcache_url_loader_job.h +++ b/content/browser/appcache/appcache_url_loader_job.h
@@ -22,11 +22,14 @@ #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/system/data_pipe.h" +namespace network { +class NetToMojoPendingBuffer; +} + namespace content { class AppCacheRequest; class AppCacheURLLoaderRequest; -class NetToMojoPendingBuffer; class URLLoaderFactoryGetter; // Holds information about the subresource load request like the routing id, @@ -183,7 +186,7 @@ // mojo data pipe entities. mojo::ScopedDataPipeProducerHandle response_body_stream_; - scoped_refptr<NetToMojoPendingBuffer> pending_write_; + scoped_refptr<network::NetToMojoPendingBuffer> pending_write_; mojo::SimpleWatcher writable_handle_watcher_;
diff --git a/content/browser/blob_storage/blob_url_loader_factory.cc b/content/browser/blob_storage/blob_url_loader_factory.cc index a9406a33..85afc946 100644 --- a/content/browser/blob_storage/blob_url_loader_factory.cc +++ b/content/browser/blob_storage/blob_url_loader_factory.cc
@@ -5,14 +5,15 @@ #include "content/browser/blob_storage/blob_url_loader_factory.h" #include <stddef.h> +#include <utility> #include "base/bind.h" #include "base/logging.h" #include "base/macros.h" +#include "base/memory/ptr_util.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread_task_runner_handle.h" #include "content/browser/blob_storage/chrome_blob_storage_context.h" #include "content/browser/storage_partition_impl.h" -#include "content/common/net_adapters.h" #include "content/public/browser/browser_thread.h" #include "content/public/common/url_loader.mojom.h" #include "mojo/public/cpp/system/simple_watcher.h" @@ -26,6 +27,7 @@ #include "storage/browser/blob/blob_reader.h" #include "storage/browser/blob/blob_storage_context.h" #include "storage/browser/blob/blob_url_request_job.h" +#include "storage/browser/blob/mojo_blob_reader.h" #include "storage/browser/fileapi/file_system_context.h" namespace content { @@ -33,10 +35,12 @@ namespace { constexpr size_t kDefaultAllocationSize = 512 * 1024; -// This class handles a request for a blob:// url. It self-destructs (see -// DeleteIfNeeded) when it has finished responding. +// This class handles a request for a blob:// url. It self-destructs (directly, +// or after passing ownership to storage::MojoBlobReader at the end of the Start +// method) when it has finished responding. // Note: some of this code is duplicated from storage::BlobURLRequestJob. -class BlobURLLoader : public mojom::URLLoader { +class BlobURLLoader : public storage::MojoBlobReader::Delegate, + public mojom::URLLoader { public: BlobURLLoader(mojom::URLLoaderRequest url_loader_request, const ResourceRequest& request, @@ -46,37 +50,29 @@ : binding_(this, std::move(url_loader_request)), client_(std::move(client)), blob_handle_(std::move(blob_handle)), - writable_handle_watcher_(FROM_HERE, - mojo::SimpleWatcher::ArmingPolicy::MANUAL), - peer_closed_handle_watcher_(FROM_HERE, - mojo::SimpleWatcher::ArmingPolicy::MANUAL), weak_factory_(this) { DCHECK_CURRENTLY_ON(BrowserThread::IO); // PostTask since it might destruct. - base::ThreadTaskRunnerHandle::Get()->PostTask( + base::SequencedTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind(&BlobURLLoader::Start, weak_factory_.GetWeakPtr(), request, make_scoped_refptr(file_system_context))); } + private: void Start(const ResourceRequest& request, scoped_refptr<storage::FileSystemContext> file_system_context) { if (!blob_handle_) { - NotifyCompleted(net::ERR_FILE_NOT_FOUND); + OnComplete(net::ERR_FILE_NOT_FOUND, 0); + delete this; return; } - blob_reader_ = blob_handle_->CreateReader(file_system_context.get()); - // We only support GET request per the spec. if (request.method != "GET") { - NotifyCompleted(net::ERR_METHOD_NOT_SUPPORTED); - return; - } - - if (blob_reader_->net_error()) { - NotifyCompleted(blob_reader_->net_error()); + OnComplete(net::ERR_METHOD_NOT_SUPPORTED, 0); + delete this; return; } @@ -95,112 +91,65 @@ // We don't support multiple range requests in one single URL request, // because we need to do multipart encoding here. // TODO(jianli): Support multipart byte range requests. - NotifyCompleted(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); + OnComplete(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, 0); + delete this; + return; } } } - storage::BlobReader::Status size_status = - blob_reader_->CalculateSize(base::Bind(&BlobURLLoader::DidCalculateSize, - weak_factory_.GetWeakPtr())); - switch (size_status) { - case storage::BlobReader::Status::NET_ERROR: - NotifyCompleted(blob_reader_->net_error()); - return; - case storage::BlobReader::Status::IO_PENDING: - return; - case storage::BlobReader::Status::DONE: - DidCalculateSize(net::OK); - return; - } - - NOTREACHED(); + storage::MojoBlobReader::Create(file_system_context.get(), + blob_handle_.get(), byte_range_, + base::WrapUnique(this)); } - ~BlobURLLoader() override {} - - private: // mojom::URLLoader implementation: void FollowRedirect() override { NOTREACHED(); } void SetPriority(net::RequestPriority priority, int32_t intra_priority_value) override {} - // Notifies the client that the request completed. Takes care of deleting this - // object now if possible (i.e. no outstanding data pipe), otherwise this - // object will be deleted when the data pipe is closed. - void NotifyCompleted(int error_code) { - if (error_code != net::OK && !sent_headers_) { - net::HttpStatusCode status_code = - storage::BlobURLRequestJob::NetErrorToHttpStatusCode(error_code); - ResourceResponseHead response; - response.headers = storage::BlobURLRequestJob::GenerateHeaders( - status_code, nullptr, nullptr, nullptr, nullptr); - client_->OnReceiveResponse(response, base::nullopt, nullptr); - } - ResourceRequestCompletionStatus request_complete_data; - // TODO(kinuko): We should probably set the error_code here, - // while it makes existing tests fail. crbug.com/732750 - request_complete_data.completion_time = base::TimeTicks::Now(); - request_complete_data.encoded_body_length = total_written_bytes_; - request_complete_data.decoded_body_length = total_written_bytes_; - client_->OnComplete(request_complete_data); - - DeleteIfNeeded(); + // storage::MojoBlobReader::Delegate implementation: + mojo::ScopedDataPipeProducerHandle PassDataPipe() override { + mojo::DataPipe data_pipe(kDefaultAllocationSize); + response_body_consumer_handle_ = std::move(data_pipe.consumer_handle); + return std::move(data_pipe.producer_handle); } - void DidCalculateSize(int result) { - if (result != net::OK) { - NotifyCompleted(result); - return; - } - - // Apply the range requirement. - if (!byte_range_.ComputeBounds(blob_reader_->total_size())) { - NotifyCompleted(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); - return; - } - - DCHECK_LE(byte_range_.first_byte_position(), - byte_range_.last_byte_position() + 1); - uint64_t length = - base::checked_cast<uint64_t>(byte_range_.last_byte_position() - - byte_range_.first_byte_position() + 1); - - if (byte_range_set_) - blob_reader_->SetReadRange(byte_range_.first_byte_position(), length); + RequestSideData DidCalculateSize(uint64_t total_size, + uint64_t content_size) override { + total_size_ = total_size; + bool result = byte_range_.ComputeBounds(total_size); + DCHECK(result); net::HttpStatusCode status_code = net::HTTP_OK; if (byte_range_set_ && byte_range_.IsValid()) { status_code = net::HTTP_PARTIAL_CONTENT; } else { + DCHECK_EQ(total_size, content_size); // TODO(horo): When the requester doesn't need the side data // (ex:FileReader) we should skip reading the side data. - if (blob_reader_->has_side_data() && - blob_reader_->ReadSideData(base::Bind(&BlobURLLoader::DidReadMetadata, - weak_factory_.GetWeakPtr())) == - storage::BlobReader::Status::IO_PENDING) { - return; - } + return REQUEST_SIDE_DATA; } - HeadersCompleted(status_code); + HeadersCompleted(status_code, content_size, nullptr); + return DONT_REQUEST_SIDE_DATA; } - void DidReadMetadata(storage::BlobReader::Status result) { - if (result != storage::BlobReader::Status::DONE) { - NotifyCompleted(blob_reader_->net_error()); - return; - } - HeadersCompleted(net::HTTP_OK); + void DidReadSideData(net::IOBufferWithSize* data) override { + HeadersCompleted(net::HTTP_OK, total_size_, data); } - void HeadersCompleted(net::HttpStatusCode status_code) { + void HeadersCompleted(net::HttpStatusCode status_code, + uint64_t content_size, + net::IOBufferWithSize* metadata) { ResourceResponseHead response; response.content_length = 0; + if (status_code == net::HTTP_OK || status_code == net::HTTP_PARTIAL_CONTENT) + response.content_length = content_size; response.headers = storage::BlobURLRequestJob::GenerateHeaders( - status_code, blob_handle_.get(), blob_reader_.get(), &byte_range_, - &response.content_length); + status_code, blob_handle_.get(), &byte_range_, total_size_, + content_size); std::string mime_type; response.headers->GetMimeType(&mime_type); @@ -214,112 +163,38 @@ client_->OnReceiveResponse(response, base::nullopt, nullptr); sent_headers_ = true; - net::IOBufferWithSize* metadata = blob_reader_->side_data(); if (metadata) { const uint8_t* data = reinterpret_cast<const uint8_t*>(metadata->data()); client_->OnReceiveCachedMetadata( std::vector<uint8_t>(data, data + metadata->size())); } - - mojo::DataPipe data_pipe(kDefaultAllocationSize); - response_body_stream_ = std::move(data_pipe.producer_handle); - response_body_consumer_handle_ = std::move(data_pipe.consumer_handle); - peer_closed_handle_watcher_.Watch( - response_body_stream_.get(), MOJO_HANDLE_SIGNAL_PEER_CLOSED, - base::Bind(&BlobURLLoader::OnResponseBodyStreamClosed, - base::Unretained(this))); - peer_closed_handle_watcher_.ArmOrNotify(); - - writable_handle_watcher_.Watch( - response_body_stream_.get(), MOJO_HANDLE_SIGNAL_WRITABLE, - base::Bind(&BlobURLLoader::OnResponseBodyStreamReady, - base::Unretained(this))); - - // Start reading... - ReadMore(); } - void ReadMore() { - DCHECK(!pending_write_.get()); - - uint32_t num_bytes; - // TODO: we should use the abstractions in MojoAsyncResourceHandler. - MojoResult result = NetToMojoPendingBuffer::BeginWrite( - &response_body_stream_, &pending_write_, &num_bytes); - if (result == MOJO_RESULT_SHOULD_WAIT) { - // The pipe is full. We need to wait for it to have more space. - writable_handle_watcher_.ArmOrNotify(); - return; - } else if (result != MOJO_RESULT_OK) { - // The response body stream is in a bad state. Bail. - writable_handle_watcher_.Cancel(); - response_body_stream_.reset(); - NotifyCompleted(net::ERR_UNEXPECTED); - return; - } - - CHECK_GT(static_cast<uint32_t>(std::numeric_limits<int>::max()), num_bytes); - scoped_refptr<net::IOBuffer> buf( - new NetToMojoIOBuffer(pending_write_.get())); - int bytes_read; - storage::BlobReader::Status read_status = blob_reader_->Read( - buf.get(), static_cast<int>(num_bytes), &bytes_read, - base::Bind(&BlobURLLoader::DidRead, weak_factory_.GetWeakPtr(), false)); - switch (read_status) { - case storage::BlobReader::Status::NET_ERROR: - NotifyCompleted(blob_reader_->net_error()); - return; - case storage::BlobReader::Status::IO_PENDING: - // Wait for DidRead. - return; - case storage::BlobReader::Status::DONE: - if (bytes_read > 0) { - DidRead(true, bytes_read); - } else { - writable_handle_watcher_.Cancel(); - pending_write_->Complete(0); - pending_write_ = nullptr; // This closes the data pipe. - NotifyCompleted(net::OK); - return; - } - } - } - - void DidRead(bool completed_synchronously, int num_bytes) { + void DidRead(int num_bytes) override { if (response_body_consumer_handle_.is_valid()) { // Send the data pipe on the first OnReadCompleted call. client_->OnStartLoadingResponseBody( std::move(response_body_consumer_handle_)); } - response_body_stream_ = pending_write_->Complete(num_bytes); - total_written_bytes_ += num_bytes; - pending_write_ = nullptr; - if (completed_synchronously) { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(&BlobURLLoader::ReadMore, weak_factory_.GetWeakPtr())); - } else { - ReadMore(); + } + + void OnComplete(net::Error error_code, + uint64_t total_written_bytes) override { + if (error_code != net::OK && !sent_headers_) { + net::HttpStatusCode status_code = + storage::BlobURLRequestJob::NetErrorToHttpStatusCode(error_code); + ResourceResponseHead response; + response.headers = storage::BlobURLRequestJob::GenerateHeaders( + status_code, nullptr, nullptr, 0, 0); + client_->OnReceiveResponse(response, base::nullopt, nullptr); } - } - - void OnResponseBodyStreamClosed(MojoResult result) { - response_body_stream_.reset(); - pending_write_ = nullptr; - DeleteIfNeeded(); - } - - void OnResponseBodyStreamReady(MojoResult result) { - // TODO: Handle a bad |result| value. - DCHECK_EQ(result, MOJO_RESULT_OK); - ReadMore(); - } - - void DeleteIfNeeded() { - bool has_data_pipe = - pending_write_.get() || response_body_stream_.is_valid(); - if (!has_data_pipe) - delete this; + ResourceRequestCompletionStatus request_complete_data; + // TODO(kinuko): We should probably set the error_code here, + // while it makes existing tests fail. crbug.com/732750 + request_complete_data.completion_time = base::TimeTicks::Now(); + request_complete_data.encoded_body_length = total_written_bytes; + request_complete_data.decoded_body_length = total_written_bytes; + client_->OnComplete(request_complete_data); } mojo::Binding<mojom::URLLoader> binding_; @@ -328,18 +203,11 @@ bool byte_range_set_ = false; net::HttpByteRange byte_range_; + uint64_t total_size_ = 0; bool sent_headers_ = false; std::unique_ptr<storage::BlobDataHandle> blob_handle_; - std::unique_ptr<storage::BlobReader> blob_reader_; - - // TODO(jam): share with URLLoaderImpl - mojo::ScopedDataPipeProducerHandle response_body_stream_; mojo::ScopedDataPipeConsumerHandle response_body_consumer_handle_; - scoped_refptr<NetToMojoPendingBuffer> pending_write_; - mojo::SimpleWatcher writable_handle_watcher_; - mojo::SimpleWatcher peer_closed_handle_watcher_; - int64_t total_written_bytes_ = 0; base::WeakPtrFactory<BlobURLLoader> weak_factory_;
diff --git a/content/browser/browser_associated_interface_unittest.cc b/content/browser/browser_associated_interface_unittest.cc index c18a79d..8b315e3 100644 --- a/content/browser/browser_associated_interface_unittest.cc +++ b/content/browser/browser_associated_interface_unittest.cc
@@ -95,7 +95,7 @@ void OnFilterRemoved() override { // Check that the bindings are cleared by // BrowserAssociatedInterface::ClearBindings() callbacks. - EXPECT_FALSE(internal_state_->bindings_.get()); + EXPECT_FALSE(internal_state_->bindings_.has_value()); } // mojom::BrowserAssociatedInterfaceTestDriver:
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc index 0eed74e..e44dd5ab 100644 --- a/content/browser/browser_plugin/browser_plugin_guest.cc +++ b/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -62,15 +62,16 @@ namespace { -std::vector<ui::CompositionUnderline> ConvertToUiUnderline( - const std::vector<blink::WebCompositionUnderline>& underlines) { - std::vector<ui::CompositionUnderline> ui_underlines; - for (const auto& underline : underlines) { - ui_underlines.emplace_back(ui::CompositionUnderline( - underline.start_offset, underline.end_offset, underline.color, - underline.thick, underline.background_color)); +std::vector<ui::ImeTextSpan> ConvertToUiImeTextSpan( + const std::vector<blink::WebImeTextSpan>& ime_text_spans) { + std::vector<ui::ImeTextSpan> ui_ime_text_spans; + for (const auto& ime_text_span : ime_text_spans) { + ui_ime_text_spans.emplace_back( + ui::ImeTextSpan(ime_text_span.start_offset, ime_text_span.end_offset, + ime_text_span.color, ime_text_span.thick, + ime_text_span.background_color)); } - return ui_underlines; + return ui_ime_text_spans; } }; // namespace @@ -929,29 +930,30 @@ void BrowserPluginGuest::OnImeSetComposition( int browser_plugin_instance_id, const BrowserPluginHostMsg_SetComposition_Params& params) { - std::vector<ui::CompositionUnderline> ui_underlines = - ConvertToUiUnderline(params.underlines); + std::vector<ui::ImeTextSpan> ui_ime_text_spans = + ConvertToUiImeTextSpan(params.ime_text_spans); GetWebContents() ->GetRenderViewHost() ->GetWidget() ->GetWidgetInputHandler() - ->ImeSetComposition(params.text, ui_underlines, params.replacement_range, - params.selection_start, params.selection_end); + ->ImeSetComposition(params.text, ui_ime_text_spans, + params.replacement_range, params.selection_start, + params.selection_end); } void BrowserPluginGuest::OnImeCommitText( int browser_plugin_instance_id, const base::string16& text, - const std::vector<blink::WebCompositionUnderline>& underlines, + const std::vector<blink::WebImeTextSpan>& ime_text_spans, const gfx::Range& replacement_range, int relative_cursor_pos) { - std::vector<ui::CompositionUnderline> ui_underlines = - ConvertToUiUnderline(underlines); + std::vector<ui::ImeTextSpan> ui_ime_text_spans = + ConvertToUiImeTextSpan(ime_text_spans); GetWebContents() ->GetRenderViewHost() ->GetWidget() ->GetWidgetInputHandler() - ->ImeCommitText(text, ui_underlines, replacement_range, + ->ImeCommitText(text, ui_ime_text_spans, replacement_range, relative_cursor_pos); }
diff --git a/content/browser/browser_plugin/browser_plugin_guest.h b/content/browser/browser_plugin/browser_plugin_guest.h index 725b77d..ac97e22 100644 --- a/content/browser/browser_plugin/browser_plugin_guest.h +++ b/content/browser/browser_plugin/browser_plugin_guest.h
@@ -38,8 +38,8 @@ #include "third_party/WebKit/public/platform/WebDragOperation.h" #include "third_party/WebKit/public/platform/WebFocusType.h" #include "third_party/WebKit/public/platform/WebInputEvent.h" -#include "third_party/WebKit/public/web/WebCompositionUnderline.h" #include "third_party/WebKit/public/web/WebDragStatus.h" +#include "third_party/WebKit/public/web/WebImeTextSpan.h" #include "ui/base/ime/text_input_mode.h" #include "ui/base/ime/text_input_type.h" #include "ui/gfx/geometry/rect.h" @@ -336,12 +336,11 @@ void OnImeSetComposition( int instance_id, const BrowserPluginHostMsg_SetComposition_Params& params); - void OnImeCommitText( - int instance_id, - const base::string16& text, - const std::vector<blink::WebCompositionUnderline>& underlines, - const gfx::Range& replacement_range, - int relative_cursor_pos); + void OnImeCommitText(int instance_id, + const base::string16& text, + const std::vector<blink::WebImeTextSpan>& ime_text_spans, + const gfx::Range& replacement_range, + int relative_cursor_pos); void OnImeFinishComposingText(int instance_id, bool keep_selection); void OnExtendSelectionAndDelete(int instance_id, int before, int after); void OnImeCancelComposition();
diff --git a/content/browser/devtools/BUILD.gn b/content/browser/devtools/BUILD.gn index 1f3a739e..611d028 100644 --- a/content/browser/devtools/BUILD.gn +++ b/content/browser/devtools/BUILD.gn
@@ -74,6 +74,8 @@ # These are relative to $target_gen_dir. outputs = [ + "protocol/browser.cc", + "protocol/browser.h", "protocol/dom.cc", "protocol/dom.h", "protocol/emulation.cc",
diff --git a/content/browser/devtools/browser_devtools_agent_host.cc b/content/browser/devtools/browser_devtools_agent_host.cc index bb7a585..74d57201 100644 --- a/content/browser/devtools/browser_devtools_agent_host.cc +++ b/content/browser/devtools/browser_devtools_agent_host.cc
@@ -9,6 +9,7 @@ #include "base/memory/ptr_util.h" #include "base/single_thread_task_runner.h" #include "content/browser/devtools/devtools_session.h" +#include "content/browser/devtools/protocol/browser_handler.h" #include "content/browser/devtools/protocol/io_handler.h" #include "content/browser/devtools/protocol/memory_handler.h" #include "content/browser/devtools/protocol/protocol.h" @@ -51,6 +52,7 @@ if (only_discovery_) return; + session->AddHandler(base::WrapUnique(new protocol::BrowserHandler())); session->AddHandler(base::WrapUnique(new protocol::IOHandler( GetIOContext()))); session->AddHandler(base::WrapUnique(new protocol::MemoryHandler()));
diff --git a/content/browser/devtools/protocol/browser_handler.cc b/content/browser/devtools/protocol/browser_handler.cc new file mode 100644 index 0000000..b5fd5f4 --- /dev/null +++ b/content/browser/devtools/protocol/browser_handler.cc
@@ -0,0 +1,38 @@ +// 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 "content/browser/devtools/protocol/browser_handler.h" + +#include "content/public/browser/devtools_agent_host.h" +#include "content/public/common/content_client.h" +#include "content/public/common/user_agent.h" +#include "v8/include/v8-version-string.h" + +namespace content { +namespace protocol { + +BrowserHandler::BrowserHandler() + : DevToolsDomainHandler(Browser::Metainfo::domainName) {} + +BrowserHandler::~BrowserHandler() {} + +void BrowserHandler::Wire(UberDispatcher* dispatcher) { + Browser::Dispatcher::wire(dispatcher, this); +} + +Response BrowserHandler::GetVersion(std::string* protocol_version, + std::string* product, + std::string* revision, + std::string* user_agent, + std::string* js_version) { + *protocol_version = DevToolsAgentHost::GetProtocolVersion(); + *revision = GetWebKitRevision(); + *product = GetContentClient()->GetProduct(); + *user_agent = GetContentClient()->GetUserAgent(); + *js_version = V8_VERSION_STRING; + return Response::OK(); +} + +} // namespace protocol +} // namespace content
diff --git a/content/browser/devtools/protocol/browser_handler.h b/content/browser/devtools/protocol/browser_handler.h new file mode 100644 index 0000000..fe109fe --- /dev/null +++ b/content/browser/devtools/protocol/browser_handler.h
@@ -0,0 +1,37 @@ +// 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 CONTENT_BROWSER_DEVTOOLS_PROTOCOL_BROWSER_HANDLER_H_ +#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_BROWSER_HANDLER_H_ + +#include "base/macros.h" +#include "content/browser/devtools/protocol/browser.h" +#include "content/browser/devtools/protocol/devtools_domain_handler.h" + +namespace content { + +namespace protocol { + +class BrowserHandler : public DevToolsDomainHandler, public Browser::Backend { + public: + BrowserHandler(); + ~BrowserHandler() override; + + void Wire(UberDispatcher* dispatcher) override; + + // Protocol methods. + Response GetVersion(std::string* protocol_version, + std::string* product, + std::string* revision, + std::string* user_agent, + std::string* js_version) override; + + private: + DISALLOW_COPY_AND_ASSIGN(BrowserHandler); +}; + +} // namespace protocol +} // namespace content + +#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_BROWSER_HANDLER_H_
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc index 9a526397..4d89cb2b 100644 --- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc +++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -167,12 +167,6 @@ return true; } - void ShowCertificateViewerInDevTools( - WebContents* web_contents, - scoped_refptr<net::X509Certificate> certificate) override { - last_shown_certificate_ = certificate; - } - base::DictionaryValue* SendCommand( const std::string& method, std::unique_ptr<base::DictionaryValue> params) { @@ -353,10 +347,6 @@ return urls; } - const scoped_refptr<net::X509Certificate>& last_shown_certificate() { - return last_shown_certificate_; - } - const scoped_refptr<net::X509Certificate>& ok_cert() { return ok_cert_; } const scoped_refptr<net::X509Certificate>& expired_cert() { @@ -419,7 +409,6 @@ std::unique_ptr<base::DictionaryValue> waiting_for_notification_params_; int waiting_for_command_result_id_; bool in_dispatch_; - scoped_refptr<net::X509Certificate> last_shown_certificate_; scoped_refptr<net::X509Certificate> ok_cert_; scoped_refptr<net::X509Certificate> expired_cert_; bool agent_host_can_close_; @@ -586,17 +575,21 @@ bool MatchesBitmap(const SkBitmap& expected_bmp, const SkBitmap& actual_bmp, const gfx::Rect& matching_mask, + float device_scale_factor, int error_limit) { // Number of pixels with an error int error_pixels_count = 0; gfx::Rect error_bounding_rect = gfx::Rect(); + // Scale expectations along with the mask. + device_scale_factor = device_scale_factor ? device_scale_factor : 1; + // Check that bitmaps have identical dimensions. - EXPECT_EQ(expected_bmp.width(), actual_bmp.width()); - EXPECT_EQ(expected_bmp.height(), actual_bmp.height()); - if (expected_bmp.width() != actual_bmp.width() || - expected_bmp.height() != actual_bmp.height()) { + EXPECT_EQ(expected_bmp.width() * device_scale_factor, actual_bmp.width()); + EXPECT_EQ(expected_bmp.height() * device_scale_factor, actual_bmp.height()); + if (expected_bmp.width() * device_scale_factor != actual_bmp.width() || + expected_bmp.height() * device_scale_factor != actual_bmp.height()) { return false; } @@ -604,7 +597,8 @@ for (int x = matching_mask.x(); x < matching_mask.right(); ++x) { for (int y = matching_mask.y(); y < matching_mask.bottom(); ++y) { - SkColor actual_color = actual_bmp.getColor(x, y); + SkColor actual_color = + actual_bmp.getColor(x * device_scale_factor, y * device_scale_factor); SkColor expected_color = expected_bmp.getColor(x, y); if (!ColorsMatchWithinLimit(actual_color, expected_color, error_limit)) { if (error_pixels_count < 10) { @@ -632,13 +626,14 @@ enum ScreenshotEncoding { ENCODING_PNG, ENCODING_JPEG }; void CaptureScreenshotAndCompareTo(const SkBitmap& expected_bitmap, ScreenshotEncoding encoding, - bool fromSurface, + bool from_surface, + float device_scale_factor = 0, const gfx::RectF& clip = gfx::RectF(), float clip_scale = 0) { std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue()); params->SetString("format", encoding == ENCODING_PNG ? "png" : "jpeg"); params->SetInteger("quality", 100); - params->SetBoolean("fromSurface", fromSurface); + params->SetBoolean("fromSurface", from_surface); if (clip_scale) { std::unique_ptr<base::DictionaryValue> clip_value( new base::DictionaryValue()); @@ -674,13 +669,14 @@ matching_mask.Inset(4, 4, 4, 4); #endif EXPECT_TRUE(MatchesBitmap(expected_bitmap, *result_bitmap, matching_mask, - error_limit)); + device_scale_factor, error_limit)); } // Takes a screenshot of a colored box that is positioned inside the frame. void PlaceAndCaptureBox(const gfx::Size& frame_size, const gfx::Size& box_size, - float screenshot_scale) { + float screenshot_scale, + float device_scale_factor) { static const int kBoxOffsetHeight = 100; const gfx::Size scaled_box_size = ScaleToFlooredSize(box_size, screenshot_scale); @@ -711,7 +707,7 @@ params.reset(new base::DictionaryValue()); params->SetInteger("width", frame_size.width()); params->SetInteger("height", frame_size.height()); - params->SetDouble("deviceScaleFactor", 1); + params->SetDouble("deviceScaleFactor", device_scale_factor); params->SetBoolean("mobile", false); SendCommand("Emulation.setDeviceMetricsOverride", std::move(params)); @@ -727,8 +723,8 @@ expected_bitmap.allocN32Pixels(scaled_box_size.width(), scaled_box_size.height()); expected_bitmap.eraseColor(SkColorSetRGB(0x00, 0x00, 0xff)); - CaptureScreenshotAndCompareTo(expected_bitmap, ENCODING_PNG, true, clip, - screenshot_scale); + CaptureScreenshotAndCompareTo(expected_bitmap, ENCODING_PNG, true, + device_scale_factor, clip, screenshot_scale); // Reset for next screenshot. SendCommand("Emulation.clearDeviceMetricsOverride", nullptr); @@ -801,12 +797,17 @@ Attach(); // Test capturing a subarea inside the emulated frame at different scales. - PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 1.0); - PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 2.0); - PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 0.5); + PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 1.0, 1.); + PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 2.0, 1.); + PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 0.5, 1.); // Ensure that content outside the emulated frame is painted, too. - PlaceAndCaptureBox(kFrameSize, gfx::Size(10, 8192), 1.0); + PlaceAndCaptureBox(kFrameSize, gfx::Size(10, 8192), 1.0, 1.); + + // Check non-1 device scale factor. + PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 1.0, 2.); + // Ensure not emulating device scale factor works. + PlaceAndCaptureBox(kFrameSize, gfx::Size(100, 200), 1.0, 0.); } // Verifies that setDefaultBackgroundColor and captureScreenshot support a @@ -1548,59 +1549,6 @@ EXPECT_THAT(console_messages_, ElementsAre("before", "at", "done", "after")); } -// Tests that the Security.showCertificateViewer command shows the -// certificate corresponding to the visible navigation entry, even when -// an interstitial is showing. Regression test for -// https://crbug.com/647759. -IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, ShowCertificateViewer) { - // First test that the correct certificate is shown for a normal - // (non-interstitial) page. - NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1); - Attach(); - - // Set a dummy certificate on the NavigationEntry. - shell() - ->web_contents() - ->GetController() - .GetVisibleEntry() - ->GetSSL() - .certificate = ok_cert(); - - std::unique_ptr<base::DictionaryValue> params1(new base::DictionaryValue()); - SendCommand("Security.showCertificateViewer", std::move(params1), true); - - scoped_refptr<net::X509Certificate> normal_page_cert = shell() - ->web_contents() - ->GetController() - .GetVisibleEntry() - ->GetSSL() - .certificate; - ASSERT_TRUE(normal_page_cert); - EXPECT_EQ(normal_page_cert, last_shown_certificate()); - - // Now test that the correct certificate is shown on an interstitial. - TestInterstitialDelegate* delegate = new TestInterstitialDelegate; - WebContentsImpl* web_contents = - static_cast<WebContentsImpl*>(shell()->web_contents()); - GURL interstitial_url("https://example.test"); - InterstitialPageImpl* interstitial = new InterstitialPageImpl( - web_contents, static_cast<RenderWidgetHostDelegate*>(web_contents), true, - interstitial_url, delegate); - interstitial->Show(); - WaitForInterstitialAttach(web_contents); - - // Set the transient navigation entry certificate. - NavigationEntry* transient_entry = - web_contents->GetController().GetTransientEntry(); - ASSERT_TRUE(transient_entry); - transient_entry->GetSSL().certificate = expired_cert(); - ASSERT_TRUE(transient_entry->GetSSL().certificate); - - std::unique_ptr<base::DictionaryValue> params2(new base::DictionaryValue()); - SendCommand("Security.showCertificateViewer", std::move(params2), true); - EXPECT_EQ(transient_entry->GetSSL().certificate, last_shown_certificate()); -} - IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, CertificateError) { net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED);
diff --git a/content/browser/devtools/protocol/io_handler.h b/content/browser/devtools/protocol/io_handler.h index 3bff07c..066541c 100644 --- a/content/browser/devtools/protocol/io_handler.h +++ b/content/browser/devtools/protocol/io_handler.h
@@ -49,4 +49,4 @@ } // namespace protocol } // namespace content -#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_TRACING_HANDLER_H_ +#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_IO_HANDLER_H_
diff --git a/content/browser/devtools/protocol/page_handler.cc b/content/browser/devtools/protocol/page_handler.cc index 714cccf7..21c9d64 100644 --- a/content/browser/devtools/protocol/page_handler.cc +++ b/content/browser/devtools/protocol/page_handler.cc
@@ -458,8 +458,10 @@ if (!modified_params.view_size.height) emulated_view_size.set_height(original_view_size.height()); - dpfactor = - modified_params.device_scale_factor / screen_info.device_scale_factor; + dpfactor = modified_params.device_scale_factor + ? modified_params.device_scale_factor / + screen_info.device_scale_factor + : 1; // When clip is specified, we scale viewport via clip, otherwise we use // scale. modified_params.scale = clip.isJust() ? 1 : dpfactor;
diff --git a/content/browser/devtools/protocol/security_handler.cc b/content/browser/devtools/protocol/security_handler.cc index 0ba37a9..803f58f 100644 --- a/content/browser/devtools/protocol/security_handler.cc +++ b/content/browser/devtools/protocol/security_handler.cc
@@ -6,6 +6,7 @@ #include <string> +#include "base/base64.h" #include "content/browser/devtools/devtools_session.h" #include "content/browser/frame_host/render_frame_host_impl.h" #include "content/public/browser/navigation_controller.h" @@ -14,6 +15,7 @@ #include "content/public/browser/ssl_status.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_delegate.h" +#include "net/cert/x509_certificate.h" #include "third_party/WebKit/public/platform/WebMixedContentContextType.h" namespace content { @@ -66,12 +68,32 @@ const std::vector<SecurityStyleExplanation>& explanations_to_add, Explanations* explanations) { for (const auto& it : explanations_to_add) { + std::unique_ptr<protocol::Array<String>> certificate = + protocol::Array<String>::create(); + if (it.certificate) { + std::string der; + std::string encoded; + bool rv = net::X509Certificate::GetDEREncoded( + it.certificate->os_cert_handle(), &der); + DCHECK(rv); + base::Base64Encode(der, &encoded); + + certificate->addItem(encoded); + + for (auto* cert : it.certificate->GetIntermediateCertificates()) { + rv = net::X509Certificate::GetDEREncoded(cert, &der); + DCHECK(rv); + base::Base64Encode(der, &encoded); + certificate->addItem(encoded); + } + } + explanations->addItem( Security::SecurityStateExplanation::Create() .SetSecurityState(security_style) .SetSummary(it.summary) .SetDescription(it.description) - .SetHasCertificate(it.has_certificate) + .SetCertificate(std::move(certificate)) .SetMixedContentType(MixedContentTypeToProtocolMixedContentType( it.mixed_content_type)) .Build()); @@ -210,19 +232,6 @@ return Response::OK(); } -Response SecurityHandler::ShowCertificateViewer() { - if (!host_) - return Response::InternalError(); - WebContents* web_contents = WebContents::FromRenderFrameHost(host_); - scoped_refptr<net::X509Certificate> certificate = - web_contents->GetController().GetVisibleEntry()->GetSSL().certificate; - if (!certificate) - return Response::Error("Could not find certificate"); - web_contents->GetDelegate()->ShowCertificateViewerInDevTools( - web_contents, certificate); - return Response::OK(); -} - Response SecurityHandler::HandleCertificateError(int event_id, const String& action) { if (cert_error_callbacks_.find(event_id) == cert_error_callbacks_.end()) {
diff --git a/content/browser/devtools/protocol/security_handler.h b/content/browser/devtools/protocol/security_handler.h index 96c24ff3..c70fdef 100644 --- a/content/browser/devtools/protocol/security_handler.h +++ b/content/browser/devtools/protocol/security_handler.h
@@ -40,7 +40,6 @@ // Security::Backend overrides. Response Enable() override; Response Disable() override; - Response ShowCertificateViewer() override; Response HandleCertificateError(int event_id, const String& action) override; Response SetOverrideCertificateErrors(bool override) override;
diff --git a/content/browser/devtools/protocol_config.json b/content/browser/devtools/protocol_config.json index a43e4ef..057470ce 100644 --- a/content/browser/devtools/protocol_config.json +++ b/content/browser/devtools/protocol_config.json
@@ -10,6 +10,10 @@ "export_header": "content/common/content_export.h", "options": [ { + "domain": "Browser", + "include": ["getVersion"] + }, + { "domain": "DOM", "include": ["setFileInputFiles"], "include_events": [],
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc index b95c89a2..10503c7 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.cc +++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -18,6 +18,7 @@ #include "content/browser/devtools/devtools_frame_trace_recorder.h" #include "content/browser/devtools/devtools_manager.h" #include "content/browser/devtools/devtools_session.h" +#include "content/browser/devtools/protocol/browser_handler.h" #include "content/browser/devtools/protocol/dom_handler.h" #include "content/browser/devtools/protocol/emulation_handler.h" #include "content/browser/devtools/protocol/input_handler.h" @@ -506,6 +507,7 @@ protocol::EmulationHandler* emulation_handler = new protocol::EmulationHandler(); + session->AddHandler(base::WrapUnique(new protocol::BrowserHandler())); session->AddHandler(base::WrapUnique(new protocol::DOMHandler())); session->AddHandler(base::WrapUnique(emulation_handler)); session->AddHandler(base::WrapUnique(new protocol::InputHandler()));
diff --git a/content/browser/dom_storage/dom_storage_host.cc b/content/browser/dom_storage/dom_storage_host.cc index 162cdc7..38655ef 100644 --- a/content/browser/dom_storage/dom_storage_host.cc +++ b/content/browser/dom_storage/dom_storage_host.cc
@@ -32,8 +32,16 @@ references.namespace_ = context_->GetStorageNamespace(namespace_id); if (!references.namespace_.get()) return context_->DiagnoseSessionNamespaceId(namespace_id); - references.area_ = references.namespace_->OpenStorageArea(origin); - DCHECK(references.area_.get()); + + // namespace->OpenStorageArea() is called only once per process + // (areas_open_count[area] is 0). + references.area_ = references.namespace_->GetOpenStorageArea(origin); + if (!references.area_ || !areas_open_count_[references.area_.get()]) { + references.area_ = references.namespace_->OpenStorageArea(origin); + DCHECK(references.area_.get()); + DCHECK_EQ(0, areas_open_count_[references.area_.get()]); + } + ++areas_open_count_[references.area_.get()]; connections_[connection_id] = references; return base::nullopt; } @@ -42,7 +50,15 @@ const auto found = connections_.find(connection_id); if (found == connections_.end()) return; - found->second.namespace_->CloseStorageArea(found->second.area_.get()); + DOMStorageArea* area = found->second.area_.get(); + DCHECK(areas_open_count_[area]); + + // namespace->CloseStorageArea() is called only once per process + // (areas_open_count[area] becomes 0). + if (--areas_open_count_[area] == 0) { + found->second.namespace_->CloseStorageArea(area); + areas_open_count_.erase(area); + } connections_.erase(found); } @@ -84,29 +100,34 @@ return area->GetItem(key); } -bool DOMStorageHost::SetAreaItem( - int connection_id, const base::string16& key, - const base::string16& value, const GURL& page_url, - base::NullableString16* old_value) { +bool DOMStorageHost::SetAreaItem(int connection_id, + const base::string16& key, + const base::string16& value, + const base::NullableString16& client_old_value, + const GURL& page_url) { DOMStorageArea* area = GetOpenArea(connection_id); if (!area) return false; - if (!area->SetItem(key, value, old_value)) + base::NullableString16 old_value; + if (!area->SetItem(key, value, &old_value)) return false; - if (old_value->is_null() || old_value->string() != value) - context_->NotifyItemSet(area, key, value, *old_value, page_url); + if (old_value.is_null() || old_value.string() != value) + context_->NotifyItemSet(area, key, value, old_value, page_url); return true; } bool DOMStorageHost::RemoveAreaItem( - int connection_id, const base::string16& key, const GURL& page_url, - base::string16* old_value) { + int connection_id, + const base::string16& key, + const base::NullableString16& client_old_value, + const GURL& page_url) { DOMStorageArea* area = GetOpenArea(connection_id); if (!area) return false; - if (!area->RemoveItem(key, old_value)) + base::string16 old_value; + if (!area->RemoveItem(key, &old_value)) return false; - context_->NotifyItemRemoved(area, key, *old_value, page_url); + context_->NotifyItemRemoved(area, key, old_value, page_url); return true; }
diff --git a/content/browser/dom_storage/dom_storage_host.h b/content/browser/dom_storage/dom_storage_host.h index 6b931d19..5804806 100644 --- a/content/browser/dom_storage/dom_storage_host.h +++ b/content/browser/dom_storage/dom_storage_host.h
@@ -45,13 +45,15 @@ base::NullableString16 GetAreaKey(int connection_id, unsigned index); base::NullableString16 GetAreaItem(int connection_id, const base::string16& key); - bool SetAreaItem(int connection_id, const base::string16& key, - const base::string16& value, const GURL& page_url, - base::NullableString16* old_value); + bool SetAreaItem(int connection_id, + const base::string16& key, + const base::string16& value, + const base::NullableString16& client_old_value, + const GURL& page_url); bool RemoveAreaItem(int connection_id, const base::string16& key, - const GURL& page_url, - base::string16* old_value); + const base::NullableString16& client_old_value, + const GURL& page_url); bool ClearArea(int connection_id, const GURL& page_url); bool HasAreaOpen(int namespace_id, const GURL& origin) const; bool HasConnection(int connection_id) const { @@ -75,6 +77,7 @@ scoped_refptr<DOMStorageContextImpl> context_; AreaMap connections_; + std::map<DOMStorageArea*, int> areas_open_count_; DISALLOW_COPY_AND_ASSIGN(DOMStorageHost); };
diff --git a/content/browser/dom_storage/dom_storage_message_filter.cc b/content/browser/dom_storage/dom_storage_message_filter.cc index ec5622f..bb64fcc 100644 --- a/content/browser/dom_storage/dom_storage_message_filter.cc +++ b/content/browser/dom_storage/dom_storage_message_filter.cc
@@ -112,27 +112,30 @@ } void DOMStorageMessageFilter::OnSetItem( - int connection_id, const base::string16& key, - const base::string16& value, const GURL& page_url) { - DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO)); - DCHECK_EQ(0, connection_dispatching_message_for_); - base::AutoReset<int> auto_reset(&connection_dispatching_message_for_, - connection_id); - base::NullableString16 not_used; - bool success = host_->SetAreaItem(connection_id, key, value, - page_url, ¬_used); - Send(new DOMStorageMsg_AsyncOperationComplete(success)); -} - -void DOMStorageMessageFilter::OnRemoveItem( - int connection_id, const base::string16& key, + int connection_id, + const base::string16& key, + const base::string16& value, + const base::NullableString16& client_old_value, const GURL& page_url) { DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO)); DCHECK_EQ(0, connection_dispatching_message_for_); base::AutoReset<int> auto_reset(&connection_dispatching_message_for_, connection_id); - base::string16 not_used; - host_->RemoveAreaItem(connection_id, key, page_url, ¬_used); + bool success = + host_->SetAreaItem(connection_id, key, value, client_old_value, page_url); + Send(new DOMStorageMsg_AsyncOperationComplete(success)); +} + +void DOMStorageMessageFilter::OnRemoveItem( + int connection_id, + const base::string16& key, + const base::NullableString16& client_old_value, + const GURL& page_url) { + DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_EQ(0, connection_dispatching_message_for_); + base::AutoReset<int> auto_reset(&connection_dispatching_message_for_, + connection_id); + host_->RemoveAreaItem(connection_id, key, client_old_value, page_url); Send(new DOMStorageMsg_AsyncOperationComplete(true)); }
diff --git a/content/browser/dom_storage/dom_storage_message_filter.h b/content/browser/dom_storage/dom_storage_message_filter.h index c3394e7..ff199f8 100644 --- a/content/browser/dom_storage/dom_storage_message_filter.h +++ b/content/browser/dom_storage/dom_storage_message_filter.h
@@ -55,9 +55,14 @@ const GURL& origin); void OnCloseStorageArea(int connection_id); void OnLoadStorageArea(int connection_id, DOMStorageValuesMap* map); - void OnSetItem(int connection_id, const base::string16& key, - const base::string16& value, const GURL& page_url); - void OnRemoveItem(int connection_id, const base::string16& key, + void OnSetItem(int connection_id, + const base::string16& key, + const base::string16& value, + const base::NullableString16& client_old_value, + const GURL& page_url); + void OnRemoveItem(int connection_id, + const base::string16& key, + const base::NullableString16& client_old_value, const GURL& page_url); void OnClear(int connection_id, const GURL& page_url); void OnFlushMessages();
diff --git a/content/browser/dom_storage/dom_storage_namespace.cc b/content/browser/dom_storage/dom_storage_namespace.cc index 847b193..10568d3 100644 --- a/content/browser/dom_storage/dom_storage_namespace.cc +++ b/content/browser/dom_storage/dom_storage_namespace.cc
@@ -196,6 +196,13 @@ origins->push_back(entry.first); } +int DOMStorageNamespace::GetAreaOpenCount(const GURL& origin) const { + const auto& found = areas_.find(origin); + if (found == areas_.end()) + return 0; + return found->second.open_count_; +} + DOMStorageNamespace::AreaHolder* DOMStorageNamespace::GetAreaHolder(const GURL& origin) { AreaMap::iterator found = areas_.find(origin);
diff --git a/content/browser/dom_storage/dom_storage_namespace.h b/content/browser/dom_storage/dom_storage_namespace.h index 8f75f2ab..2fdab5a 100644 --- a/content/browser/dom_storage/dom_storage_namespace.h +++ b/content/browser/dom_storage/dom_storage_namespace.h
@@ -85,6 +85,8 @@ void GetOriginsWithAreas(std::vector<GURL>* origins) const; + int GetAreaOpenCount(const GURL& origin) const; + private: friend class base::RefCountedThreadSafe<DOMStorageNamespace>;
diff --git a/content/browser/download/download_request_core.cc b/content/browser/download/download_request_core.cc index e37a480..2f3619b 100644 --- a/content/browser/download/download_request_core.cc +++ b/content/browser/download/download_request_core.cc
@@ -461,106 +461,4 @@ request() ? request()->url().spec().c_str() : "<NULL request>"); } -// static -DownloadInterruptReason DownloadRequestCore::HandleSuccessfulServerResponse( - const net::HttpResponseHeaders& http_headers, - DownloadSaveInfo* save_info) { - switch (http_headers.response_code()) { - case -1: // Non-HTTP request. - case net::HTTP_OK: - case net::HTTP_NON_AUTHORITATIVE_INFORMATION: - case net::HTTP_PARTIAL_CONTENT: - // Expected successful codes. - break; - - case net::HTTP_CREATED: - case net::HTTP_ACCEPTED: - // Per RFC 7231 the entity being transferred is metadata about the - // resource at the target URL and not the resource at that URL (or the - // resource that would be at the URL once processing is completed in the - // case of HTTP_ACCEPTED). However, we currently don't have special - // handling for these response and they are downloaded the same as a - // regular response. - break; - - case net::HTTP_NO_CONTENT: - case net::HTTP_RESET_CONTENT: - // These two status codes don't have an entity (or rather RFC 7231 - // requires that there be no entity). They are treated the same as the - // resource not being found since there is no entity to download. - - case net::HTTP_NOT_FOUND: - return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT; - break; - - case net::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE: - // Retry by downloading from the start automatically: - // If we haven't received data when we get this error, we won't. - return DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE; - break; - case net::HTTP_UNAUTHORIZED: - case net::HTTP_PROXY_AUTHENTICATION_REQUIRED: - // Server didn't authorize this request. - return DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED; - break; - case net::HTTP_FORBIDDEN: - // Server forbids access to this resource. - return DOWNLOAD_INTERRUPT_REASON_SERVER_FORBIDDEN; - break; - default: // All other errors. - // Redirection and informational codes should have been handled earlier - // in the stack. - // TODO(xingliu): Handle HTTP_PRECONDITION_FAILED and resurrect - // DOWNLOAD_INTERRUPT_REASON_SERVER_PRECONDITION for range requests. - // This will change extensions::api::download::InterruptReason. - DCHECK_NE(3, http_headers.response_code() / 100); - DCHECK_NE(1, http_headers.response_code() / 100); - return DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED; - } - - // The caller is expecting a partial response. - if (save_info && (save_info->offset > 0 || save_info->length > 0)) { - if (http_headers.response_code() != net::HTTP_PARTIAL_CONTENT) { - // Server should send partial content when "If-Match" or - // "If-Unmodified-Since" check passes, and the range request header has - // last byte position. e.g. "Range:bytes=50-99". - if (save_info->length != DownloadSaveInfo::kLengthFullContent) - return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT; - - // Requested a partial range, but received the entire response, when - // the range request header is "Range:bytes={offset}-". - save_info->offset = 0; - save_info->hash_of_partial_file.clear(); - save_info->hash_state.reset(); - return DOWNLOAD_INTERRUPT_REASON_NONE; - } - - int64_t first_byte = -1; - int64_t last_byte = -1; - int64_t length = -1; - if (!http_headers.GetContentRangeFor206(&first_byte, &last_byte, &length)) - return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT; - DCHECK_GE(first_byte, 0); - - if (first_byte != save_info->offset || - (save_info->length > 0 && - last_byte != save_info->offset + save_info->length - 1)) { - // The server returned a different range than the one we requested. Assume - // the response is bad. - // - // In the future we should consider allowing offsets that are less than - // the offset we've requested, since in theory we can truncate the partial - // file at the offset and continue. - return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT; - } - - return DOWNLOAD_INTERRUPT_REASON_NONE; - } - - if (http_headers.response_code() == net::HTTP_PARTIAL_CONTENT) - return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT; - - return DOWNLOAD_INTERRUPT_REASON_NONE; -} - } // namespace content
diff --git a/content/browser/download/download_request_core.h b/content/browser/download/download_request_core.h index 93c4315a..52fd227 100644 --- a/content/browser/download/download_request_core.h +++ b/content/browser/download/download_request_core.h
@@ -115,10 +115,6 @@ net::URLRequest* request() const { return request_; } private: - static DownloadInterruptReason HandleSuccessfulServerResponse( - const net::HttpResponseHeaders& http_headers, - DownloadSaveInfo* save_info); - std::unique_ptr<DownloadCreateInfo> CreateDownloadCreateInfo( DownloadInterruptReason result);
diff --git a/content/browser/download/download_response_handler.cc b/content/browser/download/download_response_handler.cc new file mode 100644 index 0000000..715df6d --- /dev/null +++ b/content/browser/download/download_response_handler.cc
@@ -0,0 +1,70 @@ +// 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 "content/browser/download/download_response_handler.h" + +#include "content/browser/download/download_stats.h" +#include "content/browser/download/download_utils.h" + +namespace content { + +DownloadResponseHandler::DownloadResponseHandler( + ResourceRequest* resource_request, + Delegate* delegate, + bool is_parallel_request) + : delegate_(delegate) { + if (!is_parallel_request) + RecordDownloadCount(UNTHROTTLED_COUNT); + + // TODO(qinmin): create the DownloadSaveInfo from |resource_request| +} + +DownloadResponseHandler::~DownloadResponseHandler() = default; + +void DownloadResponseHandler::OnReceiveResponse( + const content::ResourceResponseHead& head, + const base::Optional<net::SSLInfo>& ssl_info, + mojom::DownloadedTempFilePtr downloaded_file) { + // TODO(qinmin): create the DownloadCreateInfo from |head|. + + // TODO(qinmin): pass DownloadSaveInfo here. + DownloadInterruptReason result = + head.headers + ? HandleSuccessfulServerResponse(*(head.headers.get()), nullptr) + : DOWNLOAD_INTERRUPT_REASON_NONE; + if (result != DOWNLOAD_INTERRUPT_REASON_NONE) { + delegate_->OnResponseStarted(download_create_info_, + mojo::ScopedDataPipeConsumerHandle()); + } +} + +void DownloadResponseHandler::OnReceiveRedirect( + const net::RedirectInfo& redirect_info, + const content::ResourceResponseHead& head) {} + +void DownloadResponseHandler::OnDataDownloaded(int64_t data_length, + int64_t encoded_length) {} + +void DownloadResponseHandler::OnUploadProgress( + int64_t current_position, + int64_t total_size, + OnUploadProgressCallback callback) {} + +void DownloadResponseHandler::OnReceiveCachedMetadata( + const std::vector<uint8_t>& data) {} + +void DownloadResponseHandler::OnTransferSizeUpdated( + int32_t transfer_size_diff) {}; + +void DownloadResponseHandler::OnStartLoadingResponseBody( + mojo::ScopedDataPipeConsumerHandle body) { + delegate_->OnResponseStarted(download_create_info_, std::move(body)); +} + +void DownloadResponseHandler::OnComplete( + const content::ResourceRequestCompletionStatus& completion_status) { + // TODO(qinmin): passing the |completion_status| to DownloadFile. +} + +} // namespace content
diff --git a/content/browser/download/download_response_handler.h b/content/browser/download/download_response_handler.h new file mode 100644 index 0000000..f60158e --- /dev/null +++ b/content/browser/download/download_response_handler.h
@@ -0,0 +1,59 @@ +// 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 CONTENT_BROWSER_DOWNLOAD_RESPONSE_HANDLER_ +#define CONTENT_BROWSER_DOWNLOAD_RESPONSE_HANDLER_ + +#include "content/browser/download/download_create_info.h" +#include "content/public/common/resource_request.h" +#include "content/public/common/url_loader.mojom.h" + +namespace content { + +// This class is responsible for handling the server response for a download. +// It passes the DataPipeConsumerHandle and completion status to the download +// sink. The class is common to both navigation triggered downloads and +// context menu downloads +class DownloadResponseHandler : public mojom::URLLoaderClient { + public: + class Delegate { + public: + virtual void OnResponseStarted( + const DownloadCreateInfo& download_create_info, + mojo::ScopedDataPipeConsumerHandle body) = 0; + }; + + DownloadResponseHandler(ResourceRequest* resource_request, + Delegate* delegate, + bool is_parallel_request); + ~DownloadResponseHandler() override; + + // mojom::URLLoaderClient + void OnReceiveResponse(const content::ResourceResponseHead& head, + const base::Optional<net::SSLInfo>& ssl_info, + mojom::DownloadedTempFilePtr downloaded_file) override; + void OnReceiveRedirect(const net::RedirectInfo& redirect_info, + const content::ResourceResponseHead& head) override; + void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override; + void OnUploadProgress(int64_t current_position, + int64_t total_size, + OnUploadProgressCallback callback) override; + void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override; + void OnTransferSizeUpdated(int32_t transfer_size_diff) override; + void OnStartLoadingResponseBody( + mojo::ScopedDataPipeConsumerHandle body) override; + void OnComplete(const content::ResourceRequestCompletionStatus& + completion_status) override; + + private: + Delegate* const delegate_; + + DownloadCreateInfo download_create_info_; + + DISALLOW_COPY_AND_ASSIGN(DownloadResponseHandler); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_DOWNLOAD_RESPONSE_HANDLER
diff --git a/content/browser/download/download_utils.cc b/content/browser/download/download_utils.cc index 856a531..3e288d8 100644 --- a/content/browser/download/download_utils.cc +++ b/content/browser/download/download_utils.cc
@@ -10,12 +10,14 @@ #include "content/browser/download/download_interrupt_reasons_impl.h" #include "content/browser/download/download_stats.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/download_save_info.h" #include "content/public/browser/download_url_parameters.h" #include "content/public/common/resource_request.h" #include "net/base/elements_upload_data_stream.h" #include "net/base/load_flags.h" #include "net/base/upload_bytes_element_reader.h" #include "net/http/http_request_headers.h" +#include "net/http/http_status_code.h" #include "net/url_request/url_request_context.h" namespace content { @@ -250,5 +252,105 @@ return request; } +DownloadInterruptReason HandleSuccessfulServerResponse( + const net::HttpResponseHeaders& http_headers, + DownloadSaveInfo* save_info) { + switch (http_headers.response_code()) { + case -1: // Non-HTTP request. + case net::HTTP_OK: + case net::HTTP_NON_AUTHORITATIVE_INFORMATION: + case net::HTTP_PARTIAL_CONTENT: + // Expected successful codes. + break; + + case net::HTTP_CREATED: + case net::HTTP_ACCEPTED: + // Per RFC 7231 the entity being transferred is metadata about the + // resource at the target URL and not the resource at that URL (or the + // resource that would be at the URL once processing is completed in the + // case of HTTP_ACCEPTED). However, we currently don't have special + // handling for these response and they are downloaded the same as a + // regular response. + break; + + case net::HTTP_NO_CONTENT: + case net::HTTP_RESET_CONTENT: + // These two status codes don't have an entity (or rather RFC 7231 + // requires that there be no entity). They are treated the same as the + // resource not being found since there is no entity to download. + + case net::HTTP_NOT_FOUND: + return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT; + break; + + case net::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE: + // Retry by downloading from the start automatically: + // If we haven't received data when we get this error, we won't. + return DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE; + break; + case net::HTTP_UNAUTHORIZED: + case net::HTTP_PROXY_AUTHENTICATION_REQUIRED: + // Server didn't authorize this request. + return DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED; + break; + case net::HTTP_FORBIDDEN: + // Server forbids access to this resource. + return DOWNLOAD_INTERRUPT_REASON_SERVER_FORBIDDEN; + break; + default: // All other errors. + // Redirection and informational codes should have been handled earlier + // in the stack. + // TODO(xingliu): Handle HTTP_PRECONDITION_FAILED and resurrect + // DOWNLOAD_INTERRUPT_REASON_SERVER_PRECONDITION for range requests. + // This will change extensions::api::download::InterruptReason. + DCHECK_NE(3, http_headers.response_code() / 100); + DCHECK_NE(1, http_headers.response_code() / 100); + return DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED; + } + + // The caller is expecting a partial response. + if (save_info && (save_info->offset > 0 || save_info->length > 0)) { + if (http_headers.response_code() != net::HTTP_PARTIAL_CONTENT) { + // Server should send partial content when "If-Match" or + // "If-Unmodified-Since" check passes, and the range request header has + // last byte position. e.g. "Range:bytes=50-99". + if (save_info->length != DownloadSaveInfo::kLengthFullContent) + return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT; + + // Requested a partial range, but received the entire response, when + // the range request header is "Range:bytes={offset}-". + save_info->offset = 0; + save_info->hash_of_partial_file.clear(); + save_info->hash_state.reset(); + return DOWNLOAD_INTERRUPT_REASON_NONE; + } + + int64_t first_byte = -1; + int64_t last_byte = -1; + int64_t length = -1; + if (!http_headers.GetContentRangeFor206(&first_byte, &last_byte, &length)) + return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT; + DCHECK_GE(first_byte, 0); + + if (first_byte != save_info->offset || + (save_info->length > 0 && + last_byte != save_info->offset + save_info->length - 1)) { + // The server returned a different range than the one we requested. Assume + // the response is bad. + // + // In the future we should consider allowing offsets that are less than + // the offset we've requested, since in theory we can truncate the partial + // file at the offset and continue. + return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT; + } + + return DOWNLOAD_INTERRUPT_REASON_NONE; + } + + if (http_headers.response_code() == net::HTTP_PARTIAL_CONTENT) + return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT; + + return DOWNLOAD_INTERRUPT_REASON_NONE; +} } // namespace content
diff --git a/content/browser/download/download_utils.h b/content/browser/download/download_utils.h index 741218a..4b8c2ef 100644 --- a/content/browser/download/download_utils.h +++ b/content/browser/download/download_utils.h
@@ -8,6 +8,7 @@ #include "content/public/browser/download_interrupt_reasons.h" #include "net/base/net_errors.h" #include "net/cert/cert_status_flags.h" +#include "net/http/http_response_headers.h" namespace net { class URLRequest; @@ -17,6 +18,7 @@ class DownloadUrlParameters; struct ResourceRequest; +struct DownloadSaveInfo; // Handle the url request completion status and return the interrupt reasons. // |cert_status| is ignored if error_code is not net::ERR_ABORTED. @@ -29,9 +31,13 @@ DownloadUrlParameters* params); // Create a URLRequest from |params|. -std::unique_ptr<net::URLRequest> CreateURLRequestOnIOThread( +std::unique_ptr<net::URLRequest> CONTENT_EXPORT CreateURLRequestOnIOThread( DownloadUrlParameters* params); +DownloadInterruptReason CONTENT_EXPORT +HandleSuccessfulServerResponse(const net::HttpResponseHeaders& http_headers, + DownloadSaveInfo* save_info); + } // namespace content #endif // CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_UTILS_H_
diff --git a/content/browser/download/parallel_download_job.cc b/content/browser/download/parallel_download_job.cc index 519711e..c800f09 100644 --- a/content/browser/download/parallel_download_job.cc +++ b/content/browser/download/parallel_download_job.cc
@@ -134,8 +134,10 @@ void ParallelDownloadJob::BuildParallelRequests() { DCHECK(!requests_sent_); DCHECK(!is_paused()); - if (is_canceled_) + if (is_canceled_ || + download_item_->GetLastReason() != DOWNLOAD_INTERRUPT_REASON_NONE) { return; + } // TODO(qinmin): The size of |slices_to_download| should be no larger than // |kParallelRequestCount| unless |kParallelRequestCount| is changed after
diff --git a/content/browser/download/parallel_download_job_unittest.cc b/content/browser/download/parallel_download_job_unittest.cc index ae7d5b04c..223a3a1 100644 --- a/content/browser/download/parallel_download_job_unittest.cc +++ b/content/browser/download/parallel_download_job_unittest.cc
@@ -9,6 +9,7 @@ #include "base/memory/ptr_util.h" #include "base/run_loop.h" +#include "base/test/mock_callback.h" #include "base/test/scoped_task_environment.h" #include "content/browser/download/download_destination_observer.h" #include "content/browser/download/download_file_impl.h" @@ -22,6 +23,7 @@ using ::testing::_; using ::testing::NiceMock; +using ::testing::Return; using ::testing::StrictMock; namespace content { @@ -91,6 +93,11 @@ ParallelDownloadJob::WorkerMap& workers() { return workers_; } + void MakeFileInitialized(const DownloadFile::InitializeCallback& callback, + DownloadInterruptReason result) { + ParallelDownloadJob::OnDownloadFileInitialized(callback, result); + } + int GetParallelRequestCount() const override { return request_count_; } int64_t GetMinSliceSize() const override { return min_slice_size_; } int GetMinRemainingTimeInSeconds() const override { @@ -198,7 +205,7 @@ // Task 1: Range:50-, for 50 bytes. CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2, 1, 10); BuildParallelRequests(); - EXPECT_EQ(1, static_cast<int>(job_->workers().size())); + EXPECT_EQ(1u, job_->workers().size()); VerifyWorker(50, 0); DestroyParallelJob(); @@ -208,7 +215,7 @@ // Task 2: Range:66-, for 34 bytes. CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 3, 1, 10); BuildParallelRequests(); - EXPECT_EQ(2, static_cast<int>(job_->workers().size())); + EXPECT_EQ(2u, job_->workers().size()); VerifyWorker(33, 33); VerifyWorker(66, 0); DestroyParallelJob(); @@ -242,7 +249,7 @@ DownloadItem::ReceivedSlices slices = {DownloadItem::ReceivedSlice(0, 17)}; CreateParallelJob(12, 88, slices, 3, 1, 10); BuildParallelRequests(); - EXPECT_EQ(2, static_cast<int>(job_->workers().size())); + EXPECT_EQ(2u, job_->workers().size()); VerifyWorker(44, 27); VerifyWorker(71, 0); DestroyParallelJob(); @@ -256,7 +263,7 @@ slices = {DownloadItem::ReceivedSlice(0, 60)}; CreateParallelJob(60, 40, slices, 4, 20, 10); BuildParallelRequests(); - EXPECT_EQ(1, static_cast<int>(job_->workers().size())); + EXPECT_EQ(1u, job_->workers().size()); VerifyWorker(80, 0); DestroyParallelJob(); @@ -277,7 +284,7 @@ DownloadItem::ReceivedSlice(40, 10), DownloadItem::ReceivedSlice(90, 10)}; CreateParallelJob(0, 12, slices, 2, 1, 10); BuildParallelRequests(); - EXPECT_EQ(3, static_cast<int>(job_->workers().size())); + EXPECT_EQ(3u, job_->workers().size()); VerifyWorker(30, 10); VerifyWorker(50, 40); VerifyWorker(100, 0); @@ -359,7 +366,7 @@ DownloadItem::ReceivedSlices slices = {DownloadItem::ReceivedSlice(0, 99)}; CreateParallelJob(99, 1, slices, 3, 1, 10); BuildParallelRequests(); - EXPECT_EQ(0, static_cast<int>(job_->workers().size())); + EXPECT_EQ(0u, job_->workers().size()); DestroyParallelJob(); } @@ -398,4 +405,26 @@ task_environment_.RunUntilIdle(); } +// Interruption from IO thread after the file initialized and before building +// the parallel requests, should correctly stop the download. +TEST_F(ParallelDownloadJobTest, InterruptOnStartup) { + DownloadItem::ReceivedSlices slices = {DownloadItem::ReceivedSlice(0, 99)}; + CreateParallelJob(99, 1, slices, 3, 1, 10); + + // Start to build the requests without any error. + base::MockCallback<DownloadFile::InitializeCallback> callback; + EXPECT_CALL(callback, Run(_)).Times(1); + job_->MakeFileInitialized(callback.Get(), DOWNLOAD_INTERRUPT_REASON_NONE); + + // Simulate and inject an error from IO thread after file initializd. + EXPECT_CALL(*download_item_.get(), GetLastReason()) + .WillOnce(Return(DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED)); + + // Because of the error, no parallel requests are built. + task_environment_.RunUntilIdle(); + EXPECT_EQ(0u, job_->workers().size()); + + DestroyParallelJob(); +} + } // namespace content
diff --git a/content/browser/frame_host/input/legacy_ipc_frame_input_handler.cc b/content/browser/frame_host/input/legacy_ipc_frame_input_handler.cc index 849d9c1..b44c9e5 100644 --- a/content/browser/frame_host/input/legacy_ipc_frame_input_handler.cc +++ b/content/browser/frame_host/input/legacy_ipc_frame_input_handler.cc
@@ -20,17 +20,18 @@ void LegacyIPCFrameInputHandler::SetCompositionFromExistingText( int32_t start, int32_t end, - const std::vector<ui::CompositionUnderline>& ui_underlines) { - std::vector<blink::WebCompositionUnderline> underlines; - for (const auto& underline : ui_underlines) { - blink::WebCompositionUnderline blink_underline( - underline.start_offset, underline.end_offset, underline.color, - underline.thick, underline.background_color); - underlines.push_back(blink_underline); + const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) { + std::vector<blink::WebImeTextSpan> ime_text_spans; + for (const auto& ime_text_span : ui_ime_text_spans) { + blink::WebImeTextSpan blink_ime_text_span( + ime_text_span.start_offset, ime_text_span.end_offset, + ime_text_span.color, ime_text_span.thick, + ime_text_span.background_color); + ime_text_spans.push_back(blink_ime_text_span); } SendInput(base::MakeUnique<InputMsg_SetCompositionFromExistingText>( - routing_id_, start, end, underlines)); + routing_id_, start, end, ime_text_spans)); } void LegacyIPCFrameInputHandler::ExtendSelectionAndDelete(int32_t before,
diff --git a/content/browser/frame_host/input/legacy_ipc_frame_input_handler.h b/content/browser/frame_host/input/legacy_ipc_frame_input_handler.h index 7a10e51..c46e6940 100644 --- a/content/browser/frame_host/input/legacy_ipc_frame_input_handler.h +++ b/content/browser/frame_host/input/legacy_ipc_frame_input_handler.h
@@ -24,7 +24,7 @@ void SetCompositionFromExistingText( int32_t start, int32_t end, - const std::vector<ui::CompositionUnderline>& underlines) override; + const std::vector<ui::ImeTextSpan>& ime_text_spans) override; void ExtendSelectionAndDelete(int32_t before, int32_t after) override; void DeleteSurroundingText(int32_t before, int32_t after) override; void DeleteSurroundingTextInCodePoints(int32_t before,
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index c69cae8..e3310940 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -1048,7 +1048,7 @@ set_nav_entry_id(0); if (is_audible_) - GetProcess()->OnAudioStreamRemoved(); + GetProcess()->OnMediaStreamRemoved(); } void RenderFrameHostImpl::ReportContentSecurityPolicyViolation( @@ -1240,9 +1240,9 @@ if (is_audible_ == is_audible) return; if (is_audible) - GetProcess()->OnAudioStreamAdded(); + GetProcess()->OnMediaStreamAdded(); else - GetProcess()->OnAudioStreamRemoved(); + GetProcess()->OnMediaStreamRemoved(); is_audible_ = is_audible; GetFrameResourceCoordinator()->SetProperty(
diff --git a/content/browser/loader/redirect_to_file_resource_handler.cc b/content/browser/loader/redirect_to_file_resource_handler.cc index 3bddfd7..d6acbbc 100644 --- a/content/browser/loader/redirect_to_file_resource_handler.cc +++ b/content/browser/loader/redirect_to_file_resource_handler.cc
@@ -134,11 +134,6 @@ net::URLRequest* request) : LayeredResourceHandler(request, std::move(next_handler)), buf_(new net::GrowableIOBuffer()), - buf_write_pending_(false), - write_cursor_(0), - writer_(NULL), - next_buffer_size_(kInitialReadBufSize), - completed_during_write_(false), weak_factory_(this) {} RedirectToFileResourceHandler::~RedirectToFileResourceHandler() { @@ -158,7 +153,12 @@ void RedirectToFileResourceHandler::OnResponseStarted( ResourceResponse* response, std::unique_ptr<ResourceController> controller) { - DCHECK(writer_); + if (!writer_) { + response_pending_file_creation_ = response; + HoldController(std::move(controller)); + request()->LogBlockedBy("RedirectToFileResourceHandler"); + return; + } response->head.download_file_path = writer_->path(); next_handler_->OnResponseStarted(response, std::move(controller)); } @@ -168,12 +168,7 @@ std::unique_ptr<ResourceController> controller) { DCHECK(!writer_); - // Defer starting the request until we have created the temporary file. - // TODO(darin): This is sub-optimal. We should not delay starting the - // network request like this. - will_start_url_ = url; - HoldController(std::move(controller)); - request()->LogBlockedBy("RedirectToFileResourceHandler"); + // Create the file ASAP but don't block. if (create_temporary_file_stream_.is_null()) { CreateTemporaryFileStream( base::Bind(&RedirectToFileResourceHandler::DidCreateTemporaryFile, @@ -183,6 +178,7 @@ base::Bind(&RedirectToFileResourceHandler::DidCreateTemporaryFile, weak_factory_.GetWeakPtr())); } + next_handler_->OnWillStart(url, std::move(controller)); } void RedirectToFileResourceHandler::OnWillRead( @@ -252,23 +248,30 @@ std::unique_ptr<net::FileStream> file_stream, ShareableFileReference* deletable_file) { DCHECK(!writer_); - DCHECK(has_controller()); if (error_code != base::File::FILE_OK) { - CancelWithError(net::FileErrorToNetError(error_code)); + if (has_controller()) { + CancelWithError(net::FileErrorToNetError(error_code)); + } else { + OutOfBandCancel(net::FileErrorToNetError(error_code), + true /* tell_renderer */); + } return; } writer_ = new Writer(this, std::move(file_stream), deletable_file); - // Resume the request. - request()->LogUnblocked(); - next_handler_->OnWillStart(std::move(will_start_url_), ReleaseController()); + if (response_pending_file_creation_) { + scoped_refptr<ResourceResponse> response = + std::move(response_pending_file_creation_); + request()->LogUnblocked(); + OnResponseStarted(response.get(), ReleaseController()); + } } void RedirectToFileResourceHandler::DidWriteToFile(int result) { bool failed = false; if (result > 0) { - next_handler_->OnDataDownloaded(result); + OnDataDownloaded(result); write_cursor_ += result; // WriteMore will resume the request if the request hasn't completed and // there's more buffer space. @@ -349,7 +352,7 @@ break; if (rv <= 0) return false; - next_handler_->OnDataDownloaded(rv); + OnDataDownloaded(rv); write_cursor_ += rv; }
diff --git a/content/browser/loader/redirect_to_file_resource_handler.h b/content/browser/loader/redirect_to_file_resource_handler.h index 9f642e7..079b3ae 100644 --- a/content/browser/loader/redirect_to_file_resource_handler.h +++ b/content/browser/loader/redirect_to_file_resource_handler.h
@@ -97,6 +97,8 @@ bool BufIsFull() const; + // If populated, OnResponseStarted completion is pending on file creation. + scoped_refptr<ResourceResponse> response_pending_file_creation_; CreateTemporaryFileStreamFunction create_temporary_file_stream_; // We allocate a single, fixed-size IO buffer (buf_) used to read from the @@ -107,24 +109,23 @@ // tracks the offset into buf_ that we are writing to disk. scoped_refptr<net::GrowableIOBuffer> buf_; - bool buf_write_pending_; - int write_cursor_; + bool buf_write_pending_ = false; + int write_cursor_ = 0; // Helper writer object which maintains references to the net::FileStream and // storage::ShareableFileReference. This is maintained separately so that, // on Windows, the temporary file isn't deleted until after it is closed. class Writer; - Writer* writer_; + Writer* writer_ = nullptr; // |next_buffer_size_| is the size of the buffer to be allocated on the next // OnWillRead() call. We exponentially grow the size of the buffer allocated // when our owner fills our buffers. On the first OnWillRead() call, we // allocate a buffer of 32k and double it in OnReadCompleted() if the buffer // was filled, up to a maximum size of 512k. - int next_buffer_size_; + int next_buffer_size_ = kInitialReadBufSize; - bool completed_during_write_; - GURL will_start_url_; + bool completed_during_write_ = false; net::URLRequestStatus completed_status_; base::WeakPtrFactory<RedirectToFileResourceHandler> weak_factory_;
diff --git a/content/browser/loader/redirect_to_file_resource_handler_unittest.cc b/content/browser/loader/redirect_to_file_resource_handler_unittest.cc index aaee16d..e7074444 100644 --- a/content/browser/loader/redirect_to_file_resource_handler_unittest.cc +++ b/content/browser/loader/redirect_to_file_resource_handler_unittest.cc
@@ -275,19 +275,24 @@ create_file_stream_callback_ = create_file_stream_callback; } - // Simulates starting the request, the response starting, and stream creation - // completing with the specified error code. Has |test_handler_| resume the - // request, if needed. Returns final status of |mock_loader_|. - MockResourceLoader::Status StartAndCreateStream(base::File::Error file_error) - WARN_UNUSED_RESULT { - DCHECK(file_stream_); + void PerformOnWillStart() { + MockResourceLoader::Status expected_status; + if (GetParam() == CompletionMode::ASYNC) { + expected_status = MockResourceLoader::Status::CALLBACK_PENDING; + } else { + expected_status = MockResourceLoader::Status::IDLE; + } + EXPECT_EQ(expected_status, mock_loader_->OnWillStart(url_request_->url())); + } - EXPECT_EQ(MockResourceLoader::Status::CALLBACK_PENDING, - mock_loader_->OnWillStart(url_request_->url())); + // Sets up the file stream or error, and performs the file callback. + void PerformCreateFile(base::File::Error file_error) { + DCHECK(file_stream_); file_stream_->set_expect_closed(file_error == base::File::FILE_OK); if (file_error != base::File::FILE_OK) file_stream_ = nullptr; + base::ResetAndReturn(&create_file_stream_callback_) .Run(file_error, std::move(file_stream_), // Not really used by the test, but the ResourceHandler expects it @@ -297,6 +302,18 @@ storage::ShareableFileReference::DELETE_ON_FINAL_RELEASE, base::ThreadTaskRunnerHandle::Get().get()) .get()); + } + + // Simulates starting the request, the response starting, and stream creation + // completing with the specified error code. Has |test_handler_| resume the + // request, if needed. Returns final status of |mock_loader_|. + MockResourceLoader::Status StartAndCreateStream(base::File::Error file_error) + WARN_UNUSED_RESULT { + PerformOnWillStart(); + + // Create the file right away. + PerformCreateFile(file_error); + // If this is an async test, |test_handler_| will defer the OnWillStart // event on success (On error, its OnWillStart method is not called). if (file_error == base::File::FILE_OK && @@ -389,6 +406,67 @@ CompleteRequestSuccessfully(test_data.size()); } +TEST_P(RedirectToFileResourceHandlerTest, SingleBodyReadDelayedFileOnResponse) { + std::string test_data = CreateTestData(kMaxInitialSyncReadSize); + + PerformOnWillStart(); + if (GetParam() == CompletionMode::ASYNC) { + EXPECT_EQ(MockResourceLoader::Status::CALLBACK_PENDING, + mock_loader_->status()); + test_handler_->Resume(); + mock_loader_->WaitUntilIdleOrCanceled(); + } + ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status()); + mock_loader_->OnResponseStarted(make_scoped_refptr(new ResourceResponse())); + ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING, + mock_loader_->status()); + + PerformCreateFile(base::File::FILE_OK); + + if (GetParam() == CompletionMode::ASYNC) { + EXPECT_EQ(MockResourceLoader::Status::CALLBACK_PENDING, + mock_loader_->status()); + test_handler_->Resume(); + mock_loader_->WaitUntilIdleOrCanceled(); + } + EXPECT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status()); + + ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->OnWillRead()); + ASSERT_EQ(MockResourceLoader::Status::IDLE, + mock_loader_->OnReadCompleted(test_data)); + // Wait for the write to complete, in the async case. + base::RunLoop().RunUntilIdle(); + + CompleteRequestSuccessfully(test_data.size()); +} + +TEST_P(RedirectToFileResourceHandlerTest, SingleBodyReadDelayedFileError) { + std::string test_data = CreateTestData(0); + + PerformOnWillStart(); + if (GetParam() == CompletionMode::ASYNC) { + EXPECT_EQ(MockResourceLoader::Status::CALLBACK_PENDING, + mock_loader_->status()); + test_handler_->Resume(); + mock_loader_->WaitUntilIdleOrCanceled(); + } + ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status()); + mock_loader_->OnResponseStarted(make_scoped_refptr(new ResourceResponse())); + ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING, + mock_loader_->status()); + + PerformCreateFile(base::File::FILE_ERROR_FAILED); + + EXPECT_EQ(MockResourceLoader::Status::CANCELED, mock_loader_->status()); + EXPECT_EQ(0, test_handler_->on_response_completed_called()); + EXPECT_EQ(net::ERR_FAILED, mock_loader_->error_code()); + ASSERT_EQ(MockResourceLoader::Status::IDLE, + mock_loader_->OnResponseCompleted( + net::URLRequestStatus::FromError(net::ERR_FAILED))); + EXPECT_FALSE(test_handler_->final_status().is_success()); + EXPECT_EQ(net::ERR_FAILED, test_handler_->final_status().error()); +} + TEST_P(RedirectToFileResourceHandlerTest, ManySequentialBodyReads) { const size_t kBytesPerRead = 128; std::string test_data = @@ -757,9 +835,17 @@ EXPECT_EQ(0, test_handler_->on_response_completed_called()); EXPECT_EQ(net::ERR_FAILED, mock_loader_->error_code()); - ASSERT_EQ(MockResourceLoader::Status::IDLE, - mock_loader_->OnResponseCompleted( - net::URLRequestStatus::FromError(net::ERR_FAILED))); + if (GetParam() == CompletionMode::ASYNC) { + EXPECT_EQ(MockResourceLoader::Status::CANCELED, mock_loader_->status()); + ASSERT_EQ(MockResourceLoader::Status::IDLE, + mock_loader_->OnResponseCompletedFromExternalOutOfBandCancel( + net::URLRequestStatus::FromError(net::ERR_FAILED))); + } else { + ASSERT_EQ(MockResourceLoader::Status::IDLE, + mock_loader_->OnResponseCompleted( + net::URLRequestStatus::FromError(net::ERR_FAILED))); + } + EXPECT_EQ(0, test_handler_->total_bytes_downloaded()); EXPECT_FALSE(test_handler_->final_status().is_success()); EXPECT_EQ(net::ERR_FAILED, test_handler_->final_status().error());
diff --git a/content/browser/media/media_browsertest.cc b/content/browser/media/media_browsertest.cc index 1345092..239bfb2 100644 --- a/content/browser/media/media_browsertest.cc +++ b/content/browser/media/media_browsertest.cc
@@ -241,15 +241,6 @@ IN_PROC_BROWSER_TEST_F(MediaTest, VideoBearRotated270) { RunVideoSizeTest("bear_rotate_270.mp4", 720, 1280); } - -// Android can't reliably load lots of videos on a page. -// See http://crbug.com/749265 -#if !defined(OS_ANDROID) -IN_PROC_BROWSER_TEST_F(MediaTest, LoadManyVideos) { - base::StringPairs query_params; - RunMediaTestPage("load_many_videos.html", query_params, kEnded, true); -} -#endif // !defined(OS_ANDROID) #endif // BUILDFLAG(USE_PROPRIETARY_CODECS) #if defined(OS_CHROMEOS)
diff --git a/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.cc b/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.cc index 12f039c..282843f 100644 --- a/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.cc +++ b/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.cc
@@ -13,15 +13,16 @@ namespace content { namespace { -std::vector<blink::WebCompositionUnderline> ConvertToBlinkUnderline( - const std::vector<ui::CompositionUnderline>& ui_underlines) { - std::vector<blink::WebCompositionUnderline> underlines; - for (const auto& underline : ui_underlines) { - underlines.emplace_back(blink::WebCompositionUnderline( - underline.start_offset, underline.end_offset, underline.color, - underline.thick, underline.background_color)); +std::vector<blink::WebImeTextSpan> ConvertToBlinkImeTextSpan( + const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) { + std::vector<blink::WebImeTextSpan> ime_text_spans; + for (const auto& ime_text_span : ui_ime_text_spans) { + ime_text_spans.emplace_back(blink::WebImeTextSpan( + ime_text_span.start_offset, ime_text_span.end_offset, + ime_text_span.color, ime_text_span.thick, + ime_text_span.background_color)); } - return underlines; + return ime_text_spans; } } // namespace @@ -29,7 +30,6 @@ LegacyIPCWidgetInputHandler::LegacyIPCWidgetInputHandler( LegacyInputRouterImpl* input_router) : input_router_(input_router) {} - LegacyIPCWidgetInputHandler::~LegacyIPCWidgetInputHandler() {} void LegacyIPCWidgetInputHandler::SetFocus(bool focused) { @@ -52,25 +52,25 @@ void LegacyIPCWidgetInputHandler::ImeSetComposition( const base::string16& text, - const std::vector<ui::CompositionUnderline>& ui_underlines, + const std::vector<ui::ImeTextSpan>& ui_ime_text_spans, const gfx::Range& range, int32_t start, int32_t end) { - std::vector<blink::WebCompositionUnderline> underlines = - ConvertToBlinkUnderline(ui_underlines); + std::vector<blink::WebImeTextSpan> ime_text_spans = + ConvertToBlinkImeTextSpan(ui_ime_text_spans); SendInput(base::MakeUnique<InputMsg_ImeSetComposition>( - input_router_->routing_id(), text, underlines, range, start, end)); + input_router_->routing_id(), text, ime_text_spans, range, start, end)); } void LegacyIPCWidgetInputHandler::ImeCommitText( const base::string16& text, - const std::vector<ui::CompositionUnderline>& ui_underlines, + const std::vector<ui::ImeTextSpan>& ui_ime_text_spans, const gfx::Range& range, int32_t relative_cursor_position) { - std::vector<blink::WebCompositionUnderline> underlines = - ConvertToBlinkUnderline(ui_underlines); + std::vector<blink::WebImeTextSpan> ime_text_spans = + ConvertToBlinkImeTextSpan(ui_ime_text_spans); SendInput(base::MakeUnique<InputMsg_ImeCommitText>( - input_router_->routing_id(), text, underlines, range, + input_router_->routing_id(), text, ime_text_spans, range, relative_cursor_position)); }
diff --git a/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.h b/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.h index 9bc8f0c..7bfd9e7 100644 --- a/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.h +++ b/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.h
@@ -27,14 +27,13 @@ void SetEditCommandsForNextKeyEvent( const std::vector<EditCommand>& commands) override; void CursorVisibilityChanged(bool visible) override; - void ImeSetComposition( - const base::string16& text, - const std::vector<ui::CompositionUnderline>& underlines, - const gfx::Range& range, - int32_t start, - int32_t end) override; + void ImeSetComposition(const base::string16& text, + const std::vector<ui::ImeTextSpan>& ime_text_spans, + const gfx::Range& range, + int32_t start, + int32_t end) override; void ImeCommitText(const base::string16& text, - const std::vector<ui::CompositionUnderline>& underlines, + const std::vector<ui::ImeTextSpan>& ime_text_spans, const gfx::Range& range, int32_t relative_cursor_position) override; void ImeFinishComposingText(bool keep_selection) override;
diff --git a/content/browser/renderer_host/input/mock_widget_input_handler.cc b/content/browser/renderer_host/input/mock_widget_input_handler.cc index df93838..5e9c0f7 100644 --- a/content/browser/renderer_host/input/mock_widget_input_handler.cc +++ b/content/browser/renderer_host/input/mock_widget_input_handler.cc
@@ -32,14 +32,14 @@ void MockWidgetInputHandler::ImeSetComposition( const base::string16& text, - const std::vector<ui::CompositionUnderline>& underlines, + const std::vector<ui::ImeTextSpan>& ime_text_spans, const gfx::Range& range, int32_t start, int32_t end) {} void MockWidgetInputHandler::ImeCommitText( const base::string16& text, - const std::vector<ui::CompositionUnderline>& underlines, + const std::vector<ui::ImeTextSpan>& ime_text_spans, const gfx::Range& range, int32_t relative_cursor_position) {}
diff --git a/content/browser/renderer_host/input/mock_widget_input_handler.h b/content/browser/renderer_host/input/mock_widget_input_handler.h index 8eb481b..adae4d3 100644 --- a/content/browser/renderer_host/input/mock_widget_input_handler.h +++ b/content/browser/renderer_host/input/mock_widget_input_handler.h
@@ -36,14 +36,13 @@ void SetEditCommandsForNextKeyEvent( const std::vector<content::EditCommand>& commands) override; void CursorVisibilityChanged(bool visible) override; - void ImeSetComposition( - const base::string16& text, - const std::vector<ui::CompositionUnderline>& underlines, - const gfx::Range& range, - int32_t start, - int32_t end) override; + void ImeSetComposition(const base::string16& text, + const std::vector<ui::ImeTextSpan>& ime_text_spans, + const gfx::Range& range, + int32_t start, + int32_t end) override; void ImeCommitText(const base::string16& text, - const std::vector<ui::CompositionUnderline>& underlines, + const std::vector<ui::ImeTextSpan>& ime_text_spans, const gfx::Range& range, int32_t relative_cursor_position) override; void ImeFinishComposingText(bool keep_selection) override;
diff --git a/content/browser/renderer_host/media/audio_input_device_manager.cc b/content/browser/renderer_host/media/audio_input_device_manager.cc index 876e113..581e2b1 100644 --- a/content/browser/renderer_host/media/audio_input_device_manager.cc +++ b/content/browser/renderer_host/media/audio_input_device_manager.cc
@@ -168,25 +168,13 @@ UMA_HISTOGRAM_TIMES("Media.AudioInputDeviceManager.OpenOnDeviceThreadTime", base::TimeTicks::Now() - start_time); - media::AudioParameters valid_input_params = - input_params.IsValid() - ? input_params - : media::AudioParameters::UnavailableDeviceParams(); - StreamDeviceInfo info(device.type, device.name, device.id); info.session_id = session_id; - info.device.input.sample_rate = valid_input_params.sample_rate(); - info.device.input.channel_layout = valid_input_params.channel_layout(); - info.device.input.frames_per_buffer = valid_input_params.frames_per_buffer(); - info.device.input.effects = valid_input_params.effects(); - info.device.input.mic_positions = valid_input_params.mic_positions(); + info.device.input = input_params.IsValid() + ? input_params + : media::AudioParameters::UnavailableDeviceParams(); info.device.matched_output_device_id = matched_output_device_id; - info.device.matched_output.sample_rate = matched_output_params.sample_rate(); - info.device.matched_output.channel_layout = - matched_output_params.channel_layout(); - info.device.matched_output.frames_per_buffer = - matched_output_params.frames_per_buffer(); - info.device.matched_output.effects = matched_output_params.effects(); + info.device.matched_output = matched_output_params; devices_.push_back(info);
diff --git a/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc b/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc index cfb976b..e0ce863 100644 --- a/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc +++ b/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
@@ -343,10 +343,9 @@ manager_->GetOpenedDeviceInfoById(session_id); EXPECT_TRUE( media::AudioParameters(media::AudioParameters::AUDIO_FAKE, - static_cast<media::ChannelLayout>( - device_info->device.input.channel_layout), - device_info->device.input.sample_rate, 16, - device_info->device.input.frames_per_buffer) + device_info->device.input.channel_layout(), + device_info->device.input.sample_rate(), 16, + device_info->device.input.frames_per_buffer()) .IsValid()); manager_->Close(session_id);
diff --git a/content/browser/renderer_host/media/audio_output_authorization_handler.cc b/content/browser/renderer_host/media/audio_output_authorization_handler.cc index 9bdfbc9..b19c9978 100644 --- a/content/browser/renderer_host/media/audio_output_authorization_handler.cc +++ b/content/browser/renderer_host/media/audio_output_authorization_handler.cc
@@ -131,11 +131,10 @@ if (info && !info->device.matched_output_device_id.empty()) { media::AudioParameters params( media::AudioParameters::AUDIO_PCM_LOW_LATENCY, - static_cast<media::ChannelLayout>( - info->device.matched_output.channel_layout), - info->device.matched_output.sample_rate, 16, - info->device.matched_output.frames_per_buffer); - params.set_effects(info->device.matched_output.effects); + info->device.matched_output.channel_layout(), + info->device.matched_output.sample_rate(), 16, + info->device.matched_output.frames_per_buffer()); + params.set_effects(info->device.matched_output.effects()); // We don't need the origin for authorization in this case, but it's used // for hashing the device id before sending it back to the renderer.
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc index 661136c6..6f353fa3 100644 --- a/content/browser/renderer_host/media/media_stream_manager.cc +++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -1175,10 +1175,10 @@ *existing_device_info = device_info; // Make sure that the audio |effects| reflect what the request // is set to and not what the capabilities are. - FilterAudioEffects(request->controls, - &existing_device_info->device.input.effects); - EnableHotwordEffect(request->controls, - &existing_device_info->device.input.effects); + int effects = existing_device_info->device.input.effects(); + FilterAudioEffects(request->controls, &effects); + EnableHotwordEffect(request->controls, &effects); + existing_device_info->device.input.set_effects(effects); *existing_request_state = request->state(device_info.device.type); return true; } @@ -1308,6 +1308,7 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); DVLOG(1) << "Opened({stream_type = " << stream_type << "} " << "{capture_session_id = " << capture_session_id << "})"; + // Find the request(s) containing this device and mark it as used. // It can be used in several requests since the same device can be // requested from the same web page. @@ -1336,10 +1337,10 @@ // parameters to the default settings (including supported effects), // we need to adjust those settings here according to what the // request asks for. - FilterAudioEffects(request->controls, - &device_info.device.input.effects); - EnableHotwordEffect(request->controls, - &device_info.device.input.effects); + int effects = device_info.device.input.effects(); + FilterAudioEffects(request->controls, &effects); + EnableHotwordEffect(request->controls, &effects); + device_info.device.input.set_effects(effects); device_info.device.matched_output = info->device.matched_output; } @@ -1504,8 +1505,13 @@ if (sample_rate <= 0 || sample_rate > 96000) sample_rate = 44100; - device_info.device.input.sample_rate = sample_rate; - device_info.device.input.channel_layout = media::CHANNEL_LAYOUT_STEREO; + media::AudioParameters params( + device_info.device.input.format(), media::CHANNEL_LAYOUT_STEREO, + sample_rate, device_info.device.input.bits_per_sample(), + device_info.device.input.frames_per_buffer()); + params.set_effects(device_info.device.input.effects()); + params.set_mic_positions(device_info.device.input.mic_positions()); + device_info.device.input = params; } if (device_info.device.type == request->audio_type())
diff --git a/content/browser/renderer_host/media/video_capture_host.cc b/content/browser/renderer_host/media/video_capture_host.cc index 9c1a673f..d9a2b4e 100644 --- a/content/browser/renderer_host/media/video_capture_host.cc +++ b/content/browser/renderer_host/media/video_capture_host.cc
@@ -12,27 +12,78 @@ #include "content/browser/browser_main_loop.h" #include "content/browser/renderer_host/media/media_stream_manager.h" #include "content/browser/renderer_host/media/video_capture_manager.h" +#include "content/public/browser/render_process_host.h" #include "mojo/common/values_struct_traits.h" #include "mojo/public/cpp/bindings/strong_binding.h" namespace content { -VideoCaptureHost::VideoCaptureHost(MediaStreamManager* media_stream_manager) - : media_stream_manager_(media_stream_manager), +// Helper class that does all the work of notifying RenderProcessHost instance +// about active video capture stream changes. It should be called and destroyed +// on UI thread. +class VideoCaptureHost::RenderProcessHostDelegate { + public: + explicit RenderProcessHostDelegate(int render_process_id) + : render_process_id_(render_process_id) {} + + ~RenderProcessHostDelegate() { DCHECK_CURRENTLY_ON(BrowserThread::UI); } + + // Helper functions that are used for notifying Browser-side RenderProcessHost + // if renderer is currently consuming video capture. This information is then + // used to determine if the renderer process should be backgrounded or not. + void NotifyStreamAdded() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + ++number_of_active_streams_; + RenderProcessHost* host = RenderProcessHost::FromID(render_process_id_); + if (host) + host->OnMediaStreamAdded(); + } + + void NotifyStreamRemoved() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + // DoError() from camera side failure can be followed by Stop() from JS + // side, so we should check before going to negative. + // TODO(emircan): Investigate all edge cases and add more browsertests. + // https://crbug.com/754765 + if (number_of_active_streams_ == 0) + return; + --number_of_active_streams_; + RenderProcessHost* host = RenderProcessHost::FromID(render_process_id_); + if (host) + host->OnMediaStreamRemoved(); + } + + void NotifyAllStreamsRemoved() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + for (uint32_t i = 0; i < number_of_active_streams_; ++i) + NotifyStreamRemoved(); + } + + private: + const int render_process_id_; + uint32_t number_of_active_streams_ = 0; + DISALLOW_COPY_AND_ASSIGN(RenderProcessHostDelegate); +}; + +VideoCaptureHost::VideoCaptureHost(int render_process_id, + MediaStreamManager* media_stream_manager) + : render_process_host_delegate_( + new RenderProcessHostDelegate(render_process_id)), + media_stream_manager_(media_stream_manager), weak_factory_(this) { DVLOG(1) << __func__; DCHECK_CURRENTLY_ON(BrowserThread::IO); } // static -void VideoCaptureHost::Create( - MediaStreamManager* media_stream_manager, - mojom::VideoCaptureHostRequest request) { +void VideoCaptureHost::Create(int render_process_id, + MediaStreamManager* media_stream_manager, + mojom::VideoCaptureHostRequest request) { DVLOG(1) << __func__; DCHECK_CURRENTLY_ON(BrowserThread::IO); - mojo::MakeStrongBinding( - base::MakeUnique<VideoCaptureHost>(media_stream_manager), - std::move(request)); + mojo::MakeStrongBinding(base::MakeUnique<VideoCaptureHost>( + render_process_id, media_stream_manager), + std::move(request)); } VideoCaptureHost::~VideoCaptureHost() { @@ -50,6 +101,15 @@ controllers_.erase(it++); } } + + // base::Unretained() usage is safe because |render_process_host_delegate_| is + // destroyed on UI thread. + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&RenderProcessHostDelegate::NotifyAllStreamsRemoved, + base::Unretained(render_process_host_delegate_.get()))); + BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, + render_process_host_delegate_.release()); } void VideoCaptureHost::OnError(VideoCaptureControllerID controller_id) { @@ -118,6 +178,12 @@ if (base::ContainsKey(device_id_to_observer_map_, controller_id)) { device_id_to_observer_map_[controller_id]->OnStateChanged( mojom::VideoCaptureState::STARTED); + // base::Unretained() usage is safe because |render_process_host_delegate_| + // is destroyed on UI thread. + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&RenderProcessHostDelegate::NotifyStreamAdded, + base::Unretained(render_process_host_delegate_.get()))); } } @@ -139,6 +205,12 @@ if (controllers_.find(controller_id) != controllers_.end()) { device_id_to_observer_map_[device_id]->OnStateChanged( mojom::VideoCaptureState::STARTED); + // base::Unretained() usage is safe because |render_process_host_delegate_| + // is destroyed on UI thread. + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&RenderProcessHostDelegate::NotifyStreamAdded, + base::Unretained(render_process_host_delegate_.get()))); return; } @@ -162,6 +234,12 @@ device_id_to_observer_map_.erase(controller_id); DeleteVideoCaptureController(controller_id, false); + // base::Unretained() usage is safe because |render_process_host_delegate_| is + // destroyed on UI thread. + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&RenderProcessHostDelegate::NotifyStreamRemoved, + base::Unretained(render_process_host_delegate_.get()))); } void VideoCaptureHost::Pause(int32_t device_id) { @@ -272,6 +350,12 @@ } DeleteVideoCaptureController(controller_id, true); + // base::Unretained() usage is safe because |render_process_host_delegate_| is + // destroyed on UI thread. + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&RenderProcessHostDelegate::NotifyStreamRemoved, + base::Unretained(render_process_host_delegate_.get()))); } void VideoCaptureHost::DoEnded(VideoCaptureControllerID controller_id) { @@ -286,6 +370,12 @@ } DeleteVideoCaptureController(controller_id, false); + // base::Unretained() usage is safe because |render_process_host_delegate_| is + // destroyed on UI thread. + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&RenderProcessHostDelegate::NotifyStreamRemoved, + base::Unretained(render_process_host_delegate_.get()))); } void VideoCaptureHost::OnControllerAdded(
diff --git a/content/browser/renderer_host/media/video_capture_host.h b/content/browser/renderer_host/media/video_capture_host.h index 9669c35..d9ad77c 100644 --- a/content/browser/renderer_host/media/video_capture_host.h +++ b/content/browser/renderer_host/media/video_capture_host.h
@@ -28,9 +28,11 @@ : public VideoCaptureControllerEventHandler, public mojom::VideoCaptureHost { public: - explicit VideoCaptureHost(MediaStreamManager* media_stream_manager); + VideoCaptureHost(int render_process_id, + MediaStreamManager* media_stream_manager); - static void Create(MediaStreamManager* media_stream_manager, + static void Create(int render_process_id, + MediaStreamManager* media_stream_manager, mojom::VideoCaptureHostRequest request); ~VideoCaptureHost() override; @@ -90,6 +92,9 @@ void DeleteVideoCaptureController(VideoCaptureControllerID controller_id, bool on_error); + class RenderProcessHostDelegate; + std::unique_ptr<RenderProcessHostDelegate> render_process_host_delegate_; + MediaStreamManager* const media_stream_manager_; // A map of VideoCaptureControllerID to the VideoCaptureController to which it
diff --git a/content/browser/renderer_host/media/video_capture_unittest.cc b/content/browser/renderer_host/media/video_capture_unittest.cc index c2060af0..f87d522 100644 --- a/content/browser/renderer_host/media/video_capture_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_unittest.cc
@@ -134,7 +134,8 @@ base::MakeUnique<MediaStreamManager>(audio_system_.get()); // Create a Host and connect it to a simulated IPC channel. - host_.reset(new VideoCaptureHost(media_stream_manager_.get())); + host_.reset(new VideoCaptureHost(0 /* render_process_id */, + media_stream_manager_.get())); OpenSession(); }
diff --git a/content/browser/renderer_host/render_process_host_browsertest.cc b/content/browser/renderer_host/render_process_host_browsertest.cc index 4358501..019a08c 100644 --- a/content/browser/renderer_host/render_process_host_browsertest.cc +++ b/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -14,7 +14,9 @@ #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_process_host_observer.h" #include "content/public/browser/web_contents.h" +#include "content/public/common/content_switches.h" #include "content/public/common/url_constants.h" +#include "content/public/test/browser_test_utils.h" #include "content/public/test/content_browser_test.h" #include "content/public/test/content_browser_test_utils.h" #include "content/public/test/test_service.mojom.h" @@ -55,6 +57,10 @@ void SetUpCommandLine(base::CommandLine* command_line) override { command_line->AppendSwitch(switches::kIgnoreAutoplayRestrictionsForTests); + // These flags are necessary to emulate camera input for getUserMedia() + // tests. + command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream); + command_line->AppendSwitch(switches::kUseFakeUIForMediaStream); } protected: @@ -474,7 +480,7 @@ run_loop.Run(); // No point in running the rest of the test if this is wrong. - ASSERT_EQ(1, rph->get_audio_stream_count_for_testing()); + ASSERT_EQ(1, rph->get_media_stream_count_for_testing()); } host_destructions_ = 0; @@ -505,7 +511,85 @@ } // Verify shutdown went as expected. - EXPECT_EQ(0, rph->get_audio_stream_count_for_testing()); + EXPECT_EQ(0, rph->get_media_stream_count_for_testing()); + EXPECT_EQ(1, process_exits_); + EXPECT_EQ(0, host_destructions_); + if (!host_destructions_) + rph->RemoveObserver(this); +} + +// Tests that video capture stream count increments when getUserMedia() is +// called. +IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, + GetUserMediaIncrementsVideoCaptureStreams) { + ASSERT_TRUE(embedded_test_server()->Start()); + NavigateToURL(shell(), + embedded_test_server()->GetURL("/media/getusermedia.html")); + RenderProcessHostImpl* rph = static_cast<RenderProcessHostImpl*>( + shell()->web_contents()->GetMainFrame()->GetProcess()); + std::string result; + EXPECT_TRUE(ExecuteScriptAndExtractString( + shell(), "getUserMediaAndExpectSuccess({video: true});", &result)) + << "Failed to execute javascript."; + EXPECT_EQ(1, rph->get_media_stream_count_for_testing()); +} + +// Tests that video capture stream count resets when getUserMedia() is called +// and stopped. +IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, StopResetsVideoCaptureStreams) { + ASSERT_TRUE(embedded_test_server()->Start()); + NavigateToURL(shell(), + embedded_test_server()->GetURL("/media/getusermedia.html")); + RenderProcessHostImpl* rph = static_cast<RenderProcessHostImpl*>( + shell()->web_contents()->GetMainFrame()->GetProcess()); + std::string result; + EXPECT_TRUE(ExecuteScriptAndExtractString( + shell(), "getUserMediaAndStop({video: true});", &result)) + << "Failed to execute javascript."; + EXPECT_EQ(0, rph->get_media_stream_count_for_testing()); +} + +// Tests that video capture stream counts (used for process priority +// calculations) are properly set and cleared during media playback and renderer +// terminations. +IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, + KillProcessZerosVideoCaptureStreams) { + ASSERT_TRUE(embedded_test_server()->Start()); + NavigateToURL(shell(), + embedded_test_server()->GetURL("/media/getusermedia.html")); + RenderProcessHostImpl* rph = static_cast<RenderProcessHostImpl*>( + shell()->web_contents()->GetMainFrame()->GetProcess()); + std::string result; + EXPECT_TRUE(ExecuteScriptAndExtractString( + shell(), "getUserMediaAndExpectSuccess({video: true});", &result)) + << "Failed to execute javascript."; + EXPECT_EQ(1, rph->get_media_stream_count_for_testing()); + + host_destructions_ = 0; + process_exits_ = 0; + rph->AddObserver(this); + + mojom::TestServicePtr service; + BindInterface(rph, &service); + + { + // Force a bad message event to occur which will terminate the renderer. + base::RunLoop run_loop; + set_process_exit_callback(media::BindToCurrentLoop(run_loop.QuitClosure())); + service->DoSomething(base::Bind(&base::DoNothing)); + run_loop.Run(); + } + + { + // Cycle UI and IO loop once to ensure OnChannelClosing() has been delivered + // to audio stream owners and they get a chance to notify of stream closure. + base::RunLoop run_loop; + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, + media::BindToCurrentLoop(run_loop.QuitClosure())); + run_loop.Run(); + } + + EXPECT_EQ(0, rph->get_media_stream_count_for_testing()); EXPECT_EQ(1, process_exits_); EXPECT_EQ(0, host_destructions_); if (!host_destructions_)
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 503f889..5622f6b 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -803,6 +803,12 @@ // sites are hosted by a RenderProcessHost. This class is meant to help reusing // RenderProcessHosts among SiteInstances, not to perform security checks for a // RenderProcessHost. +// +// TODO(alexmos): Currently, the tracking in this class and in +// UnmatchedServiceWorkerProcessTracker is associated with a BrowserContext, +// but it needs to also consider StoragePartitions, so that process reuse is +// allowed only within the same StoragePartition. For now, the tracking is +// done only for the default StoragePartition. See https://crbug.com/752667. const void* const kCommittedSiteProcessCountTrackerKey = "CommittedSiteProcessCountTrackerKey"; const void* const kPendingSiteProcessCountTrackerKey = @@ -898,6 +904,37 @@ CountPerProcessPerSiteMap map_; }; +bool ShouldUseSiteProcessTracking(BrowserContext* browser_context, + StoragePartition* dest_partition, + const GURL& site_url) { + if (site_url.is_empty()) + return false; + + // TODO(alexmos): Sites should be tracked separately for each + // StoragePartition. For now, track them only in the default one. + StoragePartition* default_partition = + BrowserContext::GetDefaultStoragePartition(browser_context); + if (dest_partition != default_partition) + return false; + + return true; +} + +bool ShouldTrackProcessForSite(BrowserContext* browser_context, + RenderProcessHost* render_process_host, + const GURL& site_url) { + return ShouldUseSiteProcessTracking( + browser_context, render_process_host->GetStoragePartition(), site_url); +} + +bool ShouldFindReusableProcessHostForSite(BrowserContext* browser_context, + const GURL& site_url) { + return ShouldUseSiteProcessTracking( + browser_context, + BrowserContext::GetStoragePartitionForSite(browser_context, site_url), + site_url); +} + const void* const kUnmatchedServiceWorkerProcessTrackerKey = "UnmatchedServiceWorkerProcessTrackerKey"; @@ -910,6 +947,12 @@ // processes are reused for a navigation to a matching site. After a single // matching navigation is put into the process, all service workers for that // site in that process are considered 'matched.' +// +// TODO(alexmos): Currently, the tracking in this class and in +// SiteProcessCountTracker is associated with a BrowserContext, but it needs to +// also consider StoragePartitions, so that process reuse is allowed only +// within the same StoragePartition. For now, the tracking is done only for +// the default StoragePartition. See https://crbug.com/752667. class UnmatchedServiceWorkerProcessTracker : public base::SupportsUserData::Data, public RenderProcessHostObserver { @@ -920,6 +963,10 @@ RenderProcessHost* render_process_host, const GURL& site_url) { DCHECK(!site_url.is_empty()); + if (!ShouldTrackProcessForSite(browser_context, render_process_host, + site_url)) + return; + UnmatchedServiceWorkerProcessTracker* tracker = static_cast<UnmatchedServiceWorkerProcessTracker*>( browser_context->GetUserData( @@ -936,8 +983,9 @@ // the process from the tracker if it exists. static RenderProcessHost* MatchWithSite(BrowserContext* browser_context, const GURL& site_url) { - if (site_url.is_empty()) + if (!ShouldFindReusableProcessHostForSite(browser_context, site_url)) return nullptr; + UnmatchedServiceWorkerProcessTracker* tracker = static_cast<UnmatchedServiceWorkerProcessTracker*>( browser_context->GetUserData( @@ -1866,7 +1914,7 @@ base::Unretained(this))); registry->AddInterface( - base::Bind(&VideoCaptureHost::Create, + base::Bind(&VideoCaptureHost::Create, GetID(), BrowserMainLoop::GetInstance()->media_stream_manager())); registry->AddInterface( @@ -1986,7 +2034,7 @@ } void RenderProcessHostImpl::BindSharedBitmapAllocationNotifier( - cc::mojom::SharedBitmapAllocationNotifierRequest request) { + viz::mojom::SharedBitmapAllocationNotifierRequest request) { shared_bitmap_allocation_notifier_impl_.Bind(std::move(request)); } @@ -2240,14 +2288,14 @@ return audio_output_stream_factory_context_.get(); } -void RenderProcessHostImpl::OnAudioStreamAdded() { - ++audio_stream_count_; +void RenderProcessHostImpl::OnMediaStreamAdded() { + ++media_stream_count_; UpdateProcessPriority(); } -void RenderProcessHostImpl::OnAudioStreamRemoved() { - DCHECK_GT(audio_stream_count_, 0); - --audio_stream_count_; +void RenderProcessHostImpl::OnMediaStreamRemoved() { + DCHECK_GT(media_stream_count_, 0); + --media_stream_count_; UpdateProcessPriority(); } @@ -2261,7 +2309,8 @@ BrowserContext* browser_context, RenderProcessHost* render_process_host, const GURL& site_url) { - if (site_url.is_empty()) + if (!ShouldTrackProcessForSite(browser_context, render_process_host, + site_url)) return; SiteProcessCountTracker* tracker = static_cast<SiteProcessCountTracker*>( @@ -2279,7 +2328,8 @@ BrowserContext* browser_context, RenderProcessHost* render_process_host, const GURL& site_url) { - if (site_url.is_empty()) + if (!ShouldTrackProcessForSite(browser_context, render_process_host, + site_url)) return; SiteProcessCountTracker* tracker = static_cast<SiteProcessCountTracker*>( @@ -2297,7 +2347,8 @@ BrowserContext* browser_context, RenderProcessHost* render_process_host, const GURL& site_url) { - if (site_url.is_empty()) + if (!ShouldTrackProcessForSite(browser_context, render_process_host, + site_url)) return; SiteProcessCountTracker* tracker = static_cast<SiteProcessCountTracker*>( @@ -2315,7 +2366,8 @@ BrowserContext* browser_context, RenderProcessHost* render_process_host, const GURL& site_url) { - if (site_url.is_empty()) + if (!ShouldTrackProcessForSite(browser_context, render_process_host, + site_url)) return; SiteProcessCountTracker* tracker = static_cast<SiteProcessCountTracker*>( @@ -3707,11 +3759,11 @@ return; } - // We background a process as soon as it hosts no active audio streams and no - // visible widgets -- the callers must call this function whenever we + // We background a process as soon as it hosts no active audio/video streams + // and no visible widgets -- the callers must call this function whenever we // transition in/out of those states. const bool should_background = - visible_widgets_ == 0 && audio_stream_count_ == 0 && + visible_widgets_ == 0 && media_stream_count_ == 0 && !base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableRendererBackgrounding); const bool should_background_changed = @@ -3889,7 +3941,7 @@ RenderProcessHost* RenderProcessHostImpl::FindReusableProcessHostForSite( BrowserContext* browser_context, const GURL& site_url) { - if (site_url.is_empty()) + if (!ShouldFindReusableProcessHostForSite(browser_context, site_url)) return nullptr; std::set<RenderProcessHost*> eligible_foreground_hosts;
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h index ede5f06..ddadb7f 100644 --- a/content/browser/renderer_host/render_process_host_impl.h +++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -334,11 +334,11 @@ RendererAudioOutputStreamFactoryContext* GetRendererAudioOutputStreamFactoryContext() override; - // Called when an audio stream is added or removed and used to determine if - // the process should be backgrounded or not. - void OnAudioStreamAdded() override; - void OnAudioStreamRemoved() override; - int get_audio_stream_count_for_testing() const { return audio_stream_count_; } + // Called when a video capture stream or an audio stream is added or removed + // and used to determine if the process should be backgrounded or not. + void OnMediaStreamAdded() override; + void OnMediaStreamRemoved() override; + int get_media_stream_count_for_testing() const { return media_stream_count_; } // Sets the global factory used to create new RenderProcessHosts. It may be // nullptr, in which case the default RenderProcessHost will be created (this @@ -439,7 +439,7 @@ blink::mojom::OffscreenCanvasProviderRequest request); void BindFrameSinkProvider(mojom::FrameSinkProviderRequest request); void BindSharedBitmapAllocationNotifier( - cc::mojom::SharedBitmapAllocationNotifierRequest request); + viz::mojom::SharedBitmapAllocationNotifierRequest request); void CreateStoragePartitionService( mojom::StoragePartitionServiceRequest request); void CreateRendererHost(mojom::RendererHostRequest request); @@ -738,9 +738,9 @@ mojom::RendererAssociatedPtr renderer_interface_; mojo::Binding<mojom::RendererHost> renderer_host_binding_; - // Tracks active audio streams within the render process; used to determine if - // if a process should be backgrounded. - int audio_stream_count_ = 0; + // Tracks active audio and video streams within the render process; used to + // determine if if a process should be backgrounded. + int media_stream_count_ = 0; std::unique_ptr<resource_coordinator::ResourceCoordinatorInterface> process_resource_coordinator_;
diff --git a/content/browser/renderer_host/render_process_host_unittest.cc b/content/browser/renderer_host/render_process_host_unittest.cc index c5db4da..7952100 100644 --- a/content/browser/renderer_host/render_process_host_unittest.cc +++ b/content/browser/renderer_host/render_process_host_unittest.cc
@@ -754,6 +754,97 @@ EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess()); } +// Helper test class to modify the StoragePartition returned for a particular +// site URL. +class StoragePartitionContentBrowserClient : public ContentBrowserClient { + public: + StoragePartitionContentBrowserClient(const GURL& site, + const std::string& partition_domain, + const std::string& partition_name) + : site_(site), + partition_domain_(partition_domain), + partition_name_(partition_name) {} + ~StoragePartitionContentBrowserClient() override {} + + private: + void GetStoragePartitionConfigForSite(BrowserContext* browser_context, + const GURL& site, + bool can_be_default, + std::string* partition_domain, + std::string* partition_name, + bool* in_memory) override { + partition_domain->clear(); + partition_name->clear(); + *in_memory = false; + + if (site == site_) { + *partition_domain = partition_domain_; + *partition_name = partition_name_; + } + } + + GURL site_; + std::string partition_domain_; + std::string partition_name_; +}; + +// Check that a SiteInstance cannot reuse a RenderProcessHost in a different +// StoragePartition. +TEST_F(RenderProcessHostUnitTest, + DoNotReuseProcessInDifferentStoragePartition) { + const GURL kUrl("https://foo.com"); + NavigateAndCommit(kUrl); + + // Change foo.com SiteInstances to use a different StoragePartition. + StoragePartitionContentBrowserClient modified_client(kUrl, "foo_domain", + "foo_name"); + ContentBrowserClient* regular_client = + SetBrowserClientForTesting(&modified_client); + + // Create a foo.com SiteInstance and check that its process does not + // reuse the foo process from the first navigation, since it's now in a + // different StoragePartiiton. + scoped_refptr<SiteInstanceImpl> site_instance = + SiteInstanceImpl::CreateForURL(browser_context(), kUrl); + site_instance->set_process_reuse_policy( + SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE); + RenderProcessHost* process = site_instance->GetProcess(); + EXPECT_NE(main_test_rfh()->GetProcess(), process); + + SetBrowserClientForTesting(regular_client); +} + +// Check that a SiteInstance cannot reuse a ServiceWorker process in a +// different StoragePartition. +TEST_F(RenderProcessHostUnitTest, + DoNotReuseServiceWorkerProcessInDifferentStoragePartition) { + const GURL kUrl("https://foo.com"); + + // Create a RenderProcessHost for a service worker. + scoped_refptr<SiteInstanceImpl> sw_site_instance = + SiteInstanceImpl::CreateForURL(browser_context(), kUrl); + sw_site_instance->set_is_for_service_worker(); + RenderProcessHost* sw_process = sw_site_instance->GetProcess(); + + // Change foo.com SiteInstances to use a different StoragePartition. + StoragePartitionContentBrowserClient modified_client(kUrl, "foo_domain", + "foo_name"); + ContentBrowserClient* regular_client = + SetBrowserClientForTesting(&modified_client); + + // Create a foo.com SiteInstance and check that its process does not reuse + // the ServiceWorker foo.com process, since it's now in a different + // StoragePartition. + scoped_refptr<SiteInstanceImpl> site_instance = + SiteInstanceImpl::CreateForURL(browser_context(), kUrl); + site_instance->set_process_reuse_policy( + SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE); + RenderProcessHost* process = site_instance->GetProcess(); + EXPECT_NE(sw_process, process); + + SetBrowserClientForTesting(regular_client); +} + class SpareRenderProcessHostUnitTest : public RenderViewHostImplTestHarness { protected: void SetUp() override {
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 66146f0..4d07580 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -83,7 +83,7 @@ #include "skia/ext/image_operations.h" #include "skia/ext/platform_canvas.h" #include "storage/browser/fileapi/isolated_context.h" -#include "third_party/WebKit/public/web/WebCompositionUnderline.h" +#include "third_party/WebKit/public/web/WebImeTextSpan.h" #include "ui/base/clipboard/clipboard.h" #include "ui/base/ui_base_switches.h" #include "ui/display/display_switches.h" @@ -1719,21 +1719,21 @@ void RenderWidgetHostImpl::ImeSetComposition( const base::string16& text, - const std::vector<ui::CompositionUnderline>& underlines, + const std::vector<ui::ImeTextSpan>& ime_text_spans, const gfx::Range& replacement_range, int selection_start, int selection_end) { GetWidgetInputHandler()->ImeSetComposition( - text, underlines, replacement_range, selection_start, selection_end); + text, ime_text_spans, replacement_range, selection_start, selection_end); } void RenderWidgetHostImpl::ImeCommitText( const base::string16& text, - const std::vector<ui::CompositionUnderline>& underlines, + const std::vector<ui::ImeTextSpan>& ime_text_spans, const gfx::Range& replacement_range, int relative_cursor_pos) { - GetWidgetInputHandler()->ImeCommitText(text, underlines, replacement_range, - relative_cursor_pos); + GetWidgetInputHandler()->ImeCommitText( + text, ime_text_spans, replacement_range, relative_cursor_pos); } void RenderWidgetHostImpl::ImeFinishComposingText(bool keep_selection) { @@ -1741,9 +1741,9 @@ } void RenderWidgetHostImpl::ImeCancelComposition() { - GetWidgetInputHandler()->ImeSetComposition( - base::string16(), std::vector<ui::CompositionUnderline>(), - gfx::Range::InvalidRange(), 0, 0); + GetWidgetInputHandler()->ImeSetComposition(base::string16(), + std::vector<ui::ImeTextSpan>(), + gfx::Range::InvalidRange(), 0, 0); } void RenderWidgetHostImpl::RejectMouseLockOrUnlockIfNecessary() {
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index 8cc2749..52b5fa9 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -415,12 +415,11 @@ // (on Windows); // * when it receives a "preedit_changed" signal of GtkIMContext (on Linux); // * when markedText of NSTextInput is called (on Mac). - void ImeSetComposition( - const base::string16& text, - const std::vector<ui::CompositionUnderline>& underlines, - const gfx::Range& replacement_range, - int selection_start, - int selection_end); + void ImeSetComposition(const base::string16& text, + const std::vector<ui::ImeTextSpan>& ime_text_spans, + const gfx::Range& replacement_range, + int selection_start, + int selection_end); // Deletes the ongoing composition if any, inserts the specified text, and // moves the cursor. @@ -430,7 +429,7 @@ // * when it receives a "commit" signal of GtkIMContext (on Linux); // * when insertText of NSTextInput is called (on Mac). void ImeCommitText(const base::string16& text, - const std::vector<ui::CompositionUnderline>& underlines, + const std::vector<ui::ImeTextSpan>& ime_text_spans, const gfx::Range& replacement_range, int relative_cursor_pos);
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index ffd1e2ee..f693b0e3 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -61,7 +61,7 @@ #include "services/service_manager/public/cpp/interface_provider.h" #include "services/ui/public/interfaces/window_manager_constants.mojom.h" #include "third_party/WebKit/public/platform/WebInputEvent.h" -#include "third_party/WebKit/public/web/WebCompositionUnderline.h" +#include "third_party/WebKit/public/web/WebImeTextSpan.h" #include "ui/accessibility/platform/aura_window_properties.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/client/cursor_client.h" @@ -1191,7 +1191,7 @@ // TODO(suzhe): due to a bug of webkit, we can't use selection range with // composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788 text_input_manager_->GetActiveWidget()->ImeSetComposition( - composition.text, composition.underlines, gfx::Range::InvalidRange(), + composition.text, composition.ime_text_spans, gfx::Range::InvalidRange(), composition.selection.end(), composition.selection.end()); has_composition_text_ = !composition.text.empty(); @@ -1218,8 +1218,7 @@ if (text_input_manager_ && text_input_manager_->GetActiveWidget()) { if (text.length()) text_input_manager_->GetActiveWidget()->ImeCommitText( - text, std::vector<ui::CompositionUnderline>(), - gfx::Range::InvalidRange(), 0); + text, std::vector<ui::ImeTextSpan>(), gfx::Range::InvalidRange(), 0); else if (has_composition_text_) text_input_manager_->GetActiveWidget()->ImeFinishComposingText(false); }
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc index fa9609c..c111633 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -1648,14 +1648,14 @@ composition_text.text = base::ASCIIToUTF16("|a|b"); // Focused segment - composition_text.underlines.push_back( - ui::CompositionUnderline(0, 3, 0xff000000, true, 0x78563412)); + composition_text.ime_text_spans.push_back( + ui::ImeTextSpan(0, 3, 0xff000000, true, 0x78563412)); // Non-focused segment, with different background color. - composition_text.underlines.push_back( - ui::CompositionUnderline(3, 4, 0xff000000, false, 0xefcdab90)); + composition_text.ime_text_spans.push_back( + ui::ImeTextSpan(3, 4, 0xff000000, false, 0xefcdab90)); - const ui::CompositionUnderlines& underlines = composition_text.underlines; + const ui::ImeTextSpans& ime_text_spans = composition_text.ime_text_spans; // Caret is at the end. (This emulates Japanese MSIME 2007 and later) composition_text.selection = gfx::Range(4); @@ -1672,15 +1672,16 @@ InputMsg_ImeSetComposition::Read(msg, ¶ms); // composition text EXPECT_EQ(composition_text.text, std::get<0>(params)); - // underlines - ASSERT_EQ(underlines.size(), std::get<1>(params).size()); - for (size_t i = 0; i < underlines.size(); ++i) { - EXPECT_EQ(underlines[i].start_offset, + // ime spans + ASSERT_EQ(ime_text_spans.size(), std::get<1>(params).size()); + for (size_t i = 0; i < ime_text_spans.size(); ++i) { + EXPECT_EQ(ime_text_spans[i].start_offset, std::get<1>(params)[i].start_offset); - EXPECT_EQ(underlines[i].end_offset, std::get<1>(params)[i].end_offset); - EXPECT_EQ(underlines[i].color, std::get<1>(params)[i].color); - EXPECT_EQ(underlines[i].thick, std::get<1>(params)[i].thick); - EXPECT_EQ(underlines[i].background_color, + EXPECT_EQ(ime_text_spans[i].end_offset, + std::get<1>(params)[i].end_offset); + EXPECT_EQ(ime_text_spans[i].color, std::get<1>(params)[i].color); + EXPECT_EQ(ime_text_spans[i].thick, std::get<1>(params)[i].thick); + EXPECT_EQ(ime_text_spans[i].background_color, std::get<1>(params)[i].background_color); } EXPECT_EQ(gfx::Range::InvalidRange(), std::get<2>(params)); @@ -1704,12 +1705,12 @@ composition_text.text = base::ASCIIToUTF16("|a|b"); // Focused segment - composition_text.underlines.push_back( - ui::CompositionUnderline(0, 3, 0xff000000, true, 0x78563412)); + composition_text.ime_text_spans.push_back( + ui::ImeTextSpan(0, 3, 0xff000000, true, 0x78563412)); // Non-focused segment, with different background color. - composition_text.underlines.push_back( - ui::CompositionUnderline(3, 4, 0xff000000, false, 0xefcdab90)); + composition_text.ime_text_spans.push_back( + ui::ImeTextSpan(3, 4, 0xff000000, false, 0xefcdab90)); // Caret is at the end. (This emulates Japanese MSIME 2007 and later) composition_text.selection = gfx::Range(4);
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h index 9374bf3..72664cd 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.h +++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -37,7 +37,7 @@ #import "ui/base/cocoa/command_dispatcher.h" #include "ui/base/cocoa/remote_layer_api.h" #import "ui/base/cocoa/tool_tip_base_view.h" -#include "ui/base/ime/composition_underline.h" +#include "ui/base/ime/ime_text_span.h" #include "ui/display/display_observer.h" namespace content { @@ -127,7 +127,7 @@ NSRange markedTextSelectedRange_; // Underline information of the |markedText_|. - std::vector<ui::CompositionUnderline> underlines_; + std::vector<ui::ImeTextSpan> ime_text_spans_; // Replacement range information received from |setMarkedText:|. gfx::Range setMarkedTextReplacementRange_;
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index db0fb3681..d61f81f 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -280,7 +280,7 @@ // Extract underline information from an attributed string. Mostly copied from // third_party/WebKit/Source/WebKit/mac/WebView/WebHTMLView.mm void ExtractUnderlines(NSAttributedString* string, - std::vector<ui::CompositionUnderline>* underlines) { + std::vector<ui::ImeTextSpan>* ime_text_spans) { int length = [[string string] length]; int i = 0; while (i < length) { @@ -295,9 +295,9 @@ color = WebColorFromNSColor( [colorAttr colorUsingColorSpaceName:NSDeviceRGBColorSpace]); } - underlines->push_back( - ui::CompositionUnderline(range.location, NSMaxRange(range), color, - [style intValue] > 1, SK_ColorTRANSPARENT)); + ime_text_spans->push_back( + ui::ImeTextSpan(range.location, NSMaxRange(range), color, + [style intValue] > 1, SK_ColorTRANSPARENT)); } i = range.location + range.length; } @@ -2197,7 +2197,7 @@ textToBeInserted_.clear(); markedText_.clear(); markedTextSelectedRange_ = NSMakeRange(NSNotFound, 0); - underlines_.clear(); + ime_text_spans_.clear(); setMarkedTextReplacementRange_ = gfx::Range::InvalidRange(); unmarkTextCalled_ = NO; hasEditCommands_ = NO; @@ -2259,8 +2259,7 @@ BOOL textInserted = NO; if (textToBeInserted_.length() > ((hasMarkedText_ || oldHasMarkedText) ? 0u : 1u)) { - widgetHost->ImeCommitText(textToBeInserted_, - std::vector<ui::CompositionUnderline>(), + widgetHost->ImeCommitText(textToBeInserted_, std::vector<ui::ImeTextSpan>(), gfx::Range::InvalidRange(), 0); textInserted = YES; } @@ -2272,7 +2271,7 @@ // composition node in WebKit. // When marked text is available, |markedTextSelectedRange_| will be the // range being selected inside the marked text. - widgetHost->ImeSetComposition(markedText_, underlines_, + widgetHost->ImeSetComposition(markedText_, ime_text_spans_, setMarkedTextReplacementRange_, markedTextSelectedRange_.location, NSMaxRange(markedTextSelectedRange_)); @@ -3306,7 +3305,7 @@ hasMarkedText_ = NO; markedText_.clear(); markedTextSelectedRange_ = NSMakeRange(NSNotFound, 0); - underlines_.clear(); + ime_text_spans_.clear(); // If we are handling a key down event, then FinishComposingText() will be // called in keyEvent: method. @@ -3335,13 +3334,13 @@ markedText_ = base::SysNSStringToUTF16(im_text); hasMarkedText_ = (length > 0); - underlines_.clear(); + ime_text_spans_.clear(); if (isAttributedString) { - ExtractUnderlines(string, &underlines_); + ExtractUnderlines(string, &ime_text_spans_); } else { // Use a thin black underline by default. - underlines_.push_back(ui::CompositionUnderline(0, length, SK_ColorBLACK, - false, SK_ColorTRANSPARENT)); + ime_text_spans_.push_back( + ui::ImeTextSpan(0, length, SK_ColorBLACK, false, SK_ColorTRANSPARENT)); } // If we are handling a key down event, then SetComposition() will be @@ -3356,7 +3355,7 @@ } else { if (renderWidgetHostView_->GetActiveWidget()) { renderWidgetHostView_->GetActiveWidget()->ImeSetComposition( - markedText_, underlines_, gfx::Range(replacementRange), + markedText_, ime_text_spans_, gfx::Range(replacementRange), newSelRange.location, NSMaxRange(newSelRange)); } } @@ -3415,8 +3414,8 @@ gfx::Range replacement_range(replacementRange); if (renderWidgetHostView_->GetActiveWidget()) { renderWidgetHostView_->GetActiveWidget()->ImeCommitText( - base::SysNSStringToUTF16(im_text), - std::vector<ui::CompositionUnderline>(), replacement_range, 0); + base::SysNSStringToUTF16(im_text), std::vector<ui::ImeTextSpan>(), + replacement_range, 0); } }
diff --git a/content/browser/service_worker/service_worker_installed_scripts_sender.cc b/content/browser/service_worker/service_worker_installed_scripts_sender.cc index bf4cbfe..51c683e 100644 --- a/content/browser/service_worker/service_worker_installed_scripts_sender.cc +++ b/content/browser/service_worker/service_worker_installed_scripts_sender.cc
@@ -10,8 +10,8 @@ #include "content/browser/service_worker/service_worker_disk_cache.h" #include "content/browser/service_worker/service_worker_script_cache_map.h" #include "content/browser/service_worker/service_worker_storage.h" -#include "content/common/net_adapters.h" #include "net/http/http_response_headers.h" +#include "services/network/public/cpp/net_adapters.h" namespace content { @@ -176,7 +176,7 @@ // an equivalent error. DCHECK(!pending_write_); uint32_t num_bytes = 0; - MojoResult rv = NetToMojoPendingBuffer::BeginWrite( + MojoResult rv = network::NetToMojoPendingBuffer::BeginWrite( &body_handle_, &pending_write_, &num_bytes); switch (rv) { case MOJO_RESULT_INVALID_ARGUMENT: @@ -193,8 +193,8 @@ break; } - scoped_refptr<NetToMojoIOBuffer> buffer = - base::MakeRefCounted<NetToMojoIOBuffer>(pending_write_.get()); + scoped_refptr<network::NetToMojoIOBuffer> buffer = + base::MakeRefCounted<network::NetToMojoIOBuffer>(pending_write_.get()); reader_->ReadData(buffer.get(), num_bytes, base::Bind(&Sender::OnResponseDataRead, AsWeakPtr())); } @@ -253,7 +253,7 @@ std::unique_ptr<MetaDataSender> meta_data_sender_; // For body. - scoped_refptr<NetToMojoPendingBuffer> pending_write_; + scoped_refptr<network::NetToMojoPendingBuffer> pending_write_; mojo::SimpleWatcher watcher_; // Pipes.
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 4442c8f7..bec99bd 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -3403,6 +3403,7 @@ void WebContentsImpl::DidGetResourceResponseStart( const ResourceRequestDetails& details) { + SetNotWaitingForResponse(); controller_.ssl_manager()->DidStartResourceResponse( details.url, details.has_certificate, details.ssl_cert_status);
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc index d588e66..6c74fc6 100644 --- a/content/browser/web_contents/web_contents_impl_browsertest.cc +++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -244,6 +244,7 @@ EXPECT_EQ(&shell()->web_contents()->GetController(), load_observer.controller_); } + // Test that a renderer-initiated navigation to an invalid URL does not leave // around a pending entry that could be used in a URL spoof. We test this in // a browser test because our unit test framework incorrectly calls @@ -484,13 +485,15 @@ base::string16 title = title_watcher.WaitAndGetTitle(); ASSERT_EQ(title, base::ASCIIToUTF16("pushState")); - // LoadingStateChanged should be called 4 times: start and stop for the - // initial load of push_state.html, and start and stop for the "navigation" - // triggered by history.pushState(). However, the start notification for the - // history.pushState() navigation should set to_different_document to false. + // LoadingStateChanged should be called 5 times: start and stop for the + // initial load of push_state.html, once for the switch from + // IsWaitingForResponse() to !IsWaitingForResponse(), and start and stop for + // the "navigation" triggered by history.pushState(). However, the start + // notification for the history.pushState() navigation should set + // to_different_document to false. EXPECT_EQ("pushState", shell()->web_contents()->GetLastCommittedURL().ref()); - EXPECT_EQ(4, delegate->loadingStateChangedCount()); - EXPECT_EQ(3, delegate->loadingStateToDifferentDocumentCount()); + EXPECT_EQ(5, delegate->loadingStateChangedCount()); + EXPECT_EQ(4, delegate->loadingStateToDifferentDocumentCount()); } IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, @@ -512,6 +515,55 @@ EXPECT_TRUE(new_web_contents_observer.RenderViewCreatedCalled()); } +namespace { + +class DidGetResourceResponseStartObserver : public WebContentsObserver { + public: + DidGetResourceResponseStartObserver(Shell* shell) + : WebContentsObserver(shell->web_contents()), shell_(shell) { + shell->web_contents()->SetDelegate(&delegate_); + EXPECT_FALSE(shell->web_contents()->IsWaitingForResponse()); + EXPECT_FALSE(shell->web_contents()->IsLoading()); + } + + ~DidGetResourceResponseStartObserver() override {} + + void DidGetResourceResponseStart( + const ResourceRequestDetails& details) override { + EXPECT_FALSE(shell_->web_contents()->IsWaitingForResponse()); + EXPECT_TRUE(shell_->web_contents()->IsLoading()); + EXPECT_GT(delegate_.loadingStateChangedCount(), 0); + ++resource_response_start_count_; + } + + int resource_response_start_count() const { + return resource_response_start_count_; + } + + private: + Shell* shell_; + LoadingStateChangedDelegate delegate_; + int resource_response_start_count_ = 0; + + DISALLOW_COPY_AND_ASSIGN(DidGetResourceResponseStartObserver); +}; + +} // namespace + +// Makes sure that the WebContents is no longer marked as waiting for a response +// after DidGetResourceResponseStart() is called. +IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, + DidGetResourceResponseStartUpdatesWaitingState) { + DidGetResourceResponseStartObserver observer(shell()); + + ASSERT_TRUE(embedded_test_server()->Start()); + LoadStopNotificationObserver load_observer( + &shell()->web_contents()->GetController()); + NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")); + load_observer.Wait(); + EXPECT_GT(observer.resource_response_start_count(), 0); +} + struct LoadProgressDelegateAndObserver : public WebContentsDelegate, public WebContentsObserver { LoadProgressDelegateAndObserver(Shell* shell)
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn index ecb25838..0f2c3b3 100644 --- a/content/common/BUILD.gn +++ b/content/common/BUILD.gn
@@ -245,8 +245,6 @@ "net/url_request_service_worker_data.h", "net/url_request_user_data.cc", "net/url_request_user_data.h", - "net_adapters.cc", - "net_adapters.h", "origin_trials/trial_token.cc", "origin_trials/trial_token.h", "origin_trials/trial_token_validator.cc",
diff --git a/content/common/DEPS b/content/common/DEPS index 736590dd..c0da6de2 100644 --- a/content/common/DEPS +++ b/content/common/DEPS
@@ -65,12 +65,12 @@ "+third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerState.h", "+third_party/WebKit/public/platform/modules/serviceworker/service_worker_event_status.mojom.h", "+third_party/WebKit/public/web/WebAXEnums.h", - "+third_party/WebKit/public/web/WebCompositionUnderline.h", "+third_party/WebKit/public/web/WebDeviceEmulationParams.h", "+third_party/WebKit/public/web/WebDragStatus.h", "+third_party/WebKit/public/web/WebFindOptions.h", "+third_party/WebKit/public/web/WebFrameOwnerProperties.h", "+third_party/WebKit/public/web/WebFrameSerializerCacheControlPolicy.h", + "+third_party/WebKit/public/web/WebImeTextSpan.h", "+third_party/WebKit/public/web/WebMediaPlayerAction.h", "+third_party/WebKit/public/web/WebPluginAction.h", "+third_party/WebKit/public/web/WebPopupType.h",
diff --git a/content/common/browser_plugin/browser_plugin_messages.h b/content/common/browser_plugin/browser_plugin_messages.h index 57ac7ad..1258423 100644 --- a/content/common/browser_plugin/browser_plugin_messages.h +++ b/content/common/browser_plugin/browser_plugin_messages.h
@@ -18,8 +18,8 @@ #include "ipc/ipc_message_utils.h" #include "third_party/WebKit/public/platform/WebDragOperation.h" #include "third_party/WebKit/public/platform/WebFocusType.h" -#include "third_party/WebKit/public/web/WebCompositionUnderline.h" #include "third_party/WebKit/public/web/WebDragStatus.h" +#include "third_party/WebKit/public/web/WebImeTextSpan.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" @@ -45,7 +45,7 @@ IPC_STRUCT_BEGIN(BrowserPluginHostMsg_SetComposition_Params) IPC_STRUCT_MEMBER(base::string16, text) - IPC_STRUCT_MEMBER(std::vector<blink::WebCompositionUnderline>, underlines) + IPC_STRUCT_MEMBER(std::vector<blink::WebImeTextSpan>, ime_text_spans) IPC_STRUCT_MEMBER(gfx::Range, replacement_range) IPC_STRUCT_MEMBER(int, selection_start) IPC_STRUCT_MEMBER(int, selection_end) @@ -81,13 +81,12 @@ // This message is sent from BrowserPlugin to BrowserPluginGuest to notify that // deleting the current composition and inserting specified text is requested. -IPC_MESSAGE_CONTROL5( - BrowserPluginHostMsg_ImeCommitText, - int /* browser_plugin_instance_id */, - base::string16 /* text */, - std::vector<blink::WebCompositionUnderline> /* underlines */, - gfx::Range /* replacement_range */, - int /* relative_cursor_pos */) +IPC_MESSAGE_CONTROL5(BrowserPluginHostMsg_ImeCommitText, + int /* browser_plugin_instance_id */, + base::string16 /* text */, + std::vector<blink::WebImeTextSpan> /* ime_text_spans */, + gfx::Range /* replacement_range */, + int /* relative_cursor_pos */) // This message is sent from BrowserPlugin to BrowserPluginGuest to notify that // inserting the current composition is requested.
diff --git a/content/common/common.sb b/content/common/common.sb index fbe0ff5..f8fe48b 100644 --- a/content/common/common.sb +++ b/content/common/common.sb
@@ -19,6 +19,7 @@ (define permitted-dir "PERMITTED_DIR") (define homedir-as-literal "USER_HOMEDIR_AS_LITERAL") (define elcap-or-later "ELCAP_OR_LATER") +(define macos-1013 "MACOS_1013") ; Consumes a subpath and appends it to the user's homedir path. (define (user-homedir-path subpath)
diff --git a/content/common/content_param_traits_macros.h b/content/common/content_param_traits_macros.h index a1187c78..9c5638e 100644 --- a/content/common/content_param_traits_macros.h +++ b/content/common/content_param_traits_macros.h
@@ -21,7 +21,7 @@ #include "third_party/WebKit/public/platform/WebContentSecurityPolicy.h" #include "third_party/WebKit/public/platform/WebInputEvent.h" #include "third_party/WebKit/public/platform/WebPageVisibilityState.h" -#include "third_party/WebKit/public/web/WebCompositionUnderline.h" +#include "third_party/WebKit/public/web/WebImeTextSpan.h" #include "third_party/WebKit/public/web/WebSharedWorkerCreationContextType.h" #include "ui/gfx/gpu_memory_buffer.h" #include "ui/gfx/ipc/geometry/gfx_param_traits.h" @@ -52,7 +52,7 @@ IPC_ENUM_TRAITS_MAX_VALUE(blink::WebPageVisibilityState, blink::kWebPageVisibilityStateLast) -IPC_STRUCT_TRAITS_BEGIN(blink::WebCompositionUnderline) +IPC_STRUCT_TRAITS_BEGIN(blink::WebImeTextSpan) IPC_STRUCT_TRAITS_MEMBER(start_offset) IPC_STRUCT_TRAITS_MEMBER(end_offset) IPC_STRUCT_TRAITS_MEMBER(color)
diff --git a/content/common/dom_storage/dom_storage_messages.h b/content/common/dom_storage/dom_storage_messages.h index 3325bf9b..dc55283 100644 --- a/content/common/dom_storage/dom_storage_messages.h +++ b/content/common/dom_storage/dom_storage_messages.h
@@ -77,17 +77,19 @@ // Set a value that's associated with a key in a storage area. // A completion notification is sent in response. -IPC_MESSAGE_CONTROL4(DOMStorageHostMsg_SetItem, +IPC_MESSAGE_CONTROL5(DOMStorageHostMsg_SetItem, int /* connection_id */, base::string16 /* key */, base::string16 /* value */, + base::NullableString16 /* client_old_value */, GURL /* page_url */) // Remove the value associated with a key in a storage area. // A completion notification is sent in response. -IPC_MESSAGE_CONTROL3(DOMStorageHostMsg_RemoveItem, +IPC_MESSAGE_CONTROL4(DOMStorageHostMsg_RemoveItem, int /* connection_id */, base::string16 /* key */, + base::NullableString16 /* client_old_value */, GURL /* page_url */) // Clear the storage area. A completion notification is sent in response.
diff --git a/content/common/input/input_handler.mojom b/content/common/input/input_handler.mojom index 39cc748..2613a00 100644 --- a/content/common/input/input_handler.mojom +++ b/content/common/input/input_handler.mojom
@@ -169,13 +169,13 @@ // This message sends a string being composed with an input method. ImeSetComposition(mojo.common.mojom.String16 text, - array<ui.mojom.CompositionUnderline> underlines, + array<ui.mojom.ImeTextSpan> ime_text_spans, gfx.mojom.Range range, int32 start, int32 end); // This message deletes the current composition, inserts specified text, and // moves the cursor. ImeCommitText(mojo.common.mojom.String16 text, - array<ui.mojom.CompositionUnderline> underlines, + array<ui.mojom.ImeTextSpan> ime_text_spans, gfx.mojom.Range range, int32 relative_cursor_position); // This message inserts the ongoing composition. @@ -216,7 +216,7 @@ // Sets the text composition to be between the given start and end offsets in // the currently focused editable field. SetCompositionFromExistingText( - int32 start, int32 end, array<ui.mojom.CompositionUnderline> underlines); + int32 start, int32 end, array<ui.mojom.ImeTextSpan> ime_text_spans); // Deletes the current selection plus the specified number of characters // before and after the selection or caret.
diff --git a/content/common/input_messages.h b/content/common/input_messages.h index 142f8db4..73dedb03 100644 --- a/content/common/input_messages.h +++ b/content/common/input_messages.h
@@ -169,9 +169,9 @@ // Sets the text composition to be between the given start and end offsets in // the currently focused editable field. IPC_MESSAGE_ROUTED3(InputMsg_SetCompositionFromExistingText, - int /* start */, - int /* end */, - std::vector<blink::WebCompositionUnderline> /* underlines */) + int /* start */, + int /* end */, + std::vector<blink::WebImeTextSpan> /* ime_text_spans */) // Deletes the current selection plus the specified number of characters before // and after the selection or caret. @@ -201,22 +201,20 @@ int /* end */) // This message sends a string being composed with an input method. -IPC_MESSAGE_ROUTED5( - InputMsg_ImeSetComposition, - base::string16, /* text */ - std::vector<blink::WebCompositionUnderline>, /* underlines */ - gfx::Range /* replacement_range */, - int, /* selectiont_start */ - int /* selection_end */) +IPC_MESSAGE_ROUTED5(InputMsg_ImeSetComposition, + base::string16, /* text */ + std::vector<blink::WebImeTextSpan>, /* ime_text_spans */ + gfx::Range /* replacement_range */, + int, /* selectiont_start */ + int /* selection_end */) // This message deletes the current composition, inserts specified text, and // moves the cursor. -IPC_MESSAGE_ROUTED4( - InputMsg_ImeCommitText, - base::string16 /* text */, - std::vector<blink::WebCompositionUnderline>, /* underlines */ - gfx::Range /* replacement_range */, - int /* relative_cursor_pos */) +IPC_MESSAGE_ROUTED4(InputMsg_ImeCommitText, + base::string16 /* text */, + std::vector<blink::WebImeTextSpan>, /* ime_text_spans */ + gfx::Range /* replacement_range */, + int /* relative_cursor_pos */) // This message inserts the ongoing composition. IPC_MESSAGE_ROUTED1(InputMsg_ImeFinishComposingText, bool /* keep_selection */)
diff --git a/content/common/media/media_stream_messages.h b/content/common/media/media_stream_messages.h index ea288d3..e44672f 100644 --- a/content/common/media/media_stream_messages.h +++ b/content/common/media/media_stream_messages.h
@@ -25,18 +25,12 @@ IPC_STRUCT_TRAITS_BEGIN(content::StreamDeviceInfo) IPC_STRUCT_TRAITS_MEMBER(device.type) - IPC_STRUCT_TRAITS_MEMBER(device.name) IPC_STRUCT_TRAITS_MEMBER(device.id) IPC_STRUCT_TRAITS_MEMBER(device.video_facing) IPC_STRUCT_TRAITS_MEMBER(device.matched_output_device_id) - IPC_STRUCT_TRAITS_MEMBER(device.input.sample_rate) - IPC_STRUCT_TRAITS_MEMBER(device.input.channel_layout) - IPC_STRUCT_TRAITS_MEMBER(device.input.frames_per_buffer) - IPC_STRUCT_TRAITS_MEMBER(device.input.effects) - IPC_STRUCT_TRAITS_MEMBER(device.input.mic_positions) - IPC_STRUCT_TRAITS_MEMBER(device.matched_output.sample_rate) - IPC_STRUCT_TRAITS_MEMBER(device.matched_output.channel_layout) - IPC_STRUCT_TRAITS_MEMBER(device.matched_output.frames_per_buffer) + IPC_STRUCT_TRAITS_MEMBER(device.name) + IPC_STRUCT_TRAITS_MEMBER(device.input) + IPC_STRUCT_TRAITS_MEMBER(device.matched_output) IPC_STRUCT_TRAITS_MEMBER(device.camera_calibration) IPC_STRUCT_TRAITS_MEMBER(session_id) IPC_STRUCT_TRAITS_END()
diff --git a/content/common/render_message_filter.mojom b/content/common/render_message_filter.mojom index e51d3dc..b61002b7 100644 --- a/content/common/render_message_filter.mojom +++ b/content/common/render_message_filter.mojom
@@ -4,7 +4,6 @@ module content.mojom; -import "cc/ipc/shared_bitmap_allocation_notifier.mojom"; import "content/common/input/input_handler.mojom"; import "content/common/native_types.mojom"; import "content/common/widget.mojom";
diff --git a/content/common/sandbox_mac.h b/content/common/sandbox_mac.h index 8496104..93765ed 100644 --- a/content/common/sandbox_mac.h +++ b/content/common/sandbox_mac.h
@@ -61,6 +61,7 @@ // TODO(kerrnel): this is only for the legacy sandbox. static const char* kSandboxElCapOrLater; + static const char* kSandboxMacOS1013; private: FRIEND_TEST_ALL_PREFIXES(MacDirAccessSandboxTest, StringEscape);
diff --git a/content/common/sandbox_mac.mm b/content/common/sandbox_mac.mm index 9156287..e9789fe 100644 --- a/content/common/sandbox_mac.mm +++ b/content/common/sandbox_mac.mm
@@ -84,6 +84,7 @@ const char* Sandbox::kSandboxPermittedDir = "PERMITTED_DIR"; const char* Sandbox::kSandboxElCapOrLater = "ELCAP_OR_LATER"; +const char* Sandbox::kSandboxMacOS1013 = "MACOS_1013"; // Warm up System APIs that empirically need to be accessed before the Sandbox // is turned on. @@ -282,6 +283,10 @@ if (!compiler.InsertBooleanParam(kSandboxElCapOrLater, elcap_or_later)) return false; + bool macos_1013 = base::mac::IsOS10_13(); + if (!compiler.InsertBooleanParam(kSandboxMacOS1013, macos_1013)) + return false; + // Initialize sandbox. std::string error_str; bool success = compiler.CompileAndApplyProfile(&error_str);
diff --git a/content/network/BUILD.gn b/content/network/BUILD.gn index fe29a2cf..cc11dea 100644 --- a/content/network/BUILD.gn +++ b/content/network/BUILD.gn
@@ -59,6 +59,7 @@ "//content/public/common:common_sources", "//mojo/public/cpp/bindings", "//net", + "//services/network/public/cpp", "//services/service_manager/public/cpp", "//services/service_manager/public/interfaces", ]
diff --git a/content/network/DEPS b/content/network/DEPS index 2f038c7..b24d403 100644 --- a/content/network/DEPS +++ b/content/network/DEPS
@@ -4,7 +4,6 @@ "-content", "+content/common/content_export.h", "+content/common/loader_util.h", - "+content/common/net_adapters.h", "+content/network", "+content/public/common/appcache_info.h", "+content/public/common/content_client.h", @@ -18,6 +17,7 @@ "+content/public/common/url_loader.mojom.h", "+content/public/common/url_loader_factory.mojom.h", "+content/public/network", + "+services/network", "+services/service_manager/public", ]
diff --git a/content/network/url_loader_impl.cc b/content/network/url_loader_impl.cc index b244f79..140cacd 100644 --- a/content/network/url_loader_impl.cc +++ b/content/network/url_loader_impl.cc
@@ -8,7 +8,6 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "content/common/loader_util.h" -#include "content/common/net_adapters.h" #include "content/network/network_context.h" #include "content/public/common/referrer.h" #include "content/public/common/resource_response.h" @@ -19,6 +18,7 @@ #include "net/base/upload_bytes_element_reader.h" #include "net/base/upload_file_element_reader.h" #include "net/url_request/url_request_context.h" +#include "services/network/public/cpp/net_adapters.h" namespace content { @@ -289,7 +289,7 @@ if (!pending_write_.get()) { // TODO: we should use the abstractions in MojoAsyncResourceHandler. pending_write_buffer_offset_ = 0; - MojoResult result = NetToMojoPendingBuffer::BeginWrite( + MojoResult result = network::NetToMojoPendingBuffer::BeginWrite( &response_body_stream_, &pending_write_, &pending_write_buffer_size_); if (result != MOJO_RESULT_OK && result != MOJO_RESULT_SHOULD_WAIT) { // The response body stream is in a bad state. Bail. @@ -313,8 +313,8 @@ } } - scoped_refptr<net::IOBuffer> buf(new NetToMojoIOBuffer( - pending_write_.get(), pending_write_buffer_offset_)); + auto buf = base::MakeRefCounted<network::NetToMojoIOBuffer>( + pending_write_.get(), pending_write_buffer_offset_); int bytes_read; url_request_->Read(buf.get(), static_cast<int>(pending_write_buffer_size_ -
diff --git a/content/network/url_loader_impl.h b/content/network/url_loader_impl.h index a349be2..d0c057a9 100644 --- a/content/network/url_loader_impl.h +++ b/content/network/url_loader_impl.h
@@ -18,10 +18,13 @@ #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_request.h" +namespace network { +class NetToMojoPendingBuffer; +} + namespace content { class NetworkContext; -class NetToMojoPendingBuffer; struct ResourceResponse; class CONTENT_EXPORT URLLoaderImpl : public mojom::URLLoader, @@ -73,7 +76,7 @@ int64_t total_written_bytes_ = 0; mojo::ScopedDataPipeProducerHandle response_body_stream_; - scoped_refptr<NetToMojoPendingBuffer> pending_write_; + scoped_refptr<network::NetToMojoPendingBuffer> pending_write_; uint32_t pending_write_buffer_size_ = 0; uint32_t pending_write_buffer_offset_ = 0; mojo::SimpleWatcher writable_handle_watcher_;
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java b/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java index 713b236..5370d225 100644 --- a/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java +++ b/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java
@@ -872,9 +872,10 @@ } @CalledByNative - private void populateUnderlinesFromSpans(CharSequence text, long underlines) { + private void populateImeTextSpansFromJava(CharSequence text, long imeTextSpans) { if (DEBUG_LOGS) { - Log.i(TAG, "populateUnderlinesFromSpans: text [%s], underlines [%d]", text, underlines); + Log.i(TAG, "populateImeTextSpansFromJava: text [%s], ime_text_spans [%d]", text, + imeTextSpans); } if (!(text instanceof SpannableString)) return; @@ -883,11 +884,11 @@ spannableString.getSpans(0, text.length(), CharacterStyle.class); for (CharacterStyle span : spans) { if (span instanceof BackgroundColorSpan) { - nativeAppendBackgroundColorSpan(underlines, spannableString.getSpanStart(span), + nativeAppendBackgroundColorSpan(imeTextSpans, spannableString.getSpanStart(span), spannableString.getSpanEnd(span), ((BackgroundColorSpan) span).getBackgroundColor()); } else if (span instanceof UnderlineSpan) { - nativeAppendUnderlineSpan(underlines, spannableString.getSpanStart(span), + nativeAppendUnderlineSpan(imeTextSpans, spannableString.getSpanStart(span), spannableString.getSpanEnd(span)); } } @@ -917,9 +918,9 @@ private native boolean nativeSendKeyEvent(long nativeImeAdapterAndroid, KeyEvent event, int type, int modifiers, long timestampMs, int keyCode, int scanCode, boolean isSystemKey, int unicodeChar); - private static native void nativeAppendUnderlineSpan(long underlinePtr, int start, int end); - private static native void nativeAppendBackgroundColorSpan(long underlinePtr, int start, - int end, int backgroundColor); + private static native void nativeAppendUnderlineSpan(long spanPtr, int start, int end); + private static native void nativeAppendBackgroundColorSpan( + long spanPtr, int start, int end, int backgroundColor); private native void nativeSetComposingText(long nativeImeAdapterAndroid, CharSequence text, String textStr, int newCursorPosition); private native void nativeCommitText(
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/ImeUtils.java b/content/public/android/java/src/org/chromium/content/browser/input/ImeUtils.java index 8ef905d6..b667c45b 100644 --- a/content/public/android/java/src/org/chromium/content/browser/input/ImeUtils.java +++ b/content/public/android/java/src/org/chromium/content/browser/input/ImeUtils.java
@@ -44,7 +44,6 @@ outAttrs.inputType |= EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS; } - int imeAction = 0; if (inputMode == WebTextInputMode.DEFAULT) { if (inputType == TextInputType.TEXT) { // Normal text field @@ -112,21 +111,8 @@ } } - if (inputMode == WebTextInputMode.DEFAULT && inputType == TextInputType.SEARCH) { - imeAction |= EditorInfo.IME_ACTION_SEARCH; - } else if ((outAttrs.inputType & EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE) != 0) { - // For textarea that sends you to another webpage on enter key press using - // JavaScript, we will only show ENTER. - imeAction |= EditorInfo.IME_ACTION_NONE; - } else if ((inputFlags & WebTextInputFlags.HAVE_NEXT_FOCUSABLE_ELEMENT) != 0) { - imeAction |= EditorInfo.IME_ACTION_NEXT; - } else { - // For last element inside form, we should give preference to GO key as PREVIOUS - // has less importance in those cases. - imeAction |= EditorInfo.IME_ACTION_GO; - } - - outAttrs.imeOptions |= imeAction; + outAttrs.imeOptions |= getImeAction(inputType, inputFlags, inputMode, + (outAttrs.inputType & EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE) != 0); // Handling of autocapitalize. Blink will send the flag taking into account the element's // type. This is not using AutocapitalizeNone because Android does not autocapitalize by @@ -148,6 +134,25 @@ outAttrs.initialSelEnd = initialSelEnd; } + private static int getImeAction( + int inputType, int inputFlags, int inputMode, boolean isMultiLineInput) { + int imeAction = 0; + if (inputMode == WebTextInputMode.DEFAULT && inputType == TextInputType.SEARCH) { + imeAction |= EditorInfo.IME_ACTION_SEARCH; + } else if (isMultiLineInput) { + // For textarea that sends you to another webpage on enter key press using + // JavaScript, we will only show ENTER. + imeAction |= EditorInfo.IME_ACTION_NONE; + } else if ((inputFlags & WebTextInputFlags.HAVE_NEXT_FOCUSABLE_ELEMENT) != 0) { + imeAction |= EditorInfo.IME_ACTION_NEXT; + } else { + // For last element inside form, we should give preference to GO key as PREVIOUS + // has less importance in those cases. + imeAction |= EditorInfo.IME_ACTION_GO; + } + return imeAction; + } + /** * @param editorInfo The EditorInfo * @return Debug string for the given {@EditorInfo}.
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json index 54aadee7..360cc64 100644 --- a/content/public/app/mojo/content_browser_manifest.json +++ b/content/public/app/mojo/content_browser_manifest.json
@@ -25,7 +25,6 @@ "blink::mojom::OffscreenCanvasProvider", "blink::mojom::PermissionService", "blink::mojom::WebSocket", - "cc::mojom::SharedBitmapAllocationNotifier", "content::mojom::FieldTrialRecorder", "content::mojom::FrameSinkProvider", "content::mojom::MediaStreamDispatcherHost", @@ -47,7 +46,8 @@ "resource_coordinator::mojom::CoordinationUnit", "shape_detection::mojom::TextDetection", "storage::mojom::BlobRegistry", - "ui::mojom::Gpu" + "ui::mojom::Gpu", + "viz::mojom::SharedBitmapAllocationNotifier" ], "geolocation_config": [ "device::mojom::GeolocationConfig"
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn index 8349727..aa409f7 100644 --- a/content/public/browser/BUILD.gn +++ b/content/public/browser/BUILD.gn
@@ -231,6 +231,7 @@ "restore_type.h", "save_page_type.h", "screen_orientation_delegate.h", + "security_style_explanation.cc", "security_style_explanation.h", "security_style_explanations.cc", "security_style_explanations.h",
diff --git a/content/public/browser/browser_associated_interface.h b/content/public/browser/browser_associated_interface.h index 2b86e21..5fedb75 100644 --- a/content/public/browser/browser_associated_interface.h +++ b/content/public/browser/browser_associated_interface.h
@@ -5,11 +5,11 @@ #ifndef CONTENT_BROWSER_BROWSER_ASSOCIATED_INTERFACE_H_ #define CONTENT_BROWSER_BROWSER_ASSOCIATED_INTERFACE_H_ -#include <memory> #include <string> #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/optional.h" #include "content/common/content_export.h" #include "content/public/browser/browser_message_filter.h" #include "content/public/browser/browser_thread.h" @@ -55,7 +55,6 @@ // |filter| and |impl| must live at least as long as this object. BrowserAssociatedInterface(BrowserMessageFilter* filter, Interface* impl) : internal_state_(new InternalState(impl)) { - internal_state_->Initialize(); filter->AddAssociatedInterface( Interface::Name_, base::Bind(&InternalState::BindRequest, internal_state_), @@ -69,16 +68,8 @@ class InternalState : public base::RefCountedThreadSafe<InternalState> { public: - explicit InternalState(Interface* impl) : impl_(impl) {} - - void Initialize() { - if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { - BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, - base::Bind(&InternalState::Initialize, this)); - return; - } - bindings_.reset(new mojo::AssociatedBindingSet<Interface>); - } + explicit InternalState(Interface* impl) + : impl_(impl), bindings_(base::in_place) {} void ClearBindings() { if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { @@ -106,7 +97,7 @@ ~InternalState() {} Interface* impl_; - std::unique_ptr<mojo::AssociatedBindingSet<Interface>> bindings_; + base::Optional<mojo::AssociatedBindingSet<Interface>> bindings_; DISALLOW_COPY_AND_ASSIGN(InternalState); };
diff --git a/content/public/browser/render_process_host.h b/content/public/browser/render_process_host.h index 238a1a6..da30dc5 100644 --- a/content/public/browser/render_process_host.h +++ b/content/public/browser/render_process_host.h
@@ -130,10 +130,10 @@ virtual RendererAudioOutputStreamFactoryContext* GetRendererAudioOutputStreamFactoryContext() = 0; - // Called when an audio stream is added or removed and used to determine if - // the process should be backgrounded or not. - virtual void OnAudioStreamAdded() = 0; - virtual void OnAudioStreamRemoved() = 0; + // Called when a video capture stream or an audio stream is added or removed + // and used to determine if the process should be backgrounded or not. + virtual void OnMediaStreamAdded() = 0; + virtual void OnMediaStreamRemoved() = 0; // Indicates whether the current RenderProcessHost is exclusively hosting // guest RenderFrames. Not all guest RenderFrames are created equal. A guest,
diff --git a/content/public/browser/security_style_explanation.cc b/content/public/browser/security_style_explanation.cc new file mode 100644 index 0000000..9d497471 --- /dev/null +++ b/content/public/browser/security_style_explanation.cc
@@ -0,0 +1,36 @@ +// 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 "content/public/browser/security_style_explanation.h" + +namespace content { + +SecurityStyleExplanation::SecurityStyleExplanation() {} + +SecurityStyleExplanation::SecurityStyleExplanation( + const std::string& summary, + const std::string& description) + : summary(summary), + description(description), + mixed_content_type(blink::WebMixedContentContextType::kNotMixedContent) {} + +SecurityStyleExplanation::SecurityStyleExplanation( + const std::string& summary, + const std::string& description, + scoped_refptr<net::X509Certificate> certificate, + blink::WebMixedContentContextType mixed_content_type) + : summary(summary), + description(description), + certificate(certificate), + mixed_content_type(mixed_content_type) {} + +SecurityStyleExplanation::SecurityStyleExplanation( + const SecurityStyleExplanation& other) = default; + +SecurityStyleExplanation& SecurityStyleExplanation::operator=( + const SecurityStyleExplanation& other) = default; + +SecurityStyleExplanation::~SecurityStyleExplanation() {} + +} // namespace content
diff --git a/content/public/browser/security_style_explanation.h b/content/public/browser/security_style_explanation.h index e2d51b9..9f0b12b 100644 --- a/content/public/browser/security_style_explanation.h +++ b/content/public/browser/security_style_explanation.h
@@ -8,6 +8,7 @@ #include <string> #include "content/common/content_export.h" +#include "net/cert/x509_certificate.h" #include "third_party/WebKit/public/platform/WebMixedContentContextType.h" namespace content { @@ -17,32 +18,24 @@ // resource. An example summary phrase would be "Expired Certificate", // with a description along the lines of "This site's certificate chain // contains errors (net::CERT_DATE_INVALID)". -struct SecurityStyleExplanation { - CONTENT_EXPORT SecurityStyleExplanation(){}; - CONTENT_EXPORT SecurityStyleExplanation(const std::string& summary, - const std::string& description) - : summary(summary), - description(description), - has_certificate(false), - mixed_content_type( - blink::WebMixedContentContextType::kNotMixedContent) {} - CONTENT_EXPORT SecurityStyleExplanation( +struct CONTENT_EXPORT SecurityStyleExplanation { + SecurityStyleExplanation(); + SecurityStyleExplanation(const std::string& summary, + const std::string& description); + SecurityStyleExplanation( const std::string& summary, const std::string& description, - bool has_certificate, - blink::WebMixedContentContextType mixed_content_type) - : summary(summary), - description(description), - has_certificate(has_certificate), - mixed_content_type(mixed_content_type) {} - CONTENT_EXPORT ~SecurityStyleExplanation() {} + scoped_refptr<net::X509Certificate> certificate, + blink::WebMixedContentContextType mixed_content_type); + SecurityStyleExplanation(const SecurityStyleExplanation& other); + SecurityStyleExplanation& operator=(const SecurityStyleExplanation& other); + ~SecurityStyleExplanation(); std::string summary; std::string description; - // |has_certificate| indicates that this explanation has an associated - // certificate. UI surfaces can use this to add a button/link for viewing the - // certificate of the current page. - bool has_certificate; + // |certificate| indicates that this explanation has an associated + // certificate. + scoped_refptr<net::X509Certificate> certificate; // |mixed_content_type| indicates that the explanation describes a particular // type of mixed content. A value of kNotMixedContent means that the // explanation does not relate to mixed content. UI surfaces can use this to
diff --git a/content/public/browser/security_style_explanations.h b/content/public/browser/security_style_explanations.h index 041236d..981970b 100644 --- a/content/public/browser/security_style_explanations.h +++ b/content/public/browser/security_style_explanations.h
@@ -25,11 +25,10 @@ // SecurityStyleExplanation that contains a human-readable explanation of the // factor. A single page may contain multiple explanations, each of which may // have a different severity level ("secure", "warning", "insecure" and "info"). -struct SecurityStyleExplanations { - CONTENT_EXPORT SecurityStyleExplanations(); - CONTENT_EXPORT SecurityStyleExplanations( - const SecurityStyleExplanations& other); - CONTENT_EXPORT ~SecurityStyleExplanations(); +struct CONTENT_EXPORT SecurityStyleExplanations { + SecurityStyleExplanations(); + SecurityStyleExplanations(const SecurityStyleExplanations& other); + ~SecurityStyleExplanations(); // True if the page was loaded over HTTPS and ran mixed (HTTP) content // such as scripts.
diff --git a/content/public/browser/web_contents_delegate.cc b/content/public/browser/web_contents_delegate.cc index 30c545b..959fe72 100644 --- a/content/public/browser/web_contents_delegate.cc +++ b/content/public/browser/web_contents_delegate.cc
@@ -14,7 +14,6 @@ #include "content/public/browser/web_contents.h" #include "content/public/common/bindings_policy.h" #include "content/public/common/url_constants.h" -#include "net/cert/x509_certificate.h" #include "ui/gfx/geometry/rect.h" namespace content { @@ -266,11 +265,6 @@ return blink::kWebSecurityStyleUnknown; } -void WebContentsDelegate::ShowCertificateViewerInDevTools( - WebContents* web_contents, - scoped_refptr<net::X509Certificate> certificate) { -} - void WebContentsDelegate::RequestAppBannerFromDevTools( content::WebContents* web_contents) { }
diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h index 3ffbea6..8b548ba 100644 --- a/content/public/browser/web_contents_delegate.h +++ b/content/public/browser/web_contents_delegate.h
@@ -63,10 +63,6 @@ class Size; } -namespace net { -class X509Certificate; -} - namespace url { class Origin; } @@ -546,11 +542,6 @@ WebContents* web_contents, SecurityStyleExplanations* security_style_explanations); - // Displays platform-specific (OS) dialog with the certificate details. - virtual void ShowCertificateViewerInDevTools( - WebContents* web_contents, - scoped_refptr<net::X509Certificate> certificate); - // Requests the app banner. This method is called from the DevTools. virtual void RequestAppBannerFromDevTools(content::WebContents* web_contents);
diff --git a/content/public/common/media_stream_request.cc b/content/public/common/media_stream_request.cc index 8512aad5..b042198 100644 --- a/content/public/common/media_stream_request.cc +++ b/content/public/common/media_stream_request.cc
@@ -63,19 +63,21 @@ id(id), video_facing(media::MEDIA_VIDEO_FACING_NONE), name(name), - input(sample_rate, channel_layout, frames_per_buffer) {} + input(media::AudioParameters::AUDIO_FAKE, + static_cast<media::ChannelLayout>(channel_layout), + sample_rate, + 0, + frames_per_buffer) {} MediaStreamDevice::MediaStreamDevice(const MediaStreamDevice& other) = default; MediaStreamDevice::~MediaStreamDevice() {} bool MediaStreamDevice::IsEqual(const MediaStreamDevice& second) const { - const AudioDeviceParameters& input_second = second.input; - return type == second.type && - name == second.name && - id == second.id && - input.sample_rate == input_second.sample_rate && - input.channel_layout == input_second.channel_layout; + const media::AudioParameters& input_second = second.input; + return type == second.type && name == second.name && id == second.id && + input.sample_rate() == input_second.sample_rate() && + input.channel_layout() == input_second.channel_layout(); } MediaStreamDevices::MediaStreamDevices() {} @@ -94,23 +96,6 @@ return NULL; } -MediaStreamDevice::AudioDeviceParameters::AudioDeviceParameters() - : sample_rate(), channel_layout(), frames_per_buffer(), effects() {} - -MediaStreamDevice::AudioDeviceParameters::AudioDeviceParameters( - int sample_rate, - int channel_layout, - int frames_per_buffer) - : sample_rate(sample_rate), - channel_layout(channel_layout), - frames_per_buffer(frames_per_buffer), - effects() {} - -MediaStreamDevice::AudioDeviceParameters::AudioDeviceParameters( - const AudioDeviceParameters& other) = default; - -MediaStreamDevice::AudioDeviceParameters::~AudioDeviceParameters() {} - MediaStreamRequest::MediaStreamRequest( int render_process_id, int render_frame_id,
diff --git a/content/public/common/media_stream_request.h b/content/public/common/media_stream_request.h index f3b09c0..36821c4 100644 --- a/content/public/common/media_stream_request.h +++ b/content/public/common/media_stream_request.h
@@ -122,49 +122,19 @@ // The device's "friendly" name. Not guaranteed to be unique. std::string name; - // Contains properties that match directly with those with the same name - // in media::AudioParameters. - // TODO(ajm): Remove this type and use media::AudioParameters directly. - struct CONTENT_EXPORT AudioDeviceParameters { - AudioDeviceParameters(); - AudioDeviceParameters(int sample_rate, - int channel_layout, - int frames_per_buffer); - AudioDeviceParameters(const AudioDeviceParameters& other); - - ~AudioDeviceParameters(); - - // Preferred sample rate in samples per second for the device. - int sample_rate; - - // Preferred channel configuration for the device. - // TODO(henrika): ideally, we would like to use media::ChannelLayout here - // but including media/base/channel_layout.h violates checkdeps rules. - int channel_layout; - - // Preferred number of frames per buffer for the device. This is filled - // in on the browser side and can be used by the renderer to match the - // expected browser side settings and avoid unnecessary buffering. - // See media::AudioParameters for more. - int frames_per_buffer; - - // See media::AudioParameters::PlatformEffectsMask. - int effects; - - std::vector<media::Point> mic_positions; - }; - // These below two member variables are valid only when the type of device is // audio (i.e. IsAudioInputMediaType returns true). // Contains the device properties of the capture device. - AudioDeviceParameters input; + media::AudioParameters input = + media::AudioParameters::UnavailableDeviceParams(); // If the capture device has an associated output device (e.g. headphones), // this will contain the properties for the output device. If no such device // exists (e.g. webcam w/mic), then the value of this member will be all // zeros. - AudioDeviceParameters matched_output; + media::AudioParameters matched_output = + media::AudioParameters::UnavailableDeviceParams(); // This field is optional and available only for some camera models. base::Optional<CameraCalibration> camera_calibration;
diff --git a/content/public/test/mock_render_process_host.cc b/content/public/test/mock_render_process_host.cc index 0f95e02..dcc3163 100644 --- a/content/public/test/mock_render_process_host.cc +++ b/content/public/test/mock_render_process_host.cc
@@ -159,9 +159,9 @@ return nullptr; } -void MockRenderProcessHost::OnAudioStreamAdded() {} +void MockRenderProcessHost::OnMediaStreamAdded() {} -void MockRenderProcessHost::OnAudioStreamRemoved() {} +void MockRenderProcessHost::OnMediaStreamRemoved() {} StoragePartition* MockRenderProcessHost::GetStoragePartition() const { return BrowserContext::GetDefaultStoragePartition(browser_context_);
diff --git a/content/public/test/mock_render_process_host.h b/content/public/test/mock_render_process_host.h index 9dd2787..d67bd9d 100644 --- a/content/public/test/mock_render_process_host.h +++ b/content/public/test/mock_render_process_host.h
@@ -66,8 +66,8 @@ bool IsForGuestsOnly() const override; RendererAudioOutputStreamFactoryContext* GetRendererAudioOutputStreamFactoryContext() override; - void OnAudioStreamAdded() override; - void OnAudioStreamRemoved() override; + void OnMediaStreamAdded() override; + void OnMediaStreamRemoved() override; StoragePartition* GetStoragePartition() const override; virtual void AddWord(const base::string16& word); bool Shutdown(int exit_code, bool wait) override;
diff --git a/content/public/test/text_input_test_utils.cc b/content/public/test/text_input_test_utils.cc index 65ec8d2..1e7153a 100644 --- a/content/public/test/text_input_test_utils.cc +++ b/content/public/test/text_input_test_utils.cc
@@ -22,8 +22,8 @@ #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/test/test_utils.h" -#include "third_party/WebKit/public/web/WebCompositionUnderline.h" -#include "ui/base/ime/composition_underline.h" +#include "third_party/WebKit/public/web/WebImeTextSpan.h" +#include "ui/base/ime/ime_text_span.h" #include "ui/base/ime/input_method.h" #include "ui/base/ime/input_method_observer.h" @@ -268,22 +268,22 @@ void SendImeCommitTextToWidget( RenderWidgetHost* rwh, const base::string16& text, - const std::vector<ui::CompositionUnderline>& underlines, + const std::vector<ui::ImeTextSpan>& ime_text_spans, const gfx::Range& replacement_range, int relative_cursor_pos) { RenderWidgetHostImpl::From(rwh)->ImeCommitText( - text, underlines, replacement_range, relative_cursor_pos); + text, ime_text_spans, replacement_range, relative_cursor_pos); } void SendImeSetCompositionTextToWidget( RenderWidgetHost* rwh, const base::string16& text, - const std::vector<ui::CompositionUnderline>& underlines, + const std::vector<ui::ImeTextSpan>& ime_text_spans, const gfx::Range& replacement_range, int selection_start, int selection_end) { RenderWidgetHostImpl::From(rwh)->ImeSetComposition( - text, underlines, replacement_range, selection_start, selection_end); + text, ime_text_spans, replacement_range, selection_start, selection_end); } bool DestroyRenderWidgetHost(int32_t process_id,
diff --git a/content/public/test/text_input_test_utils.h b/content/public/test/text_input_test_utils.h index c8d9775..80c055c 100644 --- a/content/public/test/text_input_test_utils.h +++ b/content/public/test/text_input_test_utils.h
@@ -26,7 +26,7 @@ } namespace ui { -struct CompositionUnderline; +struct ImeTextSpan; } namespace content { @@ -74,7 +74,7 @@ void SendImeCommitTextToWidget( RenderWidgetHost* rwh, const base::string16& text, - const std::vector<ui::CompositionUnderline>& underlines, + const std::vector<ui::ImeTextSpan>& ime_text_spans, const gfx::Range& replacement_range, int relative_cursor_pos); @@ -83,7 +83,7 @@ void SendImeSetCompositionTextToWidget( RenderWidgetHost* rwh, const base::string16& text, - const std::vector<ui::CompositionUnderline>& underlines, + const std::vector<ui::ImeTextSpan>& ime_text_spans, const gfx::Range& replacement_range, int selection_start, int selection_end);
diff --git a/content/renderer/browser_plugin/browser_plugin.cc b/content/renderer/browser_plugin/browser_plugin.cc index 88ef96b5..9e281e4 100644 --- a/content/renderer/browser_plugin/browser_plugin.cc +++ b/content/renderer/browser_plugin/browser_plugin.cc
@@ -551,7 +551,7 @@ bool BrowserPlugin::SetComposition( const blink::WebString& text, - const blink::WebVector<blink::WebCompositionUnderline>& underlines, + const blink::WebVector<blink::WebImeTextSpan>& ime_text_spans, const blink::WebRange& replacementRange, int selectionStart, int selectionEnd) { @@ -560,8 +560,8 @@ BrowserPluginHostMsg_SetComposition_Params params; params.text = text.Utf16(); - for (size_t i = 0; i < underlines.size(); ++i) { - params.underlines.push_back(underlines[i]); + for (size_t i = 0; i < ime_text_spans.size(); ++i) { + params.ime_text_spans.push_back(ime_text_spans[i]); } params.replacement_range = @@ -580,15 +580,15 @@ bool BrowserPlugin::CommitText( const blink::WebString& text, - const blink::WebVector<blink::WebCompositionUnderline>& underlines, + const blink::WebVector<blink::WebImeTextSpan>& ime_text_spans, const blink::WebRange& replacementRange, int relative_cursor_pos) { if (!attached()) return false; - std::vector<blink::WebCompositionUnderline> std_underlines; - for (size_t i = 0; i < underlines.size(); ++i) { - std_underlines.push_back(underlines[i]); + std::vector<blink::WebImeTextSpan> std_ime_text_spans; + for (size_t i = 0; i < ime_text_spans.size(); ++i) { + std_ime_text_spans.push_back(ime_text_spans[i]); } gfx::Range replacement_range = replacementRange.IsNull() @@ -597,7 +597,7 @@ static_cast<uint32_t>(replacementRange.EndOffset())); BrowserPluginManager::Get()->Send(new BrowserPluginHostMsg_ImeCommitText( - browser_plugin_instance_id_, text.Utf16(), std_underlines, + browser_plugin_instance_id_, text.Utf16(), std_ime_text_spans, replacement_range, relative_cursor_pos)); // TODO(kochi): This assumes the IPC handling always succeeds. return true;
diff --git a/content/renderer/browser_plugin/browser_plugin.h b/content/renderer/browser_plugin/browser_plugin.h index 637002e8..74abac0 100644 --- a/content/renderer/browser_plugin/browser_plugin.h +++ b/content/renderer/browser_plugin/browser_plugin.h
@@ -14,8 +14,8 @@ #include "base/sequenced_task_runner_helpers.h" #include "content/renderer/mouse_lock_dispatcher.h" #include "content/renderer/render_view_impl.h" -#include "third_party/WebKit/public/web/WebCompositionUnderline.h" #include "third_party/WebKit/public/web/WebDragStatus.h" +#include "third_party/WebKit/public/web/WebImeTextSpan.h" #include "third_party/WebKit/public/web/WebInputMethodController.h" #include "third_party/WebKit/public/web/WebNode.h" @@ -111,15 +111,14 @@ const blink::WebString& value) override; bool SetComposition( const blink::WebString& text, - const blink::WebVector<blink::WebCompositionUnderline>& underlines, + const blink::WebVector<blink::WebImeTextSpan>& ime_text_spans, const blink::WebRange& replacementRange, int selectionStart, int selectionEnd) override; - bool CommitText( - const blink::WebString& text, - const blink::WebVector<blink::WebCompositionUnderline>& underlines, - const blink::WebRange& replacementRange, - int relative_cursor_pos) override; + bool CommitText(const blink::WebString& text, + const blink::WebVector<blink::WebImeTextSpan>& ime_text_spans, + const blink::WebRange& replacementRange, + int relative_cursor_pos) override; bool FinishComposingText( blink::WebInputMethodController::ConfirmCompositionBehavior selection_behavior) override;
diff --git a/content/renderer/dom_storage/dom_storage_cached_area.cc b/content/renderer/dom_storage/dom_storage_cached_area.cc index b2686d9..12480ea8c 100644 --- a/content/renderer/dom_storage/dom_storage_cached_area.cc +++ b/content/renderer/dom_storage/dom_storage_cached_area.cc
@@ -53,16 +53,15 @@ return false; PrimeIfNeeded(connection_id); - base::NullableString16 unused; - if (!map_->SetItem(key, value, &unused)) + base::NullableString16 old_value; + if (!map_->SetItem(key, value, &old_value)) return false; // Ignore mutations to 'key' until OnSetItemComplete. ignore_key_mutations_[key]++; - proxy_->SetItem( - connection_id, key, value, page_url, - base::Bind(&DOMStorageCachedArea::OnSetItemComplete, - weak_factory_.GetWeakPtr(), key)); + proxy_->SetItem(connection_id, key, value, old_value, page_url, + base::Bind(&DOMStorageCachedArea::OnSetItemComplete, + weak_factory_.GetWeakPtr(), key)); return true; } @@ -70,16 +69,16 @@ const base::string16& key, const GURL& page_url) { PrimeIfNeeded(connection_id); - base::string16 unused; - if (!map_->RemoveItem(key, &unused)) + base::string16 old_value; + if (!map_->RemoveItem(key, &old_value)) return; // Ignore mutations to 'key' until OnRemoveItemComplete. ignore_key_mutations_[key]++; - proxy_->RemoveItem( - connection_id, key, page_url, - base::Bind(&DOMStorageCachedArea::OnRemoveItemComplete, - weak_factory_.GetWeakPtr(), key)); + proxy_->RemoveItem(connection_id, key, + base::NullableString16(old_value, false), page_url, + base::Bind(&DOMStorageCachedArea::OnRemoveItemComplete, + weak_factory_.GetWeakPtr(), key)); } void DOMStorageCachedArea::Clear(int connection_id, const GURL& page_url) {
diff --git a/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc b/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc index 4c433271..46b3815e 100644 --- a/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc +++ b/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc
@@ -37,6 +37,7 @@ void SetItem(int connection_id, const base::string16& key, const base::string16& value, + const base::NullableString16& old_value, const GURL& page_url, const CompletionCallback& callback) override { pending_callbacks_.push_back(callback); @@ -49,6 +50,7 @@ void RemoveItem(int connection_id, const base::string16& key, + const base::NullableString16& old_value, const GURL& page_url, const CompletionCallback& callback) override { pending_callbacks_.push_back(callback);
diff --git a/content/renderer/dom_storage/dom_storage_dispatcher.cc b/content/renderer/dom_storage/dom_storage_dispatcher.cc index b52367a..9d2ec453 100644 --- a/content/renderer/dom_storage/dom_storage_dispatcher.cc +++ b/content/renderer/dom_storage/dom_storage_dispatcher.cc
@@ -114,10 +114,12 @@ void SetItem(int connection_id, const base::string16& key, const base::string16& value, + const base::NullableString16& old_value, const GURL& page_url, const CompletionCallback& callback) override; void RemoveItem(int connection_id, const base::string16& key, + const base::NullableString16& old_value, const GURL& page_url, const CompletionCallback& callback) override; void ClearArea(int connection_id, @@ -243,20 +245,26 @@ } void DomStorageDispatcher::ProxyImpl::SetItem( - int connection_id, const base::string16& key, - const base::string16& value, const GURL& page_url, + int connection_id, + const base::string16& key, + const base::string16& value, + const base::NullableString16& old_value, + const GURL& page_url, const CompletionCallback& callback) { PushPendingCallback(callback); throttling_filter_->SendThrottled(new DOMStorageHostMsg_SetItem( - connection_id, key, value, page_url)); + connection_id, key, value, old_value, page_url)); } void DomStorageDispatcher::ProxyImpl::RemoveItem( - int connection_id, const base::string16& key, const GURL& page_url, + int connection_id, + const base::string16& key, + const base::NullableString16& old_value, + const GURL& page_url, const CompletionCallback& callback) { PushPendingCallback(callback); throttling_filter_->SendThrottled(new DOMStorageHostMsg_RemoveItem( - connection_id, key, page_url)); + connection_id, key, old_value, page_url)); } void DomStorageDispatcher::ProxyImpl::ClearArea(int connection_id,
diff --git a/content/renderer/dom_storage/dom_storage_proxy.h b/content/renderer/dom_storage/dom_storage_proxy.h index 80cd87cdc..8fbd361 100644 --- a/content/renderer/dom_storage/dom_storage_proxy.h +++ b/content/renderer/dom_storage/dom_storage_proxy.h
@@ -26,11 +26,13 @@ virtual void SetItem(int connection_id, const base::string16& key, const base::string16& value, + const base::NullableString16& old_value, const GURL& page_url, const CompletionCallback& callback) = 0; virtual void RemoveItem(int connection_id, const base::string16& key, + const base::NullableString16& old_value, const GURL& page_url, const CompletionCallback& callback) = 0;
diff --git a/content/renderer/input/frame_input_handler_impl.cc b/content/renderer/input/frame_input_handler_impl.cc index ba35f657..637ebdcb 100644 --- a/content/renderer/input/frame_input_handler_impl.cc +++ b/content/renderer/input/frame_input_handler_impl.cc
@@ -66,11 +66,11 @@ void FrameInputHandlerImpl::SetCompositionFromExistingText( int32_t start, int32_t end, - const std::vector<ui::CompositionUnderline>& ui_underlines) { + const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) { if (!main_thread_task_runner_->BelongsToCurrentThread()) { RunOnMainThread( base::Bind(&FrameInputHandlerImpl::SetCompositionFromExistingText, - weak_this_, start, end, ui_underlines)); + weak_this_, start, end, ui_ime_text_spans)); return; } @@ -78,16 +78,17 @@ return; ImeEventGuard guard(render_frame_->GetRenderWidget()); - std::vector<blink::WebCompositionUnderline> underlines; - for (const auto& underline : ui_underlines) { - blink::WebCompositionUnderline blink_underline( - underline.start_offset, underline.end_offset, underline.color, - underline.thick, underline.background_color); - underlines.push_back(blink_underline); + std::vector<blink::WebImeTextSpan> ime_text_spans; + for (const auto& ime_text_span : ui_ime_text_spans) { + blink::WebImeTextSpan blink_ime_text_span( + ime_text_span.start_offset, ime_text_span.end_offset, + ime_text_span.color, ime_text_span.thick, + ime_text_span.background_color); + ime_text_spans.push_back(blink_ime_text_span); } render_frame_->GetWebFrame()->SetCompositionFromExistingText(start, end, - underlines); + ime_text_spans); } void FrameInputHandlerImpl::ExtendSelectionAndDelete(int32_t before,
diff --git a/content/renderer/input/frame_input_handler_impl.h b/content/renderer/input/frame_input_handler_impl.h index 705f816..6519950 100644 --- a/content/renderer/input/frame_input_handler_impl.h +++ b/content/renderer/input/frame_input_handler_impl.h
@@ -44,7 +44,7 @@ void SetCompositionFromExistingText( int32_t start, int32_t end, - const std::vector<ui::CompositionUnderline>& underlines) override; + const std::vector<ui::ImeTextSpan>& ime_text_spans) override; void ExtendSelectionAndDelete(int32_t before, int32_t after) override; void DeleteSurroundingText(int32_t before, int32_t after) override; void DeleteSurroundingTextInCodePoints(int32_t before,
diff --git a/content/renderer/input/widget_input_handler_impl.cc b/content/renderer/input/widget_input_handler_impl.cc index a042d773..d82da0f 100644 --- a/content/renderer/input/widget_input_handler_impl.cc +++ b/content/renderer/input/widget_input_handler_impl.cc
@@ -24,17 +24,17 @@ namespace { -std::vector<blink::WebCompositionUnderline> -ConvertUIUnderlinesToBlinkUnderlines( - const std::vector<ui::CompositionUnderline>& ui_underlines) { - std::vector<blink::WebCompositionUnderline> underlines; - for (const auto& underline : ui_underlines) { - blink::WebCompositionUnderline blink_underline( - underline.start_offset, underline.end_offset, underline.color, - underline.thick, underline.background_color); - underlines.push_back(blink_underline); +std::vector<blink::WebImeTextSpan> ConvertUIImeTextSpansToBlinkImeTextSpans( + const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) { + std::vector<blink::WebImeTextSpan> ime_text_spans; + for (const auto& ime_text_span : ui_ime_text_spans) { + blink::WebImeTextSpan blink_ime_text_span( + ime_text_span.start_offset, ime_text_span.end_offset, + ime_text_span.color, ime_text_span.thick, + ime_text_span.background_color); + ime_text_spans.push_back(blink_ime_text_span); } - return underlines; + return ime_text_spans; } } // namespace @@ -89,24 +89,25 @@ void WidgetInputHandlerImpl::ImeSetComposition( const base::string16& text, - const std::vector<ui::CompositionUnderline>& underlines, + const std::vector<ui::ImeTextSpan>& ime_text_spans, const gfx::Range& range, int32_t start, int32_t end) { - RunOnMainThread(base::Bind( - &RenderWidget::OnImeSetComposition, render_widget_, text, - ConvertUIUnderlinesToBlinkUnderlines(underlines), range, start, end)); + RunOnMainThread( + base::Bind(&RenderWidget::OnImeSetComposition, render_widget_, text, + ConvertUIImeTextSpansToBlinkImeTextSpans(ime_text_spans), + range, start, end)); } void WidgetInputHandlerImpl::ImeCommitText( const base::string16& text, - const std::vector<ui::CompositionUnderline>& underlines, + const std::vector<ui::ImeTextSpan>& ime_text_spans, const gfx::Range& range, int32_t relative_cursor_position) { - RunOnMainThread(base::Bind(&RenderWidget::OnImeCommitText, render_widget_, - text, - ConvertUIUnderlinesToBlinkUnderlines(underlines), - range, relative_cursor_position)); + RunOnMainThread( + base::Bind(&RenderWidget::OnImeCommitText, render_widget_, text, + ConvertUIImeTextSpansToBlinkImeTextSpans(ime_text_spans), + range, relative_cursor_position)); } void WidgetInputHandlerImpl::ImeFinishComposingText(bool keep_selection) {
diff --git a/content/renderer/input/widget_input_handler_impl.h b/content/renderer/input/widget_input_handler_impl.h index c05ac43..5c5cddc2 100644 --- a/content/renderer/input/widget_input_handler_impl.h +++ b/content/renderer/input/widget_input_handler_impl.h
@@ -36,14 +36,13 @@ void SetEditCommandsForNextKeyEvent( const std::vector<EditCommand>& commands) override; void CursorVisibilityChanged(bool visible) override; - void ImeSetComposition( - const base::string16& text, - const std::vector<ui::CompositionUnderline>& underlines, - const gfx::Range& range, - int32_t start, - int32_t end) override; + void ImeSetComposition(const base::string16& text, + const std::vector<ui::ImeTextSpan>& ime_text_spans, + const gfx::Range& range, + int32_t start, + int32_t end) override; void ImeCommitText(const base::string16& text, - const std::vector<ui::CompositionUnderline>& underlines, + const std::vector<ui::ImeTextSpan>& ime_text_spans, const gfx::Range& range, int32_t relative_cursor_position) override; void ImeFinishComposingText(bool keep_selection) override;
diff --git a/content/renderer/media/local_media_stream_audio_source.cc b/content/renderer/media/local_media_stream_audio_source.cc index 2c7f1aa8..4d2e913 100644 --- a/content/renderer/media/local_media_stream_audio_source.cc +++ b/content/renderer/media/local_media_stream_audio_source.cc
@@ -22,24 +22,23 @@ MediaStreamSource::SetDeviceInfo(device_info); // If the device buffer size was not provided, use a default. - int frames_per_buffer = device_info.device.input.frames_per_buffer; + int frames_per_buffer = device_info.device.input.frames_per_buffer(); if (frames_per_buffer <= 0) { // TODO(miu): Like in ProcessedLocalAudioSource::GetBufferSize(), we should // re-evaluate whether Android needs special treatment here. Or, perhaps we // should just DCHECK_GT(device_info...frames_per_buffer, 0)? // http://crbug.com/638081 #if defined(OS_ANDROID) - frames_per_buffer = device_info.device.input.sample_rate / 50; // 20 ms + frames_per_buffer = device_info.device.input.sample_rate() / 50; // 20 ms #else - frames_per_buffer = device_info.device.input.sample_rate / 100; // 10 ms + frames_per_buffer = device_info.device.input.sample_rate() / 100; // 10 ms #endif } MediaStreamAudioSource::SetFormat(media::AudioParameters( media::AudioParameters::AUDIO_PCM_LOW_LATENCY, - static_cast<media::ChannelLayout>( - device_info.device.input.channel_layout), - device_info.device.input.sample_rate, + device_info.device.input.channel_layout(), + device_info.device.input.sample_rate(), 16, // Legacy parameter (data is always in 32-bit float format). frames_per_buffer)); }
diff --git a/content/renderer/media/media_stream_audio_processor_options.cc b/content/renderer/media/media_stream_audio_processor_options.cc index 5fdd272..70ce8ad6 100644 --- a/content/renderer/media/media_stream_audio_processor_options.cc +++ b/content/renderer/media/media_stream_audio_processor_options.cc
@@ -292,9 +292,9 @@ // static AudioProcessingProperties AudioProcessingProperties::FromConstraints( const blink::WebMediaConstraints& constraints, - const MediaStreamDevice::AudioDeviceParameters& input_params) { + const media::AudioParameters& input_params) { DCHECK(IsOldAudioConstraints()); - MediaAudioConstraints audio_constraints(constraints, input_params.effects); + MediaAudioConstraints audio_constraints(constraints, input_params.effects()); AudioProcessingProperties properties; properties.enable_sw_echo_cancellation = audio_constraints.GetEchoCancellationProperty(); @@ -524,14 +524,14 @@ std::vector<media::Point> GetArrayGeometryPreferringConstraints( const MediaAudioConstraints& audio_constraints, - const MediaStreamDevice::AudioDeviceParameters& input_params) { + const media::AudioParameters& input_params) { const std::string constraints_geometry = audio_constraints.GetGoogArrayGeometry(); // Give preference to the audio constraint over the device-supplied mic // positions. This is mainly for testing purposes. return constraints_geometry.empty() - ? input_params.mic_positions + ? input_params.mic_positions() : media::ParsePointsFromString(constraints_geometry); }
diff --git a/content/renderer/media/media_stream_audio_processor_options.h b/content/renderer/media/media_stream_audio_processor_options.h index dde2d23..ee9619e 100644 --- a/content/renderer/media/media_stream_audio_processor_options.h +++ b/content/renderer/media/media_stream_audio_processor_options.h
@@ -117,7 +117,7 @@ // TODO(guidou): Remove this function. http://crbug.com/706408 static AudioProcessingProperties FromConstraints( const blink::WebMediaConstraints& constraints, - const MediaStreamDevice::AudioDeviceParameters& input_params); + const media::AudioParameters& input_params); bool enable_sw_echo_cancellation = true; bool disable_hw_echo_cancellation = false; @@ -213,7 +213,7 @@ // TODO(guidou): Remove this function. http://crbug.com/706408 CONTENT_EXPORT std::vector<media::Point> GetArrayGeometryPreferringConstraints( const MediaAudioConstraints& audio_constraints, - const MediaStreamDevice::AudioDeviceParameters& input_params); + const media::AudioParameters& input_params); // TODO(guidou): Remove this function. http://crbug.com/706408 CONTENT_EXPORT bool IsOldAudioConstraints();
diff --git a/content/renderer/media/media_stream_audio_processor_unittest.cc b/content/renderer/media/media_stream_audio_processor_unittest.cc index 9aada88..5f55168 100644 --- a/content/renderer/media/media_stream_audio_processor_unittest.cc +++ b/content/renderer/media/media_stream_audio_processor_unittest.cc
@@ -220,7 +220,6 @@ base::MessageLoop main_thread_message_loop_; media::AudioParameters params_; - MediaStreamDevice::AudioDeviceParameters input_device_params_; // TODO(guidou): Remove this field. http://crbug.com/706408 base::test::ScopedFeatureList scoped_feature_list_; @@ -383,7 +382,7 @@ { // Both geometries empty. MockConstraintFactory constraint_factory; - MediaStreamDevice::AudioDeviceParameters input_params; + media::AudioParameters input_params; const auto& actual_geometry = GetArrayGeometryPreferringConstraints( MakeMediaAudioConstraints(constraint_factory), input_params); @@ -392,9 +391,13 @@ { // Constraints geometry empty. MockConstraintFactory constraint_factory; - MediaStreamDevice::AudioDeviceParameters input_params; - input_params.mic_positions.push_back(media::Point(0, 0, 0)); - input_params.mic_positions.push_back(media::Point(0, 0.05f, 0)); + + std::vector<media::Point> mic_positions; + mic_positions.push_back(media::Point(0, 0, 0)); + mic_positions.push_back(media::Point(0, 0.05f, 0)); + + media::AudioParameters input_params; + input_params.set_mic_positions(mic_positions); const auto& actual_geometry = GetArrayGeometryPreferringConstraints( MakeMediaAudioConstraints(constraint_factory), input_params); @@ -405,7 +408,7 @@ MockConstraintFactory constraint_factory; constraint_factory.AddAdvanced().goog_array_geometry.SetExact( blink::WebString::FromUTF8("-0.02 0 0 0.02 0 0")); - MediaStreamDevice::AudioDeviceParameters input_params; + media::AudioParameters input_params; const auto& actual_geometry = GetArrayGeometryPreferringConstraints( MakeMediaAudioConstraints(constraint_factory), input_params); @@ -416,9 +419,13 @@ MockConstraintFactory constraint_factory; constraint_factory.AddAdvanced().goog_array_geometry.SetExact( blink::WebString::FromUTF8("-0.02 0 0 0.02 0 0")); - MediaStreamDevice::AudioDeviceParameters input_params; - input_params.mic_positions.push_back(media::Point(0, 0, 0)); - input_params.mic_positions.push_back(media::Point(0, 0.05f, 0)); + + std::vector<media::Point> mic_positions; + mic_positions.push_back(media::Point(0, 0, 0)); + mic_positions.push_back(media::Point(0, 0.05f, 0)); + + media::AudioParameters input_params; + input_params.set_mic_positions(mic_positions); // Constraints geometry is preferred. const auto& actual_geometry = GetArrayGeometryPreferringConstraints(
diff --git a/content/renderer/media/mock_media_stream_dispatcher.cc b/content/renderer/media/mock_media_stream_dispatcher.cc index a4b3fe5..5af1804c 100644 --- a/content/renderer/media/mock_media_stream_dispatcher.cc +++ b/content/renderer/media/mock_media_stream_dispatcher.cc
@@ -96,9 +96,10 @@ kAudioOutputDeviceIdPrefix + base::IntToString(session_id_); } audio.session_id = session_id_; - audio.device.input.sample_rate = media::AudioParameters::kAudioCDSampleRate; - audio.device.input.channel_layout = media::CHANNEL_LAYOUT_STEREO; - audio.device.input.frames_per_buffer = audio.device.input.sample_rate / 100; + audio.device.input = media::AudioParameters( + media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO, + media::AudioParameters::kAudioCDSampleRate, 0, + media::AudioParameters::kAudioCDSampleRate / 100); audio_input_array_.push_back(audio); }
diff --git a/content/renderer/media/user_media_client_impl.cc b/content/renderer/media/user_media_client_impl.cc index ed7ec65..bb26affa 100644 --- a/content/renderer/media/user_media_client_impl.cc +++ b/content/renderer/media/user_media_client_impl.cc
@@ -1086,7 +1086,7 @@ for (auto& device_info : overridden_audio_array) { device_info.device.matched_output_device_id = ""; device_info.device.matched_output = - MediaStreamDevice::AudioDeviceParameters(); + media::AudioParameters::UnavailableDeviceParams(); } }
diff --git a/content/renderer/media/webrtc/processed_local_audio_source.cc b/content/renderer/media/webrtc/processed_local_audio_source.cc index 6fea798..d3a4a35 100644 --- a/content/renderer/media/webrtc/processed_local_audio_source.cc +++ b/content/renderer/media/webrtc/processed_local_audio_source.cc
@@ -87,21 +87,22 @@ ", channel_layout=%d, sample_rate=%d, buffer_size=%d" ", session_id=%d, paired_output_sample_rate=%d" ", paired_output_frames_per_buffer=%d, effects=%d. ", - consumer_render_frame_id_, device_info().device.input.channel_layout, - device_info().device.input.sample_rate, - device_info().device.input.frames_per_buffer, device_info().session_id, - device_info().device.matched_output.sample_rate, - device_info().device.matched_output.frames_per_buffer, - device_info().device.input.effects)); + consumer_render_frame_id_, device_info().device.input.channel_layout(), + device_info().device.input.sample_rate(), + device_info().device.input.frames_per_buffer(), device_info().session_id, + device_info().device.matched_output.sample_rate(), + device_info().device.matched_output.frames_per_buffer(), + device_info().device.input.effects())); // Disable HW echo cancellation if constraints explicitly specified no // echo cancellation. if (audio_processing_properties_.disable_hw_echo_cancellation && - (device_info().device.input.effects & + (device_info().device.input.effects() & media::AudioParameters::ECHO_CANCELLER)) { StreamDeviceInfo modified_device_info(device_info()); - modified_device_info.device.input.effects &= - ~media::AudioParameters::ECHO_CANCELLER; + modified_device_info.device.input.set_effects( + modified_device_info.device.input.effects() & + ~media::AudioParameters::ECHO_CANCELLER); SetDeviceInfo(modified_device_info); } @@ -119,9 +120,9 @@ // If KEYBOARD_MIC effect is set, change the layout to the corresponding // layout that includes the keyboard mic. - media::ChannelLayout channel_layout = static_cast<media::ChannelLayout>( - device_info().device.input.channel_layout); - if ((device_info().device.input.effects & + media::ChannelLayout channel_layout = + device_info().device.input.channel_layout(); + if ((device_info().device.input.effects() & media::AudioParameters::KEYBOARD_MIC) && audio_processing_properties_.goog_experimental_noise_suppression) { if (channel_layout == media::CHANNEL_LAYOUT_STEREO) { @@ -150,14 +151,15 @@ } DVLOG(1) << "Audio input hardware sample rate: " - << device_info().device.input.sample_rate; + << device_info().device.input.sample_rate(); media::AudioSampleRate asr; - if (media::ToAudioSampleRate(device_info().device.input.sample_rate, &asr)) { + if (media::ToAudioSampleRate(device_info().device.input.sample_rate(), + &asr)) { UMA_HISTOGRAM_ENUMERATION( "WebRTC.AudioInputSampleRate", asr, media::kAudioSampleRateMax + 1); } else { UMA_HISTOGRAM_COUNTS("WebRTC.AudioInputSampleRateUnexpected", - device_info().device.input.sample_rate); + device_info().device.input.sample_rate()); } // Determine the audio format required of the AudioCapturerSource. Then, pass @@ -165,9 +167,9 @@ // ProcessedLocalAudioSource to the processor's output format. media::AudioParameters params( media::AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, - device_info().device.input.sample_rate, 16, - GetBufferSize(device_info().device.input.sample_rate)); - params.set_effects(device_info().device.input.effects); + device_info().device.input.sample_rate(), 16, + GetBufferSize(device_info().device.input.sample_rate())); + params.set_effects(device_info().device.input.effects()); DCHECK(params.IsValid()); audio_processor_->OnCaptureFormatChanged(params); MediaStreamAudioSource::SetFormat(audio_processor_->OutputFormat()); @@ -356,7 +358,7 @@ // If audio processing is off and the native hardware buffer size was // provided, use it. It can be harmful, in terms of CPU/power consumption, to // use smaller buffer sizes than the native size (http://crbug.com/362261). - if (int hardware_buffer_size = device_info().device.input.frames_per_buffer) + if (int hardware_buffer_size = device_info().device.input.frames_per_buffer()) return hardware_buffer_size; // If the buffer size is missing from the StreamDeviceInfo, provide 10ms as a
diff --git a/content/renderer/media/webrtc_audio_device_impl.cc b/content/renderer/media/webrtc_audio_device_impl.cc index a7111d0e..147c1f5 100644 --- a/content/renderer/media/webrtc_audio_device_impl.cc +++ b/content/renderer/media/webrtc_audio_device_impl.cc
@@ -487,15 +487,15 @@ // Don't set output parameters unless all of them are valid. const StreamDeviceInfo& device_info = capturers_.back()->device_info(); if (device_info.session_id <= 0 || - !device_info.device.matched_output.sample_rate || - !device_info.device.matched_output.frames_per_buffer) { + !device_info.device.matched_output.sample_rate() || + !device_info.device.matched_output.frames_per_buffer()) { return false; } *session_id = device_info.session_id; - *output_sample_rate = device_info.device.matched_output.sample_rate; + *output_sample_rate = device_info.device.matched_output.sample_rate(); *output_frames_per_buffer = - device_info.device.matched_output.frames_per_buffer; + device_info.device.matched_output.frames_per_buffer(); return true; }
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc index ea83dcf..f4692bf 100644 --- a/content/renderer/pepper/pepper_plugin_instance_impl.cc +++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -110,9 +110,9 @@ #include "third_party/WebKit/public/platform/WebURL.h" #include "third_party/WebKit/public/platform/WebURLError.h" #include "third_party/WebKit/public/platform/WebURLRequest.h" -#include "third_party/WebKit/public/web/WebCompositionUnderline.h" #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebDocumentLoader.h" +#include "third_party/WebKit/public/web/WebImeTextSpan.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" #include "third_party/WebKit/public/web/WebPluginContainer.h" #include "third_party/WebKit/public/web/WebPluginScriptForbiddenScope.h" @@ -945,22 +945,19 @@ bool PepperPluginInstanceImpl::SendCompositionEventToPlugin( PP_InputEvent_Type type, const base::string16& text) { - std::vector<blink::WebCompositionUnderline> empty; - return SendCompositionEventWithUnderlineInformationToPlugin( - type, - text, - empty, - static_cast<int>(text.size()), + std::vector<blink::WebImeTextSpan> empty; + return SendCompositionEventWithImeTextSpanInformationToPlugin( + type, text, empty, static_cast<int>(text.size()), static_cast<int>(text.size())); } -bool -PepperPluginInstanceImpl::SendCompositionEventWithUnderlineInformationToPlugin( - PP_InputEvent_Type type, - const base::string16& text, - const std::vector<blink::WebCompositionUnderline>& underlines, - int selection_start, - int selection_end) { +bool PepperPluginInstanceImpl:: + SendCompositionEventWithImeTextSpanInformationToPlugin( + PP_InputEvent_Type type, + const base::string16& text, + const std::vector<blink::WebImeTextSpan>& ime_text_spans, + int selection_start, + int selection_end) { // Keep a reference on the stack. See NOTE above. scoped_refptr<PepperPluginInstanceImpl> ref(this); @@ -981,9 +978,9 @@ std::vector<size_t> utf16_offsets; utf16_offsets.push_back(selection_start); utf16_offsets.push_back(selection_end); - for (size_t i = 0; i < underlines.size(); ++i) { - utf16_offsets.push_back(underlines[i].start_offset); - utf16_offsets.push_back(underlines[i].end_offset); + for (size_t i = 0; i < ime_text_spans.size(); ++i) { + utf16_offsets.push_back(ime_text_spans[i].start_offset); + utf16_offsets.push_back(ime_text_spans[i].end_offset); } std::vector<size_t> utf8_offsets(utf16_offsets); event.character_text = base::UTF16ToUTF8AndAdjustOffsets(text, &utf8_offsets); @@ -1006,8 +1003,8 @@ offset_set.end()); // Set the composition target. - for (size_t i = 0; i < underlines.size(); ++i) { - if (underlines[i].thick) { + for (size_t i = 0; i < ime_text_spans.size(); ++i) { + if (ime_text_spans[i].thick) { std::vector<uint32_t>::iterator it = std::find(event.composition_segment_offsets.begin(), event.composition_segment_offsets.end(), @@ -1049,15 +1046,12 @@ bool PepperPluginInstanceImpl::HandleCompositionUpdate( const base::string16& text, - const std::vector<blink::WebCompositionUnderline>& underlines, + const std::vector<blink::WebImeTextSpan>& ime_text_spans, int selection_start, int selection_end) { - return SendCompositionEventWithUnderlineInformationToPlugin( - PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE, - text, - underlines, - selection_start, - selection_end); + return SendCompositionEventWithImeTextSpanInformationToPlugin( + PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE, text, ime_text_spans, + selection_start, selection_end); } bool PepperPluginInstanceImpl::HandleCompositionEnd( @@ -2335,7 +2329,7 @@ return false; render_frame_->SimulateImeCommitText( base::UTF8ToUTF16(input_event.character_text), - std::vector<blink::WebCompositionUnderline>(), gfx::Range()); + std::vector<blink::WebImeTextSpan>(), gfx::Range()); break; default: return false; @@ -2358,18 +2352,18 @@ base::string16 utf16_text = base::UTF8ToUTF16AndAdjustOffsets(input_event.character_text, &offsets); - std::vector<blink::WebCompositionUnderline> underlines; + std::vector<blink::WebImeTextSpan> ime_text_spans; for (size_t i = 2; i + 1 < offsets.size(); ++i) { - blink::WebCompositionUnderline underline; - underline.start_offset = offsets[i]; - underline.end_offset = offsets[i + 1]; + blink::WebImeTextSpan ime_text_span; + ime_text_span.start_offset = offsets[i]; + ime_text_span.end_offset = offsets[i + 1]; if (input_event.composition_target_segment == static_cast<int32_t>(i - 2)) - underline.thick = true; - underlines.push_back(underline); + ime_text_span.thick = true; + ime_text_spans.push_back(ime_text_span); } - render_frame_->SimulateImeSetComposition( - utf16_text, underlines, offsets[0], offsets[1]); + render_frame_->SimulateImeSetComposition(utf16_text, ime_text_spans, + offsets[0], offsets[1]); } ContentDecryptorDelegate*
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.h b/content/renderer/pepper/pepper_plugin_instance_impl.h index f0cc2331..11e1961d 100644 --- a/content/renderer/pepper/pepper_plugin_instance_impl.h +++ b/content/renderer/pepper/pepper_plugin_instance_impl.h
@@ -78,7 +78,7 @@ class WebMouseEvent; class WebPluginContainer; class WebURLResponse; -struct WebCompositionUnderline; +struct WebImeTextSpan; struct WebCursorInfo; struct WebURLError; struct WebPrintParams; @@ -240,7 +240,7 @@ bool HandleCompositionStart(const base::string16& text); bool HandleCompositionUpdate( const base::string16& text, - const std::vector<blink::WebCompositionUnderline>& underlines, + const std::vector<blink::WebImeTextSpan>& ime_text_spans, int selection_start, int selection_end); bool HandleCompositionEnd(const base::string16& text); @@ -688,10 +688,10 @@ // Internal helper functions for HandleCompositionXXX(). bool SendCompositionEventToPlugin(PP_InputEvent_Type type, const base::string16& text); - bool SendCompositionEventWithUnderlineInformationToPlugin( + bool SendCompositionEventWithImeTextSpanInformationToPlugin( PP_InputEvent_Type type, const base::string16& text, - const std::vector<blink::WebCompositionUnderline>& underlines, + const std::vector<blink::WebImeTextSpan>& ime_text_spans, int selection_start, int selection_end);
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index f0b6745..971139b7 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -1478,19 +1478,19 @@ void RenderFrameImpl::SimulateImeSetComposition( const base::string16& text, - const std::vector<blink::WebCompositionUnderline>& underlines, + const std::vector<blink::WebImeTextSpan>& ime_text_spans, int selection_start, int selection_end) { - render_view_->OnImeSetComposition( - text, underlines, gfx::Range::InvalidRange(), - selection_start, selection_end); + render_view_->OnImeSetComposition(text, ime_text_spans, + gfx::Range::InvalidRange(), selection_start, + selection_end); } void RenderFrameImpl::SimulateImeCommitText( const base::string16& text, - const std::vector<blink::WebCompositionUnderline>& underlines, + const std::vector<blink::WebImeTextSpan>& ime_text_spans, const gfx::Range& replacement_range) { - render_view_->OnImeCommitText(text, underlines, replacement_range, 0); + render_view_->OnImeCommitText(text, ime_text_spans, replacement_range, 0); } void RenderFrameImpl::SimulateImeFinishComposingText(bool keep_selection) { @@ -1499,7 +1499,7 @@ void RenderFrameImpl::OnImeSetComposition( const base::string16& text, - const std::vector<blink::WebCompositionUnderline>& underlines, + const std::vector<blink::WebImeTextSpan>& ime_text_spans, int selection_start, int selection_end) { // When a PPAPI plugin has focus, we bypass WebKit. @@ -1523,7 +1523,8 @@ // Nonempty: composition is ongoing. if (!pepper_composition_text_.empty()) { focused_pepper_plugin_->HandleCompositionUpdate( - pepper_composition_text_, underlines, selection_start, selection_end); + pepper_composition_text_, ime_text_spans, selection_start, + selection_end); } } } @@ -2215,10 +2216,11 @@ } void RenderFrameImpl::OnSetCompositionFromExistingText( - int start, int end, - const std::vector<blink::WebCompositionUnderline>& underlines) { + int start, + int end, + const std::vector<blink::WebImeTextSpan>& ime_text_spans) { ImeEventGuard guard(GetRenderWidget()); - frame_->SetCompositionFromExistingText(start, end, underlines); + frame_->SetCompositionFromExistingText(start, end, ime_text_spans); } void RenderFrameImpl::OnExecuteNoValueEditCommand(const std::string& name) {
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index d83c434..8b5770dd 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -103,7 +103,7 @@ class WebPresentationClient; class WebPushClient; class WebSecurityOrigin; -struct WebCompositionUnderline; +struct WebImeTextSpan; struct WebContextMenuData; struct WebCursorInfo; struct WebFindOptions; @@ -372,12 +372,12 @@ // Simulates IME events for testing purpose. void SimulateImeSetComposition( const base::string16& text, - const std::vector<blink::WebCompositionUnderline>& underlines, + const std::vector<blink::WebImeTextSpan>& ime_text_spans, int selection_start, int selection_end); void SimulateImeCommitText( const base::string16& text, - const std::vector<blink::WebCompositionUnderline>& underlines, + const std::vector<blink::WebImeTextSpan>& ime_text_spans, const gfx::Range& replacement_range); void SimulateImeFinishComposingText(bool keep_selection); @@ -385,7 +385,7 @@ // RenderFrame. void OnImeSetComposition( const base::string16& text, - const std::vector<blink::WebCompositionUnderline>& underlines, + const std::vector<blink::WebImeTextSpan>& ime_text_spans, int selection_start, int selection_end); void OnImeCommitText(const base::string16& text, @@ -940,8 +940,9 @@ void OnVisualStateRequest(uint64_t key); void OnSetEditableSelectionOffsets(int start, int end); void OnSetCompositionFromExistingText( - int start, int end, - const std::vector<blink::WebCompositionUnderline>& underlines); + int start, + int end, + const std::vector<blink::WebImeTextSpan>& ime_text_spans); void OnExecuteNoValueEditCommand(const std::string& name); void OnExtendSelectionAndDelete(int before, int after); void OnDeleteSurroundingText(int before, int after);
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 6ce744eb..ed991b7 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -669,13 +669,13 @@ IsRunningInMash() ? ui::mojom::kServiceName : mojom::kBrowserServiceName, GetIOTaskRunner()); - cc::mojom::SharedBitmapAllocationNotifierPtr + viz::mojom::SharedBitmapAllocationNotifierPtr shared_bitmap_allocation_notifier_ptr; GetConnector()->BindInterface( mojom::kBrowserServiceName, mojo::MakeRequest(&shared_bitmap_allocation_notifier_ptr)); shared_bitmap_manager_ = base::MakeUnique<viz::ClientSharedBitmapManager>( - cc::mojom::ThreadSafeSharedBitmapAllocationNotifierPtr::Create( + viz::mojom::ThreadSafeSharedBitmapAllocationNotifierPtr::Create( shared_bitmap_allocation_notifier_ptr.PassInterface(), GetChannel()->ipc_task_runner_refptr()));
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index dec950f..8a8b844 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc
@@ -1256,15 +1256,13 @@ case IME_SETCOMPOSITION: view()->OnImeSetComposition( base::WideToUTF16(ime_message->ime_string), - std::vector<blink::WebCompositionUnderline>(), - gfx::Range::InvalidRange(), - ime_message->selection_start, - ime_message->selection_end); + std::vector<blink::WebImeTextSpan>(), gfx::Range::InvalidRange(), + ime_message->selection_start, ime_message->selection_end); break; case IME_COMMITTEXT: view()->OnImeCommitText(base::WideToUTF16(ime_message->ime_string), - std::vector<blink::WebCompositionUnderline>(), + std::vector<blink::WebImeTextSpan>(), gfx::Range::InvalidRange(), 0); break; @@ -1273,11 +1271,9 @@ break; case IME_CANCELCOMPOSITION: - view()->OnImeSetComposition( - base::string16(), - std::vector<blink::WebCompositionUnderline>(), - gfx::Range::InvalidRange(), - 0, 0); + view()->OnImeSetComposition(base::string16(), + std::vector<blink::WebImeTextSpan>(), + gfx::Range::InvalidRange(), 0, 0); break; } @@ -1511,48 +1507,44 @@ ExecuteJavaScriptForTests("document.getElementById('test').focus();"); const base::string16 empty_string; - const std::vector<blink::WebCompositionUnderline> empty_underline; + const std::vector<blink::WebImeTextSpan> empty_ime_text_span; std::vector<gfx::Rect> bounds; view()->OnSetFocus(true); // ASCII composition const base::string16 ascii_composition = base::UTF8ToUTF16("aiueo"); - view()->OnImeSetComposition(ascii_composition, empty_underline, + view()->OnImeSetComposition(ascii_composition, empty_ime_text_span, gfx::Range::InvalidRange(), 0, 0); view()->GetCompositionCharacterBounds(&bounds); ASSERT_EQ(ascii_composition.size(), bounds.size()); for (size_t i = 0; i < bounds.size(); ++i) EXPECT_LT(0, bounds[i].width()); - view()->OnImeCommitText(empty_string, - std::vector<blink::WebCompositionUnderline>(), + view()->OnImeCommitText(empty_string, std::vector<blink::WebImeTextSpan>(), gfx::Range::InvalidRange(), 0); // Non surrogate pair unicode character. const base::string16 unicode_composition = base::UTF8ToUTF16( "\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86\xE3\x81\x88\xE3\x81\x8A"); - view()->OnImeSetComposition(unicode_composition, empty_underline, + view()->OnImeSetComposition(unicode_composition, empty_ime_text_span, gfx::Range::InvalidRange(), 0, 0); view()->GetCompositionCharacterBounds(&bounds); ASSERT_EQ(unicode_composition.size(), bounds.size()); for (size_t i = 0; i < bounds.size(); ++i) EXPECT_LT(0, bounds[i].width()); - view()->OnImeCommitText(empty_string, empty_underline, + view()->OnImeCommitText(empty_string, empty_ime_text_span, gfx::Range::InvalidRange(), 0); // Surrogate pair character. const base::string16 surrogate_pair_char = base::UTF8ToUTF16("\xF0\xA0\xAE\x9F"); - view()->OnImeSetComposition(surrogate_pair_char, - empty_underline, - gfx::Range::InvalidRange(), - 0, - 0); + view()->OnImeSetComposition(surrogate_pair_char, empty_ime_text_span, + gfx::Range::InvalidRange(), 0, 0); view()->GetCompositionCharacterBounds(&bounds); ASSERT_EQ(surrogate_pair_char.size(), bounds.size()); EXPECT_LT(0, bounds[0].width()); EXPECT_EQ(0, bounds[1].width()); - view()->OnImeCommitText(empty_string, empty_underline, + view()->OnImeCommitText(empty_string, empty_ime_text_span, gfx::Range::InvalidRange(), 0); // Mixed string. @@ -1563,10 +1555,8 @@ const bool is_surrogate_pair_empty_rect[8] = { false, true, false, false, true, false, false, true }; view()->OnImeSetComposition(surrogate_pair_mixed_composition, - empty_underline, - gfx::Range::InvalidRange(), - 0, - 0); + empty_ime_text_span, gfx::Range::InvalidRange(), + 0, 0); view()->GetCompositionCharacterBounds(&bounds); ASSERT_EQ(utf16_length, bounds.size()); for (size_t i = 0; i < utf16_length; ++i) { @@ -1576,7 +1566,7 @@ EXPECT_LT(0, bounds[i].width()); } } - view()->OnImeCommitText(empty_string, empty_underline, + view()->OnImeCommitText(empty_string, empty_ime_text_span, gfx::Range::InvalidRange(), 0); } #endif @@ -1592,8 +1582,8 @@ "</html>"); ExecuteJavaScriptForTests("document.getElementById('test1').focus();"); frame()->SetEditableSelectionOffsets(4, 8); - const std::vector<blink::WebCompositionUnderline> empty_underline; - frame()->SetCompositionFromExistingText(7, 10, empty_underline); + const std::vector<blink::WebImeTextSpan> empty_ime_text_span; + frame()->SetCompositionFromExistingText(7, 10, empty_ime_text_span); blink::WebInputMethodController* controller = frame()->GetWebFrame()->GetInputMethodController(); blink::WebTextInputInfo info = controller->TextInputInfo(); @@ -2457,13 +2447,13 @@ ExecuteJavaScriptForTests("document.getElementById('test').focus();"); const base::string16 empty_string; - const std::vector<blink::WebCompositionUnderline> empty_underline; + const std::vector<blink::WebImeTextSpan> empty_ime_text_span; std::vector<gfx::Rect> bounds_at_1x; view()->OnSetFocus(true); // ASCII composition const base::string16 ascii_composition = base::UTF8ToUTF16("aiueo"); - view()->OnImeSetComposition(ascii_composition, empty_underline, + view()->OnImeSetComposition(ascii_composition, empty_ime_text_span, gfx::Range::InvalidRange(), 0, 0); view()->GetCompositionCharacterBounds(&bounds_at_1x); ASSERT_EQ(ascii_composition.size(), bounds_at_1x.size());
diff --git a/content/renderer/render_view_browsertest_mac.mm b/content/renderer/render_view_browsertest_mac.mm index c425813..21e28f8 100644 --- a/content/renderer/render_view_browsertest_mac.mm +++ b/content/renderer/render_view_browsertest_mac.mm
@@ -23,7 +23,7 @@ #include <Cocoa/Cocoa.h> using blink::WebFrameContentDumper; -using blink::WebCompositionUnderline; +using blink::WebImeTextSpan; namespace content { @@ -182,11 +182,11 @@ // Simulate some IME related IPCs. using Text = base::string16; - using Underlines = std::vector<blink::WebCompositionUnderline>; + using ImeTextSpans = std::vector<blink::WebImeTextSpan>; view->OnMessageReceived(InputMsg_ImeSetComposition( - routing_id, Text(), Underlines(), Range(), 0, 0)); + routing_id, Text(), ImeTextSpans(), Range(), 0, 0)); view->OnMessageReceived( - InputMsg_ImeCommitText(routing_id, Text(), Underlines(), Range(), 0)); + InputMsg_ImeCommitText(routing_id, Text(), ImeTextSpans(), Range(), 0)); view->OnMessageReceived(InputMsg_ImeFinishComposingText(routing_id, false)); }
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 89e9a3a..5c373d4 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -120,7 +120,7 @@ #include "content/renderer/text_input_client_observer.h" #endif -using blink::WebCompositionUnderline; +using blink::WebImeTextSpan; using blink::WebCursorInfo; using blink::WebDeviceEmulationParams; using blink::WebDragOperation; @@ -1660,15 +1660,16 @@ void RenderWidget::OnImeSetComposition( const base::string16& text, - const std::vector<WebCompositionUnderline>& underlines, + const std::vector<WebImeTextSpan>& ime_text_spans, const gfx::Range& replacement_range, - int selection_start, int selection_end) { + int selection_start, + int selection_end) { if (!ShouldHandleImeEvents()) return; #if BUILDFLAG(ENABLE_PLUGINS) if (auto* plugin = GetFocusedPepperPluginInsideWidget()) { - plugin->render_frame()->OnImeSetComposition(text, underlines, + plugin->render_frame()->OnImeSetComposition(text, ime_text_spans, selection_start, selection_end); return; } @@ -1677,8 +1678,7 @@ blink::WebInputMethodController* controller = GetInputMethodController(); if (!controller || !controller->SetComposition( - WebString::FromUTF16(text), - WebVector<WebCompositionUnderline>(underlines), + WebString::FromUTF16(text), WebVector<WebImeTextSpan>(ime_text_spans), replacement_range.IsValid() ? WebRange(replacement_range.start(), replacement_range.length()) : WebRange(), @@ -1693,7 +1693,7 @@ void RenderWidget::OnImeCommitText( const base::string16& text, - const std::vector<WebCompositionUnderline>& underlines, + const std::vector<WebImeTextSpan>& ime_text_spans, const gfx::Range& replacement_range, int relative_cursor_pos) { if (!ShouldHandleImeEvents()) @@ -1710,8 +1710,7 @@ input_handler_->set_handling_input_event(true); if (auto* controller = GetInputMethodController()) { controller->CommitText( - WebString::FromUTF16(text), - WebVector<WebCompositionUnderline>(underlines), + WebString::FromUTF16(text), WebVector<WebImeTextSpan>(ime_text_spans), replacement_range.IsValid() ? WebRange(replacement_range.start(), replacement_range.length()) : WebRange(),
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index ab1b3ea..3785f02 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h
@@ -52,7 +52,7 @@ #include "third_party/WebKit/public/platform/WebRect.h" #include "third_party/WebKit/public/platform/WebReferrerPolicy.h" #include "third_party/WebKit/public/platform/WebTextInputInfo.h" -#include "third_party/WebKit/public/web/WebCompositionUnderline.h" +#include "third_party/WebKit/public/web/WebImeTextSpan.h" #include "third_party/WebKit/public/web/WebPopupType.h" #include "third_party/WebKit/public/web/WebTextDirection.h" #include "third_party/WebKit/public/web/WebWidget.h" @@ -435,15 +435,14 @@ void OnSetEditCommandsForNextKeyEvent(const EditCommands& edit_commands); void OnImeSetComposition( const base::string16& text, - const std::vector<blink::WebCompositionUnderline>& underlines, + const std::vector<blink::WebImeTextSpan>& ime_text_spans, const gfx::Range& replacement_range, int selection_start, int selection_end); - void OnImeCommitText( - const base::string16& text, - const std::vector<blink::WebCompositionUnderline>& underlines, - const gfx::Range& replacement_range, - int relative_cursor_pos); + void OnImeCommitText(const base::string16& text, + const std::vector<blink::WebImeTextSpan>& ime_text_spans, + const gfx::Range& replacement_range, + int relative_cursor_pos); void OnImeFinishComposingText(bool keep_selection); // Called by the browser process to update text input state.
diff --git a/content/renderer/render_widget_browsertest.cc b/content/renderer/render_widget_browsertest.cc index 3f8fcf9..7d4cc20 100644 --- a/content/renderer/render_widget_browsertest.cc +++ b/content/renderer/render_widget_browsertest.cc
@@ -37,10 +37,9 @@ } void CommitText(std::string text) { - widget()->OnImeCommitText( - base::UTF8ToUTF16(text), - std::vector<blink::WebCompositionUnderline>(), - gfx::Range::InvalidRange(), 0); + widget()->OnImeCommitText(base::UTF8ToUTF16(text), + std::vector<blink::WebImeTextSpan>(), + gfx::Range::InvalidRange(), 0); } ui::TextInputType GetTextInputType() { return widget()->GetTextInputType(); } @@ -128,10 +127,10 @@ LoadHTML( "<div contenteditable>EDITABLE</div>" "<script> document.querySelector('div').focus(); </script>"); - blink::WebVector<blink::WebCompositionUnderline> emptyUnderlines; + blink::WebVector<blink::WebImeTextSpan> empty_ime_text_spans; DCHECK(widget()->GetInputMethodController()); - widget()->GetInputMethodController()->SetComposition("hello", emptyUnderlines, - blink::WebRange(), 3, 3); + widget()->GetInputMethodController()->SetComposition( + "hello", empty_ime_text_spans, blink::WebRange(), 3, 3); gfx::Range range; GetCompositionRange(&range); EXPECT_TRUE(range.IsValid());
diff --git a/content/renderer/render_widget_fullscreen_pepper.cc b/content/renderer/render_widget_fullscreen_pepper.cc index a40db58..4206136 100644 --- a/content/renderer/render_widget_fullscreen_pepper.cc +++ b/content/renderer/render_widget_fullscreen_pepper.cc
@@ -30,7 +30,7 @@ using blink::WebCanvas; using blink::WebCoalescedInputEvent; -using blink::WebCompositionUnderline; +using blink::WebImeTextSpan; using blink::WebCursorInfo; using blink::WebGestureEvent; using blink::WebInputEvent;
diff --git a/content/renderer/renderer.sb b/content/renderer/renderer.sb index fd54bf7..daa3666 100644 --- a/content/renderer/renderer.sb +++ b/content/renderer/renderer.sb
@@ -33,8 +33,12 @@ ; https://crbug.com/288697 (allow file-read* - (path "/private/etc/localtime") - (subpath "/usr/share/zoneinfo")) + (path "/private/etc/localtime")) + +; https://crbug.com/754280 +(if (param-true? macos-1013) + (allow file-read-data (subpath "/usr/share/zoneinfo.default")) + (allow file-read-data (subpath "/usr/share/zoneinfo"))) (allow file-read-metadata (path "/private/etc"))
diff --git a/content/shell/test_runner/text_input_controller.cc b/content/shell/test_runner/text_input_controller.cc index 9e7d7ba..d9f0929 100644 --- a/content/shell/test_runner/text_input_controller.cc +++ b/content/shell/test_runner/text_input_controller.cc
@@ -14,8 +14,8 @@ #include "third_party/WebKit/public/platform/WebCoalescedInputEvent.h" #include "third_party/WebKit/public/platform/WebInputEventResult.h" #include "third_party/WebKit/public/platform/WebKeyboardEvent.h" -#include "third_party/WebKit/public/web/WebCompositionUnderline.h" #include "third_party/WebKit/public/web/WebFrameWidget.h" +#include "third_party/WebKit/public/web/WebImeTextSpan.h" #include "third_party/WebKit/public/web/WebInputMethodController.h" #include "third_party/WebKit/public/web/WebKit.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" @@ -173,7 +173,7 @@ void TextInputController::InsertText(const std::string& text) { if (auto* controller = GetInputMethodController()) { controller->CommitText(blink::WebString::FromUTF8(text), - std::vector<blink::WebCompositionUnderline>(), + std::vector<blink::WebImeTextSpan>(), blink::WebRange(), 0); } } @@ -202,28 +202,28 @@ blink::WebString web_text(blink::WebString::FromUTF8(text)); // Split underline into up to 3 elements (before, selection, and after). - std::vector<blink::WebCompositionUnderline> underlines; - blink::WebCompositionUnderline underline; + std::vector<blink::WebImeTextSpan> ime_text_spans; + blink::WebImeTextSpan ime_text_span; if (!start) { - underline.end_offset = length; + ime_text_span.end_offset = length; } else { - underline.end_offset = start; - underlines.push_back(underline); - underline.start_offset = start; - underline.end_offset = start + length; + ime_text_span.end_offset = start; + ime_text_spans.push_back(ime_text_span); + ime_text_span.start_offset = start; + ime_text_span.end_offset = start + length; } - underline.thick = true; - underlines.push_back(underline); + ime_text_span.thick = true; + ime_text_spans.push_back(ime_text_span); if (start + length < static_cast<int>(web_text.length())) { - underline.start_offset = underline.end_offset; - underline.end_offset = web_text.length(); - underline.thick = false; - underlines.push_back(underline); + ime_text_span.start_offset = ime_text_span.end_offset; + ime_text_span.end_offset = web_text.length(); + ime_text_span.thick = false; + ime_text_spans.push_back(ime_text_span); } if (auto* controller = GetInputMethodController()) { - controller->SetComposition(web_text, underlines, blink::WebRange(), start, - start + length); + controller->SetComposition(web_text, ime_text_spans, blink::WebRange(), + start, start + length); } } @@ -311,12 +311,12 @@ blink::WebString newText = blink::WebString::FromUTF8(text); size_t textLength = newText.length(); - std::vector<blink::WebCompositionUnderline> underlines; - underlines.push_back(blink::WebCompositionUnderline( - 0, textLength, SK_ColorBLACK, false, SK_ColorTRANSPARENT)); + std::vector<blink::WebImeTextSpan> ime_text_spans; + ime_text_spans.push_back(blink::WebImeTextSpan(0, textLength, SK_ColorBLACK, + false, SK_ColorTRANSPARENT)); if (auto* controller = GetInputMethodController()) { controller->SetComposition( - newText, blink::WebVector<blink::WebCompositionUnderline>(underlines), + newText, blink::WebVector<blink::WebImeTextSpan>(ime_text_spans), blink::WebRange(), textLength, textLength); } }
diff --git a/content/test/data/accessibility/aria/aria-col-attr-expected-mac.txt b/content/test/data/accessibility/aria/aria-col-attr-expected-mac.txt index 2f53480..e2f6b921 100644 --- a/content/test/data/accessibility/aria/aria-col-attr-expected-mac.txt +++ b/content/test/data/accessibility/aria/aria-col-attr-expected-mac.txt
@@ -1,5 +1,5 @@ AXWebArea -++AXGrid AXARIAColumnCount='5' +++AXTable AXARIAColumnCount='5' ++++AXRow ++++++AXCell AXTitle='cell 2' AXARIAColumnIndex='2' ++++++++AXStaticText AXValue='cell 2'
diff --git a/content/test/data/accessibility/aria/aria-columnheader-expected-mac.txt b/content/test/data/accessibility/aria/aria-columnheader-expected-mac.txt index ada8210..7c778711 100644 --- a/content/test/data/accessibility/aria/aria-columnheader-expected-mac.txt +++ b/content/test/data/accessibility/aria/aria-columnheader-expected-mac.txt
@@ -1,5 +1,5 @@ AXWebArea -++AXGrid +++AXTable ++++AXRow ++++++AXCell AXTitle='Browser' ++++++++AXStaticText AXValue='Browser'
diff --git a/content/test/data/accessibility/aria/aria-grid-expected-mac.txt b/content/test/data/accessibility/aria/aria-grid-expected-mac.txt index 22c6b08..68f4871 100644 --- a/content/test/data/accessibility/aria/aria-grid-expected-mac.txt +++ b/content/test/data/accessibility/aria/aria-grid-expected-mac.txt
@@ -1,5 +1,5 @@ AXWebArea AXRoleDescription='HTML content' -++AXGrid AXRoleDescription='grid' +++AXTable AXRoleDescription='table' ++++AXRow AXRoleDescription='row' ++++++AXCell AXRoleDescription='cell' AXTitle='Browser' ++++++++AXStaticText AXRoleDescription='text' AXValue='Browser'
diff --git a/content/test/data/accessibility/aria/aria-gridcell-expected-mac.txt b/content/test/data/accessibility/aria/aria-gridcell-expected-mac.txt index 22c6b08..68f4871 100644 --- a/content/test/data/accessibility/aria/aria-gridcell-expected-mac.txt +++ b/content/test/data/accessibility/aria/aria-gridcell-expected-mac.txt
@@ -1,5 +1,5 @@ AXWebArea AXRoleDescription='HTML content' -++AXGrid AXRoleDescription='grid' +++AXTable AXRoleDescription='table' ++++AXRow AXRoleDescription='row' ++++++AXCell AXRoleDescription='cell' AXTitle='Browser' ++++++++AXStaticText AXRoleDescription='text' AXValue='Browser'
diff --git a/content/test/data/accessibility/aria/aria-row-attr-expected-mac.txt b/content/test/data/accessibility/aria/aria-row-attr-expected-mac.txt index 35def74..a4fc45e 100644 --- a/content/test/data/accessibility/aria/aria-row-attr-expected-mac.txt +++ b/content/test/data/accessibility/aria/aria-row-attr-expected-mac.txt
@@ -1,5 +1,5 @@ AXWebArea -++AXGrid AXARIARowCount='5' +++AXTable AXARIARowCount='5' ++++AXRow ++++++AXCell AXTitle='cell 2' AXARIARowIndex='3' ++++++++AXStaticText AXValue='cell 2'
diff --git a/content/test/data/accessibility/aria/aria-row-expected-mac.txt b/content/test/data/accessibility/aria/aria-row-expected-mac.txt index ada8210..7c778711 100644 --- a/content/test/data/accessibility/aria/aria-row-expected-mac.txt +++ b/content/test/data/accessibility/aria/aria-row-expected-mac.txt
@@ -1,5 +1,5 @@ AXWebArea -++AXGrid +++AXTable ++++AXRow ++++++AXCell AXTitle='Browser' ++++++++AXStaticText AXValue='Browser'
diff --git a/content/test/data/accessibility/aria/aria-rowgroup-expected-mac.txt b/content/test/data/accessibility/aria/aria-rowgroup-expected-mac.txt index f22f6ef8..b8033e6 100644 --- a/content/test/data/accessibility/aria/aria-rowgroup-expected-mac.txt +++ b/content/test/data/accessibility/aria/aria-rowgroup-expected-mac.txt
@@ -1,5 +1,5 @@ AXWebArea -++AXGrid +++AXTable ++++AXRow ++++AXRow ++++AXGroup
diff --git a/content/test/data/accessibility/aria/aria-rowheader-expected-mac.txt b/content/test/data/accessibility/aria/aria-rowheader-expected-mac.txt index c8d13ff..5b6be0f 100644 --- a/content/test/data/accessibility/aria/aria-rowheader-expected-mac.txt +++ b/content/test/data/accessibility/aria/aria-rowheader-expected-mac.txt
@@ -1,5 +1,5 @@ AXWebArea -++AXGrid +++AXTable ++++AXRow ++++++AXCell AXTitle='Browser' ++++++++AXStaticText AXValue='Browser'
diff --git a/content/test/data/accessibility/aria/aria-sort-aria-grid-expected-mac.txt b/content/test/data/accessibility/aria/aria-sort-aria-grid-expected-mac.txt index 747f5a01..b4b49bd 100644 --- a/content/test/data/accessibility/aria/aria-sort-aria-grid-expected-mac.txt +++ b/content/test/data/accessibility/aria/aria-sort-aria-grid-expected-mac.txt
@@ -1,5 +1,5 @@ AXWebArea -++AXGrid +++AXTable ++++AXRow ++++++AXCell AXTitle='Alphabet' ++++++++AXStaticText AXValue='Alphabet' @@ -11,7 +11,7 @@ ++++++++AXStaticText AXValue='B' ++++AXColumn ++++AXGroup -++AXGrid +++AXTable ++++AXRow ++++++AXCell AXTitle='Alphabet' ++++++++AXStaticText AXValue='Alphabet' @@ -23,7 +23,7 @@ ++++++++AXStaticText AXValue='B' ++++AXColumn ++++AXGroup -++AXGrid +++AXTable ++++AXRow ++++++AXCell AXTitle='Alphabet' AXSortDirection='AXAscendingSortDirection' ++++++++AXStaticText AXValue='Alphabet' @@ -35,7 +35,7 @@ ++++++++AXStaticText AXValue='B' ++++AXColumn ++++AXGroup -++AXGrid +++AXTable ++++AXRow ++++++AXCell AXTitle='Alphabet' AXSortDirection='AXDescendingSortDirection' ++++++++AXStaticText AXValue='Alphabet' @@ -47,7 +47,7 @@ ++++++++AXStaticText AXValue='A' ++++AXColumn ++++AXGroup -++AXGrid +++AXTable ++++AXRow ++++++AXCell AXTitle='Alphabet' AXSortDirection='AXUnknownSortDirection' ++++++++AXStaticText AXValue='Alphabet' @@ -59,7 +59,7 @@ ++++++++AXStaticText AXValue='A' ++++AXColumn ++++AXGroup -++AXGrid +++AXTable ++++AXRow ++++++AXCell AXTitle='Alphabet' ++++++++AXStaticText AXValue='Alphabet' @@ -71,7 +71,7 @@ ++++AXColumn ++++AXColumn ++++AXGroup -++AXGrid +++AXTable ++++AXRow ++++++AXCell AXTitle='Alphabet' ++++++++AXStaticText AXValue='Alphabet' @@ -83,7 +83,7 @@ ++++AXColumn ++++AXColumn ++++AXGroup -++AXGrid +++AXTable ++++AXRow ++++++AXCell AXTitle='Alphabet' AXSortDirection='AXAscendingSortDirection' ++++++++AXStaticText AXValue='Alphabet' @@ -95,7 +95,7 @@ ++++AXColumn ++++AXColumn ++++AXGroup -++AXGrid +++AXTable ++++AXRow ++++++AXCell AXTitle='Alphabet' AXSortDirection='AXDescendingSortDirection' ++++++++AXStaticText AXValue='Alphabet' @@ -107,7 +107,7 @@ ++++AXColumn ++++AXColumn ++++AXGroup -++AXGrid +++AXTable ++++AXRow ++++++AXCell AXTitle='Alphabet' AXSortDirection='AXUnknownSortDirection' ++++++++AXStaticText AXValue='Alphabet'
diff --git a/content/test/data/accessibility/aria/table-column-hidden-expected-mac.txt b/content/test/data/accessibility/aria/table-column-hidden-expected-mac.txt index 073f663..a178596 100644 --- a/content/test/data/accessibility/aria/table-column-hidden-expected-mac.txt +++ b/content/test/data/accessibility/aria/table-column-hidden-expected-mac.txt
@@ -1,5 +1,5 @@ AXWebArea -++AXGrid AXARIAColumnCount='4' +++AXTable AXARIAColumnCount='4' ++++AXRow ++++++AXCell AXTitle='Month' AXARIAColumnIndex='1' AXARIARowIndex='1' ++++++++AXStaticText AXValue='Month'
diff --git a/content/test/gpu/generate_buildbot_json.py b/content/test/gpu/generate_buildbot_json.py index 0019ccc5..b4702b5c 100755 --- a/content/test/gpu/generate_buildbot_json.py +++ b/content/test/gpu/generate_buildbot_json.py
@@ -264,19 +264,6 @@ 'swarming': True, 'os_type': 'win', }, - 'Win10 Release (Intel HD 530)': { - 'swarming_dimensions': [ - { - 'gpu': '8086:1912', - 'os': 'Windows-10', - }, - ], - 'build_config': 'Release', - # This bot is a one-off and doesn't have similar slaves in the - # swarming pool. - 'swarming': False, - 'os_type': 'win', - }, 'Win10 Release (Intel HD 630)': { 'swarming_dimensions': [ { @@ -290,19 +277,6 @@ 'swarming': False, 'os_type': 'win', }, - 'Win10 Debug (Intel HD 530)': { - 'swarming_dimensions': [ - { - 'gpu': '8086:1912', - 'os': 'Windows-10', - }, - ], - 'build_config': 'Debug', - # This bot is a one-off and doesn't have similar slaves in the - # swarming pool. - 'swarming': False, - 'os_type': 'win', - }, 'Win10 Release (NVIDIA Quadro P400)': { 'swarming_dimensions': [ { @@ -538,19 +512,6 @@ 'swarming': True, 'os_type': 'linux', }, - 'Linux Release (Intel HD 530)': { - 'swarming_dimensions': [ - { - 'gpu': '8086:1912', - 'os': 'Ubuntu' - }, - ], - 'build_config': 'Release', - # This bot is a one-off and doesn't have similar slaves in the - # swarming pool. - 'swarming': False, - 'os_type': 'linux', - }, 'Linux Release (Intel HD 630)': { 'swarming_dimensions': [ { @@ -564,19 +525,6 @@ 'swarming': False, 'os_type': 'linux', }, - 'Linux Debug (Intel HD 530)': { - 'swarming_dimensions': [ - { - 'gpu': '8086:1912', - 'os': 'Ubuntu' - }, - ], - 'build_config': 'Debug', - # This bot is a one-off and doesn't have similar slaves in the - # swarming pool. - 'swarming': False, - 'os_type': 'linux', - }, 'Linux Release (AMD R7 240)': { 'swarming_dimensions': [ { @@ -1351,6 +1299,25 @@ ], 'desktop_args': ['--use-gpu-in-tests'] }, + 'gl_tests_passthrough': { + 'tester_configs': [ + { + 'os_types': ['win'], + } + ], + 'disabled_tester_configs': [ + { + 'names': [ + 'Linux ChromiumOS Ozone (Intel)', + ], + }, + ], + 'test': 'gl_tests', + 'desktop_args': [ + '--use-gpu-in-tests', + '--use-passthrough-cmd-decoder', + ] + }, 'gl_unittests': { 'disabled_tester_configs': [ { @@ -1543,8 +1510,6 @@ 'disabled_tester_configs': [ { 'names': [ - 'Win10 Debug (Intel HD 530)', - 'Win10 Release (Intel HD 530)', 'Win10 Release (Intel HD 630)', ], },
diff --git a/content/test/test_render_frame.cc b/content/test/test_render_frame.cc index 09a4d4b..d6c1bb15 100644 --- a/content/test/test_render_frame.cc +++ b/content/test/test_render_frame.cc
@@ -106,8 +106,8 @@ void TestRenderFrame::SetCompositionFromExistingText( int start, int end, - const std::vector<blink::WebCompositionUnderline>& underlines) { - OnSetCompositionFromExistingText(start, end, underlines); + const std::vector<blink::WebImeTextSpan>& ime_text_spans) { + OnSetCompositionFromExistingText(start, end, ime_text_spans); } blink::WebNavigationPolicy TestRenderFrame::DecidePolicyForNavigation(
diff --git a/content/test/test_render_frame.h b/content/test/test_render_frame.h index 567b355..cc888aa 100644 --- a/content/test/test_render_frame.h +++ b/content/test/test_render_frame.h
@@ -49,7 +49,7 @@ void SetCompositionFromExistingText( int start, int end, - const std::vector<blink::WebCompositionUnderline>& underlines); + const std::vector<blink::WebImeTextSpan>& ime_text_spans); blink::WebNavigationPolicy DecidePolicyForNavigation( const blink::WebFrameClient::NavigationPolicyInfo& info) override;
diff --git a/device/bluetooth/test/fake_central.cc b/device/bluetooth/test/fake_central.cc index afe554ec6..9f0bc62 100644 --- a/device/bluetooth/test/fake_central.cc +++ b/device/bluetooth/test/fake_central.cc
@@ -28,17 +28,14 @@ const std::string& name, const std::vector<device::BluetoothUUID>& known_service_uuids, SimulatePreconnectedPeripheralCallback callback) { - auto device_iter = devices_.find(address); - if (device_iter == devices_.end()) { - auto fake_peripheral = base::MakeUnique<FakePeripheral>(this, address); - - auto insert_iter = devices_.emplace(address, std::move(fake_peripheral)); - DCHECK(insert_iter.second); - device_iter = insert_iter.first; + FakePeripheral* fake_peripheral = GetFakePeripheral(address); + if (fake_peripheral == nullptr) { + auto fake_peripheral_ptr = base::MakeUnique<FakePeripheral>(this, address); + fake_peripheral = fake_peripheral_ptr.get(); + auto pair = devices_.emplace(address, std::move(fake_peripheral_ptr)); + DCHECK(pair.second); } - FakePeripheral* fake_peripheral = - static_cast<FakePeripheral*>(device_iter->second.get()); fake_peripheral->SetName(name); fake_peripheral->SetSystemConnected(true); fake_peripheral->SetServiceUUIDs(device::BluetoothDevice::UUIDSet( @@ -51,14 +48,12 @@ const std::string& address, uint16_t code, SetNextGATTConnectionResponseCallback callback) { - auto device_iter = devices_.find(address); - if (device_iter == devices_.end()) { + FakePeripheral* fake_peripheral = GetFakePeripheral(address); + if (fake_peripheral == nullptr) { std::move(callback).Run(false); return; } - FakePeripheral* fake_peripheral = - static_cast<FakePeripheral*>(device_iter->second.get()); fake_peripheral->SetNextGATTConnectionResponse(code); std::move(callback).Run(true); } @@ -67,13 +62,12 @@ const std::string& address, uint16_t code, SetNextGATTDiscoveryResponseCallback callback) { - auto device_iter = devices_.find(address); - if (device_iter == devices_.end()) { + FakePeripheral* fake_peripheral = GetFakePeripheral(address); + if (fake_peripheral == nullptr) { std::move(callback).Run(false); + return; } - FakePeripheral* fake_peripheral = - static_cast<FakePeripheral*>(device_iter->second.get()); fake_peripheral->SetNextGATTDiscoveryResponse(code); std::move(callback).Run(true); } @@ -81,19 +75,24 @@ void FakeCentral::SimulateGATTServicesChanged( const std::string& address, SimulateGATTServicesChangedCallback callback) { + FakePeripheral* fake_peripheral = GetFakePeripheral(address); + if (fake_peripheral == nullptr) { + std::move(callback).Run(false); + return; + } + std::move(callback).Run(true); } void FakeCentral::AddFakeService(const std::string& peripheral_address, const device::BluetoothUUID& service_uuid, AddFakeServiceCallback callback) { - auto device_iter = devices_.find(peripheral_address); - if (device_iter == devices_.end()) { + FakePeripheral* fake_peripheral = GetFakePeripheral(peripheral_address); + if (fake_peripheral == nullptr) { std::move(callback).Run(base::nullopt); + return; } - FakePeripheral* fake_peripheral = - static_cast<FakePeripheral*>(device_iter->second.get()); std::move(callback).Run(fake_peripheral->AddFakeService(service_uuid)); } @@ -103,16 +102,11 @@ const std::string& service_id, const std::string& peripheral_address, AddFakeCharacteristicCallback callback) { - auto device_iter = devices_.find(peripheral_address); - if (device_iter == devices_.end()) { - std::move(callback).Run(base::nullopt); - } - FakeRemoteGattService* fake_remote_gatt_service = - static_cast<FakeRemoteGattService*>( - device_iter->second.get()->GetGattService(service_id)); + GetFakeRemoteGattService(peripheral_address, service_id); if (fake_remote_gatt_service == nullptr) { std::move(callback).Run(base::nullopt); + return; } std::move(callback).Run(fake_remote_gatt_service->AddFakeCharacteristic( @@ -124,15 +118,8 @@ const std::string& service_id, const std::string& peripheral_address, RemoveFakeCharacteristicCallback callback) { - auto device_iter = devices_.find(peripheral_address); - if (device_iter == devices_.end()) { - std::move(callback).Run(false); - return; - } - FakeRemoteGattService* fake_remote_gatt_service = - static_cast<FakeRemoteGattService*>( - device_iter->second.get()->GetGattService(service_id)); + GetFakeRemoteGattService(peripheral_address, service_id); if (fake_remote_gatt_service == nullptr) { std::move(callback).Run(false); return; @@ -374,18 +361,34 @@ FakeCentral::~FakeCentral() {} -FakeRemoteGattCharacteristic* FakeCentral::GetFakeRemoteGattCharacteristic( - const std::string& peripheral_address, - const std::string& service_id, - const std::string& characteristic_id) const { +FakePeripheral* FakeCentral::GetFakePeripheral( + const std::string& peripheral_address) const { auto device_iter = devices_.find(peripheral_address); if (device_iter == devices_.end()) { return nullptr; } + return static_cast<FakePeripheral*>(device_iter->second.get()); +} + +FakeRemoteGattService* FakeCentral::GetFakeRemoteGattService( + const std::string& peripheral_address, + const std::string& service_id) const { + FakePeripheral* fake_peripheral = GetFakePeripheral(peripheral_address); + if (fake_peripheral == nullptr) { + return nullptr; + } + + return static_cast<FakeRemoteGattService*>( + fake_peripheral->GetGattService(service_id)); +} + +FakeRemoteGattCharacteristic* FakeCentral::GetFakeRemoteGattCharacteristic( + const std::string& peripheral_address, + const std::string& service_id, + const std::string& characteristic_id) const { FakeRemoteGattService* fake_remote_gatt_service = - static_cast<FakeRemoteGattService*>( - device_iter->second.get()->GetGattService(service_id)); + GetFakeRemoteGattService(peripheral_address, service_id); if (fake_remote_gatt_service == nullptr) { return nullptr; }
diff --git a/device/bluetooth/test/fake_central.h b/device/bluetooth/test/fake_central.h index 775e114..5aa27f22 100644 --- a/device/bluetooth/test/fake_central.h +++ b/device/bluetooth/test/fake_central.h
@@ -15,8 +15,10 @@ namespace bluetooth { +class FakePeripheral; class FakeRemoteGattCharacteristic; class FakeRemoteGattDescriptor; +class FakeRemoteGattService; // Implementation of FakeCentral in // src/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom. @@ -150,6 +152,11 @@ private: ~FakeCentral() override; + FakePeripheral* GetFakePeripheral( + const std::string& peripheral_address) const; + FakeRemoteGattService* GetFakeRemoteGattService( + const std::string& peripheral_address, + const std::string& service_id) const; FakeRemoteGattCharacteristic* GetFakeRemoteGattCharacteristic( const std::string& peripheral_address, const std::string& service_id,
diff --git a/docs/updating_clang.md b/docs/updating_clang.md index 28b1ac13..5ef098d 100644 --- a/docs/updating_clang.md +++ b/docs/updating_clang.md
@@ -27,7 +27,8 @@ 1. Run an exhaustive set of try jobs to test the new compiler: ``` git cl try && - git cl try -m tryserver.chromium.mac -b mac_chromium_asan_rel_ng && + git cl try -m tryserver.chromium.mac -b mac_chromium_asan_rel_ng \ + -b ios-device && \ git cl try -m tryserver.chromium.linux -b linux_chromium_chromeos_dbg_ng \ -b linux_chromium_chromeos_asan_rel_ng -b linux_chromium_msan_rel_ng \ -b fuchsia -b linux_chromium_cfi_rel_ng &&
diff --git a/extensions/browser/api/app_current_window_internal/app_current_window_internal_api.cc b/extensions/browser/api/app_current_window_internal/app_current_window_internal_api.cc index 779e9a2c..6130865 100644 --- a/extensions/browser/api/app_current_window_internal/app_current_window_internal_api.cc +++ b/extensions/browser/api/app_current_window_internal/app_current_window_internal_api.cc
@@ -330,27 +330,21 @@ std::unique_ptr<SetShape::Params> params(SetShape::Params::Create(*args_)); const Region& shape = params->region; - // Build a region from the supplied list of rects. + // Build the list of hit-test rects from the supplied list of rects. // If |rects| is missing, then the input region is removed. This clears the // input region so that the entire window accepts input events. // To specify an empty input region (so the window ignores all input), // |rects| should be an empty list. - std::unique_ptr<SkRegion> region(new SkRegion); + std::unique_ptr<AppWindow::ShapeRects> shape_rects; if (shape.rects) { + shape_rects = base::MakeUnique<AppWindow::ShapeRects>(); + shape_rects->reserve(shape.rects->size()); for (const RegionRect& input_rect : *shape.rects) { - int32_t x = input_rect.left; - int32_t y = input_rect.top; - int32_t width = input_rect.width; - int32_t height = input_rect.height; - - SkIRect rect = SkIRect::MakeXYWH(x, y, width, height); - region->op(rect, SkRegion::kUnion_Op); + shape_rects->emplace_back(input_rect.left, input_rect.top, + input_rect.width, input_rect.height); } - } else { - region.reset(NULL); } - - window()->UpdateShape(std::move(region)); + window()->UpdateShape(std::move(shape_rects)); return RespondNow(NoArguments()); }
diff --git a/extensions/browser/api/feedback_private/feedback_private_delegate.h b/extensions/browser/api/feedback_private/feedback_private_delegate.h index feb1f066..ab9e048 100644 --- a/extensions/browser/api/feedback_private/feedback_private_delegate.h +++ b/extensions/browser/api/feedback_private/feedback_private_delegate.h
@@ -15,6 +15,10 @@ class BrowserContext; } // namespace content +namespace system_logs { +class SystemLogsFetcher; +} // namespace system_logs + namespace extensions { // Delegate class for embedder-specific chrome.feedbackPrivate behavior. @@ -29,6 +33,10 @@ virtual std::unique_ptr<base::DictionaryValue> GetStrings( content::BrowserContext* browser_context, bool from_crash) const = 0; + + // Returns a SystemLogsFetcher for responding to a request for system logs. + virtual system_logs::SystemLogsFetcher* CreateSystemLogsFetcher( + content::BrowserContext* context) const = 0; }; } // namespace extensions
diff --git a/extensions/browser/api/storage/backend_task_runner.cc b/extensions/browser/api/storage/backend_task_runner.cc index 0d5e614..50794e1 100644 --- a/extensions/browser/api/storage/backend_task_runner.cc +++ b/extensions/browser/api/storage/backend_task_runner.cc
@@ -4,15 +4,14 @@ #include "extensions/browser/api/storage/backend_task_runner.h" -#include "base/task_scheduler/lazy_task_runner.h" +#include "extensions/browser/extension_file_task_runner.h" namespace extensions { -base::LazySequencedTaskRunner g_sequenced_task_task_runner = - LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER({base::MayBlock()}); - +// TODO(stanisc): consider switching all calls of GetBackendTaskRunner() to +// GetExtensionFileTaskRunner(). scoped_refptr<base::SequencedTaskRunner> GetBackendTaskRunner() { - return g_sequenced_task_task_runner.Get(); + return GetExtensionFileTaskRunner(); } bool IsOnBackendSequence() {
diff --git a/extensions/browser/app_window/app_window.cc b/extensions/browser/app_window/app_window.cc index ed4ba26..ca452e18 100644 --- a/extensions/browser/app_window/app_window.cc +++ b/extensions/browser/app_window/app_window.cc
@@ -578,8 +578,8 @@ image_loader_ptr_factory_.GetWeakPtr())); } -void AppWindow::UpdateShape(std::unique_ptr<SkRegion> region) { - native_app_window_->UpdateShape(std::move(region)); +void AppWindow::UpdateShape(std::unique_ptr<ShapeRects> rects) { + native_app_window_->UpdateShape(std::move(rects)); } void AppWindow::UpdateDraggableRegions(
diff --git a/extensions/browser/app_window/app_window.h b/extensions/browser/app_window/app_window.h index 7d07ae89..09536a8 100644 --- a/extensions/browser/app_window/app_window.h +++ b/extensions/browser/app_window/app_window.h
@@ -118,6 +118,8 @@ FULLSCREEN_TYPE_FORCED = 1 << 3, }; + using ShapeRects = std::vector<gfx::Rect>; + struct BoundsSpecification { // INT_MIN represents an unspecified position component. static const int kUnspecifiedPosition; @@ -275,8 +277,8 @@ // Specifies a url for the launcher icon. void SetAppIconUrl(const GURL& icon_url); - // Set the window shape. Passing a NULL |region| sets the default shape. - void UpdateShape(std::unique_ptr<SkRegion> region); + // Sets the window shape. Passing a nullptr |rects| sets the default shape. + void UpdateShape(std::unique_ptr<ShapeRects> rects); // Called from the render interface to modify the draggable regions. void UpdateDraggableRegions(const std::vector<DraggableRegion>& regions);
diff --git a/extensions/browser/app_window/native_app_window.h b/extensions/browser/app_window/native_app_window.h index 719180bb..0ae528f 100644 --- a/extensions/browser/app_window/native_app_window.h +++ b/extensions/browser/app_window/native_app_window.h
@@ -29,6 +29,8 @@ class NativeAppWindow : public ui::BaseWindow, public web_modal::WebContentsModalDialogHost { public: + using ShapeRects = std::vector<gfx::Rect>; + // Sets whether the window is fullscreen and the type of fullscreen. // |fullscreen_types| is a bit field of AppWindow::FullscreenType. virtual void SetFullscreen(int fullscreen_types) = 0; @@ -46,12 +48,13 @@ virtual void UpdateDraggableRegions( const std::vector<DraggableRegion>& regions) = 0; - // Returns the region used by frameless windows for dragging. May return NULL. + // Returns the region used by frameless windows for dragging. May return + // nullptr. virtual SkRegion* GetDraggableRegion() = 0; - // Called when the window shape is changed. If |region| is NULL then the + // Called when the window shape is changed. If |region| is nullptr then the // window is restored to the default shape. - virtual void UpdateShape(std::unique_ptr<SkRegion> region) = 0; + virtual void UpdateShape(std::unique_ptr<ShapeRects> rects) = 0; // Allows the window to handle unhandled keyboard messages coming back from // the renderer.
diff --git a/extensions/common/extension_api.cc b/extensions/common/extension_api.cc index a60af27..8dbf447 100644 --- a/extensions/common/extension_api.cc +++ b/extensions/common/extension_api.cc
@@ -183,11 +183,10 @@ // Check to see if there are any parts of this API that are allowed in this // context. - const std::vector<Feature*> features = provider->second->GetChildren(api); - for (std::vector<Feature*>::const_iterator it = features.begin(); - it != features.end(); - ++it) { - if ((*it)->IsAvailableToContext(extension, context, url).is_available()) + const std::vector<const Feature*> features = + provider->second->GetChildren(api); + for (const Feature* feature : features) { + if (feature->IsAvailableToContext(extension, context, url).is_available()) return true; } @@ -210,7 +209,7 @@ Feature::Context context, const GURL& url, CheckAliasStatus check_alias) { - Feature* feature = GetFeatureDependency(full_name); + const Feature* feature = GetFeatureDependency(full_name); if (!feature) { return Feature::Availability(Feature::NOT_PRESENT, std::string("Unknown feature: ") + full_name); @@ -222,7 +221,7 @@ return availability; Feature::Availability alias_availability = - IsAliasAvailable(full_name, feature, extension, context, url); + IsAliasAvailable(full_name, *feature, extension, context, url); return alias_availability.is_available() ? alias_availability : availability; } @@ -272,7 +271,8 @@ return result; } -Feature* ExtensionAPI::GetFeatureDependency(const std::string& full_name) { +const Feature* ExtensionAPI::GetFeatureDependency( + const std::string& full_name) { std::string feature_type; std::string feature_name; SplitDependencyName(full_name, &feature_type, &feature_name); @@ -282,7 +282,7 @@ if (provider == dependency_providers_.end()) return NULL; - Feature* feature = provider->second->GetFeature(feature_name); + const Feature* feature = provider->second->GetFeature(feature_name); // Try getting the feature for the parent API, if this was a child. if (!feature) { std::string child_name; @@ -328,11 +328,11 @@ Feature::Availability ExtensionAPI::IsAliasAvailable( const std::string& full_name, - Feature* feature, + const Feature& feature, const Extension* extension, Feature::Context context, const GURL& url) { - const std::string& alias = feature->alias(); + const std::string& alias = feature.alias(); if (alias.empty()) return Feature::Availability(Feature::NOT_PRESENT, "Alias not defined"); @@ -348,7 +348,7 @@ std::string child_name; GetAPINameFromFullName(full_name, &child_name); std::string full_alias_name = alias + "." + child_name; - Feature* alias_feature = provider->second->GetFeature(full_alias_name); + const Feature* alias_feature = provider->second->GetFeature(full_alias_name); // If there is no child feature, use the alias API feature to check // availability. @@ -356,7 +356,7 @@ alias_feature = provider->second->GetFeature(alias); CHECK(alias_feature) << "Cannot find alias feature " << alias - << " for API feature " << feature->name(); + << " for API feature " << feature.name(); return alias_feature->IsAvailableToContext(extension, context, url); }
diff --git a/extensions/common/extension_api.h b/extensions/common/extension_api.h index 493674aecc4..01761a6 100644 --- a/extensions/common/extension_api.h +++ b/extensions/common/extension_api.h
@@ -142,7 +142,7 @@ // Gets a feature from any dependency provider registered with ExtensionAPI. // Returns NULL if the feature could not be found. - Feature* GetFeatureDependency(const std::string& dependency_name); + const Feature* GetFeatureDependency(const std::string& dependency_name); private: FRIEND_TEST_ALL_PREFIXES(ExtensionAPITest, DefaultConfigurationFeatures); @@ -157,7 +157,7 @@ // Checks if |full_name| is available to provided context and extension under // associated API's alias name. Feature::Availability IsAliasAvailable(const std::string& full_name, - Feature* feature, + const Feature& feature, const Extension* extension, Feature::Context context, const GURL& url);
diff --git a/extensions/common/features/feature_provider.cc b/extensions/common/features/feature_provider.cc index 2d75f82..51a697c 100644 --- a/extensions/common/features/feature_provider.cc +++ b/extensions/common/features/feature_provider.cc
@@ -127,7 +127,7 @@ return GetFeatureFromProviderByName("behavior", name); } -Feature* FeatureProvider::GetFeature(const std::string& name) const { +const Feature* FeatureProvider::GetFeature(const std::string& name) const { FeatureMap::const_iterator iter = features_.find(name); if (iter != features_.end()) return iter->second.get(); @@ -149,7 +149,7 @@ // Children of a given API are named starting with parent.name()+".", which // means they'll be contiguous in the features_ std::map. -std::vector<Feature*> FeatureProvider::GetChildren( +std::vector<const Feature*> FeatureProvider::GetChildren( const Feature& parent) const { std::string prefix = parent.name() + "."; const FeatureMap::const_iterator first_child = features_.lower_bound(prefix); @@ -159,7 +159,7 @@ const FeatureMap::const_iterator after_children = features_.lower_bound(prefix); - std::vector<Feature*> result; + std::vector<const Feature*> result; result.reserve(std::distance(first_child, after_children)); for (FeatureMap::const_iterator it = first_child; it != after_children; ++it) {
diff --git a/extensions/common/features/feature_provider.h b/extensions/common/features/feature_provider.h index c5cde10..0576dc7c 100644 --- a/extensions/common/features/feature_provider.h +++ b/extensions/common/features/feature_provider.h
@@ -18,7 +18,7 @@ // Note: Binding code (specifically native_extension_bindings_system.cc) relies // on this being a sorted map. -using FeatureMap = std::map<std::string, std::unique_ptr<Feature>>; +using FeatureMap = std::map<std::string, std::unique_ptr<const Feature>>; // Implemented by classes that can vend features. class FeatureProvider { @@ -46,13 +46,13 @@ static const Feature* GetBehaviorFeature(const std::string& name); // Returns the feature with the specified name. - Feature* GetFeature(const std::string& name) const; + const Feature* GetFeature(const std::string& name) const; // Returns the parent feature of |feature|, or null if there isn't one. const Feature* GetParent(const Feature& feature) const; // Returns the features inside the |parent| namespace, recursively. - std::vector<Feature*> GetChildren(const Feature& parent) const; + std::vector<const Feature*> GetChildren(const Feature& parent) const; // Returns a map containing all features described by this instance. // TODO(devlin): Rename this to be features().
diff --git a/extensions/common/features/feature_provider_unittest.cc b/extensions/common/features/feature_provider_unittest.cc index 2bf161f..1af86f9 100644 --- a/extensions/common/features/feature_provider_unittest.cc +++ b/extensions/common/features/feature_provider_unittest.cc
@@ -56,7 +56,7 @@ .Build(); ASSERT_TRUE(extension.get()); - Feature* feature = provider->GetFeature("description"); + const Feature* feature = provider->GetFeature("description"); EXPECT_EQ(Feature::IS_AVAILABLE, feature ->IsAvailableToContext(extension.get(), @@ -125,7 +125,7 @@ ASSERT_TRUE(app->is_platform_app()); // A permission requested in the manifest is available. - Feature* feature = provider->GetFeature("power"); + const Feature* feature = provider->GetFeature("power"); EXPECT_EQ(Feature::IS_AVAILABLE, feature ->IsAvailableToContext(app.get(), Feature::UNSPECIFIED_CONTEXT, @@ -169,9 +169,9 @@ add_feature("parent.other_child.other_grandchild"); add_feature("parent.unparented_child", true); - Feature* parent = provider.GetFeature("parent"); + const Feature* parent = provider.GetFeature("parent"); ASSERT_TRUE(parent); - std::vector<Feature*> children = provider.GetChildren(*parent); + std::vector<const Feature*> children = provider.GetChildren(*parent); std::set<std::string> children_names; for (const Feature* child : children) children_names.insert(child->name());
diff --git a/extensions/common/features/simple_feature.cc b/extensions/common/features/simple_feature.cc index 4e68be6..55b5da0 100644 --- a/extensions/common/features/simple_feature.cc +++ b/extensions/common/features/simple_feature.cc
@@ -469,7 +469,7 @@ Feature::Availability SimpleFeature::CheckDependencies( const base::Callback<Availability(const Feature*)>& checker) const { for (const auto& dep_name : dependencies_) { - Feature* dependency = + const Feature* dependency = ExtensionAPI::GetSharedInstance()->GetFeatureDependency(dep_name); if (!dependency) return CreateAvailability(NOT_PRESENT);
diff --git a/extensions/common/manifest.cc b/extensions/common/manifest.cc index c2e608f..0aef218 100644 --- a/extensions/common/manifest.cc +++ b/extensions/common/manifest.cc
@@ -247,7 +247,8 @@ } bool Manifest::CanAccessKey(const std::string& key) const { - Feature* feature = FeatureProvider::GetManifestFeatures()->GetFeature(key); + const Feature* feature = + FeatureProvider::GetManifestFeatures()->GetFeature(key); if (!feature) return true;
diff --git a/extensions/common/manifest_handlers/permissions_parser.cc b/extensions/common/manifest_handlers/permissions_parser.cc index af8ba0c..5cbe8bc 100644 --- a/extensions/common/manifest_handlers/permissions_parser.cc +++ b/extensions/common/manifest_handlers/permissions_parser.cc
@@ -117,7 +117,7 @@ for (APIPermissionSet::const_iterator iter = api_permissions->begin(); iter != api_permissions->end(); ++iter) { - Feature* feature = permission_features->GetFeature(iter->name()); + const Feature* feature = permission_features->GetFeature(iter->name()); // The feature should exist since we just got an APIPermission for it. The // two systems should be updated together whenever a permission is added.
diff --git a/extensions/components/native_app_window/native_app_window_views.cc b/extensions/components/native_app_window/native_app_window_views.cc index 4081af9..0104b55 100644 --- a/extensions/components/native_app_window/native_app_window_views.cc +++ b/extensions/components/native_app_window/native_app_window_views.cc
@@ -372,7 +372,7 @@ return draggable_region_.get(); } -void NativeAppWindowViews::UpdateShape(std::unique_ptr<SkRegion> region) { +void NativeAppWindowViews::UpdateShape(std::unique_ptr<ShapeRects> rects) { // Stub implementation. See also ChromeNativeAppWindowViews. }
diff --git a/extensions/components/native_app_window/native_app_window_views.h b/extensions/components/native_app_window/native_app_window_views.h index f89c263..a782d40 100644 --- a/extensions/components/native_app_window/native_app_window_views.h +++ b/extensions/components/native_app_window/native_app_window_views.h
@@ -130,7 +130,7 @@ void UpdateDraggableRegions( const std::vector<extensions::DraggableRegion>& regions) override; SkRegion* GetDraggableRegion() override; - void UpdateShape(std::unique_ptr<SkRegion> region) override; + void UpdateShape(std::unique_ptr<ShapeRects> rects) override; void HandleKeyboardEvent( const content::NativeWebKeyboardEvent& event) override; bool IsFrameless() const override;
diff --git a/extensions/renderer/bindings/argument_spec.cc b/extensions/renderer/bindings/argument_spec.cc index d97263d..b7929cf 100644 --- a/extensions/renderer/bindings/argument_spec.cc +++ b/extensions/renderer/bindings/argument_spec.cc
@@ -214,7 +214,10 @@ switch (type_) { case ArgumentType::INTEGER: - is_valid_type = value->IsInt32(); + // -0 is treated internally as a double, but we classify it as an integer. + is_valid_type = + value->IsInt32() || + (value->IsNumber() && value.As<v8::Number>()->Value() == 0.0); break; case ArgumentType::DOUBLE: is_valid_type = value->IsNumber(); @@ -383,8 +386,15 @@ std::string* error) const { switch (type_) { case ArgumentType::INTEGER: { - DCHECK(value->IsInt32()); - int int_val = value.As<v8::Int32>()->Value(); + DCHECK(value->IsNumber()); + int int_val = 0; + if (value->IsInt32()) { + int_val = value.As<v8::Int32>()->Value(); + } else { + // See comment in IsCorrectType(). + DCHECK_EQ(0.0, value.As<v8::Number>()->Value()); + int_val = 0; + } if (!CheckFundamentalBounds(int_val, minimum_, maximum_, error)) return false; if (out_value)
diff --git a/extensions/renderer/bindings/argument_spec_unittest.cc b/extensions/renderer/bindings/argument_spec_unittest.cc index a12b487..1ebabea 100644 --- a/extensions/renderer/bindings/argument_spec_unittest.cc +++ b/extensions/renderer/bindings/argument_spec_unittest.cc
@@ -154,6 +154,10 @@ ExpectSuccess(spec, "-1", "-1"); ExpectSuccess(spec, "0", "0"); ExpectSuccess(spec, "0.0", "0"); + ExpectSuccess(spec, "-0.0", "0"); + ExpectSuccess(spec, "-0.", "0"); + ExpectSuccess(spec, "-.0", "0"); + ExpectSuccess(spec, "-0", "0"); ExpectFailure(spec, "undefined", InvalidType(kTypeInteger, kTypeUndefined)); ExpectFailure(spec, "null", InvalidType(kTypeInteger, kTypeNull)); ExpectFailure(spec, "1.1", InvalidType(kTypeInteger, kTypeDouble));
diff --git a/extensions/renderer/feature_cache.cc b/extensions/renderer/feature_cache.cc index df10bd2..11e28d7 100644 --- a/extensions/renderer/feature_cache.cc +++ b/extensions/renderer/feature_cache.cc
@@ -61,7 +61,7 @@ GURL empty_url; const Extension* extension = context->extension(); for (const auto& map_entry : api_feature_provider->GetAllFeatures()) { - Feature* feature = map_entry.second.get(); + const Feature* feature = map_entry.second.get(); // Exclude internal APIs. if (feature->IsInternal()) continue;
diff --git a/extensions/shell/BUILD.gn b/extensions/shell/BUILD.gn index 495aa1c..d821baf 100644 --- a/extensions/shell/BUILD.gn +++ b/extensions/shell/BUILD.gn
@@ -174,6 +174,8 @@ if (use_aura) { sources += [ + "browser/root_window_controller.cc", + "browser/root_window_controller.h", "browser/shell_app_window_client_aura.cc", "browser/shell_desktop_controller_aura.cc", "browser/shell_desktop_controller_aura.h", @@ -309,6 +311,7 @@ if (use_aura) { sources += [ + "browser/root_window_controller_unittest.cc", "browser/shell_desktop_controller_aura_unittest.cc", "browser/shell_native_app_window_aura_unittest.cc", "browser/shell_screen_unittest.cc",
diff --git a/extensions/shell/browser/default_shell_browser_main_delegate.cc b/extensions/shell/browser/default_shell_browser_main_delegate.cc index 1275f32..c81eb702 100644 --- a/extensions/shell/browser/default_shell_browser_main_delegate.cc +++ b/extensions/shell/browser/default_shell_browser_main_delegate.cc
@@ -101,9 +101,10 @@ void DefaultShellBrowserMainDelegate::Shutdown() { } -DesktopController* DefaultShellBrowserMainDelegate::CreateDesktopController() { +DesktopController* DefaultShellBrowserMainDelegate::CreateDesktopController( + content::BrowserContext* context) { #if defined(USE_AURA) - return new ShellDesktopControllerAura(); + return new ShellDesktopControllerAura(context); #elif defined(OS_MACOSX) return new ShellDesktopControllerMac(); #else
diff --git a/extensions/shell/browser/default_shell_browser_main_delegate.h b/extensions/shell/browser/default_shell_browser_main_delegate.h index 05ce558..64a132c 100644 --- a/extensions/shell/browser/default_shell_browser_main_delegate.h +++ b/extensions/shell/browser/default_shell_browser_main_delegate.h
@@ -21,7 +21,8 @@ // ShellBrowserMainDelegate: void Start(content::BrowserContext* context) override; void Shutdown() override; - DesktopController* CreateDesktopController() override; + DesktopController* CreateDesktopController( + content::BrowserContext* context) override; private: DISALLOW_COPY_AND_ASSIGN(DefaultShellBrowserMainDelegate);
diff --git a/extensions/shell/browser/root_window_controller.cc b/extensions/shell/browser/root_window_controller.cc new file mode 100644 index 0000000..4988082 --- /dev/null +++ b/extensions/shell/browser/root_window_controller.cc
@@ -0,0 +1,169 @@ +// 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 "extensions/shell/browser/root_window_controller.h" + +#include "extensions/browser/app_window/app_window.h" +#include "extensions/browser/app_window/native_app_window.h" +#include "extensions/shell/browser/shell_app_delegate.h" +#include "extensions/shell/browser/shell_screen.h" +#include "ui/aura/layout_manager.h" +#include "ui/aura/window.h" +#include "ui/aura/window_tracker.h" +#include "ui/aura/window_tree_host.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/geometry/size.h" + +namespace extensions { + +namespace { + +// A simple layout manager that makes each new window fill its parent. +class FillLayout : public aura::LayoutManager { + public: + FillLayout(aura::Window* owner) : owner_(owner) { DCHECK(owner_); } + ~FillLayout() override = default; + + private: + // aura::LayoutManager: + void OnWindowResized() override { + // Size the owner's immediate child windows. + aura::WindowTracker children_tracker(owner_->children()); + while (!children_tracker.windows().empty()) { + aura::Window* child = children_tracker.Pop(); + child->SetBounds(gfx::Rect(owner_->bounds().size())); + } + } + + void OnWindowAddedToLayout(aura::Window* child) override { + DCHECK_EQ(owner_, child->parent()); + + // Create a rect at 0,0 with the size of the parent. + gfx::Size parent_size = child->parent()->bounds().size(); + child->SetBounds(gfx::Rect(parent_size)); + } + + void OnWillRemoveWindowFromLayout(aura::Window* child) override {} + + void OnWindowRemovedFromLayout(aura::Window* child) override {} + + void OnChildWindowVisibilityChanged(aura::Window* child, + bool visible) override {} + + void SetChildBounds(aura::Window* child, + const gfx::Rect& requested_bounds) override { + SetChildBoundsDirect(child, requested_bounds); + } + + aura::Window* owner_; // Not owned. + + DISALLOW_COPY_AND_ASSIGN(FillLayout); +}; + +} // namespace + +RootWindowController::RootWindowController( + DesktopDelegate* desktop_delegate, + ShellScreen* screen, + const gfx::Rect& bounds, + content::BrowserContext* browser_context) + : desktop_delegate_(desktop_delegate), + screen_(screen), + browser_context_(browser_context) { + DCHECK(desktop_delegate_); + DCHECK(screen_); + DCHECK(browser_context_); + host_.reset(aura::WindowTreeHost::Create( + gfx::Rect(screen_->GetPrimaryDisplay().GetSizeInPixel()))); + + // The ShellScreen will resize the primary display when the WindowTreeHost is + // resized, so the display is always the size of the WindowTreeHost. + host_->AddObserver(screen_); + + host_->InitHost(); + host_->window()->Show(); + + aura::client::SetWindowParentingClient(host_->window(), this); + + // Ensure the window fills the display. + host_->window()->SetLayoutManager(new FillLayout(host_->window())); + + host_->AddObserver(this); + host_->Show(); +} + +RootWindowController::~RootWindowController() { + CloseAppWindows(); + DestroyWindowTreeHost(); +} + +AppWindow* RootWindowController::CreateAppWindow( + content::BrowserContext* browser_context, + const Extension* extension) { + // Only one BrowserContext should ever be used with this class. + DCHECK_EQ(browser_context_, browser_context); + + if (app_windows_.empty()) { + // Start observing for OnAppWindowRemoved. + AppWindowRegistry* registry = AppWindowRegistry::Get(browser_context_); + registry->AddObserver(this); + } + + app_windows_.push_back( + new AppWindow(browser_context, new ShellAppDelegate, extension)); + return app_windows_.back(); +} + +void RootWindowController::AddAppWindow(gfx::NativeWindow window) { + aura::Window* root_window = host_->window(); + root_window->AddChild(window); +} + +void RootWindowController::CloseAppWindows() { + if (app_windows_.empty()) + return; + + // Remove the observer before closing windows to avoid triggering + // OnAppWindowRemoved, which would mutate |app_windows_|. + AppWindowRegistry::Get(browser_context_)->RemoveObserver(this); + for (AppWindow* app_window : app_windows_) + app_window->GetBaseWindow()->Close(); // Close() deletes |app_window|. + app_windows_.clear(); +} + +void RootWindowController::UpdateSize(const gfx::Size& size) { + host_->UpdateRootWindowSizeInPixels(size); +} + +aura::Window* RootWindowController::GetDefaultParent(aura::Window* window, + const gfx::Rect& bounds) { + return host_->window(); +} + +void RootWindowController::OnHostCloseRequested(aura::WindowTreeHost* host) { + DCHECK_EQ(host_.get(), host); + CloseAppWindows(); + + // The ShellDesktopControllerAura will delete us. + desktop_delegate_->CloseRootWindowController(this); +} + +void RootWindowController::OnAppWindowRemoved(AppWindow* window) { + if (app_windows_.empty()) + return; + + // If we created this AppWindow, remove it from our list so we don't try to + // close it again later. + app_windows_.remove(window); + if (app_windows_.empty()) + AppWindowRegistry::Get(browser_context_)->RemoveObserver(this); +} + +void RootWindowController::DestroyWindowTreeHost() { + host_->RemoveObserver(screen_); + host_->RemoveObserver(this); + host_.reset(); +} + +} // namespace extensions
diff --git a/extensions/shell/browser/root_window_controller.h b/extensions/shell/browser/root_window_controller.h new file mode 100644 index 0000000..92bf969 --- /dev/null +++ b/extensions/shell/browser/root_window_controller.h
@@ -0,0 +1,109 @@ +// 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 EXTENSIONS_SHELL_BROWSER_ROOT_WINDOW_CONTROLLER_H_ +#define EXTENSIONS_SHELL_BROWSER_ROOT_WINDOW_CONTROLLER_H_ + +#include <list> +#include <memory> + +#include "base/macros.h" +#include "extensions/browser/app_window/app_window_registry.h" +#include "ui/aura/client/window_parenting_client.h" +#include "ui/aura/window_tree_host_observer.h" +#include "ui/gfx/native_widget_types.h" + +namespace aura { +class WindowTreeHost; +} // namespace aura + +namespace content { +class BrowserContext; +} // namespace content + +namespace gfx { +class Rect; +class Size; +} // namespace gfx + +namespace extensions { +class AppWindow; +class Extension; +class ShellScreen; + +// Owns and manages a WindowTreeHost for a display. New AppWindows will fill +// the entire root window. Any additional AppWindows are simply drawn over the +// existing AppWindow(s) and cannot be resized except by resizing the +// WindowTreeHost. +class RootWindowController : public aura::client::WindowParentingClient, + public aura::WindowTreeHostObserver, + public AppWindowRegistry::Observer { + public: + class DesktopDelegate { + public: + virtual ~DesktopDelegate() = default; + + // Called when the root window requests to be closed. This should eventually + // destroy |root_window_controller|. + virtual void CloseRootWindowController( + RootWindowController* root_window_controller) = 0; + }; + + // RootWindowController initializes and displays a WindowTreeHost within + // |bounds|. |desktop_delegate| must outlive the RootWindowController. + RootWindowController(DesktopDelegate* desktop_delegate, + ShellScreen* screen, + const gfx::Rect& bounds, + content::BrowserContext* browser_context); + ~RootWindowController() override; + + // Creates a new app window and adds it to the desktop. The AppWindow deletes + // itself when its native window closes. + AppWindow* CreateAppWindow(content::BrowserContext* context, + const Extension* extension); + + // Attaches a NativeAppWindow's window to our root window. + void AddAppWindow(gfx::NativeWindow window); + + // Closes the root window's AppWindows, resulting in their destruction. + void CloseAppWindows(); + + // Updates the size of the root window. + void UpdateSize(const gfx::Size& size); + + aura::WindowTreeHost* host() { return host_.get(); } + + // aura::client::WindowParentingClient: + aura::Window* GetDefaultParent(aura::Window* window, + const gfx::Rect& bounds) override; + + // aura::WindowTreeHostObserver: + void OnHostCloseRequested(aura::WindowTreeHost* host) override; + + // AppWindowRegistry::Observer: + void OnAppWindowRemoved(AppWindow* app_window) override; + + private: + void DestroyWindowTreeHost(); + + DesktopDelegate* const desktop_delegate_; + ShellScreen* const screen_; + + // The BrowserContext used to create AppWindows. + content::BrowserContext* const browser_context_; + + // The host we create. + std::unique_ptr<aura::WindowTreeHost> host_; + + // List of AppWindows we've created. Used to close any remaining app windows + // when |host_| is closed or |this| is destroyed. + // Note: Pointers are unowned. NativeAppWindow::Close() will delete them. + std::list<AppWindow*> app_windows_; + + DISALLOW_COPY_AND_ASSIGN(RootWindowController); +}; + +} // namespace extensions + +#endif // EXTENSIONS_SHELL_BROWSER_ROOT_WINDOW_CONTROLLER_H_
diff --git a/extensions/shell/browser/root_window_controller_unittest.cc b/extensions/shell/browser/root_window_controller_unittest.cc new file mode 100644 index 0000000..1455c7b --- /dev/null +++ b/extensions/shell/browser/root_window_controller_unittest.cc
@@ -0,0 +1,236 @@ +// 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 "extensions/shell/browser/root_window_controller.h" + +#include <algorithm> +#include <list> +#include <memory> + +#include "base/memory/ptr_util.h" +#include "content/public/browser/browser_context.h" +#include "extensions/browser/app_window/app_window.h" +#include "extensions/browser/app_window/native_app_window.h" +#include "extensions/common/test_util.h" +#include "extensions/shell/browser/root_window_controller.h" +#include "extensions/shell/browser/shell_app_window_client.h" +#include "extensions/shell/browser/shell_native_app_window_aura.h" +#include "extensions/shell/browser/shell_screen.h" +#include "extensions/shell/test/shell_test_base_aura.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/aura/window.h" +#include "ui/aura/window_tree_host.h" +#include "ui/display/screen.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/geometry/size.h" + +namespace extensions { + +namespace { + +// A fake that creates and exposes RootWindowControllers. +class FakeDesktopDelegate : public RootWindowController::DesktopDelegate { + public: + explicit FakeDesktopDelegate(content::BrowserContext* browser_context, + ShellScreen* screen, + const gfx::Rect& bounds) + : browser_context_(browser_context), screen_(screen), bounds_(bounds) {} + ~FakeDesktopDelegate() override = default; + + RootWindowController* CreateRootWindowController() { + root_window_controllers_.emplace_back( + base::MakeUnique<RootWindowController>(this, screen_, bounds_, + browser_context_)); + return root_window_controllers_.back().get(); + } + + // RootWindowController::DesktopDelegate: + void CloseRootWindowController( + RootWindowController* root_window_controller) override { + auto it = std::find_if(root_window_controllers_.begin(), + root_window_controllers_.end(), + [&](const auto& candidate) { + return candidate.get() == root_window_controller; + }); + DCHECK(it != root_window_controllers_.end()); + root_window_controllers_.erase(it); + } + + auto root_window_controller_count() { + return root_window_controllers_.size(); + } + + private: + content::BrowserContext* browser_context_; + ShellScreen* screen_; + const gfx::Rect bounds_; + std::list<std::unique_ptr<RootWindowController>> root_window_controllers_; + + DISALLOW_COPY_AND_ASSIGN(FakeDesktopDelegate); +}; + +// An AppWindowClient for use without a DesktopController. +class TestAppWindowClient : public ShellAppWindowClient { + public: + TestAppWindowClient() = default; + ~TestAppWindowClient() override = default; + + NativeAppWindow* CreateNativeAppWindow( + AppWindow* window, + AppWindow::CreateParams* params) override { + return new ShellNativeAppWindowAura(window, *params); + } +}; + +constexpr gfx::Rect kScreenBounds = gfx::Rect(0, 0, 800, 600); + +} // namespace + +class RootWindowControllerTest : public ShellTestBaseAura { + public: + RootWindowControllerTest() = default; + ~RootWindowControllerTest() override = default; + + void SetUp() override { + ShellTestBaseAura::SetUp(); + + AppWindowClient::Set(&app_window_client_); + screen_ = base::MakeUnique<ShellScreen>(nullptr, kScreenBounds.size()); + display::Screen::SetScreenInstance(screen_.get()); + extension_ = test_util::CreateEmptyExtension(); + + desktop_delegate_ = base::MakeUnique<FakeDesktopDelegate>( + browser_context(), screen_.get(), kScreenBounds); + } + + void TearDown() override { + desktop_delegate_.reset(); + display::Screen::SetScreenInstance(nullptr); + screen_.reset(); + AppWindowClient::Set(nullptr); + ShellTestBaseAura::TearDown(); + } + + protected: + // Creates and returns an AppWindow using the RootWindowController. + AppWindow* CreateAppWindow(RootWindowController* root) { + AppWindow* app_window = + root->CreateAppWindow(browser_context(), extension()); + InitAppWindow(app_window); + root->AddAppWindow(app_window->GetNativeWindow()); + return app_window; + } + + // Checks that there are |num_expected| AppWindows open. + void ExpectNumAppWindows(RootWindowController* root, size_t expected) { + EXPECT_EQ(expected, root->host()->window()->children().size()); + EXPECT_EQ(expected, + AppWindowRegistry::Get(browser_context())->app_windows().size()); + } + + FakeDesktopDelegate* desktop_delegate() { return desktop_delegate_.get(); } + const Extension* extension() { return extension_.get(); } + + ShellScreen* screen() { return screen_.get(); } + + private: + TestAppWindowClient app_window_client_; + + scoped_refptr<Extension> extension_; + std::unique_ptr<ShellScreen> screen_; + std::unique_ptr<FakeDesktopDelegate> desktop_delegate_; + + DISALLOW_COPY_AND_ASSIGN(RootWindowControllerTest); +}; + +// Tests RootWindowController's basic setup and teardown. +TEST_F(RootWindowControllerTest, Basic) { + RootWindowController* root_window_controller = + desktop_delegate()->CreateRootWindowController(); + EXPECT_TRUE(root_window_controller->host()); + + // The RootWindowController destroys itself when the root window closes. + root_window_controller->OnHostCloseRequested(root_window_controller->host()); + EXPECT_EQ(0u, desktop_delegate()->root_window_controller_count()); +} + +// Tests the window layout. +TEST_F(RootWindowControllerTest, FillLayout) { + RootWindowController* root_window_controller = + desktop_delegate()->CreateRootWindowController(); + + root_window_controller->host()->SetBoundsInPixels(gfx::Rect(0, 0, 500, 700)); + + AppWindow* app_window = + root_window_controller->CreateAppWindow(browser_context(), extension()); + InitAppWindow(app_window); + root_window_controller->AddAppWindow(app_window->GetNativeWindow()); + + ExpectNumAppWindows(root_window_controller, 1u); + + // Test that reshaping the host window also resizes the child window, and + // moving the host doesn't affect the child's position relative to the host. + root_window_controller->host()->SetBoundsInPixels( + gfx::Rect(100, 200, 300, 400)); + + const aura::Window* root_window = root_window_controller->host()->window(); + EXPECT_EQ(gfx::Rect(0, 0, 300, 400), root_window->bounds()); + EXPECT_EQ(gfx::Rect(0, 0, 300, 400), root_window->children()[0]->bounds()); + + // The AppWindow will close on shutdown. +} + +// Tests creating and removing AppWindows. +TEST_F(RootWindowControllerTest, AppWindows) { + RootWindowController* root_window_controller = + desktop_delegate()->CreateRootWindowController(); + + { + // Create some AppWindows. + CreateAppWindow(root_window_controller); + AppWindow* middle_window = CreateAppWindow(root_window_controller); + CreateAppWindow(root_window_controller); + + ExpectNumAppWindows(root_window_controller, 3u); + + // Close one window, which deletes |middle_window|. + middle_window->GetBaseWindow()->Close(); + } + + ExpectNumAppWindows(root_window_controller, 2u); + + // Close all remaining windows. + root_window_controller->CloseAppWindows(); + ExpectNumAppWindows(root_window_controller, 0u); +} + +// Tests that a second RootWindowController can be used independently of the +// first. +TEST_F(RootWindowControllerTest, Multiple) { + // Create the longer-lived RootWindowController before the shorter-lived one + // is deleted. Otherwise it may be created at the same address, preventing + // the test from failing on use-after-free. + RootWindowController* longer_lived = + desktop_delegate()->CreateRootWindowController(); + { + RootWindowController* shorter_lived = + desktop_delegate()->CreateRootWindowController(); + { + AppWindow* app_window = CreateAppWindow(shorter_lived); + ExpectNumAppWindows(shorter_lived, 1u); + app_window->GetBaseWindow()->Close(); // Deletes the AppWindow. + } + ExpectNumAppWindows(shorter_lived, 0u); + + // Simulate a close request to delete the controller. + shorter_lived->OnHostCloseRequested(shorter_lived->host()); + } + + // The still-living RootWindowController can still be used. + AppWindow* app_window = CreateAppWindow(longer_lived); + ExpectNumAppWindows(longer_lived, 1u); + app_window->GetBaseWindow()->Close(); +} + +} // namespace extensions
diff --git a/extensions/shell/browser/shell_browser_main_delegate.h b/extensions/shell/browser/shell_browser_main_delegate.h index a3ddf7f..67d2d7c 100644 --- a/extensions/shell/browser/shell_browser_main_delegate.h +++ b/extensions/shell/browser/shell_browser_main_delegate.h
@@ -28,7 +28,8 @@ // Creates the ShellDesktopControllerAura instance to initialize the root // window and window manager. Subclass may return its subclass to customize // the window manager. - virtual DesktopController* CreateDesktopController() = 0; + virtual DesktopController* CreateDesktopController( + content::BrowserContext* context) = 0; }; } // namespace extensions
diff --git a/extensions/shell/browser/shell_browser_main_parts.cc b/extensions/shell/browser/shell_browser_main_parts.cc index ea8076a1..b772850a 100644 --- a/extensions/shell/browser/shell_browser_main_parts.cc +++ b/extensions/shell/browser/shell_browser_main_parts.cc
@@ -179,7 +179,8 @@ storage_monitor::StorageMonitor::Create(); - desktop_controller_.reset(browser_main_delegate_->CreateDesktopController()); + desktop_controller_.reset( + browser_main_delegate_->CreateDesktopController(browser_context_.get())); // TODO(jamescook): Initialize user_manager::UserManager.
diff --git a/extensions/shell/browser/shell_desktop_controller_aura.cc b/extensions/shell/browser/shell_desktop_controller_aura.cc index 5ecf36f..c563510 100644 --- a/extensions/shell/browser/shell_desktop_controller_aura.cc +++ b/extensions/shell/browser/shell_desktop_controller_aura.cc
@@ -4,36 +4,28 @@ #include "extensions/shell/browser/shell_desktop_controller_aura.h" -#include <algorithm> #include <string> #include "base/command_line.h" #include "base/location.h" #include "base/logging.h" -#include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" -#include "build/build_config.h" -#include "extensions/browser/app_window/app_window.h" -#include "extensions/browser/app_window/native_app_window.h" -#include "extensions/shell/browser/shell_app_delegate.h" #include "extensions/shell/browser/shell_app_window_client.h" #include "extensions/shell/browser/shell_screen.h" #include "extensions/shell/common/switches.h" #include "ui/aura/client/cursor_client.h" #include "ui/aura/client/default_capture_client.h" -#include "ui/aura/layout_manager.h" #include "ui/aura/window.h" -#include "ui/aura/window_tracker.h" #include "ui/aura/window_tree_host.h" #include "ui/base/cursor/cursor.h" #include "ui/base/cursor/image_cursors.h" #include "ui/base/ime/input_method.h" +#include "ui/base/ime/input_method_factory.h" #include "ui/base/user_activity/user_activity_detector.h" #include "ui/display/screen.h" -#include "ui/events/event_sink.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/native_widget_types.h" @@ -58,55 +50,14 @@ namespace extensions { namespace { -// A simple layout manager that makes each new window fill the root window. -class FillLayout : public aura::LayoutManager { - public: - FillLayout(aura::Window* owner) : owner_(owner) { DCHECK(owner_); } - - ~FillLayout() override {} - - private: - // aura::LayoutManager: - void OnWindowResized() override { - // Size the owner's immediate child windows. - aura::WindowTracker children_tracker(owner_->children()); - while (!children_tracker.windows().empty()) { - aura::Window* child = children_tracker.Pop(); - child->SetBounds(gfx::Rect(owner_->bounds().size())); - } - } - - void OnWindowAddedToLayout(aura::Window* child) override { - DCHECK_EQ(owner_, child->parent()); - - // Create a rect at 0,0 with the size of the parent. - gfx::Size parent_size = child->parent()->bounds().size(); - child->SetBounds(gfx::Rect(parent_size)); - } - - void OnWillRemoveWindowFromLayout(aura::Window* child) override {} - - void OnWindowRemovedFromLayout(aura::Window* child) override {} - - void OnChildWindowVisibilityChanged(aura::Window* child, - bool visible) override {} - - void SetChildBounds(aura::Window* child, - const gfx::Rect& requested_bounds) override { - SetChildBoundsDirect(child, requested_bounds); - } - - aura::Window* owner_; // Not owned. - - DISALLOW_COPY_AND_ASSIGN(FillLayout); -}; - // A class that bridges the gap between CursorManager and Aura. It borrows // heavily from NativeCursorManagerAsh. class ShellNativeCursorManager : public wm::NativeCursorManager { public: - explicit ShellNativeCursorManager(aura::WindowTreeHost* host) - : host_(host), image_cursors_(new ui::ImageCursors) {} + explicit ShellNativeCursorManager( + ShellDesktopControllerAura* desktop_controller) + : desktop_controller_(desktop_controller), + image_cursors_(new ui::ImageCursors) {} ~ShellNativeCursorManager() override {} // wm::NativeCursorManager overrides. @@ -123,7 +74,7 @@ delegate->CommitCursor(cursor); if (delegate->IsCursorVisible()) - ApplyCursor(cursor); + SetCursorOnAllRootWindows(cursor); } void SetVisibility(bool visible, @@ -135,7 +86,7 @@ } else { gfx::NativeCursor invisible_cursor(ui::CursorType::kNone); image_cursors_->SetPlatformCursor(&invisible_cursor); - ApplyCursor(invisible_cursor); + SetCursorOnAllRootWindows(invisible_cursor); } } @@ -156,9 +107,12 @@ private: // Sets |cursor| as the active cursor within Aura. - void ApplyCursor(gfx::NativeCursor cursor) { host_->SetCursor(cursor); } + void SetCursorOnAllRootWindows(gfx::NativeCursor cursor) { + if (desktop_controller_->GetPrimaryHost()) + desktop_controller_->GetPrimaryHost()->SetCursor(cursor); + } - aura::WindowTreeHost* host_; // Not owned. + ShellDesktopControllerAura* desktop_controller_; // Not owned. std::unique_ptr<ui::ImageCursors> image_cursors_; @@ -180,8 +134,10 @@ } // namespace -ShellDesktopControllerAura::ShellDesktopControllerAura() - : app_window_client_(new ShellAppWindowClient) { +ShellDesktopControllerAura::ShellDesktopControllerAura( + content::BrowserContext* browser_context) + : browser_context_(browser_context), + app_window_client_(new ShellAppWindowClient) { extensions::AppWindowClient::Set(app_window_client_.get()); #if defined(OS_CHROMEOS) @@ -193,12 +149,12 @@ display_configurator_->ForceInitialConfigure(); display_configurator_->AddObserver(this); #endif - CreateRootWindow(); + + InitWindowManager(); } ShellDesktopControllerAura::~ShellDesktopControllerAura() { - CloseAppWindows(); - DestroyRootWindow(); + TearDownWindowManager(); #if defined(OS_CHROMEOS) chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver( this); @@ -216,41 +172,26 @@ AppWindow* ShellDesktopControllerAura::CreateAppWindow( content::BrowserContext* context, const Extension* extension) { - // Start observing for OnAppWindowClosed. Note: We can't remove this observer - // later because this class expects to outlive the AppWindowRegistry. - AppWindowRegistry* registry = AppWindowRegistry::Get(context); - if (!registry->HasObserver(this)) - registry->AddObserver(this); - - app_windows_.push_back( - new AppWindow(context, new ShellAppDelegate, extension)); - return app_windows_.back(); + return root_window_controller_->CreateAppWindow(context, extension); } void ShellDesktopControllerAura::AddAppWindow(gfx::NativeWindow window) { - aura::Window* root_window = host_->window(); - root_window->AddChild(window); + root_window_controller_->AddAppWindow(window); } void ShellDesktopControllerAura::CloseAppWindows() { - // Move the original list into a temporary one: Closing the windows will - // trigger OnAppWindowRemoved, which would invalidate iterators into the - // original list. - std::list<AppWindow*> app_windows = std::move(app_windows_); - for (AppWindow* app_window : app_windows) - app_window->GetBaseWindow()->Close(); // Close() deletes |app_window|. + root_window_controller_->CloseAppWindows(); } -void ShellDesktopControllerAura::OnAppWindowRemoved(AppWindow* window) { - // If we created this AppWindow, remove it from our list so we don't try to - // close it again later. - app_windows_.remove(window); -} +void ShellDesktopControllerAura::CloseRootWindowController( + RootWindowController* root_window_controller) { + DCHECK_EQ(root_window_controller_.get(), root_window_controller); -aura::Window* ShellDesktopControllerAura::GetDefaultParent( - aura::Window* window, - const gfx::Rect& bounds) { - return host_->window(); + // Just quit. The RootWindowController must stay alive until we begin + // TearDownWindowManager(). + // run_loop_ may be null in tests. + if (run_loop_) + run_loop_->QuitWhenIdle(); } #if defined(OS_CHROMEOS) @@ -268,56 +209,103 @@ const display::DisplayConfigurator::DisplayStateList& displays) { gfx::Size size = GetPrimaryDisplaySize(); if (!size.IsEmpty()) - host_->UpdateRootWindowSizeInPixels(size); + root_window_controller_->UpdateSize(size); } #endif -void ShellDesktopControllerAura::OnHostCloseRequested( - aura::WindowTreeHost* host) { - DCHECK_EQ(host_.get(), host); - CloseAppWindows(); - - // run_loop_ may be null in tests. - if (run_loop_) - run_loop_->QuitWhenIdle(); -} - ui::EventDispatchDetails ShellDesktopControllerAura::DispatchKeyEventPostIME( ui::KeyEvent* key_event) { - return host_->DispatchKeyEventPostIME(key_event); + DCHECK(root_window_controller_); + + // TODO(michaelpg): With multiple windows, determine which root window + // triggered the event. See ash::WindowTreeHostManager for example. + return GetPrimaryHost()->DispatchKeyEventPostIME(key_event); +} + +aura::WindowTreeHost* ShellDesktopControllerAura::GetPrimaryHost() { + if (!root_window_controller_) + return nullptr; + return root_window_controller_->host(); } void ShellDesktopControllerAura::InitWindowManager() { - wm::FocusController* focus_controller = - new wm::FocusController(new AppsFocusRules()); - aura::client::SetFocusClient(host_->window(), focus_controller); - host_->window()->AddPreTargetHandler(focus_controller); - wm::SetActivationClient(host_->window(), focus_controller); - focus_client_.reset(focus_controller); + root_window_event_filter_ = base::MakeUnique<wm::CompoundEventFilter>(); - capture_client_.reset( - new aura::client::DefaultCaptureClient(host_->window())); + // Set up basic pieces of ui::wm. + screen_ = base::MakeUnique<ShellScreen>(this, GetStartingWindowSize()); + display::Screen::SetScreenInstance(screen_.get()); - // Ensure new windows fill the display. - host_->window()->SetLayoutManager(new FillLayout(host_->window())); + focus_controller_ = + base::MakeUnique<wm::FocusController>(new AppsFocusRules()); - cursor_manager_.reset( - new wm::CursorManager(std::unique_ptr<wm::NativeCursorManager>( - new ShellNativeCursorManager(host_.get())))); - cursor_manager_->SetDisplay( - display::Screen::GetScreen()->GetPrimaryDisplay()); - cursor_manager_->SetCursor(ui::CursorType::kPointer); - aura::client::SetCursorClient(host_->window(), cursor_manager_.get()); + cursor_manager_ = base::MakeUnique<wm::CursorManager>( + base::MakeUnique<ShellNativeCursorManager>(this)); - user_activity_detector_.reset(new ui::UserActivityDetector); + user_activity_detector_ = base::MakeUnique<ui::UserActivityDetector>(); #if defined(OS_CHROMEOS) - user_activity_notifier_.reset( - new ui::UserActivityPowerManagerNotifier(user_activity_detector_.get())); + user_activity_notifier_ = + base::MakeUnique<ui::UserActivityPowerManagerNotifier>( + user_activity_detector_.get()); #endif + + // Create the root window, then set it up as our primary window. + CreateRootWindowController(); + FinalizeWindowManager(); } -void ShellDesktopControllerAura::CreateRootWindow() { - // Set up basic pieces of ui::wm. +void ShellDesktopControllerAura::CreateRootWindowController() { + // TODO(michaelpg): Support creating a host for a secondary display. + root_window_controller_ = base::MakeUnique<RootWindowController>( + this, screen_.get(), + gfx::Rect(screen_->GetPrimaryDisplay().GetSizeInPixel()), + browser_context_); + + // Initialize the root window with our clients. + aura::Window* root_window = root_window_controller_->host()->window(); + root_window->AddPreTargetHandler(root_window_event_filter_.get()); + aura::client::SetFocusClient(root_window, focus_controller_.get()); + root_window->AddPreTargetHandler(focus_controller_.get()); + wm::SetActivationClient(root_window, focus_controller_.get()); + aura::client::SetCursorClient(root_window, cursor_manager_.get()); +} + +void ShellDesktopControllerAura::FinalizeWindowManager() { + // Create an input method and become its delegate. + input_method_ = + ui::CreateInputMethod(this, GetPrimaryHost()->GetAcceleratedWidget()); + + cursor_manager_->SetDisplay(screen_->GetPrimaryDisplay()); + cursor_manager_->SetCursor(ui::CursorType::kPointer); + + // TODO(michaelpg): Replace with a capture client supporting multiple + // WindowTreeHosts. + capture_client_ = base::MakeUnique<aura::client::DefaultCaptureClient>( + GetPrimaryHost()->window()); +} + +void ShellDesktopControllerAura::TearDownWindowManager() { + GetPrimaryHost()->window()->RemovePreTargetHandler( + root_window_event_filter_.get()); + root_window_event_filter_.reset(); + + // The DefaultCaptureClient must be destroyed before the root window. + capture_client_.reset(); + + GetPrimaryHost()->window()->RemovePreTargetHandler(focus_controller_.get()); + wm::SetActivationClient(GetPrimaryHost()->window(), nullptr); + root_window_controller_.reset(); + + focus_controller_.reset(); + cursor_manager_.reset(); +#if defined(OS_CHROMEOS) + user_activity_notifier_.reset(); +#endif + user_activity_detector_.reset(); + display::Screen::SetScreenInstance(nullptr); + screen_.reset(); +} + +gfx::Size ShellDesktopControllerAura::GetStartingWindowSize() { gfx::Size size; base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); if (command_line->HasSwitch(switches::kAppShellHostWindowSize)) { @@ -331,49 +319,7 @@ } if (size.IsEmpty()) size = gfx::Size(1920, 1080); - - screen_.reset(new ShellScreen(size)); - display::Screen::SetScreenInstance(screen_.get()); - - host_.reset(screen_->CreateHostForPrimaryDisplay()); - aura::client::SetWindowParentingClient(host_->window(), this); - root_window_event_filter_.reset(new wm::CompoundEventFilter); - host_->window()->AddPreTargetHandler(root_window_event_filter_.get()); - - // Trigger creation of an input method and become its delegate. - ui::InputMethod* input_method = host_->GetInputMethod(); - input_method->SetDelegate(this); - - InitWindowManager(); - - host_->AddObserver(this); - - // Ensure the X window gets mapped. - host_->Show(); -} - -void ShellDesktopControllerAura::DestroyRootWindow() { - host_->RemoveObserver(this); - wm::FocusController* focus_controller = - static_cast<wm::FocusController*>(focus_client_.get()); - if (focus_controller) { - host_->window()->RemovePreTargetHandler(focus_controller); - wm::SetActivationClient(host_->window(), NULL); - } - - host_->window()->RemovePreTargetHandler(root_window_event_filter_.get()); - root_window_event_filter_.reset(); - - capture_client_.reset(); - focus_client_.reset(); - cursor_manager_.reset(); -#if defined(OS_CHROMEOS) - user_activity_notifier_.reset(); -#endif - user_activity_detector_.reset(); - host_.reset(); - display::Screen::SetScreenInstance(nullptr); - screen_.reset(); + return size; } gfx::Size ShellDesktopControllerAura::GetPrimaryDisplaySize() {
diff --git a/extensions/shell/browser/shell_desktop_controller_aura.h b/extensions/shell/browser/shell_desktop_controller_aura.h index 4dae572..d18a1b4 100644 --- a/extensions/shell/browser/shell_desktop_controller_aura.h +++ b/extensions/shell/browser/shell_desktop_controller_aura.h
@@ -5,16 +5,13 @@ #ifndef EXTENSIONS_SHELL_BROWSER_SHELL_DESKTOP_CONTROLLER_AURA_H_ #define EXTENSIONS_SHELL_BROWSER_SHELL_DESKTOP_CONTROLLER_AURA_H_ -#include <list> #include <memory> #include "base/compiler_specific.h" #include "base/macros.h" #include "build/build_config.h" -#include "extensions/browser/app_window/app_window_registry.h" #include "extensions/shell/browser/desktop_controller.h" -#include "ui/aura/client/window_parenting_client.h" -#include "ui/aura/window_tree_host_observer.h" +#include "extensions/shell/browser/root_window_controller.h" #include "ui/base/ime/input_method_delegate.h" #if defined(OS_CHROMEOS) @@ -23,57 +20,56 @@ #endif namespace aura { -class Window; class WindowTreeHost; namespace client { class DefaultCaptureClient; -class FocusClient; -} -} +} // namespace client +} // namespace aura namespace base { class RunLoop; -} +} // namespace base + +namespace content { +class BrowserContext; +} // namespace content namespace gfx { class Size; -} +} // namespace gfx namespace ui { +class InputMethod; class UserActivityDetector; #if defined(OS_CHROMEOS) class UserActivityPowerManagerNotifier; #endif -} +} // namespace ui namespace wm { class CompoundEventFilter; class CursorManager; -} +class FocusController; +} // namespace wm namespace extensions { class AppWindowClient; -class Extension; class ShellScreen; // Simple desktop controller for app_shell. Sets up a root Aura window for the // primary display. class ShellDesktopControllerAura : public DesktopController, - public AppWindowRegistry::Observer, - public aura::client::WindowParentingClient, + public RootWindowController::DesktopDelegate, #if defined(OS_CHROMEOS) public chromeos::PowerManagerClient::Observer, public display::DisplayConfigurator::Observer, #endif - public aura::WindowTreeHostObserver, public ui::internal::InputMethodDelegate { public: - ShellDesktopControllerAura(); + explicit ShellDesktopControllerAura(content::BrowserContext* browser_context); ~ShellDesktopControllerAura() override; - aura::WindowTreeHost* host() { return host_.get(); } - // DesktopController: void Run() override; AppWindow* CreateAppWindow(content::BrowserContext* context, @@ -81,12 +77,9 @@ void AddAppWindow(gfx::NativeWindow window) override; void CloseAppWindows() override; - // AppWindowRegistry::Observer overrides: - void OnAppWindowRemoved(AppWindow* app_window) override; - - // aura::client::WindowParentingClient overrides: - aura::Window* GetDefaultParent(aura::Window* window, - const gfx::Rect& bounds) override; + // RootWindowController::DesktopDelegate: + void CloseRootWindowController( + RootWindowController* root_window_controller) override; #if defined(OS_CHROMEOS) // chromeos::PowerManagerClient::Observer overrides: @@ -98,42 +91,58 @@ const display::DisplayConfigurator::DisplayStateList& displays) override; #endif - // aura::WindowTreeHostObserver overrides: - void OnHostCloseRequested(aura::WindowTreeHost* host) override; - // ui::internal::InputMethodDelegate overrides: ui::EventDispatchDetails DispatchKeyEventPostIME( ui::KeyEvent* key_event) override; + // Returns the RootWindowController's WindowTreeHost. + aura::WindowTreeHost* GetPrimaryHost(); + + RootWindowController* root_window_controller() { + return root_window_controller_.get(); + } + protected: // Creates and sets the aura clients and window manager stuff. Subclass may // initialize different sets of the clients. virtual void InitWindowManager(); - private: - // Creates the window that hosts the app. - void CreateRootWindow(); + // Tears down the window manager stuff set up in InitWindowManager(). + virtual void TearDownWindowManager(); - // Closes and destroys the root window hosting the app. - void DestroyRootWindow(); + private: + // Creates the RootWindowController that hosts the app. + void CreateRootWindowController(); + + // Finishes set-up using the RootWindowController. + void FinalizeWindowManager(); + + // Returns the desired dimensions of the RootWindowController from the command + // line, or falls back to a default size. + gfx::Size GetStartingWindowSize(); // Returns the dimensions (in pixels) of the primary display, or an empty size // if the dimensions can't be determined or no display is connected. gfx::Size GetPrimaryDisplaySize(); + content::BrowserContext* const browser_context_; + #if defined(OS_CHROMEOS) std::unique_ptr<display::DisplayConfigurator> display_configurator_; #endif std::unique_ptr<ShellScreen> screen_; - std::unique_ptr<aura::WindowTreeHost> host_; - std::unique_ptr<wm::CompoundEventFilter> root_window_event_filter_; + // TODO(michaelpg): Support one RootWindowController per display. + std::unique_ptr<RootWindowController> root_window_controller_; + + std::unique_ptr<ui::InputMethod> input_method_; + std::unique_ptr<aura::client::DefaultCaptureClient> capture_client_; - std::unique_ptr<aura::client::FocusClient> focus_client_; + std::unique_ptr<wm::FocusController> focus_controller_; std::unique_ptr<wm::CursorManager> cursor_manager_;
diff --git a/extensions/shell/browser/shell_desktop_controller_aura_unittest.cc b/extensions/shell/browser/shell_desktop_controller_aura_unittest.cc index 4590aff8..af55714b 100644 --- a/extensions/shell/browser/shell_desktop_controller_aura_unittest.cc +++ b/extensions/shell/browser/shell_desktop_controller_aura_unittest.cc
@@ -56,12 +56,7 @@ #endif ShellTestBaseAura::SetUp(); - - // The input method will be used for the next CreateInputMethod call, - // causing the host to take ownership. - ui::SetUpInputMethodForTesting(new ui::InputMethodMinimal(nullptr)); - - controller_.reset(new ShellDesktopControllerAura()); + controller_.reset(new ShellDesktopControllerAura(browser_context())); } void TearDown() override { @@ -73,30 +68,6 @@ } protected: - // Creates an AppWindow, which should delete itself when closed. - AppWindow* CreateAppWindow(Extension* extension) { - AppWindow* app_window = - controller_->CreateAppWindow(browser_context(), extension); - - std::unique_ptr<content::WebContents> web_contents( - content::WebContents::Create( - content::WebContents::CreateParams(browser_context()))); - std::unique_ptr<TestAppWindowContents> app_window_contents = - base::MakeUnique<TestAppWindowContents>(std::move(web_contents)); - - // Init the ShellExtensionsWebContentsObserver. - app_window->app_delegate()->InitWebContents( - app_window_contents->GetWebContents()); - - content::RenderFrameHost* main_frame = - app_window_contents->GetWebContents()->GetMainFrame(); - EXPECT_TRUE(main_frame); - - app_window->Init(GURL(std::string()), app_window_contents.release(), - main_frame, AppWindow::CreateParams()); - return app_window; - } - std::unique_ptr<ShellDesktopControllerAura> controller_; #if defined(OS_CHROMEOS) @@ -126,7 +97,8 @@ // Tests that basic input events are handled and forwarded to the host. // TODO(michaelpg): Test other types of input. TEST_F(ShellDesktopControllerAuraTest, InputEvents) { - ui::InputMethod* input_method = controller_->host()->GetInputMethod(); + ui::InputMethod* input_method = + controller_->GetPrimaryHost()->GetInputMethod(); ASSERT_TRUE(input_method); // Set up a focused text input to receive the keypress event. @@ -137,8 +109,8 @@ // Dispatch a keypress on the window tree host to verify it is processed. ui::KeyEvent key_press(base::char16(97), ui::VKEY_A, ui::EF_NONE); ui::EventDispatchDetails details = - controller_->host()->dispatcher()->DispatchEvent( - controller_->host()->window(), &key_press); + controller_->GetPrimaryHost()->dispatcher()->DispatchEvent( + controller_->GetPrimaryHost()->window(), &key_press); EXPECT_FALSE(details.dispatcher_destroyed); EXPECT_FALSE(details.target_destroyed); EXPECT_TRUE(key_press.handled()); @@ -148,58 +120,35 @@ input_method->DetachTextInputClient(&client); } -// Tests the basic window layout. -TEST_F(ShellDesktopControllerAuraTest, FillLayout) { - controller_->host()->SetBoundsInPixels(gfx::Rect(0, 0, 500, 700)); - - scoped_refptr<Extension> extension = test_util::CreateEmptyExtension(); - CreateAppWindow(extension.get()); - - aura::Window* root_window = controller_->host()->window(); - EXPECT_EQ(1u, root_window->children().size()); - - // Test that reshaping the host window also resizes the child window. - controller_->host()->SetBoundsInPixels(gfx::Rect(0, 0, 400, 300)); - - EXPECT_EQ(400, root_window->bounds().width()); - EXPECT_EQ(400, root_window->children()[0]->bounds().width()); - - // The AppWindow will close on shutdown. -} - -// Tests that the AppWindows are removed when closed. -TEST_F(ShellDesktopControllerAuraTest, OnAppWindowClose) { - scoped_refptr<Extension> extension = test_util::CreateEmptyExtension(); - AppWindow* app_window1 = CreateAppWindow(extension.get()); - - aura::Window* root_window = controller_->host()->window(); - EXPECT_EQ(1u, root_window->children().size()); - - AppWindow* app_window2 = CreateAppWindow(extension.get()); - EXPECT_EQ(2u, root_window->children().size()); - - app_window1->GetBaseWindow()->Close(); - app_window1 = nullptr; // Close() deletes the AppWindow. - // The second window is still open. - EXPECT_EQ(1u, root_window->children().size()); - - app_window2->GetBaseWindow()->Close(); - app_window2 = nullptr; // Close() deletes the AppWindow. - EXPECT_EQ(0u, root_window->children().size()); -} - // Tests closing all AppWindows. TEST_F(ShellDesktopControllerAuraTest, CloseAppWindows) { + const AppWindowRegistry* app_window_registry = + AppWindowRegistry::Get(browser_context()); scoped_refptr<Extension> extension = test_util::CreateEmptyExtension(); - CreateAppWindow(extension.get()); - CreateAppWindow(extension.get()); - CreateAppWindow(extension.get()); - - aura::Window* root_window = controller_->host()->window(); - EXPECT_EQ(3u, root_window->children().size()); + for (int i = 0; i < 3; i++) { + InitAppWindow( + controller_->CreateAppWindow(browser_context(), extension.get())); + } + EXPECT_EQ(3u, app_window_registry->app_windows().size()); controller_->CloseAppWindows(); - EXPECT_EQ(0u, root_window->children().size()); + EXPECT_EQ(0u, app_window_registry->app_windows().size()); +} + +// Tests that the AppWindows are removed when the desktop controller goes away. +TEST_F(ShellDesktopControllerAuraTest, OnAppWindowClose) { + const AppWindowRegistry* app_window_registry = + AppWindowRegistry::Get(browser_context()); + scoped_refptr<Extension> extension = test_util::CreateEmptyExtension(); + for (int i = 0; i < 3; i++) { + InitAppWindow( + controller_->CreateAppWindow(browser_context(), extension.get())); + } + EXPECT_EQ(3u, app_window_registry->app_windows().size()); + + // Deleting the controller closes all app windows. + controller_.reset(); + EXPECT_EQ(0u, app_window_registry->app_windows().size()); } } // namespace extensions
diff --git a/extensions/shell/browser/shell_extensions_api_client.cc b/extensions/shell/browser/shell_extensions_api_client.cc index d1fa28e..2471ef4 100644 --- a/extensions/shell/browser/shell_extensions_api_client.cc +++ b/extensions/shell/browser/shell_extensions_api_client.cc
@@ -51,4 +51,10 @@ return messaging_delegate_.get(); } +FeedbackPrivateDelegate* +ShellExtensionsAPIClient::GetFeedbackPrivateDelegate() { + NOTIMPLEMENTED(); + return nullptr; +} + } // namespace extensions
diff --git a/extensions/shell/browser/shell_extensions_api_client.h b/extensions/shell/browser/shell_extensions_api_client.h index 9db406fe..66154af 100644 --- a/extensions/shell/browser/shell_extensions_api_client.h +++ b/extensions/shell/browser/shell_extensions_api_client.h
@@ -9,6 +9,7 @@ #include "extensions/browser/api/extensions_api_client.h" +#include "base/macros.h" #include "build/build_config.h" namespace extensions { @@ -31,6 +32,7 @@ FileSystemDelegate* GetFileSystemDelegate() override; #endif MessagingDelegate* GetMessagingDelegate() override; + FeedbackPrivateDelegate* GetFeedbackPrivateDelegate() override; private: #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
diff --git a/extensions/shell/browser/shell_native_app_window.cc b/extensions/shell/browser/shell_native_app_window.cc index 02c137d..676e20a 100644 --- a/extensions/shell/browser/shell_native_app_window.cc +++ b/extensions/shell/browser/shell_native_app_window.cc
@@ -131,7 +131,7 @@ return NULL; } -void ShellNativeAppWindow::UpdateShape(std::unique_ptr<SkRegion> region) { +void ShellNativeAppWindow::UpdateShape(std::unique_ptr<ShapeRects> rects) { NOTIMPLEMENTED(); }
diff --git a/extensions/shell/browser/shell_native_app_window.h b/extensions/shell/browser/shell_native_app_window.h index fcc3f6e..a282a41 100644 --- a/extensions/shell/browser/shell_native_app_window.h +++ b/extensions/shell/browser/shell_native_app_window.h
@@ -52,7 +52,7 @@ void UpdateDraggableRegions( const std::vector<DraggableRegion>& regions) override; SkRegion* GetDraggableRegion() override; - void UpdateShape(std::unique_ptr<SkRegion> region) override; + void UpdateShape(std::unique_ptr<ShapeRects> rects) override; void HandleKeyboardEvent( const content::NativeWebKeyboardEvent& event) override; bool IsFrameless() const override;
diff --git a/extensions/shell/browser/shell_screen.cc b/extensions/shell/browser/shell_screen.cc index 3881f0d0..1be0067c 100644 --- a/extensions/shell/browser/shell_screen.cc +++ b/extensions/shell/browser/shell_screen.cc
@@ -8,9 +8,12 @@ #include <vector> #include "base/logging.h" +#include "extensions/shell/browser/root_window_controller.h" +#include "extensions/shell/browser/shell_desktop_controller_aura.h" #include "ui/aura/env.h" #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" +#include "ui/display/display.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/native_widget_types.h" @@ -22,8 +25,11 @@ } // namespace -ShellScreen::ShellScreen(const gfx::Size& size) : host_(nullptr) { +ShellScreen::ShellScreen(ShellDesktopControllerAura* desktop_controller, + const gfx::Size& size) + : desktop_controller_(desktop_controller) { DCHECK(!size.IsEmpty()); + // Screen is positioned at (0,0). display::Display display(kDisplayId); gfx::Rect bounds(size); @@ -32,38 +38,17 @@ } ShellScreen::~ShellScreen() { - DCHECK(!host_) << "Window not closed before destroying ShellScreen"; + DCHECK(!desktop_controller_ || !desktop_controller_->root_window_controller()) + << "WindowTreeHost not closed before destroying ShellScreen"; } -aura::WindowTreeHost* ShellScreen::CreateHostForPrimaryDisplay() { - DCHECK(!host_); - host_ = aura::WindowTreeHost::Create( - gfx::Rect(GetPrimaryDisplay().GetSizeInPixel())); - host_->window()->AddObserver(this); - host_->InitHost(); - host_->window()->Show(); - return host_; -} - -// aura::WindowObserver overrides: - -void ShellScreen::OnWindowBoundsChanged(aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) { - DCHECK_EQ(host_->window(), window); - display::Display display(GetPrimaryDisplay()); - display.SetSize(new_bounds.size()); +void ShellScreen::OnHostResized(aura::WindowTreeHost* host) { + // Based on ash::WindowTreeHostManager. + display::Display display = GetDisplayNearestWindow(host->window()); + display.SetSize(host->GetBoundsInPixels().size()); display_list().UpdateDisplay(display); } -void ShellScreen::OnWindowDestroying(aura::Window* window) { - DCHECK_EQ(host_->window(), window); - host_->window()->RemoveObserver(this); - host_ = nullptr; -} - -// display::Screen overrides: - gfx::Point ShellScreen::GetCursorScreenPoint() { return aura::Env::GetInstance()->last_mouse_location(); } @@ -73,7 +58,9 @@ } gfx::NativeWindow ShellScreen::GetWindowAtScreenPoint(const gfx::Point& point) { - return host_->window()->GetEventHandlerForPoint(point); + return desktop_controller_->GetPrimaryHost() + ->window() + ->GetEventHandlerForPoint(point); } display::Display ShellScreen::GetDisplayNearestWindow(
diff --git a/extensions/shell/browser/shell_screen.h b/extensions/shell/browser/shell_screen.h index 9746212..6d4cb55 100644 --- a/extensions/shell/browser/shell_screen.h +++ b/extensions/shell/browser/shell_screen.h
@@ -6,7 +6,7 @@ #define EXTENSIONS_SHELL_BROWSER_SHELL_SCREEN_H_ #include "base/macros.h" -#include "ui/aura/window_observer.h" +#include "ui/aura/window_tree_host_observer.h" #include "ui/display/display.h" #include "ui/display/screen_base.h" @@ -19,23 +19,21 @@ } namespace extensions { +class ShellDesktopControllerAura; // A minimal Aura implementation of a screen. Scale factor is locked at 1.0. // When running on a Linux desktop resizing the main window resizes the screen. -class ShellScreen : public display::ScreenBase, public aura::WindowObserver { +class ShellScreen : public display::ScreenBase, + public aura::WindowTreeHostObserver { public: - // Creates a screen occupying |size| physical pixels. - explicit ShellScreen(const gfx::Size& size); + // Creates a screen occupying |size| physical pixels. |desktop_controller| + // can be null in tests. + ShellScreen(ShellDesktopControllerAura* desktop_controller, + const gfx::Size& size); ~ShellScreen() override; - // Caller owns the returned object. - aura::WindowTreeHost* CreateHostForPrimaryDisplay(); - - // WindowObserver overrides: - void OnWindowBoundsChanged(aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) override; - void OnWindowDestroying(aura::Window* window) override; + // aura::WindowTreeHostObserver overrides: + void OnHostResized(aura::WindowTreeHost* host) override; // display::Screen overrides: gfx::Point GetCursorScreenPoint() override; @@ -45,7 +43,7 @@ gfx::NativeWindow window) const override; private: - aura::WindowTreeHost* host_; // Not owned. + ShellDesktopControllerAura* const desktop_controller_; DISALLOW_COPY_AND_ASSIGN(ShellScreen); };
diff --git a/extensions/shell/browser/shell_screen_unittest.cc b/extensions/shell/browser/shell_screen_unittest.cc index 75a5cd16..b3f31bd 100644 --- a/extensions/shell/browser/shell_screen_unittest.cc +++ b/extensions/shell/browser/shell_screen_unittest.cc
@@ -6,8 +6,8 @@ #include <memory> +#include "extensions/shell/test/shell_test_base_aura.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/aura/test/aura_test_base.h" #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" #include "ui/display/display.h" @@ -16,11 +16,11 @@ namespace extensions { -using ShellScreenTest = aura::test::AuraTestBase; +using ShellScreenTest = ShellTestBaseAura; // Basic sanity tests for ShellScreen. TEST_F(ShellScreenTest, ShellScreen) { - ShellScreen screen(gfx::Size(640, 480)); + ShellScreen screen(nullptr, gfx::Size(640, 480)); // There is only one display. EXPECT_EQ(1, screen.GetNumDisplays()); @@ -30,13 +30,16 @@ EXPECT_EQ("640x480", screen.GetPrimaryDisplay().size().ToString()); // Tests that reshaping the host window reshapes the display. - // NOTE: AuraTestBase already has its own WindowTreeHost. This is creating a - // second one. - std::unique_ptr<aura::WindowTreeHost> host( - screen.CreateHostForPrimaryDisplay()); + std::unique_ptr<aura::WindowTreeHost> host(aura::WindowTreeHost::Create( + gfx::Rect(screen.GetPrimaryDisplay().GetSizeInPixel()))); + host->AddObserver(&screen); + host->InitHost(); EXPECT_TRUE(host->window()); - host->window()->SetBounds(gfx::Rect(0, 0, 800, 600)); + + host->SetBoundsInPixels(gfx::Rect(0, 0, 800, 600)); EXPECT_EQ("800x600", screen.GetPrimaryDisplay().size().ToString()); + + host->RemoveObserver(&screen); } } // namespace extensions
diff --git a/extensions/shell/test/shell_test_base_aura.cc b/extensions/shell/test/shell_test_base_aura.cc index 20912c5..74e033a 100644 --- a/extensions/shell/test/shell_test_base_aura.cc +++ b/extensions/shell/test/shell_test_base_aura.cc
@@ -5,9 +5,14 @@ #include "extensions/shell/test/shell_test_base_aura.h" #include "base/memory/ptr_util.h" +#include "content/public/browser/web_contents.h" #include "content/public/test/test_browser_thread_bundle.h" +#include "extensions/browser/app_window/app_window.h" +#include "extensions/browser/app_window/test_app_window_contents.h" +#include "extensions/shell/browser/shell_app_delegate.h" #include "extensions/shell/test/shell_test_extensions_browser_client.h" #include "extensions/shell/test/shell_test_helper_aura.h" +#include "url/gurl.h" namespace extensions { @@ -30,4 +35,25 @@ helper_->TearDown(); } +void ShellTestBaseAura::InitAppWindow(AppWindow* app_window) { + // Create a TestAppWindowContents for the ShellAppDelegate to initialize the + // ShellExtensionWebContentsObserver with. + std::unique_ptr<content::WebContents> web_contents( + content::WebContents::Create( + content::WebContents::CreateParams(browser_context()))); + std::unique_ptr<TestAppWindowContents> app_window_contents = + base::MakeUnique<TestAppWindowContents>(std::move(web_contents)); + + // Initialize the web contents and AppWindow. + app_window->app_delegate()->InitWebContents( + app_window_contents->GetWebContents()); + + content::RenderFrameHost* main_frame = + app_window_contents->GetWebContents()->GetMainFrame(); + DCHECK(main_frame); + + app_window->Init(GURL(), app_window_contents.release(), main_frame, + AppWindow::CreateParams()); +} + } // namespace extensions
diff --git a/extensions/shell/test/shell_test_base_aura.h b/extensions/shell/test/shell_test_base_aura.h index 65d7ef2..5e9d8e6 100644 --- a/extensions/shell/test/shell_test_base_aura.h +++ b/extensions/shell/test/shell_test_base_aura.h
@@ -12,6 +12,7 @@ #include "extensions/browser/extensions_test.h" namespace extensions { +class AppWindow; class ShellTestHelperAura; class ShellTestBaseAura : public ExtensionsTest { @@ -23,6 +24,9 @@ void SetUp() override; void TearDown() override; + // Initializes |app_window| for testing. + void InitAppWindow(AppWindow* app_window); + private: std::unique_ptr<ShellTestHelperAura> helper_;
diff --git a/extensions/utility/utility_handler.cc b/extensions/utility/utility_handler.cc index 250330f..320e1fba 100644 --- a/extensions/utility/utility_handler.cc +++ b/extensions/utility/utility_handler.cc
@@ -4,8 +4,14 @@ #include "extensions/utility/utility_handler.h" +#include <memory> +#include <string> +#include <utility> + #include "base/command_line.h" #include "base/files/file_path.h" +#include "base/location.h" +#include "base/task_scheduler/post_task.h" #include "content/public/utility/utility_thread.h" #include "extensions/common/constants.h" #include "extensions/common/extension_l10n_util.h" @@ -27,6 +33,33 @@ namespace { +struct UnpackResult { + std::unique_ptr<base::DictionaryValue> parsed_manifest; + base::string16 error; +}; + +// Unpacks the extension on background task runner. +// On success, returns UnpackResult with |parsed_manifest| set to the parsed +// extension manifest. +// On failure returns UnpackResult with |error| set to the encountered error +// message. +UnpackResult UnpackOnBackgroundTaskRunner(const base::FilePath& path, + const std::string& extension_id, + Manifest::Location location, + int32_t creation_flags) { + Unpacker unpacker(path.DirName(), path, extension_id, location, + creation_flags); + + UnpackResult result; + if (unpacker.Run()) { + result.parsed_manifest = unpacker.TakeParsedManifest(); + } else { + result.error = unpacker.error_message(); + } + + return result; +} + class ExtensionUnpackerImpl : public extensions::mojom::ExtensionUnpacker { public: ExtensionUnpackerImpl() = default; @@ -42,13 +75,19 @@ void Unzip(const base::FilePath& file, const base::FilePath& path, UnzipCallback callback) override { - std::unique_ptr<base::DictionaryValue> manifest; - if (UnzipFileManifestIntoPath(file, path, &manifest)) { - std::move(callback).Run( - UnzipFileIntoPath(file, path, std::move(manifest))); - } else { - std::move(callback).Run(false); - } + // Move unzip operation to background thread to avoid blocking the main + // utility thread for extended amont of time. For example, this prevents + // extension unzipping block receipt of the connection complete + // notification for the utility process channel to the browser process, + // which could cause the utility process to terminate itself due to browser + // process being considered unreachable. + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, + {base::TaskPriority::USER_BLOCKING, base::MayBlock(), + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, + base::BindOnce(&ExtensionUnpackerImpl::UnzipOnBackgroundTaskRunner, + file, path), + std::move(callback)); } void Unpack(version_info::Channel channel, @@ -68,13 +107,20 @@ SetCurrentChannel(channel); SetCurrentFeatureSessionType(type); - Unpacker unpacker(path.DirName(), path, extension_id, location, - creation_flags); - if (unpacker.Run()) { - std::move(callback).Run(base::string16(), unpacker.TakeParsedManifest()); - } else { - std::move(callback).Run(unpacker.error_message(), nullptr); - } + // Move unpack operation to background thread to prevent it from blocking + // the utility process thread for extended amount of time. + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, + {base::TaskPriority::USER_BLOCKING, base::MayBlock(), + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, + base::BindOnce(&UnpackOnBackgroundTaskRunner, path, extension_id, + location, creation_flags), + base::BindOnce( + [](UnpackCallback callback, UnpackResult result) { + std::move(callback).Run(result.error, + std::move(result.parsed_manifest)); + }, + std::move(callback))); } static bool UnzipFileManifestIntoPath( @@ -104,6 +150,17 @@ true /* log_skipped_files */); } + // Unzips the extension from |file| to |path|. + // Returns whether the unzip operation succeeded. + static bool UnzipOnBackgroundTaskRunner(const base::FilePath& file, + const base::FilePath& path) { + std::unique_ptr<base::DictionaryValue> manifest; + if (!UnzipFileManifestIntoPath(file, path, &manifest)) + return false; + + return UnzipFileIntoPath(file, path, std::move(manifest)); + } + DISALLOW_COPY_AND_ASSIGN(ExtensionUnpackerImpl); };
diff --git a/headless/BUILD.gn b/headless/BUILD.gn index 91987a4..d2a644d 100644 --- a/headless/BUILD.gn +++ b/headless/BUILD.gn
@@ -223,7 +223,7 @@ extra_deps = [ ":gen_devtools_client_api" ] } -if (headless_fontconfig_utils) { +if (headless_fontconfig_utils && !is_fuchsia) { static_library("headless_fontconfig_utils") { sources = [ "public/util/fontconfig.cc", @@ -280,8 +280,6 @@ "lib/browser/headless_window_tree_host.h", "lib/headless_content_client.cc", "lib/headless_content_client.h", - "lib/headless_crash_reporter_client.cc", - "lib/headless_crash_reporter_client.h", "public/headless_browser.cc", "public/headless_browser.h", "public/headless_browser_context.h", @@ -323,6 +321,13 @@ "public/util/user_agent.h", ] + if (!is_fuchsia) { + sources += [ + "lib/headless_crash_reporter_client.cc", + "lib/headless_crash_reporter_client.h", + ] + } + sources += generated_devtools_api if (use_aura) { @@ -391,11 +396,14 @@ ] deps += [ - "//components/crash/content/browser", "//components/security_state/content", "//third_party/WebKit/public:blink_headers", ] + if (!is_fuchsia) { + deps += [ "//components/crash/content/browser" ] + } + if (enable_basic_printing) { deps += [ "//components/printing/browser", @@ -404,13 +412,6 @@ } } - if (is_fuchsia) { - sources -= [ - "lib/headless_crash_reporter_client.cc", - "lib/headless_crash_reporter_client.h", - ] - } - if (is_mac) { deps += [ ":mac_helpers" ] } else { @@ -431,7 +432,7 @@ deps += [ "//ui/ozone" ] } - if (headless_fontconfig_utils) { + if (headless_fontconfig_utils && !is_fuchsia) { deps += [ ":headless_fontconfig_utils" ] } @@ -510,7 +511,6 @@ ":headless_renderer", "//base/test:run_all_unittests", "//base/test:test_support", - "//components/crash/content/browser", "//components/security_state/content", "//content/public/app:both", "//content/public/child:child", @@ -519,14 +519,14 @@ "//testing/gtest", ] + if (!is_fuchsia) { + deps += [ "//components/crash/content/browser" ] + } + if (enable_basic_printing) { sources += [ "lib/browser/headless_printing_unittest.cc" ] deps += [ "//components/printing/browser" ] } - - if (is_fuchsia) { - deps -= [ "//components/crash/content/browser" ] - } } if (is_mac) { @@ -655,13 +655,16 @@ deps = [ ":headless_renderer", "//base", - "//components/crash/content/browser", "//components/security_state/content", "//content/test:test_support", "//testing/gmock", "//testing/gtest", ] + if (!is_fuchsia) { + deps += [ "//components/crash/content/browser" ] + } + # Only include this if we built the js_binary if (is_linux) { data += [ "$root_out_dir/headless_browser_tests.pak" ] @@ -675,10 +678,6 @@ "//pdf", ] } - - if (is_fuchsia) { - deps -= [ "//components/crash/content/browser" ] - } } if (is_win) { @@ -774,7 +773,6 @@ deps = [ ":headless_renderer", - "//components/crash/content/browser", "//components/security_state/content", "//content/public/app:both", "//content/public/browser", @@ -782,6 +780,10 @@ "//content/public/common", ] + if (!is_fuchsia) { + deps += [ "//components/crash/content/browser" ] + } + if (enable_basic_printing) { deps += [ "//components/printing/browser", @@ -798,10 +800,6 @@ "//sandbox", ] } - - if (is_fuchsia) { - deps -= [ "//components/crash/content/browser" ] - } } if (is_fuchsia) {
diff --git a/infra/config/cq.cfg b/infra/config/cq.cfg index eec7f9105..70f103d 100644 --- a/infra/config/cq.cfg +++ b/infra/config/cq.cfg
@@ -50,7 +50,7 @@ builders { name: "chromium_presubmit" } builders { name: "fuchsia_compile" - experiment_percentage: 10 + experiment_percentage: 100 } builders { name: "linux_chromium_asan_rel_ng" } builders { name: "linux_chromium_chromeos_rel_ng" }
diff --git a/ios/OWNERS b/ios/OWNERS index a5fae73..839f864 100644 --- a/ios/OWNERS +++ b/ios/OWNERS
@@ -11,3 +11,6 @@ # These are for the common case of adding or renaming files. If you're doing # structural changes, please get a review from a reviewer in this file. per-file BUILD.gn=* + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/build/OWNERS b/ios/build/OWNERS index ae82009..ba9c65db 100644 --- a/ios/build/OWNERS +++ b/ios/build/OWNERS
@@ -1,2 +1,5 @@ rohitrao@chromium.org sdefresne@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/build/bots/OWNERS b/ios/build/bots/OWNERS index 7466a7b..bab98631 100644 --- a/ios/build/bots/OWNERS +++ b/ios/build/bots/OWNERS
@@ -3,3 +3,6 @@ rohitrao@chromium.org sdefresne@chromium.org smut@google.com + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/build/bots/chromium.fyi/ClangToTiOS.json b/ios/build/bots/chromium.fyi/ClangToTiOS.json index 2b5ab01..d8b662f8 100644 --- a/ios/build/bots/chromium.fyi/ClangToTiOS.json +++ b/ios/build/bots/chromium.fyi/ClangToTiOS.json
@@ -8,6 +8,7 @@ "is_component_build=false", "is_debug=false", "llvm_force_head_revision=true", + "additional_target_cpus=[\"arm64\",\"x64\",\"x86\"]", "target_cpu=\"arm\"", "target_os=\"ios\"" ],
diff --git a/ios/build/bots/scripts/OWNERS b/ios/build/bots/scripts/OWNERS index 1faa6041..eacf766 100644 --- a/ios/build/bots/scripts/OWNERS +++ b/ios/build/bots/scripts/OWNERS
@@ -2,3 +2,6 @@ baxley@chromium.org sergeyberezin@chromium.org smut@google.com + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/OWNERS b/ios/chrome/OWNERS index df13981..1a9f1a2 100644 --- a/ios/chrome/OWNERS +++ b/ios/chrome/OWNERS
@@ -12,3 +12,6 @@ per-file ios_share_extension_resources.gyp=* per-file ios_today_extension_resources.gyp=* per-file ios_today_extension_resources_bundle.gypi=* + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/app/BUILD.gn b/ios/chrome/app/BUILD.gn index 567b08f..96ab0ee 100644 --- a/ios/chrome/app/BUILD.gn +++ b/ios/chrome/app/BUILD.gn
@@ -153,6 +153,7 @@ "//components/keyed_service/ios", "//components/metrics", "//components/ntp_snippets", + "//components/payments/core", "//components/prefs", "//components/proxy_config", "//components/signin/core/browser", @@ -189,6 +190,7 @@ "//ios/chrome/browser/net", "//ios/chrome/browser/ntp_snippets", "//ios/chrome/browser/omaha", + "//ios/chrome/browser/payments", "//ios/chrome/browser/prefs", "//ios/chrome/browser/reading_list", "//ios/chrome/browser/search_engines",
diff --git a/ios/chrome/app/DEPS b/ios/chrome/app/DEPS index 522a5e99..e52ccc7 100644 --- a/ios/chrome/app/DEPS +++ b/ios/chrome/app/DEPS
@@ -14,6 +14,7 @@ "+components/history/core/browser", "+components/metrics", "+components/ntp_snippets", + "+components/payments/core", "+components/prefs", "+components/reading_list/core", "+components/signin/core/browser",
diff --git a/ios/chrome/app/OWNERS b/ios/chrome/app/OWNERS index 9e2503a..cb182dd 100644 --- a/ios/chrome/app/OWNERS +++ b/ios/chrome/app/OWNERS
@@ -1,2 +1,5 @@ marq@chromium.org rohitrao@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/app/application_delegate/BUILD.gn b/ios/chrome/app/application_delegate/BUILD.gn index d984b50..6f346ea 100644 --- a/ios/chrome/app/application_delegate/BUILD.gn +++ b/ios/chrome/app/application_delegate/BUILD.gn
@@ -100,6 +100,7 @@ "//components/feature_engagement", "//components/handoff", "//components/metrics", + "//components/payments/core", "//components/prefs", "//ios/chrome/app", "//ios/chrome/app/safe_mode", @@ -114,6 +115,7 @@ "//ios/chrome/browser/metrics", "//ios/chrome/browser/metrics:metrics_internal", "//ios/chrome/browser/net", + "//ios/chrome/browser/payments", "//ios/chrome/browser/tabs", "//ios/chrome/browser/u2f", "//ios/chrome/browser/ui",
diff --git a/ios/chrome/app/application_delegate/OWNERS b/ios/chrome/app/application_delegate/OWNERS index f49ed38..01e8c98 100644 --- a/ios/chrome/app/application_delegate/OWNERS +++ b/ios/chrome/app/application_delegate/OWNERS
@@ -1 +1,4 @@ marq@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/app/application_delegate/app_state.mm b/ios/chrome/app/application_delegate/app_state.mm index 17c365a6..2072d63 100644 --- a/ios/chrome/app/application_delegate/app_state.mm +++ b/ios/chrome/app/application_delegate/app_state.mm
@@ -357,13 +357,18 @@ startupInformation:_startupInformation browserViewInformation:[_browserLauncher browserViewInformation]]; - } else if (_shouldOpenNTPTabOnActive && - ![tabSwitcher openNewTabFromTabSwitcher]) { - BrowserViewController* bvc = - [[_browserLauncher browserViewInformation] currentBVC]; - BOOL incognito = bvc == [[_browserLauncher browserViewInformation] otrBVC]; - [bvc.dispatcher - openNewTab:[OpenNewTabCommand commandWithIncognito:incognito]]; + } else if (_shouldOpenNTPTabOnActive) { + if (![tabSwitcher openNewTabFromTabSwitcher]) { + BrowserViewController* bvc = + [[_browserLauncher browserViewInformation] currentBVC]; + BOOL incognito = + bvc == [[_browserLauncher browserViewInformation] otrBVC]; + [bvc.dispatcher + openNewTab:[OpenNewTabCommand commandWithIncognito:incognito]]; + } + } else { + [[[_browserLauncher browserViewInformation] currentBVC] + presentBubblesIfEligible]; } _shouldOpenNTPTabOnActive = NO;
diff --git a/ios/chrome/app/application_delegate/mock_tab_opener.mm b/ios/chrome/app/application_delegate/mock_tab_opener.mm index e41a08d..ca19a67 100644 --- a/ios/chrome/app/application_delegate/mock_tab_opener.mm +++ b/ios/chrome/app/application_delegate/mock_tab_opener.mm
@@ -50,4 +50,10 @@ return nil; } +- (BOOL)shouldCompletePaymentRequestOnCurrentTab: + (id<StartupInformation>)startupInformation { + // Stub. + return NO; +} + @end
diff --git a/ios/chrome/app/application_delegate/tab_opening.h b/ios/chrome/app/application_delegate/tab_opening.h index ff5ae8d..2d83df9 100644 --- a/ios/chrome/app/application_delegate/tab_opening.h +++ b/ios/chrome/app/application_delegate/tab_opening.h
@@ -41,6 +41,11 @@ - (ProceduralBlock)completionBlockForTriggeringAction: (NTPTabOpeningPostOpeningAction)action; +// Attempts to complete a Payment Request flow with a payment response from a +// a third party app. Returns whether or not this operation was successful. +- (BOOL)shouldCompletePaymentRequestOnCurrentTab: + (id<StartupInformation>)startupInformation; + @end #endif // IOS_CHROME_APP_APPLICATION_DELEGATE_TAB_OPENING_H_
diff --git a/ios/chrome/app/application_delegate/user_activity_handler.mm b/ios/chrome/app/application_delegate/user_activity_handler.mm index 3dcee1f..784ee54 100644 --- a/ios/chrome/app/application_delegate/user_activity_handler.mm +++ b/ios/chrome/app/application_delegate/user_activity_handler.mm
@@ -17,6 +17,7 @@ #import "ios/chrome/app/application_delegate/startup_information.h" #import "ios/chrome/app/application_delegate/tab_opening.h" #include "ios/chrome/app/application_mode.h" +#include "ios/chrome/app/chrome_app_startup_parameters.h" #import "ios/chrome/app/spotlight/actions_spotlight_manager.h" #import "ios/chrome/app/spotlight/spotlight_util.h" #include "ios/chrome/browser/app_startup_parameters.h" @@ -42,6 +43,7 @@ NSString* const kShortcutNewIncognitoTab = @"OpenIncognitoTab"; NSString* const kShortcutVoiceSearch = @"OpenVoiceSearch"; NSString* const kShortcutQRScanner = @"OpenQRScanner"; + } // namespace @interface UserActivityHandler () @@ -73,15 +75,21 @@ handoff::ORIGIN_COUNT); } else if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) { - // App was launched as the result of a Universal Link navigation. The value - // of userActivity.webpageURL is not used. The only supported action - // at this time is opening a New Tab Page. - GURL newTabURL(kChromeUINewTabURL); - webpageURL = net::NSURLWithGURL(newTabURL); + // App was launched as the result of a Universal Link navigation. + GURL gurl = net::GURLWithNSURL(webpageURL); AppStartupParameters* startupParams = - [[AppStartupParameters alloc] initWithExternalURL:newTabURL]; + [[AppStartupParameters alloc] initWithUniversalLink:gurl]; [startupInformation setStartupParameters:startupParams]; base::RecordAction(base::UserMetricsAction("IOSLaunchedByUniversalLink")); + + if (startupParams) + webpageURL = net::NSURLWithGURL([startupParams externalURL]); + + // Don't call continueUserActivityURL if the completePaymentRequest flag + // is set since the startup parameters need to be handled in + // -handleStartupParametersWithTabOpener: + if (startupParams && startupParams.completePaymentRequest) + return YES; } else if (spotlight::IsSpotlightAvailable() && [userActivity.activityType isEqualToString:CSSearchableItemActionType]) { @@ -226,6 +234,13 @@ // synchronously. [startupInformation setStartupParameters:nil]; } else { + // Depending on the startup parameters the user may need to stay on the + // current tab rather than open a new one in order to complete a Payment + // Request. This attempts to complete any Payment Request instances on + // the current tab, and returns if successful. + if ([tabOpener shouldCompletePaymentRequestOnCurrentTab:startupInformation]) + return; + // The app is already active so the applicationDidBecomeActive: method // will never be called. Open the requested URL after all modal UIs have // been dismissed. |_startupParameters| must be retained until all deferred
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index 546e267..5c080ae2 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -13,6 +13,7 @@ #include "base/bind.h" #include "base/callback_helpers.h" +#include "base/feature_list.h" #include "base/files/file_path.h" #include "base/ios/block_types.h" #import "base/mac/bind_objc_block.h" @@ -29,6 +30,7 @@ #include "components/feature_engagement/public/tracker.h" #include "components/metrics/metrics_pref_names.h" #include "components/metrics/metrics_service.h" +#include "components/payments/core/features.h" #include "components/prefs/pref_change_registrar.h" #include "components/signin/core/browser/signin_manager.h" #include "components/url_formatter/url_formatter.h" @@ -83,6 +85,8 @@ #import "ios/chrome/browser/metrics/previous_session_info.h" #import "ios/chrome/browser/net/cookie_util.h" #include "ios/chrome/browser/net/crl_set_fetcher.h" +#include "ios/chrome/browser/payments/ios_payment_instrument_launcher.h" +#include "ios/chrome/browser/payments/ios_payment_instrument_launcher_factory.h" #include "ios/chrome/browser/pref_names.h" #include "ios/chrome/browser/prefs/pref_observer_bridge.h" #import "ios/chrome/browser/reading_list/reading_list_download_service.h" @@ -141,6 +145,7 @@ #include "ios/web/net/request_tracker_impl.h" #include "ios/web/net/web_http_protocol_handler_delegate.h" #import "ios/web/public/navigation_manager.h" +#include "ios/web/public/payments/payment_request.h" #include "ios/web/public/web_capabilities.h" #include "ios/web/public/web_state/web_state.h" #import "ios/web/public/web_view_creation_util.h" @@ -2375,6 +2380,40 @@ } } +- (BOOL)shouldCompletePaymentRequestOnCurrentTab: + (id<StartupInformation>)startupInformation { + if (!startupInformation.startupParameters) + return NO; + + if (!startupInformation.startupParameters.completePaymentRequest) + return NO; + + if (!base::FeatureList::IsEnabled(payments::features::kWebPaymentsNativeApps)) + return NO; + + payments::IOSPaymentInstrumentLauncher* paymentAppLauncher = + payments::IOSPaymentInstrumentLauncherFactory::GetInstance() + ->GetForBrowserState(_mainBrowserState); + + if (!paymentAppLauncher->delegate()) + return NO; + + std::string payment_id = + startupInformation.startupParameters.externalURLParams + .find(web::kPaymentRequestIDExternal) + ->second; + if (paymentAppLauncher->payment_request_id() != payment_id) + return NO; + + std::string payment_response = + startupInformation.startupParameters.externalURLParams + .find(web::kPaymentRequestDataExternal) + ->second; + paymentAppLauncher->ReceiveResponseFromIOSPaymentInstrument(payment_response); + [startupInformation setStartupParameters:nil]; + return YES; +} + #pragma mark - SettingsNavigationControllerDelegate - (void)closeSettings {
diff --git a/ios/chrome/app/spotlight/OWNERS b/ios/chrome/app/spotlight/OWNERS index 3ebff38d..56360bb 100644 --- a/ios/chrome/app/spotlight/OWNERS +++ b/ios/chrome/app/spotlight/OWNERS
@@ -1 +1,4 @@ olivierrobin@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/app/strings/OWNERS b/ios/chrome/app/strings/OWNERS index 69a98a6..8c38e91 100644 --- a/ios/chrome/app/strings/OWNERS +++ b/ios/chrome/app/strings/OWNERS
@@ -1,2 +1,5 @@ per-file *.grd=* per-file *.xtb=* + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index eb48d60..439ffa0 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -737,6 +737,9 @@ <message name="IDS_IOS_NET_EXPORT_NO_EMAIL_ACCOUNTS_ALERT_TITLE" desc="The title of the alert informing a user with no email accounts that they need to configure an email account to send net-export data. [Length: 20em]"> No Email Accounts </message> + <message name="IDS_IOS_NEW_INCOGNITO_TAB_IPH_PROMOTION_TEXT" desc="Text for the New Incognito Tab Tip in-product help promotion, explaining that incognito tabs can be used to browse privately. [iOS only]" meaning="The user has never created an incognito tab before. A bubble is displayed pointing to the tools menu button and informing users about how to use incognito mode."> + To browse privately, open an incognito tab + </message> <message name="IDS_IOS_NEW_TAB_BOOKMARKS_PAGE_TITLE_MOBILE" desc="The 'Bookmarks' title on the new tab page [Length: 10em]"> Bookmarks </message>
diff --git a/ios/chrome/app/theme/OWNERS b/ios/chrome/app/theme/OWNERS index 40a68c7..b127701 100644 --- a/ios/chrome/app/theme/OWNERS +++ b/ios/chrome/app/theme/OWNERS
@@ -1 +1,4 @@ rohitrao@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn index 6fefea52..397f9e28 100644 --- a/ios/chrome/browser/BUILD.gn +++ b/ios/chrome/browser/BUILD.gn
@@ -217,6 +217,7 @@ configs += [ "//build/config/compiler:enable_arc" ] testonly = true sources = [ + "app_startup_parameters_unittest.mm", "callback_counter_unittest.mm", "chrome_browser_provider_observer_bridge_unittest.mm", "chrome_url_util_unittest.mm",
diff --git a/ios/chrome/browser/OWNERS b/ios/chrome/browser/OWNERS index def1e2a..0adc841 100644 --- a/ios/chrome/browser/OWNERS +++ b/ios/chrome/browser/OWNERS
@@ -4,3 +4,6 @@ per-file ios_chrome_io_thread*=rsleevi@chromium.org per-file ios_chrome_flag_descriptions.*=* + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/app_startup_parameters.h b/ios/chrome/browser/app_startup_parameters.h index 547a79ea..165fdef4 100644 --- a/ios/chrome/browser/app_startup_parameters.h +++ b/ios/chrome/browser/app_startup_parameters.h
@@ -7,6 +7,8 @@ #import <Foundation/Foundation.h> +#include <map> + enum NTPTabOpeningPostOpeningAction { // No action should be done NO_ACTION = 0, @@ -22,9 +24,18 @@ // of launch from another app. @interface AppStartupParameters : NSObject -// The URL received that should be opened. +// The URL that should be opened. This may not always be the same URL as the one +// that was receieved. The reason for this is in the case of Universal Link +// navigation where we may want to open up a fallback URL e.g., the New Tab +// Page instead of the actual universal link. @property(nonatomic, readonly, assign) const GURL& externalURL; +// The URL query string parameters in the case that the app was launched as a +// result of Universal Link navigation. The map associates query string +// parameters with their corresponding value. +@property(nonatomic, assign) std::map<std::string, std::string> + externalURLParams; + //// Boolean to track if a voice search is requested at startup. //@property(nonatomic, readwrite, assign) BOOL launchVoiceSearch; // Boolean to track if the app should launch in incognito mode. @@ -35,12 +46,16 @@ //@property(nonatomic, readwrite, assign) BOOL launchQRScanner; @property(nonatomic, readwrite, assign) NTPTabOpeningPostOpeningAction postOpeningAction; +// Boolean to track if a Payment Request response is requested at startup. +@property(nonatomic, readwrite, assign) BOOL completePaymentRequest; - (instancetype)init NS_UNAVAILABLE; - (instancetype)initWithExternalURL:(const GURL&)externalURL NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithUniversalLink:(const GURL&)universalLink; + @end #endif // IOS_CHROME_BROWSER_APP_STARTUP_PARAMETERS_H_
diff --git a/ios/chrome/browser/app_startup_parameters.mm b/ios/chrome/browser/app_startup_parameters.mm index 742ca53..1e20047 100644 --- a/ios/chrome/browser/app_startup_parameters.mm +++ b/ios/chrome/browser/app_startup_parameters.mm
@@ -4,6 +4,11 @@ #import "ios/chrome/browser/app_startup_parameters.h" +#include "base/stl_util.h" +#include "ios/chrome/browser/chrome_url_constants.h" +#include "ios/web/public/payments/payment_request.h" +#import "net/base/mac/url_conversions.h" +#include "net/base/url_util.h" #include "url/gurl.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -14,8 +19,10 @@ GURL _externalURL; } +@synthesize externalURLParams = _externalURLParams; @synthesize postOpeningAction = _postOpeningAction; @synthesize launchInIncognito = _launchInIncognito; +@synthesize completePaymentRequest = _completePaymentRequest; - (const GURL&)externalURL { return _externalURL; @@ -29,6 +36,32 @@ return self; } +- (instancetype)initWithUniversalLink:(const GURL&)universalLink { + // If a new tab with |_externalURL| needs to be opened after the App + // was launched as the result of a Universal Link navigation, the only + // supported possibility at this time is the New Tab Page. + self = [self initWithExternalURL:GURL(kChromeUINewTabURL)]; + + if (self) { + std::map<std::string, std::string> parameters; + net::QueryIterator query_iterator(universalLink); + while (!query_iterator.IsAtEnd()) { + parameters.insert(std::make_pair(query_iterator.GetKey(), + query_iterator.GetUnescapedValue())); + query_iterator.Advance(); + } + + // Currently only Payment Request parameters are supported. + if (base::ContainsKey(parameters, web::kPaymentRequestIDExternal) && + base::ContainsKey(parameters, web::kPaymentRequestDataExternal)) { + _externalURLParams = parameters; + _completePaymentRequest = YES; + } + } + + return self; +} + - (NSString*)description { NSMutableString* description = [NSMutableString stringWithFormat:@"AppStartupParameters: %s", @@ -51,6 +84,10 @@ break; } + if (self.completePaymentRequest) { + [description appendString:@", should complete payment request"]; + } + return description; }
diff --git a/ios/chrome/browser/app_startup_parameters_unittest.mm b/ios/chrome/browser/app_startup_parameters_unittest.mm new file mode 100644 index 0000000..953fe04 --- /dev/null +++ b/ios/chrome/browser/app_startup_parameters_unittest.mm
@@ -0,0 +1,61 @@ +// 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 "ios/chrome/browser/app_startup_parameters.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace { + +struct UniversalLinkDecodeTestCase { + GURL universal_link; + std::map<std::string, std::string> expected_external_url_params; + bool expected_complete_payment_request; +}; + +TEST(AppStartupParameters, QueryParametersPaymentRequest) { + const UniversalLinkDecodeTestCase test_cases[] = { + { + GURL("https://goo.gl/ioschrome/"), {}, false, + }, + { + GURL("https://goo.gl/ioschrome?payment-request-id"), {}, false, + }, + { + GURL("https://goo.gl/ioschrome?payment-request-id=092831-af18l-324" + "&payment-request-data="), + {{"payment-request-id", "092831-af18l-324"}, + {"payment-request-data", ""}}, + true, + }, + { + GURL("https://goo.gl/ioschrome?payment-request-id=092831-af18l-324" + "&payment-request-data=JNLSKFknrlwe80dkzrnLEWR"), + {{"payment-request-id", "092831-af18l-324"}, + {"payment-request-data", "JNLSKFknrlwe80dkzrnLEWR"}}, + true, + }, + { + GURL("https://goo.gl/ioschrome?payment-request-id=092831-af18l-324" + "&payment-request-data=JNLSKFknrlwe80dkzrnLEWR" + "&unecessary-parameter=0"), + {{"payment-request-id", "092831-af18l-324"}, + {"payment-request-data", "JNLSKFknrlwe80dkzrnLEWR"}, + {"unecessary-parameter", "0"}}, + true, + }, + }; + + for (size_t i = 0; i < arraysize(test_cases); ++i) { + const UniversalLinkDecodeTestCase& test_case = test_cases[i]; + AppStartupParameters* params = [[AppStartupParameters alloc] + initWithUniversalLink:test_case.universal_link]; + EXPECT_EQ(test_case.expected_external_url_params, params.externalURLParams); + EXPECT_EQ(test_case.expected_complete_payment_request, + params.completePaymentRequest); + } +} + +} // namespace
diff --git a/ios/chrome/browser/autofill/OWNERS b/ios/chrome/browser/autofill/OWNERS index 6a806bd..adccd5d 100644 --- a/ios/chrome/browser/autofill/OWNERS +++ b/ios/chrome/browser/autofill/OWNERS
@@ -1 +1,4 @@ mahmadi@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/browser_state/BUILD.gn b/ios/chrome/browser/browser_state/BUILD.gn index 677e58d..a5b7139e 100644 --- a/ios/chrome/browser/browser_state/BUILD.gn +++ b/ios/chrome/browser/browser_state/BUILD.gn
@@ -105,11 +105,11 @@ "//ios/chrome/browser/sync", "//ios/chrome/browser/sync/glue", "//ios/chrome/browser/translate", + "//ios/chrome/browser/ui/browser_list", "//ios/chrome/browser/undo", "//ios/net", "//ios/public/provider/chrome/browser", "//ios/public/provider/chrome/browser/signin", - "//ios/shared/chrome/browser/ui/browser_list", "//ios/web", "//net", "//net:extras",
diff --git a/ios/chrome/browser/browser_state/OWNERS b/ios/chrome/browser/browser_state/OWNERS index c5cd5cb..39066e1 100644 --- a/ios/chrome/browser/browser_state/OWNERS +++ b/ios/chrome/browser/browser_state/OWNERS
@@ -1 +1,4 @@ sdefresne@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm b/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm index 4f472d4..c91071c 100644 --- a/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm +++ b/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm
@@ -47,9 +47,9 @@ #include "ios/chrome/browser/sync/ios_user_event_service_factory.h" #include "ios/chrome/browser/sync/sync_setup_service_factory.h" #include "ios/chrome/browser/translate/translate_accept_languages_factory.h" +#include "ios/chrome/browser/ui/browser_list/browser_list_session_service_factory.h" #include "ios/chrome/browser/undo/bookmark_undo_service_factory.h" #include "ios/chrome/browser/web_data_service_factory.h" -#include "ios/shared/chrome/browser/ui/browser_list/browser_list_session_service_factory.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support."
diff --git a/ios/chrome/browser/browser_state_metrics/OWNERS b/ios/chrome/browser/browser_state_metrics/OWNERS index eccc04a..62cd9921 100644 --- a/ios/chrome/browser/browser_state_metrics/OWNERS +++ b/ios/chrome/browser/browser_state_metrics/OWNERS
@@ -2,3 +2,6 @@ erg@chromium.org # COMPONENT: UI>Browser>Profiles + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/content_suggestions/OWNERS b/ios/chrome/browser/content_suggestions/OWNERS index 2d35f0a..f192143 100644 --- a/ios/chrome/browser/content_suggestions/OWNERS +++ b/ios/chrome/browser/content_suggestions/OWNERS
@@ -1 +1,4 @@ gambard@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/content_suggestions/content_suggestions_mediator.mm b/ios/chrome/browser/content_suggestions/content_suggestions_mediator.mm index 9391c7d..80e518b 100644 --- a/ios/chrome/browser/content_suggestions/content_suggestions_mediator.mm +++ b/ios/chrome/browser/content_suggestions/content_suggestions_mediator.mm
@@ -196,11 +196,7 @@ if (!self.sectionInformationByCategory[categoryWrapper]) { [self addSectionInformationForCategory:category]; } - if (IsCategoryStatusAvailable( - self.contentService->GetCategoryStatus(category))) { - [sectionsInfo - addObject:self.sectionInformationByCategory[categoryWrapper]]; - } + [sectionsInfo addObject:self.sectionInformationByCategory[categoryWrapper]]; } [sectionsInfo addObject:self.learnMoreSectionInfo]; @@ -344,21 +340,15 @@ (ntp_snippets::ContentSuggestionsService*)suggestionsService category:(ntp_snippets::Category)category statusChangedTo:(ntp_snippets::CategoryStatus)status { - ContentSuggestionsCategoryWrapper* wrapper = - [[ContentSuggestionsCategoryWrapper alloc] initWithCategory:category]; if (!ntp_snippets::IsCategoryStatusInitOrAvailable(status)) { // Remove the category from the UI if it is not available. + ContentSuggestionsCategoryWrapper* wrapper = + [[ContentSuggestionsCategoryWrapper alloc] initWithCategory:category]; ContentSuggestionsSectionInformation* sectionInfo = self.sectionInformationByCategory[wrapper]; [self.dataSink clearSection:sectionInfo]; [self.sectionInformationByCategory removeObjectForKey:wrapper]; - } else { - if (!self.sectionInformationByCategory[wrapper]) { - [self addSectionInformationForCategory:category]; - } - [self.dataSink - dataAvailableForSection:self.sectionInformationByCategory[wrapper]]; } }
diff --git a/ios/chrome/browser/context_menu/OWNERS b/ios/chrome/browser/context_menu/OWNERS index bf1620f..ab525656 100644 --- a/ios/chrome/browser/context_menu/OWNERS +++ b/ios/chrome/browser/context_menu/OWNERS
@@ -1 +1,4 @@ noyau@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/device_sharing/OWNERS b/ios/chrome/browser/device_sharing/OWNERS index 987c0c88..7030015a3 100644 --- a/ios/chrome/browser/device_sharing/OWNERS +++ b/ios/chrome/browser/device_sharing/OWNERS
@@ -1 +1,4 @@ erikchen@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/dom_distiller/OWNERS b/ios/chrome/browser/dom_distiller/OWNERS index bf1620f..ab525656 100644 --- a/ios/chrome/browser/dom_distiller/OWNERS +++ b/ios/chrome/browser/dom_distiller/OWNERS
@@ -1 +1,4 @@ noyau@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/feature_engagement/OWNERS b/ios/chrome/browser/feature_engagement/OWNERS index b5a2453..782b0c3 100644 --- a/ios/chrome/browser/feature_engagement/OWNERS +++ b/ios/chrome/browser/feature_engagement/OWNERS
@@ -1,2 +1,5 @@ edchin@chromium.org gchatz@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/find_in_page/OWNERS b/ios/chrome/browser/find_in_page/OWNERS index 40a68c7..b127701 100644 --- a/ios/chrome/browser/find_in_page/OWNERS +++ b/ios/chrome/browser/find_in_page/OWNERS
@@ -1 +1,4 @@ rohitrao@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/first_run/OWNERS b/ios/chrome/browser/first_run/OWNERS index 4905815..169936c 100644 --- a/ios/chrome/browser/first_run/OWNERS +++ b/ios/chrome/browser/first_run/OWNERS
@@ -2,3 +2,6 @@ msarda@chromium.org # COMPONENT: UI>Browser>FirstRun + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/history/OWNERS b/ios/chrome/browser/history/OWNERS index 1085212..1c26985 100644 --- a/ios/chrome/browser/history/OWNERS +++ b/ios/chrome/browser/history/OWNERS
@@ -1,2 +1,5 @@ lpromero@chromium.org sczs@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/infobars/OWNERS b/ios/chrome/browser/infobars/OWNERS index d2e1add..c85e66a 100644 --- a/ios/chrome/browser/infobars/OWNERS +++ b/ios/chrome/browser/infobars/OWNERS
@@ -1 +1,4 @@ jif@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/invalidation/OWNERS b/ios/chrome/browser/invalidation/OWNERS index 7f08e5f..2cdcafd2 100644 --- a/ios/chrome/browser/invalidation/OWNERS +++ b/ios/chrome/browser/invalidation/OWNERS
@@ -3,3 +3,6 @@ pavely@chromium.org # COMPONENT: Services>Invalidation + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/itunes_links/OWNERS b/ios/chrome/browser/itunes_links/OWNERS index d2e1add..c85e66a 100644 --- a/ios/chrome/browser/itunes_links/OWNERS +++ b/ios/chrome/browser/itunes_links/OWNERS
@@ -1 +1,4 @@ jif@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/language/OWNERS b/ios/chrome/browser/language/OWNERS index f1e82d5..bc263cd 100644 --- a/ios/chrome/browser/language/OWNERS +++ b/ios/chrome/browser/language/OWNERS
@@ -1 +1,4 @@ file://components/language/OWNERS + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/metrics/OWNERS b/ios/chrome/browser/metrics/OWNERS index 17a1cc1..e2a5d55 100644 --- a/ios/chrome/browser/metrics/OWNERS +++ b/ios/chrome/browser/metrics/OWNERS
@@ -1,2 +1,5 @@ lpromero@chromium.org olivierrobin@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/net/OWNERS b/ios/chrome/browser/net/OWNERS index ed94051..22d5a1c 100644 --- a/ios/chrome/browser/net/OWNERS +++ b/ios/chrome/browser/net/OWNERS
@@ -1 +1,4 @@ droger@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ntp_snippets/OWNERS b/ios/chrome/browser/ntp_snippets/OWNERS index 7f58514..94af0b0 100644 --- a/ios/chrome/browser/ntp_snippets/OWNERS +++ b/ios/chrome/browser/ntp_snippets/OWNERS
@@ -1,2 +1,5 @@ noyau@chromium.org gambard@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ntp_tiles/OWNERS b/ios/chrome/browser/ntp_tiles/OWNERS index b622730..96f8a26 100644 --- a/ios/chrome/browser/ntp_tiles/OWNERS +++ b/ios/chrome/browser/ntp_tiles/OWNERS
@@ -1,2 +1,5 @@ sfiera@chromium.org file://components/ntp_tiles/OWNERS + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/omaha/OWNERS b/ios/chrome/browser/omaha/OWNERS index 40a68c7..b127701 100644 --- a/ios/chrome/browser/omaha/OWNERS +++ b/ios/chrome/browser/omaha/OWNERS
@@ -1 +1,4 @@ rohitrao@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/passwords/OWNERS b/ios/chrome/browser/passwords/OWNERS index adc8d4b..83fe1582 100644 --- a/ios/chrome/browser/passwords/OWNERS +++ b/ios/chrome/browser/passwords/OWNERS
@@ -1,3 +1,6 @@ melandory@chromium.org vabr@chromium.org vasilii@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/payments/BUILD.gn b/ios/chrome/browser/payments/BUILD.gn index 5463f9a..84f2e85 100644 --- a/ios/chrome/browser/payments/BUILD.gn +++ b/ios/chrome/browser/payments/BUILD.gn
@@ -13,6 +13,10 @@ "ios_payment_instrument.mm", "ios_payment_instrument_finder.h", "ios_payment_instrument_finder.mm", + "ios_payment_instrument_launcher.h", + "ios_payment_instrument_launcher.mm", + "ios_payment_instrument_launcher_factory.h", + "ios_payment_instrument_launcher_factory.mm", "ios_payment_request_cache_factory.h", "ios_payment_request_cache_factory.mm", "origin_security_checker.h", @@ -53,6 +57,7 @@ testonly = true sources = [ "ios_payment_instrument_finder_unittest.mm", + "ios_payment_instrument_launcher_unittest.mm", "payment_request_unittest.mm", "payment_response_helper_unittest.mm", ]
diff --git a/ios/chrome/browser/payments/OWNERS b/ios/chrome/browser/payments/OWNERS index 4cfb56d..2a262cc2 100644 --- a/ios/chrome/browser/payments/OWNERS +++ b/ios/chrome/browser/payments/OWNERS
@@ -1,2 +1,5 @@ lpromero@chromium.org mahmadi@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/payments/ios_payment_instrument.h b/ios/chrome/browser/payments/ios_payment_instrument.h index 417e49d0..7adde13 100644 --- a/ios/chrome/browser/payments/ios_payment_instrument.h +++ b/ios/chrome/browser/payments/ios_payment_instrument.h
@@ -15,6 +15,7 @@ #include "base/strings/string16.h" #include "components/payments/core/payment_instrument.h" #include "ios/chrome/browser/payments/payment_request.h" +#include "url/gurl.h" @class PaymentRequestUIDelegate; @@ -40,7 +41,7 @@ // the native payment app from Chrome. IOSPaymentInstrument( const std::string& method_name, - const std::string& universal_link, + const GURL& universal_link, const std::string& app_name, UIImage* icon_image, id<PaymentRequestUIDelegate> payment_request_ui_delegate); @@ -69,7 +70,7 @@ private: std::string method_name_; - std::string universal_link_; + GURL universal_link_; std::string app_name_; base::scoped_nsobject<UIImage> icon_image_;
diff --git a/ios/chrome/browser/payments/ios_payment_instrument.mm b/ios/chrome/browser/payments/ios_payment_instrument.mm index 29522f6..fa19e48 100644 --- a/ios/chrome/browser/payments/ios_payment_instrument.mm +++ b/ios/chrome/browser/payments/ios_payment_instrument.mm
@@ -5,7 +5,6 @@ #include "ios/chrome/browser/payments/ios_payment_instrument.h" #include "base/strings/utf_string_conversions.h" -#include "url/gurl.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -32,7 +31,7 @@ IOSPaymentInstrument::IOSPaymentInstrument( const std::string& method_name, - const std::string& universal_link, + const GURL& universal_link, const std::string& app_name, UIImage* icon_image, id<PaymentRequestUIDelegate> payment_request_ui_delegate)
diff --git a/ios/chrome/browser/payments/ios_payment_instrument_finder.mm b/ios/chrome/browser/payments/ios_payment_instrument_finder.mm index ad9cf41..6578fba67 100644 --- a/ios/chrome/browser/payments/ios_payment_instrument_finder.mm +++ b/ios/chrome/browser/payments/ios_payment_instrument_finder.mm
@@ -343,8 +343,8 @@ UIImage* icon = [UIImage imageWithData:data scale:[UIScreen mainScreen].scale]; instruments_found_.push_back(base::MakeUnique<IOSPaymentInstrument>( - local_method_name.spec(), local_universal_link.spec(), - local_app_name, icon, payment_request_ui_delegate_)); + local_method_name.spec(), local_universal_link, local_app_name, + icon, payment_request_ui_delegate_)); } OnPaymentInstrumentProcessed(); };
diff --git a/ios/chrome/browser/payments/ios_payment_instrument_launcher.h b/ios/chrome/browser/payments/ios_payment_instrument_launcher.h new file mode 100644 index 0000000..bab3a95 --- /dev/null +++ b/ios/chrome/browser/payments/ios_payment_instrument_launcher.h
@@ -0,0 +1,111 @@ +// 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 IOS_CHROME_BROWSER_PAYMENTS_IOS_PAYMENT_INSTRUMENT_LAUNCHER_H_ +#define IOS_CHROME_BROWSER_PAYMENTS_IOS_PAYMENT_INSTRUMENT_LAUNCHER_H_ + +#include "components/keyed_service/core/keyed_service.h" +#include "ios/chrome/browser/payments/payment_request.h" + +namespace base { +class DictionaryValue; +} // namespace base + +namespace web { +class NavigationItem; +} // namespace web + +namespace payments { + +// Launches a native iOS third party payment app and handles the response +// returned from that payment app. Only one instance of this object can exist +// per browser state. This launcher can only handle one request at a time, +// so any calls this class while another request is processing will fail and +// will cause the in-flight request to fail. +class IOSPaymentInstrumentLauncher : public KeyedService { + public: + IOSPaymentInstrumentLauncher(); + ~IOSPaymentInstrumentLauncher() override; + + // Attempts to launch a third party iOS payment app. Uses |payment_request| + // and |acitive_web_state| to build numerous parameters that get seraliazed + // into a JSON string and then encoded into base-64. |universal_link| is then + // invoked with the built parameters passed in as a query string. If the class + // fails to open the universal link the error callback of |delegate| will + // be invoked. If the class is successful in opening the universal link + // the success callback will be invoked when the payment app calls back into + // Chrome with a payment response. Finally, the class returns a boolean + // indicating if it made an attempt to launch the IOSPaymentInstrument. The + // only instance when the launcher will not attempt a launch is when there is + // another in-flight request already happening. + bool LaunchIOSPaymentInstrument( + payments::PaymentRequest* payment_request, + web::WebState* active_web_state, + GURL& universal_link, + payments::PaymentInstrument::Delegate* delegate); + + // Callback for when an iOS payment app sends a response back to Chrome. + // |response| is a base-64 encodeded string. When decoded, |response| is + // is expected to contain the method name of the payment instrument used, + // whether or not the payment app was able to successfully complete its part + // of the transaction, and details that contain information for the merchant + // website to complete the transaction. The details are only parsed if + // the payment app claims to have successfully completed its part of the + // transaction. + void ReceiveResponseFromIOSPaymentInstrument( + const std::string& base_64_response); + + // Before invoking ReceieveResponseFromIOSPaymentInstrument, callers can + // use delegate() to ensure that the delegate property is valid. + payments::PaymentInstrument::Delegate* delegate() { return delegate_; } + + // Sets the delegate for the current IOSPaymentInstrumentLauncher request. + void set_delegate(payments::PaymentInstrument::Delegate* delegate) { + delegate_ = delegate; + } + + // The payment request ID is exposed in order validate responses from + // third party payment apps. + std::string payment_request_id() { return payment_request_id_; } + + private: + friend class IOSPaymentInstrumentLauncherTest; + + // Returns the JSON-serialized dictionary from each method name the merchant + // requested to the corresponding method data. |stringified_method_data| is + // a mapping of the payment method names to the corresponding JSON-stringified + // payment method specific data. This function converts that map into a JSON + // readable object. + std::unique_ptr<base::DictionaryValue> SerializeMethodData( + const std::map<std::string, std::set<std::string>>& + stringified_method_data); + + // Returns the JSON-serialized top-level certificate chain of the browsing + // context. |item| has information on the browsing state, including the + // SSL certificate needed to build the certificate chain. + std::unique_ptr<base::ListValue> SerializeCertificateChain( + web::NavigationItem* item); + + // Returns the JSON-serialized array of web::PaymentDetailsModifier objects. + // |details| is the object that represents the details of a PaymentRequest + // object and contains the vector of web::PaymentDetailsModifier objects to + // serialize. + std::unique_ptr<base::ListValue> SerializeModifiers( + web::PaymentDetails details); + + // Invokes the payment instrument delegate with the appropriate function. + // If |method_name| or |details| are empty then |delegate_| calls + // OnInstrumentDetailsError, otherwise |delegate_| calls + // OnInstrumentDetailsReady. After invoking the delegate function this method + // will also reset |delegate_| and |payment_request_id_|. + void CompleteLaunchRequest(const std::string& method_name, + const std::string& details); + + payments::PaymentInstrument::Delegate* delegate_; + std::string payment_request_id_; +}; + +} // namespace payments + +#endif // IOS_CHROME_BROWSER_PAYMENTS_IOS_PAYMENT_INSTRUMENT_LAUNCHER_H_
diff --git a/ios/chrome/browser/payments/ios_payment_instrument_launcher.mm b/ios/chrome/browser/payments/ios_payment_instrument_launcher.mm new file mode 100644 index 0000000..ea3bd41 --- /dev/null +++ b/ios/chrome/browser/payments/ios_payment_instrument_launcher.mm
@@ -0,0 +1,268 @@ +// 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. + +#import "ios/chrome/browser/payments/ios_payment_instrument_launcher.h" + +#include <map> + +#include "base/base64.h" +#include "base/ios/ios_util.h" +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/memory/ptr_util.h" +#include "base/strings/sys_string_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" +#include "components/payments/core/payment_instrument.h" +#include "ios/web/public/navigation_item.h" +#include "ios/web/public/navigation_manager.h" +#include "ios/web/public/payments/payment_request.h" +#include "ios/web/public/ssl_status.h" +#include "ios/web/public/web_state/web_state.h" +#include "net/base/mac/url_conversions.mm" +#include "net/base/url_util.h" +#include "net/cert/x509_certificate.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { + +// Parameters sent to a payment app. +static const char kMethodNames[] = "methodNames"; +static const char kMethodData[] = "methodData"; +static const char kMerchantName[] = "merchantName"; +static const char kTopLevelOrigin[] = "topLevelOrigin"; +static const char kTopLevelCertificateChain[] = "topLevelCertificateChain"; +static const char kCertificate[] = "cert"; +static const char kTotal[] = "total"; +static const char kModifiers[] = "modifiers"; + +// Parameters received from a payment app. +static const char kSuccess[] = "success"; +static const char kMethodName[] = "methodName"; +static const char kDetails[] = "details"; + +} // namespace + +namespace payments { + +IOSPaymentInstrumentLauncher::IOSPaymentInstrumentLauncher() + : delegate_(nullptr), payment_request_id_("") {} + +IOSPaymentInstrumentLauncher::~IOSPaymentInstrumentLauncher() {} + +bool IOSPaymentInstrumentLauncher::LaunchIOSPaymentInstrument( + payments::PaymentRequest* payment_request, + web::WebState* active_web_state, + GURL& universal_link, + payments::PaymentInstrument::Delegate* delegate) { + DCHECK(delegate); + + // Only one request can be handled at a time. + if (delegate_ || !payment_request_id_.empty()) { + return false; + } + + delegate_ = delegate; + + std::unique_ptr<base::DictionaryValue> params_to_payment_app = + base::MakeUnique<base::DictionaryValue>(); + + // TODO(crbug.com/748556): Filter the following list to only show method names + // that we know the payment app supports. For now, sending all the requested + // method names i.e., 'basic-card' and 'https://alice-pay.com" to the payment + // app works as the payment app provider can then decide what to do with that + // information, but this is not ideal nor is this consistent with Android + // implementation. + std::unique_ptr<base::ListValue> method_names = + base::MakeUnique<base::ListValue>(); + for (auto const& it : payment_request->stringified_method_data()) + method_names->GetList().emplace_back(it.first); + params_to_payment_app->SetList(kMethodNames, std::move(method_names)); + + params_to_payment_app->SetDictionary( + kMethodData, + SerializeMethodData(payment_request->stringified_method_data())); + + params_to_payment_app->SetString( + kMerchantName, base::UTF16ToASCII(active_web_state->GetTitle())); + + params_to_payment_app->SetKey( + kTopLevelOrigin, + base::Value(active_web_state->GetLastCommittedURL().host())); + + params_to_payment_app->SetList( + kTopLevelCertificateChain, + SerializeCertificateChain( + active_web_state->GetNavigationManager()->GetVisibleItem())); + + params_to_payment_app->SetDictionary( + kTotal, payment_request->web_payment_request() + .details.total.amount.ToDictionaryValue()); + + params_to_payment_app->SetList( + kModifiers, + SerializeModifiers(payment_request->web_payment_request().details)); + + // JSON stringify the object so that it can be encoded in base-64. + std::string stringified_parameters; + base::JSONWriter::Write(*params_to_payment_app, &stringified_parameters); + std::string base_64_params; + base::Base64Encode(stringified_parameters, &base_64_params); + + payment_request_id_ = + payment_request->web_payment_request().payment_request_id; + + universal_link = net::AppendQueryParameter( + universal_link, web::kPaymentRequestIDExternal, payment_request_id_); + universal_link = net::AppendQueryParameter( + universal_link, web::kPaymentRequestDataExternal, base_64_params); + NSURL* url = net::NSURLWithGURL(universal_link); + [[UIApplication sharedApplication] + openURL:url + options:(base::ios::IsRunningOnIOS10OrLater() + ? @{ UIApplicationOpenURLOptionUniversalLinksOnly : @YES } + : nil)completionHandler:^(BOOL success) { + if (!success) { + CompleteLaunchRequest("", ""); + } + }]; + + return true; +} + +void IOSPaymentInstrumentLauncher::ReceiveResponseFromIOSPaymentInstrument( + const std::string& base_64_response) { + DCHECK(delegate_); + + std::string stringified_parameters; + base::Base64Decode(base_64_response, &stringified_parameters); + + std::unique_ptr<base::Value> value = + base::JSONReader::Read(stringified_parameters); + if (!value) { + CompleteLaunchRequest("", ""); + return; + } + + std::unique_ptr<base::DictionaryValue> dict = + base::DictionaryValue::From(std::move(value)); + if (!dict) { + CompleteLaunchRequest("", ""); + return; + } + + int success; + if (!dict->GetInteger(kSuccess, &success) || success == 0) { + CompleteLaunchRequest("", ""); + return; + } + + std::string method_name; + if (!dict->GetString(kMethodName, &method_name) || method_name.empty()) { + CompleteLaunchRequest("", ""); + return; + } + + std::string stringified_details; + if (!dict->GetString(kDetails, &stringified_details) || + stringified_details.empty()) { + CompleteLaunchRequest("", ""); + return; + } + + CompleteLaunchRequest(method_name, stringified_details); +} + +std::unique_ptr<base::DictionaryValue> +IOSPaymentInstrumentLauncher::SerializeMethodData( + const std::map<std::string, std::set<std::string>>& + stringified_method_data) { + std::unique_ptr<base::DictionaryValue> method_data = + base::MakeUnique<base::DictionaryValue>(); + + std::unique_ptr<base::ListValue> data_list; + std::unique_ptr<base::Value> data; + for (auto const& map_it : stringified_method_data) { + data_list = base::MakeUnique<base::ListValue>(); + for (auto const& data_it : map_it.second) { + data = base::JSONReader().ReadToValue(data_it); + // We insert the stringified data, not the JSON object and only if the + // corresponding JSON object is valid. + if (data) + data_list->GetList().emplace_back(data_it); + } + + method_data->SetKey(map_it.first, *data_list); + } + + return method_data; +} + +std::unique_ptr<base::ListValue> +IOSPaymentInstrumentLauncher::SerializeCertificateChain( + web::NavigationItem* item) { + std::unique_ptr<base::ListValue> cert_chain_list = + base::MakeUnique<base::ListValue>(); + + if (!item) + return cert_chain_list; + + scoped_refptr<net::X509Certificate> cert = item->GetSSL().certificate; + std::vector<std::vector<const char>> cert_chain; + net::X509Certificate::OSCertHandles cert_handles = + cert->GetIntermediateCertificates(); + if (cert_handles.empty() || cert_handles[0] != cert->os_cert_handle()) + cert_handles.insert(cert_handles.begin(), cert->os_cert_handle()); + + cert_chain.reserve(cert_handles.size()); + for (auto* handle : cert_handles) { + std::string cert_bytes; + net::X509Certificate::GetDEREncoded(handle, &cert_bytes); + cert_chain.push_back( + std::vector<const char>(cert_bytes.begin(), cert_bytes.end())); + } + + std::unique_ptr<base::DictionaryValue> cert_chain_dict; + std::unique_ptr<base::ListValue> byte_array; + for (std::vector<const char> cert_string : cert_chain) { + byte_array = base::MakeUnique<base::ListValue>(); + cert_chain_dict = base::MakeUnique<base::DictionaryValue>(); + for (const char byte : cert_string) + byte_array->GetList().emplace_back(byte); + cert_chain_dict->Set(kCertificate, std::move(byte_array)); + cert_chain_list->GetList().push_back(*cert_chain_dict); + } + + return cert_chain_list; +} + +std::unique_ptr<base::ListValue> +IOSPaymentInstrumentLauncher::SerializeModifiers(web::PaymentDetails details) { + std::unique_ptr<base::ListValue> modifiers = + base::MakeUnique<base::ListValue>(); + size_t numModifiers = details.modifiers.size(); + for (size_t i = 0; i < numModifiers; ++i) { + const std::unique_ptr<base::DictionaryValue> modifier = + details.modifiers[i].ToDictionaryValue(); + modifiers->GetList().push_back(*modifier.get()); + } + + return modifiers; +} + +void IOSPaymentInstrumentLauncher::CompleteLaunchRequest( + const std::string& method_name, + const std::string& details) { + if (!method_name.empty() && !details.empty()) + delegate_->OnInstrumentDetailsReady(method_name, details); + else + delegate_->OnInstrumentDetailsError(); + delegate_ = nullptr; + payment_request_id_ = ""; +} + +} // namespace payments
diff --git a/ios/chrome/browser/payments/ios_payment_instrument_launcher_factory.h b/ios/chrome/browser/payments/ios_payment_instrument_launcher_factory.h new file mode 100644 index 0000000..401a6ce6 --- /dev/null +++ b/ios/chrome/browser/payments/ios_payment_instrument_launcher_factory.h
@@ -0,0 +1,50 @@ +// 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 IOS_CHROME_BROWSER_PAYMENTS_IOS_PAYMENT_INSTRUMENT_LAUNCHER_FACTORY_H_ +#define IOS_CHROME_BROWSER_PAYMENTS_IOS_PAYMENT_INSTRUMENT_LAUNCHER_FACTORY_H_ + +#include <memory> + +#include "base/macros.h" +#include "components/keyed_service/ios/browser_state_keyed_service_factory.h" + +namespace base { +template <typename T> +struct DefaultSingletonTraits; +} // namespace base + +namespace ios { +class ChromeBrowserState; +} // namespace ios + +namespace payments { +class IOSPaymentInstrumentLauncher; + +// Ensures that there's only one instance of +// payments::IOSPaymentInstrumentLauncher per browser state. +class IOSPaymentInstrumentLauncherFactory + : public BrowserStateKeyedServiceFactory { + public: + static IOSPaymentInstrumentLauncher* GetForBrowserState( + ios::ChromeBrowserState* browser_state); + static IOSPaymentInstrumentLauncherFactory* GetInstance(); + + private: + friend struct base::DefaultSingletonTraits< + IOSPaymentInstrumentLauncherFactory>; + + IOSPaymentInstrumentLauncherFactory(); + ~IOSPaymentInstrumentLauncherFactory() override; + + // BrowserStateKeyedServiceFactory implementation. + std::unique_ptr<KeyedService> BuildServiceInstanceFor( + web::BrowserState* context) const override; + + DISALLOW_COPY_AND_ASSIGN(IOSPaymentInstrumentLauncherFactory); +}; + +} // namespace payments + +#endif // IOS_CHROME_BROWSER_PAYMENTS_IOS_PAYMENT_INSTRUMENT_LAUNCHER_FACTORY_H_
diff --git a/ios/chrome/browser/payments/ios_payment_instrument_launcher_factory.mm b/ios/chrome/browser/payments/ios_payment_instrument_launcher_factory.mm new file mode 100644 index 0000000..a4e4ff38 --- /dev/null +++ b/ios/chrome/browser/payments/ios_payment_instrument_launcher_factory.mm
@@ -0,0 +1,43 @@ +// 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 "ios/chrome/browser/payments/ios_payment_instrument_launcher_factory.h" + +#include "base/memory/ptr_util.h" +#include "base/memory/singleton.h" +#include "components/keyed_service/ios/browser_state_dependency_manager.h" +#include "ios/chrome/browser/browser_state/chrome_browser_state.h" +#include "ios/chrome/browser/payments/ios_payment_instrument_launcher.h" +#include "ios/web/public/browser_state.h" + +namespace payments { + +// static +payments::IOSPaymentInstrumentLauncher* +IOSPaymentInstrumentLauncherFactory::GetForBrowserState( + ios::ChromeBrowserState* browser_state) { + return static_cast<payments::IOSPaymentInstrumentLauncher*>( + GetInstance()->GetServiceForBrowserState(browser_state, true)); +} + +// static +IOSPaymentInstrumentLauncherFactory* +IOSPaymentInstrumentLauncherFactory::GetInstance() { + return base::Singleton<IOSPaymentInstrumentLauncherFactory>::get(); +} + +IOSPaymentInstrumentLauncherFactory::IOSPaymentInstrumentLauncherFactory() + : BrowserStateKeyedServiceFactory( + "IOSPaymentInstrumentLauncher", + BrowserStateDependencyManager::GetInstance()) {} + +IOSPaymentInstrumentLauncherFactory::~IOSPaymentInstrumentLauncherFactory() {} + +std::unique_ptr<KeyedService> +IOSPaymentInstrumentLauncherFactory::BuildServiceInstanceFor( + web::BrowserState* context) const { + return base::WrapUnique(new payments::IOSPaymentInstrumentLauncher); +} + +} // namespace payments
diff --git a/ios/chrome/browser/payments/ios_payment_instrument_launcher_unittest.mm b/ios/chrome/browser/payments/ios_payment_instrument_launcher_unittest.mm new file mode 100644 index 0000000..26a33eb --- /dev/null +++ b/ios/chrome/browser/payments/ios_payment_instrument_launcher_unittest.mm
@@ -0,0 +1,330 @@ +// 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 "ios/chrome/browser/payments/ios_payment_instrument_launcher.h" + +#include <map> +#include <memory> + +#include "base/base64.h" +#include "base/ios/ios_util.h" +#include "base/json/json_writer.h" +#include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" +#include "base/values.h" +#include "components/autofill/core/browser/test_personal_data_manager.h" +#include "components/payments/core/payment_instrument.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" +#include "ios/chrome/browser/payments/test_payment_request.h" +#include "ios/web/public/payments/payment_request.h" +#include "ios/web/public/test/fakes/test_navigation_manager.h" +#import "ios/web/public/test/fakes/test_web_state.h" +#include "testing/gtest/include/gtest/gtest.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace payments { + +namespace { + +class FakePaymentInstrumentDelegate : public PaymentInstrument::Delegate { + public: + FakePaymentInstrumentDelegate() {} + + void OnInstrumentDetailsReady( + const std::string& method_name, + const std::string& stringified_details) override { + if (run_loop_) + run_loop_->Quit(); + on_instrument_details_ready_called_ = true; + } + + void OnInstrumentDetailsError() override { + if (run_loop_) + run_loop_->Quit(); + on_instrument_details_error_called_ = true; + } + + bool WasOnInstrumentDetailsReadyCalled() { + return on_instrument_details_ready_called_; + } + + bool WasOnInstrumentDetailsErrorCalled() { + return on_instrument_details_error_called_; + } + + void RunLoop() { + run_loop_.reset(new base::RunLoop()); + run_loop_->Run(); + } + + private: + bool on_instrument_details_ready_called_ = false; + bool on_instrument_details_error_called_ = false; + + std::unique_ptr<base::RunLoop> run_loop_; +}; + +} // namespace + +class IOSPaymentInstrumentLauncherTest : public testing::Test { + protected: + IOSPaymentInstrumentLauncherTest() + : chrome_browser_state_(TestChromeBrowserState::Builder().Build()) {} + + std::unique_ptr<base::DictionaryValue> SerializeMethodDataWrapper( + const std::map<std::string, std::set<std::string>>& + stringified_method_data) { + IOSPaymentInstrumentLauncher launcher; + return launcher.SerializeMethodData(stringified_method_data); + } + + void SetPaymentRequestID(IOSPaymentInstrumentLauncher& launcher) { + launcher.payment_request_id_ = "some-payment-request-id"; + } + + base::test::ScopedTaskEnvironment scoped_task_environment_; + + web::TestWebState web_state_; + std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; +}; + +// Tests that serializing empty stringified method data yields the expected +// result. +TEST_F(IOSPaymentInstrumentLauncherTest, EmptyStringifiedMethodDataDictionary) { + web::PaymentRequest web_payment_request; + autofill::TestPersonalDataManager personal_data_manager; + TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, + &personal_data_manager); + + base::DictionaryValue expected_dict; + + EXPECT_TRUE(expected_dict.Equals( + SerializeMethodDataWrapper(payment_request.stringified_method_data()) + .get())); +} + +// Tests that serializing populated stringified method data yields the expected +// result. +TEST_F(IOSPaymentInstrumentLauncherTest, + PopulatedStringifiedMethodDataDictionary) { + web::PaymentRequest web_payment_request; + PaymentMethodData method_datum1; + method_datum1.supported_methods.push_back("https://jefpay.com"); + method_datum1.supported_methods.push_back("https://bobpay.com"); + std::unique_ptr<base::DictionaryValue> data = + base::MakeUnique<base::DictionaryValue>(); + data->SetString("Some data", "Some stringified data"); + std::string stringified_data; + base::JSONWriter::Write(*data, &stringified_data); + method_datum1.data = stringified_data; + web_payment_request.method_data.push_back(method_datum1); + PaymentMethodData method_datum2; + method_datum2.supported_methods.push_back("https://alicepay.com"); + web_payment_request.method_data.push_back(method_datum2); + PaymentMethodData method_datum3; + method_datum3.supported_methods.push_back("https://jefpay.com"); + web_payment_request.method_data.push_back(method_datum3); + PaymentMethodData method_datum4; + method_datum4.supported_methods.push_back("https://alicepay.com"); + method_datum4.supported_methods.push_back("https://bobpay.com"); + web_payment_request.method_data.push_back(method_datum4); + + autofill::TestPersonalDataManager personal_data_manager; + TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, + &personal_data_manager); + + base::DictionaryValue expected_dict; + std::unique_ptr<base::ListValue> jef_data_list = + base::MakeUnique<base::ListValue>(); + std::unique_ptr<base::DictionaryValue> jef_data = + base::MakeUnique<base::DictionaryValue>(); + jef_data->SetString("Some data", "Some stringified data"); + std::string jef_stringified_data; + base::JSONWriter::Write(*jef_data, &jef_stringified_data); + jef_data_list->GetList().emplace_back(jef_stringified_data); + expected_dict.SetKey("https://jefpay.com", *jef_data_list); + std::unique_ptr<base::ListValue> bob_data_list = + base::MakeUnique<base::ListValue>(); + std::unique_ptr<base::DictionaryValue> bob_data = + base::MakeUnique<base::DictionaryValue>(); + bob_data->SetString("Some data", "Some stringified data"); + std::string bob_stringified_data; + base::JSONWriter::Write(*bob_data, &bob_stringified_data); + bob_data_list->GetList().emplace_back(bob_stringified_data); + expected_dict.SetListWithoutPathExpansion("https://bobpay.com", + std::move(bob_data_list)); + std::unique_ptr<base::ListValue> alice_data_list = + base::MakeUnique<base::ListValue>(); + expected_dict.SetKey("https://alicepay.com", *alice_data_list); + + EXPECT_TRUE(expected_dict.Equals( + SerializeMethodDataWrapper(payment_request.stringified_method_data()) + .get())); +} + +// Tests that attempting to open an invalid universal link calls the +// OnInstrumentDetailsError() function of the delegate. +TEST_F(IOSPaymentInstrumentLauncherTest, + LaunchIOSPaymentInstrument_MalformedUniversalLink) { + if (base::ios::IsRunningOnIOS10OrLater()) { + std::unique_ptr<web::TestNavigationManager> navigation_manager = + base::MakeUnique<web::TestNavigationManager>(); + web_state_.SetNavigationManager(std::move(navigation_manager)); + + web::PaymentRequest web_payment_request; + autofill::TestPersonalDataManager personal_data_manager; + TestPaymentRequest payment_request(web_payment_request, + chrome_browser_state_.get(), &web_state_, + &personal_data_manager); + + FakePaymentInstrumentDelegate instrument_delegate; + IOSPaymentInstrumentLauncher launcher; + + EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsReadyCalled()); + EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsErrorCalled()); + + GURL malformed_link = GURL("http://bad-link.com"); + launcher.LaunchIOSPaymentInstrument(&payment_request, &web_state_, + malformed_link, &instrument_delegate); + instrument_delegate.RunLoop(); + + EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsReadyCalled()); + EXPECT_TRUE(instrument_delegate.WasOnInstrumentDetailsErrorCalled()); + } +} + +// Tests that if the response from the payment app is not a valid JSON +// dictionary then the OnInstrumentDetailsError() function of the delegate +// is called. +TEST_F(IOSPaymentInstrumentLauncherTest, + ReceiveResponseFromIOSPaymentInstrument_ResponseNotDictionary) { + FakePaymentInstrumentDelegate instrument_delegate; + IOSPaymentInstrumentLauncher launcher; + + EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsReadyCalled()); + EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsErrorCalled()); + + std::string stringified_response = "\"JSON\""; + std::string base_64_params; + base::Base64Encode(stringified_response, &base_64_params); + + launcher.set_delegate(&instrument_delegate); + launcher.ReceiveResponseFromIOSPaymentInstrument(base_64_params); + + EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsReadyCalled()); + EXPECT_TRUE(instrument_delegate.WasOnInstrumentDetailsErrorCalled()); +} + +// Tests that if a payment app claims to have not been successful in +// fulfilling its side of the transaction then OnInstrumentDetailsError() +// is called. +TEST_F(IOSPaymentInstrumentLauncherTest, + ReceiveResponseFromIOSPaymentInstrument_PaymentAppFailed) { + FakePaymentInstrumentDelegate instrument_delegate; + IOSPaymentInstrumentLauncher launcher; + + EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsReadyCalled()); + EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsErrorCalled()); + + base::DictionaryValue response; + response.SetInteger("success", 0); + response.SetString("methodName", "visa"); + response.SetString("details", "Some details"); + std::string stringified_response; + base::JSONWriter::Write(response, &stringified_response); + std::string base_64_params; + base::Base64Encode(stringified_response, &base_64_params); + + launcher.set_delegate(&instrument_delegate); + launcher.ReceiveResponseFromIOSPaymentInstrument(base_64_params); + + EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsReadyCalled()); + EXPECT_TRUE(instrument_delegate.WasOnInstrumentDetailsErrorCalled()); +} + +// Tests that if the response from the payment app does not contain a +// method name then OnInstrumentDetailsError() of the delegate is +// called. +TEST_F(IOSPaymentInstrumentLauncherTest, + ReceiveResponseFromIOSPaymentInstrument_NoMethodName) { + FakePaymentInstrumentDelegate instrument_delegate; + IOSPaymentInstrumentLauncher launcher; + + EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsReadyCalled()); + EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsErrorCalled()); + + base::DictionaryValue response; + response.SetInteger("success", 1); + response.SetString("details", "Some details"); + std::string stringified_response; + base::JSONWriter::Write(response, &stringified_response); + std::string base_64_params; + base::Base64Encode(stringified_response, &base_64_params); + + launcher.set_delegate(&instrument_delegate); + launcher.ReceiveResponseFromIOSPaymentInstrument(base_64_params); + + EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsReadyCalled()); + EXPECT_TRUE(instrument_delegate.WasOnInstrumentDetailsErrorCalled()); +} + +// Tests that if the response from the payment app does not contain any +// stringified details then OnInstrumentDetailsError() of the delegate is +// called. +TEST_F(IOSPaymentInstrumentLauncherTest, + ReceiveResponseFromIOSPaymentInstrument_NoDetails) { + FakePaymentInstrumentDelegate instrument_delegate; + IOSPaymentInstrumentLauncher launcher; + + EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsReadyCalled()); + EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsErrorCalled()); + + base::DictionaryValue response; + response.SetInteger("success", 1); + response.SetString("methodName", "visa"); + std::string stringified_response; + base::JSONWriter::Write(response, &stringified_response); + std::string base_64_params; + base::Base64Encode(stringified_response, &base_64_params); + + launcher.set_delegate(&instrument_delegate); + launcher.ReceiveResponseFromIOSPaymentInstrument(base_64_params); + + EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsReadyCalled()); + EXPECT_TRUE(instrument_delegate.WasOnInstrumentDetailsErrorCalled()); +} + +// Tests that if the response from the payment app has all necessary +// parameters with valid values then OnInstrumentDetailsReady() of the +// delegate is called. +TEST_F(IOSPaymentInstrumentLauncherTest, + ReceiveResponseFromIOSPaymentInstrument_WellFormedResponse) { + FakePaymentInstrumentDelegate instrument_delegate; + IOSPaymentInstrumentLauncher launcher; + + EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsReadyCalled()); + EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsErrorCalled()); + + base::DictionaryValue response; + response.SetInteger("success", 1); + response.SetString("methodName", "visa"); + response.SetString("details", "Some details"); + std::string stringified_response; + base::JSONWriter::Write(response, &stringified_response); + std::string base_64_params; + base::Base64Encode(stringified_response, &base_64_params); + + launcher.set_delegate(&instrument_delegate); + launcher.ReceiveResponseFromIOSPaymentInstrument(base_64_params); + + EXPECT_TRUE(instrument_delegate.WasOnInstrumentDetailsReadyCalled()); + EXPECT_FALSE(instrument_delegate.WasOnInstrumentDetailsErrorCalled()); +} + +} // namespace payments
diff --git a/ios/chrome/browser/payments/payment_request.h b/ios/chrome/browser/payments/payment_request.h index 75215f9..42323eac 100644 --- a/ios/chrome/browser/payments/payment_request.h +++ b/ios/chrome/browser/payments/payment_request.h
@@ -63,7 +63,7 @@ // Called when a native iOS payment app should be launched. - (void)paymentInstrument:(payments::IOSPaymentInstrument*)paymentInstrument - launchAppWithUniversalLink:(std::string)universalLink + launchAppWithUniversalLink:(GURL)universalLink instrumentDelegate:(payments::PaymentInstrument::Delegate*)delegate; @end
diff --git a/ios/chrome/browser/payments/payment_response_helper.h b/ios/chrome/browser/payments/payment_response_helper.h index 42d87b4..5434272 100644 --- a/ios/chrome/browser/payments/payment_response_helper.h +++ b/ios/chrome/browser/payments/payment_response_helper.h
@@ -20,6 +20,9 @@ // Called when the payment method details have been successfully received. - (void)paymentResponseHelperDidReceivePaymentMethodDetails; +// Called if an error occured when attempting to receive payment method details. +- (void)paymentResponseHelperDidFailToReceivePaymentMethodDetails; + // Called when the payment method details have been successfully received and // the shipping address and the contact info are normalized, if applicable. - (void)paymentResponseHelperDidCompleteWithPaymentResponse: @@ -44,7 +47,7 @@ void OnInstrumentDetailsReady( const std::string& method_name, const std::string& stringified_details) override; - void OnInstrumentDetailsError() override {} + void OnInstrumentDetailsError() override; private: // Called when the AddressNormalizationManager is done, whether any autofill
diff --git a/ios/chrome/browser/payments/payment_response_helper.mm b/ios/chrome/browser/payments/payment_response_helper.mm index 9535010..4801802 100644 --- a/ios/chrome/browser/payments/payment_response_helper.mm +++ b/ios/chrome/browser/payments/payment_response_helper.mm
@@ -59,6 +59,10 @@ &PaymentResponseHelper::AddressNormalizationCompleted, AsWeakPtr())); } +void PaymentResponseHelper::OnInstrumentDetailsError() { + [consumer_ paymentResponseHelperDidFailToReceivePaymentMethodDetails]; +} + void PaymentResponseHelper::AddressNormalizationCompleted() { web::PaymentResponse response;
diff --git a/ios/chrome/browser/payments/payment_response_helper_unittest.mm b/ios/chrome/browser/payments/payment_response_helper_unittest.mm index 1cc2d814..41eeac4f 100644 --- a/ios/chrome/browser/payments/payment_response_helper_unittest.mm +++ b/ios/chrome/browser/payments/payment_response_helper_unittest.mm
@@ -46,6 +46,9 @@ - (void)paymentResponseHelperDidReceivePaymentMethodDetails { } +- (void)paymentResponseHelperDidFailToReceivePaymentMethodDetails { +} + - (void)paymentResponseHelperDidCompleteWithPaymentResponse: (const web::PaymentResponse&)paymentResponse { return static_cast<
diff --git a/ios/chrome/browser/reading_list/OWNERS b/ios/chrome/browser/reading_list/OWNERS index c6815f7..ccd8b4f 100644 --- a/ios/chrome/browser/reading_list/OWNERS +++ b/ios/chrome/browser/reading_list/OWNERS
@@ -1,2 +1,5 @@ noyau@chromium.org olivierrobin@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/services/OWNERS b/ios/chrome/browser/services/OWNERS index b380428..f0db296d 100644 --- a/ios/chrome/browser/services/OWNERS +++ b/ios/chrome/browser/services/OWNERS
@@ -1,3 +1,6 @@ zea@chromium.org # COMPONENT: Services>CloudMessaging + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/services/gcm/OWNERS b/ios/chrome/browser/services/gcm/OWNERS index 295d996..2271273 100644 --- a/ios/chrome/browser/services/gcm/OWNERS +++ b/ios/chrome/browser/services/gcm/OWNERS
@@ -4,3 +4,6 @@ zea@chromium.org # COMPONENT: Services>CloudMessaging + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/sessions/OWNERS b/ios/chrome/browser/sessions/OWNERS index 40a68c7..b127701 100644 --- a/ios/chrome/browser/sessions/OWNERS +++ b/ios/chrome/browser/sessions/OWNERS
@@ -1 +1,4 @@ rohitrao@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/share_extension/OWNERS b/ios/chrome/browser/share_extension/OWNERS index 4a03091..6a63c2b3 100644 --- a/ios/chrome/browser/share_extension/OWNERS +++ b/ios/chrome/browser/share_extension/OWNERS
@@ -1,2 +1,5 @@ gambard@chromium.org olivierrobin@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/signin/OWNERS b/ios/chrome/browser/signin/OWNERS index bdb69b2..a8f0801c 100644 --- a/ios/chrome/browser/signin/OWNERS +++ b/ios/chrome/browser/signin/OWNERS
@@ -3,3 +3,6 @@ msarda@chromium.org # COMPONENT: Services>SignIn + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/snapshots/OWNERS b/ios/chrome/browser/snapshots/OWNERS index d13827d..f4823b16 100644 --- a/ios/chrome/browser/snapshots/OWNERS +++ b/ios/chrome/browser/snapshots/OWNERS
@@ -1,2 +1,5 @@ jif@chromium.org justincohen@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ssl/OWNERS b/ios/chrome/browser/ssl/OWNERS index 115e3a7..b9da33cc 100644 --- a/ios/chrome/browser/ssl/OWNERS +++ b/ios/chrome/browser/ssl/OWNERS
@@ -2,3 +2,6 @@ felt@chromium.org # COMPONENT: Security>UX + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/store_kit/OWNERS b/ios/chrome/browser/store_kit/OWNERS index d2e1add..c85e66a 100644 --- a/ios/chrome/browser/store_kit/OWNERS +++ b/ios/chrome/browser/store_kit/OWNERS
@@ -1 +1,4 @@ jif@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/suggestions/OWNERS b/ios/chrome/browser/suggestions/OWNERS index 1986f2f0..2c6e9e7 100644 --- a/ios/chrome/browser/suggestions/OWNERS +++ b/ios/chrome/browser/suggestions/OWNERS
@@ -4,3 +4,4 @@ # TEAM: ntp-dev@chromium.org # COMPONENT: UI>Browser>NewTabPage +# OS: iOS
diff --git a/ios/chrome/browser/sync/OWNERS b/ios/chrome/browser/sync/OWNERS index 261ab18..c1575f5 100644 --- a/ios/chrome/browser/sync/OWNERS +++ b/ios/chrome/browser/sync/OWNERS
@@ -1 +1,4 @@ file://components/sync/OWNERS + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/tabs/OWNERS b/ios/chrome/browser/tabs/OWNERS index 40a68c7..b127701 100644 --- a/ios/chrome/browser/tabs/OWNERS +++ b/ios/chrome/browser/tabs/OWNERS
@@ -1 +1,4 @@ rohitrao@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/tabs/tab.mm b/ios/chrome/browser/tabs/tab.mm index 044b7bd..6c12045 100644 --- a/ios/chrome/browser/tabs/tab.mm +++ b/ios/chrome/browser/tabs/tab.mm
@@ -102,6 +102,7 @@ #import "ios/chrome/browser/web/auto_reload_bridge.h" #import "ios/chrome/browser/web/external_app_launcher.h" #import "ios/chrome/browser/web/navigation_manager_util.h" +#import "ios/chrome/browser/web/page_placeholder_tab_helper.h" #import "ios/chrome/browser/web/passkit_dialog_provider.h" #include "ios/chrome/browser/web/print_observer.h" #import "ios/chrome/browser/web/tab_id_tab_helper.h" @@ -231,6 +232,9 @@ // YES if the Tab needs to be reloaded after the app becomes active. BOOL _requireReloadAfterBecomingActive; + // YES if the Tab needs to be reloaded after displaying. + BOOL _requireReloadOnDisplay; + // Last visited timestamp. double _lastVisitedTimestamp; @@ -1227,7 +1231,7 @@ self.navigationManager->Reload(web::ReloadType::NORMAL, false /* check_for_repost */); } else { - [self.webController requirePageReload]; + _requireReloadOnDisplay = YES; } _requireReloadAfterBecomingActive = NO; } @@ -1719,13 +1723,10 @@ if (!applicationIsNotActive) [_fullScreenController disableFullScreen]; } else { - [self.webController requirePageReload]; + _requireReloadOnDisplay = YES; } // Returning to the app (after the renderer crashed in the background) and // having the page reload is much less confusing for the user. - // Note: Given that the tab is visible, calling |requirePageReload| will not - // work when the app becomes active because there is nothing to trigger - // a view redisplay in that scenario. _requireReloadAfterBecomingActive = _visible && applicationIsNotActive; [self.dialogDelegate cancelDialogForTab:self]; } @@ -1813,6 +1814,13 @@ if (self.webState) self.webState->WasShown(); [_inputAccessoryViewController wasShown]; + + if (_requireReloadOnDisplay) { + PagePlaceholderTabHelper::FromWebState(self.webState) + ->AddPlaceholderForNextNavigation(); + [self.webController loadCurrentURL]; + _requireReloadOnDisplay = NO; + } } - (void)wasHidden {
diff --git a/ios/chrome/browser/translate/OWNERS b/ios/chrome/browser/translate/OWNERS index ca1bcb6a..51f79e89 100644 --- a/ios/chrome/browser/translate/OWNERS +++ b/ios/chrome/browser/translate/OWNERS
@@ -1,2 +1,5 @@ file://components/translate/OWNERS droger@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/u2f/OWNERS b/ios/chrome/browser/u2f/OWNERS index ea2dcf4..bd6fe7d6 100644 --- a/ios/chrome/browser/u2f/OWNERS +++ b/ios/chrome/browser/u2f/OWNERS
@@ -1 +1,4 @@ eugenebut@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/OWNERS b/ios/chrome/browser/ui/OWNERS index 7e77d32..1ccf6c3c 100644 --- a/ios/chrome/browser/ui/OWNERS +++ b/ios/chrome/browser/ui/OWNERS
@@ -3,3 +3,6 @@ # like it needs extra review, or is related to the Omnibox. marq@chromium.org rohitrao@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/activity_services/OWNERS b/ios/chrome/browser/ui/activity_services/OWNERS index d2e1add..c85e66a 100644 --- a/ios/chrome/browser/ui/activity_services/OWNERS +++ b/ios/chrome/browser/ui/activity_services/OWNERS
@@ -1 +1,4 @@ jif@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/alert_coordinator/OWNERS b/ios/chrome/browser/ui/alert_coordinator/OWNERS index 0f2892e..8b593c3 100644 --- a/ios/chrome/browser/ui/alert_coordinator/OWNERS +++ b/ios/chrome/browser/ui/alert_coordinator/OWNERS
@@ -1,2 +1,5 @@ gambard@chromium.org michaeldo@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/authentication/BUILD.gn b/ios/chrome/browser/ui/authentication/BUILD.gn index b0e8632..5d7f181 100644 --- a/ios/chrome/browser/ui/authentication/BUILD.gn +++ b/ios/chrome/browser/ui/authentication/BUILD.gn
@@ -188,7 +188,6 @@ "//ios/chrome/browser", "//ios/chrome/browser/signin", "//ios/chrome/browser/ui", - "//ios/chrome/browser/ui/authentication:authentication_ui", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/ntp:ntp_controller", "//ios/chrome/browser/ui/settings",
diff --git a/ios/chrome/browser/ui/authentication/OWNERS b/ios/chrome/browser/ui/authentication/OWNERS index bdb69b2..a8f0801c 100644 --- a/ios/chrome/browser/ui/authentication/OWNERS +++ b/ios/chrome/browser/ui/authentication/OWNERS
@@ -3,3 +3,6 @@ msarda@chromium.org # COMPONENT: Services>SignIn + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/authentication/signin_interaction_controller_egtest.mm b/ios/chrome/browser/ui/authentication/signin_interaction_controller_egtest.mm index a4470ba..64a0a75 100644 --- a/ios/chrome/browser/ui/authentication/signin_interaction_controller_egtest.mm +++ b/ios/chrome/browser/ui/authentication/signin_interaction_controller_egtest.mm
@@ -10,14 +10,9 @@ #include "components/signin/core/browser/signin_manager.h" #include "ios/chrome/browser/experimental_flags.h" #include "ios/chrome/browser/signin/signin_manager_factory.h" -#import "ios/chrome/browser/ui/authentication/signin_promo_view.h" #import "ios/chrome/browser/ui/commands/open_url_command.h" #import "ios/chrome/browser/ui/ntp/new_tab_page_controller.h" -#import "ios/chrome/browser/ui/settings/accounts_collection_view_controller.h" -#import "ios/chrome/browser/ui/settings/import_data_collection_view_controller.h" -#import "ios/chrome/browser/ui/settings/settings_collection_view_controller.h" #include "ios/chrome/browser/ui/tools_menu/tools_menu_constants.h" -#import "ios/chrome/browser/ui/tools_menu/tools_popup_controller.h" #include "ios/chrome/browser/ui/ui_util.h" #include "ios/chrome/grit/ios_strings.h" #import "ios/chrome/test/app/chrome_test_util.h" @@ -63,21 +58,6 @@ forConfigKey:kGREYConfigKeySynchronizationEnabled]; } -// Taps the view with accessibility matcher |accessibility_matcher|. -void TapViewWithMatcher(id<GREYMatcher> accessibility_matcher) { - // grey_sufficientlyVisible() is necessary because reloading a cell in a - // collection view might duplicate it (with the old one being hidden but - // EarlGrey can find it). - id<GREYMatcher> matcher = - grey_allOf(accessibility_matcher, grey_sufficientlyVisible(), nil); - [[EarlGrey selectElementWithMatcher:matcher] performAction:grey_tap()]; -} - -// Taps the view with acessibility identifier |accessibility_id|. -void TapViewWithAccessibilityId(NSString* accessiblity_id) { - TapViewWithMatcher(grey_accessibilityID(accessiblity_id)); -} - // Taps the button with accessibility label |label|. void TapButtonWithAccessibilityLabel(NSString* label) { id<GREYMatcher> matcher = @@ -164,13 +144,16 @@ AssertAuthenticatedIdentityInActiveProfile(identity1); // Open accounts settings, then sync settings. - TapViewWithAccessibilityId(kSettingsAccountCellId); - TapViewWithAccessibilityId(kSettingsAccountsSyncCellId); + [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsAccountButton()] + performAction:grey_tap()]; + [[EarlGrey selectElementWithMatcher:chrome_test_util::AccountsSyncButton()] + performAction:grey_tap()]; // Switch Sync account to |identity2|. TapButtonWithAccessibilityLabel(identity2.userEmail); - - TapViewWithAccessibilityId(kImportDataKeepSeparateCellId); + [[EarlGrey selectElementWithMatcher: + chrome_test_util::SettingsImportDataKeepSeparateButton()] + performAction:grey_tap()]; TapButtonWithLabelId(IDS_IOS_OPTIONS_IMPORT_DATA_CONTINUE_BUTTON); // Check the signed-in user did change. @@ -199,13 +182,16 @@ AssertAuthenticatedIdentityInActiveProfile(identity1); // Open accounts settings, then sync settings. - TapViewWithAccessibilityId(kSettingsAccountCellId); - TapViewWithAccessibilityId(kSettingsAccountsSyncCellId); + [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsAccountButton()] + performAction:grey_tap()]; + [[EarlGrey selectElementWithMatcher:chrome_test_util::AccountsSyncButton()] + performAction:grey_tap()]; // Switch Sync account to |identity2|. TapButtonWithAccessibilityLabel(identity2.userEmail); - - TapViewWithAccessibilityId(kImportDataImportCellId); + [[EarlGrey selectElementWithMatcher:chrome_test_util:: + SettingsImportDataImportButton()] + performAction:grey_tap()]; TapButtonWithLabelId(IDS_IOS_OPTIONS_IMPORT_DATA_CONTINUE_BUTTON); // Check the signed-in user did change. @@ -246,8 +232,11 @@ AssertAuthenticatedIdentityInActiveProfile(managed_identity); // Switch Sync account to |identity|. - TapViewWithAccessibilityId(kSettingsAccountCellId); - TapViewWithAccessibilityId(kSettingsAccountsSyncCellId); + [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsAccountButton()] + performAction:grey_tap()]; + [[EarlGrey selectElementWithMatcher:chrome_test_util::AccountsSyncButton()] + performAction:grey_tap()]; + TapButtonWithAccessibilityLabel(identity.userEmail); SetEarlGreySynchronizationEnabled(NO); @@ -276,16 +265,19 @@ AssertAuthenticatedIdentityInActiveProfile(identity); // Go to Accounts Settings and tap the sign out button. - TapViewWithAccessibilityId(kSettingsAccountCellId); + [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsAccountButton()] + performAction:grey_tap()]; + const CGFloat scroll_displacement = 100.0; - [[[EarlGrey selectElementWithMatcher:grey_accessibilityID( - kSettingsAccountsSignoutCellId)] + [[[EarlGrey + selectElementWithMatcher:grey_allOf( + chrome_test_util::SignOutAccountsButton(), + grey_interactable(), nil)] usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, scroll_displacement) - onElementWithMatcher:grey_accessibilityID(kSettingsAccountsId)] + onElementWithMatcher:chrome_test_util::SettingsAccountsCollectionView()] performAction:grey_tap()]; TapButtonWithLabelId(IDS_IOS_DISCONNECT_DIALOG_CONTINUE_BUTTON_MOBILE); - [[EarlGrey selectElementWithMatcher:NavigationBarDoneButton()] performAction:grey_tap()]; @@ -319,16 +311,19 @@ AssertAuthenticatedIdentityInActiveProfile(identity); // Go to Accounts Settings and tap the sign out button. - TapViewWithAccessibilityId(kSettingsAccountCellId); + [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsAccountButton()] + performAction:grey_tap()]; + const CGFloat scroll_displacement = 100.0; - [[[EarlGrey selectElementWithMatcher:grey_accessibilityID( - kSettingsAccountsSignoutCellId)] + [[[EarlGrey + selectElementWithMatcher:grey_allOf( + chrome_test_util::SignOutAccountsButton(), + grey_interactable(), nil)] usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, scroll_displacement) - onElementWithMatcher:grey_accessibilityID(kSettingsAccountsId)] + onElementWithMatcher:chrome_test_util::SettingsAccountsCollectionView()] performAction:grey_tap()]; TapButtonWithLabelId(IDS_IOS_MANAGED_DISCONNECT_DIALOG_ACCEPT); - [[EarlGrey selectElementWithMatcher:NavigationBarDoneButton()] performAction:grey_tap()]; @@ -463,18 +458,22 @@ AssertAuthenticatedIdentityInActiveProfile(identity2); // Go to Accounts Settings and tap the sign out button. - TapViewWithAccessibilityId(kSettingsAccountCellId); + [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsAccountButton()] + performAction:grey_tap()]; + const CGFloat scroll_displacement = 100.0; - [[[EarlGrey selectElementWithMatcher:grey_accessibilityID( - kSettingsAccountsSignoutCellId)] + [[[EarlGrey + selectElementWithMatcher:grey_allOf( + chrome_test_util::SignOutAccountsButton(), + grey_interactable(), nil)] usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, scroll_displacement) - onElementWithMatcher:grey_accessibilityID(kSettingsAccountsId)] + onElementWithMatcher:chrome_test_util::SettingsAccountsCollectionView()] performAction:grey_tap()]; TapButtonWithLabelId(IDS_IOS_DISCONNECT_DIALOG_CONTINUE_BUTTON_MOBILE); AssertAuthenticatedIdentityInActiveProfile(nil); - - TapViewWithMatcher(chrome_test_util::SignInMenuButton()); + [[EarlGrey selectElementWithMatcher:chrome_test_util::SignInMenuButton()] + performAction:grey_tap()]; [ChromeEarlGreyUI signInToIdentityByEmail:identity1.userEmail]; // Open new tab to cancel sign-in. @@ -514,7 +513,7 @@ selectElementWithMatcher:grey_accessibilityID(kToolsMenuBookmarksId)] usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, scroll_displacement) - onElementWithMatcher:grey_accessibilityID(kToolsMenuTableViewId)] + onElementWithMatcher:chrome_test_util::ToolsMenuView()] performAction:grey_tap()]; if (!IsIPadIdiom()) { @@ -530,8 +529,7 @@ grey_descendant(grey_text(topLevelFolderTitle)), nil); [[EarlGrey selectElementWithMatcher:all_bookmarks_matcher] performAction:grey_tap()]; - - TapViewWithAccessibilityId(kSigninPromoSecondaryButtonId); + TapButtonWithLabelId(IDS_IOS_BOOKMARK_PROMO_SIGN_IN_BUTTON); // Assert sign-in screen was shown. id<GREYMatcher> signin_matcher = @@ -552,7 +550,7 @@ selectElementWithMatcher:grey_accessibilityID(kToolsMenuBookmarksId)] usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, scroll_displacement) - onElementWithMatcher:grey_accessibilityID(kToolsMenuTableViewId)] + onElementWithMatcher:chrome_test_util::ToolsMenuView()] performAction:grey_tap()]; if (!IsIPadIdiom()) { [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Menu")] @@ -560,7 +558,7 @@ } [[EarlGrey selectElementWithMatcher:all_bookmarks_matcher] performAction:grey_tap()]; - TapViewWithAccessibilityId(kSigninPromoSecondaryButtonId); + TapButtonWithLabelId(IDS_IOS_BOOKMARK_PROMO_SIGN_IN_BUTTON); [[EarlGrey selectElementWithMatcher:signin_matcher] assertWithMatcher:grey_sufficientlyVisible()];
diff --git a/ios/chrome/browser/ui/authentication/signin_promo_view.h b/ios/chrome/browser/ui/authentication/signin_promo_view.h index fda056f..d9eaa27 100644 --- a/ios/chrome/browser/ui/authentication/signin_promo_view.h +++ b/ios/chrome/browser/ui/authentication/signin_promo_view.h
@@ -20,11 +20,6 @@ SigninPromoViewModeWarmState, }; -extern NSString* const kSigninPromoViewId; -extern NSString* const kSigninPromoPrimaryButtonId; -extern NSString* const kSigninPromoSecondaryButtonId; -extern NSString* const kSigninPromoCloseButtonId; - // This class creates an image view, a label and 2 buttons. This view can be // configured with 2 modes : "Cold State" and "Warm State". // + "Cold State" mode displays the chomium icon in the image view, and only
diff --git a/ios/chrome/browser/ui/authentication/signin_promo_view.mm b/ios/chrome/browser/ui/authentication/signin_promo_view.mm index b67421d..31bb7b38 100644 --- a/ios/chrome/browser/ui/authentication/signin_promo_view.mm +++ b/ios/chrome/browser/ui/authentication/signin_promo_view.mm
@@ -32,12 +32,6 @@ const CGFloat kButtonHeight = 36; } -NSString* const kSigninPromoViewId = @"kSigninPromoViewId"; -NSString* const kSigninPromoPrimaryButtonId = @"kSigninPromoPrimaryButtonId"; -NSString* const kSigninPromoSecondaryButtonId = - @"kSigninPromoSecondaryButtonId"; -NSString* const kSigninPromoCloseButtonId = @"kSigninPromoCloseButtonId"; - @implementation SigninPromoView { NSArray<NSLayoutConstraint*>* _coldStateConstraints; NSArray<NSLayoutConstraint*>* _warmStateConstraints; @@ -56,7 +50,6 @@ self = [super initWithFrame:frame]; if (self) { self.isAccessibilityElement = YES; - self.accessibilityIdentifier = kSigninPromoViewId; // Adding subviews. self.clipsToBounds = YES; @@ -70,7 +63,7 @@ _primaryButton = [[MDCFlatButton alloc] init]; _primaryButton.translatesAutoresizingMaskIntoConstraints = NO; - _primaryButton.accessibilityIdentifier = kSigninPromoPrimaryButtonId; + _primaryButton.accessibilityIdentifier = @"signin_promo_primary_button"; _primaryButton.titleLabel.lineBreakMode = NSLineBreakByTruncatingTail; [_primaryButton addTarget:self action:@selector(onPrimaryButtonAction:) @@ -79,7 +72,7 @@ _secondaryButton = [[MDCFlatButton alloc] init]; _secondaryButton.translatesAutoresizingMaskIntoConstraints = NO; - _secondaryButton.accessibilityIdentifier = kSigninPromoSecondaryButtonId; + _secondaryButton.accessibilityIdentifier = @"signin_promo_secondary_button"; [_secondaryButton addTarget:self action:@selector(onSecondaryButtonAction:) forControlEvents:UIControlEventTouchUpInside]; @@ -87,7 +80,7 @@ _closeButton = [[UIButton alloc] init]; _closeButton.translatesAutoresizingMaskIntoConstraints = NO; - _closeButton.accessibilityIdentifier = kSigninPromoCloseButtonId; + _closeButton.accessibilityIdentifier = @"signin_promo_close_button"; [self addSubview:_closeButton]; // Adding style.
diff --git a/ios/chrome/browser/ui/autofill/OWNERS b/ios/chrome/browser/ui/autofill/OWNERS index 6a806bd..adccd5d 100644 --- a/ios/chrome/browser/ui/autofill/OWNERS +++ b/ios/chrome/browser/ui/autofill/OWNERS
@@ -1 +1,4 @@ mahmadi@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/bookmarks/BUILD.gn b/ios/chrome/browser/ui/bookmarks/BUILD.gn index 8d4f289..91ce5d6 100644 --- a/ios/chrome/browser/ui/bookmarks/BUILD.gn +++ b/ios/chrome/browser/ui/bookmarks/BUILD.gn
@@ -187,7 +187,6 @@ "//ios/chrome/browser/bookmarks:bookmarks_utils", "//ios/chrome/browser/browser_state", "//ios/chrome/browser/ui", - "//ios/chrome/browser/ui/authentication:authentication_ui", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/toolbar", "//ios/chrome/browser/ui/tools_menu",
diff --git a/ios/chrome/browser/ui/bookmarks/OWNERS b/ios/chrome/browser/ui/bookmarks/OWNERS index 3b99155..f6480c4 100644 --- a/ios/chrome/browser/ui/bookmarks/OWNERS +++ b/ios/chrome/browser/ui/bookmarks/OWNERS
@@ -1,3 +1,6 @@ noyau@chromium.org lpromero@chromium.org ramyasharma@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm index 785d4e4..9fd6d95 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
@@ -18,7 +18,6 @@ #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/experimental_flags.h" #include "ios/chrome/browser/pref_names.h" -#import "ios/chrome/browser/ui/authentication/signin_promo_view.h" #import "ios/chrome/browser/ui/commands/generic_chrome_command.h" #include "ios/chrome/browser/ui/commands/ios_command_ids.h" #import "ios/chrome/browser/ui/toolbar/toolbar_controller.h" @@ -1096,16 +1095,16 @@ }]; // Check that promo is visible. [BookmarksTestCase verifyPromoAlreadySeen:NO]; - [[EarlGrey selectElementWithMatcher:chrome_test_util::SignInPromoView()] - assertWithMatcher:grey_sufficientlyVisible()]; + [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"promo_view")] + assertWithMatcher:grey_notNil()]; // Tap the dismiss button. [[EarlGrey - selectElementWithMatcher:grey_accessibilityID(kSigninPromoCloseButtonId)] + selectElementWithMatcher:grey_accessibilityID(@"promo_no_thanks_button")] performAction:grey_tap()]; // Wait until promo is gone. - [[EarlGrey selectElementWithMatcher:chrome_test_util::SignInPromoView()] + [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"promo_view")] assertWithMatcher:grey_notVisible()]; // Check that the promo already seen state is updated. @@ -1127,16 +1126,12 @@ // Check that promo is visible. [BookmarksTestCase verifyPromoAlreadySeen:NO]; - [[EarlGrey - selectElementWithMatcher:grey_allOf(chrome_test_util::SignInPromoView(), - grey_sufficientlyVisible(), nil)] + [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"promo_view")] assertWithMatcher:grey_notNil()]; // Tap the Sign in button. [[EarlGrey - selectElementWithMatcher:grey_allOf(grey_accessibilityID( - kSigninPromoSecondaryButtonId), - grey_sufficientlyVisible(), nil)] + selectElementWithMatcher:grey_accessibilityID(@"promo_sign_in_button")] performAction:grey_tap()]; // Tap the CANCEL button. @@ -1146,9 +1141,7 @@ uppercaseString])] performAction:grey_tap()]; // Check that the bookmarks UI reappeared and the cell is still here. - [[EarlGrey - selectElementWithMatcher:grey_allOf(chrome_test_util::SignInPromoView(), - grey_sufficientlyVisible(), nil)] + [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"promo_view")] assertWithMatcher:grey_notNil()]; [BookmarksTestCase verifyPromoAlreadySeen:NO];
diff --git a/ios/shared/chrome/browser/ui/browser_list/BUILD.gn b/ios/chrome/browser/ui/browser_list/BUILD.gn similarity index 100% rename from ios/shared/chrome/browser/ui/browser_list/BUILD.gn rename to ios/chrome/browser/ui/browser_list/BUILD.gn
diff --git a/ios/shared/chrome/browser/ui/browser_list/DEPS b/ios/chrome/browser/ui/browser_list/DEPS similarity index 100% rename from ios/shared/chrome/browser/ui/browser_list/DEPS rename to ios/chrome/browser/ui/browser_list/DEPS
diff --git a/ios/shared/chrome/browser/ui/browser_list/browser.h b/ios/chrome/browser/ui/browser_list/browser.h similarity index 87% rename from ios/shared/chrome/browser/ui/browser_list/browser.h rename to ios/chrome/browser/ui/browser_list/browser.h index 213f8d1..665e031 100644 --- a/ios/shared/chrome/browser/ui/browser_list/browser.h +++ b/ios/chrome/browser/ui/browser_list/browser.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_H_ -#define IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_H_ +#ifndef IOS_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_H_ +#define IOS_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_H_ #include <memory> @@ -46,4 +46,4 @@ DISALLOW_COPY_AND_ASSIGN(Browser); }; -#endif // IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_H_ +#endif // IOS_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_H_
diff --git a/ios/shared/chrome/browser/ui/browser_list/browser.mm b/ios/chrome/browser/ui/browser_list/browser.mm similarity index 86% rename from ios/shared/chrome/browser/ui/browser_list/browser.mm rename to ios/chrome/browser/ui/browser_list/browser.mm index b80b383..c4f8b380 100644 --- a/ios/shared/chrome/browser/ui/browser_list/browser.mm +++ b/ios/chrome/browser/ui/browser_list/browser.mm
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/shared/chrome/browser/ui/browser_list/browser.h" +#import "ios/chrome/browser/ui/browser_list/browser.h" #include "base/logging.h" #include "base/memory/ptr_util.h" +#import "ios/chrome/browser/ui/browser_list/browser_web_state_list_delegate.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/shared/chrome/browser/ui/broadcaster/chrome_broadcaster.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser_web_state_list_delegate.h" #import "ios/shared/chrome/browser/ui/commands/command_dispatcher.h" #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/shared/chrome/browser/ui/browser_list/browser_list.h b/ios/chrome/browser/ui/browser_list/browser_list.h similarity index 86% rename from ios/shared/chrome/browser/ui/browser_list/browser_list.h rename to ios/chrome/browser/ui/browser_list/browser_list.h index 11edf98f..a2a71e5 100644 --- a/ios/shared/chrome/browser/ui/browser_list/browser_list.h +++ b/ios/chrome/browser/ui/browser_list/browser_list.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_H_ -#define IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_H_ +#ifndef IOS_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_H_ +#define IOS_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_H_ #include <memory> #include <vector> @@ -11,7 +11,7 @@ #include "base/macros.h" #include "base/observer_list.h" #include "base/supports_user_data.h" -#include "ios/shared/chrome/browser/ui/browser_list/browser.h" +#include "ios/chrome/browser/ui/browser_list/browser.h" class BrowserListObserver; @@ -60,4 +60,4 @@ DISALLOW_COPY_AND_ASSIGN(BrowserList); }; -#endif // IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_H_ +#endif // IOS_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_H_
diff --git a/ios/shared/chrome/browser/ui/browser_list/browser_list.mm b/ios/chrome/browser/ui/browser_list/browser_list.mm similarity index 93% rename from ios/shared/chrome/browser/ui/browser_list/browser_list.mm rename to ios/chrome/browser/ui/browser_list/browser_list.mm index 94a039f4..1bac1c2b 100644 --- a/ios/shared/chrome/browser/ui/browser_list/browser_list.mm +++ b/ios/chrome/browser/ui/browser_list/browser_list.mm
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/shared/chrome/browser/ui/browser_list/browser_list.h" +#import "ios/chrome/browser/ui/browser_list/browser_list.h" #include <stdint.h> #include "base/logging.h" #include "base/memory/ptr_util.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser_list_observer.h" +#import "ios/chrome/browser/ui/browser_list/browser_list_observer.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support."
diff --git a/ios/shared/chrome/browser/ui/browser_list/browser_list_observer.h b/ios/chrome/browser/ui/browser_list/browser_list_observer.h similarity index 76% rename from ios/shared/chrome/browser/ui/browser_list/browser_list_observer.h rename to ios/chrome/browser/ui/browser_list/browser_list_observer.h index 6afc61e..dc13323 100644 --- a/ios/shared/chrome/browser/ui/browser_list/browser_list_observer.h +++ b/ios/chrome/browser/ui/browser_list/browser_list_observer.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_OBSERVER_H_ -#define IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_OBSERVER_H_ +#ifndef IOS_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_OBSERVER_H_ +#define IOS_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_OBSERVER_H_ #include "base/macros.h" @@ -26,4 +26,4 @@ DISALLOW_COPY_AND_ASSIGN(BrowserListObserver); }; -#endif // IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_OBSERVER_H_ +#endif // IOS_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_OBSERVER_H_
diff --git a/ios/shared/chrome/browser/ui/browser_list/browser_list_observer.mm b/ios/chrome/browser/ui/browser_list/browser_list_observer.mm similarity index 89% rename from ios/shared/chrome/browser/ui/browser_list/browser_list_observer.mm rename to ios/chrome/browser/ui/browser_list/browser_list_observer.mm index ac6a9e4..f9a80a2 100644 --- a/ios/shared/chrome/browser/ui/browser_list/browser_list_observer.mm +++ b/ios/chrome/browser/ui/browser_list/browser_list_observer.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/shared/chrome/browser/ui/browser_list/browser_list_observer.h" +#import "ios/chrome/browser/ui/browser_list/browser_list_observer.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support."
diff --git a/ios/shared/chrome/browser/ui/browser_list/browser_list_session_service.h b/ios/chrome/browser/ui/browser_list/browser_list_session_service.h similarity index 81% rename from ios/shared/chrome/browser/ui/browser_list/browser_list_session_service.h rename to ios/chrome/browser/ui/browser_list/browser_list_session_service.h index c4803b2..061e05f 100644 --- a/ios/shared/chrome/browser/ui/browser_list/browser_list_session_service.h +++ b/ios/chrome/browser/ui/browser_list/browser_list_session_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 IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_SESSION_SERVICE_H_ -#define IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_SESSION_SERVICE_H_ +#ifndef IOS_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_SESSION_SERVICE_H_ +#define IOS_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_SESSION_SERVICE_H_ #include "base/macros.h" #include "components/keyed_service/core/keyed_service.h" @@ -31,4 +31,4 @@ DISALLOW_COPY_AND_ASSIGN(BrowserListSessionService); }; -#endif // IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_SESSION_SERVICE_H_ +#endif // IOS_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_SESSION_SERVICE_H_
diff --git a/ios/shared/chrome/browser/ui/browser_list/browser_list_session_service_factory.h b/ios/chrome/browser/ui/browser_list/browser_list_session_service_factory.h similarity index 82% rename from ios/shared/chrome/browser/ui/browser_list/browser_list_session_service_factory.h rename to ios/chrome/browser/ui/browser_list/browser_list_session_service_factory.h index f2d20de..3e8f058 100644 --- a/ios/shared/chrome/browser/ui/browser_list/browser_list_session_service_factory.h +++ b/ios/chrome/browser/ui/browser_list/browser_list_session_service_factory.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_SESSION_SERVICE_FACTORY_H_ -#define IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_SESSION_SERVICE_FACTORY_H_ +#ifndef IOS_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_SESSION_SERVICE_FACTORY_H_ +#define IOS_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_SESSION_SERVICE_FACTORY_H_ #include "base/macros.h" #include "components/keyed_service/ios/browser_state_keyed_service_factory.h" @@ -44,4 +44,4 @@ DISALLOW_COPY_AND_ASSIGN(BrowserListSessionServiceFactory); }; -#endif // IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_SESSION_SERVICE_FACTORY_H_ +#endif // IOS_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_SESSION_SERVICE_FACTORY_H_
diff --git a/ios/shared/chrome/browser/ui/browser_list/browser_list_session_service_factory.mm b/ios/chrome/browser/ui/browser_list/browser_list_session_service_factory.mm similarity index 93% rename from ios/shared/chrome/browser/ui/browser_list/browser_list_session_service_factory.mm rename to ios/chrome/browser/ui/browser_list/browser_list_session_service_factory.mm index 3276814..877c95a 100644 --- a/ios/shared/chrome/browser/ui/browser_list/browser_list_session_service_factory.mm +++ b/ios/chrome/browser/ui/browser_list/browser_list_session_service_factory.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/shared/chrome/browser/ui/browser_list/browser_list_session_service_factory.h" +#import "ios/chrome/browser/ui/browser_list/browser_list_session_service_factory.h" #include <memory> @@ -16,8 +16,8 @@ #include "ios/chrome/browser/browser_state/browser_state_otr_helper.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/sessions/session_service_ios.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser_list.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser_list_session_service_impl.h" +#import "ios/chrome/browser/ui/browser_list/browser_list.h" +#import "ios/chrome/browser/ui/browser_list/browser_list_session_service_impl.h" #import "ios/web/public/certificate_policy_cache.h" #import "ios/web/public/web_state/session_certificate_policy_cache.h"
diff --git a/ios/shared/chrome/browser/ui/browser_list/browser_list_session_service_impl.h b/ios/chrome/browser/ui/browser_list/browser_list_session_service_impl.h similarity index 85% rename from ios/shared/chrome/browser/ui/browser_list/browser_list_session_service_impl.h rename to ios/chrome/browser/ui/browser_list/browser_list_session_service_impl.h index 6a0cb29..cf32fae4 100644 --- a/ios/shared/chrome/browser/ui/browser_list/browser_list_session_service_impl.h +++ b/ios/chrome/browser/ui/browser_list/browser_list_session_service_impl.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_SESSION_SERVICE_IMPL_H_ -#define IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_SESSION_SERVICE_IMPL_H_ +#ifndef IOS_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_SESSION_SERVICE_IMPL_H_ +#define IOS_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_SESSION_SERVICE_IMPL_H_ #import <Foundation/Foundation.h> @@ -12,7 +12,7 @@ #include "base/callback.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser_list_session_service.h" +#import "ios/chrome/browser/ui/browser_list/browser_list_session_service.h" #import "ios/web/public/web_state/web_state.h" class BrowserList; @@ -62,4 +62,4 @@ DISALLOW_COPY_AND_ASSIGN(BrowserListSessionServiceImpl); }; -#endif // IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_SESSION_SERVICE_IMPL_H_ +#endif // IOS_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_LIST_SESSION_SERVICE_IMPL_H_
diff --git a/ios/shared/chrome/browser/ui/browser_list/browser_list_session_service_impl.mm b/ios/chrome/browser/ui/browser_list/browser_list_session_service_impl.mm similarity index 97% rename from ios/shared/chrome/browser/ui/browser_list/browser_list_session_service_impl.mm rename to ios/chrome/browser/ui/browser_list/browser_list_session_service_impl.mm index b1e164d..f6841c1 100644 --- a/ios/shared/chrome/browser/ui/browser_list/browser_list_session_service_impl.mm +++ b/ios/chrome/browser/ui/browser_list/browser_list_session_service_impl.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/shared/chrome/browser/ui/browser_list/browser_list_session_service_impl.h" +#import "ios/chrome/browser/ui/browser_list/browser_list_session_service_impl.h" #include <map> @@ -14,12 +14,12 @@ #import "ios/chrome/browser/sessions/session_ios.h" #import "ios/chrome/browser/sessions/session_service_ios.h" #import "ios/chrome/browser/sessions/session_window_ios.h" +#import "ios/chrome/browser/ui/browser_list/browser.h" +#import "ios/chrome/browser/ui/browser_list/browser_list.h" +#import "ios/chrome/browser/ui/browser_list/browser_list_observer.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/chrome/browser/web_state_list/web_state_list_observer.h" #import "ios/chrome/browser/web_state_list/web_state_list_serialization.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser_list.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser_list_observer.h" #import "ios/web/public/navigation_item.h" #import "ios/web/public/navigation_manager.h" #import "ios/web/public/web_state/web_state.h"
diff --git a/ios/shared/chrome/browser/ui/browser_list/browser_list_unittest.mm b/ios/chrome/browser/ui/browser_list/browser_list_unittest.mm similarity index 96% rename from ios/shared/chrome/browser/ui/browser_list/browser_list_unittest.mm rename to ios/chrome/browser/ui/browser_list/browser_list_unittest.mm index ece8ca1..fc1e633 100644 --- a/ios/shared/chrome/browser/ui/browser_list/browser_list_unittest.mm +++ b/ios/chrome/browser/ui/browser_list/browser_list_unittest.mm
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/shared/chrome/browser/ui/browser_list/browser_list.h" +#import "ios/chrome/browser/ui/browser_list/browser_list.h" #include <memory> #include "base/macros.h" #include "base/scoped_observer.h" #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser_list_observer.h" +#import "ios/chrome/browser/ui/browser_list/browser_list_observer.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h"
diff --git a/ios/shared/chrome/browser/ui/browser_list/browser_user_data.h b/ios/chrome/browser/ui/browser_list/browser_user_data.h similarity index 89% rename from ios/shared/chrome/browser/ui/browser_list/browser_user_data.h rename to ios/chrome/browser/ui/browser_list/browser_user_data.h index 15562a3..337956be 100644 --- a/ios/shared/chrome/browser/ui/browser_list/browser_user_data.h +++ b/ios/chrome/browser/ui/browser_list/browser_user_data.h
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_USER_DATA_H_ -#define IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_USER_DATA_H_ +#ifndef IOS_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_USER_DATA_H_ +#define IOS_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_USER_DATA_H_ #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/supports_user_data.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser.h" +#import "ios/chrome/browser/ui/browser_list/browser.h" // A base class for classes attached to, and scoped to, the lifetime of a // Browser. For example: @@ -71,4 +71,4 @@ template <> \ int BrowserUserData<TYPE>::kLocatorKey = 0 -#endif // IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_USER_DATA_H_ +#endif // IOS_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_USER_DATA_H_
diff --git a/ios/shared/chrome/browser/ui/browser_list/browser_web_state_list_delegate.h b/ios/chrome/browser/ui/browser_list/browser_web_state_list_delegate.h similarity index 74% rename from ios/shared/chrome/browser/ui/browser_list/browser_web_state_list_delegate.h rename to ios/chrome/browser/ui/browser_list/browser_web_state_list_delegate.h index e09ba1d7..355468d 100644 --- a/ios/shared/chrome/browser/ui/browser_list/browser_web_state_list_delegate.h +++ b/ios/chrome/browser/ui/browser_list/browser_web_state_list_delegate.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_WEB_STATE_LIST_DELEGATE_H_ -#define IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_WEB_STATE_LIST_DELEGATE_H_ +#ifndef IOS_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_WEB_STATE_LIST_DELEGATE_H_ +#define IOS_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_WEB_STATE_LIST_DELEGATE_H_ #include "base/macros.h" #import "ios/chrome/browser/web_state_list/web_state_list_delegate.h" @@ -26,4 +26,4 @@ DISALLOW_COPY_AND_ASSIGN(BrowserWebStateListDelegate); }; -#endif // IOS_SHARED_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_WEB_STATE_LIST_DELEGATE_H_ +#endif // IOS_CHROME_BROWSER_UI_BROWSER_LIST_BROWSER_WEB_STATE_LIST_DELEGATE_H_
diff --git a/ios/shared/chrome/browser/ui/browser_list/browser_web_state_list_delegate.mm b/ios/chrome/browser/ui/browser_list/browser_web_state_list_delegate.mm similarity index 92% rename from ios/shared/chrome/browser/ui/browser_list/browser_web_state_list_delegate.mm rename to ios/chrome/browser/ui/browser_list/browser_web_state_list_delegate.mm index b8c92f3..5ebff4d 100644 --- a/ios/shared/chrome/browser/ui/browser_list/browser_web_state_list_delegate.mm +++ b/ios/chrome/browser/ui/browser_list/browser_web_state_list_delegate.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/shared/chrome/browser/ui/browser_list/browser_web_state_list_delegate.h" +#import "ios/chrome/browser/ui/browser_list/browser_web_state_list_delegate.h" #include "base/logging.h" #import "ios/chrome/browser/find_in_page/find_tab_helper.h"
diff --git a/ios/chrome/browser/ui/browser_view_controller.h b/ios/chrome/browser/ui/browser_view_controller.h index 6d87b4a..88a7947 100644 --- a/ios/chrome/browser/ui/browser_view_controller.h +++ b/ios/chrome/browser/ui/browser_view_controller.h
@@ -107,6 +107,12 @@ // Called when the user explicitly opens the tab switcher. - (void)userEnteredTabSwitcher; +// Presents either the new tab tip or incognito tab tip in-product help bubbles +// if the the user is in a valid state to see one of them. At most one bubble +// will be shown. If the feature engagement tracker determines it is not valid +// to see one of the bubbles, that bubble will not be shown. +- (void)presentBubblesIfEligible; + // Called when the browser state provided to this instance is being destroyed. // At this point the browser will no longer ever be active, and will likely be // deallocated soon.
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index 0a40ac3..703859def 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -581,6 +581,10 @@ @property(nonatomic, strong) BubbleViewControllerPresenter* tabTipBubblePresenter; +// Used to display the new incognito tab tip in-product help promotion bubble. +@property(nonatomic, strong) + BubbleViewControllerPresenter* incognitoTabTipBubblePresenter; + // BVC initialization: // If the BVC is initialized with a valid browser state & tab model immediately, // the path is straightforward: functionality is enabled, and the UI is built @@ -694,10 +698,22 @@ // promotion until the feature engagement tracker database is fully initialized. // Does not present the bubble if |tabTipBubblePresenter.userEngaged| is |YES| // to prevent resetting |tabTipBubblePresenter| and affecting the value of -// |userEngaged|. +// |userEngaged|. Does not present the bubble if the feature engagement tracker +// determines it is not valid to present it. - (void)presentNewTabTipBubbleOnInitialized; -// Presents a bubble associated with the new tab tip in-product help promotion. +// Optionally presents a bubble associated with the new tab tip in-product help +// promotion. If the feature engagement tracker determines it is valid to show +// the new tab tip, then it initializes |tabTipBubblePresenter| and presents +// the bubble. If it is not valid to show the new tab tip, +// |tabTipBubblePresenter| is set to |nil| and no bubble is shown. - (void)presentNewTabTipBubble; +// Waits to present a bubble associated with the new incognito tab tip +// in-product help promotion until the feature engagement tracker database is +// fully initialized. +- (void)presentNewIncognitoTabTipBubbleOnInitialized; +// Presents a bubble associated with the new incognito tab tip in-product help +// promotion. +- (void)presentNewIncognitoTabTipBubble; // Create and show the find bar. - (void)initFindBarForTab; @@ -947,7 +963,8 @@ @synthesize presenting = _presenting; @synthesize foregroundTabWasAddedCompletionBlock = _foregroundTabWasAddedCompletionBlock; -@synthesize tabTipBubblePresenter = tabTipBubblePresenter; +@synthesize tabTipBubblePresenter = _tabTipBubblePresenter; +@synthesize incognitoTabTipBubblePresenter = _incognitoTabTipBubblePresenter; #pragma mark - Object lifecycle @@ -1217,6 +1234,11 @@ } } +- (void)presentBubblesIfEligible { + [self presentNewTabTipBubbleOnInitialized]; + [self presentNewIncognitoTabTipBubble]; +} + #pragma mark - UIViewController methods // Perform additional set up after loading the view, typically from a nib. @@ -1263,7 +1285,7 @@ [super viewDidAppear:animated]; self.viewVisible = YES; [self updateDialogPresenterActiveState]; - [self presentNewTabTipBubbleOnInitialized]; + [self presentBubblesIfEligible]; } - (void)viewWillAppear:(BOOL)animated { @@ -2073,6 +2095,9 @@ tabSwitcherAnchor = [self.toolbarController anchorPointForTabSwitcherButton:BubbleArrowDirectionUp]; } + // If the feature engagement tracker does not consider it valid to display + // the new tab tip, then |bubblePresenterForFeature| returns |nil| and the + // call to |presentInViewController| is a no-op. self.tabTipBubblePresenter = [self bubblePresenterForFeature:feature_engagement::kIPHNewTabTipFeature direction:BubbleArrowDirectionUp @@ -2083,6 +2108,46 @@ anchorPoint:tabSwitcherAnchor]; } +- (void)presentNewIncognitoTabTipBubbleOnInitialized { + // Do not override |incognitoTabtipBubblePresenter| or set it to nil if the + // user is still considered engaged. + if (!self.incognitoTabTipBubblePresenter.isUserEngaged) { + __weak BrowserViewController* weakSelf = self; + void (^onInitializedBlock)(bool) = ^(bool successfullyLoaded) { + [weakSelf presentNewIncognitoTabTipBubble]; + }; + + // Use a callback in case the new incognito tab tip should be shown on + // startup. This ensures that the tracker's database will be fully loaded + // before checking if the promotion should be displayed. + feature_engagement::TrackerFactory::GetForBrowserState(self.browserState) + ->AddOnInitializedCallback(base::BindBlockArc(onInitializedBlock)); + } +} + +- (void)presentNewIncognitoTabTipBubble { + DCHECK([self.toolbarController + respondsToSelector:@selector(anchorPointForToolsMenuButton:)]); + NSString* text = l10n_util::GetNSStringWithFixup( + IDS_IOS_NEW_INCOGNITO_TAB_IPH_PROMOTION_TEXT); + CGPoint toolsButtonAnchor = [self.toolbarController + anchorPointForToolsMenuButton:BubbleArrowDirectionUp]; + self.incognitoTabTipBubblePresenter = + [self bubblePresenterForFeature:feature_engagement:: + kIPHNewIncognitoTabTipFeature + direction:BubbleArrowDirectionUp + alignment:BubbleAlignmentTrailing + text:text]; + [self.incognitoTabTipBubblePresenter + presentInViewController:self + view:self.view + anchorPoint:toolsButtonAnchor]; + // Only trigger the tools menu button animation if the bubble is shown. + if (self.incognitoTabTipBubblePresenter) { + [self.toolbarController triggerToolsMenuButtonAnimation]; + } +} + #pragma mark - Tap handling - (void)setLastTapPoint:(OpenNewTabCommand*)command { @@ -4097,6 +4162,15 @@ [configuration setUserAgentType:self.userAgentType]; + if (self.incognitoTabTipBubblePresenter.triggerFollowUpAction) { + [configuration setHighlightNewIncognitoTabCell:YES]; + [self.incognitoTabTipBubblePresenter setTriggerFollowUpAction:NO]; + } + + if (self.incognitoTabTipBubblePresenter.isUserEngaged) { + base::RecordAction(UserMetricsAction("NewIncognitoTabTipTargetSelected")); + } + [_toolbarController showToolsMenuPopupWithConfiguration:configuration]; ToolsPopupController* toolsPopupController =
diff --git a/ios/chrome/browser/ui/bubble/OWNERS b/ios/chrome/browser/ui/bubble/OWNERS index d122690d..2c40cf4 100644 --- a/ios/chrome/browser/ui/bubble/OWNERS +++ b/ios/chrome/browser/ui/bubble/OWNERS
@@ -1,2 +1,4 @@ edchin@chromium.org -gchatz@chromium.org \ No newline at end of file +gchatz@chromium.org +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/bubble/bubble_util_unittest.mm b/ios/chrome/browser/ui/bubble/bubble_util_unittest.mm index bed713c..2cb7c9b 100644 --- a/ios/chrome/browser/ui/bubble/bubble_util_unittest.mm +++ b/ios/chrome/browser/ui/bubble/bubble_util_unittest.mm
@@ -14,7 +14,7 @@ #endif namespace { -const CGFloat kTestBubbleAlignmentOffset = 40.0f; +const CGFloat kTestBubbleAlignmentOffset = 25.0f; } // namespace namespace bubble_util {
diff --git a/ios/chrome/browser/ui/bubble/bubble_view.mm b/ios/chrome/browser/ui/bubble/bubble_view.mm index 5c4f211..b2b8b3c 100644 --- a/ios/chrome/browser/ui/bubble/bubble_view.mm +++ b/ios/chrome/browser/ui/bubble/bubble_view.mm
@@ -12,7 +12,7 @@ #error "This file requires ARC support." #endif -const CGFloat kBubbleAlignmentOffset = 40.0f; +const CGFloat kBubbleAlignmentOffset = 25.0f; namespace { // The color of the bubble (both circular background and arrow).
diff --git a/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.h b/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.h index 4db25936..911f1c6 100644 --- a/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.h +++ b/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.h
@@ -30,6 +30,13 @@ // the bubble had an effect on the user's action. @property(nonatomic, assign, readonly, getter=isUserEngaged) BOOL userEngaged; +// Determines whether a follow-up action, such as highlighting a UI element, +// should be triggered. This depends on |userEngaged|, since a follow-up action +// should only occur if the user is engaged with the bubble. Defaults to |YES|, +// and is set to |NO| once |userEngaged| is set to |NO| or after the user has +// triggered the follow-up action. +@property(nonatomic, assign) BOOL triggerFollowUpAction; + // Initializes the presenter. |text| is the text displayed by the bubble. // |arrowDirection| is the direction the bubble's arrow is pointing. |alignment| // is the position of the arrow on the bubble. |dismissalCallback| is a block
diff --git a/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.mm b/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.mm index cb298b0..21dd759f 100644 --- a/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.mm +++ b/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.mm
@@ -71,6 +71,7 @@ @synthesize bubbleDismissalTimer = _bubbleDismissalTimer; @synthesize engagementTimer = _engagementTimer; @synthesize userEngaged = _userEngaged; +@synthesize triggerFollowUpAction = _triggerFollowUpAction; @synthesize arrowDirection = _arrowDirection; @synthesize alignment = _alignment; @synthesize dismissalCallback = _dismissalCallback; @@ -96,6 +97,7 @@ _insideBubbleTapRecognizer.delegate = self; _insideBubbleTapRecognizer.cancelsTouchesInView = NO; _userEngaged = NO; + _triggerFollowUpAction = NO; _arrowDirection = arrowDirection; _alignment = alignment; _dismissalCallback = dismissalCallback; @@ -132,6 +134,7 @@ repeats:NO]; self.userEngaged = YES; + self.triggerFollowUpAction = YES; self.engagementTimer = [NSTimer scheduledTimerWithTimeInterval:kBubbleEngagementDuration target:self @@ -206,6 +209,7 @@ // Marks the user as not engaged when |engagementTimer| fires. - (void)engagementTimerFired:(id)sender { self.userEngaged = NO; + self.triggerFollowUpAction = NO; self.engagementTimer = nil; }
diff --git a/ios/chrome/browser/ui/bubble/bubble_view_unittest.mm b/ios/chrome/browser/ui/bubble/bubble_view_unittest.mm index c9c64d71..6842465 100644 --- a/ios/chrome/browser/ui/bubble/bubble_view_unittest.mm +++ b/ios/chrome/browser/ui/bubble/bubble_view_unittest.mm
@@ -46,7 +46,7 @@ CGSize bubbleSize = [bubble sizeThatFits:maxSize_]; // Since the label is shorter than the minimum line width, expect the bubble // to be the minimum width and accommodate one line of text. - EXPECT_NEAR(80.0f, bubbleSize.width, 1.0f); + EXPECT_NEAR(56.0f, bubbleSize.width, 1.0f); EXPECT_NEAR(61.5f, bubbleSize.height, 1.0f); }
diff --git a/ios/chrome/browser/ui/collection_view/OWNERS b/ios/chrome/browser/ui/collection_view/OWNERS index 077a06e..c984591 100644 --- a/ios/chrome/browser/ui/collection_view/OWNERS +++ b/ios/chrome/browser/ui/collection_view/OWNERS
@@ -1,2 +1,5 @@ lpromero@chromium.org rohitrao@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/colors/OWNERS b/ios/chrome/browser/ui/colors/OWNERS index 4bb62eb..a188a478 100644 --- a/ios/chrome/browser/ui/colors/OWNERS +++ b/ios/chrome/browser/ui/colors/OWNERS
@@ -1 +1,4 @@ lpromero@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/content_suggestions/OWNERS b/ios/chrome/browser/ui/content_suggestions/OWNERS index 2d35f0a..f192143 100644 --- a/ios/chrome/browser/ui/content_suggestions/OWNERS +++ b/ios/chrome/browser/ui/content_suggestions/OWNERS
@@ -1 +1,4 @@ gambard@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.mm index 5aa5a63..967abb0 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.mm
@@ -343,8 +343,6 @@ NSInteger sectionIdentifier = SectionIdentifierForInfo(sectionInfo); if (suggestions.count == 0) { - // No suggestions for this section. Add the item signaling this section is - // empty if there is currently no item in it. if ([model hasSectionForSectionIdentifier:sectionIdentifier] && [model numberOfItemsInSection:[model sectionForSectionIdentifier: sectionIdentifier]] == 0) { @@ -358,35 +356,6 @@ return indexPaths; } - if (sectionIdentifier == SectionIdentifierLearnMore) { - // The "Learn more" items should only be displayed if there is at least one - // ContentSuggestions section. - if ((![model hasSectionForSectionIdentifier:SectionIdentifierArticles] && - ! - [model hasSectionForSectionIdentifier:SectionIdentifierReadingList]) || - [model itemsInSectionWithIdentifier:sectionIdentifier].count > 0) { - return @[]; - } - } else if (IsFromContentSuggestions(sectionIdentifier)) { - // If the section is a ContentSuggestions section, add the "Learn more" - // items if they are not already present. - if ([model hasSectionForSectionIdentifier:SectionIdentifierLearnMore] && - [model itemsInSectionWithIdentifier:SectionIdentifierLearnMore].count == - 0) { - ContentSuggestionsSectionInformation* learnMoreSectionInfo = - self.sectionInfoBySectionIdentifier[@(SectionIdentifierLearnMore)]; - for (CSCollectionViewItem* item in - [self.dataSource itemsForSectionInfo:learnMoreSectionInfo]) { - item.type = ItemTypeForInfo(learnMoreSectionInfo); - NSIndexPath* addedIndexPath = [self addItem:item - toSectionWithIdentifier:SectionIdentifierLearnMore]; - - [indexPaths addObject:addedIndexPath]; - } - } - } - - // Add the items from this section. [suggestions enumerateObjectsUsingBlock:^(CSCollectionViewItem* item, NSUInteger index, BOOL* stop) { NSInteger section = [model sectionForSectionIdentifier:sectionIdentifier];
diff --git a/ios/chrome/browser/ui/context_menu/OWNERS b/ios/chrome/browser/ui/context_menu/OWNERS index 49ba79e..07726cf 100644 --- a/ios/chrome/browser/ui/context_menu/OWNERS +++ b/ios/chrome/browser/ui/context_menu/OWNERS
@@ -1 +1,4 @@ michaeldo@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/contextual_search/OWNERS b/ios/chrome/browser/ui/contextual_search/OWNERS index 3141303..17f2da6 100644 --- a/ios/chrome/browser/ui/contextual_search/OWNERS +++ b/ios/chrome/browser/ui/contextual_search/OWNERS
@@ -1,2 +1,5 @@ marq@chromium.org olivierrobin@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/dialogs/OWNERS b/ios/chrome/browser/ui/dialogs/OWNERS index 48efb49e..bd85dcf2 100644 --- a/ios/chrome/browser/ui/dialogs/OWNERS +++ b/ios/chrome/browser/ui/dialogs/OWNERS
@@ -1 +1,4 @@ kkhorimoto@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/elements/OWNERS b/ios/chrome/browser/ui/elements/OWNERS index f49ed38..01e8c98 100644 --- a/ios/chrome/browser/ui/elements/OWNERS +++ b/ios/chrome/browser/ui/elements/OWNERS
@@ -1 +1,4 @@ marq@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/fancy_ui/OWNERS b/ios/chrome/browser/ui/fancy_ui/OWNERS index 40a68c7..b127701 100644 --- a/ios/chrome/browser/ui/fancy_ui/OWNERS +++ b/ios/chrome/browser/ui/fancy_ui/OWNERS
@@ -1 +1,4 @@ rohitrao@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/favicon/OWNERS b/ios/chrome/browser/ui/favicon/OWNERS index 2d35f0a..f192143 100644 --- a/ios/chrome/browser/ui/favicon/OWNERS +++ b/ios/chrome/browser/ui/favicon/OWNERS
@@ -1 +1,4 @@ gambard@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/find_bar/BUILD.gn b/ios/chrome/browser/ui/find_bar/BUILD.gn index ad487457..9ca15b2 100644 --- a/ios/chrome/browser/ui/find_bar/BUILD.gn +++ b/ios/chrome/browser/ui/find_bar/BUILD.gn
@@ -55,7 +55,6 @@ "//components/strings", "//ios/chrome/app/strings", "//ios/chrome/browser/find_in_page", - "//ios/chrome/browser/ui:ui", "//ios/chrome/browser/ui/tools_menu", "//ios/chrome/test/app:test_support", "//ios/chrome/test/earl_grey:test_support",
diff --git a/ios/chrome/browser/ui/find_bar/OWNERS b/ios/chrome/browser/ui/find_bar/OWNERS index 8298f43..479c250 100644 --- a/ios/chrome/browser/ui/find_bar/OWNERS +++ b/ios/chrome/browser/ui/find_bar/OWNERS
@@ -1,2 +1,5 @@ justincohen@chromium.org stkhapugin@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/find_bar/find_in_page_egtest.mm b/ios/chrome/browser/ui/find_bar/find_in_page_egtest.mm index 36bb7af..ef3dfcd 100644 --- a/ios/chrome/browser/ui/find_bar/find_in_page_egtest.mm +++ b/ios/chrome/browser/ui/find_bar/find_in_page_egtest.mm
@@ -4,14 +4,12 @@ #import <XCTest/XCTest.h> -#include "base/ios/ios_util.h" #include "base/strings/string_number_conversions.h" #include "components/strings/grit/components_strings.h" #import "ios/chrome/browser/find_in_page/find_in_page_controller.h" #import "ios/chrome/browser/ui/find_bar/find_bar_controller_ios.h" #import "ios/chrome/browser/ui/find_bar/find_bar_view.h" #include "ios/chrome/browser/ui/tools_menu/tools_menu_constants.h" -#include "ios/chrome/browser/ui/ui_util.h" #import "ios/chrome/test/app/tab_test_util.h" #import "ios/chrome/test/earl_grey/accessibility_util.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" @@ -96,12 +94,6 @@ // Tests that find in page allows iteration between search results and displays // correct number of results. - (void)testFindInPage { - // TODO(crbug.com/753098): Re-enable this test on iOS 11 iPad once - // grey_typeText works on iOS 11. - if (base::ios::IsRunningOnIOS11OrLater() && IsIPadIdiom()) { - EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 11."); - } - // Type "find". [self typeFindInPageText:@"find"]; // Should be highlighting result 1 of 2. @@ -184,7 +176,7 @@ - (void)typeFindInPageText:(NSString*)text { [[EarlGrey selectElementWithMatcher:[self findInPageInputField]] - performAction:grey_typeText(text)]; + performAction:grey_replaceText(text)]; } - (id<GREYMatcher>)findInPageInputField {
diff --git a/ios/chrome/browser/ui/first_run/OWNERS b/ios/chrome/browser/ui/first_run/OWNERS index 3281fe5b..e29ab3e 100644 --- a/ios/chrome/browser/ui/first_run/OWNERS +++ b/ios/chrome/browser/ui/first_run/OWNERS
@@ -1,2 +1,5 @@ bzanotti@chromium.org kkhorimoto@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/history/BUILD.gn b/ios/chrome/browser/ui/history/BUILD.gn index 10674d96..ed52dc65c 100644 --- a/ios/chrome/browser/ui/history/BUILD.gn +++ b/ios/chrome/browser/ui/history/BUILD.gn
@@ -207,7 +207,6 @@ "//ios/chrome/app/strings", "//ios/chrome/browser", "//ios/chrome/browser/browser_state", - "//ios/chrome/browser/ui/authentication:authentication_ui", "//ios/chrome/browser/ui/settings", "//ios/chrome/browser/ui/tools_menu", "//ios/chrome/browser/ui/util",
diff --git a/ios/chrome/browser/ui/history/OWNERS b/ios/chrome/browser/ui/history/OWNERS index 1085212..1c26985 100644 --- a/ios/chrome/browser/ui/history/OWNERS +++ b/ios/chrome/browser/ui/history/OWNERS
@@ -1,2 +1,5 @@ lpromero@chromium.org sczs@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/history/history_ui_egtest.mm b/ios/chrome/browser/ui/history/history_ui_egtest.mm index 590f142f..51b4feed 100644 --- a/ios/chrome/browser/ui/history/history_ui_egtest.mm +++ b/ios/chrome/browser/ui/history/history_ui_egtest.mm
@@ -14,7 +14,6 @@ #include "components/strings/grit/components_strings.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/chrome_url_constants.h" -#import "ios/chrome/browser/ui/authentication/signin_promo_view.h" #import "ios/chrome/browser/ui/history/history_entry_item.h" #import "ios/chrome/browser/ui/settings/clear_browsing_data_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/settings_collection_view_controller.h"
diff --git a/ios/chrome/browser/ui/infobars/OWNERS b/ios/chrome/browser/ui/infobars/OWNERS index d2e1add..c85e66a 100644 --- a/ios/chrome/browser/ui/infobars/OWNERS +++ b/ios/chrome/browser/ui/infobars/OWNERS
@@ -1 +1,4 @@ jif@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/keyboard/OWNERS b/ios/chrome/browser/ui/keyboard/OWNERS index 4bb62eb..a188a478 100644 --- a/ios/chrome/browser/ui/keyboard/OWNERS +++ b/ios/chrome/browser/ui/keyboard/OWNERS
@@ -1 +1,4 @@ lpromero@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/keyboard_commands_egtest.mm b/ios/chrome/browser/ui/keyboard_commands_egtest.mm index 2b72f680..db85067 100644 --- a/ios/chrome/browser/ui/keyboard_commands_egtest.mm +++ b/ios/chrome/browser/ui/keyboard_commands_egtest.mm
@@ -115,8 +115,7 @@ - (void)selectToolsMenuItem:(id<GREYMatcher>)toolsMenuItem { [ChromeEarlGreyUI openToolsMenu]; - id<GREYMatcher> toolsMenuTableView = - grey_accessibilityID(kToolsMenuTableViewId); + id<GREYMatcher> toolsMenuTableView = chrome_test_util::ToolsMenuView(); [[[EarlGrey selectElementWithMatcher:toolsMenuItem] usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, kScrollDisplacement)
diff --git a/ios/chrome/browser/ui/main/OWNERS b/ios/chrome/browser/ui/main/OWNERS index f49ed38..01e8c98 100644 --- a/ios/chrome/browser/ui/main/OWNERS +++ b/ios/chrome/browser/ui/main/OWNERS
@@ -1 +1,4 @@ marq@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/ntp/OWNERS b/ios/chrome/browser/ui/ntp/OWNERS index 3306281..9b78e8b 100644 --- a/ios/chrome/browser/ui/ntp/OWNERS +++ b/ios/chrome/browser/ui/ntp/OWNERS
@@ -1,2 +1,5 @@ rohitrao@chromium.org justincohen@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/ntp/recent_tabs/OWNERS b/ios/chrome/browser/ui/ntp/recent_tabs/OWNERS index d2e1add..c85e66a 100644 --- a/ios/chrome/browser/ui/ntp/recent_tabs/OWNERS +++ b/ios/chrome/browser/ui/ntp/recent_tabs/OWNERS
@@ -1 +1,4 @@ jif@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/omnibox/OWNERS b/ios/chrome/browser/ui/omnibox/OWNERS index 03b0059..5e5e932a 100644 --- a/ios/chrome/browser/ui/omnibox/OWNERS +++ b/ios/chrome/browser/ui/omnibox/OWNERS
@@ -2,3 +2,6 @@ rohitrao@chromium.org # COMPONENT: UI>Browser>Omnibox + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/overscroll_actions/OWNERS b/ios/chrome/browser/ui/overscroll_actions/OWNERS index d2e1add..c85e66a 100644 --- a/ios/chrome/browser/ui/overscroll_actions/OWNERS +++ b/ios/chrome/browser/ui/overscroll_actions/OWNERS
@@ -1 +1,4 @@ jif@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/payments/OWNERS b/ios/chrome/browser/ui/payments/OWNERS index 4cfb56d..2a262cc2 100644 --- a/ios/chrome/browser/ui/payments/OWNERS +++ b/ios/chrome/browser/ui/payments/OWNERS
@@ -1,2 +1,5 @@ lpromero@chromium.org mahmadi@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/payments/payment_request_manager.mm b/ios/chrome/browser/ui/payments/payment_request_manager.mm index 36ff598d..dddb360 100644 --- a/ios/chrome/browser/ui/payments/payment_request_manager.mm +++ b/ios/chrome/browser/ui/payments/payment_request_manager.mm
@@ -39,6 +39,8 @@ #include "ios/chrome/browser/autofill/validation_rules_storage_factory.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/payments/ios_can_make_payment_query_factory.h" +#include "ios/chrome/browser/payments/ios_payment_instrument_launcher.h" +#include "ios/chrome/browser/payments/ios_payment_instrument_launcher_factory.h" #include "ios/chrome/browser/payments/ios_payment_request_cache_factory.h" #include "ios/chrome/browser/payments/origin_security_checker.h" #include "ios/chrome/browser/payments/payment_request.h" @@ -308,12 +310,21 @@ (ProceduralBlockWithBool)callback { DCHECK(_pendingPaymentRequest); _pendingPaymentRequest = nullptr; + [self resetIOSPaymentInstrumentLauncherDelegate]; [self dismissUI]; [_paymentRequestJsManager rejectRequestPromiseWithErrorName:kAbortErrorName errorMessage:errorMessage completionHandler:callback]; } +- (void)resetIOSPaymentInstrumentLauncherDelegate { + payments::IOSPaymentInstrumentLauncher* paymentAppLauncher = + payments::IOSPaymentInstrumentLauncherFactory::GetInstance() + ->GetForBrowserState(_browserState); + DCHECK(paymentAppLauncher); + paymentAppLauncher->set_delegate(nullptr); +} + - (void)close { [self setActiveWebState:nullptr]; } @@ -474,6 +485,30 @@ paymentRequest->request_payer_phone(), paymentRequest->request_payer_name()); + // Log metrics around which payment methods are requested by the merchant. + const GURL kGooglePayUrl("https://google.com/pay"); + const GURL kAndroidPayUrl("https://android.com/pay"); + // Looking for payment methods that are NOT Google-related as well as the + // Google-related ones. + bool requestedMethodGoogle = false; + bool requestedMethodOther = false; + for (const GURL& url_payment_method : + paymentRequest->url_payment_method_identifiers()) { + if (url_payment_method == kGooglePayUrl || + url_payment_method == kAndroidPayUrl) { + requestedMethodGoogle = true; + } else { + requestedMethodOther = true; + } + } + + paymentRequest->journey_logger().SetRequestedPaymentMethodTypes( + /*requested_basic_card=*/!paymentRequest->supported_card_networks() + .empty(), + /*requested_method_google=*/ + requestedMethodGoogle, + /*requested_method_other=*/requestedMethodOther); + UIImage* pageFavicon = nil; web::NavigationItem* navigationItem = _activeWebState->GetNavigationManager()->GetVisibleItem(); @@ -756,12 +791,24 @@ } - (void)paymentInstrument:(payments::IOSPaymentInstrument*)paymentInstrument - launchAppWithUniversalLink:(std::string)universalLink + launchAppWithUniversalLink:(GURL)universalLink instrumentDelegate: (payments::PaymentInstrument::Delegate*)delegate { - // TODO(crbug.com/748556): Implement this function to use a native app's - // universal link to open it from Chrome with several arguments supplied - // from the Payment Request object. + DCHECK(_pendingPaymentRequest); + DCHECK(_activeWebState); + + [_paymentRequestCoordinator setPending:YES]; + [_paymentRequestCoordinator setCancellable:YES]; + + payments::IOSPaymentInstrumentLauncher* paymentAppLauncher = + payments::IOSPaymentInstrumentLauncherFactory::GetInstance() + ->GetForBrowserState(_browserState); + DCHECK(paymentAppLauncher); + if (!paymentAppLauncher->LaunchIOSPaymentInstrument( + _pendingPaymentRequest, _activeWebState, universalLink, delegate)) { + [_paymentRequestCoordinator setPending:NO]; + [_paymentRequestCoordinator setCancellable:YES]; + } } #pragma mark - PaymentRequestCoordinatorDelegate methods @@ -840,6 +887,11 @@ [_paymentRequestCoordinator setCancellable:NO]; } +- (void)paymentResponseHelperDidFailToReceivePaymentMethodDetails { + [_paymentRequestCoordinator setPending:NO]; + [_paymentRequestCoordinator setCancellable:YES]; +} + - (void)paymentResponseHelperDidCompleteWithPaymentResponse: (const web::PaymentResponse&)paymentResponse { [_paymentRequestJsManager @@ -859,6 +911,7 @@ _pendingPaymentRequest->journey_logger().SetAborted( payments::JourneyLogger::ABORT_REASON_MERCHANT_NAVIGATION); _pendingPaymentRequest = nullptr; + [self resetIOSPaymentInstrumentLauncherDelegate]; } [self dismissUI];
diff --git a/ios/chrome/browser/ui/product_tour/OWNERS b/ios/chrome/browser/ui/product_tour/OWNERS index 48efb49e..bd85dcf2 100644 --- a/ios/chrome/browser/ui/product_tour/OWNERS +++ b/ios/chrome/browser/ui/product_tour/OWNERS
@@ -1 +1,4 @@ kkhorimoto@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/promos/OWNERS b/ios/chrome/browser/ui/promos/OWNERS index f49ed38..01e8c98 100644 --- a/ios/chrome/browser/ui/promos/OWNERS +++ b/ios/chrome/browser/ui/promos/OWNERS
@@ -1 +1,4 @@ marq@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/qr_scanner/OWNERS b/ios/chrome/browser/ui/qr_scanner/OWNERS index d2e1add..c85e66a 100644 --- a/ios/chrome/browser/ui/qr_scanner/OWNERS +++ b/ios/chrome/browser/ui/qr_scanner/OWNERS
@@ -1 +1,4 @@ jif@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/reader_mode/OWNERS b/ios/chrome/browser/ui/reader_mode/OWNERS index bf1620f..ab525656 100644 --- a/ios/chrome/browser/ui/reader_mode/OWNERS +++ b/ios/chrome/browser/ui/reader_mode/OWNERS
@@ -1 +1,4 @@ noyau@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/reading_list/OWNERS b/ios/chrome/browser/ui/reading_list/OWNERS index ad2440ad..8f4d804 100644 --- a/ios/chrome/browser/ui/reading_list/OWNERS +++ b/ios/chrome/browser/ui/reading_list/OWNERS
@@ -4,3 +4,6 @@ per-file *badge_view*=edchin@chromium.org per-file *badge_view*=gchatz@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/sad_tab/OWNERS b/ios/chrome/browser/ui/sad_tab/OWNERS index 48efb49e..bd85dcf2 100644 --- a/ios/chrome/browser/ui/sad_tab/OWNERS +++ b/ios/chrome/browser/ui/sad_tab/OWNERS
@@ -1 +1,4 @@ kkhorimoto@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn index 96bcdce..bb4f70b 100644 --- a/ios/chrome/browser/ui/settings/BUILD.gn +++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -350,7 +350,6 @@ "//ios/chrome/browser/search_engines", "//ios/chrome/browser/signin", "//ios/chrome/browser/ui:ui_internal", - "//ios/chrome/browser/ui/authentication:authentication_ui", "//ios/chrome/browser/ui/settings:test_support", "//ios/chrome/browser/ui/tools_menu", "//ios/chrome/browser/ui/util:util",
diff --git a/ios/chrome/browser/ui/settings/OWNERS b/ios/chrome/browser/ui/settings/OWNERS index ccddf8d..126713c7 100644 --- a/ios/chrome/browser/ui/settings/OWNERS +++ b/ios/chrome/browser/ui/settings/OWNERS
@@ -1,2 +1,5 @@ lpromero@chromium.org sdefresne@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/settings/accounts_collection_egtest.mm b/ios/chrome/browser/ui/settings/accounts_collection_egtest.mm index 432b587a..9efe103 100644 --- a/ios/chrome/browser/ui/settings/accounts_collection_egtest.mm +++ b/ios/chrome/browser/ui/settings/accounts_collection_egtest.mm
@@ -9,7 +9,6 @@ #include "components/signin/core/browser/signin_manager.h" #include "components/strings/grit/components_strings.h" #include "ios/chrome/browser/signin/signin_manager_factory.h" -#import "ios/chrome/browser/ui/settings/accounts_collection_view_controller.h" #include "ios/chrome/browser/ui/tools_menu/tools_menu_constants.h" #import "ios/chrome/browser/ui/tools_menu/tools_popup_controller.h" #include "ios/chrome/grit/ios_strings.h" @@ -32,7 +31,6 @@ using chrome_test_util::SettingsAccountButton; using chrome_test_util::SignOutAccountsButton; using chrome_test_util::SignInMenuButton; -using chrome_test_util::SignInPromoView; namespace { @@ -122,7 +120,7 @@ ios::FakeChromeIdentityService::GetInstanceFromChromeProvider() ->ForgetIdentity(identity, nil); - [[EarlGrey selectElementWithMatcher:SignInPromoView()] + [[EarlGrey selectElementWithMatcher:SignInMenuButton()] assertWithMatcher:grey_sufficientlyVisible()]; AssertAuthenticatedIdentityInActiveProfile(nil); @@ -152,7 +150,7 @@ ios::FakeChromeIdentityService::GetInstanceFromChromeProvider() ->ForgetIdentity(identity, nil); - [[EarlGrey selectElementWithMatcher:SignInPromoView()] + [[EarlGrey selectElementWithMatcher:SignInMenuButton()] assertWithMatcher:grey_sufficientlyVisible()]; AssertAuthenticatedIdentityInActiveProfile(nil); @@ -266,7 +264,7 @@ performAction:grey_tap()]; // Check that the user is signed out and the Main Settings screen is shown. - [[EarlGrey selectElementWithMatcher:SignInPromoView()] + [[EarlGrey selectElementWithMatcher:SignInMenuButton()] assertWithMatcher:grey_sufficientlyVisible()]; AssertAuthenticatedIdentityInActiveProfile(nil); @@ -300,7 +298,8 @@ performAction:grey_tap()]; // Check that Account Settings screen is open and |identity| is signed in. - [[EarlGrey selectElementWithMatcher:grey_accessibilityID(kSettingsAccountsId)] + [[EarlGrey selectElementWithMatcher:chrome_test_util:: + SettingsAccountsCollectionView()] assertWithMatcher:grey_sufficientlyVisible()]; AssertAuthenticatedIdentityInActiveProfile(identity);
diff --git a/ios/chrome/browser/ui/settings/settings_egtest.mm b/ios/chrome/browser/ui/settings/settings_egtest.mm index 6d5ae00..2f1a430 100644 --- a/ios/chrome/browser/ui/settings/settings_egtest.mm +++ b/ios/chrome/browser/ui/settings/settings_egtest.mm
@@ -21,7 +21,6 @@ #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/content_settings/host_content_settings_map_factory.h" #include "ios/chrome/browser/pref_names.h" -#import "ios/chrome/browser/ui/authentication/signin_promo_view.h" #import "ios/chrome/browser/ui/browser_view_controller.h" #import "ios/chrome/browser/ui/settings/clear_browsing_data_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/settings_collection_view_controller.h" @@ -777,9 +776,8 @@ @"Settings should register key commands when presented."); // Present the Sign-in UI. - id<GREYMatcher> matcher = - grey_allOf(grey_accessibilityID(kSigninPromoPrimaryButtonId), - grey_sufficientlyVisible(), nil); + id<GREYMatcher> matcher = grey_allOf(chrome_test_util::SignInMenuButton(), + grey_sufficientlyVisible(), nil); [[EarlGrey selectElementWithMatcher:matcher] performAction:grey_tap()]; // Wait for UI to finish loading the Sign-in screen. [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
diff --git a/ios/chrome/browser/ui/side_swipe/OWNERS b/ios/chrome/browser/ui/side_swipe/OWNERS index 330cb31..867f7564 100644 --- a/ios/chrome/browser/ui/side_swipe/OWNERS +++ b/ios/chrome/browser/ui/side_swipe/OWNERS
@@ -1 +1,4 @@ justincohen@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/stack_view/OWNERS b/ios/chrome/browser/ui/stack_view/OWNERS index 48efb49e..bd85dcf2 100644 --- a/ios/chrome/browser/ui/stack_view/OWNERS +++ b/ios/chrome/browser/ui/stack_view/OWNERS
@@ -1 +1,4 @@ kkhorimoto@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/sync/BUILD.gn b/ios/chrome/browser/ui/sync/BUILD.gn index de187ce..164c8669 100644 --- a/ios/chrome/browser/ui/sync/BUILD.gn +++ b/ios/chrome/browser/ui/sync/BUILD.gn
@@ -52,7 +52,6 @@ "//ios/chrome/browser/bookmarks:bookmarks_utils", "//ios/chrome/browser/signin", "//ios/chrome/browser/sync", - "//ios/chrome/browser/ui/authentication:authentication_ui", "//ios/chrome/browser/ui/settings", "//ios/chrome/browser/ui/tools_menu", "//ios/chrome/test/app:test_support",
diff --git a/ios/chrome/browser/ui/sync/OWNERS b/ios/chrome/browser/ui/sync/OWNERS index 3431e1a..3f08195 100644 --- a/ios/chrome/browser/ui/sync/OWNERS +++ b/ios/chrome/browser/ui/sync/OWNERS
@@ -1,3 +1,6 @@ msarda@chromium.org # COMPONENT: Services>Sync + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/sync/sync_fake_server_egtest.mm b/ios/chrome/browser/ui/sync/sync_fake_server_egtest.mm index 278d2c5..0c0f325e 100644 --- a/ios/chrome/browser/ui/sync/sync_fake_server_egtest.mm +++ b/ios/chrome/browser/ui/sync/sync_fake_server_egtest.mm
@@ -16,7 +16,6 @@ #include "ios/chrome/browser/signin/authentication_service.h" #include "ios/chrome/browser/signin/authentication_service_factory.h" #include "ios/chrome/browser/sync/ios_chrome_profile_sync_service_factory.h" -#import "ios/chrome/browser/ui/authentication/signin_promo_view.h" #import "ios/chrome/browser/ui/settings/settings_collection_view_controller.h" #include "ios/chrome/browser/ui/tools_menu/tools_menu_constants.h" #import "ios/chrome/browser/ui/tools_menu/tools_popup_controller.h"
diff --git a/ios/chrome/browser/ui/tab_switcher/OWNERS b/ios/chrome/browser/ui/tab_switcher/OWNERS index f16c1db1..e2b64c4 100644 --- a/ios/chrome/browser/ui/tab_switcher/OWNERS +++ b/ios/chrome/browser/ui/tab_switcher/OWNERS
@@ -1,2 +1,5 @@ edchin@chromium.org jif@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/tabs/OWNERS b/ios/chrome/browser/ui/tabs/OWNERS index 40a68c7..b127701 100644 --- a/ios/chrome/browser/ui/tabs/OWNERS +++ b/ios/chrome/browser/ui/tabs/OWNERS
@@ -1 +1,4 @@ rohitrao@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/toolbar/OWNERS b/ios/chrome/browser/ui/toolbar/OWNERS index 3306281..9b78e8b 100644 --- a/ios/chrome/browser/ui/toolbar/OWNERS +++ b/ios/chrome/browser/ui/toolbar/OWNERS
@@ -1,2 +1,5 @@ rohitrao@chromium.org justincohen@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/OWNERS b/ios/chrome/browser/ui/toolbar/keyboard_assist/OWNERS index d2e1add..c85e66a 100644 --- a/ios/chrome/browser/ui/toolbar/keyboard_assist/OWNERS +++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/OWNERS
@@ -1 +1,4 @@ jif@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_controller.h b/ios/chrome/browser/ui/toolbar/toolbar_controller.h index 01b2b6f..412e40a 100644 --- a/ios/chrome/browser/ui/toolbar/toolbar_controller.h +++ b/ios/chrome/browser/ui/toolbar/toolbar_controller.h
@@ -294,6 +294,9 @@ // Shows/hides iPhone toolbar views for when the new tab page is displayed. - (void)hideViewsForNewTabPage:(BOOL)hide; +// Triggers an animation on the tools menu button to draw the user's attention. +- (void)triggerToolsMenuButtonAnimation; + @end #endif // IOS_CHROME_BROWSER_UI_TOOLBAR_TOOLBAR_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_controller.mm b/ios/chrome/browser/ui/toolbar/toolbar_controller.mm index 5fbf638a9..ba069b311 100644 --- a/ios/chrome/browser/ui/toolbar/toolbar_controller.mm +++ b/ios/chrome/browser/ui/toolbar/toolbar_controller.mm
@@ -1040,6 +1040,10 @@ return hash; } +- (void)triggerToolsMenuButtonAnimation { + [toolsMenuButton_ triggerAnimation]; +} + #pragma mark - #pragma mark PopupMenuDelegate methods.
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm b/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm index bd0d13e..e681448 100644 --- a/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm +++ b/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm
@@ -173,6 +173,12 @@ EARL_GREY_TEST_SKIPPED(@"Test not support on iPhone"); } + // TODO(crbug.com/753098): Re-enable this test on iOS 11 iPad once + // grey_typeText works on iOS 11. + if (base::ios::IsRunningOnIOS11OrLater()) { + EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 11."); + } + const GURL URL = web::test::HttpServer::MakeUrl("http://origin"); [ChromeEarlGrey loadURL:URL]; @@ -320,6 +326,12 @@ // Verifies that the clear text button clears any text in the omnibox. - (void)testOmniboxClearTextButton { + // TODO(crbug.com/753098): Re-enable this test on iOS 11 iPad once + // grey_typeText works on iOS 11. + if (base::ios::IsRunningOnIOS11OrLater() && IsIPadIdiom()) { + EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 11."); + } + const GURL URL = web::test::HttpServer::MakeUrl("http://origin"); [ChromeEarlGrey loadURL:URL];
diff --git a/ios/chrome/browser/ui/tools_menu/OWNERS b/ios/chrome/browser/ui/tools_menu/OWNERS index 67c824d2..403665e 100644 --- a/ios/chrome/browser/ui/tools_menu/OWNERS +++ b/ios/chrome/browser/ui/tools_menu/OWNERS
@@ -1,2 +1,5 @@ rohitrao@chromium.org jif@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/tools_menu/tools_menu_configuration.h b/ios/chrome/browser/ui/tools_menu/tools_menu_configuration.h index 66e1049..41aaaa8 100644 --- a/ios/chrome/browser/ui/tools_menu/tools_menu_configuration.h +++ b/ios/chrome/browser/ui/tools_menu/tools_menu_configuration.h
@@ -32,6 +32,8 @@ @property(nonatomic, getter=isInNewTabPage) BOOL inNewTabPage; // Indicates that the menu should show a "NEW" badge on the reading list item. @property(nonatomic, assign) BOOL showReadingListNewBadge; +// Indicates that the New Incognito Tab cell should be highlighted in blue. +@property(nonatomic, assign) BOOL highlightNewIncognitoTabCell; // Indicates that the menu is being shown while user agent is |userAgentType|. // If NONE, shows "Request Desktop Site" in disabled state.
diff --git a/ios/chrome/browser/ui/tools_menu/tools_menu_configuration.mm b/ios/chrome/browser/ui/tools_menu/tools_menu_configuration.mm index 441b491..fdd6309 100644 --- a/ios/chrome/browser/ui/tools_menu/tools_menu_configuration.mm +++ b/ios/chrome/browser/ui/tools_menu/tools_menu_configuration.mm
@@ -18,6 +18,7 @@ @synthesize noOpenedTabs = _noOpenedTabs; @synthesize inIncognito = _inIncognito; @synthesize showReadingListNewBadge = _showReadingListNewBadge; +@synthesize highlightNewIncognitoTabCell = _highlightNewIncognitoTabCell; @synthesize userAgentType = _userAgentType; @synthesize requestStartTime = _requestStartTime; @synthesize inNewTabPage = _inNewTabPage;
diff --git a/ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.h b/ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.h index 8e7ff99..fbd9762 100644 --- a/ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.h +++ b/ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.h
@@ -98,6 +98,10 @@ - (void)hideContent; +// Highlight the New Incognito Tab cell in blue. The highlight fades in, pulses +// once, and fades out. +- (void)triggerNewIncognitoTabCellHighlight; + @end #endif // IOS_CHROME_BROWSER_UI_TOOLS_MENU_TOOLS_MENU_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.mm b/ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.mm index 920ff87..0a2db26 100644 --- a/ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.mm +++ b/ios/chrome/browser/ui/tools_menu/tools_menu_view_controller.mm
@@ -15,6 +15,7 @@ #include "components/strings/grit/components_strings.h" #include "ios/chrome/browser/experimental_flags.h" #import "ios/chrome/browser/ui/animation_util.h" +#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" #import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h" #import "ios/chrome/browser/ui/commands/browser_commands.h" #include "ios/chrome/browser/ui/commands/ios_command_ids.h" @@ -120,6 +121,9 @@ // Determines if the reading list should display a new feature badge. Defaults // to |NO|. @property(nonatomic, assign) BOOL showReadingListNewBadge; +// Indicates whether the New Incognito Tab cell should be highlighted. Defaults +// to |NO|. +@property(nonatomic, assign) BOOL highlightNewIncognitoTabCell; // Tracks events for the purpose of in-product help. Does not take ownership of // tracker. Tracker must not be destroyed during lifetime of // ToolsMenuViewController. Defaults to |NULL|. @@ -139,6 +143,7 @@ @implementation ToolsMenuViewController @synthesize showReadingListNewBadge = _showReadingListNewBadge; +@synthesize highlightNewIncognitoTabCell = _highlightNewIncognitoTabCell; @synthesize engagementTracker = _engagementTracker; @synthesize menuView = _menuView; @synthesize isCurrentPageBookmarked = _isCurrentPageBookmarked; @@ -232,6 +237,8 @@ self.requestStartTime = configuration.requestStartTime; self.showReadingListNewBadge = configuration.showReadingListNewBadge; self.engagementTracker = configuration.engagementTracker; + self.highlightNewIncognitoTabCell = + configuration.highlightNewIncognitoTabCell; if (configuration.readingListMenuNotifier) { _readingListMenuNotifier = configuration.readingListMenuNotifier; @@ -473,6 +480,9 @@ [[self readingListCell] updateSeenState:_readingListMenuNotifier.readingListUnseenItemsExist animated:YES]; + if (self.highlightNewIncognitoTabCell) { + [self triggerNewIncognitoTabCellHighlight]; + } } - (void)hideContent { @@ -678,4 +688,33 @@ [[self readingListCell] updateSeenState:unseenItemsExist animated:YES]; } +#pragma mark - New Incognito Tab in-product help promotion + +- (void)triggerNewIncognitoTabCellHighlight { + for (ToolsMenuViewCell* visibleCell in [_menuView visibleCells]) { + if ([visibleCell.accessibilityIdentifier + isEqualToString:kToolsMenuNewIncognitoTabId]) { + // Set the label's background color to be clear so that the highlight is + // is not covered by the label. + visibleCell.title.backgroundColor = [UIColor clearColor]; + [UIView animateWithDuration:ios::material::kDuration5 + delay:0.0 + options:UIViewAnimationOptionAllowUserInteraction | + UIViewAnimationOptionRepeat | + UIViewAnimationOptionAutoreverse | + UIViewAnimationOptionCurveEaseInOut + animations:^{ + [UIView setAnimationRepeatCount:2]; + visibleCell.contentView.backgroundColor = + [[MDCPalette cr_bluePalette] tint100]; + } + completion:^(BOOL finished) { + visibleCell.contentView.backgroundColor = [UIColor whiteColor]; + }]; + self.highlightNewIncognitoTabCell = NO; + break; + } + } +} + @end
diff --git a/ios/chrome/browser/ui/tools_menu/tools_popup_menu_egtest.mm b/ios/chrome/browser/ui/tools_menu/tools_popup_menu_egtest.mm index ba37230..5c655c4 100644 --- a/ios/chrome/browser/ui/tools_menu/tools_popup_menu_egtest.mm +++ b/ios/chrome/browser/ui/tools_menu/tools_popup_menu_egtest.mm
@@ -53,8 +53,7 @@ performAction:grey_tap()]; } - [[EarlGrey - selectElementWithMatcher:grey_accessibilityID(kToolsMenuTableViewId)] + [[EarlGrey selectElementWithMatcher:chrome_test_util::ToolsMenuView()] assertWithMatcher:grey_notVisible()]; }
diff --git a/ios/chrome/browser/ui/util/OWNERS b/ios/chrome/browser/ui/util/OWNERS index 1f7a7b8..37eb1aa 100644 --- a/ios/chrome/browser/ui/util/OWNERS +++ b/ios/chrome/browser/ui/util/OWNERS
@@ -1,2 +1,5 @@ kkhorimoto@chromium.org marq@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/voice/OWNERS b/ios/chrome/browser/ui/voice/OWNERS index 48efb49e..bd85dcf2 100644 --- a/ios/chrome/browser/ui/voice/OWNERS +++ b/ios/chrome/browser/ui/voice/OWNERS
@@ -1 +1,4 @@ kkhorimoto@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/webui/OWNERS b/ios/chrome/browser/ui/webui/OWNERS index be9def2..11231a36 100644 --- a/ios/chrome/browser/ui/webui/OWNERS +++ b/ios/chrome/browser/ui/webui/OWNERS
@@ -3,3 +3,6 @@ per-file ntp_tiles_internals_ui.*=file://components/ntp_tiles/OWNERS per-file popular_sites_internals_ui.*=file://components/ntp_tiles/OWNERS + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/webui/gcm/OWNERS b/ios/chrome/browser/ui/webui/gcm/OWNERS index 295d996..2271273 100644 --- a/ios/chrome/browser/ui/webui/gcm/OWNERS +++ b/ios/chrome/browser/ui/webui/gcm/OWNERS
@@ -4,3 +4,6 @@ zea@chromium.org # COMPONENT: Services>CloudMessaging + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/webui/net_export/OWNERS b/ios/chrome/browser/ui/webui/net_export/OWNERS index be796293..3d058981 100644 --- a/ios/chrome/browser/ui/webui/net_export/OWNERS +++ b/ios/chrome/browser/ui/webui/net_export/OWNERS
@@ -1,3 +1,6 @@ file://net/OWNERS # COMPONENT: Internals>Network>Logging + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/ui/webui/sync_internals/OWNERS b/ios/chrome/browser/ui/webui/sync_internals/OWNERS index 261ab18..c1575f5 100644 --- a/ios/chrome/browser/ui/webui/sync_internals/OWNERS +++ b/ios/chrome/browser/ui/webui/sync_internals/OWNERS
@@ -1 +1,4 @@ file://components/sync/OWNERS + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/update_client/OWNERS b/ios/chrome/browser/update_client/OWNERS index 75e2f4d..8d0e865 100644 --- a/ios/chrome/browser/update_client/OWNERS +++ b/ios/chrome/browser/update_client/OWNERS
@@ -4,3 +4,6 @@ waffles@chromium.org # COMPONENT: Internals>Installer>Components + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/voice/OWNERS b/ios/chrome/browser/voice/OWNERS index cc50037..2f0d436 100644 --- a/ios/chrome/browser/voice/OWNERS +++ b/ios/chrome/browser/voice/OWNERS
@@ -1,2 +1,5 @@ kkhorimoto@chromium.org rohitrao@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/web/OWNERS b/ios/chrome/browser/web/OWNERS index 5a2923e..1a6c73c 100644 --- a/ios/chrome/browser/web/OWNERS +++ b/ios/chrome/browser/web/OWNERS
@@ -1,2 +1,5 @@ eugenebut@chromium.org # This directory needs to be carved into subdirs with more specific OWNERS. + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/web/resources/OWNERS b/ios/chrome/browser/web/resources/OWNERS index da255e6..7b2fb33 100644 --- a/ios/chrome/browser/web/resources/OWNERS +++ b/ios/chrome/browser/web/resources/OWNERS
@@ -1 +1,4 @@ per-file payment_request.js=mahmadi@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/web_resource/OWNERS b/ios/chrome/browser/web_resource/OWNERS index 50c6bcd4..16d5d98c 100644 --- a/ios/chrome/browser/web_resource/OWNERS +++ b/ios/chrome/browser/web_resource/OWNERS
@@ -1,2 +1,5 @@ achuith@chromium.org rsesek@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/browser/web_state_list/OWNERS b/ios/chrome/browser/web_state_list/OWNERS index c5cd5cb..39066e1 100644 --- a/ios/chrome/browser/web_state_list/OWNERS +++ b/ios/chrome/browser/web_state_list/OWNERS
@@ -1 +1,4 @@ sdefresne@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/common/physical_web/OWNERS b/ios/chrome/common/physical_web/OWNERS index 3ebff38d..56360bb 100644 --- a/ios/chrome/common/physical_web/OWNERS +++ b/ios/chrome/common/physical_web/OWNERS
@@ -1 +1,4 @@ olivierrobin@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/content_widget_extension/OWNERS b/ios/chrome/content_widget_extension/OWNERS index 55fb7e49..2b72d62 100644 --- a/ios/chrome/content_widget_extension/OWNERS +++ b/ios/chrome/content_widget_extension/OWNERS
@@ -1 +1,3 @@ -lod@chromium.org \ No newline at end of file +lod@chromium.org +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/search_widget_extension/OWNERS b/ios/chrome/search_widget_extension/OWNERS index 55fb7e49..2b72d62 100644 --- a/ios/chrome/search_widget_extension/OWNERS +++ b/ios/chrome/search_widget_extension/OWNERS
@@ -1 +1,3 @@ -lod@chromium.org \ No newline at end of file +lod@chromium.org +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/share_extension/OWNERS b/ios/chrome/share_extension/OWNERS index 3ebff38d..56360bb 100644 --- a/ios/chrome/share_extension/OWNERS +++ b/ios/chrome/share_extension/OWNERS
@@ -1 +1,4 @@ olivierrobin@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn index 7a7cbe3..cce1532 100644 --- a/ios/chrome/test/BUILD.gn +++ b/ios/chrome/test/BUILD.gn
@@ -166,6 +166,7 @@ "//ios/chrome/browser/ui/autofill/cells:unit_tests", "//ios/chrome/browser/ui/bookmarks:unit_tests", "//ios/chrome/browser/ui/bookmarks/cells:unit_tests", + "//ios/chrome/browser/ui/browser_list:unit_tests", "//ios/chrome/browser/ui/bubble:unit_tests", "//ios/chrome/browser/ui/collection_view:unit_tests", "//ios/chrome/browser/ui/collection_view/cells:unit_tests", @@ -215,7 +216,6 @@ "//ios/chrome/search_widget_extension:unit_tests", "//ios/chrome/test/base:unit_tests", "//ios/shared/chrome/browser/ui/broadcaster:unit_tests", - "//ios/shared/chrome/browser/ui/browser_list:unit_tests", "//ios/shared/chrome/browser/ui/commands:unit_tests", "//ios/shared/chrome/browser/ui/coordinators:unit_tests", "//ios/shared/chrome/browser/ui/dialogs:unit_tests",
diff --git a/ios/chrome/test/OWNERS b/ios/chrome/test/OWNERS index 1df316e..6f764fe 100644 --- a/ios/chrome/test/OWNERS +++ b/ios/chrome/test/OWNERS
@@ -1 +1,4 @@ baxley@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/test/app/BUILD.gn b/ios/chrome/test/app/BUILD.gn index bdd90add..c689139e 100644 --- a/ios/chrome/test/app/BUILD.gn +++ b/ios/chrome/test/app/BUILD.gn
@@ -67,7 +67,6 @@ "//ios/chrome/browser/sync", "//ios/chrome/browser/tabs", "//ios/chrome/browser/ui:ui_internal", - "//ios/chrome/browser/ui/authentication:authentication_ui", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/main", "//ios/chrome/browser/ui/ntp:ntp_controller",
diff --git a/ios/chrome/test/app/signin_test_util.h b/ios/chrome/test/app/signin_test_util.h index b60ada3..1f9fcfa3 100644 --- a/ios/chrome/test/app/signin_test_util.h +++ b/ios/chrome/test/app/signin_test_util.h
@@ -25,10 +25,6 @@ // the accounts were correctly removed from the keychain. bool SignOutAndClearAccounts(); -// Resets Sign-in promo impression preferences for bookmarks and settings view, -// and resets kIosBookmarkPromoAlreadySeen flag for bookmarks. -void ResetSigninPromoPreferences(); - } // namespace chrome_test_util #endif // IOS_CHROME_TEST_APP_SIGNIN_TEST_UTIL_H_
diff --git a/ios/chrome/test/app/signin_test_util.mm b/ios/chrome/test/app/signin_test_util.mm index 096390c..8fc529e4 100644 --- a/ios/chrome/test/app/signin_test_util.mm +++ b/ios/chrome/test/app/signin_test_util.mm
@@ -12,12 +12,10 @@ #include "components/signin/core/common/signin_pref_names.h" #include "google_apis/gaia/gaia_constants.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" -#include "ios/chrome/browser/pref_names.h" #include "ios/chrome/browser/signin/account_tracker_service_factory.h" #import "ios/chrome/browser/signin/authentication_service.h" #include "ios/chrome/browser/signin/authentication_service_factory.h" #include "ios/chrome/browser/signin/gaia_auth_fetcher_ios.h" -#import "ios/chrome/browser/ui/authentication/signin_promo_view.h" #import "ios/chrome/test/app/chrome_test_util.h" #import "ios/public/provider/chrome/browser/chrome_browser_provider.h" #import "ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h" @@ -174,12 +172,4 @@ return !identity_service->HasIdentities(); } -void ResetSigninPromoPreferences() { - ios::ChromeBrowserState* browser_state = GetOriginalBrowserState(); - PrefService* prefs = browser_state->GetPrefs(); - prefs->SetInteger(prefs::kIosBookmarkSigninPromoDisplayedCount, 0); - prefs->SetBoolean(prefs::kIosBookmarkPromoAlreadySeen, false); - prefs->SetInteger(prefs::kIosSettingsSigninPromoDisplayedCount, 0); -} - } // namespace chrome_test_util
diff --git a/ios/chrome/test/data/OWNERS b/ios/chrome/test/data/OWNERS index 72e8ffc..d03d28b 100644 --- a/ios/chrome/test/data/OWNERS +++ b/ios/chrome/test/data/OWNERS
@@ -1 +1,4 @@ * + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/test/earl_grey/BUILD.gn b/ios/chrome/test/earl_grey/BUILD.gn index ceb5f1e..bee6b5d 100644 --- a/ios/chrome/test/earl_grey/BUILD.gn +++ b/ios/chrome/test/earl_grey/BUILD.gn
@@ -179,12 +179,10 @@ deps = [ "//base", "//base/test:test_support", - "//components/signin/core/common", "//components/strings", "//ios/chrome/app/strings", "//ios/chrome/browser/ui", "//ios/chrome/browser/ui/authentication:authentication", - "//ios/chrome/browser/ui/authentication:authentication_ui", "//ios/chrome/browser/ui/collection_view/cells", "//ios/chrome/browser/ui/commands:commands", "//ios/chrome/browser/ui/omnibox:omnibox_internal",
diff --git a/ios/chrome/test/earl_grey/OWNERS b/ios/chrome/test/earl_grey/OWNERS index 86cd262..b69f0d0 100644 --- a/ios/chrome/test/earl_grey/OWNERS +++ b/ios/chrome/test/earl_grey/OWNERS
@@ -1,2 +1,5 @@ baxley@chromium.org liaoyuke@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/chrome/test/earl_grey/chrome_matchers.h b/ios/chrome/test/earl_grey/chrome_matchers.h index 0b4e542..adb7a10 100644 --- a/ios/chrome/test/earl_grey/chrome_matchers.h +++ b/ios/chrome/test/earl_grey/chrome_matchers.h
@@ -101,12 +101,12 @@ // Returns matcher for the settings button in the tools menu. id<GREYMatcher> SettingsMenuButton(); +// Returns matcher for the tools menu table view. +id<GREYMatcher> ToolsMenuView(); + // Returns matcher for the OK button. id<GREYMatcher> OKButton(); -// Returns matcher for the sign-in promo view in the settings menu. -id<GREYMatcher> SignInPromoView(); - // Returns matcher for the signin button in the settings menu. id<GREYMatcher> SignInMenuButton(); @@ -114,6 +114,15 @@ // settings menu. id<GREYMatcher> SettingsAccountButton(); +// Returns matcher for the accounts collection view. +id<GREYMatcher> SettingsAccountsCollectionView(); + +// Returns matcher for the Import Data cell in switch sync account view. +id<GREYMatcher> SettingsImportDataImportButton(); + +// Returns matcher for the Keep Data Separate cell in switch sync account view. +id<GREYMatcher> SettingsImportDataKeepSeparateButton(); + // Returns matcher for the menu button to sync accounts. id<GREYMatcher> AccountsSyncButton();
diff --git a/ios/chrome/test/earl_grey/chrome_matchers.mm b/ios/chrome/test/earl_grey/chrome_matchers.mm index addbce3..618018a1 100644 --- a/ios/chrome/test/earl_grey/chrome_matchers.mm +++ b/ios/chrome/test/earl_grey/chrome_matchers.mm
@@ -12,11 +12,11 @@ #include "base/strings/sys_string_conversions.h" #import "base/test/ios/wait_util.h" #include "components/strings/grit/components_strings.h" -#import "ios/chrome/browser/ui/authentication/signin_promo_view.h" #import "ios/chrome/browser/ui/collection_view/cells/collection_view_switch_item.h" #import "ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h" #import "ios/chrome/browser/ui/settings/accounts_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/clear_browsing_data_collection_view_controller.h" +#import "ios/chrome/browser/ui/settings/import_data_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/settings_collection_view_controller.h" #import "ios/chrome/browser/ui/static_content/static_html_view_controller.h" #import "ios/chrome/browser/ui/toolbar/toolbar_controller.h" @@ -190,22 +190,34 @@ return grey_accessibilityID(kToolsMenuSettingsId); } +id<GREYMatcher> ToolsMenuView() { + return grey_accessibilityID(kToolsMenuTableViewId); +} + id<GREYMatcher> OKButton() { return ButtonWithAccessibilityLabelId(IDS_OK); } -id<GREYMatcher> SignInPromoView() { - return grey_accessibilityID(kSigninPromoViewId); -} - id<GREYMatcher> SignInMenuButton() { - return grey_accessibilityID(kSigninPromoSecondaryButtonId); + return grey_accessibilityID(kSettingsSignInCellId); } id<GREYMatcher> SettingsAccountButton() { return grey_accessibilityID(kSettingsAccountCellId); } +id<GREYMatcher> SettingsAccountsCollectionView() { + return grey_accessibilityID(kSettingsAccountsId); +} + +id<GREYMatcher> SettingsImportDataImportButton() { + return grey_accessibilityID(kImportDataImportCellId); +} + +id<GREYMatcher> SettingsImportDataKeepSeparateButton() { + return grey_accessibilityID(kImportDataKeepSeparateCellId); +} + id<GREYMatcher> AccountsSyncButton() { return grey_accessibilityID(kSettingsAccountsSyncCellId); }
diff --git a/ios/chrome/test/earl_grey/chrome_test_case.mm b/ios/chrome/test/earl_grey/chrome_test_case.mm index 4aaf058..6da92b8 100644 --- a/ios/chrome/test/earl_grey/chrome_test_case.mm +++ b/ios/chrome/test/earl_grey/chrome_test_case.mm
@@ -8,10 +8,8 @@ #import <EarlGrey/EarlGrey.h> -#include "base/command_line.h" #include "base/mac/scoped_block.h" #include "base/strings/sys_string_conversions.h" -#include "components/signin/core/common/signin_switches.h" #import "ios/chrome/test/app/chrome_test_util.h" #include "ios/chrome/test/app/settings_test_util.h" #include "ios/chrome/test/app/signin_test_util.h" @@ -165,7 +163,6 @@ _isMockAuthenticationDisabled = NO; _tearDownHandler = nil; - chrome_test_util::ResetSigninPromoPreferences(); chrome_test_util::OpenNewTab(); [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; } @@ -250,11 +247,6 @@ } + (void)enableMockAuthentication { - // Enable sign-in promo for all tests. - // TODO(crbug.com/739910): Remove this line when the sign-in promo is enabled - // by default. - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableSigninPromo); chrome_test_util::SetUpMockAuthentication(); chrome_test_util::SetUpMockAccountReconcilor(); chrome_test_util::SetUpFakeSyncServer();
diff --git a/ios/chrome/today_extension/OWNERS b/ios/chrome/today_extension/OWNERS index 3ebff38d..56360bb 100644 --- a/ios/chrome/today_extension/OWNERS +++ b/ios/chrome/today_extension/OWNERS
@@ -1 +1,4 @@ olivierrobin@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/clean/OWNERS b/ios/clean/OWNERS index 6d63668..d846ad4fa 100644 --- a/ios/clean/OWNERS +++ b/ios/clean/OWNERS
@@ -1,3 +1,6 @@ edchin@chromium.org lpromero@chromium.org marq@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/clean/chrome/app/steps/BUILD.gn b/ios/clean/chrome/app/steps/BUILD.gn index a9a6b5e..c6640336 100644 --- a/ios/clean/chrome/app/steps/BUILD.gn +++ b/ios/clean/chrome/app/steps/BUILD.gn
@@ -55,11 +55,11 @@ "//ios/chrome/browser/browser_state", "//ios/chrome/browser/browser_state:browser_state_impl", "//ios/chrome/browser/content_settings", + "//ios/chrome/browser/ui/browser_list", "//ios/chrome/browser/web:web_internal", "//ios/chrome/browser/web_state_list", "//ios/clean/chrome/browser/ui/root", "//ios/net", - "//ios/shared/chrome/browser/ui/browser_list", "//ios/shared/chrome/browser/ui/coordinators", "//ios/web:web_arc", ]
diff --git a/ios/clean/chrome/app/steps/root_coordinator+application_step.mm b/ios/clean/chrome/app/steps/root_coordinator+application_step.mm index ac306df..29ce960 100644 --- a/ios/clean/chrome/app/steps/root_coordinator+application_step.mm +++ b/ios/clean/chrome/app/steps/root_coordinator+application_step.mm
@@ -7,13 +7,13 @@ #include "base/memory/ptr_util.h" #include "base/supports_user_data.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" +#import "ios/chrome/browser/ui/browser_list/browser.h" +#import "ios/chrome/browser/ui/browser_list/browser_list.h" +#import "ios/chrome/browser/ui/browser_list/browser_list_session_service.h" +#import "ios/chrome/browser/ui/browser_list/browser_list_session_service_factory.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/chrome/browser/web_state_list/web_state_opener.h" #import "ios/clean/chrome/app/application_state.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser_list.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser_list_session_service.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser_list_session_service_factory.h" #import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator+internal.h" #import "ios/web/public/navigation_manager.h" #include "ios/web/public/web_state/web_state.h"
diff --git a/ios/clean/chrome/app/steps/root_coordinator_initializer.mm b/ios/clean/chrome/app/steps/root_coordinator_initializer.mm index d098a546..0feba6b 100644 --- a/ios/clean/chrome/app/steps/root_coordinator_initializer.mm +++ b/ios/clean/chrome/app/steps/root_coordinator_initializer.mm
@@ -7,14 +7,14 @@ #import "ios/chrome/app/startup/provider_registration.h" #include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" +#import "ios/chrome/browser/ui/browser_list/browser_list.h" +#import "ios/chrome/browser/ui/browser_list/browser_list_session_service.h" +#import "ios/chrome/browser/ui/browser_list/browser_list_session_service_factory.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/chrome/browser/web_state_list/web_state_opener.h" #import "ios/clean/chrome/app/steps/step_context.h" #import "ios/clean/chrome/app/steps/step_features.h" #import "ios/clean/chrome/browser/ui/root/root_coordinator.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser_list.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser_list_session_service.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser_list_session_service_factory.h" #import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator+internal.h" #include "ios/web/public/web_state/web_state.h"
diff --git a/ios/clean/chrome/browser/ui/bookmarks/BUILD.gn b/ios/clean/chrome/browser/ui/bookmarks/BUILD.gn index dec4e7694..591d83f 100644 --- a/ios/clean/chrome/browser/ui/bookmarks/BUILD.gn +++ b/ios/clean/chrome/browser/ui/bookmarks/BUILD.gn
@@ -13,7 +13,7 @@ deps = [ "//ios/chrome/browser/ui", "//ios/chrome/browser/ui/bookmarks", - "//ios/shared/chrome/browser/ui/browser_list", + "//ios/chrome/browser/ui/browser_list", "//ios/shared/chrome/browser/ui/coordinators", ] }
diff --git a/ios/clean/chrome/browser/ui/bookmarks/bookmarks_coordinator.mm b/ios/clean/chrome/browser/ui/bookmarks/bookmarks_coordinator.mm index 2a3a6f0..63b16bc 100644 --- a/ios/clean/chrome/browser/ui/bookmarks/bookmarks_coordinator.mm +++ b/ios/clean/chrome/browser/ui/bookmarks/bookmarks_coordinator.mm
@@ -7,8 +7,8 @@ #import "ios/chrome/browser/ui/bookmarks/bookmark_controller_factory.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_home_handset_view_controller.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_home_tablet_ntp_controller.h" +#import "ios/chrome/browser/ui/browser_list/browser.h" #include "ios/chrome/browser/ui/ui_util.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser.h" #import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator+internal.h" #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/clean/chrome/browser/ui/context_menu/BUILD.gn b/ios/clean/chrome/browser/ui/context_menu/BUILD.gn index 75ed85b0..ec87bff 100644 --- a/ios/clean/chrome/browser/ui/context_menu/BUILD.gn +++ b/ios/clean/chrome/browser/ui/context_menu/BUILD.gn
@@ -16,9 +16,9 @@ deps = [ ":context_menu_ui", + "//ios/chrome/browser/ui/browser_list", "//ios/chrome/browser/web_state_list:web_state_list", "//ios/clean/chrome/browser/ui/commands:commands", - "//ios/shared/chrome/browser/ui/browser_list", "//ios/shared/chrome/browser/ui/commands", "//ios/shared/chrome/browser/ui/coordinators", "//ios/web",
diff --git a/ios/clean/chrome/browser/ui/context_menu/context_menu_mediator.mm b/ios/clean/chrome/browser/ui/context_menu/context_menu_mediator.mm index fe17c57..2c5d24b 100644 --- a/ios/clean/chrome/browser/ui/context_menu/context_menu_mediator.mm +++ b/ios/clean/chrome/browser/ui/context_menu/context_menu_mediator.mm
@@ -4,10 +4,10 @@ #import "ios/clean/chrome/browser/ui/context_menu/context_menu_mediator.h" +#import "ios/chrome/browser/ui/browser_list/browser.h" #import "ios/clean/chrome/browser/ui/commands/context_menu_commands.h" #import "ios/clean/chrome/browser/ui/context_menu/context_menu_consumer.h" #import "ios/clean/chrome/browser/ui/context_menu/context_menu_context_impl.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser.h" #import "ios/web/public/url_scheme_util.h" #include "url/gurl.h"
diff --git a/ios/clean/chrome/browser/ui/context_menu/web_context_menu_coordinator.mm b/ios/clean/chrome/browser/ui/context_menu/web_context_menu_coordinator.mm index a86ea59..253777b 100644 --- a/ios/clean/chrome/browser/ui/context_menu/web_context_menu_coordinator.mm +++ b/ios/clean/chrome/browser/ui/context_menu/web_context_menu_coordinator.mm
@@ -5,11 +5,11 @@ #import "ios/clean/chrome/browser/ui/context_menu/web_context_menu_coordinator.h" #include "base/logging.h" +#import "ios/chrome/browser/ui/browser_list/browser.h" #import "ios/clean/chrome/browser/ui/commands/context_menu_commands.h" #import "ios/clean/chrome/browser/ui/context_menu/context_menu_context_impl.h" #import "ios/clean/chrome/browser/ui/context_menu/context_menu_mediator.h" #import "ios/clean/chrome/browser/ui/context_menu/context_menu_view_controller.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser.h" #import "ios/shared/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator+internal.h"
diff --git a/ios/clean/chrome/browser/ui/find_in_page/BUILD.gn b/ios/clean/chrome/browser/ui/find_in_page/BUILD.gn index dccbfe0..918c16d 100644 --- a/ios/clean/chrome/browser/ui/find_in_page/BUILD.gn +++ b/ios/clean/chrome/browser/ui/find_in_page/BUILD.gn
@@ -16,11 +16,11 @@ ":find_in_page_ui", "//base", "//ios/chrome/browser/find_in_page", + "//ios/chrome/browser/ui/browser_list", "//ios/chrome/browser/web_state_list", "//ios/clean/chrome/browser", "//ios/clean/chrome/browser/ui/actions", "//ios/clean/chrome/browser/ui/commands", - "//ios/shared/chrome/browser/ui/browser_list", "//ios/shared/chrome/browser/ui/commands", "//ios/shared/chrome/browser/ui/coordinators", "//ios/web",
diff --git a/ios/clean/chrome/browser/ui/find_in_page/find_in_page_coordinator.mm b/ios/clean/chrome/browser/ui/find_in_page/find_in_page_coordinator.mm index 14acfc1..01ec12e 100644 --- a/ios/clean/chrome/browser/ui/find_in_page/find_in_page_coordinator.mm +++ b/ios/clean/chrome/browser/ui/find_in_page/find_in_page_coordinator.mm
@@ -8,11 +8,11 @@ #include "base/logging.h" #import "ios/chrome/browser/find_in_page/find_tab_helper.h" +#import "ios/chrome/browser/ui/browser_list/browser.h" #include "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/clean/chrome/browser/ui/commands/find_in_page_visibility_commands.h" #import "ios/clean/chrome/browser/ui/find_in_page/find_in_page_mediator.h" #import "ios/clean/chrome/browser/ui/find_in_page/find_in_page_view_controller.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser.h" #import "ios/shared/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator+internal.h"
diff --git a/ios/clean/chrome/browser/ui/ntp/BUILD.gn b/ios/clean/chrome/browser/ui/ntp/BUILD.gn index a774196f..d1972ca 100644 --- a/ios/clean/chrome/browser/ui/ntp/BUILD.gn +++ b/ios/clean/chrome/browser/ui/ntp/BUILD.gn
@@ -32,6 +32,7 @@ "//ios/chrome/browser/reading_list", "//ios/chrome/browser/ui", "//ios/chrome/browser/ui/alert_coordinator", + "//ios/chrome/browser/ui/browser_list", "//ios/chrome/browser/ui/content_suggestions", "//ios/chrome/browser/ui/content_suggestions:content_suggestions_util", "//ios/chrome/browser/ui/content_suggestions/cells", @@ -42,7 +43,6 @@ "//ios/clean/chrome/browser/ui/bookmarks", "//ios/clean/chrome/browser/ui/commands", "//ios/clean/chrome/browser/ui/recent_tabs", - "//ios/shared/chrome/browser/ui/browser_list", "//ios/shared/chrome/browser/ui/commands", "//ios/shared/chrome/browser/ui/coordinators", "//ios/web:web_arc",
diff --git a/ios/clean/chrome/browser/ui/ntp/ntp_coordinator.mm b/ios/clean/chrome/browser/ui/ntp/ntp_coordinator.mm index 3380b4e..365ab19 100644 --- a/ios/clean/chrome/browser/ui/ntp/ntp_coordinator.mm +++ b/ios/clean/chrome/browser/ui/ntp/ntp_coordinator.mm
@@ -5,6 +5,7 @@ #import "ios/clean/chrome/browser/ui/ntp/ntp_coordinator.h" #include "base/logging.h" +#import "ios/chrome/browser/ui/browser_list/browser.h" #include "ios/chrome/browser/ui/ui_util.h" #import "ios/clean/chrome/browser/ui/bookmarks/bookmarks_coordinator.h" #import "ios/clean/chrome/browser/ui/commands/ntp_commands.h" @@ -12,7 +13,6 @@ #import "ios/clean/chrome/browser/ui/ntp/ntp_mediator.h" #import "ios/clean/chrome/browser/ui/ntp/ntp_view_controller.h" #import "ios/clean/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser.h" #import "ios/shared/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator+internal.h"
diff --git a/ios/clean/chrome/browser/ui/ntp/ntp_home_coordinator.mm b/ios/clean/chrome/browser/ui/ntp/ntp_home_coordinator.mm index ce336ed..19a27c76 100644 --- a/ios/clean/chrome/browser/ui/ntp/ntp_home_coordinator.mm +++ b/ios/clean/chrome/browser/ui/ntp/ntp_home_coordinator.mm
@@ -20,6 +20,7 @@ #include "ios/chrome/browser/ntp_tiles/ios_most_visited_sites_factory.h" #include "ios/chrome/browser/reading_list/reading_list_model_factory.h" #import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h" +#import "ios/chrome/browser/ui/browser_list/browser.h" #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_gesture_commands.h" #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.h" #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.h" @@ -38,7 +39,6 @@ #import "ios/chrome/browser/ui/uikit_ui_util.h" #include "ios/chrome/grit/ios_strings.h" #import "ios/clean/chrome/browser/ui/ntp/ntp_home_header_coordinator.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser.h" #import "ios/shared/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator+internal.h" #import "ios/third_party/material_components_ios/src/components/Snackbar/src/MaterialSnackbar.h"
diff --git a/ios/clean/chrome/browser/ui/omnibox/BUILD.gn b/ios/clean/chrome/browser/ui/omnibox/BUILD.gn index 44ddf1a96..1b75b9f 100644 --- a/ios/clean/chrome/browser/ui/omnibox/BUILD.gn +++ b/ios/clean/chrome/browser/ui/omnibox/BUILD.gn
@@ -14,11 +14,11 @@ "//base", "//components/toolbar", "//ios/chrome/browser/ssl", + "//ios/chrome/browser/ui/browser_list", "//ios/chrome/browser/ui/omnibox:omnibox_internal", "//ios/chrome/browser/ui/toolbar", "//ios/chrome/browser/web_state_list", "//ios/clean/chrome/browser", - "//ios/shared/chrome/browser/ui/browser_list", "//ios/shared/chrome/browser/ui/coordinators", "//ios/shared/chrome/browser/ui/omnibox", "//ios/web",
diff --git a/ios/clean/chrome/browser/ui/omnibox/location_bar_coordinator.mm b/ios/clean/chrome/browser/ui/omnibox/location_bar_coordinator.mm index 2880d51..4e5ab50 100644 --- a/ios/clean/chrome/browser/ui/omnibox/location_bar_coordinator.mm +++ b/ios/clean/chrome/browser/ui/omnibox/location_bar_coordinator.mm
@@ -5,11 +5,11 @@ #import "ios/clean/chrome/browser/ui/omnibox/location_bar_coordinator.h" #include "base/memory/ptr_util.h" +#import "ios/chrome/browser/ui/browser_list/browser.h" #import "ios/chrome/browser/ui/omnibox/location_bar_controller_impl.h" #include "ios/chrome/browser/ui/toolbar/toolbar_model_ios.h" #import "ios/clean/chrome/browser/ui/omnibox/location_bar_mediator.h" #import "ios/clean/chrome/browser/ui/omnibox/location_bar_view_controller.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser.h" #import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator+internal.h" #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/clean/chrome/browser/ui/recent_tabs/BUILD.gn b/ios/clean/chrome/browser/ui/recent_tabs/BUILD.gn index 0ebc0e4..0fc25c9 100644 --- a/ios/clean/chrome/browser/ui/recent_tabs/BUILD.gn +++ b/ios/clean/chrome/browser/ui/recent_tabs/BUILD.gn
@@ -12,8 +12,8 @@ deps = [ "//ios/chrome/browser/ui", + "//ios/chrome/browser/ui/browser_list", "//ios/chrome/browser/ui/ntp/recent_tabs", - "//ios/shared/chrome/browser/ui/browser_list", "//ios/shared/chrome/browser/ui/coordinators", ] }
diff --git a/ios/clean/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.mm b/ios/clean/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.mm index 12ca148..d7bd8ceb 100644 --- a/ios/clean/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.mm +++ b/ios/clean/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.mm
@@ -4,10 +4,10 @@ #import "ios/clean/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.h" +#import "ios/chrome/browser/ui/browser_list/browser.h" #import "ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_panel_controller.h" #import "ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_panel_view_controller.h" #include "ios/chrome/browser/ui/ui_util.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser.h" #import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator+internal.h" #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/clean/chrome/browser/ui/root/BUILD.gn b/ios/clean/chrome/browser/ui/root/BUILD.gn index d499ecd..c9c6460 100644 --- a/ios/clean/chrome/browser/ui/root/BUILD.gn +++ b/ios/clean/chrome/browser/ui/root/BUILD.gn
@@ -9,10 +9,10 @@ ] deps = [ ":root_ui", + "//ios/chrome/browser/ui/browser_list", "//ios/clean/chrome/browser", "//ios/clean/chrome/browser/ui/commands", "//ios/clean/chrome/browser/ui/tab_grid", - "//ios/shared/chrome/browser/ui/browser_list", "//ios/shared/chrome/browser/ui/commands", "//ios/shared/chrome/browser/ui/coordinators", ]
diff --git a/ios/clean/chrome/browser/ui/root/root_coordinator.mm b/ios/clean/chrome/browser/ui/root/root_coordinator.mm index 289e2700..12de61a 100644 --- a/ios/clean/chrome/browser/ui/root/root_coordinator.mm +++ b/ios/clean/chrome/browser/ui/root/root_coordinator.mm
@@ -8,9 +8,9 @@ #error "This file requires ARC support." #endif +#import "ios/chrome/browser/ui/browser_list/browser.h" #import "ios/clean/chrome/browser/ui/root/root_container_view_controller.h" #import "ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser.h" #import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator+internal.h" #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/clean/chrome/browser/ui/settings/BUILD.gn b/ios/clean/chrome/browser/ui/settings/BUILD.gn index fae4fa0..ddace90 100644 --- a/ios/clean/chrome/browser/ui/settings/BUILD.gn +++ b/ios/clean/chrome/browser/ui/settings/BUILD.gn
@@ -17,10 +17,10 @@ deps = [ "//base:base", "//ios/chrome/browser/browser_state", + "//ios/chrome/browser/ui/browser_list", "//ios/chrome/browser/ui/settings", "//ios/clean/chrome/browser/ui/actions", "//ios/clean/chrome/browser/ui/commands", - "//ios/shared/chrome/browser/ui/browser_list", "//ios/shared/chrome/browser/ui/commands", "//ios/shared/chrome/browser/ui/coordinators", ] @@ -37,8 +37,8 @@ deps = [ ":settings", "//ios/chrome/browser/browser_state:test_support", + "//ios/chrome/browser/ui/browser_list", "//ios/chrome/browser/ui/settings", - "//ios/shared/chrome/browser/ui/browser_list", "//ios/shared/chrome/browser/ui/coordinators:test_support", "//testing/gtest", ]
diff --git a/ios/clean/chrome/browser/ui/settings/settings_coordinator.mm b/ios/clean/chrome/browser/ui/settings/settings_coordinator.mm index 8194051..26958214 100644 --- a/ios/clean/chrome/browser/ui/settings/settings_coordinator.mm +++ b/ios/clean/chrome/browser/ui/settings/settings_coordinator.mm
@@ -6,10 +6,10 @@ #include "base/logging.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" +#import "ios/chrome/browser/ui/browser_list/browser.h" #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h" #import "ios/clean/chrome/browser/ui/commands/settings_commands.h" #import "ios/clean/chrome/browser/ui/settings/settings_main_page_coordinator.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser.h" #import "ios/shared/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator+internal.h"
diff --git a/ios/clean/chrome/browser/ui/settings/settings_main_page_coordinator.mm b/ios/clean/chrome/browser/ui/settings/settings_main_page_coordinator.mm index e89125d..f8cb709f 100644 --- a/ios/clean/chrome/browser/ui/settings/settings_main_page_coordinator.mm +++ b/ios/clean/chrome/browser/ui/settings/settings_main_page_coordinator.mm
@@ -6,9 +6,9 @@ #include "base/logging.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" +#import "ios/chrome/browser/ui/browser_list/browser.h" #import "ios/chrome/browser/ui/settings/settings_collection_view_controller.h" #import "ios/clean/chrome/browser/ui/settings/material_cell_catalog_coordinator.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser.h" #import "ios/shared/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator+internal.h" #import "ios/shared/chrome/browser/ui/settings/settings_main_page_commands.h"
diff --git a/ios/clean/chrome/browser/ui/tab/BUILD.gn b/ios/clean/chrome/browser/ui/tab/BUILD.gn index 5bc2d72..d04dfb4 100644 --- a/ios/clean/chrome/browser/ui/tab/BUILD.gn +++ b/ios/clean/chrome/browser/ui/tab/BUILD.gn
@@ -16,6 +16,7 @@ ":tab_ui", "//base", "//ios/chrome/browser", + "//ios/chrome/browser/ui/browser_list", "//ios/chrome/browser/web_state_list", "//ios/clean/chrome/browser/ui/actions", "//ios/clean/chrome/browser/ui/commands", @@ -26,7 +27,6 @@ "//ios/clean/chrome/browser/ui/transitions", "//ios/clean/chrome/browser/ui/web_contents", "//ios/shared/chrome/browser/ui/broadcaster", - "//ios/shared/chrome/browser/ui/browser_list", "//ios/shared/chrome/browser/ui/commands", "//ios/shared/chrome/browser/ui/coordinators", "//ios/web", @@ -64,8 +64,8 @@ ":tab", ":tab_ui", "//base", + "//ios/chrome/browser/ui/browser_list", "//ios/chrome/browser/ui/toolbar/test", - "//ios/shared/chrome/browser/ui/browser_list", "//ios/shared/chrome/browser/ui/coordinators", "//ios/shared/chrome/browser/ui/coordinators:test_support", "//ios/shared/chrome/browser/ui/tab:test_support",
diff --git a/ios/clean/chrome/browser/ui/tab/tab_coordinator.mm b/ios/clean/chrome/browser/ui/tab/tab_coordinator.mm index a29ecb7b..01e9139c 100644 --- a/ios/clean/chrome/browser/ui/tab/tab_coordinator.mm +++ b/ios/clean/chrome/browser/ui/tab/tab_coordinator.mm
@@ -10,6 +10,7 @@ #include "base/memory/ptr_util.h" #include "base/scoped_observer.h" #include "ios/chrome/browser/chrome_url_constants.h" +#import "ios/chrome/browser/ui/browser_list/browser.h" #include "ios/chrome/browser/web_state_list/web_state_list.h" #include "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h" #import "ios/clean/chrome/browser/ui/commands/tab_commands.h" @@ -23,7 +24,6 @@ #import "ios/clean/chrome/browser/ui/transitions/zoom_transition_controller.h" #import "ios/clean/chrome/browser/ui/web_contents/web_coordinator.h" #import "ios/shared/chrome/browser/ui/broadcaster/chrome_broadcaster.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser.h" #import "ios/shared/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator+internal.h" #import "ios/web/public/web_state/web_state.h"
diff --git a/ios/clean/chrome/browser/ui/tab/tab_coordinator_unittest.mm b/ios/clean/chrome/browser/ui/tab/tab_coordinator_unittest.mm index 5ac4ca8a..5b4f1fe 100644 --- a/ios/clean/chrome/browser/ui/tab/tab_coordinator_unittest.mm +++ b/ios/clean/chrome/browser/ui/tab/tab_coordinator_unittest.mm
@@ -7,9 +7,9 @@ #include "base/memory/ptr_util.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#import "ios/chrome/browser/ui/browser_list/browser.h" #import "ios/chrome/browser/ui/toolbar/test/toolbar_test_web_state.h" #import "ios/clean/chrome/browser/ui/tab/tab_container_view_controller.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser.h" #import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator+internal.h" #import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator_test.h" #import "ios/shared/chrome/browser/ui/tab/tab_test_util.h"
diff --git a/ios/clean/chrome/browser/ui/tab_grid/BUILD.gn b/ios/clean/chrome/browser/ui/tab_grid/BUILD.gn index cb12b1a..9d2b93cf9 100644 --- a/ios/clean/chrome/browser/ui/tab_grid/BUILD.gn +++ b/ios/clean/chrome/browser/ui/tab_grid/BUILD.gn
@@ -17,6 +17,7 @@ "//base", "//ios/chrome/browser/browser_state", "//ios/chrome/browser/snapshots", + "//ios/chrome/browser/ui/browser_list", "//ios/chrome/browser/ui/tools_menu:configuration", "//ios/chrome/browser/web_state_list", "//ios/clean/chrome/browser", @@ -27,7 +28,6 @@ "//ios/clean/chrome/browser/ui/tab_collection", "//ios/clean/chrome/browser/ui/tab_collection:tab_collection_ui", "//ios/clean/chrome/browser/ui/tools", - "//ios/shared/chrome/browser/ui/browser_list", "//ios/shared/chrome/browser/ui/commands", "//ios/shared/chrome/browser/ui/coordinators", "//ios/web",
diff --git a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm index fe0a209..cb9f9e77 100644 --- a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm +++ b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
@@ -10,6 +10,7 @@ #include "base/strings/sys_string_conversions.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/snapshots/snapshot_cache_factory.h" +#import "ios/chrome/browser/ui/browser_list/browser.h" #import "ios/chrome/browser/ui/tools_menu/tools_menu_configuration.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/chrome/browser/web_state_list/web_state_opener.h" @@ -23,7 +24,6 @@ #import "ios/clean/chrome/browser/ui/tab_grid/tab_grid_mediator.h" #import "ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.h" #import "ios/clean/chrome/browser/ui/tools/tools_coordinator.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser.h" #import "ios/shared/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator+internal.h" #import "ios/web/public/navigation_manager.h"
diff --git a/ios/clean/chrome/browser/ui/tab_strip/BUILD.gn b/ios/clean/chrome/browser/ui/tab_strip/BUILD.gn index e75f5f6..074ebaf 100644 --- a/ios/clean/chrome/browser/ui/tab_strip/BUILD.gn +++ b/ios/clean/chrome/browser/ui/tab_strip/BUILD.gn
@@ -10,10 +10,10 @@ deps = [ ":tab_strip_ui", "//ios/chrome/browser/browser_state", + "//ios/chrome/browser/ui/browser_list", "//ios/chrome/browser/web_state_list", "//ios/clean/chrome/browser/ui/commands", "//ios/clean/chrome/browser/ui/tab_collection", - "//ios/shared/chrome/browser/ui/browser_list", "//ios/shared/chrome/browser/ui/commands", "//ios/shared/chrome/browser/ui/coordinators", "//ios/web",
diff --git a/ios/clean/chrome/browser/ui/tab_strip/tab_strip_coordinator.mm b/ios/clean/chrome/browser/ui/tab_strip/tab_strip_coordinator.mm index 8478ce5..0f7eb69 100644 --- a/ios/clean/chrome/browser/ui/tab_strip/tab_strip_coordinator.mm +++ b/ios/clean/chrome/browser/ui/tab_strip/tab_strip_coordinator.mm
@@ -4,12 +4,12 @@ #import "ios/clean/chrome/browser/ui/tab_strip/tab_strip_coordinator.h" +#import "ios/chrome/browser/ui/browser_list/browser.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/clean/chrome/browser/ui/commands/tab_grid_commands.h" #import "ios/clean/chrome/browser/ui/commands/tab_strip_commands.h" #import "ios/clean/chrome/browser/ui/tab_collection/tab_collection_mediator.h" #import "ios/clean/chrome/browser/ui/tab_strip/tab_strip_view_controller.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser.h" #import "ios/shared/chrome/browser/ui/commands/command_dispatcher.h" #include "ios/web/public/web_state/web_state.h"
diff --git a/ios/clean/chrome/browser/ui/toolbar/BUILD.gn b/ios/clean/chrome/browser/ui/toolbar/BUILD.gn index 0184951..e517ef7 100644 --- a/ios/clean/chrome/browser/ui/toolbar/BUILD.gn +++ b/ios/clean/chrome/browser/ui/toolbar/BUILD.gn
@@ -16,13 +16,13 @@ ":toolbar_ui", "//base", "//ios/chrome/browser", + "//ios/chrome/browser/ui/browser_list", "//ios/chrome/browser/ui/tools_menu:configuration", "//ios/chrome/browser/web_state_list", "//ios/clean/chrome/browser/ui/commands", "//ios/clean/chrome/browser/ui/omnibox", "//ios/clean/chrome/browser/ui/tools", "//ios/shared/chrome/browser/ui/broadcaster", - "//ios/shared/chrome/browser/ui/browser_list", "//ios/shared/chrome/browser/ui/commands", "//ios/shared/chrome/browser/ui/coordinators", "//ios/web",
diff --git a/ios/clean/chrome/browser/ui/toolbar/toolbar_coordinator.mm b/ios/clean/chrome/browser/ui/toolbar/toolbar_coordinator.mm index e48a074..50079c6 100644 --- a/ios/clean/chrome/browser/ui/toolbar/toolbar_coordinator.mm +++ b/ios/clean/chrome/browser/ui/toolbar/toolbar_coordinator.mm
@@ -5,6 +5,7 @@ #import "ios/clean/chrome/browser/ui/toolbar/toolbar_coordinator.h" #include "ios/chrome/browser/chrome_url_constants.h" +#import "ios/chrome/browser/ui/browser_list/browser.h" #import "ios/chrome/browser/ui/tools_menu/tools_menu_configuration.h" #import "ios/clean/chrome/browser/ui/commands/tools_menu_commands.h" #import "ios/clean/chrome/browser/ui/omnibox/location_bar_coordinator.h" @@ -12,7 +13,6 @@ #import "ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.h" #import "ios/clean/chrome/browser/ui/tools/tools_coordinator.h" #import "ios/shared/chrome/browser/ui/broadcaster/chrome_broadcaster.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser.h" #import "ios/shared/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator+internal.h" #import "ios/web/public/web_state/web_state.h"
diff --git a/ios/clean/chrome/browser/ui/tools/BUILD.gn b/ios/clean/chrome/browser/ui/tools/BUILD.gn index c9ddf772..d9c569bf 100644 --- a/ios/clean/chrome/browser/ui/tools/BUILD.gn +++ b/ios/clean/chrome/browser/ui/tools/BUILD.gn
@@ -16,10 +16,10 @@ deps = [ ":tools_ui", "//base", + "//ios/chrome/browser/ui/browser_list", "//ios/chrome/browser/ui/tools_menu:configuration", "//ios/clean/chrome/browser/ui/commands", "//ios/clean/chrome/browser/ui/transitions", - "//ios/shared/chrome/browser/ui/browser_list", "//ios/shared/chrome/browser/ui/coordinators", "//ios/web", "//ui/base",
diff --git a/ios/clean/chrome/browser/ui/tools/tools_coordinator.mm b/ios/clean/chrome/browser/ui/tools/tools_coordinator.mm index 0251ceba..7610df3 100644 --- a/ios/clean/chrome/browser/ui/tools/tools_coordinator.mm +++ b/ios/clean/chrome/browser/ui/tools/tools_coordinator.mm
@@ -4,10 +4,10 @@ #import "ios/clean/chrome/browser/ui/tools/tools_coordinator.h" +#import "ios/chrome/browser/ui/browser_list/browser.h" #import "ios/clean/chrome/browser/ui/tools/menu_view_controller.h" #import "ios/clean/chrome/browser/ui/tools/tools_mediator.h" #import "ios/clean/chrome/browser/ui/transitions/zooming_menu_transition_controller.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support."
diff --git a/ios/clean/chrome/browser/ui/web_contents/BUILD.gn b/ios/clean/chrome/browser/ui/web_contents/BUILD.gn index 7cc6f98..36ae90d 100644 --- a/ios/clean/chrome/browser/ui/web_contents/BUILD.gn +++ b/ios/clean/chrome/browser/ui/web_contents/BUILD.gn
@@ -15,9 +15,9 @@ deps = [ ":web_contents_ui", "//ios/chrome/browser", + "//ios/chrome/browser/ui/browser_list", "//ios/clean/chrome/browser/ui/commands", "//ios/clean/chrome/browser/ui/context_menu", - "//ios/shared/chrome/browser/ui/browser_list", "//ios/shared/chrome/browser/ui/commands", "//ios/shared/chrome/browser/ui/coordinators", "//ios/web", @@ -40,6 +40,7 @@ testonly = true sources = [ "web_contents_mediator_unittest.mm", + "web_coordinator_unittest.mm", ] configs += [ "//build/config/compiler:enable_arc" ] @@ -50,6 +51,7 @@ "//base", "//base/test:test_support", "//ios/chrome/test/base", + "//ios/shared/chrome/browser/ui/coordinators", "//ios/shared/chrome/browser/ui/tab:test_support", "//ios/web/public/test/fakes", "//testing/gtest",
diff --git a/ios/clean/chrome/browser/ui/web_contents/web_coordinator.mm b/ios/clean/chrome/browser/ui/web_contents/web_coordinator.mm index db3ac94..a7ea49c 100644 --- a/ios/clean/chrome/browser/ui/web_contents/web_coordinator.mm +++ b/ios/clean/chrome/browser/ui/web_contents/web_coordinator.mm
@@ -6,12 +6,12 @@ #include "base/mac/foundation_util.h" #include "base/memory/ptr_util.h" +#import "ios/chrome/browser/ui/browser_list/browser.h" #import "ios/clean/chrome/browser/ui/commands/context_menu_commands.h" #import "ios/clean/chrome/browser/ui/context_menu/context_menu_context_impl.h" #import "ios/clean/chrome/browser/ui/context_menu/web_context_menu_coordinator.h" #import "ios/clean/chrome/browser/ui/web_contents/web_contents_mediator.h" #import "ios/clean/chrome/browser/ui/web_contents/web_contents_view_controller.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser.h" #import "ios/shared/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator+internal.h" #include "ios/web/public/navigation_manager.h"
diff --git a/ios/clean/chrome/browser/ui/web_contents/web_coordinator_unittest.mm b/ios/clean/chrome/browser/ui/web_contents/web_coordinator_unittest.mm new file mode 100644 index 0000000..2abeebc --- /dev/null +++ b/ios/clean/chrome/browser/ui/web_contents/web_coordinator_unittest.mm
@@ -0,0 +1,63 @@ +// 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. + +#import "ios/clean/chrome/browser/ui/web_contents/web_coordinator.h" + +#include "base/memory/ptr_util.h" +#import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator+internal.h" +#import "ios/shared/chrome/browser/ui/tab/tab_test_util.h" +#import "ios/web/public/test/fakes/test_web_state.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/gtest_mac.h" +#include "testing/platform_test.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { + +class WebCoordinatorTest : public PlatformTest { + public: + WebCoordinatorTest() { + auto navigation_manager = base::MakeUnique<TabNavigationManager>(); + navigation_manager->SetItemCount(0); + test_web_state_.SetView([[UIView alloc] init]); + test_web_state_.SetNavigationManager(std::move(navigation_manager)); + + coordinator_ = [[WebCoordinator alloc] init]; + } + + protected: + WebCoordinator* coordinator_; + web::TestWebState test_web_state_; +}; + +// Tests that starting without the webstate still creates a view controller. +TEST_F(WebCoordinatorTest, TestStartWithoutWebState) { + EXPECT_EQ(coordinator_.viewController, nil); + [coordinator_ start]; + EXPECT_NE(coordinator_.viewController, nil); +} + +// Tests that starting with the webstate puts the webstate's view in the VC. +TEST_F(WebCoordinatorTest, TestStartWithWebState) { + coordinator_.webState = &test_web_state_; + [coordinator_ start]; + EXPECT_TRUE([test_web_state_.GetView() + isDescendantOfView:coordinator_.viewController.view]); +} + +// Tests that starting and then setting the webstate puts the webstate's view in +// the VC. +TEST_F(WebCoordinatorTest, TestStartThenSetWebState) { + [coordinator_ start]; + EXPECT_FALSE([test_web_state_.GetView() + isDescendantOfView:coordinator_.viewController.view]); + coordinator_.webState = &test_web_state_; + EXPECT_TRUE([test_web_state_.GetView() + isDescendantOfView:coordinator_.viewController.view]); +} + +} // namespace
diff --git a/ios/net/OWNERS b/ios/net/OWNERS index 13444820..706c5f3 100644 --- a/ios/net/OWNERS +++ b/ios/net/OWNERS
@@ -1,3 +1,6 @@ droger@chromium.org ellyjones@chromium.org marq@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/public/consumer/OWNERS b/ios/public/consumer/OWNERS index ae82009..ba9c65db 100644 --- a/ios/public/consumer/OWNERS +++ b/ios/public/consumer/OWNERS
@@ -1,2 +1,5 @@ rohitrao@chromium.org sdefresne@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/public/provider/OWNERS b/ios/public/provider/OWNERS index ae82009..ba9c65db 100644 --- a/ios/public/provider/OWNERS +++ b/ios/public/provider/OWNERS
@@ -1,2 +1,5 @@ rohitrao@chromium.org sdefresne@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/public/provider/chrome/browser/signin/OWNERS b/ios/public/provider/chrome/browser/signin/OWNERS index d45210b..6068057 100644 --- a/ios/public/provider/chrome/browser/signin/OWNERS +++ b/ios/public/provider/chrome/browser/signin/OWNERS
@@ -2,3 +2,6 @@ msarda@chromium.org # COMPONENT: Services>SignIn + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/shared/OWNERS b/ios/shared/OWNERS index b8d3d41f..290f78a 100644 --- a/ios/shared/OWNERS +++ b/ios/shared/OWNERS
@@ -1,3 +1,6 @@ lpromero@chromium.org marq@chromium.org sdefresne@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/shared/chrome/browser/ui/DEPS b/ios/shared/chrome/browser/ui/DEPS index eb4f1fa..661df6b 100644 --- a/ios/shared/chrome/browser/ui/DEPS +++ b/ios/shared/chrome/browser/ui/DEPS
@@ -1,7 +1,6 @@ include_rules = [ - # Allow ios/chrome/browser but not ios/chrome/browser/ui. + # Allow ios/chrome/browser. "+ios/chrome/browser", - "-ios/chrome/browser/ui", "+components/omnibox/browser", ]
diff --git a/ios/shared/chrome/browser/ui/coordinators/BUILD.gn b/ios/shared/chrome/browser/ui/coordinators/BUILD.gn index 01805bb..ad36878 100644 --- a/ios/shared/chrome/browser/ui/coordinators/BUILD.gn +++ b/ios/shared/chrome/browser/ui/coordinators/BUILD.gn
@@ -17,7 +17,7 @@ "//ios/chrome/browser", "//ios/chrome/browser/browser_state", "//ios/chrome/browser/tabs:tabs_internal", - "//ios/shared/chrome/browser/ui/browser_list", + "//ios/chrome/browser/ui/browser_list", ] } @@ -34,7 +34,7 @@ ":coordinators", "//base", "//ios/chrome/browser/browser_state:test_support", - "//ios/shared/chrome/browser/ui/browser_list", + "//ios/chrome/browser/ui/browser_list", "//testing/gtest", ] }
diff --git a/ios/shared/chrome/browser/ui/coordinators/browser_coordinator_test.mm b/ios/shared/chrome/browser/ui/coordinators/browser_coordinator_test.mm index 5f4cb62a..4d54d95 100644 --- a/ios/shared/chrome/browser/ui/coordinators/browser_coordinator_test.mm +++ b/ios/shared/chrome/browser/ui/coordinators/browser_coordinator_test.mm
@@ -6,7 +6,7 @@ #include "base/memory/ptr_util.h" #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" -#import "ios/shared/chrome/browser/ui/browser_list/browser.h" +#import "ios/chrome/browser/ui/browser_list/browser.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support."
diff --git a/ios/shared/chrome/browser/ui/dialogs/OWNERS b/ios/shared/chrome/browser/ui/dialogs/OWNERS index 48efb49e..bd85dcf2 100644 --- a/ios/shared/chrome/browser/ui/dialogs/OWNERS +++ b/ios/shared/chrome/browser/ui/dialogs/OWNERS
@@ -1 +1,4 @@ kkhorimoto@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/shared/chrome/browser/ui/settings/BUILD.gn b/ios/shared/chrome/browser/ui/settings/BUILD.gn index ac535bc..4d5db7a 100644 --- a/ios/shared/chrome/browser/ui/settings/BUILD.gn +++ b/ios/shared/chrome/browser/ui/settings/BUILD.gn
@@ -8,13 +8,4 @@ ] configs += [ "//build/config/compiler:enable_arc" ] - - deps = [ - # "//base", - # "//ios/chrome/app:tests_fake_hook", - # "//ios/chrome/browser", - # "//ios/chrome/browser/browser_state", - # "//ios/chrome/browser/tabs:tabs_internal", - # "//ios/shared/chrome/browser/ui/browser_list", - ] }
diff --git a/ios/showcase/OWNERS b/ios/showcase/OWNERS index 411d967..aa8e854 100644 --- a/ios/showcase/OWNERS +++ b/ios/showcase/OWNERS
@@ -1,2 +1,5 @@ edchin@chromium.org lpromero@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/showcase/content_suggestions/OWNERS b/ios/showcase/content_suggestions/OWNERS index 2d35f0a..f192143 100644 --- a/ios/showcase/content_suggestions/OWNERS +++ b/ios/showcase/content_suggestions/OWNERS
@@ -1 +1,4 @@ gambard@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/testing/earl_grey/OWNERS b/ios/testing/earl_grey/OWNERS index 1df316e..6f764fe 100644 --- a/ios/testing/earl_grey/OWNERS +++ b/ios/testing/earl_grey/OWNERS
@@ -1 +1,4 @@ baxley@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/third_party/blink/OWNERS b/ios/third_party/blink/OWNERS index 40a68c7..b127701 100644 --- a/ios/third_party/blink/OWNERS +++ b/ios/third_party/blink/OWNERS
@@ -1 +1,4 @@ rohitrao@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/third_party/earl_grey/OWNERS b/ios/third_party/earl_grey/OWNERS index 3bb1f30..f1cc9a0 100644 --- a/ios/third_party/earl_grey/OWNERS +++ b/ios/third_party/earl_grey/OWNERS
@@ -1,3 +1,6 @@ baxley@chromium.org justincohen@chromium.org rohitrao@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/third_party/fishhook/OWNERS b/ios/third_party/fishhook/OWNERS index 3bb1f30..f1cc9a0 100644 --- a/ios/third_party/fishhook/OWNERS +++ b/ios/third_party/fishhook/OWNERS
@@ -1,3 +1,6 @@ baxley@chromium.org justincohen@chromium.org rohitrao@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/third_party/material_components_ios/OWNERS b/ios/third_party/material_components_ios/OWNERS index 2b842fe..1e909408 100644 --- a/ios/third_party/material_components_ios/OWNERS +++ b/ios/third_party/material_components_ios/OWNERS
@@ -4,3 +4,6 @@ # These are for the common case of adding or renaming files. If you're doing # structural changes, please get a review from an OWNER. per-file BUILD.gn=* + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/third_party/material_components_ios/README.chromium b/ios/third_party/material_components_ios/README.chromium index 5c68a80..69d4294 100644 --- a/ios/third_party/material_components_ios/README.chromium +++ b/ios/third_party/material_components_ios/README.chromium
@@ -1,7 +1,7 @@ Name: Material Components for iOS URL: https://github.com/material-components/material-components-ios Version: 0 -Revision: c2a357fb67321e9660190c55b49836c51fe04821 +Revision: a0466df249c593ba65007440d7a84e4665ac2631 License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/ios/third_party/material_font_disk_loader_ios/OWNERS b/ios/third_party/material_font_disk_loader_ios/OWNERS index 077a06e..c984591 100644 --- a/ios/third_party/material_font_disk_loader_ios/OWNERS +++ b/ios/third_party/material_font_disk_loader_ios/OWNERS
@@ -1,2 +1,5 @@ lpromero@chromium.org rohitrao@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/third_party/material_roboto_font_loader_ios/OWNERS b/ios/third_party/material_roboto_font_loader_ios/OWNERS index 077a06e..c984591 100644 --- a/ios/third_party/material_roboto_font_loader_ios/OWNERS +++ b/ios/third_party/material_roboto_font_loader_ios/OWNERS
@@ -1,2 +1,5 @@ lpromero@chromium.org rohitrao@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/third_party/material_sprited_animation_view_ios/OWNERS b/ios/third_party/material_sprited_animation_view_ios/OWNERS index 077a06e..c984591 100644 --- a/ios/third_party/material_sprited_animation_view_ios/OWNERS +++ b/ios/third_party/material_sprited_animation_view_ios/OWNERS
@@ -1,2 +1,5 @@ lpromero@chromium.org rohitrao@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/third_party/material_text_accessibility_ios/OWNERS b/ios/third_party/material_text_accessibility_ios/OWNERS index 077a06e..c984591 100644 --- a/ios/third_party/material_text_accessibility_ios/OWNERS +++ b/ios/third_party/material_text_accessibility_ios/OWNERS
@@ -1,2 +1,5 @@ lpromero@chromium.org rohitrao@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/third_party/ochamcrest/OWNERS b/ios/third_party/ochamcrest/OWNERS index 3bb1f30..f1cc9a0 100644 --- a/ios/third_party/ochamcrest/OWNERS +++ b/ios/third_party/ochamcrest/OWNERS
@@ -1,3 +1,6 @@ baxley@chromium.org justincohen@chromium.org rohitrao@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/web/OWNERS b/ios/web/OWNERS index 2710e7a..a7206ed 100644 --- a/ios/web/OWNERS +++ b/ios/web/OWNERS
@@ -1,3 +1,6 @@ eugenebut@chromium.org kkhorimoto@chromium.org marq@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/web/payments/OWNERS b/ios/web/payments/OWNERS index f189e142..6e417fc 100644 --- a/ios/web/payments/OWNERS +++ b/ios/web/payments/OWNERS
@@ -1,2 +1,5 @@ mahmadi@chromium.org lpromero@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/web/payments/payment_request.cc b/ios/web/payments/payment_request.cc index c535f9d7..63ff82d 100644 --- a/ios/web/payments/payment_request.cc +++ b/ios/web/payments/payment_request.cc
@@ -59,6 +59,9 @@ namespace web { +const char kPaymentRequestIDExternal[] = "payment-request-id"; +const char kPaymentRequestDataExternal[] = "payment-request-data"; + PaymentCurrencyAmount::PaymentCurrencyAmount() // By default, the currency is defined by [ISO4217]. For example, USD for // US Dollars.
diff --git a/ios/web/public/OWNERS b/ios/web/public/OWNERS index 08850f4..75983fd 100644 --- a/ios/web/public/OWNERS +++ b/ios/web/public/OWNERS
@@ -1,2 +1,5 @@ per-file *.mojom=set noparent per-file *.mojom=file://ipc/SECURITY_OWNERS + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/web/public/app/mojo/OWNERS b/ios/web/public/app/mojo/OWNERS index 1c9493c3..77df058 100644 --- a/ios/web/public/app/mojo/OWNERS +++ b/ios/web/public/app/mojo/OWNERS
@@ -1,2 +1,5 @@ per-file *.json=set noparent per-file *.json=file://ipc/SECURITY_OWNERS + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/web/public/payments/OWNERS b/ios/web/public/payments/OWNERS index f189e142..6e417fc 100644 --- a/ios/web/public/payments/OWNERS +++ b/ios/web/public/payments/OWNERS
@@ -1,2 +1,5 @@ mahmadi@chromium.org lpromero@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/web/public/payments/payment_request.h b/ios/web/public/payments/payment_request.h index 62c3ab6..a5353b1c 100644 --- a/ios/web/public/payments/payment_request.h +++ b/ios/web/public/payments/payment_request.h
@@ -25,6 +25,11 @@ namespace web { +// These constants are for Univesral Link query parameters when receiving +// payment response data from an external application. +extern const char kPaymentRequestIDExternal[]; +extern const char kPaymentRequestDataExternal[]; + // Supplies monetary amounts. class PaymentCurrencyAmount { public:
diff --git a/ios/web/public/test/OWNERS b/ios/web/public/test/OWNERS index c3cd7d2..a4af3ca 100644 --- a/ios/web/public/test/OWNERS +++ b/ios/web/public/test/OWNERS
@@ -1,2 +1,5 @@ baxley@chromium.org eugenebut@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/web/public/user_agent.mm b/ios/web/public/user_agent.mm index 10b16fb..ac2a4dd 100644 --- a/ios/web/public/user_agent.mm +++ b/ios/web/public/user_agent.mm
@@ -45,6 +45,7 @@ // Safari version can't be, so a lookup table is used instead (for both, since // the reported versions should stay in sync). static const OSVersionMap version_map[] = { + {11, 0, {"604.1", "604.1.34"}}, {10, 3, {"602.1", "603.1.30"}}, {10, 0, {"602.1", "602.1.50"}}, {9, 0, {"601.1.46", "601.1"}},
diff --git a/ios/web/public/webui/OWNERS b/ios/web/public/webui/OWNERS index a01ab6c..f75309d 100644 --- a/ios/web/public/webui/OWNERS +++ b/ios/web/public/webui/OWNERS
@@ -1,2 +1,5 @@ eugenebut@chromium.org michaeldo@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/web/shell/OWNERS b/ios/web/shell/OWNERS index d0f3b7e..fd32f2c 100644 --- a/ios/web/shell/OWNERS +++ b/ios/web/shell/OWNERS
@@ -3,3 +3,6 @@ per-file *.mojom=set noparent per-file *.mojom=file://ipc/SECURITY_OWNERS + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/web/shell/test/OWNERS b/ios/web/shell/test/OWNERS index 1df316e..6f764fe 100644 --- a/ios/web/shell/test/OWNERS +++ b/ios/web/shell/test/OWNERS
@@ -1 +1,4 @@ baxley@chromium.org + +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/web/web_state/ui/crw_web_controller.h b/ios/web/web_state/ui/crw_web_controller.h index 2493e20..8619a60 100644 --- a/ios/web/web_state/ui/crw_web_controller.h +++ b/ios/web/web_state/ui/crw_web_controller.h
@@ -196,12 +196,6 @@ // only checks on creation, such that the whole object needs to be rebuilt. - (void)requirePageReconstruction; -// Requires that the next display reload the page, using a placeholder while -// loading. This could be used, e.g., to handle a crash in a WebController that -// is not currently visible. -// TODO(stuartmorgan): When revisiting the methods above, revisit this as well. -- (void)requirePageReload; - // Show overlay, don't reload web page. Used when the view will be // visible only briefly (e.g., tablet side swipe). - (void)setOverlayPreviewMode:(BOOL)overlayPreviewMode;
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index e9617da..19335f89 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -320,9 +320,6 @@ base::scoped_nsobject<NSMutableArray> _webViewToolbars; // Flag to say if browsing is enabled. BOOL _webUsageEnabled; - // The next time the view is requested, reload the page (using the placeholder - // overlay until it's loaded). - BOOL _requireReloadOnDisplay; // Overlay view used instead of webView. base::scoped_nsobject<UIImageView> _placeholderOverlayView; // The touch tracking recognizer allowing us to decide if a navigation is @@ -1111,10 +1108,6 @@ [self removeWebView]; } -- (void)requirePageReload { - _requireReloadOnDisplay = YES; -} - - (void)resetContainerView { [_containerView removeFromSuperview]; _containerView.reset(); @@ -1967,10 +1960,6 @@ // then transition away. if (_overlayPreviewMode && !isChromeScheme) [self addPlaceholderOverlay]; - } else if (_requireReloadOnDisplay && _webView) { - _requireReloadOnDisplay = NO; - [self addPlaceholderOverlay]; - [self loadCurrentURL]; } }
diff --git a/ios/web/webui/web_ui_mojo_inttest.mm b/ios/web/webui/web_ui_mojo_inttest.mm index d90e2333..0c4dc8f 100644 --- a/ios/web/webui/web_ui_mojo_inttest.mm +++ b/ios/web/webui/web_ui_mojo_inttest.mm
@@ -174,13 +174,7 @@ // Tests that JS can send messages to the native code and vice versa. // TestUIHandler is used for communication and test succeeds only when // |TestUIHandler| successfully receives "ack" message from WebUI page. -#if TARGET_IPHONE_SIMULATOR -#define MAYBE_MessageExchange MessageExchange -#else -#define MAYBE_MessageExchange FLAKY_MessageExchange -#endif -// TODO(crbug.com/720098): Enable this test on device. -TEST_F(WebUIMojoTest, MAYBE_MessageExchange) { +TEST_F(WebUIMojoTest, MessageExchange) { @autoreleasepool { web_state()->SetWebUsageEnabled(true); web_state()->GetView(); // WebState won't load URL without view.
diff --git a/ios/web_view/OWNERS b/ios/web_view/OWNERS index d008751..c3456e9 100644 --- a/ios/web_view/OWNERS +++ b/ios/web_view/OWNERS
@@ -7,4 +7,6 @@ # structural changes, please get a review from an OWNER. per-file BUILD.gn=* -# COMPONENT: Mobile>iOSWebView \ No newline at end of file +# COMPONENT: Mobile>iOSWebView +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ipc/ipc_mojo_bootstrap.cc b/ipc/ipc_mojo_bootstrap.cc index afd0e3c..4ea67bbd 100644 --- a/ipc/ipc_mojo_bootstrap.cc +++ b/ipc/ipc_mojo_bootstrap.cc
@@ -172,6 +172,15 @@ if (!mojo::IsValidInterfaceId(id)) return mojo::ScopedInterfaceEndpointHandle(); + // Unless it is the master ID, |id| is from the remote side and therefore + // its namespace bit is supposed to be different than the value that this + // router would use. + if (!mojo::IsMasterInterfaceId(id) && + set_interface_id_namespace_bit_ == + mojo::HasInterfaceIdNamespaceBitSet(id)) { + return mojo::ScopedInterfaceEndpointHandle(); + } + base::AutoLock locker(lock_); bool inserted = false; Endpoint* endpoint = FindOrInsertEndpoint(id, &inserted);
diff --git a/media/base/pipeline.h b/media/base/pipeline.h index 1423afa..b39ae20 100644 --- a/media/base/pipeline.h +++ b/media/base/pipeline.h
@@ -34,6 +34,7 @@ // Executed whenever an error occurs except when the error occurs during // Start/Seek/Resume or Suspend. Those errors are reported via |seek_cb| // and |suspend_cb| respectively. + // NOTE: The client is responsible for calling Pipeline::Stop(). virtual void OnError(PipelineStatus status) = 0; // Executed whenever the media reaches the end.
diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc index ecf1574..2028019 100644 --- a/media/base/pipeline_impl.cc +++ b/media/base/pipeline_impl.cc
@@ -222,8 +222,8 @@ std::unique_ptr<TextRenderer> text_renderer, base::WeakPtr<PipelineImpl> weak_pipeline) { DCHECK(media_task_runner_->BelongsToCurrentThread()); - DCHECK_EQ(kCreated, state_) << "Received start in unexpected state: " - << state_; + DCHECK(state_ == kCreated || state_ == kStopped) + << "Received start in unexpected state: " << state_; SetState(kStarting); @@ -232,7 +232,6 @@ DCHECK(!text_renderer_); DCHECK(!renderer_ended_); DCHECK(!text_renderer_ended_); - DCHECK(!weak_pipeline_); demuxer_ = demuxer; { base::AutoLock auto_lock(shared_state_lock_); @@ -1275,18 +1274,16 @@ // Else report error via the client interface. if (!seek_cb_.is_null()) { base::ResetAndReturn(&seek_cb_).Run(error); - } else if (!suspend_cb_.is_null()) { - base::ResetAndReturn(&suspend_cb_).Run(error); - } else { - DCHECK(client_); - client_->OnError(error); + return; } - // Any kind of error stops the pipeline. - // - // TODO (tguilbert): Move this out to PipelineController to make the state - // changes more consistent. See crbug.com/695734. - Stop(); + if (!suspend_cb_.is_null()) { + base::ResetAndReturn(&suspend_cb_).Run(error); + return; + } + + DCHECK(client_); + client_->OnError(error); } void PipelineImpl::OnEnded() {
diff --git a/media/base/pipeline_impl.h b/media/base/pipeline_impl.h index e5c9de3..73ee91f 100644 --- a/media/base/pipeline_impl.h +++ b/media/base/pipeline_impl.h
@@ -29,7 +29,7 @@ // Here's a state diagram that describes the lifetime of this object. // // [ *Created ] [ Any State ] -// | Start() | Stop() / SetError() +// | Start() | Stop() // V V // [ Starting ] [ Stopping ] // | | @@ -55,9 +55,9 @@ // a chance to preroll. From then on the normal Seek() transitions are carried // out and we start playing the media. // -// If any error ever happens, this object will transition to the "Error" state -// from any state. If Stop() is ever called, this object will transition to -// "Stopped" state. +// If Stop() is ever called, this object will transition to "Stopped" state. +// Pipeline::Stop() is never called from withing PipelineImpl. It's |client_|'s +// responsibility to call stop when appropriate. // // TODO(sandersd): It should be possible to pass through Suspended when going // from InitDemuxer to InitRenderer, thereby eliminating the Resuming state.
diff --git a/media/base/pipeline_impl_unittest.cc b/media/base/pipeline_impl_unittest.cc index 8e81bd2d..9db941b9 100644 --- a/media/base/pipeline_impl_unittest.cc +++ b/media/base/pipeline_impl_unittest.cc
@@ -37,8 +37,6 @@ using ::testing::CreateFunctor; using ::testing::DeleteArg; using ::testing::DoAll; -// TODO(scherkus): Remove InSequence after refactoring Pipeline. -using ::testing::InSequence; using ::testing::Invoke; using ::testing::InvokeWithoutArgs; using ::testing::Mock; @@ -424,7 +422,6 @@ TEST_F(PipelineImplTest, NoStreams) { EXPECT_CALL(*demuxer_, Initialize(_, _, _)) .WillOnce(PostCallback<1>(PIPELINE_OK)); - EXPECT_CALL(*demuxer_, Stop()); EXPECT_CALL(callbacks_, OnMetadata(_)); StartPipelineAndExpect(PIPELINE_ERROR_COULD_NOT_RENDER); @@ -536,8 +533,9 @@ // Initialize then seek! StartPipelineAndExpect(PIPELINE_OK); + // Pipeline::Client is supposed to call Pipeline::Stop() after errors. + EXPECT_CALL(callbacks_, OnError(_)).WillOnce(Stop(pipeline_.get())); EXPECT_CALL(*demuxer_, Stop()); - EXPECT_CALL(callbacks_, OnError(_)); OnDemuxerError(); base::RunLoop().RunUntilIdle(); @@ -701,7 +699,8 @@ pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek, base::Unretained(&callbacks_))); - EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ)); + EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ)) + .WillOnce(Stop(pipeline_.get())); base::RunLoop().RunUntilIdle(); } @@ -754,7 +753,8 @@ pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek, base::Unretained(&callbacks_))); - EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ)); + EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ)) + .WillOnce(Stop(pipeline_.get())); base::RunLoop().RunUntilIdle(); } @@ -934,7 +934,8 @@ } else { EXPECT_CALL(*demuxer_, Initialize(_, _, _)) .WillOnce(PostCallback<1>(DEMUXER_ERROR_COULD_NOT_OPEN)); - EXPECT_CALL(callbacks_, OnStart(DEMUXER_ERROR_COULD_NOT_OPEN)); + EXPECT_CALL(callbacks_, OnStart(DEMUXER_ERROR_COULD_NOT_OPEN)) + .WillOnce(Stop(pipeline_.get())); } EXPECT_CALL(*demuxer_, Stop()); @@ -957,7 +958,8 @@ } else { EXPECT_CALL(*renderer_, Initialize(_, _, _)) .WillOnce(PostCallback<2>(PIPELINE_ERROR_INITIALIZATION_FAILED)); - EXPECT_CALL(callbacks_, OnStart(PIPELINE_ERROR_INITIALIZATION_FAILED)); + EXPECT_CALL(callbacks_, OnStart(PIPELINE_ERROR_INITIALIZATION_FAILED)) + .WillOnce(Stop(pipeline_.get())); } EXPECT_CALL(callbacks_, OnMetadata(_)); @@ -1008,7 +1010,8 @@ SetError(&renderer_client_, PIPELINE_ERROR_READ), RunClosure<0>())); EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)); - EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ)); + EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ)) + .WillOnce(Stop(pipeline_.get())); } return; } @@ -1028,7 +1031,8 @@ } else { EXPECT_CALL(*demuxer_, Seek(_, _)) .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ)); - EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ)); + EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ)) + .WillOnce(Stop(pipeline_.get())); } return; } @@ -1068,7 +1072,8 @@ } else { EXPECT_CALL(*demuxer_, Seek(_, _)) .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ)); - EXPECT_CALL(callbacks_, OnResume(PIPELINE_ERROR_READ)); + EXPECT_CALL(callbacks_, OnResume(PIPELINE_ERROR_READ)) + .WillOnce(Stop(pipeline_.get())); } } else if (state != kSuspended && state != kSuspending) { NOTREACHED() << "State not supported: " << state; @@ -1085,7 +1090,8 @@ case kError: if (expect_errors) { EXPECT_CALL(*demuxer_, Stop()); - EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ)); + EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ)) + .WillOnce(Stop(pipeline_.get())); } renderer_client_->OnError(PIPELINE_ERROR_READ); break;
diff --git a/media/blink/buffered_data_source_host_impl.cc b/media/blink/buffered_data_source_host_impl.cc index 8569558..1b4f872 100644 --- a/media/blink/buffered_data_source_host_impl.cc +++ b/media/blink/buffered_data_source_host_impl.cc
@@ -57,9 +57,12 @@ void BufferedDataSourceHostImpl::AddBufferedByteRange(int64_t start, int64_t end) { int64_t new_bytes = UnloadedBytesInInterval(Interval<int64_t>(start, end)); - if (new_bytes > 0) - did_loading_progress_ = true; + if (new_bytes == 0) { + // No change + return; + } buffered_byte_ranges_.SetInterval(start, end, 1); + did_loading_progress_ = true; base::TimeTicks now = tick_clock_->NowTicks(); int64_t bytes_so_far = 0;
diff --git a/media/blink/multibuffer_data_source.cc b/media/blink/multibuffer_data_source.cc index 3f29a1c..d793c69 100644 --- a/media/blink/multibuffer_data_source.cc +++ b/media/blink/multibuffer_data_source.cc
@@ -116,7 +116,7 @@ stop_signal_received_(false), media_has_played_(false), single_origin_(true), - cancel_on_defer_(true), + cancel_on_defer_(false), preload_(AUTO), bitrate_(0), playback_rate_(0.0), @@ -414,7 +414,6 @@ } void MultibufferDataSource::StopInternal_Locked() { - DVLOG(1) << __func__; lock_.AssertAcquired(); if (stop_signal_received_) return; @@ -444,7 +443,6 @@ ///////////////////////////////////////////////////////////////////////////// // BufferedResourceLoader callback methods. void MultibufferDataSource::StartCallback() { - DVLOG(1) << __func__; DCHECK(render_task_runner_->BelongsToCurrentThread()); if (init_cb_.is_null()) { @@ -495,8 +493,6 @@ media_log_->SetBooleanProperty("range_header_supported", url_data_->range_supported()); } - if (!url_data_->range_supported()) - cancel_on_defer_ = false; render_task_runner_->PostTask( FROM_HERE, base::Bind(base::ResetAndReturn(&init_cb_), success)); @@ -540,8 +536,7 @@ bool loading = is_loading || force_loading; if (!loading && cancel_on_defer_) { - DVLOG(2) << "Cancel on defer"; - if (read_op_ || !init_cb_.is_null()) { + if (read_op_) { // We can't destroy the reader if a read operation is pending. // UpdateLoadingState_Locked will be called again when the read // operation is done.
diff --git a/media/blink/multibuffer_data_source_unittest.cc b/media/blink/multibuffer_data_source_unittest.cc index a7c2b9c..b71b1f2 100644 --- a/media/blink/multibuffer_data_source_unittest.cc +++ b/media/blink/multibuffer_data_source_unittest.cc
@@ -390,21 +390,18 @@ } void CheckCapacityDefer() { - if (loader()) { - EXPECT_EQ(2 << 20, preload_low()); - EXPECT_EQ(3 << 20, preload_high()); - } else { - EXPECT_EQ(preload(), MultibufferDataSource::AUTO); - } + EXPECT_EQ(2 << 20, preload_low()); + EXPECT_EQ(3 << 20, preload_high()); } void CheckReadThenDefer() { - if (loader()) { - EXPECT_EQ(0, preload_low()); - EXPECT_EQ(0, preload_high()); - } else { - EXPECT_EQ(preload(), MultibufferDataSource::METADATA); - } + EXPECT_EQ(0, preload_low()); + EXPECT_EQ(0, preload_high()); + } + + void CheckNeverDefer() { + EXPECT_EQ(1LL << 40, preload_low()); + EXPECT_EQ(1LL << 40, preload_high()); } // Accessors for private variables on |data_source_|. @@ -1189,20 +1186,15 @@ set_preload(MultibufferDataSource::METADATA); InitializeWith206Response(); - data_source_->MediaIsPlaying(); - data_source_->SetPreload(MultibufferDataSource::METADATA); + EXPECT_EQ(MultibufferDataSource::METADATA, preload()); EXPECT_FALSE(is_local_source()); EXPECT_TRUE(data_source_->range_supported()); CheckReadThenDefer(); - // Read next block. (Needed to start up the loader again.) + // Read a bit from the beginning. EXPECT_CALL(*this, ReadCallback(kDataSize)); - ReadAt(kDataSize); - Respond(response_generator_->Generate206(kDataSize)); - EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 2)); - ReceiveData(kDataSize); + ReadAt(0); - // After reading, we should be in a deferred state. ASSERT_TRUE(active_loader()); EXPECT_TRUE(data_provider()->deferred()); }
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc index 68b41bc..545b5c7 100644 --- a/media/blink/webmediaplayer_impl.cc +++ b/media/blink/webmediaplayer_impl.cc
@@ -938,16 +938,6 @@ if (highest_ready_state_ >= ReadyState::kReadyStateHaveFutureData) return false; - // To suspend before we reach kReadyStateHaveCurrentData is only ok - // if we know we're going to get woken up when we get more data, which - // will only happen if the network is in the "Loading" state. - // This happens when the network is fast, but multiple videos are loading - // and multiplexing gets held up waiting for available threads. - if (highest_ready_state_ <= ReadyState::kReadyStateHaveMetadata && - network_state_ != WebMediaPlayer::kNetworkStateLoading) { - return true; - } - if (preroll_attempt_pending_) return true; @@ -1333,6 +1323,9 @@ SetNetworkState(PipelineErrorToNetworkState(status)); } + // PipelineController::Stop() is idempotent. + pipeline_controller_.Stop(); + UpdatePlayState(); }
diff --git a/media/blink/webmediaplayer_impl_unittest.cc b/media/blink/webmediaplayer_impl_unittest.cc index 014a2d3..116f8f1e 100644 --- a/media/blink/webmediaplayer_impl_unittest.cc +++ b/media/blink/webmediaplayer_impl_unittest.cc
@@ -270,9 +270,6 @@ } protected: - void SetNetworkState(blink::WebMediaPlayer::NetworkState state) { - wmpi_->SetNetworkState(state); - } void SetReadyState(blink::WebMediaPlayer::ReadyState state) { wmpi_->SetReadyState(state); } @@ -424,9 +421,11 @@ EXPECT_FALSE(IsSuspended()); } -TEST_F(WebMediaPlayerImplTest, IdleSuspendBeforeLoadingBegins) { +TEST_F(WebMediaPlayerImplTest, IdleSuspendIsEnabledBeforeLoadingBegins) { InitializeWebMediaPlayerImpl(); - EXPECT_FALSE(delegate_.ExpireForTesting()); + EXPECT_TRUE(delegate_.ExpireForTesting()); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(IsSuspended()); } TEST_F(WebMediaPlayerImplTest, @@ -446,7 +445,6 @@ TEST_F(WebMediaPlayerImplTest, IdleSuspendIsEnabledIfLoadingHasStalled) { InitializeWebMediaPlayerImpl(); - SetNetworkState(blink::WebMediaPlayer::kNetworkStateLoading); base::SimpleTestTickClock* clock = new base::SimpleTestTickClock(); clock->Advance(base::TimeDelta::FromSeconds(1)); SetTickClock(clock); @@ -462,7 +460,6 @@ TEST_F(WebMediaPlayerImplTest, DidLoadingProgressTriggersResume) { // Same setup as IdleSuspendIsEnabledBeforeLoadingBegins. InitializeWebMediaPlayerImpl(); - SetNetworkState(blink::WebMediaPlayer::kNetworkStateLoading); EXPECT_TRUE(delegate_.ExpireForTesting()); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(IsSuspended());
diff --git a/media/capture/video/video_capture_system_impl.cc b/media/capture/video/video_capture_system_impl.cc index da8f119d..8e18420 100644 --- a/media/capture/video/video_capture_system_impl.cc +++ b/media/capture/video/video_capture_system_impl.cc
@@ -9,41 +9,36 @@ namespace { // Compares two VideoCaptureFormat by checking smallest frame_size area, then -// by _largest_ frame_rate. Used to order a VideoCaptureFormats vector so that -// the first entry for a given resolution has the largest frame rate, as needed -// by the ConsolidateCaptureFormats() method. +// by width, and then by _largest_ frame_rate. Used to order a +// VideoCaptureFormats vector so that the first entry for a given resolution has +// the largest frame rate. bool IsCaptureFormatSmaller(const media::VideoCaptureFormat& format1, const media::VideoCaptureFormat& format2) { DCHECK(format1.frame_size.GetCheckedArea().IsValid()); DCHECK(format2.frame_size.GetCheckedArea().IsValid()); if (format1.frame_size.GetCheckedArea().ValueOrDefault(0) == format2.frame_size.GetCheckedArea().ValueOrDefault(0)) { - return format1.frame_rate > format2.frame_rate; + if (format1.frame_size.width() == format2.frame_size.width()) { + return format1.frame_rate > format2.frame_rate; + } + return format1.frame_size.width() < format2.frame_size.width(); } return format1.frame_size.GetCheckedArea().ValueOrDefault(0) < format2.frame_size.GetCheckedArea().ValueOrDefault(0); } -bool IsCaptureFormatSizeEqual(const media::VideoCaptureFormat& format1, - const media::VideoCaptureFormat& format2) { - DCHECK(format1.frame_size.GetCheckedArea().IsValid()); - DCHECK(format2.frame_size.GetCheckedArea().IsValid()); - return format1.frame_size.GetCheckedArea().ValueOrDefault(0) == - format2.frame_size.GetCheckedArea().ValueOrDefault(0); +bool IsCaptureFormatEqual(const media::VideoCaptureFormat& format1, + const media::VideoCaptureFormat& format2) { + return format1.frame_size == format2.frame_size && + format1.frame_rate == format2.frame_rate && + format1.pixel_format == format2.pixel_format; } -// This function receives a list of capture formats, removes duplicated -// resolutions while keeping the highest frame rate for each, and forcing I420 -// pixel format. +// This function receives a list of capture formats, sets all of them to I420 +// (while keeping Y16 as is), and then removes duplicates. void ConsolidateCaptureFormats(media::VideoCaptureFormats* formats) { if (formats->empty()) return; - std::sort(formats->begin(), formats->end(), IsCaptureFormatSmaller); - // Due to the ordering imposed, the largest frame_rate is kept while removing - // duplicated resolutions. - media::VideoCaptureFormats::iterator last = - std::unique(formats->begin(), formats->end(), IsCaptureFormatSizeEqual); - formats->erase(last, formats->end()); // Mark all formats as I420, since this is what the renderer side will get // anyhow: the actual pixel format is decided at the device level. // Don't do this for Y16 format as it is handled separatelly. @@ -51,6 +46,11 @@ if (format.pixel_format != media::PIXEL_FORMAT_Y16) format.pixel_format = media::PIXEL_FORMAT_I420; } + std::sort(formats->begin(), formats->end(), IsCaptureFormatSmaller); + // Remove duplicates + media::VideoCaptureFormats::iterator last = + std::unique(formats->begin(), formats->end(), IsCaptureFormatEqual); + formats->erase(last, formats->end()); } } // anonymous namespace
diff --git a/media/capture/video/win/video_capture_device_factory_win.cc b/media/capture/video/win/video_capture_device_factory_win.cc index c044c52..18fa3681 100644 --- a/media/capture/video/win/video_capture_device_factory_win.cc +++ b/media/capture/video/win/video_capture_device_factory_win.cc
@@ -245,88 +245,13 @@ VideoCaptureFormats* formats) { DVLOG(1) << "GetDeviceSupportedFormatsDirectShow for " << descriptor.display_name; - ScopedComPtr<ICreateDevEnum> dev_enum; - HRESULT hr = ::CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, - IID_PPV_ARGS(&dev_enum)); - if (FAILED(hr)) - return; - - ScopedComPtr<IEnumMoniker> enum_moniker; - hr = dev_enum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, - enum_moniker.GetAddressOf(), 0); - // CreateClassEnumerator returns S_FALSE on some Windows OS when no camera - // exists. Therefore the FAILED macro can't be used. - if (hr != S_OK) - return; - - // Walk the capture devices. No need to check for device presence again since - // that is anyway needed in GetDeviceFilter(). "google camera adapter" and old - // VFW devices are already skipped previously in GetDeviceNames() enumeration. - base::win::ScopedComPtr<IBaseFilter> capture_filter; - hr = VideoCaptureDeviceWin::GetDeviceFilter(descriptor.device_id, - capture_filter.GetAddressOf()); - if (!capture_filter.Get()) { - DLOG(ERROR) << "Failed to create capture filter: " - << logging::SystemErrorCodeToString(hr); - return; - } - - base::win::ScopedComPtr<IPin> output_capture_pin( - VideoCaptureDeviceWin::GetPin(capture_filter.Get(), PINDIR_OUTPUT, - PIN_CATEGORY_CAPTURE, GUID_NULL)); - if (!output_capture_pin.Get()) { - DLOG(ERROR) << "Failed to get capture output pin"; - return; - } - - ScopedComPtr<IAMStreamConfig> stream_config; - hr = output_capture_pin.CopyTo(stream_config.GetAddressOf()); - if (FAILED(hr)) { - DLOG(ERROR) << "Failed to get IAMStreamConfig interface from " - "capture device: " << logging::SystemErrorCodeToString(hr); - return; - } - - int count = 0, size = 0; - hr = stream_config->GetNumberOfCapabilities(&count, &size); - if (FAILED(hr)) { - DLOG(ERROR) << "GetNumberOfCapabilities failed: " - << logging::SystemErrorCodeToString(hr); - return; - } - - std::unique_ptr<BYTE[]> caps(new BYTE[size]); - for (int i = 0; i < count; ++i) { - VideoCaptureDeviceWin::ScopedMediaType media_type; - hr = stream_config->GetStreamCaps(i, media_type.Receive(), caps.get()); - // GetStreamCaps() may return S_FALSE, so don't use FAILED() or SUCCEED() - // macros here since they'll trigger incorrectly. - if (hr != S_OK || !media_type.get()) { - DLOG(ERROR) << "GetStreamCaps failed: " - << logging::SystemErrorCodeToString(hr); - return; - } - - if (media_type->majortype == MEDIATYPE_Video && - media_type->formattype == FORMAT_VideoInfo) { - VideoCaptureFormat format; - format.pixel_format = - VideoCaptureDeviceWin::TranslateMediaSubtypeToPixelFormat( - media_type->subtype); - if (format.pixel_format == PIXEL_FORMAT_UNKNOWN) - continue; - VIDEOINFOHEADER* h = - reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat); - format.frame_size.SetSize(h->bmiHeader.biWidth, h->bmiHeader.biHeight); - // Trust the frame rate from the VIDEOINFOHEADER. - format.frame_rate = - (h->AvgTimePerFrame > 0) - ? kSecondsToReferenceTime / static_cast<float>(h->AvgTimePerFrame) - : 0.0f; - formats->push_back(format); - DVLOG(1) << descriptor.display_name << " " - << VideoCaptureFormat::ToString(format); - } + CapabilityList capability_list; + VideoCaptureDeviceWin::GetDeviceCapabilityList(descriptor.device_id, + &capability_list); + for (const auto& entry : capability_list) { + formats->emplace_back(entry.supported_format); + DVLOG(1) << descriptor.display_name << " " + << VideoCaptureFormat::ToString(entry.supported_format); } }
diff --git a/media/capture/video/win/video_capture_device_win.cc b/media/capture/video/win/video_capture_device_win.cc index b1c90bc..1c010fe 100644 --- a/media/capture/video/win/video_capture_device_win.cc +++ b/media/capture/video/win/video_capture_device_win.cc
@@ -101,6 +101,120 @@ return control_range; } +// static +void VideoCaptureDeviceWin::GetDeviceCapabilityList( + const std::string& device_id, + CapabilityList* out_capability_list) { + base::win::ScopedComPtr<IBaseFilter> capture_filter; + HRESULT hr = VideoCaptureDeviceWin::GetDeviceFilter( + device_id, capture_filter.GetAddressOf()); + if (!capture_filter.Get()) { + DLOG(ERROR) << "Failed to create capture filter: " + << logging::SystemErrorCodeToString(hr); + return; + } + + base::win::ScopedComPtr<IPin> output_capture_pin( + VideoCaptureDeviceWin::GetPin(capture_filter.Get(), PINDIR_OUTPUT, + PIN_CATEGORY_CAPTURE, GUID_NULL)); + if (!output_capture_pin.Get()) { + DLOG(ERROR) << "Failed to get capture output pin"; + return; + } + + GetPinCapabilityList(capture_filter, output_capture_pin, out_capability_list); +} + +// static +void VideoCaptureDeviceWin::GetPinCapabilityList( + base::win::ScopedComPtr<IBaseFilter> capture_filter, + base::win::ScopedComPtr<IPin> output_capture_pin, + CapabilityList* out_capability_list) { + ScopedComPtr<IAMStreamConfig> stream_config; + HRESULT hr = output_capture_pin.CopyTo(stream_config.GetAddressOf()); + if (FAILED(hr)) { + DLOG(ERROR) << "Failed to get IAMStreamConfig interface from " + "capture device: " + << logging::SystemErrorCodeToString(hr); + return; + } + + // Get interface used for getting the frame rate. + ScopedComPtr<IAMVideoControl> video_control; + hr = capture_filter.CopyTo(video_control.GetAddressOf()); + + int count = 0, size = 0; + hr = stream_config->GetNumberOfCapabilities(&count, &size); + if (FAILED(hr)) { + DLOG(ERROR) << "GetNumberOfCapabilities failed: " + << logging::SystemErrorCodeToString(hr); + return; + } + + std::unique_ptr<BYTE[]> caps(new BYTE[size]); + for (int i = 0; i < count; ++i) { + VideoCaptureDeviceWin::ScopedMediaType media_type; + hr = stream_config->GetStreamCaps(i, media_type.Receive(), caps.get()); + // GetStreamCaps() may return S_FALSE, so don't use FAILED() or SUCCEED() + // macros here since they'll trigger incorrectly. + if (hr != S_OK || !media_type.get()) { + DLOG(ERROR) << "GetStreamCaps failed: " + << logging::SystemErrorCodeToString(hr); + return; + } + + if (media_type->majortype == MEDIATYPE_Video && + media_type->formattype == FORMAT_VideoInfo) { + VideoCaptureFormat format; + format.pixel_format = + VideoCaptureDeviceWin::TranslateMediaSubtypeToPixelFormat( + media_type->subtype); + if (format.pixel_format == PIXEL_FORMAT_UNKNOWN) + continue; + VIDEOINFOHEADER* h = + reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat); + format.frame_size.SetSize(h->bmiHeader.biWidth, h->bmiHeader.biHeight); + + // Try to get a better |time_per_frame| from IAMVideoControl. If not, use + // the value from VIDEOINFOHEADER. + std::vector<float> frame_rates; + if (video_control.Get()) { + ScopedCoMem<LONGLONG> time_per_frame_list; + LONG list_size = 0; + const SIZE size = {format.frame_size.width(), + format.frame_size.height()}; + hr = video_control->GetFrameRateList(output_capture_pin.Get(), i, size, + &list_size, &time_per_frame_list); + // Sometimes |list_size| will be > 0, but time_per_frame_list will be + // NULL. Some drivers may return an HRESULT of S_FALSE which SUCCEEDED() + // translates into success, so explicitly check S_OK. + // See http://crbug.com/306237. + if (hr == S_OK && list_size > 0 && time_per_frame_list) { + for (int k = 0; k < list_size; k++) { + LONGLONG time_per_frame = *(time_per_frame_list + k); + if (time_per_frame <= 0) + continue; + frame_rates.push_back(kSecondsToReferenceTime / + static_cast<float>(time_per_frame)); + } + } + } + + if (frame_rates.empty() && h->AvgTimePerFrame > 0) { + frame_rates.push_back(kSecondsToReferenceTime / + static_cast<float>(h->AvgTimePerFrame)); + } + if (frame_rates.empty()) + frame_rates.push_back(0.0f); + + for (const auto& frame_rate : frame_rates) { + format.frame_rate = frame_rate; + out_capability_list->emplace_back(i, format, h->bmiHeader); + } + } + } +} + // Finds and creates a DirectShow Video Capture filter matching the |device_id|. // static HRESULT VideoCaptureDeviceWin::GetDeviceFilter(const std::string& device_id, @@ -746,77 +860,7 @@ bool VideoCaptureDeviceWin::CreateCapabilityMap() { DCHECK(thread_checker_.CalledOnValidThread()); - ScopedComPtr<IAMStreamConfig> stream_config; - HRESULT hr = output_capture_pin_.CopyTo(stream_config.GetAddressOf()); - DLOG_IF_FAILED_WITH_HRESULT( - "Failed to get IAMStreamConfig from capture device", hr); - if (FAILED(hr)) - return false; - - // Get interface used for getting the frame rate. - ScopedComPtr<IAMVideoControl> video_control; - hr = capture_filter_.CopyTo(video_control.GetAddressOf()); - - int count = 0, size = 0; - hr = stream_config->GetNumberOfCapabilities(&count, &size); - DLOG_IF_FAILED_WITH_HRESULT("Failed to GetNumberOfCapabilities", hr); - if (FAILED(hr)) - return false; - - std::unique_ptr<BYTE[]> caps(new BYTE[size]); - for (int stream_index = 0; stream_index < count; ++stream_index) { - ScopedMediaType media_type; - hr = stream_config->GetStreamCaps(stream_index, media_type.Receive(), - caps.get()); - // GetStreamCaps() may return S_FALSE, so don't use FAILED() or SUCCEED() - // macros here since they'll trigger incorrectly. - if (hr != S_OK) { - DLOG(ERROR) << "Failed to GetStreamCaps"; - return false; - } - - if (media_type->majortype == MEDIATYPE_Video && - media_type->formattype == FORMAT_VideoInfo) { - VideoCaptureFormat format; - format.pixel_format = - TranslateMediaSubtypeToPixelFormat(media_type->subtype); - if (format.pixel_format == PIXEL_FORMAT_UNKNOWN) - continue; - - VIDEOINFOHEADER* h = - reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat); - format.frame_size.SetSize(h->bmiHeader.biWidth, h->bmiHeader.biHeight); - - // Try to get a better |time_per_frame| from IAMVideoControl. If not, use - // the value from VIDEOINFOHEADER. - REFERENCE_TIME time_per_frame = h->AvgTimePerFrame; - if (video_control.Get()) { - ScopedCoMem<LONGLONG> max_fps; - LONG list_size = 0; - const SIZE size = {format.frame_size.width(), - format.frame_size.height()}; - hr = video_control->GetFrameRateList(output_capture_pin_.Get(), - stream_index, size, &list_size, - &max_fps); - // Can't assume the first value will return the max fps. - // Sometimes |list_size| will be > 0, but max_fps will be NULL. Some - // drivers may return an HRESULT of S_FALSE which SUCCEEDED() translates - // into success, so explicitly check S_OK. See http://crbug.com/306237. - if (hr == S_OK && list_size > 0 && max_fps) { - time_per_frame = - *std::min_element(max_fps.get(), max_fps.get() + list_size); - } - } - - format.frame_rate = - (time_per_frame > 0) - ? (kSecondsToReferenceTime / static_cast<float>(time_per_frame)) - : 0.0; - - capabilities_.emplace_back(stream_index, format, h->bmiHeader); - } - } - + GetPinCapabilityList(capture_filter_, output_capture_pin_, &capabilities_); return !capabilities_.empty(); }
diff --git a/media/capture/video/win/video_capture_device_win.h b/media/capture/video/win/video_capture_device_win.h index 7ae6a710..facee7e3 100644 --- a/media/capture/video/win/video_capture_device_win.h +++ b/media/capture/video/win/video_capture_device_win.h
@@ -56,6 +56,12 @@ AM_MEDIA_TYPE* media_type_; }; + static void GetDeviceCapabilityList(const std::string& device_id, + CapabilityList* out_capability_list); + static void GetPinCapabilityList( + base::win::ScopedComPtr<IBaseFilter> capture_filter, + base::win::ScopedComPtr<IPin> output_capture_pin, + CapabilityList* out_capability_list); static HRESULT GetDeviceFilter(const std::string& device_id, IBaseFilter** filter); static base::win::ScopedComPtr<IPin> GetPin(IBaseFilter* filter,
diff --git a/media/filters/pipeline_controller.cc b/media/filters/pipeline_controller.cc index e5d0245..aad3e4f 100644 --- a/media/filters/pipeline_controller.cc +++ b/media/filters/pipeline_controller.cc
@@ -45,7 +45,7 @@ bool is_streaming, bool is_static) { DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(state_ == State::CREATED); + DCHECK_EQ(state_, State::STOPPED); DCHECK(demuxer); // Once the pipeline is started, we want to call the seeked callback but @@ -247,12 +247,18 @@ } void PipelineController::Stop() { - // For the moment, Stop() is only called on WMPI destruction, and updating the - // state of |this| is not relevant. Eventually, Start()/Stop() will be called - // in order to swap between demuxer types, and this will need to be adressed. - // - // TODO(tguilbert): Clarify the appropriate state changes when Stop() is - // called. See crbug.com/695734. + if (state_ == State::STOPPED) + return; + + demuxer_ = nullptr; + waiting_for_seek_ = false; + pending_seeked_cb_ = false; + pending_time_updated_ = false; + pending_seek_ = false; + pending_suspend_ = false; + pending_resume_ = false; + state_ = State::STOPPED; + pipeline_->Stop(); }
diff --git a/media/filters/pipeline_controller.h b/media/filters/pipeline_controller.h index 79cb14b..e8fce79 100644 --- a/media/filters/pipeline_controller.h +++ b/media/filters/pipeline_controller.h
@@ -30,7 +30,7 @@ class MEDIA_EXPORT PipelineController { public: enum class State { - CREATED, + STOPPED, STARTING, PLAYING, SEEKING, @@ -169,7 +169,7 @@ bool is_static_ = true; // Tracks the current state of |pipeline_|. - State state_ = State::CREATED; + State state_ = State::STOPPED; // Indicates that a seek has occurred. When set, a seeked callback will be // issued at the next stable state.
diff --git a/media/gpu/ipc/service/gpu_video_decode_accelerator.cc b/media/gpu/ipc/service/gpu_video_decode_accelerator.cc index 0394ce47..61c6b2e 100644 --- a/media/gpu/ipc/service/gpu_video_decode_accelerator.cc +++ b/media/gpu/ipc/service/gpu_video_decode_accelerator.cc
@@ -434,53 +434,58 @@ return; } for (size_t j = 0; j < textures_per_buffer_; j++) { - gpu::gles2::TextureRef* texture_ref = - texture_manager->GetTexture(buffer_texture_ids[j]); - if (!texture_ref) { + GLuint service_id = 0; + if (!command_decoder->GetServiceTextureId(buffer_texture_ids[j], + &service_id)) { DLOG(ERROR) << "Failed to find texture id " << buffer_texture_ids[j]; NotifyError(VideoDecodeAccelerator::INVALID_ARGUMENT); return; } - gpu::gles2::Texture* info = texture_ref->texture(); - if (info->target() != texture_target_) { - DLOG(ERROR) << "Texture target mismatch for texture id " - << buffer_texture_ids[j]; - NotifyError(VideoDecodeAccelerator::INVALID_ARGUMENT); - return; - } - if (texture_target_ == GL_TEXTURE_EXTERNAL_OES || - texture_target_ == GL_TEXTURE_RECTANGLE_ARB) { - // These textures have their dimensions defined by the underlying - // storage. - // Use |texture_dimensions_| for this size. - texture_manager->SetLevelInfo(texture_ref, texture_target_, 0, GL_RGBA, - texture_dimensions_.width(), - texture_dimensions_.height(), 1, 0, - GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); - } else { - // For other targets, texture dimensions should already be defined. - GLsizei width = 0, height = 0; - info->GetLevelSize(texture_target_, 0, &width, &height, nullptr); - if (width != texture_dimensions_.width() || - height != texture_dimensions_.height()) { - DLOG(ERROR) << "Size mismatch for texture id " + + gpu::gles2::TextureRef* texture_ref = + texture_manager->GetTexture(buffer_texture_ids[j]); + if (texture_ref) { + gpu::gles2::Texture* info = texture_ref->texture(); + if (info->target() != texture_target_) { + DLOG(ERROR) << "Texture target mismatch for texture id " << buffer_texture_ids[j]; NotifyError(VideoDecodeAccelerator::INVALID_ARGUMENT); return; } + if (texture_target_ == GL_TEXTURE_EXTERNAL_OES || + texture_target_ == GL_TEXTURE_RECTANGLE_ARB) { + // These textures have their dimensions defined by the underlying + // storage. + // Use |texture_dimensions_| for this size. + texture_manager->SetLevelInfo(texture_ref, texture_target_, 0, + GL_RGBA, texture_dimensions_.width(), + texture_dimensions_.height(), 1, 0, + GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); + } else { + // For other targets, texture dimensions should already be defined. + GLsizei width = 0, height = 0; + info->GetLevelSize(texture_target_, 0, &width, &height, nullptr); + if (width != texture_dimensions_.width() || + height != texture_dimensions_.height()) { + DLOG(ERROR) << "Size mismatch for texture id " + << buffer_texture_ids[j]; + NotifyError(VideoDecodeAccelerator::INVALID_ARGUMENT); + return; + } - // TODO(dshwang): after moving to D3D11, remove this. crbug.com/438691 - GLenum format = - video_decode_accelerator_.get()->GetSurfaceInternalFormat(); - if (format != GL_RGBA) { - DCHECK(format == GL_BGRA_EXT); - texture_manager->SetLevelInfo(texture_ref, texture_target_, 0, format, - width, height, 1, 0, format, - GL_UNSIGNED_BYTE, gfx::Rect()); + // TODO(dshwang): after moving to D3D11, remove this. crbug.com/438691 + GLenum format = + video_decode_accelerator_.get()->GetSurfaceInternalFormat(); + if (format != GL_RGBA) { + DCHECK(format == GL_BGRA_EXT); + texture_manager->SetLevelInfo(texture_ref, texture_target_, 0, + format, width, height, 1, 0, format, + GL_UNSIGNED_BYTE, gfx::Rect()); + } } + current_textures.push_back(texture_ref); } - service_ids.push_back(texture_ref->service_id()); - current_textures.push_back(texture_ref); + service_ids.push_back(service_id); } textures.push_back(current_textures); buffers.push_back(PictureBuffer(buffer_ids[i], texture_dimensions_,
diff --git a/media/renderers/video_renderer_impl.cc b/media/renderers/video_renderer_impl.cc index def6618..3418530 100644 --- a/media/renderers/video_renderer_impl.cc +++ b/media/renderers/video_renderer_impl.cc
@@ -557,35 +557,62 @@ // Paint the first frame if possible and necessary. Paint ahead of // HAVE_ENOUGH_DATA to ensure the user sees the frame as early as possible. + bool just_painted_first_frame = false; if (!sink_started_ && algorithm_->frames_queued() && !painted_first_frame_) { // We want to paint the first frame under two conditions: Either (1) we have // enough frames to know it's definitely the first frame or (2) there may be // no more frames coming (sometimes unless we paint one of them). // - // For the first condition, we need at least two frames or the first frame - // must have a timestamp >= |start_timestamp_|, since otherwise we may be - // prerolling frames before the actual start time that will be dropped. - if (algorithm_->frames_queued() > 1 || received_end_of_stream_ || - frame->timestamp() >= start_timestamp_ || low_delay_ || - !video_frame_stream_->CanReadWithoutStalling()) { + // For the first condition, we need at least two effective frames, since + // otherwise we may be prerolling frames before the actual start time that + // will be dropped. + bool should_paint_first_frame = + algorithm_->effective_frames_queued() > 1 || received_end_of_stream_ || + !video_frame_stream_->CanReadWithoutStalling(); + + // For the very first frame (i.e. not after seeks), we want to paint as fast + // as possible to ensure users don't abandon the playback. For live streams + // with long duration frames, waiting for a second frame may take seconds. + // + // Before time starts progressing we may not know if frames are effective or + // not, so the first frame must check if timestamp >= |start_timestamp_|. + // + // We only do this for the very first frame ever painted, since later frames + // risk being wrong due to the lack of duration on the first frame. This + // avoids any fast-forward or frame-flipping type effects as we try to + // resume after a seek. + if (!have_renderered_frames_ && !should_paint_first_frame) { + should_paint_first_frame = + frame->timestamp() >= start_timestamp_ || low_delay_; + } + + if (should_paint_first_frame) { scoped_refptr<VideoFrame> first_frame = algorithm_->Render(base::TimeTicks(), base::TimeTicks(), nullptr); CheckForMetadataChanges(first_frame->format(), first_frame->natural_size()); sink_->PaintSingleFrame(first_frame); - painted_first_frame_ = true; + just_painted_first_frame = painted_first_frame_ = true; } } // Signal buffering state if we've met our conditions. - if (buffering_state_ == BUFFERING_HAVE_NOTHING && HaveEnoughData_Locked()) + // + // If we've just painted the first frame, require the standard 1 frame for low + // latency playback. If we're resuming after a Flush(), wait until we have two + // frames even in low delay mode to avoid any kind of fast-forward or frame + // flipping effect while we attempt to find the best frame. + if (buffering_state_ == BUFFERING_HAVE_NOTHING && + HaveEnoughData_Locked(just_painted_first_frame ? 1u : 2u)) { TransitionToHaveEnough_Locked(); + } // Always request more decoded video if we have capacity. AttemptRead_Locked(); } -bool VideoRendererImpl::HaveEnoughData_Locked() { +bool VideoRendererImpl::HaveEnoughData_Locked( + size_t low_latency_frames_required) const { DCHECK_EQ(state_, kPlaying); lock_.AssertAcquired(); @@ -602,10 +629,16 @@ if (was_background_rendering_ && frames_decoded_) return true; - if (!low_delay_ && video_frame_stream_->CanReadWithoutStalling()) + // Note: We still require an effective frame in the stalling case since this + // method is also used to inform TransitionToHaveNothing_Locked() and thus + // would never pause and rebuffer if we always return true here. + if (!video_frame_stream_->CanReadWithoutStalling()) + return algorithm_->effective_frames_queued() > 0u; + + if (!low_delay_) return false; - return algorithm_->effective_frames_queued() > 0; + return algorithm_->effective_frames_queued() >= low_latency_frames_required; } void VideoRendererImpl::TransitionToHaveEnough_Locked() { @@ -725,7 +758,7 @@ } } -bool VideoRendererImpl::HaveReachedBufferingCap() { +bool VideoRendererImpl::HaveReachedBufferingCap() const { DCHECK(task_runner_->BelongsToCurrentThread()); if (use_complexity_based_buffering_)
diff --git a/media/renderers/video_renderer_impl.h b/media/renderers/video_renderer_impl.h index 2785bed..0cf59f82 100644 --- a/media/renderers/video_renderer_impl.h +++ b/media/renderers/video_renderer_impl.h
@@ -140,7 +140,12 @@ // Returns true if the renderer has enough data for playback purposes. // Note that having enough data may be due to reaching end of stream. - bool HaveEnoughData_Locked(); + // + // |low_latency_frames_required| indicates the required number of frame for + // have enough with a low latency playback. By default it's one frame, but + // during resume after a Flush() we may wait for 2 frames to ensure we have + // effective frames. + bool HaveEnoughData_Locked(size_t low_latency_frames_required = 1u) const; void TransitionToHaveEnough_Locked(); void TransitionToHaveNothing(); void TransitionToHaveNothing_Locked(); @@ -150,7 +155,7 @@ void UpdateStats_Locked(); // Returns true if there is no more room for additional buffered frames. - bool HaveReachedBufferingCap(); + bool HaveReachedBufferingCap() const; // Starts or stops |sink_| respectively. Do not call while |lock_| is held. void StartSink();
diff --git a/media/renderers/video_renderer_impl_unittest.cc b/media/renderers/video_renderer_impl_unittest.cc index eea5882..486ae88 100644 --- a/media/renderers/video_renderer_impl_unittest.cc +++ b/media/renderers/video_renderer_impl_unittest.cc
@@ -433,13 +433,14 @@ EXPECT_CALL(mock_cb_, OnStatisticsUpdate(_)).Times(AnyNumber()); EXPECT_CALL(mock_cb_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) .WillOnce(RunClosure(event.GetClosure())); + // Note: In the normal underflow case we queue 5 frames here instead of // four since the underflow increases the number of required frames to // reach the have enough state. if (type == UnderflowTestType::NORMAL) QueueFrames("80 100 120 140 160"); else - QueueFrames("40 60 80 90"); + QueueFrames("40 60 80 90 100"); SatisfyPendingDecode(); event.RunAndWait(); }
diff --git a/media/test/data/load_many_videos.html b/media/test/data/load_many_videos.html deleted file mode 100644 index 0eacf6f..0000000 --- a/media/test/data/load_many_videos.html +++ /dev/null
@@ -1,64 +0,0 @@ -<!-- -Loads lots of videos to make sure that we don't deadlock somewhere -while loading lots of videos. We try a variety of video formats and -containers to try to cover different read patterns. ---> -<html> -<body onload="RunTest();"> -<video controls preload=audo src="bear-320x180-hi10p.mp4"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?A"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?B"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?C"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?D"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?E"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?F"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?G"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?H"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?I"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?J"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?K"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?L"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?M"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?N"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?O"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?P"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?Q"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?R"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?S"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?T"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?U"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?V"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?W"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?X"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?Y"></video><br> -<video controls preload=audo src="bear-320x180-hi10p.mp4?Z"></video><br> -<video controls preload=audo src="bear-1280x720.mp4"></video><br> -<video controls preload=audo src="bear-320x240.webm"></video><br> -<video controls preload=audo src="bear.mp4"></video><br> -<video controls preload=audo src="bear-vp8a.webm"></video><br> -<video controls preload=audo src="bear-320x240-video-only.webm"></video><br> -<video controls preload=audo src="bear-320x240-vp9_profile2.webm"></video><br> -<video controls preload=audo src="bear-320x180-hi12p-vp9.webm"></video><br> -<video controls preload=audo src="bbb-320x240-2video-2audio.mp4"></video><br> -<video controls preload=audo src="bear-1280x720-av_with-aud-nalus_frag.mp4"></video><br> -<video controls preload=audo src="bear-vp8-webvtt.webm"></video><br> -</body> - -<script> - function CheckIfDone() { - console.log("Done?"); - var players = document.getElementsByTagName("video"); - for (var i = 0; i < players.length; i++) { - if (players[i].readyState < 4) return; - } - document.title = "ENDED"; - } - function RunTest() { - var players = document.getElementsByTagName("video"); - for (var i = 0; i < players.length; i++) { - players[i].addEventListener('canplaythrough', function(e) { CheckIfDone(); }); - } - CheckIfDone(); - } -</script> -</html>
diff --git a/media/test/pipeline_integration_test_base.cc b/media/test/pipeline_integration_test_base.cc index cae4034..6f08481 100644 --- a/media/test/pipeline_integration_test_base.cc +++ b/media/test/pipeline_integration_test_base.cc
@@ -192,6 +192,7 @@ void PipelineIntegrationTestBase::OnError(PipelineStatus status) { DCHECK_NE(status, PIPELINE_OK); pipeline_status_ = status; + pipeline_->Stop(); scoped_task_environment_.GetMainThreadTaskRunner()->PostTask( FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); }
diff --git a/mojo/edk/embedder/README.md b/mojo/edk/embedder/README.md index 99ec23e..2e7c02d 100644 --- a/mojo/edk/embedder/README.md +++ b/mojo/edk/embedder/README.md
@@ -59,7 +59,7 @@ base::Thread ipc_thread("ipc!"); ipc_thread.StartWithOptions( - base::Thread::Options(base::MessageLoop::TYPE_IO)); + base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); // As long as this object is alive, all EDK API surface relevant to IPC // connections is usable and message pipes which span a process boundary will @@ -120,7 +120,7 @@ base::Thread ipc_thread("ipc!"); ipc_thread.StartWithOptions( - base::Thread::Options(base::MessageLoop::TYPE_IO)); + base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); mojo::edk::ScopedIPCSupport ipc_support( ipc_thread.task_runner(), @@ -164,7 +164,7 @@ base::Thread ipc_thread("ipc!"); ipc_thread.StartWithOptions( - base::Thread::Options(base::MessageLoop::TYPE_IO)); + base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); mojo::edk::ScopedIPCSupport ipc_support( ipc_thread.task_runner(), @@ -212,7 +212,7 @@ base::Thread ipc_thread("ipc!"); ipc_thread.StartWithOptions( - base::Thread::Options(base::MessageLoop::TYPE_IO)); + base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); mojo::edk::ScopedIPCSupport ipc_support( ipc_thread.task_runner(),
diff --git a/mojo/public/cpp/bindings/interface_id.h b/mojo/public/cpp/bindings/interface_id.h index 53475d6..d612853 100644 --- a/mojo/public/cpp/bindings/interface_id.h +++ b/mojo/public/cpp/bindings/interface_id.h
@@ -30,6 +30,10 @@ return id != kInvalidInterfaceId; } +inline bool HasInterfaceIdNamespaceBitSet(InterfaceId id) { + return (id & kInterfaceIdNamespaceMask) != 0; +} + } // namespace mojo #endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ID_H_
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.cc b/mojo/public/cpp/bindings/lib/multiplex_router.cc index 54fae5c8..031822c 100644 --- a/mojo/public/cpp/bindings/lib/multiplex_router.cc +++ b/mojo/public/cpp/bindings/lib/multiplex_router.cc
@@ -442,6 +442,14 @@ if (!IsValidInterfaceId(id)) return ScopedInterfaceEndpointHandle(); + // Unless it is the master ID, |id| is from the remote side and therefore its + // namespace bit is supposed to be different than the value that this router + // would use. + if (!IsMasterInterfaceId(id) && + set_interface_id_namespace_bit_ == HasInterfaceIdNamespaceBitSet(id)) { + return ScopedInterfaceEndpointHandle(); + } + MayAutoLock locker(&lock_); bool inserted = false; InterfaceEndpoint* endpoint = FindOrInsertEndpoint(id, &inserted); @@ -451,13 +459,13 @@ if (encountered_error_) UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); } else { - // If the endpoint already exist, it is because we have received a - // notification that the peer endpoint has closed. - CHECK(!endpoint->closed()); - CHECK(endpoint->peer_closed()); - if (endpoint->handle_created()) return ScopedInterfaceEndpointHandle(); + + // If the endpoint already exist, it is because we have received a + // notification that the peer endpoint has closed. + DCHECK(!endpoint->closed()); + DCHECK(endpoint->peer_closed()); } endpoint->set_handle_created();
diff --git a/mojo/public/js/new_bindings/interface_types.js b/mojo/public/js/new_bindings/interface_types.js index 3d35e8c..b7085e5a 100644 --- a/mojo/public/js/new_bindings/interface_types.js +++ b/mojo/public/js/new_bindings/interface_types.js
@@ -77,12 +77,20 @@ return interfaceId !== kInvalidInterfaceId; } + function hasInterfaceIdNamespaceBitSet(interfaceId) { + if (interfaceId >= 2 * kInterfaceIdNamespaceMask) { + throw new Error("Interface ID should be a 32-bit unsigned integer."); + } + return interfaceId >= kInterfaceIdNamespaceMask; + } + mojo.InterfacePtrInfo = InterfacePtrInfo; mojo.InterfaceRequest = InterfaceRequest; mojo.AssociatedInterfacePtrInfo = AssociatedInterfacePtrInfo; mojo.AssociatedInterfaceRequest = AssociatedInterfaceRequest; internal.isMasterInterfaceId = isMasterInterfaceId; internal.isValidInterfaceId = isValidInterfaceId; + internal.hasInterfaceIdNamespaceBitSet = hasInterfaceIdNamespaceBitSet; internal.kInvalidInterfaceId = kInvalidInterfaceId; internal.kMasterInterfaceId = kMasterInterfaceId; internal.kInterfaceIdNamespaceMask = kInterfaceIdNamespaceMask;
diff --git a/mojo/public/js/new_bindings/router.js b/mojo/public/js/new_bindings/router.js index c7065dc..9aab9c2 100644 --- a/mojo/public/js/new_bindings/router.js +++ b/mojo/public/js/new_bindings/router.js
@@ -165,6 +165,15 @@ return new internal.InterfaceEndpointHandle(); } + // Unless it is the master ID, |interfaceId| is from the remote side and + // therefore its namespace bit is supposed to be different than the value + // that this router would use. + if (!internal.isMasterInterfaceId(interfaceId) && + this.setInterfaceIdNamespaceBit_ === + internal.hasInterfaceIdNamespaceBitSet(interfaceId)) { + return new internal.InterfaceEndpointHandle(); + } + var endpoint = this.endpoints_.get(interfaceId); if (!endpoint) {
diff --git a/mojo/public/js/router.js b/mojo/public/js/router.js index 5fc0ed56..805f663 100644 --- a/mojo/public/js/router.js +++ b/mojo/public/js/router.js
@@ -194,14 +194,14 @@ EndpointStateUpdateType.PEER_ENDPOINT_CLOSED); } } else { + if (endpoint.handleCreated) { + return new InterfaceEndpointHandle(); + } + // If the endpoint already exist, it is because we have received a // notification that the peer endpoint has closed. check(!endpoint.closed); check(endpoint.peerClosed); - - if (endpoint.handleCreated) { - return new InterfaceEndpointHandle(); - } } endpoint.handleCreated = true;
diff --git a/net/base/network_change_notifier.h b/net/base/network_change_notifier.h index 6678979..cf45ab7 100644 --- a/net/base/network_change_notifier.h +++ b/net/base/network_change_notifier.h
@@ -103,6 +103,7 @@ SUBTYPE_LAST = SUBTYPE_WIFI_AD }; + // DEPRECATED. Please use NetworkChangeObserver instead. crbug.com/754695. class NET_EXPORT IPAddressObserver { public: // Will be called when the IP address of the primary interface changes. @@ -117,6 +118,7 @@ DISALLOW_COPY_AND_ASSIGN(IPAddressObserver); }; + // DEPRECATED. Please use NetworkChangeObserver instead. crbug.com/754695. class NET_EXPORT ConnectionTypeObserver { public: // Will be called when the connection type of the system has changed. @@ -374,7 +376,12 @@ // called back with notifications. This is safe to call if Create() has not // been called (as long as it doesn't race the Create() call on another // thread), in which case it will simply do nothing. + + // DEPRECATED. IPAddressObserver is deprecated. Please use + // NetworkChangeObserver instead. crbug.com/754695. static void AddIPAddressObserver(IPAddressObserver* observer); + // DEPRECATED. ConnectionTypeObserver is deprecated. Please use + // NetworkChangeObserver instead. crbug.com/754695. static void AddConnectionTypeObserver(ConnectionTypeObserver* observer); static void AddDNSObserver(DNSObserver* observer); static void AddNetworkChangeObserver(NetworkChangeObserver* observer); @@ -388,7 +395,12 @@ // nothing. Technically, it's also safe to call after the notifier object has // been destroyed, if the call doesn't race the notifier's destruction, but // there's no reason to use the API in this risky way, so don't do it. + + // DEPRECATED. IPAddressObserver is deprecated. Please use + // NetworkChangeObserver instead. crbug.com/754695. static void RemoveIPAddressObserver(IPAddressObserver* observer); + // DEPRECATED. ConnectionTypeObserver is deprecated. Please use + // NetworkChangeObserver instead. crbug.com/754695. static void RemoveConnectionTypeObserver(ConnectionTypeObserver* observer); static void RemoveDNSObserver(DNSObserver* observer); static void RemoveNetworkChangeObserver(NetworkChangeObserver* observer);
diff --git a/net/dns/host_resolver_impl.cc b/net/dns/host_resolver_impl.cc index f6b1b8fa..422a8e8 100644 --- a/net/dns/host_resolver_impl.cc +++ b/net/dns/host_resolver_impl.cc
@@ -2099,6 +2099,14 @@ MakeNotStale(stale_info); return net_error; } + + // Special-case localhost names, as per the recommendations in + // https://tools.ietf.org/html/draft-west-let-localhost-be-localhost. + if (ServeLocalhost(*key, info, addresses)) { + MakeNotStale(stale_info); + return OK; + } + if (ServeFromCache(*key, info, &net_error, addresses, allow_stale, stale_info)) { source_net_log.AddEvent(NetLogEventType::HOST_RESOLVER_IMPL_CACHE_HIT, @@ -2106,6 +2114,7 @@ // |ServeFromCache()| will set |*stale_info| as needed. return net_error; } + // TODO(szym): Do not do this if nsswitch.conf instructs not to. // http://crbug.com/117655 if (ServeFromHosts(*key, info, addresses)) { @@ -2115,11 +2124,6 @@ return OK; } - if (ServeLocalhost(*key, info, addresses)) { - MakeNotStale(stale_info); - return OK; - } - return ERR_DNS_CACHE_MISS; }
diff --git a/net/dns/host_resolver_impl_unittest.cc b/net/dns/host_resolver_impl_unittest.cc index 9b3b3948..249419c 100644 --- a/net/dns/host_resolver_impl_unittest.cc +++ b/net/dns/host_resolver_impl_unittest.cc
@@ -641,30 +641,6 @@ EXPECT_EQ("just.testing", proc_->GetCaptureList()[0].hostname); } -// RFC 6761 localhost names should always resolve to loopback. -TEST_F(HostResolverImplTest, LocalhostLookup) { - // Add a rule resolving localhost names to a non-loopback IP and test - // that they still resolves to loopback. - proc_->AddRuleForAllFamilies("foo.localhost", "192.168.1.42"); - proc_->AddRuleForAllFamilies("localhost", "192.168.1.42"); - proc_->AddRuleForAllFamilies("localhost.", "192.168.1.42"); - - Request* req0 = CreateRequest("foo.localhost", 80); - EXPECT_THAT(req0->Resolve(), IsOk()); - EXPECT_TRUE(req0->HasAddress("127.0.0.1", 80)); - EXPECT_TRUE(req0->HasAddress("::1", 80)); - - Request* req1 = CreateRequest("localhost", 80); - EXPECT_THAT(req1->Resolve(), IsOk()); - EXPECT_TRUE(req1->HasAddress("127.0.0.1", 80)); - EXPECT_TRUE(req1->HasAddress("::1", 80)); - - Request* req2 = CreateRequest("localhost.", 80); - EXPECT_THAT(req2->Resolve(), IsOk()); - EXPECT_TRUE(req2->HasAddress("127.0.0.1", 80)); - EXPECT_TRUE(req2->HasAddress("::1", 80)); -} - TEST_F(HostResolverImplTest, LocalhostIPV4IPV6Lookup) { Request* req1 = CreateRequest("localhost6", 80, MEDIUM, ADDRESS_FAMILY_IPV4); EXPECT_THAT(req1->Resolve(), IsOk()); @@ -1713,6 +1689,56 @@ // TODO(cbentzel): Test a mix of requests with different HostResolverFlags. +// RFC 6761 localhost names should always resolve to loopback. +TEST_F(HostResolverImplDnsTest, LocalhostLookup) { + // Add a rule resolving localhost names to a non-loopback IP and test + // that they still resolves to loopback. + proc_->AddRuleForAllFamilies("foo.localhost", "192.168.1.42"); + proc_->AddRuleForAllFamilies("localhost", "192.168.1.42"); + proc_->AddRuleForAllFamilies("localhost.", "192.168.1.42"); + + Request* req0 = CreateRequest("foo.localhost", 80); + EXPECT_THAT(req0->Resolve(), IsOk()); + EXPECT_TRUE(req0->HasAddress("127.0.0.1", 80)); + EXPECT_TRUE(req0->HasAddress("::1", 80)); + + Request* req1 = CreateRequest("localhost", 80); + EXPECT_THAT(req1->Resolve(), IsOk()); + EXPECT_TRUE(req1->HasAddress("127.0.0.1", 80)); + EXPECT_TRUE(req1->HasAddress("::1", 80)); + + Request* req2 = CreateRequest("localhost.", 80); + EXPECT_THAT(req2->Resolve(), IsOk()); + EXPECT_TRUE(req2->HasAddress("127.0.0.1", 80)); + EXPECT_TRUE(req2->HasAddress("::1", 80)); +} + +// RFC 6761 localhost names should always resolve to loopback, even if a HOSTS +// file is active. +TEST_F(HostResolverImplDnsTest, LocalhostLookupWithHosts) { + DnsHosts hosts; + hosts[DnsHostsKey("localhost", ADDRESS_FAMILY_IPV4)] = + IPAddress({192, 168, 1, 1}); + hosts[DnsHostsKey("foo.localhost", ADDRESS_FAMILY_IPV4)] = + IPAddress({192, 168, 1, 2}); + + DnsConfig config = CreateValidDnsConfig(); + config.hosts = hosts; + ChangeDnsConfig(config); + + Request* req1 = CreateRequest("localhost", 80); + EXPECT_THAT(req1->Resolve(), IsOk()); + EXPECT_TRUE(req1->HasAddress("127.0.0.1", 80)); + EXPECT_TRUE(req1->HasAddress("::1", 80)); + EXPECT_FALSE(req1->HasAddress("192.168.1.1", 80)); + + Request* req2 = CreateRequest("foo.localhost", 80); + EXPECT_THAT(req2->Resolve(), IsOk()); + EXPECT_TRUE(req2->HasAddress("127.0.0.1", 80)); + EXPECT_TRUE(req2->HasAddress("::1", 80)); + EXPECT_FALSE(req2->HasAddress("192.168.1.2", 80)); +} + // Test successful and fallback resolutions in HostResolverImpl::DnsTask. TEST_F(HostResolverImplDnsTest, DnsTask) { proc_->AddRuleForAllFamilies("nx_succeed", "192.168.1.102"); @@ -2102,8 +2128,11 @@ // Expect synchronous resolution from DnsHosts. EXPECT_THAT(req->Resolve(), IsOk()); - EXPECT_EQ(saw_ipv4, req->HasAddress("127.0.0.1", 80)); - EXPECT_EQ(saw_ipv6, req->HasAddress("::1", 80)); + // Localhost names always resolve to IPv4 and IPv6, regardless of the content + // written into the HOSTS file above based on the results of the + // SystemHostResolverCall at the top of this test. + EXPECT_TRUE(req->HasAddress("127.0.0.1", 80)); + EXPECT_TRUE(req->HasAddress("::1", 80)); } // Cancel a request with a single DNS transaction active.
diff --git a/net/quic/chromium/quic_chromium_client_session.h b/net/quic/chromium/quic_chromium_client_session.h index a443e4a09..73d3f05 100644 --- a/net/quic/chromium/quic_chromium_client_session.h +++ b/net/quic/chromium/quic_chromium_client_session.h
@@ -475,6 +475,8 @@ // TODO(xunjieli): It only tracks |packet_readers_|. Write a better estimate. size_t EstimateMemoryUsage() const; + bool require_confirmation() const { return require_confirmation_; } + protected: // QuicSession methods: bool ShouldCreateIncomingDynamicStream(QuicStreamId id) override;
diff --git a/net/quic/chromium/quic_chromium_packet_reader.cc b/net/quic/chromium/quic_chromium_packet_reader.cc index 97e649e..816ad536 100644 --- a/net/quic/chromium/quic_chromium_packet_reader.cc +++ b/net/quic/chromium/quic_chromium_packet_reader.cc
@@ -35,34 +35,38 @@ QuicChromiumPacketReader::~QuicChromiumPacketReader() {} void QuicChromiumPacketReader::StartReading() { - if (read_pending_) - return; + for (;;) { + if (read_pending_) + return; - if (num_packets_read_ == 0) - yield_after_ = clock_->Now() + yield_after_duration_; + if (num_packets_read_ == 0) + yield_after_ = clock_->Now() + yield_after_duration_; - DCHECK(socket_); - read_pending_ = true; - int rv = socket_->Read(read_buffer_.get(), read_buffer_->size(), - base::Bind(&QuicChromiumPacketReader::OnReadComplete, - weak_factory_.GetWeakPtr())); - UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.AsyncRead", rv == ERR_IO_PENDING); - if (rv == ERR_IO_PENDING) { - num_packets_read_ = 0; - return; - } + DCHECK(socket_); + read_pending_ = true; + int rv = socket_->Read(read_buffer_.get(), read_buffer_->size(), + base::Bind(&QuicChromiumPacketReader::OnReadComplete, + weak_factory_.GetWeakPtr())); + UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.AsyncRead", rv == ERR_IO_PENDING); + if (rv == ERR_IO_PENDING) { + num_packets_read_ = 0; + return; + } - if (++num_packets_read_ > yield_after_packets_ || - clock_->Now() > yield_after_) { - num_packets_read_ = 0; - // Data was read, process it. - // Schedule the work through the message loop to 1) prevent infinite - // recursion and 2) avoid blocking the thread for too long. - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&QuicChromiumPacketReader::OnReadComplete, - weak_factory_.GetWeakPtr(), rv)); - } else { - OnReadComplete(rv); + if (++num_packets_read_ > yield_after_packets_ || + clock_->Now() > yield_after_) { + num_packets_read_ = 0; + // Data was read, process it. + // Schedule the work through the message loop to 1) prevent infinite + // recursion and 2) avoid blocking the thread for too long. + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&QuicChromiumPacketReader::OnReadComplete, + weak_factory_.GetWeakPtr(), rv)); + } else { + if (!ProcessReadResult(rv)) { + return; + } + } } } @@ -71,14 +75,14 @@ return kMaxPacketSize; } -void QuicChromiumPacketReader::OnReadComplete(int result) { +bool QuicChromiumPacketReader::ProcessReadResult(int result) { read_pending_ = false; if (result == 0) result = ERR_CONNECTION_CLOSED; if (result < 0) { visitor_->OnReadError(result, socket_); - return; + return false; } QuicReceivedPacket packet(read_buffer_->data(), result, clock_->Now()); @@ -86,12 +90,15 @@ IPEndPoint peer_address; socket_->GetLocalAddress(&local_address); socket_->GetPeerAddress(&peer_address); - if (!visitor_->OnPacket( - packet, QuicSocketAddress(QuicSocketAddressImpl(local_address)), - QuicSocketAddress(QuicSocketAddressImpl(peer_address)))) - return; + return visitor_->OnPacket( + packet, QuicSocketAddress(QuicSocketAddressImpl(local_address)), + QuicSocketAddress(QuicSocketAddressImpl(peer_address))); +} - StartReading(); +void QuicChromiumPacketReader::OnReadComplete(int result) { + if (ProcessReadResult(result)) { + StartReading(); + } } } // namespace net
diff --git a/net/quic/chromium/quic_chromium_packet_reader.h b/net/quic/chromium/quic_chromium_packet_reader.h index 113eeef..a7ad85a 100644 --- a/net/quic/chromium/quic_chromium_packet_reader.h +++ b/net/quic/chromium/quic_chromium_packet_reader.h
@@ -55,6 +55,8 @@ private: // A completion callback invoked when a read completes. void OnReadComplete(int result); + // Return true if reading should continue. + bool ProcessReadResult(int result); DatagramClientSocket* socket_; Visitor* visitor_;
diff --git a/net/quic/chromium/quic_stream_factory.cc b/net/quic/chromium/quic_stream_factory.cc index cee86b8..9572d01 100644 --- a/net/quic/chromium/quic_stream_factory.cc +++ b/net/quic/chromium/quic_stream_factory.cc
@@ -508,8 +508,7 @@ int QuicStreamFactory::Job::DoConnect() { io_state_ = STATE_CONNECT_COMPLETE; - bool require_confirmation = factory_->require_confirmation() || - was_alternative_service_recently_broken_; + bool require_confirmation = was_alternative_service_recently_broken_; net_log_.BeginEvent( NetLogEventType::QUIC_STREAM_FACTORY_JOB_CONNECT, NetLog::BoolCallback("require_confirmation", require_confirmation)); @@ -1533,6 +1532,11 @@ SocketPerformanceWatcherFactory::PROTOCOL_QUIC, address_list); } + // Wait for handshake confirmation before allowing streams to be created if + // either this session or the factory require confirmation. + if (require_confirmation_) + require_confirmation = true; + *session = new QuicChromiumClientSession( connection, std::move(socket), this, quic_crypto_client_stream_factory_, clock_, transport_security_state_, std::move(server_info), server_id,
diff --git a/net/quic/chromium/quic_stream_factory_test.cc b/net/quic/chromium/quic_stream_factory_test.cc index 1f474bfb..2fa53972 100644 --- a/net/quic/chromium/quic_stream_factory_test.cc +++ b/net/quic/chromium/quic_stream_factory_test.cc
@@ -222,7 +222,6 @@ allow_server_migration_, force_hol_blocking_, race_cert_verification_, estimate_initial_rtt_, connection_options_, client_connection_options_, /*enable_token_binding*/ false)); - factory_->set_require_confirmation(false); } void InitializeConnectionMigrationTest( @@ -469,6 +468,7 @@ store_server_configs_in_properties_ = true; idle_connection_timeout_seconds_ = 500; Initialize(); + factory_->set_require_confirmation(false); ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); @@ -781,8 +781,8 @@ EXPECT_EQ(OK, request3.Request(host_port_pair_, version_, privacy_mode_, /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); - stream = request3.CreateStream(); // Will reset stream 5. - stream.reset(); // Will reset stream 7. + stream = request3.CreateStream(); // Will reset stream 5. + stream.reset(); // Will reset stream 7. EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); @@ -790,6 +790,7 @@ TEST_P(QuicStreamFactoryTest, CreateZeroRtt) { Initialize(); + factory_->set_require_confirmation(false); ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); @@ -816,6 +817,7 @@ TEST_P(QuicStreamFactoryTest, CreateZeroRttPost) { Initialize(); + factory_->set_require_confirmation(false); ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); @@ -861,10 +863,75 @@ EXPECT_TRUE(stream.get()); QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); + EXPECT_TRUE(session->require_confirmation()); EXPECT_EQ(100000u, session->connection()->GetStats().srtt_us); ASSERT_FALSE(session->config()->HasInitialRoundTripTimeUsToSend()); } +TEST_P(QuicStreamFactoryTest, RequireConfirmation) { + crypto_client_stream_factory_.set_handshake_mode( + MockCryptoClientStream::ZERO_RTT); + host_resolver_.set_synchronous_mode(true); + host_resolver_.rules()->AddIPLiteralRule(host_port_pair_.host(), + "192.168.0.1", ""); + Initialize(); + factory_->set_require_confirmation(true); + ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + + MockQuicData socket_data; + socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + socket_data.AddWrite(ConstructInitialSettingsPacket()); + socket_data.AddSocketDataToFactory(&socket_factory_); + + QuicStreamRequest request(factory_.get()); + EXPECT_EQ(ERR_IO_PENDING, + request.Request(host_port_pair_, version_, privacy_mode_, + /*cert_verify_flags=*/0, url_, "GET", net_log_, + callback_.callback())); + + crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent( + QuicSession::HANDSHAKE_CONFIRMED); + + EXPECT_THAT(callback_.WaitForResult(), IsOk()); + std::unique_ptr<HttpStream> stream = request.CreateStream(); + EXPECT_TRUE(stream.get()); + + QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); + EXPECT_TRUE(session->require_confirmation()); +} + +TEST_P(QuicStreamFactoryTest, DontRequireConfirmationFromSameIP) { + crypto_client_stream_factory_.set_handshake_mode( + MockCryptoClientStream::ZERO_RTT); + host_resolver_.set_synchronous_mode(true); + host_resolver_.rules()->AddIPLiteralRule(host_port_pair_.host(), + "192.168.0.1", ""); + Initialize(); + factory_->set_require_confirmation(true); + http_server_properties_.SetSupportsQuic(IPAddress(192, 0, 2, 33)); + + ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + + MockQuicData socket_data; + socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + socket_data.AddWrite(ConstructInitialSettingsPacket()); + socket_data.AddSocketDataToFactory(&socket_factory_); + + QuicStreamRequest request(factory_.get()); + EXPECT_THAT(request.Request(host_port_pair_, version_, privacy_mode_, + /*cert_verify_flags=*/0, url_, "GET", net_log_, + callback_.callback()), + IsOk()); + + std::unique_ptr<HttpStream> stream = request.CreateStream(); + EXPECT_TRUE(stream.get()); + + QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); + EXPECT_FALSE(session->require_confirmation()); +} + TEST_P(QuicStreamFactoryTest, CachedInitialRtt) { ServerNetworkStats stats; stats.srtt = base::TimeDelta::FromMilliseconds(10); @@ -4269,6 +4336,7 @@ TEST_P(QuicStreamFactoryTest, EnableNotLoadFromDiskCache) { Initialize(); + factory_->set_require_confirmation(false); ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); @@ -4453,6 +4521,7 @@ TEST_P(QuicStreamFactoryTest, YieldAfterPackets) { Initialize(); + factory_->set_require_confirmation(false); ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); QuicStreamFactoryPeer::SetYieldAfterPackets(factory_.get(), 0); @@ -4497,6 +4566,7 @@ TEST_P(QuicStreamFactoryTest, YieldAfterDuration) { Initialize(); + factory_->set_require_confirmation(false); ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); QuicStreamFactoryPeer::SetYieldAfterDuration(
diff --git a/remoting/host/BUILD.gn b/remoting/host/BUILD.gn index 1bcad96..f14db57 100644 --- a/remoting/host/BUILD.gn +++ b/remoting/host/BUILD.gn
@@ -137,6 +137,8 @@ "dns_blackhole_checker.h", "evaluate_capability.cc", "evaluate_capability.h", + "file_proxy_wrapper.cc", + "file_proxy_wrapper.h", "file_transfer_message_handler.cc", "file_transfer_message_handler.h", "file_transfer_message_handler_factory.cc",
diff --git a/remoting/host/file_proxy_wrapper.cc b/remoting/host/file_proxy_wrapper.cc new file mode 100644 index 0000000..6e1aabc --- /dev/null +++ b/remoting/host/file_proxy_wrapper.cc
@@ -0,0 +1,13 @@ +// 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 "remoting/host/file_proxy_wrapper.h" + +namespace remoting { + +FileProxyWrapper::FileProxyWrapper() = default; + +FileProxyWrapper::~FileProxyWrapper() = default; + +} // namespace remoting
diff --git a/remoting/host/file_proxy_wrapper.h b/remoting/host/file_proxy_wrapper.h new file mode 100644 index 0000000..3065b3f --- /dev/null +++ b/remoting/host/file_proxy_wrapper.h
@@ -0,0 +1,39 @@ +// 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 REMOTING_HOST_FILE_PROXY_WRAPPER_H_ +#define REMOTING_HOST_FILE_PROXY_WRAPPER_H_ + +#include "base/callback.h" +#include "base/files/file_proxy.h" +#include "remoting/proto/file_transfer.pb.h" + +namespace remoting { + +class CompoundBuffer; + +// FileProxyWrapper is an interface for implementing platform-specific file +// writers for file transfers. Each operation is posted to a separate file IO +// thread, and possibly a different process depending on the platform. +class FileProxyWrapper { + public: + typedef base::Callback<void(protocol::FileTransferResponse_ErrorCode)> + ErrorCallback; + typedef base::Callback<void()> SuccessCallback; + + FileProxyWrapper(); + virtual ~FileProxyWrapper(); + + virtual void Init(const ErrorCallback& error_callback) = 0; + virtual void CreateFile(const std::string& filename, + uint64_t filesize, + const SuccessCallback& success_callback) = 0; + virtual void WriteChunk(std::unique_ptr<CompoundBuffer> buffer) = 0; + virtual void Close(const SuccessCallback& success_callback) = 0; + virtual void Cancel() = 0; +}; + +} // namespace remoting + +#endif // REMOTING_HOST_FILE_PROXY_WRAPPER_H_
diff --git a/services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer.cc b/services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer.cc index c6f2866..7d6b45c 100644 --- a/services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer.cc +++ b/services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer.cc
@@ -118,10 +118,8 @@ // angles. DCHECK(fusion_sensor_); - // Not generating a new sensor value when the |fusion_sensor_|'s reporting - // mode is ON_CHANGE and the accelerometer reading doesn't change. - if (fusion_sensor_->GetReportingMode() == mojom::ReportingMode::ON_CHANGE && - which_sensor_changed != mojom::SensorType::ACCELEROMETER) { + // Only generate a new sensor value when the accelerometer reading changes. + if (which_sensor_changed != mojom::SensorType::ACCELEROMETER) { return false; }
diff --git a/services/device/generic_sensor/generic_sensor_service_unittest.cc b/services/device/generic_sensor/generic_sensor_service_unittest.cc index 79147698..f3ae3d98 100644 --- a/services/device/generic_sensor/generic_sensor_service_unittest.cc +++ b/services/device/generic_sensor/generic_sensor_service_unittest.cc
@@ -53,7 +53,7 @@ if (GetType() == SensorType::AMBIENT_LIGHT) { // Set the shared buffer value as frequency for testing purpose. reading.als.value = configuration.frequency(); - UpdateSensorReading(reading, true); + UpdateSensorReading(reading); } return true; }
diff --git a/services/device/generic_sensor/platform_sensor.cc b/services/device/generic_sensor/platform_sensor.cc index 7bdf40c..c77be98 100644 --- a/services/device/generic_sensor/platform_sensor.cc +++ b/services/device/generic_sensor/platform_sensor.cc
@@ -6,6 +6,7 @@ #include <utility> +#include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/threading/thread_task_runner_handle.h" #include "services/device/generic_sensor/platform_sensor_provider.h" @@ -103,8 +104,7 @@ return shared_buffer_reader_->GetReading(result); } -void PlatformSensor::UpdateSensorReading(const SensorReading& reading, - bool notify_clients) { +void PlatformSensor::UpdateSensorReading(const SensorReading& reading) { ReadingBuffer* buffer = static_cast<ReadingBuffer*>(shared_buffer_mapping_.get()); auto& seqlock = buffer->seqlock.value(); @@ -112,10 +112,9 @@ buffer->reading = reading; seqlock.WriteEnd(); - if (notify_clients) - task_runner_->PostTask( - FROM_HERE, base::Bind(&PlatformSensor::NotifySensorReadingChanged, - weak_factory_.GetWeakPtr())); + task_runner_->PostTask(FROM_HERE, + base::Bind(&PlatformSensor::NotifySensorReadingChanged, + weak_factory_.GetWeakPtr())); } void PlatformSensor::NotifySensorReadingChanged() {
diff --git a/services/device/generic_sensor/platform_sensor.h b/services/device/generic_sensor/platform_sensor.h index 2bcf963c04..9e466ff 100644 --- a/services/device/generic_sensor/platform_sensor.h +++ b/services/device/generic_sensor/platform_sensor.h
@@ -84,7 +84,7 @@ // Updates shared buffer with new sensor reading data. // Note: this method is thread-safe. - void UpdateSensorReading(const SensorReading& reading, bool notify_clients); + void UpdateSensorReading(const SensorReading& reading); void NotifySensorReadingChanged(); void NotifySensorError();
diff --git a/services/device/generic_sensor/platform_sensor_accelerometer_mac.cc b/services/device/generic_sensor/platform_sensor_accelerometer_mac.cc index bc0700e7..2eaa9c9 100644 --- a/services/device/generic_sensor/platform_sensor_accelerometer_mac.cc +++ b/services/device/generic_sensor/platform_sensor_accelerometer_mac.cc
@@ -98,7 +98,7 @@ if (IsSignificantlyDifferent(reading_, reading)) { reading_ = reading; - UpdateSensorReading(reading, true); + UpdateSensorReading(reading); } }
diff --git a/services/device/generic_sensor/platform_sensor_ambient_light_mac.cc b/services/device/generic_sensor/platform_sensor_ambient_light_mac.cc index bb9208f..bd44766 100644 --- a/services/device/generic_sensor/platform_sensor_ambient_light_mac.cc +++ b/services/device/generic_sensor/platform_sensor_ambient_light_mac.cc
@@ -171,7 +171,7 @@ reading.als.timestamp = (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); reading.als.value = current_lux_; - UpdateSensorReading(reading, true); + UpdateSensorReading(reading); return true; }
diff --git a/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc b/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc index 1668e8e..871316c 100644 --- a/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc +++ b/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc
@@ -35,6 +35,8 @@ // Zero value can mean whether value is not being not used or zero value. constexpr double kZero = 0.0; +constexpr double kAmbientLightFrequencyValue = 10.0; + constexpr double kAccelerometerFrequencyValue = 10.0; constexpr double kAccelerometerOffsetValue = 1.0; constexpr double kAccelerometerScalingValue = 0.009806; @@ -655,4 +657,43 @@ scaling * (sensor_values[2] + kMagnetometerOffsetValue)); } +// Tests that Ambient Light sensor client's OnSensorReadingChanged() is called +// when the Ambient Light sensor's reporting mode is +// mojom::ReportingMode::CONTINUOUS. +TEST_F(PlatformSensorAndProviderLinuxTest, + SensorClientGetReadingChangedNotificationWhenSensorIsInContinuousMode) { + mojo::ScopedSharedBufferHandle handle = provider_->CloneSharedBufferHandle(); + mojo::ScopedSharedBufferMapping mapping = handle->MapAtOffset( + sizeof(SensorReadingSharedBuffer), + SensorReadingSharedBuffer::GetOffset(SensorType::AMBIENT_LIGHT)); + + double sensor_value[3] = {22}; + // Set a non-zero frequency here and sensor's reporting mode will be + // mojom::ReportingMode::CONTINUOUS. + InitializeSupportedSensor(SensorType::AMBIENT_LIGHT, + kAmbientLightFrequencyValue, kZero, kZero, + sensor_value); + + InitializeMockUdevMethods(sensors_dir_.GetPath()); + SetServiceStart(); + + auto sensor = CreateSensor(SensorType::AMBIENT_LIGHT); + EXPECT_TRUE(sensor); + EXPECT_EQ(mojom::ReportingMode::CONTINUOUS, sensor->GetReportingMode()); + + auto client = base::MakeUnique<NiceMock<MockPlatformSensorClient>>(sensor); + + PlatformSensorConfiguration configuration( + sensor->GetMaximumSupportedFrequency()); + EXPECT_TRUE(sensor->StartListening(client.get(), configuration)); + + WaitOnSensorReadingChangedEvent(client.get(), sensor->GetType()); + + EXPECT_TRUE(sensor->StopListening(client.get(), configuration)); + + SensorReadingSharedBuffer* buffer = + static_cast<SensorReadingSharedBuffer*>(mapping.get()); + EXPECT_THAT(buffer->reading.als.value, sensor_value[0]); +} + } // namespace device
diff --git a/services/device/generic_sensor/platform_sensor_android.cc b/services/device/generic_sensor/platform_sensor_android.cc index 5c61176..daf4d2e 100644 --- a/services/device/generic_sensor/platform_sensor_android.cc +++ b/services/device/generic_sensor/platform_sensor_android.cc
@@ -93,8 +93,7 @@ reading.raw.values[2] = value3; reading.raw.values[3] = value4; - bool needNotify = (GetReportingMode() == mojom::ReportingMode::ON_CHANGE); - UpdateSensorReading(reading, needNotify); + UpdateSensorReading(reading); } } // namespace device
diff --git a/services/device/generic_sensor/platform_sensor_fusion.cc b/services/device/generic_sensor/platform_sensor_fusion.cc index b4d49ab..15b5173 100644 --- a/services/device/generic_sensor/platform_sensor_fusion.cc +++ b/services/device/generic_sensor/platform_sensor_fusion.cc
@@ -55,17 +55,7 @@ return false; } - if (GetReportingMode() == mojom::ReportingMode::CONTINUOUS) { - timer_.Start( - FROM_HERE, - base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond / - configuration.frequency()), - base::Bind(&PlatformSensorFusion::OnSensorReadingChanged, - base::Unretained(this), GetType())); - } - fusion_algorithm_->SetFrequency(configuration.frequency()); - return true; } @@ -73,9 +63,6 @@ for (const auto& sensor : source_sensors_) sensor->StopSensor(); - if (timer_.IsRunning()) - timer_.Stop(); - fusion_algorithm_->Reset(); } @@ -102,8 +89,7 @@ } reading_ = reading; - UpdateSensorReading(reading_, - GetReportingMode() == mojom::ReportingMode::ON_CHANGE); + UpdateSensorReading(reading_); } void PlatformSensorFusion::OnSensorError() {
diff --git a/services/device/generic_sensor/platform_sensor_fusion.h b/services/device/generic_sensor/platform_sensor_fusion.h index fe9ea8d5..7d3331c 100644 --- a/services/device/generic_sensor/platform_sensor_fusion.h +++ b/services/device/generic_sensor/platform_sensor_fusion.h
@@ -70,9 +70,6 @@ SensorReading reading_; std::vector<scoped_refptr<PlatformSensor>> source_sensors_; std::unique_ptr<PlatformSensorFusionAlgorithm> fusion_algorithm_; - // Repeating timer for data polling if all source sensors are CONTINUOUS - // reporting mode. - base::RepeatingTimer timer_; mojom::ReportingMode reporting_mode_; DISALLOW_COPY_AND_ASSIGN(PlatformSensorFusion);
diff --git a/services/device/generic_sensor/platform_sensor_linux.cc b/services/device/generic_sensor/platform_sensor_linux.cc index 27907348..f501ba6 100644 --- a/services/device/generic_sensor/platform_sensor_linux.cc +++ b/services/device/generic_sensor/platform_sensor_linux.cc
@@ -51,16 +51,14 @@ void PlatformSensorLinux::UpdatePlatformSensorReading(SensorReading reading) { DCHECK(task_runner_->BelongsToCurrentThread()); - bool notifyNeeded = false; - if (GetReportingMode() == mojom::ReportingMode::ON_CHANGE) { - if (!HaveValuesChanged(reading, old_values_)) - return; - notifyNeeded = true; + if (GetReportingMode() == mojom::ReportingMode::ON_CHANGE && + !HaveValuesChanged(reading, old_values_)) { + return; } old_values_ = reading; reading.raw.timestamp = (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); - UpdateSensorReading(reading, notifyNeeded); + UpdateSensorReading(reading); } void PlatformSensorLinux::NotifyPlatformSensorError() {
diff --git a/services/device/generic_sensor/platform_sensor_win.cc b/services/device/generic_sensor/platform_sensor_win.cc index fd521ddd..48dac1b 100644 --- a/services/device/generic_sensor/platform_sensor_win.cc +++ b/services/device/generic_sensor/platform_sensor_win.cc
@@ -45,9 +45,7 @@ } void PlatformSensorWin::OnReadingUpdated(const SensorReading& reading) { - // Default reporting mode is ON_CHANGE, thus, set notify_clients parameter - // to true. - UpdateSensorReading(reading, true); + UpdateSensorReading(reading); } void PlatformSensorWin::OnSensorError() {
diff --git a/services/device/generic_sensor/sensor_impl.cc b/services/device/generic_sensor/sensor_impl.cc index 97f5800..1b91f12 100644 --- a/services/device/generic_sensor/sensor_impl.cc +++ b/services/device/generic_sensor/sensor_impl.cc
@@ -60,8 +60,10 @@ void SensorImpl::OnSensorReadingChanged(mojom::SensorType type) { DCHECK(!suspended_); - if (client_ && reading_notification_enabled_) + if (client_ && reading_notification_enabled_ && + sensor_->GetReportingMode() == mojom::ReportingMode::ON_CHANGE) { client_->SensorReadingChanged(); + } } void SensorImpl::OnSensorError() {
diff --git a/services/network/DEPS b/services/network/DEPS new file mode 100644 index 0000000..8fa9d48 --- /dev/null +++ b/services/network/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+net", +]
diff --git a/services/network/public/cpp/BUILD.gn b/services/network/public/cpp/BUILD.gn new file mode 100644 index 0000000..cc13936 --- /dev/null +++ b/services/network/public/cpp/BUILD.gn
@@ -0,0 +1,16 @@ +# 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. + +static_library("cpp") { + sources = [ + "net_adapters.cc", + "net_adapters.h", + ] + + deps = [ + "//base", + "//mojo/common", + "//net", + ] +}
diff --git a/content/common/net_adapters.cc b/services/network/public/cpp/net_adapters.cc similarity index 96% rename from content/common/net_adapters.cc rename to services/network/public/cpp/net_adapters.cc index 504f389..da516f2 100644 --- a/content/common/net_adapters.cc +++ b/services/network/public/cpp/net_adapters.cc
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/common/net_adapters.h" +#include "services/network/public/cpp/net_adapters.h" #include "net/base/net_errors.h" -namespace content { +namespace network { namespace { const uint32_t kMaxBufSize = 64 * 1024; @@ -99,4 +99,4 @@ pending_buffer_->CompleteRead(bytes_to_be_read_); } -} // namespace content +} // namespace network
diff --git a/content/common/net_adapters.h b/services/network/public/cpp/net_adapters.h similarity index 95% rename from content/common/net_adapters.h rename to services/network/public/cpp/net_adapters.h index f9955c13..1008a64 100644 --- a/content/common/net_adapters.h +++ b/services/network/public/cpp/net_adapters.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 CONTENT_COMMON_NET_ADAPTERS_ -#define CONTENT_COMMON_NET_ADAPTERS_ +#ifndef SERVICES_NETWORK_PUBLIC_CPP_NET_ADAPTERS_ +#define SERVICES_NETWORK_PUBLIC_CPP_NET_ADAPTERS_ #include <stdint.h> @@ -11,7 +11,7 @@ #include "mojo/public/cpp/system/data_pipe.h" #include "net/base/io_buffer.h" -namespace content { +namespace network { // These adapters are used to transfer data between a Mojo pipe and the net // library. @@ -131,6 +131,6 @@ int bytes_to_be_read_; }; -} // namespace content +} // namespace network -#endif // CONTENT_COMMON_NET_ADAPTERS_ +#endif // SERVICES_NETWORK_PUBLIC_CPP_NET_ADAPTERS_
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h index 95d7e2d6..804c8697 100644 --- a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h +++ b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h
@@ -4,12 +4,17 @@ #ifndef SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_OS_METRICS_H_ #define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_OS_METRICS_H_ +#include "base/gtest_prod_util.h" #include "base/process/process_handle.h" #include "base/trace_event/process_memory_dump.h" #include "build/build_config.h" #include "services/resource_coordinator/public/cpp/resource_coordinator_export.h" #include "services/resource_coordinator/public/interfaces/memory_instrumentation/memory_instrumentation.mojom.h" +namespace profiling { +FORWARD_DECLARE_TEST(ProfilingJsonExporterTest, MemoryMaps); +}; + namespace memory_instrumentation { class SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_EXPORT OSMetrics { @@ -21,6 +26,7 @@ FRIEND_TEST_ALL_PREFIXES(OSMetricsTest, ParseProcSmaps); FRIEND_TEST_ALL_PREFIXES(OSMetricsTest, TestWinModuleReading); FRIEND_TEST_ALL_PREFIXES(OSMetricsTest, TestMachOReading); + FRIEND_TEST_ALL_PREFIXES(profiling::ProfilingJsonExporterTest, MemoryMaps); static std::vector<mojom::VmRegionPtr> GetProcessMemoryMaps(base::ProcessId); #if defined(OS_LINUX) || defined(OS_ANDROID)
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc index aadb8a7..74941237 100644 --- a/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc +++ b/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc
@@ -37,48 +37,6 @@ base::StringPrintf("%" PRIx32, os_dump.private_footprint_kb * 1024)); } -void MemoryMapsAsValueInto(TracedValue* value, - const std::vector<mojom::VmRegionPtr>& memory_maps) { - static const char kHexFmt[] = "%" PRIx64; - - // Refer to the design doc goo.gl/sxfFY8 for the semantics of these fields. - value->BeginArray("vm_regions"); - for (const auto& region : memory_maps) { - value->BeginDictionary(); - - value->SetString("sa", base::StringPrintf(kHexFmt, region->start_address)); - value->SetString("sz", base::StringPrintf(kHexFmt, region->size_in_bytes)); - if (region->module_timestamp) - value->SetString("ts", - base::StringPrintf(kHexFmt, region->module_timestamp)); - value->SetInteger("pf", region->protection_flags); - value->SetString("mf", region->mapped_file); - - value->BeginDictionary("bs"); // byte stats - value->SetString( - "pss", - base::StringPrintf(kHexFmt, region->byte_stats_proportional_resident)); - value->SetString( - "pd", - base::StringPrintf(kHexFmt, region->byte_stats_private_dirty_resident)); - value->SetString( - "pc", - base::StringPrintf(kHexFmt, region->byte_stats_private_clean_resident)); - value->SetString( - "sd", - base::StringPrintf(kHexFmt, region->byte_stats_shared_dirty_resident)); - value->SetString( - "sc", - base::StringPrintf(kHexFmt, region->byte_stats_shared_clean_resident)); - value->SetString("sw", - base::StringPrintf(kHexFmt, region->byte_stats_swapped)); - value->EndDictionary(); - - value->EndDictionary(); - } - value->EndArray(); -} - }; // namespace TracingObserver::TracingObserver( @@ -202,7 +160,7 @@ if (memory_maps->size()) { traced_value->BeginDictionary("process_mmaps"); - MemoryMapsAsValueInto(traced_value.get(), *memory_maps); + MemoryMapsAsValueInto(*memory_maps, traced_value.get()); traced_value->EndDictionary(); } @@ -210,6 +168,50 @@ return true; } +// static +void TracingObserver::MemoryMapsAsValueInto( + const std::vector<mojom::VmRegionPtr>& memory_maps, + TracedValue* value) { + static const char kHexFmt[] = "%" PRIx64; + + // Refer to the design doc goo.gl/sxfFY8 for the semantics of these fields. + value->BeginArray("vm_regions"); + for (const auto& region : memory_maps) { + value->BeginDictionary(); + + value->SetString("sa", base::StringPrintf(kHexFmt, region->start_address)); + value->SetString("sz", base::StringPrintf(kHexFmt, region->size_in_bytes)); + if (region->module_timestamp) + value->SetString("ts", + base::StringPrintf(kHexFmt, region->module_timestamp)); + value->SetInteger("pf", region->protection_flags); + value->SetString("mf", region->mapped_file); + + value->BeginDictionary("bs"); // byte stats + value->SetString( + "pss", + base::StringPrintf(kHexFmt, region->byte_stats_proportional_resident)); + value->SetString( + "pd", + base::StringPrintf(kHexFmt, region->byte_stats_private_dirty_resident)); + value->SetString( + "pc", + base::StringPrintf(kHexFmt, region->byte_stats_private_clean_resident)); + value->SetString( + "sd", + base::StringPrintf(kHexFmt, region->byte_stats_shared_dirty_resident)); + value->SetString( + "sc", + base::StringPrintf(kHexFmt, region->byte_stats_shared_clean_resident)); + value->SetString("sw", + base::StringPrintf(kHexFmt, region->byte_stats_swapped)); + value->EndDictionary(); + + value->EndDictionary(); + } + value->EndArray(); +} + bool TracingObserver::IsDumpModeAllowed( base::trace_event::MemoryDumpLevelOfDetail dump_mode) const { if (!memory_dump_config_)
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.h b/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.h index 1533365..b21866f 100644 --- a/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.h +++ b/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.h
@@ -36,6 +36,10 @@ const mojom::OSMemDump*, const std::vector<mojom::VmRegionPtr>*); + static void MemoryMapsAsValueInto( + const std::vector<mojom::VmRegionPtr>& memory_maps, + base::trace_event::TracedValue* value); + private: // Returns true if the dump mode is allowed for current tracing session. bool IsDumpModeAllowed(base::trace_event::MemoryDumpLevelOfDetail) const;
diff --git a/services/service_manager/embedder/BUILD.gn b/services/service_manager/embedder/BUILD.gn index 126bb9a..6511fc7 100644 --- a/services/service_manager/embedder/BUILD.gn +++ b/services/service_manager/embedder/BUILD.gn
@@ -15,6 +15,7 @@ "embedded_service_info.cc", "embedded_service_runner.cc", "manifest_utils.cc", + "service_manager_embedder_export.h", ] # iOS embeds the Service Manager but does not use service_manager::Main() (and @@ -32,7 +33,6 @@ sources += [ "main.cc", "main_delegate.cc", - "service_manager_embedder_export.h", "set_process_title.cc", "set_process_title_linux.cc", "shared_file_util.cc", @@ -82,12 +82,22 @@ testonly = true sources = [ + "embedded_instance_manager_unittest.cc", "manifest_utils_unittest.cc", ] + # These headers are duplicated here so that they can remain private in the + # "embedder" target. See http://crbug.com/732993 for a way to make it + # unnecessary to do this. + sources += [ + "embedded_instance_manager.h", + "service_manager_embedder_export.h", + ] + deps = [ ":embedder", "//base", + "//base/test:test_support", "//testing/gtest", ] }
diff --git a/services/service_manager/embedder/embedded_instance_manager.cc b/services/service_manager/embedder/embedded_instance_manager.cc index b5c4104..16d2b7e 100644 --- a/services/service_manager/embedder/embedded_instance_manager.cc +++ b/services/service_manager/embedder/embedded_instance_manager.cc
@@ -61,6 +61,7 @@ FROM_HERE, base::Bind(&EmbeddedInstanceManager::QuitOnServiceSequence, this)); } + thread_.reset(); } EmbeddedInstanceManager::~EmbeddedInstanceManager() {
diff --git a/services/service_manager/embedder/embedded_instance_manager.h b/services/service_manager/embedder/embedded_instance_manager.h index 4a9519d..c1755a66 100644 --- a/services/service_manager/embedder/embedded_instance_manager.h +++ b/services/service_manager/embedder/embedded_instance_manager.h
@@ -29,6 +29,8 @@ namespace service_manager { +class EmbeddedInstanceManagerTestApi; + // EmbeddedInstanceManager is an implementation detail of EmbeddedServiceRunner. // Outside of tests there is no need to use it directly. class SERVICE_MANAGER_EMBEDDER_EXPORT EmbeddedInstanceManager @@ -44,6 +46,7 @@ private: friend class base::RefCountedThreadSafe<EmbeddedInstanceManager>; + friend class EmbeddedInstanceManagerTestApi; ~EmbeddedInstanceManager();
diff --git a/services/service_manager/embedder/embedded_instance_manager_unittest.cc b/services/service_manager/embedder/embedded_instance_manager_unittest.cc new file mode 100644 index 0000000..dc011ed --- /dev/null +++ b/services/service_manager/embedder/embedded_instance_manager_unittest.cc
@@ -0,0 +1,68 @@ +// 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 "services/service_manager/embedder/embedded_instance_manager.h" + +#include <memory> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/memory/ptr_util.h" +#include "base/single_thread_task_runner.h" +#include "base/test/scoped_task_environment.h" +#include "base/threading/thread.h" +#include "services/service_manager/embedder/embedded_service_info.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace service_manager { +namespace { + +void OnQuit(bool* quit_called) { + *quit_called = true; +} + +std::unique_ptr<Service> CreateTestService() { + return base::MakeUnique<Service>(); +} + +} // namespace + +class EmbeddedInstanceManagerTestApi { + public: + EmbeddedInstanceManagerTestApi(EmbeddedInstanceManager* instance) + : instance_(instance) {} + + base::Thread* GetThread() { return instance_->thread_.get(); } + + private: + EmbeddedInstanceManager* instance_; + + DISALLOW_COPY_AND_ASSIGN(EmbeddedInstanceManagerTestApi); +}; + +TEST(EmbeddedInstanceManager, ShutdownWaitsForThreadToQuit) { + base::test::ScopedTaskEnvironment scoped_task_environment; + EmbeddedServiceInfo embedded_service_info; + embedded_service_info.use_own_thread = true; + embedded_service_info.factory = base::Bind(&CreateTestService); + bool quit_called = false; + scoped_refptr<EmbeddedInstanceManager> instance_manager = + new EmbeddedInstanceManager("test", embedded_service_info, + base::Bind(&OnQuit, &quit_called)); + instance_manager->BindServiceRequest(nullptr); + EmbeddedInstanceManagerTestApi test_api(instance_manager.get()); + ASSERT_TRUE(test_api.GetThread()); + scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner = + test_api.GetThread()->task_runner(); + instance_manager->ShutDown(); + EXPECT_FALSE(test_api.GetThread()); + // Further verification the thread was shutdown. + EXPECT_FALSE( + thread_task_runner->PostTask(FROM_HERE, base::Bind(&base::DoNothing))); + // Because Shutdown() was explicitly called with the thread running the + // quit closure should not have run. + EXPECT_FALSE(quit_called); +} + +} // namespace service_manager
diff --git a/services/service_manager/public/cpp/test/BUILD.gn b/services/service_manager/public/cpp/test/BUILD.gn index ee7880c..3d231b2 100644 --- a/services/service_manager/public/cpp/test/BUILD.gn +++ b/services/service_manager/public/cpp/test/BUILD.gn
@@ -46,3 +46,20 @@ "//base/test:test_support", ] } + +source_set("test_support") { + sources = [ + "test_connector_factory.cc", + "test_connector_factory.h", + ] + + public_deps = [ + "//base", + "//services/service_manager/public/cpp", + "//services/service_manager/public/interfaces", + ] + + deps = [ + "//mojo/public/cpp/bindings", + ] +}
diff --git a/services/service_manager/public/cpp/test/test_connector_factory.cc b/services/service_manager/public/cpp/test/test_connector_factory.cc new file mode 100644 index 0000000..6d3e2b8e --- /dev/null +++ b/services/service_manager/public/cpp/test/test_connector_factory.cc
@@ -0,0 +1,79 @@ +// 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 "services/service_manager/public/cpp/test/test_connector_factory.h" + +#include "base/macros.h" +#include "mojo/public/cpp/bindings/binding_set.h" +#include "services/service_manager/public/cpp/service.h" +#include "services/service_manager/public/interfaces/connector.mojom.h" + +namespace service_manager { + +namespace { + +class TestConnectorImpl : public mojom::Connector { + public: + TestConnectorImpl(TestConnectorFactory* factory, Service* service) + : factory_(factory), service_(service) {} + + ~TestConnectorImpl() override = default; + + void BindInterface(const Identity& target, + const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe, + BindInterfaceCallback callback) override { + service_->OnBindInterface( + BindSourceInfo(factory_->source_identity(), CapabilitySet()), + interface_name, std::move(interface_pipe)); + std::move(callback).Run(mojom::ConnectResult::SUCCEEDED, Identity()); + } + + void StartService(const Identity& target, + StartServiceCallback callback) override { + NOTREACHED(); + } + + void StartServiceWithProcess( + const Identity& identity, + mojo::ScopedMessagePipeHandle service, + mojom::PIDReceiverRequest pid_receiver_request, + StartServiceWithProcessCallback callback) override { + NOTREACHED(); + } + + void Clone(mojom::ConnectorRequest request) override { + bindings_.AddBinding(this, std::move(request)); + } + + void FilterInterfaces(const std::string& spec, + const Identity& source, + mojom::InterfaceProviderRequest source_request, + mojom::InterfaceProviderPtr target) override { + NOTREACHED(); + } + + private: + TestConnectorFactory* const factory_; + Service* const service_; + mojo::BindingSet<mojom::Connector> bindings_; + + DISALLOW_COPY_AND_ASSIGN(TestConnectorImpl); +}; + +} // namespace + +TestConnectorFactory::TestConnectorFactory(Service* service) + : source_identity_("TestConnectorFactory"), + impl_(base::MakeUnique<TestConnectorImpl>(this, service)) {} + +TestConnectorFactory::~TestConnectorFactory() = default; + +std::unique_ptr<Connector> TestConnectorFactory::CreateConnector() { + mojom::ConnectorPtr proxy; + impl_->Clone(mojo::MakeRequest(&proxy)); + return base::MakeUnique<Connector>(std::move(proxy)); +} + +} // namespace service_manager
diff --git a/services/service_manager/public/cpp/test/test_connector_factory.h b/services/service_manager/public/cpp/test/test_connector_factory.h new file mode 100644 index 0000000..6573893 --- /dev/null +++ b/services/service_manager/public/cpp/test/test_connector_factory.h
@@ -0,0 +1,71 @@ +// 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 SERVICES_SERVICE_MANAGER_PUBLIC_CPP_TEST_TEST_CONNECTOR_FACTORY_H_ +#define SERVICES_SERVICE_MANAGER_PUBLIC_CPP_TEST_TEST_CONNECTOR_FACTORY_H_ + +#include <memory> + +#include "base/macros.h" +#include "services/service_manager/public/cpp/connector.h" +#include "services/service_manager/public/interfaces/connector.mojom.h" + +namespace service_manager { + +class Service; + +// Creates Connector instances which route BindInterface requests directly to +// a given Service implementation. Useful for testing production code which is +// parameterized over a Connector, while bypassing all the Service Manager +// machinery. Typical usage should look something like: +// +// TEST(MyTest, Foo) { +// MyServiceImpl impl; // Your implementation of service_manager::Service +// TestConnectorFactory connector_factory(&impl); +// std::unique_ptr<service_manager::Connector> connector = +// connector_factory.CreateConnector(); +// RunSomeClientCode(connector.get()); +// } +// +// Where |RunSomeClientCode()| would typically be some production code that +// expects a functioning Connector and uses it to connect to the service you're +// testing. +// +// Note that Connectors created by this factory ignore the target service name +// in BindInterface calls: interface requests are always routed to a single +// target Service instance. +class TestConnectorFactory { + public: + // Constructs a new TestConnectorFactory which creates Connectors whose + // requests are routed directly to |service|. |service| is not owned and must + // outlive this TestConnectorFactory instance. + explicit TestConnectorFactory(Service* service); + ~TestConnectorFactory(); + + // Allows a test to override the default Identity seen by the target service + // when it receives OnBindInterface requests from this factory's Connectors. + // + // This is useful if a Service implementation cares about the source identity + // services making incoming interface requests. Otherwise it can be ignored. + void set_source_identity(const Identity& identity) { + source_identity_ = identity; + } + + const Identity& source_identity() const { return source_identity_; } + + // Creates a new connector which routes BindInterfaces requests directly to + // the Service instance associated with this factory. + std::unique_ptr<Connector> CreateConnector(); + + private: + Identity source_identity_; + + std::unique_ptr<mojom::Connector> impl_; + + DISALLOW_COPY_AND_ASSIGN(TestConnectorFactory); +}; + +} // namespace service_manager + +#endif // SERVICES_SERVICE_MANAGER_PUBLIC_CPP_TEST_TEST_CONNECTOR_FACTORY_H_
diff --git a/services/service_manager/tests/BUILD.gn b/services/service_manager/tests/BUILD.gn index ebd0dcd..9a3ea075 100644 --- a/services/service_manager/tests/BUILD.gn +++ b/services/service_manager/tests/BUILD.gn
@@ -18,6 +18,10 @@ service_test("service_manager_unittests") { catalog = ":service_manager_unittests_catalog" + sources = [ + "test_support_unittest.cc", + ] + deps = [ ":interfaces", "//base", @@ -32,6 +36,7 @@ "//services/service_manager/background/tests:unittests", "//services/service_manager/embedder:unittests", "//services/service_manager/public/cpp", + "//services/service_manager/public/cpp/test:test_support", "//services/service_manager/public/interfaces", "//services/service_manager/runner/host:unittests", "//services/service_manager/tests/connect",
diff --git a/services/service_manager/tests/test_support_unittest.cc b/services/service_manager/tests/test_support_unittest.cc new file mode 100644 index 0000000..add4038 --- /dev/null +++ b/services/service_manager/tests/test_support_unittest.cc
@@ -0,0 +1,108 @@ +// 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 "base/bind.h" +#include "base/callback.h" +#include "base/macros.h" +#include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" +#include "mojo/public/cpp/bindings/binding_set.h" +#include "services/service_manager/public/cpp/connector.h" +#include "services/service_manager/public/cpp/service.h" +#include "services/service_manager/public/cpp/test/test_connector_factory.h" +#include "services/service_manager/tests/test.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace service_manager { + +namespace { + +// This is a test service used to demonstrate usage of TestConnectorFactory. +// See documentation on TestConnectorFactory for more details about usage. +class TestServiceImpl : public Service { + public: + using OnBindInterfaceCallback = base::Callback<void(const Identity&)>; + + TestServiceImpl() = default; + ~TestServiceImpl() override = default; + + void set_on_bind_interface_callback(const OnBindInterfaceCallback& callback) { + on_bind_interface_callback_ = callback; + } + + // Service: + void OnBindInterface(const BindSourceInfo& source_info, + const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe) override { + if (interface_name == TestC::Name_) + c_bindings_.AddBinding(&c_impl_, TestCRequest(std::move(interface_pipe))); + + if (on_bind_interface_callback_) + on_bind_interface_callback_.Run(source_info.identity); + } + + private: + // A simple test interface on the service, which can be pinged by test code + // to verify a working service connection. + class TestCImpl : public TestC { + public: + TestCImpl() = default; + ~TestCImpl() override = default; + + // TestC: + void C(CCallback callback) override { std::move(callback).Run(); } + + private: + DISALLOW_COPY_AND_ASSIGN(TestCImpl); + }; + + TestCImpl c_impl_; + mojo::BindingSet<TestC> c_bindings_; + OnBindInterfaceCallback on_bind_interface_callback_; + + DISALLOW_COPY_AND_ASSIGN(TestServiceImpl); +}; + +} // namespace + +TEST(ServiceManagerTestSupport, TestConnectorFactory) { + base::test::ScopedTaskEnvironment task_environment; + + TestServiceImpl service; + TestConnectorFactory factory(&service); + std::unique_ptr<Connector> connector = factory.CreateConnector(); + + TestCPtr c; + connector->BindInterface("ignored", &c); + + base::RunLoop loop; + c->C(loop.QuitClosure()); + loop.Run(); +} + +TEST(ServiceManagerTestSupport, TestConnectorFactoryOverrideSourceIdentity) { + base::test::ScopedTaskEnvironment task_environment; + + TestServiceImpl service; + + static const std::string kTestSourceIdentity = "worst. service. ever."; + TestConnectorFactory factory(&service); + factory.set_source_identity(Identity(kTestSourceIdentity)); + std::unique_ptr<Connector> connector = factory.CreateConnector(); + + // Verify that the test service sees our overridden source identity. + service.set_on_bind_interface_callback( + base::Bind([](const Identity& source_identity) { + EXPECT_EQ(kTestSourceIdentity, source_identity.name()); + })); + + TestCPtr c; + connector->BindInterface("ignored", &c); + + base::RunLoop loop; + c->C(loop.QuitClosure()); + loop.Run(); +} + +} // namespace service_manager
diff --git a/services/ui/public/interfaces/ime/ime.mojom b/services/ui/public/interfaces/ime/ime.mojom index 8251ac6..e9383ea5 100644 --- a/services/ui/public/interfaces/ime/ime.mojom +++ b/services/ui/public/interfaces/ime/ime.mojom
@@ -57,8 +57,8 @@ }; // Represents an underlined segment of text currently composed by IME. -// Corresponds to ui::CompositionUnderline. -struct CompositionUnderline { +// Corresponds to ui::ImeTextSpan. +struct ImeTextSpan { uint32 start_offset; uint32 end_offset; bool thick; @@ -70,7 +70,7 @@ // ui::CompositionText. struct CompositionText { string text; - array<CompositionUnderline> underlines; + array<ImeTextSpan> ime_text_spans; gfx.mojom.Range selection; }; @@ -167,7 +167,7 @@ // Sets composition text and attributes. See comments for // ui::TextInputClient::SetCompositionText() for more details. SetCompositionText(CompositionText composition); - + // Converts current composition text into final content. ConfirmCompositionText();
diff --git a/services/ui/public/interfaces/ime/ime.typemap b/services/ui/public/interfaces/ime/ime.typemap index 0327e43..51ee8a4 100644 --- a/services/ui/public/interfaces/ime/ime.typemap +++ b/services/ui/public/interfaces/ime/ime.typemap
@@ -6,7 +6,7 @@ public_headers = [ "//ui/base/ime/candidate_window.h", "//ui/base/ime/composition_text.h", - "//ui/base/ime/composition_underline.h", + "//ui/base/ime/ime_text_span.h", "//ui/base/ime/text_input_mode.h", "//ui/base/ime/text_input_type.h", ] @@ -25,7 +25,7 @@ "ui.mojom.CandidateWindowEntry=ui::CandidateWindow::Entry", "ui.mojom.CandidateWindowProperties=ui::CandidateWindow::CandidateWindowProperty", "ui.mojom.CompositionText=ui::CompositionText", - "ui.mojom.CompositionUnderline=ui::CompositionUnderline", + "ui.mojom.ImeTextSpan=ui::ImeTextSpan", "ui.mojom.TextInputMode=ui::TextInputMode", "ui.mojom.TextInputType=ui::TextInputType", ]
diff --git a/services/ui/public/interfaces/ime/ime_struct_traits.cc b/services/ui/public/interfaces/ime/ime_struct_traits.cc index a184652..1e729dd 100644 --- a/services/ui/public/interfaces/ime/ime_struct_traits.cc +++ b/services/ui/public/interfaces/ime/ime_struct_traits.cc
@@ -40,10 +40,9 @@ } // static -bool StructTraits<ui::mojom::CompositionUnderlineDataView, - ui::CompositionUnderline>:: - Read(ui::mojom::CompositionUnderlineDataView data, - ui::CompositionUnderline* out) { +bool StructTraits<ui::mojom::ImeTextSpanDataView, ui::ImeTextSpan>::Read( + ui::mojom::ImeTextSpanDataView data, + ui::ImeTextSpan* out) { if (data.is_null()) return false; out->start_offset = data.start_offset(); @@ -58,7 +57,7 @@ bool StructTraits<ui::mojom::CompositionTextDataView, ui::CompositionText>:: Read(ui::mojom::CompositionTextDataView data, ui::CompositionText* out) { return !data.is_null() && data.ReadText(&out->text) && - data.ReadUnderlines(&out->underlines) && + data.ReadImeTextSpans(&out->ime_text_spans) && data.ReadSelection(&out->selection); }
diff --git a/services/ui/public/interfaces/ime/ime_struct_traits.h b/services/ui/public/interfaces/ime/ime_struct_traits.h index 616f3f2..100d1c4 100644 --- a/services/ui/public/interfaces/ime/ime_struct_traits.h +++ b/services/ui/public/interfaces/ime/ime_struct_traits.h
@@ -9,7 +9,7 @@ #include "services/ui/public/interfaces/ime/ime.mojom-shared.h" #include "ui/base/ime/candidate_window.h" #include "ui/base/ime/composition_text.h" -#include "ui/base/ime/composition_underline.h" +#include "ui/base/ime/ime_text_span.h" #include "ui/base/ime/text_input_mode.h" #include "ui/base/ime/text_input_type.h" @@ -74,30 +74,12 @@ }; template <> -struct StructTraits<ui::mojom::CompositionUnderlineDataView, - ui::CompositionUnderline> { - static uint32_t start_offset(const ui::CompositionUnderline& c) { - return c.start_offset; - } - static uint32_t end_offset(const ui::CompositionUnderline& c) { - return c.end_offset; - } - static uint32_t color(const ui::CompositionUnderline& c) { return c.color; } - static uint32_t thick(const ui::CompositionUnderline& c) { return c.thick; } - static uint32_t background_color(const ui::CompositionUnderline& c) { - return c.background_color; - } - static bool Read(ui::mojom::CompositionUnderlineDataView data, - ui::CompositionUnderline* out); -}; - -template <> struct StructTraits<ui::mojom::CompositionTextDataView, ui::CompositionText> { static std::string text(const ui::CompositionText& c) { return base::UTF16ToUTF8(c.text); } - static ui::CompositionUnderlines underlines(const ui::CompositionText& c) { - return c.underlines; + static ui::ImeTextSpans ime_text_spans(const ui::CompositionText& c) { + return c.ime_text_spans; } static gfx::Range selection(const ui::CompositionText& c) { return c.selection; @@ -107,6 +89,20 @@ }; template <> +struct StructTraits<ui::mojom::ImeTextSpanDataView, ui::ImeTextSpan> { + static uint32_t start_offset(const ui::ImeTextSpan& c) { + return c.start_offset; + } + static uint32_t end_offset(const ui::ImeTextSpan& c) { return c.end_offset; } + static uint32_t color(const ui::ImeTextSpan& c) { return c.color; } + static uint32_t thick(const ui::ImeTextSpan& c) { return c.thick; } + static uint32_t background_color(const ui::ImeTextSpan& c) { + return c.background_color; + } + static bool Read(ui::mojom::ImeTextSpanDataView data, ui::ImeTextSpan* out); +}; + +template <> struct EnumTraits<ui::mojom::TextInputMode, ui::TextInputMode> { static ui::mojom::TextInputMode ToMojom(ui::TextInputMode text_input_mode); static bool FromMojom(ui::mojom::TextInputMode input, ui::TextInputMode* out);
diff --git a/services/ui/public/interfaces/ime/ime_struct_traits_unittest.cc b/services/ui/public/interfaces/ime/ime_struct_traits_unittest.cc index cfaec6f8..c718f82 100644 --- a/services/ui/public/interfaces/ime/ime_struct_traits_unittest.cc +++ b/services/ui/public/interfaces/ime/ime_struct_traits_unittest.cc
@@ -12,7 +12,7 @@ #include "services/ui/public/interfaces/ime/ime_struct_traits_test.mojom.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/ime/composition_text.h" -#include "ui/base/ime/composition_underline.h" +#include "ui/base/ime/ime_text_span.h" #include "ui/gfx/range/mojo/range_struct_traits.h" namespace ui { @@ -110,9 +110,9 @@ TEST_F(IMEStructTraitsTest, CompositionText) { CompositionText input; input.text = base::UTF8ToUTF16("abcdefghij"); - input.underlines.push_back(CompositionUnderline(0, 2, SK_ColorGRAY, false)); - input.underlines.push_back( - CompositionUnderline(3, 6, SK_ColorRED, true, SK_ColorGREEN)); + input.ime_text_spans.push_back(ImeTextSpan(0, 2, SK_ColorGRAY, false)); + input.ime_text_spans.push_back( + ImeTextSpan(3, 6, SK_ColorRED, true, SK_ColorGREEN)); input.selection = gfx::Range(1, 7); CompositionText output;
diff --git a/services/ui/ws/BUILD.gn b/services/ui/ws/BUILD.gn index c6a9073..60ccaffcc 100644 --- a/services/ui/ws/BUILD.gn +++ b/services/ui/ws/BUILD.gn
@@ -125,7 +125,6 @@ deps = [ "//components/viz/host", - "//components/viz/host/hit_test", "//gpu/command_buffer/client", "//gpu/command_buffer/client:gles2_interface", "//gpu/ipc/client",
diff --git a/services/viz/public/interfaces/compositing/BUILD.gn b/services/viz/public/interfaces/compositing/BUILD.gn index e9c3bf6..c157364 100644 --- a/services/viz/public/interfaces/compositing/BUILD.gn +++ b/services/viz/public/interfaces/compositing/BUILD.gn
@@ -12,6 +12,7 @@ "render_pass.mojom", "resource_settings.mojom", "returned_resource.mojom", + "shared_bitmap_allocation_notifier.mojom", "surface_info.mojom", "surface_sequence.mojom", ]
diff --git a/cc/ipc/shared_bitmap_allocation_notifier.mojom b/services/viz/public/interfaces/compositing/shared_bitmap_allocation_notifier.mojom similarity index 96% rename from cc/ipc/shared_bitmap_allocation_notifier.mojom rename to services/viz/public/interfaces/compositing/shared_bitmap_allocation_notifier.mojom index a10eff2..d8017cd 100644 --- a/cc/ipc/shared_bitmap_allocation_notifier.mojom +++ b/services/viz/public/interfaces/compositing/shared_bitmap_allocation_notifier.mojom
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -module cc.mojom; +module viz.mojom; import "gpu/ipc/common/mailbox.mojom";
diff --git a/services/viz/public/interfaces/hit_test/hit_test_region_list.mojom b/services/viz/public/interfaces/hit_test/hit_test_region_list.mojom index ff251be..f368cd08 100644 --- a/services/viz/public/interfaces/hit_test/hit_test_region_list.mojom +++ b/services/viz/public/interfaces/hit_test/hit_test_region_list.mojom
@@ -45,9 +45,6 @@ }; struct HitTestRegionList { - // SurfaceId corresponding to this HitTestData. - cc.mojom.SurfaceId surface_id; - // Flags indicate how to handle events that match no sub-regions. // kHitTestMine routes un-matched events to this surface (opaque). // kHitTestIgnore keeps previous match in the parent (transparent).
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h index 675126e..e734274 100644 --- a/skia/config/SkUserConfig.h +++ b/skia/config/SkUserConfig.h
@@ -220,8 +220,8 @@ #define SK_SUPPORT_LEGACY_DELTA_AA #endif -#ifndef SK_SUPPORT_LEGACY_ROTATED_SHADERS -#define SK_SUPPORT_LEGACY_ROTATED_SHADERS +#ifndef SK_SUPPORT_LEGACY_RP_BLENDS +#define SK_SUPPORT_LEGACY_RP_BLENDS #endif ///////////////////////// Imported from BUILD.gn and skia_common.gypi
diff --git a/storage/DEPS b/storage/DEPS index 5d45d0bc..c4e59ed 100644 --- a/storage/DEPS +++ b/storage/DEPS
@@ -1,6 +1,7 @@ include_rules = [ "+mojo", "+net", + "+services/network/public/cpp", "+sql", "+third_party/leveldatabase", "+third_party/sqlite",
diff --git a/storage/browser/BUILD.gn b/storage/browser/BUILD.gn index b5f8a15..a64d797f 100644 --- a/storage/browser/BUILD.gn +++ b/storage/browser/BUILD.gn
@@ -38,6 +38,8 @@ "blob/blob_url_request_job.h", "blob/blob_url_request_job_factory.cc", "blob/blob_url_request_job_factory.h", + "blob/mojo_blob_reader.cc", + "blob/mojo_blob_reader.h", "blob/scoped_file.cc", "blob/scoped_file.h", "blob/shareable_blob_data_item.cc", @@ -207,6 +209,7 @@ "//base:i18n", "//base/third_party/dynamic_annotations", "//net", + "//services/network/public/cpp", "//sql", "//third_party/leveldatabase", "//third_party/sqlite", @@ -293,6 +296,7 @@ ":browser", ":test_support", "//base/test:test_support", + "//mojo/common", "//mojo/edk/system", "//net:test_support", "//sql:test_support",
diff --git a/storage/browser/blob/blob_impl.cc b/storage/browser/blob/blob_impl.cc index ab41aba..6db0007 100644 --- a/storage/browser/blob/blob_impl.cc +++ b/storage/browser/blob/blob_impl.cc
@@ -4,9 +4,42 @@ #include "storage/browser/blob/blob_impl.h" +#include <utility> #include "storage/browser/blob/blob_data_handle.h" +#include "storage/browser/blob/mojo_blob_reader.h" namespace storage { +namespace { + +class ReaderDelegate : public MojoBlobReader::Delegate { + public: + ReaderDelegate(mojo::ScopedDataPipeProducerHandle handle, + mojom::BlobReaderClientPtr client) + : handle_(std::move(handle)), client_(std::move(client)) {} + + mojo::ScopedDataPipeProducerHandle PassDataPipe() override { + return std::move(handle_); + } + + MojoBlobReader::Delegate::RequestSideData DidCalculateSize( + uint64_t total_size, + uint64_t content_size) override { + if (client_) + client_->OnCalculatedSize(total_size, content_size); + return MojoBlobReader::Delegate::DONT_REQUEST_SIDE_DATA; + } + + void OnComplete(net::Error result, uint64_t total_written_bytes) override { + if (client_) + client_->OnComplete(result, total_written_bytes); + } + + private: + mojo::ScopedDataPipeProducerHandle handle_; + mojom::BlobReaderClientPtr client_; +}; + +} // namespace // static base::WeakPtr<BlobImpl> BlobImpl::Create(std::unique_ptr<BlobDataHandle> handle, @@ -19,6 +52,23 @@ bindings_.AddBinding(this, std::move(request)); } +void BlobImpl::ReadRange(uint64_t offset, + uint64_t length, + mojo::ScopedDataPipeProducerHandle handle, + mojom::BlobReaderClientPtr client) { + MojoBlobReader::Create( + nullptr, handle_.get(), + net::HttpByteRange::Bounded(offset, offset + length - 1), + base::MakeUnique<ReaderDelegate>(std::move(handle), std::move(client))); +} + +void BlobImpl::ReadAll(mojo::ScopedDataPipeProducerHandle handle, + mojom::BlobReaderClientPtr client) { + MojoBlobReader::Create( + nullptr, handle_.get(), net::HttpByteRange(), + base::MakeUnique<ReaderDelegate>(std::move(handle), std::move(client))); +} + void BlobImpl::GetInternalUUID(GetInternalUUIDCallback callback) { std::move(callback).Run(handle_->uuid()); }
diff --git a/storage/browser/blob/blob_impl.h b/storage/browser/blob/blob_impl.h index 148ae96..9693504 100644 --- a/storage/browser/blob/blob_impl.h +++ b/storage/browser/blob/blob_impl.h
@@ -20,6 +20,12 @@ mojom::BlobRequest request); void Clone(mojom::BlobRequest request) override; + void ReadRange(uint64_t offset, + uint64_t length, + mojo::ScopedDataPipeProducerHandle handle, + mojom::BlobReaderClientPtr client) override; + void ReadAll(mojo::ScopedDataPipeProducerHandle handle, + mojom::BlobReaderClientPtr client) override; void GetInternalUUID(GetInternalUUIDCallback callback) override; void FlushForTesting();
diff --git a/storage/browser/blob/blob_impl_unittest.cc b/storage/browser/blob/blob_impl_unittest.cc index 051c715..19bdc45 100644 --- a/storage/browser/blob/blob_impl_unittest.cc +++ b/storage/browser/blob/blob_impl_unittest.cc
@@ -4,7 +4,10 @@ #include "storage/browser/blob/blob_impl.h" +#include "base/task_scheduler/post_task.h" #include "base/test/scoped_task_environment.h" +#include "mojo/common/data_pipe_drainer.h" +#include "net/base/net_errors.h" #include "storage/browser/blob/blob_data_builder.h" #include "storage/browser/blob/blob_data_handle.h" #include "storage/browser/blob/blob_storage_context.h" @@ -12,6 +15,49 @@ namespace storage { +namespace { + +class DataPipeReader : public mojo::common::DataPipeDrainer::Client { + public: + DataPipeReader(std::string* data_out, base::OnceClosure done_callback) + : data_out_(data_out), done_callback_(std::move(done_callback)) {} + + void OnDataAvailable(const void* data, size_t num_bytes) override { + data_out_->append(static_cast<const char*>(data), num_bytes); + } + + void OnDataComplete() override { std::move(done_callback_).Run(); } + + private: + std::string* data_out_; + base::OnceClosure done_callback_; +}; + +class MockBlobReaderClient : public mojom::BlobReaderClient { + public: + void OnCalculatedSize(uint64_t total_size, + uint64_t expected_content_size) override { + total_size_ = total_size; + expected_content_size_ = expected_content_size; + calculated_size_ = true; + } + + void OnComplete(int32_t status, uint64_t data_length) override { + status_ = static_cast<net::Error>(status); + data_length_ = data_length; + completed_ = true; + } + + bool calculated_size_ = false; + uint64_t total_size_ = 0; + uint64_t expected_content_size_ = 0; + bool completed_ = false; + net::Error status_ = net::OK; + uint64_t data_length_ = 0; +}; + +} // namespace + class BlobImplTest : public testing::Test { public: void SetUp() override { context_ = base::MakeUnique<BlobStorageContext>(); } @@ -39,6 +85,15 @@ return received_uuid; } + std::string ReadDataPipe(mojo::ScopedDataPipeConsumerHandle pipe) { + base::RunLoop loop; + std::string data; + DataPipeReader reader(&data, loop.QuitClosure()); + mojo::common::DataPipeDrainer drainer(&reader, std::move(pipe)); + loop.Run(); + return data; + } + protected: base::test::ScopedTaskEnvironment scoped_task_environment_; std::unique_ptr<BlobStorageContext> context_; @@ -82,4 +137,198 @@ EXPECT_FALSE(blob); } +TEST_F(BlobImplTest, ReadAll) { + const std::string kId = "id"; + const std::string kContents = "hello world"; + auto handle = CreateBlobFromString(kId, kContents); + + mojom::BlobPtr ptr; + BlobImpl::Create(std::move(handle), MakeRequest(&ptr)); + + MockBlobReaderClient client; + mojom::BlobReaderClientPtr client_ptr; + mojo::Binding<mojom::BlobReaderClient> client_binding( + &client, MakeRequest(&client_ptr)); + + mojo::DataPipe pipe; + ptr->ReadAll(std::move(pipe.producer_handle), std::move(client_ptr)); + std::string received = ReadDataPipe(std::move(pipe.consumer_handle)); + EXPECT_EQ(kContents, received); + + client_binding.FlushForTesting(); + EXPECT_TRUE(client.calculated_size_); + EXPECT_EQ(kContents.size(), client.total_size_); + EXPECT_EQ(kContents.size(), client.expected_content_size_); + + EXPECT_TRUE(client.completed_); + EXPECT_EQ(net::OK, client.status_); + EXPECT_EQ(kContents.size(), client.data_length_); +} + +TEST_F(BlobImplTest, ReadAll_WithoutClient) { + const std::string kId = "id"; + const std::string kContents = "hello world"; + auto handle = CreateBlobFromString(kId, kContents); + + mojom::BlobPtr ptr; + BlobImpl::Create(std::move(handle), MakeRequest(&ptr)); + + mojo::DataPipe pipe; + ptr->ReadAll(std::move(pipe.producer_handle), nullptr); + std::string received = ReadDataPipe(std::move(pipe.consumer_handle)); + EXPECT_EQ(kContents, received); +} + +TEST_F(BlobImplTest, ReadAll_BrokenBlob) { + const std::string kId = "id"; + auto handle = context_->AddBrokenBlob( + kId, "", "", BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS); + + mojom::BlobPtr ptr; + BlobImpl::Create(std::move(handle), MakeRequest(&ptr)); + + MockBlobReaderClient client; + mojom::BlobReaderClientPtr client_ptr; + mojo::Binding<mojom::BlobReaderClient> client_binding( + &client, MakeRequest(&client_ptr)); + + mojo::DataPipe pipe; + ptr->ReadAll(std::move(pipe.producer_handle), std::move(client_ptr)); + + std::string received = ReadDataPipe(std::move(pipe.consumer_handle)); + EXPECT_EQ("", received); + + client_binding.FlushForTesting(); + EXPECT_FALSE(client.calculated_size_); + EXPECT_TRUE(client.completed_); + EXPECT_EQ(net::ERR_FAILED, client.status_); + EXPECT_EQ(0u, client.data_length_); +} + +TEST_F(BlobImplTest, ReadRange) { + const std::string kId = "id"; + const std::string kContents = "hello world"; + auto handle = CreateBlobFromString(kId, kContents); + + mojom::BlobPtr ptr; + BlobImpl::Create(std::move(handle), MakeRequest(&ptr)); + + MockBlobReaderClient client; + mojom::BlobReaderClientPtr client_ptr; + mojo::Binding<mojom::BlobReaderClient> client_binding( + &client, MakeRequest(&client_ptr)); + + mojo::DataPipe pipe; + ptr->ReadRange(2, 5, std::move(pipe.producer_handle), std::move(client_ptr)); + + std::string received = ReadDataPipe(std::move(pipe.consumer_handle)); + EXPECT_EQ(kContents.substr(2, 5), received); + + client_binding.FlushForTesting(); + EXPECT_TRUE(client.calculated_size_); + EXPECT_EQ(kContents.size(), client.total_size_); + EXPECT_EQ(5u, client.expected_content_size_); + + EXPECT_TRUE(client.completed_); + EXPECT_EQ(net::OK, client.status_); + EXPECT_EQ(5u, client.data_length_); +} + +TEST_F(BlobImplTest, ReadRange_WithoutClient) { + const std::string kId = "id"; + const std::string kContents = "hello world"; + auto handle = CreateBlobFromString(kId, kContents); + + mojom::BlobPtr ptr; + BlobImpl::Create(std::move(handle), MakeRequest(&ptr)); + + mojo::DataPipe pipe; + ptr->ReadRange(2, 5, std::move(pipe.producer_handle), nullptr); + + std::string received = ReadDataPipe(std::move(pipe.consumer_handle)); + EXPECT_EQ(kContents.substr(2, 5), received); +} + +TEST_F(BlobImplTest, ReadRange_TooLargeLength) { + const std::string kId = "id"; + const std::string kContents = "hello world"; + auto handle = CreateBlobFromString(kId, kContents); + + mojom::BlobPtr ptr; + BlobImpl::Create(std::move(handle), MakeRequest(&ptr)); + + MockBlobReaderClient client; + mojom::BlobReaderClientPtr client_ptr; + mojo::Binding<mojom::BlobReaderClient> client_binding( + &client, MakeRequest(&client_ptr)); + + mojo::DataPipe pipe; + ptr->ReadRange(2, 15, std::move(pipe.producer_handle), std::move(client_ptr)); + + std::string received = ReadDataPipe(std::move(pipe.consumer_handle)); + EXPECT_EQ(kContents.substr(2, 15), received); + + client_binding.FlushForTesting(); + EXPECT_TRUE(client.calculated_size_); + EXPECT_EQ(kContents.size(), client.total_size_); + EXPECT_EQ(kContents.size() - 2, client.expected_content_size_); + + EXPECT_TRUE(client.completed_); + EXPECT_EQ(net::OK, client.status_); + EXPECT_EQ(kContents.size() - 2, client.data_length_); +} + +TEST_F(BlobImplTest, ReadRange_BrokenBlob) { + const std::string kId = "id"; + auto handle = context_->AddBrokenBlob( + kId, "", "", BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS); + + mojom::BlobPtr ptr; + BlobImpl::Create(std::move(handle), MakeRequest(&ptr)); + + MockBlobReaderClient client; + mojom::BlobReaderClientPtr client_ptr; + mojo::Binding<mojom::BlobReaderClient> client_binding( + &client, MakeRequest(&client_ptr)); + + mojo::DataPipe pipe; + ptr->ReadRange(2, 5, std::move(pipe.producer_handle), std::move(client_ptr)); + + std::string received = ReadDataPipe(std::move(pipe.consumer_handle)); + EXPECT_EQ("", received); + + client_binding.FlushForTesting(); + EXPECT_FALSE(client.calculated_size_); + EXPECT_TRUE(client.completed_); + EXPECT_EQ(net::ERR_FAILED, client.status_); + EXPECT_EQ(0u, client.data_length_); +} + +TEST_F(BlobImplTest, ReadRange_InvalidRange) { + const std::string kId = "id"; + const std::string kContents = "hello world"; + auto handle = CreateBlobFromString(kId, kContents); + + mojom::BlobPtr ptr; + BlobImpl::Create(std::move(handle), MakeRequest(&ptr)); + + MockBlobReaderClient client; + mojom::BlobReaderClientPtr client_ptr; + mojo::Binding<mojom::BlobReaderClient> client_binding( + &client, MakeRequest(&client_ptr)); + + base::RunLoop loop; + mojo::DataPipe pipe; + ptr->ReadRange(15, 4, std::move(pipe.producer_handle), std::move(client_ptr)); + + std::string received = ReadDataPipe(std::move(pipe.consumer_handle)); + EXPECT_EQ("", received); + + client_binding.FlushForTesting(); + EXPECT_FALSE(client.calculated_size_); + EXPECT_TRUE(client.completed_); + EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, client.status_); + EXPECT_EQ(0u, client.data_length_); +} + } // namespace storage
diff --git a/storage/browser/blob/blob_registry_impl_unittest.cc b/storage/browser/blob/blob_registry_impl_unittest.cc index ee0e27d..0f0e3c8 100644 --- a/storage/browser/blob/blob_registry_impl_unittest.cc +++ b/storage/browser/blob/blob_registry_impl_unittest.cc
@@ -41,6 +41,18 @@ std::move(request)); } + void ReadRange(uint64_t offset, + uint64_t size, + mojo::ScopedDataPipeProducerHandle, + mojom::BlobReaderClientPtr) override { + NOTREACHED(); + } + + void ReadAll(mojo::ScopedDataPipeProducerHandle, + mojom::BlobReaderClientPtr) override { + NOTREACHED(); + } + void GetInternalUUID(GetInternalUUIDCallback callback) override { std::move(callback).Run(uuid_); }
diff --git a/storage/browser/blob/blob_url_request_job.cc b/storage/browser/blob/blob_url_request_job.cc index b1ac09e..03190ad 100644 --- a/storage/browser/blob/blob_url_request_job.cc +++ b/storage/browser/blob/blob_url_request_job.cc
@@ -142,9 +142,9 @@ scoped_refptr<net::HttpResponseHeaders> BlobURLRequestJob::GenerateHeaders( net::HttpStatusCode status_code, BlobDataHandle* blob_handle, - BlobReader* blob_reader, net::HttpByteRange* byte_range, - int64_t* content_size) { + uint64_t total_size, + uint64_t content_size) { std::string status("HTTP/1.1 "); status.append(base::IntToString(status_code)); status.append(" "); @@ -154,10 +154,9 @@ new net::HttpResponseHeaders(status); if (status_code == net::HTTP_OK || status_code == net::HTTP_PARTIAL_CONTENT) { - *content_size = blob_reader->remaining_bytes(); std::string content_length_header(net::HttpRequestHeaders::kContentLength); content_length_header.append(": "); - content_length_header.append(base::Int64ToString(*content_size)); + content_length_header.append(base::Uint64ToString(content_size)); headers->AddHeader(content_length_header); if (status_code == net::HTTP_PARTIAL_CONTENT) { DCHECK(byte_range->IsValid()); @@ -167,8 +166,7 @@ "%" PRId64 "-%" PRId64, byte_range->first_byte_position(), byte_range->last_byte_position())); content_range_header.append("/"); - content_range_header.append( - base::StringPrintf("%" PRId64, blob_reader->total_size())); + content_range_header.append(base::StringPrintf("%" PRId64, total_size)); headers->AddHeader(content_range_header); } if (!blob_handle->content_type().empty()) { @@ -323,12 +321,16 @@ } void BlobURLRequestJob::HeadersCompleted(net::HttpStatusCode status_code) { - int64_t content_size = 0; + uint64_t content_size = 0; + uint64_t total_size = 0; + if (status_code == net::HTTP_OK || status_code == net::HTTP_PARTIAL_CONTENT) { + content_size = blob_reader_->remaining_bytes(); + set_expected_content_size(content_size); + total_size = blob_reader_->total_size(); + } response_info_.reset(new net::HttpResponseInfo()); - response_info_->headers = - GenerateHeaders(status_code, blob_handle_.get(), blob_reader_.get(), - &byte_range_, &content_size); - set_expected_content_size(content_size); + response_info_->headers = GenerateHeaders( + status_code, blob_handle_.get(), &byte_range_, total_size, content_size); if (blob_reader_) response_info_->metadata = blob_reader_->side_data();
diff --git a/storage/browser/blob/blob_url_request_job.h b/storage/browser/blob/blob_url_request_job.h index b67aaef..00649b8 100644 --- a/storage/browser/blob/blob_url_request_job.h +++ b/storage/browser/blob/blob_url_request_job.h
@@ -48,14 +48,14 @@ void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override; // Helper method to create the HTTP headers for the response. - // |blob_handles|, |blob_reader|, |byte_range| and |content_size| are only + // |blob_handles|, |total_size|, |byte_range| and |content_size| are only // used if status_code isn't an error. static scoped_refptr<net::HttpResponseHeaders> GenerateHeaders( net::HttpStatusCode status_code, BlobDataHandle* blob_handle, - BlobReader* blob_reader, net::HttpByteRange* byte_range, - int64_t* content_size); + uint64_t total_size, + uint64_t content_size); // Helper method to map from a net error to an http status code. static net::HttpStatusCode NetErrorToHttpStatusCode(int error_code);
diff --git a/storage/browser/blob/mojo_blob_reader.cc b/storage/browser/blob/mojo_blob_reader.cc new file mode 100644 index 0000000..0e29999 --- /dev/null +++ b/storage/browser/blob/mojo_blob_reader.cc
@@ -0,0 +1,212 @@ +// 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 "storage/browser/blob/mojo_blob_reader.h" + +#include "net/base/io_buffer.h" +#include "services/network/public/cpp/net_adapters.h" +#include "storage/browser/blob/blob_data_handle.h" + +namespace storage { + +// static +void MojoBlobReader::Create(FileSystemContext* file_system_context, + const BlobDataHandle* handle, + const net::HttpByteRange& range, + std::unique_ptr<Delegate> delegate) { + new MojoBlobReader(file_system_context, handle, range, std::move(delegate)); +} + +MojoBlobReader::MojoBlobReader(FileSystemContext* file_system_context, + const BlobDataHandle* handle, + const net::HttpByteRange& range, + std::unique_ptr<Delegate> delegate) + : delegate_(std::move(delegate)), + byte_range_(range), + blob_reader_(handle->CreateReader(file_system_context)), + writable_handle_watcher_(FROM_HERE, + mojo::SimpleWatcher::ArmingPolicy::MANUAL), + peer_closed_handle_watcher_(FROM_HERE, + mojo::SimpleWatcher::ArmingPolicy::MANUAL), + weak_factory_(this) { + DCHECK(delegate_); + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(&MojoBlobReader::Start, weak_factory_.GetWeakPtr())); +} + +MojoBlobReader::~MojoBlobReader() {} + +void MojoBlobReader::Start() { + if (blob_reader_->net_error()) { + NotifyCompletedAndDeleteIfNeeded(blob_reader_->net_error()); + return; + } + + BlobReader::Status size_status = blob_reader_->CalculateSize( + base::Bind(&MojoBlobReader::DidCalculateSize, base::Unretained(this))); + switch (size_status) { + case BlobReader::Status::NET_ERROR: + NotifyCompletedAndDeleteIfNeeded(blob_reader_->net_error()); + return; + case BlobReader::Status::IO_PENDING: + return; + case BlobReader::Status::DONE: + DidCalculateSize(net::OK); + return; + } + + NOTREACHED(); +} + +void MojoBlobReader::NotifyCompletedAndDeleteIfNeeded(int result) { + if (!notified_completed_) { + delegate_->OnComplete(static_cast<net::Error>(result), + total_written_bytes_); + notified_completed_ = true; + } + + bool has_data_pipe = pending_write_ || response_body_stream_.is_valid(); + if (!has_data_pipe) + delete this; +} + +void MojoBlobReader::DidCalculateSize(int result) { + if (result != net::OK) { + NotifyCompletedAndDeleteIfNeeded(result); + return; + } + + // Apply the range requirement. + if (!byte_range_.ComputeBounds(blob_reader_->total_size())) { + NotifyCompletedAndDeleteIfNeeded(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); + return; + } + + DCHECK_LE(byte_range_.first_byte_position(), + byte_range_.last_byte_position() + 1); + uint64_t length = base::checked_cast<uint64_t>( + byte_range_.last_byte_position() - byte_range_.first_byte_position() + 1); + + if (blob_reader_->SetReadRange(byte_range_.first_byte_position(), length) != + BlobReader::Status::DONE) { + NotifyCompletedAndDeleteIfNeeded(blob_reader_->net_error()); + return; + } + + if (delegate_->DidCalculateSize(blob_reader_->total_size(), + blob_reader_->remaining_bytes()) == + Delegate::REQUEST_SIDE_DATA) { + if (!blob_reader_->has_side_data()) { + DidReadSideData(BlobReader::Status::DONE); + } else { + BlobReader::Status read_status = blob_reader_->ReadSideData( + base::Bind(&MojoBlobReader::DidReadSideData, base::Unretained(this))); + if (read_status != BlobReader::Status::IO_PENDING) + DidReadSideData(BlobReader::Status::DONE); + } + } else { + StartReading(); + } +} + +void MojoBlobReader::DidReadSideData(BlobReader::Status status) { + if (status != BlobReader::Status::DONE) { + NotifyCompletedAndDeleteIfNeeded(blob_reader_->net_error()); + return; + } + delegate_->DidReadSideData(blob_reader_->side_data()); + StartReading(); +} + +void MojoBlobReader::StartReading() { + response_body_stream_ = delegate_->PassDataPipe(); + peer_closed_handle_watcher_.Watch( + response_body_stream_.get(), MOJO_HANDLE_SIGNAL_PEER_CLOSED, + base::Bind(&MojoBlobReader::OnResponseBodyStreamClosed, + base::Unretained(this))); + peer_closed_handle_watcher_.ArmOrNotify(); + + writable_handle_watcher_.Watch( + response_body_stream_.get(), MOJO_HANDLE_SIGNAL_WRITABLE, + base::Bind(&MojoBlobReader::OnResponseBodyStreamReady, + base::Unretained(this))); + + // Start reading... + ReadMore(); +} + +void MojoBlobReader::ReadMore() { + DCHECK(!pending_write_.get()); + + uint32_t num_bytes; + // TODO: we should use the abstractions in MojoAsyncResourceHandler. + MojoResult result = network::NetToMojoPendingBuffer::BeginWrite( + &response_body_stream_, &pending_write_, &num_bytes); + if (result == MOJO_RESULT_SHOULD_WAIT) { + // The pipe is full. We need to wait for it to have more space. + writable_handle_watcher_.ArmOrNotify(); + return; + } else if (result != MOJO_RESULT_OK) { + // The response body stream is in a bad state. Bail. + writable_handle_watcher_.Cancel(); + response_body_stream_.reset(); + NotifyCompletedAndDeleteIfNeeded(net::ERR_UNEXPECTED); + return; + } + + CHECK_GT(static_cast<uint32_t>(std::numeric_limits<int>::max()), num_bytes); + auto buf = + base::MakeRefCounted<network::NetToMojoIOBuffer>(pending_write_.get()); + int bytes_read; + BlobReader::Status read_status = blob_reader_->Read( + buf.get(), static_cast<int>(num_bytes), &bytes_read, + base::Bind(&MojoBlobReader::DidRead, base::Unretained(this), false)); + switch (read_status) { + case BlobReader::Status::NET_ERROR: + NotifyCompletedAndDeleteIfNeeded(blob_reader_->net_error()); + return; + case BlobReader::Status::IO_PENDING: + // Wait for DidRead. + return; + case BlobReader::Status::DONE: + if (bytes_read > 0) { + DidRead(true, bytes_read); + } else { + writable_handle_watcher_.Cancel(); + pending_write_->Complete(0); + pending_write_ = nullptr; // This closes the data pipe. + NotifyCompletedAndDeleteIfNeeded(net::OK); + return; + } + } +} + +void MojoBlobReader::DidRead(bool completed_synchronously, int num_bytes) { + delegate_->DidRead(num_bytes); + response_body_stream_ = pending_write_->Complete(num_bytes); + total_written_bytes_ += num_bytes; + pending_write_ = nullptr; + if (completed_synchronously) { + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(&MojoBlobReader::ReadMore, weak_factory_.GetWeakPtr())); + } else { + ReadMore(); + } +} + +void MojoBlobReader::OnResponseBodyStreamClosed(MojoResult result) { + response_body_stream_.reset(); + pending_write_ = nullptr; + NotifyCompletedAndDeleteIfNeeded(net::ERR_ABORTED); +} + +void MojoBlobReader::OnResponseBodyStreamReady(MojoResult result) { + // TODO(jam): Handle a bad |result| value. + DCHECK_EQ(result, MOJO_RESULT_OK); + ReadMore(); +} + +} // namespace storage
diff --git a/storage/browser/blob/mojo_blob_reader.h b/storage/browser/blob/mojo_blob_reader.h new file mode 100644 index 0000000..04221e1 --- /dev/null +++ b/storage/browser/blob/mojo_blob_reader.h
@@ -0,0 +1,143 @@ +// 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 STORAGE_BROWSER_BLOB_MOJO_BLOB_READER_H_ +#define STORAGE_BROWSER_BLOB_MOJO_BLOB_READER_H_ + +#include <memory> +#include "base/memory/ref_counted.h" +#include "mojo/public/cpp/system/data_pipe.h" +#include "mojo/public/cpp/system/simple_watcher.h" +#include "net/base/net_errors.h" +#include "net/http/http_byte_range.h" +#include "storage/browser/blob/blob_reader.h" +#include "storage/browser/storage_browser_export.h" + +namespace net { +class IOBufferWithSize; +} + +namespace network { +class NetToMojoPendingBuffer; +} + +namespace storage { +class BlobDataHandle; +class FileSystemContext; + +// Reads a blob into a data pipe. Owns itself, and owns its delegate. Self +// destructs when reading is complete. +class STORAGE_EXPORT MojoBlobReader { + public: + // Methods on this delegate are called in the order they are defined here. + // With the exception of DidRead, each method is called at most once. + // OnComplete is always called, and is always the last method to be called, + // every other method could be skipped in case of errors, or if the method is + // otherwise not applicable. + class Delegate { + public: + enum RequestSideData { REQUEST_SIDE_DATA, DONT_REQUEST_SIDE_DATA }; + + virtual ~Delegate() {} + + // Called when the blob being read has been fully constructed and its size + // is known. |total_size| is the total size of the blob, while + // |content_size| is the size of the subset of this blob that matches the + // range passed to Create. + // Return |REQUEST_SIDE_DATA| if the blob's side data should be returned, + // otherwise MojoBlobReader will skip reading side data and immediately + // start reading the actual blob contents. Side data is used for example by + // service worker code to store compiled javascript alongside the script + // source in the cache. + virtual RequestSideData DidCalculateSize(uint64_t total_size, + uint64_t content_size) = 0; + + // Called if DidCalculateSize returned |REQUEST_SIDE_DATA|, with the side + // data associated with the blob being read. If the blob doesn't have side + // data this method is called with null. + virtual void DidReadSideData(net::IOBufferWithSize* data) {} + + // Called when the MojoBlobReader actually starts reading data from the + // blob. Should return a data pipe to which all the data read from the blob + // should be written. + virtual mojo::ScopedDataPipeProducerHandle PassDataPipe() = 0; + + // Called whenever some amount of data is read from the blob and about to be + // written to the data pipe. + virtual void DidRead(int num_bytes) {} + + // Called when reading the blob has finished. If an error occurs this could + // be the only method that gets called, but either way this method is always + // the last to be called, shortly before the delegate is deleted. + // |total_written_bytes| indicated the total number of bytes that were read + // from the blob, and written to the data pipe. When successful this should + // always be equal to the |content_size| that was passed to + // DidCalculateSize. + virtual void OnComplete(net::Error result, + uint64_t total_written_bytes) = 0; + }; + + static void Create(FileSystemContext* file_system_context, + const BlobDataHandle* handle, + const net::HttpByteRange& range, + std::unique_ptr<Delegate> delegate); + + private: + MojoBlobReader(FileSystemContext* file_system_context, + const BlobDataHandle* handle, + const net::HttpByteRange& range, + std::unique_ptr<Delegate> delegate); + ~MojoBlobReader(); + + void Start(); + + void NotifyCompletedAndDeleteIfNeeded(int result); + + void DidCalculateSize(int result); + void DidReadSideData(BlobReader::Status status); + void StartReading(); + void ReadMore(); + void DidRead(bool completed_synchronously, int num_bytes); + void OnResponseBodyStreamClosed(MojoResult result); + void OnResponseBodyStreamReady(MojoResult result); + + std::unique_ptr<Delegate> delegate_; + + // The range of the blob that should be read. Could be unbounded if the entire + // blob is being read. + net::HttpByteRange byte_range_; + + // Underlying BlobReader data is being read from. + std::unique_ptr<BlobReader> blob_reader_; + + // Mojo data pipe where the data that is being read is written to. Will be + // null during write operations, at which time |pending_write_| owns the data + // pipe instead. + mojo::ScopedDataPipeProducerHandle response_body_stream_; + + // During a write operation this owns the data pipe handle and gives access to + // the pipe's internal buffer where data should be written. + scoped_refptr<network::NetToMojoPendingBuffer> pending_write_; + + // Watchers to keep track of the state of the data pipe. One watches for the + // pipe being writable, while the other watches for the pipe unexpectedly + // closing. + mojo::SimpleWatcher writable_handle_watcher_; + mojo::SimpleWatcher peer_closed_handle_watcher_; + + // Total number of bytes written to the data pipe so far. + int64_t total_written_bytes_ = 0; + + // Set to true when the delegate's OnComplete has been called. Used to make + // sure OnComplete isn't called more than once. + bool notified_completed_ = false; + + base::WeakPtrFactory<MojoBlobReader> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(MojoBlobReader); +}; + +} // namespace storage + +#endif
diff --git a/storage/public/interfaces/blobs.mojom b/storage/public/interfaces/blobs.mojom index eb51dd8..90654ea2 100644 --- a/storage/public/interfaces/blobs.mojom +++ b/storage/public/interfaces/blobs.mojom
@@ -9,11 +9,41 @@ import "mojo/common/time.mojom"; import "url/mojo/url.mojom"; +// Interface that can be implemented to be informed of certain information while +// reading the data for a blob. +interface BlobReaderClient { + // Called when the size of the blob being read has been calculated: + // |total_size| is the total size of the blob. + // |expected_content_size| is how many bytes should be sent over the data + // pipe, taking into account a range if the blob was read with ReadRange. + // If an error occurs while reading the blob, this method might not get called. + OnCalculatedSize(uint64 total_size, + uint64 expected_content_size); + + // Called when reading the blob finished (with success or failure). Status is + // a net::Error indicating any potential error that might have occurred, + // |data_length| tells the reader how many bytes were written into the data + // pipe, and can be used as a sanity check to make sure all bytes were + // received. + OnComplete(int32 status, uint64 data_length); +}; + // This interface provides access to a blob in the blob system. interface Blob { // Creates a copy of this Blob reference. Clone(Blob& blob); + // Causes the entire contents of this blob to be written into the given data + // pipe. An optional BlobReaderClient will be informed of the result of the + // read operation. + ReadAll(handle<data_pipe_producer> pipe, BlobReaderClient? client); + + // Causes a subrange of the contents of this blob to be written into the given + // data pipe. An optional BlobReaderClient will be informed of the result of + // the read operation. + ReadRange(uint64 offset, uint64 length, handle<data_pipe_producer> pipe, + BlobReaderClient? client); + // This method is an implementation detail of the blob system. You should not // ever need to call it directly. // This returns the internal UUID of the blob, used by the blob system to
diff --git a/testing/android/docs/instrumentation.md b/testing/android/docs/instrumentation.md index 458e03f5..cfd9f0c 100644 --- a/testing/android/docs/instrumentation.md +++ b/testing/android/docs/instrumentation.md
@@ -51,13 +51,20 @@ In many cases, Chromium has extended the instrumentation test framework classes to implement additional features. -### Test runners +### Tracing -[todo](/testing/android/docs/todo.md) +Enabling tracing during a test run allows all the function calls involved to be +observed in a visual display (using Chrome's built-in chrome://tracing feature). +To run a test with tracing, add the `--trace-output` flag to the command used to +call the instrumentation test (either running the test_runner.py script, or a +generated binary such as `run_chrome_public_test_apk`). The `--trace-output` flag +takes a filename, which, after the test run, will contain a JSON file readable +by chrome://tracing. -### Test cases - -[todo](/testing/android/docs/todo.md) +By default, the trace includes only certain function calls important to the test +run, both within the Python test runner framework and the Java code running on +the device. For a more detailed look, add the (no-argument) `--trace-all` flag. +This causes every function called on the Python side to be added to the trace. ### Annotations
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json index 6e904f6..ffb4d42 100644 --- a/testing/buildbot/chromium.android.fyi.json +++ b/testing/buildbot/chromium.android.fyi.json
@@ -24,16 +24,18 @@ "Android Tests with Tracing": { "instrumentation_tests": [ { + "args": [ + "-f", + "ContextualSearchTapEventTest#*" + ], "test": "chrome_public_test_apk", "trace_output": true }, { - "test": "chrome_sync_shell_test_apk", - "trace_output": true + "test": "chrome_sync_shell_test_apk" }, { - "test": "content_shell_test_apk", - "trace_output": true + "test": "content_shell_test_apk" } ] },
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 27a41f4..cf86565 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -10472,8 +10472,7 @@ }, "Fuchsia": { "additional_compile_targets": [ - "gl_unittests", - "net_unittests" + "gl_unittests" ], "gtest_tests": [ { @@ -10549,6 +10548,16 @@ "test": "mojo_system_unittests" }, { + "args": [ + "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.net_unittests.filter", + "--test-launcher-batch-limit=200" + ], + "swarming": { + "can_use_on_swarming_builders": false + }, + "test": "net_unittests" + }, + { "swarming": { "can_use_on_swarming_builders": false }, @@ -11263,18 +11272,6 @@ } ] }, - "test": "oop_heap_profiling_unit_tests" - }, - { - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "device_type": "coho" - } - ] - }, "test": "remoting_unittests" }, { @@ -11682,12 +11679,6 @@ "swarming": { "can_use_on_swarming_builders": true }, - "test": "oop_heap_profiling_unit_tests" - }, - { - "swarming": { - "can_use_on_swarming_builders": true - }, "test": "pdf_unittests" }, { @@ -12000,12 +11991,6 @@ "swarming": { "can_use_on_swarming_builders": true }, - "test": "oop_heap_profiling_unit_tests" - }, - { - "swarming": { - "can_use_on_swarming_builders": true - }, "test": "pdf_unittests" }, { @@ -12295,12 +12280,6 @@ "swarming": { "can_use_on_swarming_builders": true }, - "test": "oop_heap_profiling_unit_tests" - }, - { - "swarming": { - "can_use_on_swarming_builders": true - }, "test": "pdf_unittests" }, { @@ -13668,7 +13647,7 @@ }, { "gpu": "8086:0a2e", - "hidpi": 0, + "hidpi": "0", "os": "Mac-10.12.5" } ],
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index 78e420f..0540cb24 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -2408,413 +2408,6 @@ "isolated_scripts": [] }, "Linux ChromiumOS Ozone Builder": {}, - "Linux Debug (Intel HD 530)": { - "gtest_tests": [ - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - }, - "test": "angle_end2end_tests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0", - "--no-xvfb" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - }, - "test": "angle_unittests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - }, - "test": "audio_unittests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - }, - "test": "gl_tests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests", - "--no-xvfb" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - }, - "test": "gl_unittests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - }, - "test": "gles2_conform_test", - "use_xvfb": false - }, - { - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - }, - "test": "swiftshader_unittests", - "use_xvfb": false - } - ], - "isolated_scripts": [ - { - "args": [ - "context_lost", - "--show-stdout", - "--browser=debug", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "context_lost_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - } - }, - { - "args": [ - "depth_capture", - "--show-stdout", - "--browser=debug", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "depth_capture_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - } - }, - { - "args": [ - "gpu_process", - "--show-stdout", - "--browser=debug", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "gpu_process_launch_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - } - }, - { - "args": [ - "hardware_accelerated_feature", - "--show-stdout", - "--browser=debug", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "hardware_accelerated_feature_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - } - }, - { - "args": [ - "info_collection", - "--show-stdout", - "--browser=debug", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--expected-vendor-id", - "8086", - "--expected-device-id", - "1912" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "info_collection_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - } - }, - { - "args": [ - "maps", - "--show-stdout", - "--browser=debug", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--os-type", - "linux", - "--build-revision", - "${got_revision}", - "--test-machine-name", - "${buildername}" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "maps_pixel_test", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - } - }, - { - "args": [ - "pixel", - "--show-stdout", - "--browser=debug", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--refimg-cloud-storage-bucket", - "chromium-gpu-archive/reference-images", - "--os-type", - "linux", - "--build-revision", - "${got_revision}", - "--test-machine-name", - "${buildername}" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "pixel_test", - "non_precommit_args": [ - "--upload-refimg-to-cloud-storage" - ], - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "precommit_args": [ - "--download-refimg-from-cloud-storage" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - } - }, - { - "args": [ - "screenshot_sync", - "--show-stdout", - "--browser=debug", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "screenshot_sync_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - } - }, - { - "args": [ - "trace_test", - "--show-stdout", - "--browser=debug", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "trace_test", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=debug", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-passthrough-cmd-decoder" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl_conformance_gl_passthrough_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=debug", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl_conformance_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - } - } - ] - }, "Linux Debug (NVIDIA)": { "gtest_tests": [ { @@ -3862,481 +3455,6 @@ } ] }, - "Linux Release (Intel HD 530)": { - "gtest_tests": [ - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - }, - "test": "angle_end2end_tests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0", - "--no-xvfb" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - }, - "test": "angle_unittests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - }, - "test": "audio_unittests", - "use_xvfb": false - }, - { - "args": [ - "--enable-gpu", - "--no-xvfb", - "--test-launcher-jobs=1", - "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*" - ], - "name": "tab_capture_end2end_tests", - "swarming": { - "can_use_on_swarming_builders": false - }, - "test": "browser_tests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - }, - "test": "gl_tests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests", - "--no-xvfb" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - }, - "test": "gl_unittests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - }, - "test": "gles2_conform_test", - "use_xvfb": false - }, - { - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - }, - "test": "swiftshader_unittests", - "use_xvfb": false - } - ], - "isolated_scripts": [ - { - "args": [ - "context_lost", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "context_lost_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - } - }, - { - "args": [ - "depth_capture", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "depth_capture_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - } - }, - { - "args": [ - "gpu_process", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "gpu_process_launch_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - } - }, - { - "args": [ - "hardware_accelerated_feature", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "hardware_accelerated_feature_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - } - }, - { - "args": [ - "info_collection", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--expected-vendor-id", - "8086", - "--expected-device-id", - "1912" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "info_collection_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - } - }, - { - "args": [ - "maps", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--os-type", - "linux", - "--build-revision", - "${got_revision}", - "--test-machine-name", - "${buildername}" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "maps_pixel_test", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - } - }, - { - "args": [ - "pixel", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--refimg-cloud-storage-bucket", - "chromium-gpu-archive/reference-images", - "--os-type", - "linux", - "--build-revision", - "${got_revision}", - "--test-machine-name", - "${buildername}" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "pixel_test", - "non_precommit_args": [ - "--upload-refimg-to-cloud-storage" - ], - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "precommit_args": [ - "--download-refimg-from-cloud-storage" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - } - }, - { - "args": [ - "screenshot_sync", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "screenshot_sync_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - } - }, - { - "args": [ - "trace_test", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "trace_test", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-passthrough-cmd-decoder", - "--webgl-conformance-version=2.0.1", - "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl2_conformance_gl_passthrough_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ], - "shards": 15 - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--webgl-conformance-version=2.0.1", - "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl2_conformance_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ], - "shards": 15 - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-passthrough-cmd-decoder" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl_conformance_gl_passthrough_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl_conformance_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Ubuntu" - } - ] - } - } - ] - }, "Linux Release (Intel HD 630)": { "gtest_tests": [ { @@ -11898,550 +11016,6 @@ } ] }, - "Win10 Debug (Intel HD 530)": { - "gtest_tests": [ - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - }, - "test": "angle_end2end_tests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - }, - "test": "angle_unittests", - "use_xvfb": false - }, - { - "args": [ - "--test-launcher-retry-limit=0" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - }, - "test": "angle_white_box_tests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - }, - "test": "audio_unittests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - }, - "test": "gl_tests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - }, - "test": "gl_unittests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests", - "--use-angle=d3d9" - ], - "name": "gles2_conform_d3d9_test", - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - }, - "test": "gles2_conform_test", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests", - "--use-angle=gl", - "--disable-gpu-sandbox" - ], - "name": "gles2_conform_gl_test", - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - }, - "test": "gles2_conform_test", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - }, - "test": "gles2_conform_test", - "use_xvfb": false - }, - { - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - }, - "test": "swiftshader_unittests", - "use_xvfb": false - }, - { - "args": [ - "--use-angle=d3d11", - "--use-test-data-path", - "--test_video_data=test-25fps.h264:320:240:250:258:::1" - ], - "name": "video_decode_accelerator_d3d11_unittest", - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - }, - "test": "video_decode_accelerator_unittest", - "use_xvfb": false - }, - { - "args": [ - "--use-angle=d3d9", - "--use-test-data-path", - "--test_video_data=test-25fps.h264:320:240:250:258:::1" - ], - "name": "video_decode_accelerator_d3d9_unittest", - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - }, - "test": "video_decode_accelerator_unittest", - "use_xvfb": false - } - ], - "isolated_scripts": [ - { - "args": [ - "context_lost", - "--show-stdout", - "--browser=debug", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "context_lost_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "depth_capture", - "--show-stdout", - "--browser=debug", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "depth_capture_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "gpu_process", - "--show-stdout", - "--browser=debug", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "gpu_process_launch_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "hardware_accelerated_feature", - "--show-stdout", - "--browser=debug", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "hardware_accelerated_feature_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "info_collection", - "--show-stdout", - "--browser=debug", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--expected-vendor-id", - "8086", - "--expected-device-id", - "1912" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "info_collection_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "maps", - "--show-stdout", - "--browser=debug", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--os-type", - "win", - "--build-revision", - "${got_revision}", - "--test-machine-name", - "${buildername}" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "maps_pixel_test", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "pixel", - "--show-stdout", - "--browser=debug", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--refimg-cloud-storage-bucket", - "chromium-gpu-archive/reference-images", - "--os-type", - "win", - "--build-revision", - "${got_revision}", - "--test-machine-name", - "${buildername}" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "pixel_test", - "non_precommit_args": [ - "--upload-refimg-to-cloud-storage" - ], - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "precommit_args": [ - "--download-refimg-from-cloud-storage" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "screenshot_sync", - "--show-stdout", - "--browser=debug", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "screenshot_sync_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "trace_test", - "--show-stdout", - "--browser=debug", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "trace_test", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=debug", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d11 --use-passthrough-cmd-decoder" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl_conformance_d3d11_passthrough_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=debug", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d9" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl_conformance_d3d9_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=debug", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=gl" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl_conformance_gl_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=debug", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl_conformance_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - } - ] - }, "Win10 Debug (NVIDIA)": { "gtest_tests": [ { @@ -12528,6 +11102,24 @@ }, { "args": [ + "--use-gpu-in-tests", + "--use-passthrough-cmd-decoder" + ], + "name": "gl_tests_passthrough", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:104a", + "os": "Windows-10" + } + ] + }, + "test": "gl_tests", + "use_xvfb": false + }, + { + "args": [ "--use-gpu-in-tests" ], "swarming": { @@ -13005,591 +11597,6 @@ } ] }, - "Win10 Release (Intel HD 530)": { - "gtest_tests": [ - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - }, - "test": "angle_end2end_tests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - }, - "test": "angle_unittests", - "use_xvfb": false - }, - { - "args": [ - "--test-launcher-retry-limit=0" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - }, - "test": "angle_white_box_tests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - }, - "test": "audio_unittests", - "use_xvfb": false - }, - { - "args": [ - "--enable-gpu", - "--no-xvfb", - "--test-launcher-jobs=1", - "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*" - ], - "name": "tab_capture_end2end_tests", - "swarming": { - "can_use_on_swarming_builders": false - }, - "test": "browser_tests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - }, - "test": "gl_tests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - }, - "test": "gl_unittests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests", - "--use-angle=d3d9" - ], - "name": "gles2_conform_d3d9_test", - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - }, - "test": "gles2_conform_test", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests", - "--use-angle=gl", - "--disable-gpu-sandbox" - ], - "name": "gles2_conform_gl_test", - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - }, - "test": "gles2_conform_test", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - }, - "test": "gles2_conform_test", - "use_xvfb": false - }, - { - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - }, - "test": "swiftshader_unittests", - "use_xvfb": false - }, - { - "args": [ - "--use-angle=d3d11", - "--use-test-data-path", - "--test_video_data=test-25fps.h264:320:240:250:258:::1" - ], - "name": "video_decode_accelerator_d3d11_unittest", - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - }, - "test": "video_decode_accelerator_unittest", - "use_xvfb": false - }, - { - "args": [ - "--use-angle=d3d9", - "--use-test-data-path", - "--test_video_data=test-25fps.h264:320:240:250:258:::1" - ], - "name": "video_decode_accelerator_d3d9_unittest", - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - }, - "test": "video_decode_accelerator_unittest", - "use_xvfb": false - } - ], - "isolated_scripts": [ - { - "args": [ - "context_lost", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "context_lost_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "depth_capture", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "depth_capture_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "gpu_process", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "gpu_process_launch_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "hardware_accelerated_feature", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "hardware_accelerated_feature_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "info_collection", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--expected-vendor-id", - "8086", - "--expected-device-id", - "1912" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "info_collection_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "maps", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--os-type", - "win", - "--build-revision", - "${got_revision}", - "--test-machine-name", - "${buildername}" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "maps_pixel_test", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "pixel", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--refimg-cloud-storage-bucket", - "chromium-gpu-archive/reference-images", - "--os-type", - "win", - "--build-revision", - "${got_revision}", - "--test-machine-name", - "${buildername}" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "pixel_test", - "non_precommit_args": [ - "--upload-refimg-to-cloud-storage" - ], - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "precommit_args": [ - "--download-refimg-from-cloud-storage" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "screenshot_sync", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "screenshot_sync_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "trace_test", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "trace_test", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--webgl-conformance-version=2.0.1", - "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl2_conformance_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ], - "shards": 15 - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d11 --use-passthrough-cmd-decoder" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl_conformance_d3d11_passthrough_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d9" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl_conformance_d3d9_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=gl" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl_conformance_gl_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl_conformance_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "8086:1912", - "os": "Windows-10" - } - ] - } - } - ] - }, "Win10 Release (Intel HD 630)": { "gtest_tests": [ { @@ -13690,6 +11697,24 @@ }, { "args": [ + "--use-gpu-in-tests", + "--use-passthrough-cmd-decoder" + ], + "name": "gl_tests_passthrough", + "swarming": { + "can_use_on_swarming_builders": false, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + }, + "test": "gl_tests", + "use_xvfb": false + }, + { + "args": [ "--use-gpu-in-tests" ], "swarming": { @@ -14275,6 +12300,24 @@ }, { "args": [ + "--use-gpu-in-tests", + "--use-passthrough-cmd-decoder" + ], + "name": "gl_tests_passthrough", + "swarming": { + "can_use_on_swarming_builders": false, + "dimension_sets": [ + { + "gpu": "10de:1cb3", + "os": "Windows-10" + } + ] + }, + "test": "gl_tests", + "use_xvfb": false + }, + { + "args": [ "--use-gpu-in-tests" ], "swarming": { @@ -14885,6 +12928,24 @@ }, { "args": [ + "--use-gpu-in-tests", + "--use-passthrough-cmd-decoder" + ], + "name": "gl_tests_passthrough", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:104a", + "os": "Windows-10" + } + ] + }, + "test": "gl_tests", + "use_xvfb": false + }, + { + "args": [ "--use-gpu-in-tests" ], "swarming": { @@ -15557,6 +13618,24 @@ }, { "args": [ + "--use-gpu-in-tests", + "--use-passthrough-cmd-decoder" + ], + "name": "gl_tests_passthrough", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6613", + "os": "Windows-2008ServerR2-SP1" + } + ] + }, + "test": "gl_tests", + "use_xvfb": false + }, + { + "args": [ "--use-gpu-in-tests" ], "swarming": { @@ -16096,6 +14175,24 @@ }, { "args": [ + "--use-gpu-in-tests", + "--use-passthrough-cmd-decoder" + ], + "name": "gl_tests_passthrough", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:104a", + "os": "Windows-2008ServerR2-SP1" + } + ] + }, + "test": "gl_tests", + "use_xvfb": false + }, + { + "args": [ "--use-gpu-in-tests" ], "swarming": { @@ -16692,6 +14789,24 @@ }, { "args": [ + "--use-gpu-in-tests", + "--use-passthrough-cmd-decoder" + ], + "name": "gl_tests_passthrough", + "swarming": { + "can_use_on_swarming_builders": false, + "dimension_sets": [ + { + "gpu": "1002:6613", + "os": "Windows-2008ServerR2-SP1" + } + ] + }, + "test": "gl_tests", + "use_xvfb": false + }, + { + "args": [ "--use-gpu-in-tests" ], "swarming": { @@ -17297,6 +15412,24 @@ }, { "args": [ + "--use-gpu-in-tests", + "--use-passthrough-cmd-decoder" + ], + "name": "gl_tests_passthrough", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "1002:6613", + "os": "Windows-2008ServerR2-SP1" + } + ] + }, + "test": "gl_tests", + "use_xvfb": false + }, + { + "args": [ "--use-gpu-in-tests" ], "swarming": { @@ -17975,6 +16108,24 @@ }, { "args": [ + "--use-gpu-in-tests", + "--use-passthrough-cmd-decoder" + ], + "name": "gl_tests_passthrough", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:104a", + "os": "Windows-2008ServerR2-SP1" + } + ] + }, + "test": "gl_tests", + "use_xvfb": false + }, + { + "args": [ "--use-gpu-in-tests" ], "swarming": { @@ -18632,6 +16783,24 @@ }, { "args": [ + "--use-gpu-in-tests", + "--use-passthrough-cmd-decoder" + ], + "name": "gl_tests_passthrough", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:104a", + "os": "Windows-2008ServerR2-SP1" + } + ] + }, + "test": "gl_tests", + "use_xvfb": false + }, + { + "args": [ "--use-gpu-in-tests" ], "swarming": { @@ -19250,6 +17419,24 @@ }, { "args": [ + "--use-gpu-in-tests", + "--use-passthrough-cmd-decoder" + ], + "name": "gl_tests_passthrough", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:104a", + "os": "Windows-2008ServerR2-SP1" + } + ] + }, + "test": "gl_tests", + "use_xvfb": false + }, + { + "args": [ "--use-gpu-in-tests" ], "swarming": {
diff --git a/testing/buildbot/chromium.gpu.json b/testing/buildbot/chromium.gpu.json index 5f677998..9231b165 100644 --- a/testing/buildbot/chromium.gpu.json +++ b/testing/buildbot/chromium.gpu.json
@@ -2050,6 +2050,24 @@ }, { "args": [ + "--use-gpu-in-tests", + "--use-passthrough-cmd-decoder" + ], + "name": "gl_tests_passthrough", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:104a", + "os": "Windows-2008ServerR2-SP1" + } + ] + }, + "test": "gl_tests", + "use_xvfb": false + }, + { + "args": [ "--use-gpu-in-tests" ], "swarming": { @@ -2408,6 +2426,24 @@ }, { "args": [ + "--use-gpu-in-tests", + "--use-passthrough-cmd-decoder" + ], + "name": "gl_tests_passthrough", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:104a", + "os": "Windows-2008ServerR2-SP1" + } + ] + }, + "test": "gl_tests", + "use_xvfb": false + }, + { + "args": [ "--use-gpu-in-tests" ], "swarming": {
diff --git a/testing/buildbot/filters/fuchsia.media_unittests.filter b/testing/buildbot/filters/fuchsia.media_unittests.filter index bbe7692..4404e90d 100644 --- a/testing/buildbot/filters/fuchsia.media_unittests.filter +++ b/testing/buildbot/filters/fuchsia.media_unittests.filter
@@ -4,8 +4,11 @@ -Mojo* # These tests are slow and may flake under qemu. crbug.com/745094 --Pipeline* +-*AesDecryptorTest.* +-*SincResamplerTest* +-AudioRendererAlgorithmTest.FillBuffer_LargeBufferSize -MediaRemotingIntegrationTest* +-Pipeline* # These tests depend on base::CancelableSyncSocket, which is currently # broken, see https://crbug.com/741783
diff --git a/testing/buildbot/filters/fuchsia.net_unittests.filter b/testing/buildbot/filters/fuchsia.net_unittests.filter index d7065d5..d18ec7f 100644 --- a/testing/buildbot/filters/fuchsia.net_unittests.filter +++ b/testing/buildbot/filters/fuchsia.net_unittests.filter
@@ -1,5 +1,4 @@ # TODO(fuchsia): Fix these tests and remove the filter. crbug.com/731302 . - -*HTTPS* -*QuicEndToEndTest.Large* -*QuicEndToEndTest.TokenBinding* @@ -8,18 +7,19 @@ -*RootCert* -*Socket* -BbrSenderTest.SimpleTransferAckDecimation2 +-BidirectionalStreamTest.TestHonorAlternativeServiceHeader -CertNetFetcherImplTest* -CertVerifyProcInternalTest.* -CloseOnConnectHttpServerTest.ServerImmediatelyClosesConnection -DiskCache* -EffectiveConnectionTypeTest* -EmbeddedTestServer* --FileStreamTest.* -HttpNetworkTransactionTest.UploadUnreadableFile -HttpServerTest.* -NetworkInterfacesTest.GetNetworkList -NetworkQualitiesPrefManager* -NetworkQualityEstimatorTest* +-NetworkThrottleManager* -Proxy* -PythonUtils* -QuicSimpleClientTest* @@ -32,3 +32,13 @@ -TokenBindingURLRequest* -URLFetcher* -URLRequest* +-HostResolverImplDnsTest.DnsTask + +# TODO(fuchsia): These run too slowly at present. crbug.com/745094 +-BbrSenderTest.* +-CryptoServerTests/* +-HttpNetworkTransactionTest.* +-*Quic* +-RangeOfTreeSizes/* +-*Spdy* +-*SendAlgorithmTests.*
diff --git a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter index b03eeb6a..d2e1074 100644 --- a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter +++ b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter
@@ -143,8 +143,10 @@ -TouchInputBrowserTest.MultiPointTouchPress -TouchInputBrowserTest.TouchHandlerNoConsume -WebContentsImplBrowserTest.ClearNonVisiblePendingOnFail +-WebContentsImplBrowserTest.DidGetResourceResponseStartUpdatesWaitingState -WebContentsImplBrowserTest.DownloadImage_Deny_FileImage -WebContentsImplBrowserTest.GetSizeForNewRenderView +-WebContentsImplBrowserTest.LoadingStateChangedForSameDocumentNavigation -WebContentsImplBrowserTest.UserAgentOverride -WebContentsViewAuraTest.ScreenshotForSwappedOutRenderViews -WebRtcGetUserMediaOldConstraintsBrowserTest.GetUserMediaWithInvalidMandatorySourceID @@ -161,3 +163,7 @@ # content/network/url_loader_impl.cc should handle failure in # URLLoaderImpl::OnResponseBodyStreamRead(). -SRC_ClearKey/EncryptedMediaTest.FrameSizeChangeVideo/0 + +# https://crbug.com/754827 +-ResourceDispatcherHostBrowserTest.SyncXMLHttpRequest_Cancelled +-BrowserSideNavigationBrowserDisableWebSecurityTest.ValidateBaseUrlForDataUrl
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index f0c0957..71a4061 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -777,10 +777,6 @@ "label": "//chrome/installer/mini_installer:next_version_mini_installer", "type": "additional_compile_target", }, - "oop_heap_profiling_unit_tests": { - "label": "//chrome/profiling:unit_tests", - "type": "console_test_launcher", - }, "ozone_unittests": { "label": "//ui/ozone:ozone_unittests", "type": "console_test_launcher",
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 22b5e67..be426c28 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1696,8 +1696,8 @@ "params": { "availability": "any", "event_new_tab_opened": "name:new_tab_opened;comparator:==0;window:3650;storage:3650", + "event_new_tab_session_time_met": "name:new_tab_session_time_met;comparator:>=1;window:3650;storage:3650", "event_omnibox_used": "name:omnibox_used;comparator:>=1;window:3650;storage:3650", - "event_session_time": "name:session_time;comparator:>=1;window:3650;storage:3650", "event_trigger": "name:new_tab_trigger;comparator:any;window:3650;storage:3650", "event_used": "name:new_tab_clicked;comparator:any;window:3650;storage:3650", "session_rate": "<=3",
diff --git a/third_party/.gitignore b/third_party/.gitignore index 4213f70..94db067 100644 --- a/third_party/.gitignore +++ b/third_party/.gitignore
@@ -24,7 +24,7 @@ /apache-win32/modules/*.dll /apk-patch-size-estimator/lib/*.jar /asan -/bazel/desugar/*.jar +/bazel/desugar/Desugar.jar /bidichecker /bison /boringssl/src
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService index f7ed034..f3edfc1 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
@@ -277,7 +277,6 @@ Bug(none) external/wpt/navigation-timing/nav2_test_attributes_values.html [ Failure Timeout ] Bug(none) external/wpt/navigation-timing/nav2_test_unloadEvents_previous_document_cross_origin.sub.html [ Failure Timeout ] Bug(none) external/wpt/notifications/shownotification-resolve-manual.https.html [ Failure Timeout ] -Bug(none) external/wpt/offscreen-canvas [ Crash Failure Timeout ] Bug(none) external/wpt/preload/fetch-destination.https.html [ Crash Failure Timeout ] Bug(none) external/wpt/preload/single-download-preload.html [ Failure Timeout ] Bug(none) external/wpt/resource-timing/resource_TAO_match_origin.htm [ Failure Timeout ] @@ -387,19 +386,15 @@ Bug(none) http/tests/appcache/fallback.html [ Failure ] Bug(none) http/tests/appcache/local-content.html [ Timeout ] Bug(none) http/tests/appcache/main-resource-hash.html [ Timeout ] -Bug(none) http/tests/appcache/main-resource-redirect.html [ Timeout ] -Bug(715632) http/tests/appcache/manifest-redirect-2.html [ Crash ] -Bug(715632) http/tests/appcache/manifest-redirect.html [ Crash ] +Bug(754827) http/tests/appcache/main-resource-redirect.html [ Crash ] Bug(none) http/tests/appcache/manifest-parsing.html [ Failure ] Bug(none) http/tests/appcache/multi-fallback.html [ Failure Timeout ] Bug(none) http/tests/appcache/non-html.xhtml [ Crash ] -Bug(none) http/tests/appcache/offline-access.html [ Timeout ] -Bug(none) http/tests/appcache/online-fallback-layering.html [ Timeout ] +Bug(754827) http/tests/appcache/offline-access.html [ Crash ] +Bug(754827) http/tests/appcache/online-fallback-layering.html [ Failure ] Bug(none) http/tests/appcache/online-whitelist.html [ Failure ] Bug(none) http/tests/appcache/reload.html [ Crash Failure Timeout ] Bug(none) http/tests/appcache/remove-cache.html [ Crash Failure Timeout ] -Bug(715632) http/tests/appcache/resource-redirect.html [ Crash ] -Bug(715632) http/tests/appcache/resource-redirect-2.html [ Crash ] Bug(none) http/tests/appcache/simple.html [ Timeout ] Bug(none) http/tests/appcache/top-frame-1.html [ Timeout ] Bug(none) http/tests/appcache/top-frame-2.html [ Crash Timeout ] @@ -729,21 +724,39 @@ Bug(none) http/tests/history/push-state-in-new-frame.html [ Timeout ] Bug(none) http/tests/htmlimports/import-cors-credentials.html [ Failure ] Bug(none) http/tests/https/verify-ssl-enabled.php [ Timeout ] -Bug(none) http/tests/inspector [ Crash Failure Timeout ] +Bug(none) http/tests/inspector/console-xhr-logging.html [ Failure ] +Bug(none) http/tests/inspector/console-resource-errors.html [ Timeout ] +Bug(none) http/tests/inspector/extensions-headers.html [ Failure ] +Bug(none) http/tests/inspector/extensions-ignore-cache.html [ Crash ] +Bug(none) http/tests/inspector/extensions-useragent.html [ Crash ] +Bug(none) http/tests/inspector/extensions/extensions-panel.html [ Failure ] +Bug(none) http/tests/inspector/network-preflight-options.html [ Timeout ] +Bug(none) http/tests/inspector/network/har-content.html [ Failure Timeout ] +Bug(none) http/tests/inspector/network/load-resource-for-frontend.html [ Failure Timeout ] +Bug(none) http/tests/inspector/network/network-content-replacement-xhr.html [ Timeout ] +Bug(none) http/tests/inspector/network/network-cyrillic-xhr.html [ Timeout ] +Bug(none) http/tests/inspector/network/network-empty-xhr.html [ Timeout ] +Bug(none) http/tests/inspector/network/network-xhr-sync.html [ Timeout ] +Bug(none) http/tests/inspector/resource-tree/resource-tree-no-xhrs.html [ Timeout ] +Bug(none) http/tests/inspector/network/network-datareceived.html [ Failure ] +Bug(none) http/tests/inspector/network/network-xhr-replay.html [ Failure ] +Bug(none) http/tests/inspector/network/ping-response.html [ Failure ] +Bug(none) http/tests/inspector/network/warning-for-long-cookie.html [ Failure ] +Bug(none) http/tests/inspector/network/x-frame-options-deny.html [ Failure ] +Bug(none) http/tests/inspector/network/long-script-content.html [ Crash ] +Bug(none) http/tests/inspector/persistence/persistence-tabbed-editor-tabs-order.html [ Crash ] +Bug(none) http/tests/inspector/resource-har-conversion.html [ Failure ] +Bug(none) http/tests/inspector/resource-parameters.html [ Failure ] +Bug(none) http/tests/inspector/resource-parameters-ipv6.html [ Timeout ] +Bug(none) http/tests/inspector/service-workers/service-workers-bypass-for-network-redirect.html [ Crash ] +Bug(none) http/tests/inspector/service-workers/service-workers-force-update-on-page-load.html [ Timeout ] +Bug(none) http/tests/inspector/service-workers/service-workers-navigation-preload.html [ Timeout ] +Bug(none) http/tests/inspector/service-workers/service-workers-redundant.html [ Timeout ] +Bug(none) http/tests/inspector/service-workers/service-workers-view.html [ Timeout ] +Bug(none) http/tests/inspector/sources/debugger/pause-in-removed-frame.html [ Timeout ] Bug(none) http/tests/inspector-enabled [ Failure Timeout ] Bug(none) http/tests/inspector-protocol [ Failure Timeout ] -Bug(none) http/tests/inspector-protocol/cachestorage/read-cached-response.js [ Timeout ] Bug(none) http/tests/inspector-protocol/page/frameScheduledNavigation.js [ Crash ] -Bug(none) http/tests/inspector/extensions/extensions-api.html [ Timeout ] -Bug(none) http/tests/inspector/extensions/extensions-audits-api.html [ Timeout ] -Bug(none) http/tests/inspector/extensions/extensions-audits-content-script.html [ Timeout ] -Bug(none) http/tests/inspector/extensions/extensions-audits.html [ Timeout ] -Bug(none) http/tests/inspector/extensions/extensions-events.html [ Timeout ] -Bug(none) http/tests/inspector/extensions/extensions-network.html [ Failure Timeout ] -Bug(none) http/tests/inspector/extensions/extensions-reload.html [ Timeout ] -Bug(none) http/tests/inspector/extensions/extensions-resources.html [ Timeout ] -Bug(none) http/tests/inspector/extensions/extensions-timeline-api.html [ Timeout ] -Bug(none) http/tests/inspector/extensions/multiple-extensions.html [ Timeout ] Bug(none) http/tests/linkHeader/link-preconnect-schemeless.https.php [ Timeout ] Bug(none) http/tests/loading/307-after-303-after-post.html [ Failure ] Bug(none) http/tests/loading/doc-write-sync-third-party-script-reload.html [ Crash ] @@ -803,7 +816,7 @@ Bug(none) http/tests/navigation/ping-cross-origin-from-https.html [ Timeout ] Bug(none) http/tests/navigation/ping-same-origin.html [ Failure ] Bug(none) http/tests/navigation/post-basic.html [ Failure ] -Bug(none) http/tests/navigation/post-frames-goback1.html [ Failure ] +Bug(none) http/tests/navigation/post-frames-goback1.html [ Crash Failure ] Bug(none) http/tests/navigation/post-frames.html [ Failure ] Bug(none) http/tests/navigation/post-goback1.html [ Failure ] Bug(none) http/tests/navigation/redirect-on-back-updates-history-item.html [ Timeout ] @@ -894,7 +907,6 @@ Bug(none) http/tests/push_messaging/unsubscribe-in-service-worker.html [ Crash Failure Timeout ] Bug(none) http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-blocked-with-redirect.html [ Failure ] Bug(none) http/tests/security/contentSecurityPolicy/1.1/form-action-src-redirect-blocked.html [ Failure ] -Bug(none) http/tests/security/contentSecurityPolicy/block-mixed-content-hides-warning.html [ Failure ] Bug(none) http/tests/security/contentSecurityPolicy/cascade/same-origin-window-open.html [ Timeout ] Bug(none) http/tests/security/contentSecurityPolicy/cascade/same-origin-with-own-policy-window-open.html [ Timeout ] Bug(none) http/tests/security/contentSecurityPolicy/cascade/same-origin-with-own-policy.html [ Timeout ] @@ -902,164 +914,37 @@ Bug(none) http/tests/security/contentSecurityPolicy/frame-src-child-frame-navigates-to-blocked-origin.html [ Failure Timeout ] Bug(none) http/tests/security/contentSecurityPolicy/frame-src-cross-origin-load.html [ Failure ] Bug(none) http/tests/security/contentSecurityPolicy/frame-src-redirect-blocked.html [ Failure ] -Bug(none) http/tests/security/contentSecurityPolicy/register-bypassing-scheme-script.https.html [ Timeout ] Bug(none) http/tests/security/contentSecurityPolicy/report-same-origin-with-cookies.php [ Failure ] -Bug(none) http/tests/security/contentSecurityPolicy/script-src-star-cross-scheme.html [ Failure ] -Bug(none) http/tests/security/contentSecurityPolicy/source-list-parsing-10.html [ Failure ] Bug(none) http/tests/security/cookies/first-party-cookie-allow-xslt.xml [ Failure ] Bug(none) http/tests/security/cookies/third-party-cookie-blocking-main-frame.html [ Failure ] Bug(none) http/tests/security/cookies/third-party-cookie-blocking-worker.html [ Failure ] Bug(none) http/tests/security/cookies/xmlhttprequest.html [ Timeout ] Bug(none) http/tests/security/cors-rfc1918 [ Crash Timeout ] -Bug(none) http/tests/security/cross-frame-access-parent-explicit-domain-isolated-world.html [ Timeout ] -Bug(none) http/tests/security/cross-frame-access-parent-isolated-world.html [ Timeout ] -Bug(none) http/tests/security/cross-frame-access-protocol-explicit-domain.html [ Timeout ] -Bug(none) http/tests/security/cross-frame-access-protocol.html [ Timeout ] -Bug(none) http/tests/security/cross-origin-OffscreenCanvas2D-transferToImageBitmap.html [ Timeout ] -Bug(none) http/tests/security/cross-origin-OffscreenCanvasWebGL-texImage2D.html [ Timeout ] -Bug(none) http/tests/security/cross-origin-createImageBitmap.html [ Timeout ] -Bug(none) http/tests/security/detached-window-cross-origin-access.html [ Timeout ] -Bug(none) http/tests/security/document-all.html [ Failure ] Bug(none) http/tests/security/img-crossorigin-cookies.html [ Failure ] Bug(none) http/tests/security/img-redirect-to-crossorigin-credentials.html [ Failure ] Bug(none) http/tests/security/listener/xss-XMLHttpRequest-addEventListener.html [ Timeout ] -Bug(none) http/tests/security/local-video-source-from-remote.html [ Timeout ] -Bug(none) http/tests/security/location-change-from-detached-DOMWindow.html [ Timeout ] -Bug(none) http/tests/security/media-element-audio-source-node-cross-origin-allowed.html [ Timeout ] -Bug(none) http/tests/security/media-element-audio-source-node-cross-origin-with-credentials.html [ Failure Timeout ] Bug(none) http/tests/security/media-element-audio-source-node-cross-origin.html [ Failure Pass Timeout ] Bug(none) http/tests/security/media-element-audio-source-node-same-origin.html [ Failure Pass ] Bug(none) http/tests/security/mime-type-execute-as-html-01.html [ Failure ] Bug(none) http/tests/security/mime-type-execute-as-html-04.html [ Failure ] -Bug(none) http/tests/security/mixedContent/about-blank-iframe-in-main-frame.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/active-subresource-in-http-iframe-not-blocked.https.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/active-subresource-in-iframe-blocked.https.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/data-url-iframe-in-main-frame.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/data-url-script-in-data-iframe.https.html [ Timeout ] Bug(none) http/tests/security/mixedContent/filesystem-url-in-iframe.html [ Failure Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-async-post-xhr-blocked.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-audio-video-in-main-frame.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-css-image-with-reload.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-css-in-iframe.html [ Failure ] -Bug(none) http/tests/security/mixedContent/insecure-css-in-main-frame.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-css-resources.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-empty-srcset-in-main-frame-blocked.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-eventsource-in-main-frame.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-fetch-blocked.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-font-in-main-frame.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-formSubmission-in-invisible-DOM.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-formSubmission-in-main-frame-allowed.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-formSubmission-in-main-frame-blocked.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-formSubmission-in-main-frame-javascript-allowed.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-formSubmission-in-main-frame.html [ Timeout ] Bug(none) http/tests/security/mixedContent/insecure-frame-in-data-iframe-in-main-frame-blocked.html [ Failure Timeout ] Bug(none) http/tests/security/mixedContent/insecure-iframe-in-iframe.html [ Failure ] Bug(none) http/tests/security/mixedContent/insecure-iframe-in-main-frame-allowed.html [ Failure Timeout ] Bug(none) http/tests/security/mixedContent/insecure-iframe-in-main-frame-blocked.html [ Failure Timeout ] Bug(none) http/tests/security/mixedContent/insecure-iframe-in-main-frame.html [ Failure Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-iframe-with-hsts.https.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-image-in-iframe.html [ Failure ] -Bug(none) http/tests/security/mixedContent/insecure-image-in-main-frame-allowed.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-image-in-main-frame-blocked.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-image-in-main-frame.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-localhost-allowed.https.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-picture-in-main-frame-blocked.https.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-plugin-in-iframe.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-prefetch-in-main-frame.html [ Failure ] -Bug(none) http/tests/security/mixedContent/insecure-script-in-data-iframe-in-main-frame-blocked.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-script-in-iframe.html [ Failure ] -Bug(none) http/tests/security/mixedContent/insecure-script-in-main-frame-allowed.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-script-in-main-frame-blocked.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-script-through-redirection.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-srcset-in-main-frame-blocked.html [ Timeout ] Bug(none) http/tests/security/mixedContent/insecure-sync-post-xhr-allowed.html [ Failure Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-sync-post-xhr-blocked.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-texttrack-in-main-frame-blocked.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/insecure-xhr-in-main-frame.https.html [ Timeout ] Bug(none) http/tests/security/mixedContent/nonwebby-scheme-in-iframe-allowed.https.html [ Failure Timeout ] -Bug(none) http/tests/security/mixedContent/preload-insecure-image-in-main-frame-blocked.html [ Timeout ] Bug(none) http/tests/security/mixedContent/redirect-http-to-https-iframe-in-main-frame.html [ Failure Timeout ] -Bug(none) http/tests/security/mixedContent/redirect-http-to-https-script-in-iframe.html [ Failure ] Bug(none) http/tests/security/mixedContent/redirect-https-to-http-iframe-in-main-frame.html [ Failure Timeout ] -Bug(none) http/tests/security/mixedContent/redirect-https-to-http-script-in-iframe.html [ Failure ] -Bug(none) http/tests/security/mixedContent/strict-mode-image-blocked.https.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/strict-mode-image-in-frame-blocked.https.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/strict-mode-image-no-policy.https.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/strict-mode-image-reportonly.https.php [ Timeout ] -Bug(none) http/tests/security/mixedContent/strict-mode-via-pref-image-blocked.https.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/strict-mode-websocket-blocked.https.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/websocket/insecure-websocket-in-sandbox-in-secure-page.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/websocket/insecure-websocket-in-secure-page-allowed.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/websocket/insecure-websocket-in-secure-page-worker-allowed.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/websocket/insecure-websocket-in-secure-page-worker.html [ Timeout ] -Bug(none) http/tests/security/mixedContent/websocket/insecure-websocket-in-secure-page.html [ Timeout ] -Bug(none) http/tests/security/no-indexeddb-from-sandbox.html [ Failure ] -Bug(none) http/tests/security/no-popup-from-sandbox-top.html [ Failure ] -Bug(none) http/tests/security/no-popup-from-sandbox.html [ Failure ] Bug(none) http/tests/security/no-referrer.html [ Timeout ] Bug(none) http/tests/security/offscreen-canvas-worker-read-blocked-by-setting.html [ Crash Pass Timeout ] -Bug(none) http/tests/security/opened-document-security-origin-resets-on-navigation.html [ Timeout ] -Bug(none) http/tests/security/originHeader/origin-header-for-https.html [ Timeout ] -Bug(none) http/tests/security/popup-allowed-by-sandbox-can-navigate.html [ Failure ] -Bug(none) http/tests/security/popup-allowed-by-sandbox-is-sandboxed-control.html [ Failure ] -Bug(none) http/tests/security/popup-allowed-by-sandbox-is-sandboxed.html [ Failure ] -Bug(none) http/tests/security/popup-allowed-by-sandbox-when-allowed.html [ Failure ] -Bug(none) http/tests/security/powerfulFeatureRestrictions/geolocation-on-sandboxed-insecure-origin.html [ Timeout ] -Bug(none) http/tests/security/powerfulFeatureRestrictions/geolocation-on-secure-origin-in-insecure-origin.html [ Timeout ] -Bug(none) http/tests/security/powerfulFeatureRestrictions/geolocation-on-secure-origin-in-secure-origin.html [ Timeout ] -Bug(none) http/tests/security/powerfulFeatureRestrictions/serviceworker-on-insecure-origin.html [ Failure ] -Bug(none) http/tests/security/referrer-on-client-redirect.html [ Timeout ] -Bug(none) http/tests/security/referrer-policy-attribute-anchor-no-referrer-when-downgrade.html [ Timeout ] -Bug(none) http/tests/security/referrer-policy-attribute-area-no-referrer-when-downgrade.html [ Timeout ] -Bug(none) http/tests/security/referrer-policy-attribute-iframe-no-referrer-when-downgrade.html [ Timeout ] -Bug(none) http/tests/security/referrer-policy-attribute-img-no-referrer-when-downgrade.html [ Timeout ] -Bug(none) http/tests/security/referrer-policy-conflicting-policies.html [ Timeout ] -Bug(none) http/tests/security/referrer-policy-https-always.html [ Timeout ] -Bug(none) http/tests/security/referrer-policy-https-default.html [ Timeout ] -Bug(none) http/tests/security/referrer-policy-https-never.html [ Timeout ] -Bug(none) http/tests/security/referrer-policy-https-no-referrer-when-downgrade.html [ Timeout ] -Bug(none) http/tests/security/referrer-policy-https-no-referrer.html [ Timeout ] -Bug(none) http/tests/security/referrer-policy-https-origin-when-crossorigin.html [ Timeout ] -Bug(none) http/tests/security/referrer-policy-https-origin.html [ Timeout ] -Bug(none) http/tests/security/referrer-policy-https-unsafe-url.html [ Timeout ] -Bug(none) http/tests/security/referrer-policy-redirect-link.html [ Timeout ] -Bug(none) http/tests/security/referrer-policy-redirect.html [ Timeout ] -Bug(none) http/tests/security/referrerPolicyHeader/basic-header-cross-origin-with-origin-when-cross-origin.php [ Timeout ] -Bug(none) http/tests/security/referrerPolicyHeader/basic-header-cross-origin-with-origin.php [ Timeout ] -Bug(none) http/tests/security/referrerPolicyHeader/basic-header-downgrade-with-no-referrer-when-downgrade.https.php [ Timeout ] -Bug(none) http/tests/security/referrerPolicyHeader/basic-header-no-downgrade-with-no-referrer-when-downgrade.https.php [ Timeout ] -Bug(none) http/tests/security/referrerPolicyHeader/basic-header-unsafe-url.https.php [ Timeout ] -Bug(none) http/tests/security/referrerPolicyHeader/legacy-always.php [ Timeout ] -Bug(none) http/tests/security/referrerPolicyHeader/legacy-default.php [ Timeout ] -Bug(none) http/tests/security/referrerPolicyHeader/legacy-never.php [ Timeout ] -Bug(none) http/tests/security/referrerPolicyHeader/legacy-origin-when-crossorigin.php [ Timeout ] -Bug(none) http/tests/security/referrerPolicyHeader/referrer-policy-cross-origin-redirect.php [ Timeout ] -Bug(none) http/tests/security/referrerPolicyHeader/referrer-policy-header-on-cross-origin-redirect-response.https.html [ Timeout ] -Bug(none) http/tests/security/sandboxed-opener-can-close-window.html [ Failure ] -Bug(none) http/tests/security/secureContexts/authenticated.html [ Timeout ] -Bug(none) http/tests/security/secureContexts/authenticated_sandbox.html [ Timeout ] -Bug(none) http/tests/security/secureContexts/authenticated_srcdoc.html [ Timeout ] Bug(none) http/tests/security/secureContexts/authenticated_worker.https.html [ Timeout ] -Bug(none) http/tests/security/secureContexts/unauthenticated.html [ Timeout ] -Bug(none) http/tests/security/secureContexts/unauthenticated_sandbox.html [ Timeout ] -Bug(none) http/tests/security/secureContexts/unauthenticated_srcdoc.html [ Timeout ] Bug(none) http/tests/security/secureContexts/unauthenticated_worker.html [ Timeout ] Bug(none) http/tests/security/suborigins/suborigin-cookies.php [ Timeout ] Bug(none) http/tests/security/suborigins/suborigin-service-worker-fetch-event.html [ Crash Failure Timeout ] Bug(none) http/tests/security/suborigins/suborigin-service-worker-no-xorigin-caching.html [ Crash Timeout ] Bug(none) http/tests/security/suborigins/suborigin-unsafe-cookies.php [ Timeout ] -Bug(none) http/tests/security/upgrade-insecure-requests/basic-upgrade.https.html [ Timeout ] -Bug(none) http/tests/security/upgrade-insecure-requests/form-upgrade.html [ Timeout ] -Bug(none) http/tests/security/upgrade-insecure-requests/iframe-upgrade.https.html [ Timeout ] -Bug(none) http/tests/security/upgrade-insecure-requests/sandbox-upgrade.https.php [ Timeout ] -Bug(none) http/tests/security/video-cross-origin-readback.html [ Timeout ] -Bug(none) http/tests/security/video-cross-origin-via-dom.html [ Timeout ] -Bug(none) http/tests/security/webgl-remote-read-remote-image-allowed-with-credentials.html [ Timeout ] -Bug(none) http/tests/security/webgl-remote-read-remote-image-allowed.html [ Timeout ] -Bug(none) http/tests/security/webgl-remote-read-remote-image-blocked-no-crossorigin.html [ Timeout ] -Bug(none) http/tests/security/window-named-proto.html [ Failure ] -Bug(none) http/tests/security/window-named-valueOf.html [ Failure ] -Bug(none) http/tests/security/xss-exception.html [ Timeout ] Bug(none) http/tests/sendbeacon/beacon-cookie.html [ Failure ] Bug(none) http/tests/sendbeacon/beacon-cross-origin.https.html [ Timeout ] Bug(none) http/tests/sendbeacon/beacon-same-origin.html [ Failure ] @@ -1093,21 +978,11 @@ Bug(none) inspector-protocol/worker/exception-from-worker-contains-stack.js [ Timeout ] Bug(none) inspector-protocol/worker/worker-console.js [ Crash Timeout ] Bug(none) inspector/agents-enable-disable.html [ Timeout ] -Bug(none) inspector/animation/animation-KeyframeEffectReadOnly-crash.html [ Timeout ] -Bug(none) inspector/animation/animation-group-matching-animations.html [ Timeout ] -Bug(none) inspector/animation/animation-group-matching-transitions.html [ Timeout ] Bug(none) inspector/animation/animation-transition-setTiming-crash.html [ Timeout ] Bug(none) inspector/audits/audits-empty-stylesheet.html [ Timeout ] Bug(none) inspector/audits/audits-panel-functional.html [ Timeout ] Bug(none) inspector/audits/audits-panel-noimages-functional.html [ Timeout ] -Bug(none) inspector/changes/changes-highlighter.html [ Timeout ] -Bug(none) inspector/changes/changes-sidebar.html [ Timeout ] Bug(none) inspector/components/chunked-file-reader.html [ Failure Timeout ] -Bug(none) inspector/components/dom-extension.html [ Timeout ] -Bug(none) inspector/components/file-path-scoring.html [ Timeout ] -Bug(none) inspector/components/parsed-url.html [ Timeout ] -Bug(none) inspector/components/progress-bar.html [ Timeout ] -Bug(none) inspector/components/segmented-range.html [ Timeout ] Bug(none) inspector/components/throttler.html [ Failure ] Bug(none) inspector/console/console-copy-treeoutline.html [ Failure ] Bug(none) inspector/console/console-export.html [ Failure ] @@ -1120,138 +995,37 @@ Bug(none) inspector/console/console-log-short-hand-method.html [ Failure ] Bug(none) inspector/console/console-object-constructor-name.html [ Failure ] Bug(none) inspector/console/console-tests.html [ Failure ] -Bug(none) inspector/console/console-uncaught-promise.html [ Failure Timeout ] -Bug(none) inspector/coverage/coverage-repeated.html [ Failure Timeout ] Bug(none) inspector/coverage/coverage-view-filter.html [ Failure ] -Bug(none) inspector/coverage/coverage-view.html [ Failure Timeout ] -Bug(none) inspector/coverage/decorations-after-script-formatter.html [ Timeout ] -Bug(none) inspector/coverage/gutter-js.html [ Timeout ] Bug(none) inspector/coverage/multiple-instances-merge.html [ Timeout Failure ] -Bug(none) inspector/coverage/reveal-autoformat.html [ Timeout ] -Bug(none) inspector/coverage/segments-merge.html [ Timeout ] Bug(none) inspector/device-mode/device-mode-responsive.html [ Timeout ] Bug(none) inspector/device-mode/device-mode-switching-devices.html [ Timeout ] Bug(none) inspector/domdebugger/domdebugger-getEventListeners.html [ Timeout ] -Bug(none) inspector/editor/text-editor-ctrl-d-2.html [ Timeout ] Bug(none) inspector/editor/text-editor-enter-behaviour.html [ Timeout ] -Bug(none) inspector/editor/text-editor-reveal-line.html [ Timeout ] Bug(none) inspector/editor/text-editor-selection-to-search.html [ Timeout ] -Bug(none) inspector/editor/text-editor-smart-braces.html [ Timeout ] -Bug(none) inspector/editor/text-editor-token-at-position.html [ Timeout ] -Bug(none) inspector/elements/accessibility/autocomplete-attribute.html [ Timeout ] -Bug(none) inspector/elements/accessibility/edit-aria-attributes.html [ Timeout ] -Bug(none) inspector/elements/attribute-modified-ns.html [ Timeout ] -Bug(none) inspector/elements/bidi-dom-tree.html [ Timeout ] -Bug(none) inspector/elements/dom-search-crash.html [ Timeout ] Bug(none) inspector/elements/edit/edit-dom-actions-4.html [ Timeout ] -Bug(none) inspector/elements/elements-img-tooltip.html [ Timeout ] -Bug(none) inspector/elements/elements-panel-reload-assert.html [ Timeout ] Bug(none) inspector/elements/elements-panel-restore-selection-when-node-comes-later.html [ Timeout ] -Bug(none) inspector/elements/elements-panel-rewrite-href.html [ Timeout ] -Bug(none) inspector/elements/elements-panel-search.html [ Timeout ] -Bug(none) inspector/elements/elements-panel-selection-on-refresh.html [ Timeout ] -Bug(none) inspector/elements/elements-panel-styles.html [ Timeout ] -Bug(none) inspector/elements/event-listener-sidebar-remove.html [ Timeout ] -Bug(none) inspector/elements/hide-shortcut.html [ Timeout ] -Bug(none) inspector/elements/highlight/highlight-css-shapes-outside-scroll.html [ Timeout ] Bug(none) inspector/elements/highlight/highlight-dom-updates.html [ Timeout ] Bug(none) inspector/elements/highlight/highlight-node-transformed.html [ Timeout ] Bug(none) inspector/elements/highlight/highlight-node.html [ Timeout ] -Bug(none) inspector/elements/highlight/highlight-svg-root-zoomed.html [ Timeout ] -Bug(none) inspector/elements/highlight/highlight-svg-root.html [ Timeout ] -Bug(none) inspector/elements/shadow/breadcrumb-shadow-roots.html [ Timeout ] -Bug(none) inspector/elements/shadow/create-shadow-root.html [ Timeout ] Bug(none) inspector/elements/shadow/elements-panel-shadow-selection-on-refresh-1.html [ Timeout ] Bug(none) inspector/elements/shadow/elements-panel-shadow-selection-on-refresh-2.html [ Timeout ] -Bug(none) inspector/elements/shadow/elements-panel-shadow-selection-on-refresh-3.html [ Timeout ] Bug(none) inspector/elements/shadow/inspect-deep-shadow-element.html [ Timeout ] -Bug(none) inspector/elements/shadow/update-shadowdom.html [ Timeout ] Bug(none) inspector/elements/styles-1/color-aware-property-value-edit.html [ Timeout ] -Bug(none) inspector/elements/styles-1/css-live-edit.html [ Timeout ] -Bug(none) inspector/elements/styles-1/disable-property-workingcopy-update.html [ Timeout ] -Bug(none) inspector/elements/styles-1/edit-media-text.html [ Timeout ] -Bug(none) inspector/elements/styles-1/edit-name-with-trimmed-value.html [ Timeout ] -Bug(none) inspector/elements/styles-1/edit-value-inside-property.html [ Timeout ] Bug(none) inspector/elements/styles-1/empty-background-url.html [ Failure ] -Bug(none) inspector/elements/styles-2/add-import-rule.html [ Timeout ] -Bug(none) inspector/elements/styles-2/cssom-shorthand-important.html [ Timeout ] -Bug(none) inspector/elements/styles-2/force-pseudo-state.html [ Timeout ] -Bug(none) inspector/elements/styles-2/inactive-properties.html [ Timeout ] -Bug(none) inspector/elements/styles-2/inject-stylesheet.html [ Timeout ] -Bug(none) inspector/elements/styles-2/media-emulation.html [ Timeout ] -Bug(none) inspector/elements/styles-2/mixed-case-color-aware-properties.html [ Timeout ] -Bug(none) inspector/elements/styles-2/page-reload-update-sidebar.html [ Timeout ] -Bug(none) inspector/elements/styles-2/property-ui-location.html [ Timeout Failure ] -Bug(none) inspector/elements/styles-3/style-autocomplete.html [ Timeout ] -Bug(none) inspector/elements/styles-3/styles-add-blank-property.html [ Timeout ] -Bug(none) inspector/elements/styles-3/styles-add-new-rule-colon.html [ Timeout ] -Bug(none) inspector/elements/styles-3/styles-add-new-rule-to-stylesheet.html [ Timeout ] -Bug(none) inspector/elements/styles-3/styles-add-new-rule.html [ Timeout ] -Bug(none) inspector/elements/styles-3/styles-change-node-while-editing.html [ Timeout ] -Bug(none) inspector/elements/styles-3/styles-commit-editing.html [ Timeout ] -Bug(none) inspector/elements/styles-3/styles-disable-inherited.html [ Timeout ] -Bug(none) inspector/elements/styles-3/styles-disable-then-change.html [ Timeout ] -Bug(none) inspector/elements/styles-3/styles-disable-then-enable-overriden-ua.html [ Timeout ] -Bug(none) inspector/elements/styles-3/styles-variables.html [ Timeout ] -Bug(none) inspector/elements/styles-4/styles-formatting.html [ Timeout ] Bug(none) inspector/elements/styles-4/styles-inline-element-style-changes-should-not-force-style-recalc.html [ Timeout ] -Bug(none) inspector/elements/styles-4/styles-live-locations-leak.html [ Timeout ] -Bug(none) inspector/elements/styles-4/styles-new-API.html [ Timeout ] -Bug(none) inspector/elements/styles-4/styles-properties-overload.html [ Timeout ] -Bug(none) inspector/elements/styles-4/styles-should-not-force-sync-style-recalc.html [ Timeout ] -Bug(none) inspector/elements/styles-4/styles-update-from-js.html [ Timeout ] -Bug(none) inspector/elements/styles-4/styles-update-links-3.html [ Timeout ] -Bug(none) inspector/elements/styles-4/styles-url-linkify.html [ Timeout ] -Bug(none) inspector/elements/styles-4/stylesheet-source-url-comment.html [ Timeout ] -Bug(none) inspector/elements/styles/cancel-upon-invalid-property.html [ Timeout ] -Bug(none) inspector/elements/styles/original-content-provider.html [ Timeout ] -Bug(none) inspector/elements/styles/url-multiple-collapsing.html [ Timeout ] -Bug(none) inspector/file-system-mapping.html [ Timeout ] Bug(none) inspector/file-system-project.html [ Failure ] -Bug(none) inspector/geolocation-emulation-tests.html [ Timeout ] -Bug(none) inspector/import-open-inspector.html [ Timeout ] -Bug(none) inspector/input-event-warning.html [ Timeout ] -Bug(none) inspector/inspected-objects-not-overriden.html [ Timeout ] -Bug(none) inspector/layers/layer-replay-scale.html [ Timeout ] Bug(none) inspector/layers/layers-3d-view-hit-testing.html [ Timeout ] -Bug(none) inspector/modules-load-elements.html [ Timeout ] -Bug(none) inspector/modules-load-initial.html [ Timeout ] -Bug(none) inspector/modules-load-network.html [ Timeout ] -Bug(none) inspector/modules-load-source.html [ Timeout ] -Bug(none) inspector/network/network-cookies-pane.html [ Timeout ] Bug(none) inspector/network/network-json-parser.html [ Timeout ] -Bug(none) inspector/profiler/cpu-profiler-save-load.html [ Timeout ] -Bug(none) inspector/profiler/heap-snapshot-loader.html [ Timeout ] Bug(none) inspector/quick-open/command-menu.html [ Timeout ] -Bug(none) inspector/runtime/runtime-es6-setSymbolPropertyValue.html [ Timeout ] -Bug(none) inspector/sass/test-ast-css-1.html [ Timeout ] -Bug(none) inspector/sass/test-ast-diff-1.html [ Timeout ] -Bug(none) inspector/sass/test-ast-editing-1.html [ Timeout ] Bug(none) inspector/sass/test-ast-scss-3.html [ Timeout ] Bug(none) inspector/sass/test-ast-scss-6.html [ Timeout ] -Bug(none) inspector/sass/test-edit-remove-property.html [ Timeout ] -Bug(none) inspector/sass/test-edit-toggle-property.html [ Timeout ] -Bug(none) inspector/sass/test-mapping-bad.html [ Timeout ] -Bug(none) inspector/sass/test-mapping-good.html [ Timeout ] -Bug(none) inspector/sass/test-mapping-with-cache-busting-url.html [ Timeout ] -Bug(none) inspector/screen-orientation-override.html [ Timeout ] -Bug(none) inspector/sha1.html [ Timeout ] Bug(none) inspector/sources/debugger-breakpoints/breakpoint-manager-listeners-count.html [ Failure ] -Bug(none) inspector/sources/debugger-breakpoints/breakpoints-in-anonymous-script-with-two-targets.html [ Timeout ] Bug(none) inspector/sources/debugger-breakpoints/event-listener-breakpoints-xhr.html [ Timeout ] -Bug(none) inspector/sources/debugger-pause/pause-in-inline-script.html [ Timeout ] -Bug(none) inspector/sources/debugger-step/debugger-step-out-document-write.html [ Timeout ] -Bug(none) inspector/sources/debugger-ui/script-snippet-model.html [ Timeout ] Bug(none) inspector/sources/debugger-ui/watch-expressions-preserve-expansion.html [ Failure ] Bug(none) inspector/sources/debugger/dynamic-script-tag.html [ Failure ] -Bug(none) inspector/tabbed-pane-closeable-persistence.html [ Timeout ] -Bug(none) inspector/tabbed-pane-max-tab-width-calculation.html [ Timeout ] -Bug(none) inspector/tracing-session-id.html [ Timeout ] Bug(none) inspector/tracing/console-timeline.html [ Failure ] Bug(none) inspector/tracing/timeline-network/timeline-network-resource-details.html [ Failure ] Bug(none) inspector/tracing/timeline-network/timeline-network-resource.html [ Failure ] -Bug(none) inspector/user-agent-setting.html [ Timeout ] -Bug(none) inspector/version-controller.html [ Timeout ] Bug(none) installedapp/getinstalledrelatedapps-empty.html [ Timeout ] Bug(none) installedapp/getinstalledrelatedapps.html [ Timeout ] Bug(none) loader/iframe-src-change-onload-crash.html [ Timeout ] @@ -1263,19 +1037,10 @@ Bug(none) paint/invalidation/video-unmute-repaint.html [ Timeout ] Bug(none) payments/payment-request-interface.html [ Failure ] Bug(none) payments/promises-keep-request-alive.html [ Timeout ] -Bug(none) plugins/createScriptableObject-before-start.html [ Failure ] -Bug(none) plugins/focus-change-3-change-blur.html [ Failure ] -Bug(none) plugins/focus-change-4-change-focus-and-blur.html [ Failure ] -Bug(none) plugins/gesture-events-scrolled.html [ Timeout Failure ] -Bug(none) plugins/gesture-events.html [ Timeout ] Bug(none) plugins/iframe-plugin-bgcolor.html [ Timeout ] -Bug(none) plugins/plugin-document-back-forward.html [ Timeout ] -Bug(none) plugins/plugin-initiate-popup-window.html [ Timeout ] Bug(none) presentation/presentation-controller-close-connection.html [ Timeout ] Bug(none) presentation/presentation-controller-connection-closed-by-receiver.html [ Timeout ] Bug(none) presentation/presentation-controller-terminate-connection.html [ Timeout ] -Bug(none) presentation/presentation-navigation-multipleurls.html [ Timeout ] -Bug(none) presentation/presentation-navigation.html [ Timeout ] Bug(none) presentation/presentation-onreceiverconnection.html [ Timeout ] Bug(none) presentation/presentation-receiver-terminate-connection.html [ Timeout ] Bug(none) presentation/presentation-reconnect.html [ Timeout ] @@ -1284,9 +1049,6 @@ Bug(none) presentation/presentationconnectionavailableevent-ctor-mock.html [ Timeout ] Bug(none) printing/subframes-percentage-height.html [ Failure ] Bug(none) scrollbars/listbox-scrollbar-combinations.html [ Failure ] -Bug(none) storage/domstorage/events/basic.html [ Failure Timeout ] -Bug(none) tables/mozilla/core/col_widths_fix_autoFixPer.html [ Timeout ] -Bug(none) tables/mozilla_expected_failures/marvin/backgr_fixed-bg.html [ Failure ] Bug(none) traversal/node-iterator-009.html [ Failure ] Bug(none) traversal/tree-walker-006.html [ Failure ] Bug(none) virtual [ Crash Failure Timeout ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index ce44765..ff6f070 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -541,7 +541,6 @@ crbug.com/635619 virtual/layout_ng/fast/block/float/floats-wrap-inside-inline-002.htm [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/floats-wrap-inside-inline-003.htm [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/floats-wrap-inside-inline-004.htm [ Failure ] -crbug.com/635619 virtual/layout_ng/fast/block/float/floats-wrap-inside-inline-007.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/formatting-context-changes.html [ Failure Crash ] crbug.com/635619 virtual/layout_ng/fast/block/float/independent-align-positioning.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/intruding-painted-twice.html [ Failure ] @@ -1737,6 +1736,34 @@ crbug.com/626703 virtual/threaded/transitions/transition-end-event-multiple-03.html [ Pass Failure ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 [ Android Mac10.9 ] external/wpt/2dcontext/line-styles/2d.line.cap.butt.html [ Crash ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/2dcontext/line-styles/2d.line.cap.open.html [ Crash ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/2dcontext/line-styles/2d.line.cap.square.html [ Crash ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/2dcontext/line-styles/2d.line.cap.valid.html [ Crash ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/2dcontext/line-styles/2d.line.join.bevel.html [ Crash ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/2dcontext/line-styles/2d.line.join.invalid.html [ Crash ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/2dcontext/line-styles/2d.line.miter.rightangle.html [ Crash ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/2dcontext/line-styles/2d.line.miter.valid.html [ Crash ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/2dcontext/line-styles/2d.line.union.html [ Skip ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/2dcontext/line-styles/2d.line.width.invalid.html [ Crash ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/2dcontext/line-styles/2d.line.width.transformed.html [ Crash ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/2dcontext/line-styles/canvas_linestyles_linecap_001.htm [ Timeout ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/2dcontext/line-styles/lineto_a.html [ Timeout ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/WebCryptoAPI/secure_context/crypto-subtle-non-secure-context-not-available.sub.html [ Crash ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/WebCryptoAPI/secure_context/crypto-subtle-secure-context-available.https.sub.html [ Skip ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/apng/animated-png-timeout.html [ Timeout ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/beacon/headers/header-referrer-no-referrer-when-downgrade.https.html [ Crash ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/beacon/headers/header-referrer-no-referrer.html [ Crash ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/beacon/headers/header-referrer-origin-when-cross-origin.html [ Crash ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/beacon/headers/header-referrer-origin.html [ Crash ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/beacon/headers/header-referrer-same-origin.html [ Crash ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/beacon/headers/header-referrer-strict-origin-when-cross-origin.https.html [ Crash ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/beacon/headers/header-referrer-strict-origin.https.html [ Crash ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/beacon/headers/header-referrer-unsafe-url.https.html [ Crash ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/clipboard-apis/async-navigator-clipboard-basics.https.html [ Crash ] +crbug.com/626703 [ Android Mac10.9 ] external/wpt/clipboard-apis/async-write-text-read-text-manual.https.html [ Skip ] +crbug.com/626703 [ Android Mac10.9 ] virtual/outofblink-cors/external/wpt/fetch/api/basic/integrity-worker.html [ Timeout ] +crbug.com/626703 [ Android Mac10.9 ] virtual/service-worker-script-streaming/external/wpt/service-workers/service-worker/claim-affect-other-registration.https.html [ Timeout ] crbug.com/626703 external/wpt/beacon/headers/header-content-type.html [ Pass Timeout ] crbug.com/626703 [ Win ] external/wpt/css/css-ui-3/outline-004.html [ Failure ] crbug.com/626703 [ Win ] external/wpt/css/css-ui-3/text-overflow-001.html [ Pass Failure ] @@ -2869,15 +2896,7 @@ crbug.com/736177 [ Mac10.12 ] fast/css/text-overflow-input.html [ Failure Pass ] crbug.com/736177 [ Mac10.12 ] fast/dom/HTMLMeterElement/meter-optimums.html [ Failure Pass ] crbug.com/736177 [ Mac10.12 ] fast/dynamic/012.html [ Failure Pass ] -crbug.com/736177 [ Mac10.12 ] fast/forms/control-restrict-line-height.html [ Failure Pass ] crbug.com/736177 [ Mac10.12 ] fast/forms/form-element-geometry.html [ Failure Pass ] -crbug.com/736177 [ Mac10.12 ] fast/forms/input-appearance-height.html [ Failure Pass ] -crbug.com/736177 [ Mac10.12 ] fast/forms/placeholder-position.html [ Failure Pass ] -crbug.com/736177 [ Mac10.12 ] fast/forms/search/search-appearance-basic.html [ Failure Pass ] -crbug.com/736177 [ Mac10.12 ] fast/forms/search/search-cancel-button-style-sharing.html [ Failure Pass ] -crbug.com/736177 [ Mac10.12 ] fast/forms/search/search-display-none-cancel-button.html [ Failure Pass ] -crbug.com/736177 [ Mac10.12 ] fast/forms/search/search-rtl.html [ Failure Pass ] -crbug.com/736177 [ Mac10.12 ] fast/forms/search/searchfield-heights.html [ Failure Pass ] crbug.com/736177 [ Mac10.12 ] fast/inline/absolute-positioned-inline-in-centred-block.html [ Failure Pass ] crbug.com/736177 [ Mac10.12 ] fast/inline/left-right-center-inline-alignment-in-ltr-and-rtl-blocks.html [ Failure Pass ] crbug.com/736177 [ Mac10.12 ] fast/lists/ordered-list-with-no-ol-tag.html [ Failure Pass ] @@ -2923,6 +2942,46 @@ crbug.com/736177 [ Mac10.12 ] virtual/off-main-thread-fetch/http/tests/misc/acid2-pixel.html [ Failure Pass ] crbug.com/736177 [ Mac10.12 ] virtual/prefer_compositing_to_lcd_text/scrollbars/custom-scrollbar-with-incomplete-style.html [ Failure Pass ] crbug.com/736177 [ Mac10.12 ] virtual/rootlayerscrolls/scrollbars/custom-scrollbar-with-incomplete-style.html [ Failure Pass ] +# These tests are failing on both Mac-10.12 when using an Intel GPU and Mac-10.11.6 when using no GPU +crbug.com/736177 [ Mac ] fast/forms/control-restrict-line-height.html [ Failure Pass ] +crbug.com/736177 [ Mac ] fast/forms/input-appearance-height.html [ Failure Pass ] +crbug.com/736177 [ Mac ] fast/forms/placeholder-position.html [ Failure Pass ] +crbug.com/736177 [ Mac ] fast/forms/search/search-appearance-basic.html [ Failure Pass ] +crbug.com/736177 [ Mac ] fast/forms/search/search-cancel-button-style-sharing.html [ Failure Pass ] +crbug.com/736177 [ Mac ] fast/forms/search/search-display-none-cancel-button.html [ Failure Pass ] +crbug.com/736177 [ Mac ] fast/forms/search/search-rtl.html [ Failure Pass ] +crbug.com/736177 [ Mac ] fast/forms/search/searchfield-heights.html [ Failure Pass ] +# These tests are failing on Mac-10.12 when using an Intel GPU and Mac Retina +crbug.com/736177 [ Mac10.12 Retina ] compositing/overflow/theme-affects-visual-overflow.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] css1/box_properties/acid_test.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] css2.1/t09-c5526c-display-00-e.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] css3/selectors3/html/css3-modsel-25.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] css3/selectors3/html/css3-modsel-70.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] css3/selectors3/xhtml/css3-modsel-25.xml [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] css3/selectors3/xhtml/css3-modsel-70.xml [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] css3/selectors3/xml/css3-modsel-25.xml [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] css3/selectors3/xml/css3-modsel-70.xml [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] fast/block/basic/011.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] fast/block/margin-collapse/103.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] fast/css/non-standard-checkbox-size.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] fast/forms/001.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] fast/forms/basic-inputs.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] fast/forms/checkbox/checkbox-appearance-basic.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] fast/forms/file/file-input-disabled.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] fast/forms/formmove.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] fast/forms/formmove2.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] fast/forms/indeterminate.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] fast/forms/input-value.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] fast/forms/radio/radio-appearance-basic.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] fast/inline/positionedLifetime.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] fast/parser/bad-xml-slash.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] fast/replaced/replaced-breaking.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] fast/text/textIteratorNilRenderer.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] fast/text/whitespace/normal-after-nowrap-breaking.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] paint/invalidation/forms/checkbox-focus-by-mouse-then-keydown.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] paint/invalidation/forms/radio-focus-by-mouse-then-keydown.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] tables/mozilla/bugs/bug1318.html [ Failure Pass ] +crbug.com/736177 [ Mac10.12 Retina ] tables/mozilla/bugs/bug4527.html [ Failure Pass ] crbug.com/736177 [ Mac ] svg/as-border-image/svg-as-border-image.html [ Failure Pass ] @@ -2945,9 +3004,6 @@ # module script lacks XHTML support crbug.com/717643 external/wpt/html/semantics/scripting-1/the-script-element/module/module-in-xhtml.xhtml [ Failure ] -# Skia rebaseline -skbug.com/6931 [ Linux ] fast/text/sub-pixel/text-scaling-pixel.html [ NeedsManualRebaseline ] - # Geolocation tests crbug.com/745079 external/wpt/geolocation-API/PositionOptions.https.html [ Failure ] @@ -2990,6 +3046,7 @@ # Sheriff failure 2017-08-11 crbug.com/754657 http/tests/media/media-source/mediasource-duration.html [ Pass Failure ] +crbug.com/626703 virtual/outofblink-cors/external/wpt/fetch/api/response/response-cancel-stream.html [ Pass Timeout ] # Ganesh dither changes crbug.com/753462 virtual/gpu/fast/canvas/canvas-text-alignment.html [ NeedsManualRebaseline ] @@ -2997,3 +3054,9 @@ crbug.com/753462 virtual/gpu/fast/canvas/gradient-add-second-start-end-stop.html [ NeedsManualRebaseline ] crbug.com/746904 [ Win ] fast/text/ellipsis-in-relative-inline.html [ Failure Pass ] + +crbug.com/731018 [ Mac ] sensor/accelerometer.html [ Failure Pass Crash ] +crbug.com/731018 [ Mac ] sensor/ambient-light-sensor.html [ Failure Pass Crash ] +crbug.com/731018 [ Mac ] sensor/gyroscope.html [ Failure Pass Crash ] +crbug.com/731018 [ Mac ] sensor/magnetometer.html [ Failure Pass Crash ] +crbug.com/731018 [ Mac ] sensor/orientation-sensor.html [ Failure Pass Crash ]
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json index 91ccd6c..ff22aa17 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -4845,6 +4845,54 @@ {} ] ], + "compat/webkit-linear-gradient-line-bottom.html": [ + [ + "/compat/webkit-linear-gradient-line-bottom.html", + [ + [ + "/compat/green-ref.html", + "==" + ] + ], + {} + ] + ], + "compat/webkit-linear-gradient-line-left.html": [ + [ + "/compat/webkit-linear-gradient-line-left.html", + [ + [ + "/compat/green-ref.html", + "==" + ] + ], + {} + ] + ], + "compat/webkit-linear-gradient-line-right.html": [ + [ + "/compat/webkit-linear-gradient-line-right.html", + [ + [ + "/compat/green-ref.html", + "==" + ] + ], + {} + ] + ], + "compat/webkit-linear-gradient-line-top.html": [ + [ + "/compat/webkit-linear-gradient-line-top.html", + [ + [ + "/compat/green-ref.html", + "==" + ] + ], + {} + ] + ], "compat/webkit-text-fill-color-property-001a.html": [ [ "/compat/webkit-text-fill-color-property-001a.html", @@ -68073,6 +68121,11 @@ {} ] ], + "compat/green-ref.html": [ + [ + {} + ] + ], "compat/webkit-text-fill-color-property-001-ref.html": [ [ {} @@ -79153,6 +79206,11 @@ {} ] ], + "css/css-transforms-2/animation/resources/interpolation-testcommon.js": [ + [ + {} + ] + ], "css/css-transforms-2/css-rotate-2d-3d-001-ref.html": [ [ {} @@ -83713,6 +83771,11 @@ {} ] ], + "css/motion-1/animation/resources/interpolation-testcommon.js": [ + [ + {} + ] + ], "css/motion-1/offset-path-ray-ref.html": [ [ {} @@ -86388,6 +86451,11 @@ {} ] ], + "editing/data/insert-list-items-in-table-cells.js": [ + [ + {} + ] + ], "editing/data/inserthorizontalrule.js": [ [ {} @@ -126320,6 +126388,24 @@ {} ] ], + "css/css-transforms-2/animation/rotate-interpolation.html": [ + [ + "/css/css-transforms-2/animation/rotate-interpolation.html", + {} + ] + ], + "css/css-transforms-2/animation/scale-interpolation.html": [ + [ + "/css/css-transforms-2/animation/scale-interpolation.html", + {} + ] + ], + "css/css-transforms-2/animation/translate-interpolation.html": [ + [ + "/css/css-transforms-2/animation/translate-interpolation.html", + {} + ] + ], "css/css-transforms-2/parsing/rotate-parsing-invalid.html": [ [ "/css/css-transforms-2/parsing/rotate-parsing-invalid.html", @@ -126860,6 +126946,30 @@ {} ] ], + "css/motion-1/animation/offset-anchor-interpolation.html": [ + [ + "/css/motion-1/animation/offset-anchor-interpolation.html", + {} + ] + ], + "css/motion-1/animation/offset-distance-interpolation.html": [ + [ + "/css/motion-1/animation/offset-distance-interpolation.html", + {} + ] + ], + "css/motion-1/animation/offset-position-interpolation.html": [ + [ + "/css/motion-1/animation/offset-position-interpolation.html", + {} + ] + ], + "css/motion-1/animation/offset-rotate-interpolation.html": [ + [ + "/css/motion-1/animation/offset-rotate-interpolation.html", + {} + ] + ], "css/motion-1/parsing/offset-anchor-parsing-invalid.html": [ [ "/css/motion-1/parsing/offset-anchor-parsing-invalid.html", @@ -129878,6 +129988,12 @@ {} ] ], + "editing/run/insert-list-items-in-table-cell.html": [ + [ + "/editing/run/insert-list-items-in-table-cell.html", + {} + ] + ], "editing/run/inserthorizontalrule.html": [ [ "/editing/run/inserthorizontalrule.html", @@ -165638,6 +165754,12 @@ {} ] ], + "wasm/create_multiple_memory.worker.js": [ + [ + "/wasm/create_multiple_memory.worker.html", + {} + ] + ], "wasm/wasm_indexeddb_test.html": [ [ "/wasm/wasm_indexeddb_test.html", @@ -174884,7 +175006,7 @@ "support" ], "./.travis.yml": [ - "250f9bc8512445215c63504d28305b723c4b3385", + "8057d3e8925cb559271139ebbbfc516cad484a6c", "support" ], "./CONTRIBUTING.md": [ @@ -181644,7 +181766,7 @@ "support" ], "WebIDL/current-realm.html": [ - "167c7c1f53ae2bf457f6b3f917f0ef988c585c7c", + "3d9564314c7ce59ce6a29dfa94c35e496e214bf5", "testharness" ], "WebIDL/ecmascript-binding/es-exceptions/DOMException-constants.any.js": [ @@ -181816,7 +181938,7 @@ "support" ], "XMLHttpRequest/access-control-and-redirects.htm": [ - "2b635d3c25e01a971ce2e75efa63ede57194a8b3", + "ff051032814b1242f527970edc58675e3e14fb98", "testharness" ], "XMLHttpRequest/access-control-basic-allow-access-control-origin-header.htm": [ @@ -183272,7 +183394,7 @@ "support" ], "beacon/headers/header-content-type-expected.txt": [ - "369e5f74f98a790f954289e3786974c2941fb682", + "cfce1555852fb39dee45de50c96d2510d7c99267", "support" ], "beacon/headers/header-content-type.html": [ @@ -183595,6 +183717,26 @@ "80579a1e88af8e60c7446f34446b90bd3e9cf8c7", "support" ], + "compat/green-ref.html": [ + "4b23ea52d785a6dd19785bd4278bf700eb5547f8", + "support" + ], + "compat/webkit-linear-gradient-line-bottom.html": [ + "af59a0aa3b8a195ba7ef401b582be9384a23a388", + "reftest" + ], + "compat/webkit-linear-gradient-line-left.html": [ + "f131166051da9a82ede93f076f15832f61f39234", + "reftest" + ], + "compat/webkit-linear-gradient-line-right.html": [ + "2d87c4a09d77f3171fa91bbf8f2f0b1a412b7d94", + "reftest" + ], + "compat/webkit-linear-gradient-line-top.html": [ + "be7fb91dc6459617c20232cd5333e9b3340f3341", + "reftest" + ], "compat/webkit-text-fill-color-currentColor.html": [ "7512b6ce45b5528ee7b9794c32954e954d736f88", "testharness" @@ -186596,7 +186738,7 @@ "reftest" ], "css-fonts/variations/font-parse-numeric-stretch-style-weight.html": [ - "421e402060f1418562819bb6efae85a7a1cc8958", + "b9aa593e5fcba0d7af8f66446d473608a7025f1c", "testharness" ], "css-fonts/variations/resources/variabletest_box.ttf": [ @@ -210843,6 +210985,22 @@ "86257012c615c6580cea602a1ee2f8617dcbb336", "support" ], + "css/css-transforms-2/animation/resources/interpolation-testcommon.js": [ + "e53ebd086f11169bf516f4d2e68449290943ba98", + "support" + ], + "css/css-transforms-2/animation/rotate-interpolation.html": [ + "f5b8b30c9bc0789d59b3451789c24009b93dd21f", + "testharness" + ], + "css/css-transforms-2/animation/scale-interpolation.html": [ + "51271e16c98a7a4e6405c28d149e77eb439e670c", + "testharness" + ], + "css/css-transforms-2/animation/translate-interpolation.html": [ + "9a28f675c790c3dec66f655418051a5a7ba52ec7", + "testharness" + ], "css/css-transforms-2/backface-visibility-hidden-001.html": [ "d12cfa3b31b7f98d0ff5693bfde49247d34cb156", "reftest" @@ -220087,6 +220245,26 @@ "13d88ccf8c2f03db7e1db7f6fc704ba46a06e0e1", "support" ], + "css/motion-1/animation/offset-anchor-interpolation.html": [ + "30eb3ea68aa502d93125d4e54ff15c0a96458cfa", + "testharness" + ], + "css/motion-1/animation/offset-distance-interpolation.html": [ + "f242f67f0d1a1c25a871d4ae949d42f9d1df0027", + "testharness" + ], + "css/motion-1/animation/offset-position-interpolation.html": [ + "6c21c93c0715af758033d7b582f072988b379b15", + "testharness" + ], + "css/motion-1/animation/offset-rotate-interpolation.html": [ + "37c091bd5a59d4853bc9f5c82e157ac3d4f29643", + "testharness" + ], + "css/motion-1/animation/resources/interpolation-testcommon.js": [ + "51a3f4808392b7bcce4f2569256c540a3be817dc", + "support" + ], "css/motion-1/offset-path-ray-ref.html": [ "dfea2bd9cadf9d1b83e95bc2dbffef3539937ff1", "support" @@ -225699,6 +225877,10 @@ "821cc4fefcfce96832c1a4547698801b554ae426", "support" ], + "editing/data/insert-list-items-in-table-cells.js": [ + "f6e8969d30a53e42c6adace5bd9598862b92c611", + "support" + ], "editing/data/inserthorizontalrule.js": [ "118414ee839b94b9a747e0dfd2068d728c171db7", "support" @@ -225951,6 +226133,10 @@ "1bed1283ad3b220b2949c0720cba60105c888ec2", "testharness" ], + "editing/run/insert-list-items-in-table-cell.html": [ + "7bb730a43273a9220ef491511acbdd5c91fbc9b7", + "testharness" + ], "editing/run/inserthorizontalrule-expected.txt": [ "6535eed7f208b2eca892bdec4e712c240db6a9f5", "support" @@ -229516,7 +229702,7 @@ "testharness" ], "hr-time/timeOrigin.html": [ - "3bb4eb8162169e582fea93a7cb1f6257325a0606", + "f07da265bb9d1036589ff116b14ea1370abc4194", "testharness" ], "hr-time/timing-attack.html": [ @@ -229708,7 +229894,7 @@ "testharness" ], "html/browsers/browsing-the-web/history-traversal/PopStateEvent.html": [ - "2a7ed0827fc61af7b3bdd238577887aff1902ea7", + "5a9c575a86adbbbca30734992b4d80c22f3973a1", "testharness" ], "html/browsers/browsing-the-web/history-traversal/browsing_context_name-0.html": [ @@ -245800,7 +245986,7 @@ "testharness" ], "intersection-observer/timestamp.html": [ - "b26e1b4b295722e8def9a2d6870465fe4140873c", + "b9bf8d472d7751ec4a1ebee925d12668bedeee7a", "testharness" ], "intersection-observer/unclipped-root.html": [ @@ -264300,7 +264486,7 @@ "support" ], "server-timing/test_server_timing.html": [ - "3f582e55c8d96a4fb1589ad9bd6e7ca26b75b7a2", + "bd80353850b822d6ee4a6b32ffae0e6e2120c61f", "testharness" ], "server-timing/test_server_timing.html.sub.headers": [ @@ -268847,6 +269033,10 @@ "652193b876206d7a0f361f145469a604d03e3784", "support" ], + "wasm/create_multiple_memory.worker.js": [ + "893d408fc56d030416a3c89ae3680dc028ecf1d7", + "testharness" + ], "wasm/incrementer.wasm": [ "acdf9d22c042ea3b2637c14b1576b4c8ffb4e97a", "support" @@ -271956,7 +272146,7 @@ "support" ], "webusb/idlharness.https.html": [ - "0da5e66dd0b0e82d25082733465c22c54a96d1de", + "135ae431cdac90d34b85fe1ea355abaf9a9fb732", "testharness" ], "webusb/resources/fake-devices.js": [ @@ -275076,7 +275266,7 @@ "testharness" ], "workers/Worker_dispatchEvent_ErrorEvent.htm": [ - "a1100df5a79ed7b484a8d5c5746bd646a165242b", + "a27efcba6fcdbb34bb07ac8553a6bbfa04761008", "testharness" ], "workers/Worker_script_mimetype.htm": [ @@ -275348,7 +275538,7 @@ "testharness" ], "workers/data-url.html": [ - "50abaf936cfb58ba14e6870c9b7f239f5d54f59c", + "8f854b63f97beae3d814478946ad86836a5cea0a", "testharness" ], "workers/interfaces.worker-expected.txt": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/.travis.yml b/third_party/WebKit/LayoutTests/external/wpt/.travis.yml index 2744822..f4469e0 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/.travis.yml +++ b/third_party/WebKit/LayoutTests/external/wpt/.travis.yml
@@ -83,11 +83,8 @@ - env: JOB=build_css SCRIPT=css/build-css-testsuites.sh - env: - secure: "YTSXPwI0DyCA1GhYrLT9KMEV6b7QQKuEeaQgeFDP38OTzJ1+cIj3CC4SRNqbnJ/6SJwPGcdqSxLuV8m4e5HFFnyCcQnJe6h8EMsTehZ7W3j/fP9UYrJqYqvGpe3Vj3xblO5pwBYmq7sg3jAmmuCgAgOW6VGf7cRMucrsmFeo7VM=" - - JOB=stability SCRIPT=tools/ci/ci_stability.sh PRODUCT=chrome:unstable - - env: - - secure: "YTSXPwI0DyCA1GhYrLT9KMEV6b7QQKuEeaQgeFDP38OTzJ1+cIj3CC4SRNqbnJ/6SJwPGcdqSxLuV8m4e5HFFnyCcQnJe6h8EMsTehZ7W3j/fP9UYrJqYqvGpe3Vj3xblO5pwBYmq7sg3jAmmuCgAgOW6VGf7cRMucrsmFeo7VM=" - JOB=stability SCRIPT=tools/ci/ci_stability.sh PRODUCT=sauce:MicrosoftEdge:14.14393 PLATFORM='Windows 10' - env: + - env: - secure: "YTSXPwI0DyCA1GhYrLT9KMEV6b7QQKuEeaQgeFDP38OTzJ1+cIj3CC4SRNqbnJ/6SJwPGcdqSxLuV8m4e5HFFnyCcQnJe6h8EMsTehZ7W3j/fP9UYrJqYqvGpe3Vj3xblO5pwBYmq7sg3jAmmuCgAgOW6VGf7cRMucrsmFeo7VM=" - JOB=stability SCRIPT=tools/ci/ci_stability.sh PRODUCT=sauce:safari:10.0 PLATFORM='macOS 10.12' script:
diff --git a/third_party/WebKit/LayoutTests/external/wpt/WebIDL/current-realm.html b/third_party/WebKit/LayoutTests/external/wpt/WebIDL/current-realm.html index fd24709b..e015ec5 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/WebIDL/current-realm.html +++ b/third_party/WebKit/LayoutTests/external/wpt/WebIDL/current-realm.html
@@ -110,8 +110,13 @@ test(function() { var c = self[0].document.createElement("canvas"), obj = c.getContext(val) - assert_global(obj) + // WebGL might not be enabled in this environment + if (!obj && val === "webgl") { + return; + } + + assert_global(obj) obj = HTMLCanvasElement.prototype.getContext.call(c, val) assert_global(obj) }, "getContext " + val)
diff --git a/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/access-control-and-redirects.htm b/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/access-control-and-redirects.htm index 10c5e2f5..dcdf400 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/access-control-and-redirects.htm +++ b/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/access-control-and-redirects.htm
@@ -16,7 +16,6 @@ assert_equals(xhr.responseText, "PASS: Cross-domain access allowed."); test.done(); } - function runAsync(test, url) { const xhr = new XMLHttpRequest(); @@ -28,7 +27,6 @@ xhr.send(); test.done(); } - test(t => { runSync(t, "resources/redirect-cors.py?location=" + get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/access-control-basic-allow.py") @@ -37,7 +35,6 @@ runAsync(t, "resources/redirect-cors.py?location=" + get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/access-control-basic-allow.py") }, "Local async redirect to remote origin"); - test(t => { runSync(t, get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/redirect-cors.py?location=" + get_host_info().HTTP_ORIGIN + @@ -48,7 +45,6 @@ "/XMLHttpRequest/resources/redirect-cors.py?location=" + get_host_info().HTTP_ORIGIN + "/XMLHttpRequest/resources/access-control-basic-allow.py&allow_origin=true") }, "Remote async redirect to local origin"); - test(t => { runSync(t, get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/redirect-cors.py?location=" + get_host_info().HTTP_REMOTE_ORIGIN +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/compat/green-ref.html b/third_party/WebKit/LayoutTests/external/wpt/compat/green-ref.html new file mode 100644 index 0000000..2671ff6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/compat/green-ref.html
@@ -0,0 +1,6 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>A green 100x100 block</title> +<link rel="author" title="Xidorn Quan" href="me@upsuper.ort"> +<link rel="author" title="Mozilla" href="https://www.mozilla.org"> +<div style="width: 100px; height: 100px; background: green;"></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/compat/webkit-linear-gradient-line-bottom.html b/third_party/WebKit/LayoutTests/external/wpt/compat/webkit-linear-gradient-line-bottom.html new file mode 100644 index 0000000..21e1c894 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/compat/webkit-linear-gradient-line-bottom.html
@@ -0,0 +1,22 @@ +<!doctype html> +<title>-webkit-linear-gradient(bottom)</title> +<link rel="author" title="Xidorn Quan" href="me@upsuper.org"> +<link rel="author" title="Mozilla" href="https://www.mozilla.org"> +<link rel="help" href="https://compat.spec.whatwg.org/#css-gradients-webkit-linear-gradient"> +<meta name="assert" content="'bottom' in -webkit-linear-gradient is equivalent to 'to top' in modern syntax"> +<link rel="match" href="green-ref.html"> +<style> + #outer { + width: 100px; + height: 100px; + overflow: hidden; + } + #inner { + width: 100px; + height: 200px; + background-image: -webkit-linear-gradient(bottom, red 50%, green 50%); + } +</style> +<div id="outer"> + <div id="inner"></div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/compat/webkit-linear-gradient-line-left.html b/third_party/WebKit/LayoutTests/external/wpt/compat/webkit-linear-gradient-line-left.html new file mode 100644 index 0000000..b0e13c1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/compat/webkit-linear-gradient-line-left.html
@@ -0,0 +1,22 @@ +<!doctype html> +<title>-webkit-linear-gradient(left)</title> +<link rel="author" title="Xidorn Quan" href="me@upsuper.org"> +<link rel="author" title="Mozilla" href="https://www.mozilla.org"> +<link rel="help" href="https://compat.spec.whatwg.org/#css-gradients-webkit-linear-gradient"> +<meta name="assert" content="'left' in -webkit-linear-gradient is equivalent to 'to right' in modern syntax"> +<link rel="match" href="green-ref.html"> +<style> + #outer { + width: 100px; + height: 100px; + overflow: hidden; + } + #inner { + width: 200px; + height: 100px; + background-image: -webkit-linear-gradient(left, green 50%, red 50%); + } +</style> +<div id="outer"> + <div id="inner"></div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/compat/webkit-linear-gradient-line-right.html b/third_party/WebKit/LayoutTests/external/wpt/compat/webkit-linear-gradient-line-right.html new file mode 100644 index 0000000..0f1a4b9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/compat/webkit-linear-gradient-line-right.html
@@ -0,0 +1,22 @@ +<!doctype html> +<title>-webkit-linear-gradient(right)</title> +<link rel="author" title="Xidorn Quan" href="me@upsuper.org"> +<link rel="author" title="Mozilla" href="https://www.mozilla.org"> +<link rel="help" href="https://compat.spec.whatwg.org/#css-gradients-webkit-linear-gradient"> +<meta name="assert" content="'right' in -webkit-linear-gradient is equivalent to 'to left' in modern syntax"> +<link rel="match" href="green-ref.html"> +<style> + #outer { + width: 100px; + height: 100px; + overflow: hidden; + } + #inner { + width: 200px; + height: 100px; + background-image: -webkit-linear-gradient(right, red 50%, green 50%); + } +</style> +<div id="outer"> + <div id="inner"></div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/compat/webkit-linear-gradient-line-top.html b/third_party/WebKit/LayoutTests/external/wpt/compat/webkit-linear-gradient-line-top.html new file mode 100644 index 0000000..579d882 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/compat/webkit-linear-gradient-line-top.html
@@ -0,0 +1,22 @@ +<!doctype html> +<title>-webkit-linear-gradient(top)</title> +<link rel="author" title="Xidorn Quan" href="me@upsuper.org"> +<link rel="author" title="Mozilla" href="https://www.mozilla.org"> +<link rel="help" href="https://compat.spec.whatwg.org/#css-gradients-webkit-linear-gradient"> +<meta name="assert" content="'top' in -webkit-linear-gradient is equivalent to 'to bottom' in modern syntax"> +<link rel="match" href="green-ref.html"> +<style> + #outer { + width: 100px; + height: 100px; + overflow: hidden; + } + #inner { + width: 100px; + height: 200px; + background-image: -webkit-linear-gradient(top, green 50%, red 50%); + } +</style> +<div id="outer"> + <div id="inner"></div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css-fonts/variations/font-parse-numeric-stretch-style-weight.html b/third_party/WebKit/LayoutTests/external/wpt/css-fonts/variations/font-parse-numeric-stretch-style-weight.html index 53cef20..5152424 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css-fonts/variations/font-parse-numeric-stretch-style-weight.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css-fonts/variations/font-parse-numeric-stretch-style-weight.html
@@ -21,12 +21,15 @@ 'calc(100 + 300)', 'calc(0.2 + 205.5)', ], - 'stretch': ['51%', '199%', 'calc(10% + 20%)'] + 'stretch': ['51%', '199%', 'calc(10% + 20%)'], + 'style' : [ 'normal', 'italic', 'oblique', 'oblique 50deg', 'oblique -90deg', 'oblique 90deg', + 'oblique calc(30deg + 20deg)' ] }; var styleInvalidTests = { 'weight': ['100 400', 'calc(0 - 100)', 'calc(200 + 801)'], - 'stretch': ['100% 110%', '0%', '100% 150%', 'calc(1 + 10%)'] + 'stretch': ['100% 110%', '0%', '100% 150%', 'calc(1 + 10%)'], + 'style' : [ 'normal 10deg', 'italic 10deg', 'oblique -91deg', 'oblique 91deg', 'oblique calc(90deg + 20deg)'] }; function testParseStyle() { @@ -70,6 +73,13 @@ ['ultra-condensed', 'ultra-condensed'], ['ultra-expanded', 'ultra-expanded'], ], + 'style' : [ + [ "normal", "normal" ], + [ "italic", "italic" ], + [ "oblique", "oblique" ], + [ "oblique 10deg", "oblique 10deg" ], + [ "oblique 10deg 20deg", "oblique 10deg 20deg" ] + ] }; var faceInvalidTests = { @@ -87,9 +97,11 @@ 'a b c', ], 'stretch': [ - '0%', '60% 70% 80%', 'a%', 'a b c', '0.1', '-60% 80%', 'ultra-expannnned', - '50% 0' + '-0.5%', '-1%', '0%', 'calc(0% - 10%)', '60% 70% 80%', 'a%', 'a b c', '0.1', + '-60% 80%', 'ultra-expannnned', '50% 0' ], + 'style' : [ 'oblique 100deg', 'oblique italic', 'oblique -91deg', 'oblique 0', + 'oblique 10', 'iiitalic', '90deg', '11', 'italic 90deg' ] }; function testParseFace() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/motion-1/animation/offset-anchor-interpolation.html b/third_party/WebKit/LayoutTests/external/wpt/css/motion-1/animation/offset-anchor-interpolation.html new file mode 100644 index 0000000..414a0bd0d --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/motion-1/animation/offset-anchor-interpolation.html
@@ -0,0 +1,72 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>offset-anchor interpolation</title> + <link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org"> + <link rel="help" href="https://drafts.fxtf.org/motion-1/#offset-anchor-property"> + <meta name="assert" content="offset-anchor supports <position> animation."> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="resources/interpolation-testcommon.js"></script> + <style> + body { + width: 500px; + height: 500px; + transform: rotate(0deg); + } + div { + width: 10px; + height: 10px; + } + </style> + </head> + <body> + <script> + test_interpolation({ + property: 'offset-anchor', + from: '220px 240px', + to: '300px 400px', + }, [ + {at: -1, expect: '140px 80px'}, + {at: 0, expect: '220px 240px'}, + {at: 0.125, expect: '230px 260px'}, + {at: 0.875, expect: '290px 380px'}, + {at: 1, expect: '300px 400px'}, + {at: 2, expect: '380px 560px'} + ]); + + test_interpolation({ + property: 'offset-anchor', + from: 'left 480px top 400px', + to: 'right -140% bottom -60%', + }, [ + {at: -1, expect: 'calc(960px - 240%) calc(800px - 160%)'}, + {at: 0, expect: 'left 480px top 400px'}, + {at: 0.125, expect: 'calc(420px + 30%) calc(350px + 20%)'}, + {at: 0.875, expect: 'calc(210% + 60px) calc(140% + 50px)'}, + {at: 1, expect: 'right -140% bottom -60%'}, + {at: 2, expect: 'calc(480% - 480px) calc(320% - 400px)'} + ]); + + test_interpolation({ + property: 'offset-anchor', + from: 'left top', + to: 'left 8px bottom 20%', + }, [ + {at: -1, expect: '-8px -80%'}, + {at: 0, expect: 'left top'}, + {at: 0.125, expect: '1px 10%'}, + {at: 0.875, expect: '7px 70%'}, + {at: 1, expect: 'left 8px bottom 20%'}, + {at: 2, expect: '16px 160%'} + ]); + + test_no_interpolation({ + property: 'offset-anchor', + from: 'right 10px top 20%', + to: 'auto' + }); + </script> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/motion-1/animation/offset-distance-interpolation.html b/third_party/WebKit/LayoutTests/external/wpt/css/motion-1/animation/offset-distance-interpolation.html new file mode 100644 index 0000000..a56878a0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/motion-1/animation/offset-distance-interpolation.html
@@ -0,0 +1,55 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>offset-distance interpolation</title> + <link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org"> + <link rel="help" href="https://drafts.fxtf.org/motion-1/#offset-distance-property"> + <meta name="assert" content="offset-distance supports animation."> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="resources/interpolation-testcommon.js"></script> + </head> + <body> + <script> + test_interpolation({ + property: 'offset-distance', + from: '-30px', + to: '50px', + }, [ + {at: -1, expect: '-110px'}, + {at: 0, expect: '-30px'}, + {at: 0.125, expect: '-20px'}, + {at: 0.875, expect: '40px'}, + {at: 1, expect: '50px'}, + {at: 2, expect: '130px'} + ]); + + test_interpolation({ + property: 'offset-distance', + from: '20%', + to: '100%', + }, [ + {at: -1, expect: '-60%'}, + {at: 0, expect: '20%'}, + {at: 0.125, expect: '30%'}, + {at: 0.875, expect: '90%'}, + {at: 1, expect: '100%'}, + {at: 2, expect: '180%'} + ]); + + test_interpolation({ + property: 'offset-distance', + from: 'calc(20% - 30px)', + to: 'calc(50px + 100%)', + }, [ + {at: -1, expect: 'calc(-110px + -60%)'}, + {at: 0, expect: 'calc(20% - 30px)'}, + {at: 0.125, expect: 'calc(-20px + 30%)'}, + {at: 0.875, expect: 'calc(40px + 90%)'}, + {at: 1, expect: 'calc(50px + 100%)'}, + {at: 2, expect: 'calc(130px + 180%)'} + ]); + </script> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/motion-1/animation/offset-position-interpolation.html b/third_party/WebKit/LayoutTests/external/wpt/css/motion-1/animation/offset-position-interpolation.html new file mode 100644 index 0000000..c31034d --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/motion-1/animation/offset-position-interpolation.html
@@ -0,0 +1,72 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>offset-position interpolation</title> + <link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org"> + <link rel="help" href="https://drafts.fxtf.org/motion-1/#offset-position-property"> + <meta name="assert" content="offset-position supports <position> animation."> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="resources/interpolation-testcommon.js"></script> + <style> + body { + width: 500px; + height: 500px; + transform: rotate(0deg); + } + div { + width: 10px; + height: 10px; + } + </style> + </head> + <body> + <script> + test_interpolation({ + property: 'offset-position', + from: '220px 240px', + to: '300px 400px', + }, [ + {at: -1, expect: '140px 80px'}, + {at: 0, expect: '220px 240px'}, + {at: 0.125, expect: '230px 260px'}, + {at: 0.875, expect: '290px 380px'}, + {at: 1, expect: '300px 400px'}, + {at: 2, expect: '380px 560px'} + ]); + + test_interpolation({ + property: 'offset-position', + from: 'left 480px top 400px', + to: 'right -140% bottom -60%', + }, [ + {at: -1, expect: 'calc(960px - 240%) calc(800px - 160%)'}, + {at: 0, expect: 'left 480px top 400px'}, + {at: 0.125, expect: 'calc(420px + 30%) calc(350px + 20%)'}, + {at: 0.875, expect: 'calc(210% + 60px) calc(140% + 50px)'}, + {at: 1, expect: 'right -140% bottom -60%'}, + {at: 2, expect: 'calc(480% - 480px) calc(320% - 400px)'} + ]); + + test_interpolation({ + property: 'offset-position', + from: 'left top', + to: 'left 8px bottom 20%', + }, [ + {at: -1, expect: '-8px -80%'}, + {at: 0, expect: 'left top'}, + {at: 0.125, expect: '1px 10%'}, + {at: 0.875, expect: '7px 70%'}, + {at: 1, expect: 'left 8px bottom 20%'}, + {at: 2, expect: '16px 160%'} + ]); + + test_no_interpolation({ + property: 'offset-position', + from: 'right 10px top 20%', + to: 'auto' + }); + </script> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/motion-1/animation/offset-rotate-interpolation.html b/third_party/WebKit/LayoutTests/external/wpt/css/motion-1/animation/offset-rotate-interpolation.html new file mode 100644 index 0000000..a73c1a4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/motion-1/animation/offset-rotate-interpolation.html
@@ -0,0 +1,55 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>offset-rotate interpolation</title> + <link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org"> + <link rel="help" href="https://drafts.fxtf.org/motion-1/#offset-rotate-property"> + <meta name="assert" content="offset-rotate supports animation."> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="resources/interpolation-testcommon.js"></script> + </head> + <body> + <script> + test_interpolation({ + property: 'offset-rotate', + from: '100deg', + to: '180deg', + }, [ + {at: -1, expect: '20deg'}, + {at: 0, expect: '100deg'}, + {at: 0.125, expect: '110deg'}, + {at: 0.875, expect: '170deg'}, + {at: 1, expect: '180deg'}, + {at: 2, expect: '260deg'} + ]); + + test_interpolation({ + property: 'offset-rotate', + from: 'auto 100deg', + to: 'reverse', + }, [ + {at: -1, expect: 'auto 20deg'}, + {at: 0, expect: 'auto 100deg'}, + {at: 0.125, expect: 'auto 110deg'}, + {at: 0.875, expect: 'auto 170deg'}, + {at: 1, expect: 'reverse'}, + {at: 2, expect: 'auto 260deg'} + ]); + + // No interpolation between auto/reverse and angle. + test_no_interpolation({ + property: 'offset-rotate', + from: 'reverse 90deg', + to: '360deg', + }); + + test_no_interpolation({ + property: 'offset-rotate', + from: '6rad', + to: 'auto', + }); + </script> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/motion-1/animation/resources/interpolation-testcommon.js b/third_party/WebKit/LayoutTests/external/wpt/css/motion-1/animation/resources/interpolation-testcommon.js new file mode 100644 index 0000000..be86c43 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/motion-1/animation/resources/interpolation-testcommon.js
@@ -0,0 +1,65 @@ +'use strict'; +function test_interpolation(settings, expectations) { + // Returns a timing function that at 0.5 evaluates to progress. + function timingFunction(progress) { + if (progress === 0) + return 'steps(1, end)'; + if (progress === 1) + return 'steps(1, start)'; + var y = (8 * progress - 1) / 6; + return 'cubic-bezier(0, ' + y + ', 1, ' + y + ')'; + } + + test(function(){ + assert_true(CSS.supports(settings.property, settings.from), 'Value "' + settings.from + '" is supported by ' + settings.property); + assert_true(CSS.supports(settings.property, settings.to), 'Value "' + settings.to + '" is supported by ' + settings.property); + }, '"' + settings.from + '" and "' + settings.to + '" are valid ' + settings.property + ' values'); + + for (var i = 0; i < expectations.length; ++i) { + var progress = expectations[i].at; + var expectation = expectations[i].expect; + var animationId = 'anim' + i; + var targetId = 'target' + i; + var referenceId = 'reference' + i; + + test(function(){ + assert_true(CSS.supports(settings.property, expectation), 'Value "' + expectation + '" is supported by ' + settings.property); + + var stylesheet = document.createElement('style'); + stylesheet.textContent = + '#' + targetId + ' {\n' + + ' animation: 2s ' + timingFunction(progress) + ' -1s paused ' + animationId + ';\n' + + '}\n' + + '@keyframes ' + animationId + ' {\n' + + ' 0% { ' + settings.property + ': ' + settings.from + '; }\n' + + ' 100% { ' + settings.property + ': ' + settings.to + '; }\n' + + '}\n' + + '#' + referenceId + ' {\n' + + ' ' + settings.property + ': ' + expectation + ';\n' + + '}\n'; + document.head.appendChild(stylesheet); + + var target = document.createElement('div'); + target.id = targetId; + document.body.appendChild(target); + + var reference = document.createElement('div'); + reference.id = referenceId; + document.body.appendChild(reference); + reference.style = ''; + + assert_equals(getComputedStyle(target)[settings.property], getComputedStyle(reference)[settings.property]); + }, 'Animation between "' + settings.from + '" and "' + settings.to + '" at progress ' + progress); + } +} + +function test_no_interpolation(settings) { + var expectatFrom = [-1, 0, 0.125].map(function (progress) { + return {at: progress, expect: settings.from}; + }); + var expectatTo = [0.875, 1, 2].map(function (progress) { + return {at: progress, expect: settings.to}; + }); + + test_interpolation(settings, expectatFrom.concat(expectatTo)); +}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/history-traversal/PopStateEvent.html b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/history-traversal/PopStateEvent.html index ace09e5..85205c1 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/history-traversal/PopStateEvent.html +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/history-traversal/PopStateEvent.html
@@ -6,12 +6,6 @@ <div id="log"></div> <script> test(function () { - var e = document.createEvent('PopStateEvent'); - var eProto = Object.getPrototypeOf(e); - assert_equals(eProto, PopStateEvent.prototype); -}, 'document.createEvent'); - -test(function () { assert_false('initPopStateEvent' in PopStateEvent.prototype, 'There should be no PopStateEvent#initPopStateEvent'); }, 'initPopStateEvent');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/intersection-observer/timestamp.html b/third_party/WebKit/LayoutTests/external/wpt/intersection-observer/timestamp.html index cffd915..90032560 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/intersection-observer/timestamp.html +++ b/third_party/WebKit/LayoutTests/external/wpt/intersection-observer/timestamp.html
@@ -87,7 +87,13 @@ // Test results are only significant if there's a gap between // top window time and iframe window time. assert_greater_than(topWindowTimeBeforeNotification, iframeWindowTimeAfterNotification, - "Time ranges for top and iframe windows are disjoint."); + "Time ranges for top and iframe windows are disjoint. Times: " + + [topWindowTimeOnTestStart, topWindowTimeBeforeCreatingIframe, + topWindowTimeBeforeNotification, topWindowTimeAfterNotification, + iframeWindowTimeBeforeNotification, iframeWindowTimeAfterNotification, + topWindowEntries[1].time - topWindowTimeBeforeNotification, + iframeWindowEntries[1].time - iframeWindowTimeBeforeNotification + ]); assert_equals(topWindowEntries.length, 2, "Top window observer has two notifications."); assert_between_inclusive(
diff --git a/third_party/WebKit/LayoutTests/external/wpt/server-timing/test_server_timing.html b/third_party/WebKit/LayoutTests/external/wpt/server-timing/test_server_timing.html index 43164d69..6a6c8977 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/server-timing/test_server_timing.html +++ b/third_party/WebKit/LayoutTests/external/wpt/server-timing/test_server_timing.html
@@ -11,21 +11,21 @@ window.addEventListener('load', function() { // there should be exactly two server-timing entries, 1 for document, 1 for img#one test_entries(performance.getEntriesByType('navigation')[0].serverTiming, [{ - value: 1.2, - metric: 'metric1', + duration: 1.2, + name: 'metric1', description: 'document', }]) test_entries(performance.getEntriesByName(document.querySelector('img#one').src)[0].serverTiming, [{ - value: 3.4, - metric: 'metric2', + duration: 3.4, + name: 'metric2', description: 'blue.png', }]) new PerformanceObserver(function(entryList, observer) { // there should be exactly one server-timing entry, 1 for img#two test_entries(entryList.getEntriesByName(document.querySelector('img#two').src)[0].serverTiming, [{ - value: 5.6, - metric: 'metric3', + duration: 5.6, + name: 'metric3', description: 'green.png', }]) observer.disconnect()
diff --git a/third_party/WebKit/LayoutTests/external/wpt/workers/Worker_dispatchEvent_ErrorEvent.htm b/third_party/WebKit/LayoutTests/external/wpt/workers/Worker_dispatchEvent_ErrorEvent.htm index aea7e02..11ade605 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/workers/Worker_dispatchEvent_ErrorEvent.htm +++ b/third_party/WebKit/LayoutTests/external/wpt/workers/Worker_dispatchEvent_ErrorEvent.htm
@@ -25,12 +25,6 @@ }); test(function() { - var e = document.createEvent("ErrorEvent"); - var eProto = Object.getPrototypeOf(e); - assert_equals(eProto, ErrorEvent.prototype); -}, "document.createEvent('ErrorEvent')"); - -test(function() { var e = new ErrorEvent("error"); assert_false("initErrorEvent" in e, "should not be supported"); }, "initErrorEvent");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/workers/data-url.html b/third_party/WebKit/LayoutTests/external/wpt/workers/data-url.html index 3a4eb6c..8743490f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/workers/data-url.html +++ b/third_party/WebKit/LayoutTests/external/wpt/workers/data-url.html
@@ -25,7 +25,8 @@ w.onmessage = t.step_func_done(function(e) { assert_unreached('Should not receive any message back.'); }); - w.onerror = t.step_func_done(function() { + w.onerror = t.step_func_done(function(e) { + assert_true(true, 'Should throw ' + e.message); }); }, test_desc); } @@ -50,8 +51,9 @@ assert_worker_sends_pass('cross-origin worker', '', 'fetch("/").then(() => self.postMessage("FAIL"), () => self.postMessage("PASS"))'); // 'data:' workers have opaque origin -assert_worker_sends_pass('worker has opaque origin', 'application/javascript', 'if (self.location.origin == "null") postMessage("PASS"); else postMessage("FAIL");'); +assert_worker_sends_pass('worker has opaque origin', 'application/javascript', 'if (self.location.origin == "null") {postMessage("PASS");} else {postMessage("FAIL");}'); +setup({allow_uncaught_exception:true}); // invalid javascript will trigger an ErrorEvent assert_worker_construction_fails('invalid javascript produces error', 'application/javascript', '}x=3');
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png b/third_party/WebKit/LayoutTests/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png index ade4312..f46a177a 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png +++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Range/scale-page-bounding-client-rect.html b/third_party/WebKit/LayoutTests/fast/dom/Range/scale-page-bounding-client-rect.html index 4150018..f2e03d2c 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/Range/scale-page-bounding-client-rect.html +++ b/third_party/WebKit/LayoutTests/fast/dom/Range/scale-page-bounding-client-rect.html
@@ -8,16 +8,17 @@ testRunner.dumpAsText(); var range = document.createRange(); - range.selectNodeContents(document.getElementById('div')); + range.selectNode(document.getElementById('div')); var rect = range.getBoundingClientRect(); window.internals.setPageScaleFactor(2); var scaledRange = document.createRange(); - scaledRange.selectNodeContents(document.getElementById('div')); + scaledRange.selectNode(document.getElementById('div')); var scaledRect = scaledRange.getBoundingClientRect(); var result = document.getElementById("result"); - if (rect.left == scaledRect.left && + if (rect.width && rect.height && + rect.left == scaledRect.left && rect.top == scaledRect.top && rect.right == scaledRect.right && rect.bottom == scaledRect.bottom)
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Range/scale-page-client-rects.html b/third_party/WebKit/LayoutTests/fast/dom/Range/scale-page-client-rects.html index 65529dd..487c0937 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/Range/scale-page-client-rects.html +++ b/third_party/WebKit/LayoutTests/fast/dom/Range/scale-page-client-rects.html
@@ -8,18 +8,19 @@ testRunner.dumpAsText(); var range = document.createRange(); - range.selectNodeContents(document.getElementById('div')); + range.selectNode(document.getElementById('div')); var rectList = range.getClientRects(); var rect = rectList[0]; window.internals.setPageScaleFactor(2); var scaledRange = document.createRange(); - scaledRange.selectNodeContents(document.getElementById('div')); + scaledRange.selectNode(document.getElementById('div')); var scaledRectList = scaledRange.getClientRects(); var scaledRect = scaledRectList[0]; var result = document.getElementById("result"); - if (rect.left == scaledRect.left && + if (rect.width && rect.height && + rect.left == scaledRect.left && rect.top == scaledRect.top && rect.right == scaledRect.right && rect.bottom == scaledRect.bottom)
diff --git a/third_party/WebKit/LayoutTests/fast/forms/password-length-emoji-expected.html b/third_party/WebKit/LayoutTests/fast/forms/password-length-emoji-expected.html deleted file mode 100644 index 4f451de..0000000 --- a/third_party/WebKit/LayoutTests/fast/forms/password-length-emoji-expected.html +++ /dev/null
@@ -1,11 +0,0 @@ -<!doctype html> -<html> -<body> -<p> This tests that the number of bullet points shown in a password -field reflects the number of "grapheme clusters" even if some of the grapheme -clusters are characters outside the Basic Multilingual Plane, or combining -characters. For <a href="https://crbug.com/486880">crbug.com/486880</a>.</p> -<input type="password" value="x"></input> <!-- one ascii character --> -<br><input type="password" value="cafe"></input> <!-- without combining character --> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/password-length-emoji.html b/third_party/WebKit/LayoutTests/fast/forms/password-length-emoji.html deleted file mode 100644 index 22258396..0000000 --- a/third_party/WebKit/LayoutTests/fast/forms/password-length-emoji.html +++ /dev/null
@@ -1,11 +0,0 @@ -<!doctype html> -<html> -<body> -<p> This tests that the number of bullet points shown in a password -field reflects the number of "grapheme clusters" even if some of the grapheme -clusters are characters outside the Basic Multilingual Plane, or combining -characters. For <a href="https://crbug.com/486880">crbug.com/486880</a>.</p> -<input type="password" value="😃"></input> <!-- Smiley face (U+1F603) --> -<br><input type="password" value="café"></input> <!-- with combining character --> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/fast/gradients/background-clipped-expected.png b/third_party/WebKit/LayoutTests/fast/gradients/background-clipped-expected.png index 3f4bcff..190b298a 100644 --- a/third_party/WebKit/LayoutTests/fast/gradients/background-clipped-expected.png +++ b/third_party/WebKit/LayoutTests/fast/gradients/background-clipped-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/repaint/sub-frame-svg-background-expected.html b/third_party/WebKit/LayoutTests/fast/repaint/sub-frame-svg-background-expected.html new file mode 100644 index 0000000..b0f6008f --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/repaint/sub-frame-svg-background-expected.html
@@ -0,0 +1,3 @@ +<!DOCTYPE html> +<iframe srcdoc="<html style='background:green;'></html>"></iframe> +
diff --git a/third_party/WebKit/LayoutTests/fast/repaint/sub-frame-svg-background.html b/third_party/WebKit/LayoutTests/fast/repaint/sub-frame-svg-background.html new file mode 100644 index 0000000..693e29d --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/repaint/sub-frame-svg-background.html
@@ -0,0 +1,17 @@ +<!DOCTYPE html> +<script src="../../resources/run-after-layout-and-paint.js"></script> +<script> + if (window.testRunner) { + testRunner.overridePreference("WebKitWebSecurityEnabled", false); + testRunner.waitUntilDone(); + } + + function runTest() { + runAfterLayoutAndPaint(function(){ + var frame = document.getElementById("frame"); + frame.contentDocument.documentElement.style.background = "green"; + }, true); + } +</script> +<iframe id="frame" src="data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20style%3D%22background%3Ared%3B%22%3E%3C%2Fsvg%3E" onload="runTest();"></iframe> +
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-unit/datagrid-editable-longtext-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector-unit/datagrid-editable-longtext-expected.txt new file mode 100644 index 0000000..1b4bd59f9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/inspector-unit/datagrid-editable-longtext-expected.txt
@@ -0,0 +1,31 @@ +This tests long text in datagrid. +Original lengths +key text length: 1500 +value text length: 1000 + +Test committing a long key +key element is being edited +key text length: 3000 +Blurring the key +Editor value committed. +key text length: 3000 + +Test no-op editing the key +key element is being edited +key text length: 3000 +Blurring the key +key text length: 3000 + +Test committing a long value +value element is being edited +value text length: 3000 +Blurring the value +Editor value committed. +value text length: 1000 + +Test no-op editing the value +value element is being edited +value text length: 3000 +Blurring the value +value text length: 1000 +
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-unit/datagrid-editable-longtext.js b/third_party/WebKit/LayoutTests/http/tests/inspector-unit/datagrid-editable-longtext.js new file mode 100644 index 0000000..cd25055 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/inspector-unit/datagrid-editable-longtext.js
@@ -0,0 +1,72 @@ +TestRunner.loadModule('data_grid').then(test); + +function test() { + TestRunner.addResult("This tests long text in datagrid."); + + var columns = [ + {id: "key", title: "Key column", editable: true, longText: false}, + {id: "value", title: "Value column", editable: true, longText: true} + ]; + var dataGrid = new DataGrid.DataGrid(columns, onEdit); + UI.inspectorView.element.appendChild(dataGrid.element); + + var rootNode = dataGrid.rootNode(); + var node = new DataGrid.DataGridNode({key: "k".repeat(1500), value: "v".repeat(1500)}); + rootNode.appendChild(node); + + var keyElement = dataGrid.element.querySelector(".data .key-column"); + var valueElement = dataGrid.element.querySelector(".data .value-column"); + + TestRunner.addResult("Original lengths"); + dumpKeyLength(); + dumpValueLength(); + + TestRunner.addResult("\nTest committing a long key"); + dataGrid._startEditing(keyElement); + keyElement.textContent = "k".repeat(3000); + dumpKeyLength(); + TestRunner.addResult("Blurring the key"); + keyElement.blur(); + dumpKeyLength(); + + TestRunner.addResult("\nTest no-op editing the key"); + dataGrid._startEditing(keyElement); + dumpKeyLength(); + TestRunner.addResult("Blurring the key"); + keyElement.blur(); + dumpKeyLength(); + + TestRunner.addResult("\nTest committing a long value"); + dataGrid._startEditing(valueElement); + valueElement.textContent = "v".repeat(3000); + dumpValueLength(); + TestRunner.addResult("Blurring the value"); + valueElement.blur(); + dumpValueLength(); + + TestRunner.addResult("\nTest no-op editing the value"); + dataGrid._startEditing(valueElement); + dumpValueLength(); + TestRunner.addResult("Blurring the value"); + valueElement.blur(); + dumpValueLength(); + + + TestRunner.completeTest(); + + function dumpKeyLength() { + if (keyElement.classList.contains("being-edited")) + TestRunner.addResult("key element is being edited"); + TestRunner.addResult("key text length: " + keyElement.textContent.length); + } + + function dumpValueLength() { + if (valueElement.classList.contains("being-edited")) + TestRunner.addResult("value element is being edited"); + TestRunner.addResult("value text length: " + valueElement.textContent.length); + } + + function onEdit() { + TestRunner.addResult("Editor value committed."); + } +}
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-active-and-passive-reload.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-active-and-passive-reload.html index c6d6a1b..35a56592 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-active-and-passive-reload.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-active-and-passive-reload.html
@@ -11,8 +11,20 @@ InspectorTest.addResult("\nBefore Refresh --------------"); var mixedExplanations = [ - /** @type {!Protocol.Security.SecurityStateExplanation} */ ({"securityState": Protocol.Security.SecurityState.Neutral, "summary": "Neutral Test Summary", "description": "Neutral Test Description", mixedContentType: Protocol.Security.MixedContentType.OptionallyBlockable}), - /** @type {!Protocol.Security.SecurityStateExplanation} */ ({"securityState": Protocol.Security.SecurityState.Insecure, "summary": "Insecure Test Summary", "description": "Insecure Test Description", mixedContentType: Protocol.Security.MixedContentType.Blockable}) + { + securityState: Protocol.Security.SecurityState.Neutral, + summary: "Neutral Test Summary", + description: "Neutral Test Description", + mixedContentType: Protocol.Security.MixedContentType.OptionallyBlockable, + certificate: [] + }, + { + securityState: Protocol.Security.SecurityState.Insecure, + summary: "Insecure Test Summary", + description: "Insecure Test Description", + mixedContentType: Protocol.Security.MixedContentType.Blockable, + certificate: [] + } ]; InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Neutral, true, mixedExplanations, insecureContentStatus, null));
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-reload.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-reload.html index 8200b6e..b8ada9e 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-reload.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-reload.html
@@ -11,7 +11,13 @@ InspectorTest.addResult("\nBefore Refresh --------------"); var mixedExplanations = [ - /** @type {!Protocol.Security.SecurityStateExplanation} */ ({"securityState": Protocol.Security.SecurityState.Neutral, "summary": "Neutral Test Summary", "description": "Neutral Test Description", mixedContentType: Protocol.Security.MixedContentType.OptionallyBlockable}) + { + securityState: Protocol.Security.SecurityState.Neutral, + summary: "Neutral Test Summary", + description: "Neutral Test Description", + mixedContentType: Protocol.Security.MixedContentType.OptionallyBlockable, + certificate: [] + } ]; InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Neutral, true, mixedExplanations, insecureContentStatus, null));
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-explanation-ordering.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-explanation-ordering.html index d6d2707..cf1bcc2 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-explanation-ordering.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-explanation-ordering.html
@@ -13,26 +13,28 @@ // first to make sure it gets reordered. var explanations = [ { - "description": "Public-key pinning was bypassed by a local root certificate.", - "securityState": "info", - "summary": "Public-Key Pinning Bypassed" + description: "Public-key pinning was bypassed by a local root certificate.", + securityState: "info", + summary: "Public-Key Pinning Bypassed", + certificate: [] }, { - "hasCertificate": "true", - "description": "The connection to this site is using a valid, trusted server certificate.", - "securityState": "secure", - "summary": "Valid Certificate" + description: "The connection to this site is using a valid, trusted server certificate.", + securityState: "secure", + summary: "Valid Certificate", + certificate: ["BASE64CERTIFICATE"] }, { - "description": "The connection to this site uses a strong protocol (TLS 1.2), a strong key exchange (ECDHE_RSA), and an obsolete cipher (AES_256_CBC with HMAC-SHA1).", - "securityState": "secure", - "summary": "Obsolete Connection Settings" - + description: "The connection to this site uses a strong protocol (TLS 1.2), a strong key exchange (ECDHE_RSA), and an obsolete cipher (AES_256_CBC with HMAC-SHA1).", + securityState: "secure", + summary: "Obsolete Connection Settings", + certificate: [] }, { - "description": "All resources on this page are served securely.", - "securityState": "secure", - "summary": "Secure resources" + description: "All resources on this page are served securely.", + securityState: "secure", + summary: "Secure resources", + certificate: [] } ];
diff --git a/third_party/WebKit/LayoutTests/images/exif-orientation-height-image-document-expected.png b/third_party/WebKit/LayoutTests/images/exif-orientation-height-image-document-expected.png index cd52fb195..cdb6f4f5 100644 --- a/third_party/WebKit/LayoutTests/images/exif-orientation-height-image-document-expected.png +++ b/third_party/WebKit/LayoutTests/images/exif-orientation-height-image-document-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/browser/browser-version-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/browser/browser-version-expected.txt new file mode 100644 index 0000000..24247d8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/browser/browser-version-expected.txt
@@ -0,0 +1,6 @@ +Verifies Browser.getVersion method. +version.protocolVersion: OK +version.revision: OK +version.userAgent: OK +version.jsVersion: OK +
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/browser/browser-version.js b/third_party/WebKit/LayoutTests/inspector-protocol/browser/browser-version.js new file mode 100644 index 0000000..4673acb --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/browser/browser-version.js
@@ -0,0 +1,14 @@ +(async function(testRunner) { + var {page, session, dp} = await testRunner.startBlank('Verifies Browser.getVersion method.'); + var response = await dp.Browser.getVersion(); + check('protocolVersion', /^\d+\.\d+$/); // e.g. 1.2 + check('revision', /^@[0-9abcdef]+$/); // e.g. @7d9cc1464f836e6d8c1ab9396a48c656df153d58 + check('userAgent', /^.+$/); // e.g. Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.77.34.5 Safari/537.36 + check('jsVersion', /^.+$/); // e.g. 6.2.196 + testRunner.completeTest(); + + function check(fieldName, regex) { + var status = regex.test(response.result[fieldName]) ? 'OK' : 'FAIL'; + testRunner.log(`version.${fieldName}: ${status}`); + } +})
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/svg/absolute-sized-document-no-scrollbars-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/svg/absolute-sized-document-no-scrollbars-expected.txt index df6f7c4..a01cdd3 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/svg/absolute-sized-document-no-scrollbars-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/svg/absolute-sized-document-no-scrollbars-expected.txt
@@ -7,6 +7,11 @@ "drawsContent": true, "paintInvalidations": [ { + "object": "LayoutView #document", + "rect": [0, 0, 800, 600], + "reason": "style change" + }, + { "object": "LayoutSVGRect rect", "rect": [0, 0, 576, 432], "reason": "style change" @@ -26,6 +31,10 @@ ], "objectPaintInvalidations": [ { + "object": "LayoutView #document", + "reason": "style change" + }, + { "object": "LayoutSVGRoot svg", "reason": "style change" },
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/svg/relative-sized-document-scrollbars-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/svg/relative-sized-document-scrollbars-expected.txt index d8e84657..93d817a 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/svg/relative-sized-document-scrollbars-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/svg/relative-sized-document-scrollbars-expected.txt
@@ -7,6 +7,11 @@ "drawsContent": true, "paintInvalidations": [ { + "object": "LayoutView #document", + "rect": [0, 0, 800, 600], + "reason": "style change" + }, + { "object": "LayoutSVGRect rect", "rect": [6, 4, 788, 592], "reason": "style change" @@ -21,6 +26,10 @@ ], "objectPaintInvalidations": [ { + "object": "LayoutView #document", + "reason": "style change" + }, + { "object": "LayoutSVGRoot svg", "reason": "style change" },
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-transformed-expected.png index d41092cd..e2bde95 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-transformed-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-transformed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-transformed2-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-transformed2-expected.png index b4cad73..1b3c400 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-transformed2-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-transformed2-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/reflection-in-composited-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/reflection-in-composited-expected.png index 85b3331..d8e4bc4 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/reflection-in-composited-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/reflection-in-composited-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/backgrounds/repeat/negative-offset-repeat-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/backgrounds/repeat/negative-offset-repeat-transformed-expected.png index a3f2569..028e3c1a 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/backgrounds/repeat/negative-offset-repeat-transformed-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/backgrounds/repeat/negative-offset-repeat-transformed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-inner-bleed-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-inner-bleed-expected.png index 0eab2bdf..cbb7d12 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-inner-bleed-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-inner-bleed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-composite-video-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-composite-video-expected.png index 1795b005..55b60e3 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-composite-video-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-composite-video-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-composite-video-shadow-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-composite-video-shadow-expected.png index 9b5c937..ebe81ec 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-composite-video-shadow-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/canvas-composite-video-shadow-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/image-object-in-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/image-object-in-canvas-expected.png index fd50afb..b6a7f6c 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/image-object-in-canvas-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/canvas/image-object-in-canvas-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/css/transformed-mask-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/css/transformed-mask-expected.png index cf3831d..e3b1a02 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/css/transformed-mask-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/css/transformed-mask-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/reflections/opacity-reflection-transform-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/reflections/opacity-reflection-transform-expected.png index 4cb5bc6..80125af 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/reflections/opacity-reflection-transform-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/reflections/opacity-reflection-transform-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/animated-path-inside-transformed-html-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/animated-path-inside-transformed-html-expected.png index 41911ac..df8d472 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/animated-path-inside-transformed-html-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/animated-path-inside-transformed-html-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/batik/filters/feTile-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/batik/filters/feTile-expected.png index 28a45a3..7f5d1c2 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/batik/filters/feTile-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/batik/filters/feTile-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/batik/text/smallFonts-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/batik/text/smallFonts-expected.png index 4a6abd7..9baedf1 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/batik/text/smallFonts-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/batik/text/smallFonts-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/batik/text/textFeatures-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/batik/text/textFeatures-expected.png index e7a2fb2..b1c7cef 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/batik/text/textFeatures-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/batik/text/textFeatures-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/focus-ring-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/focus-ring-expected.png index 14da8c6e..b4534f5c 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/focus-ring-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/focus-ring-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/pattern-rotate-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/pattern-rotate-expected.png index ecabe78..ada9f41 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/pattern-rotate-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/pattern-rotate-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/transformed-outlines-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/transformed-outlines-expected.png index 16826b45..43fbe89 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/transformed-outlines-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/transformed-outlines-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/hixie/perf/004-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/hixie/perf/004-expected.png index 4c5450f..0862b5ba7 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/hixie/perf/004-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/hixie/perf/004-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/transforms/text-with-pattern-inside-transformed-html-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/transforms/text-with-pattern-inside-transformed-html-expected.png index 998fed4..988c294e 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/transforms/text-with-pattern-inside-transformed-html-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/transforms/text-with-pattern-inside-transformed-html-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/transforms/text-with-pattern-with-svg-transform-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/transforms/text-with-pattern-with-svg-transform-expected.png index d20544ae..0bdd37bb 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/transforms/text-with-pattern-with-svg-transform-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/transforms/text-with-pattern-with-svg-transform-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/transformed-document-element-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/transformed-document-element-expected.png index f43c0d24..49c2a80 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/transforms/transformed-document-element-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/transformed-document-element-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-expected.png index 1795b005..55b60e3 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-shadow-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-shadow-expected.png index 9b5c937..ebe81ec 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-shadow-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-shadow-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/image-object-in-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/image-object-in-canvas-expected.png index c93f73f0..a7603f3 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/image-object-in-canvas-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/image-object-in-canvas-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/placeholder-position-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/placeholder-position-expected.png index 0f91d1e0..aee0d16 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/placeholder-position-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/placeholder-position-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/forms/placeholder-position-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/forms/placeholder-position-expected.png index 284ceea..68da93f71 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/forms/placeholder-position-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/forms/placeholder-position-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/canvas/canvas-composite-video-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/canvas/canvas-composite-video-expected.png index 9877fa03..c0aea11f 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/canvas/canvas-composite-video-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/canvas/canvas-composite-video-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/canvas/canvas-composite-video-shadow-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/canvas/canvas-composite-video-shadow-expected.png index f6b9b659..6f89722 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/canvas/canvas-composite-video-shadow-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/canvas/canvas-composite-video-shadow-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/placeholder-position-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/placeholder-position-expected.png index 655db98..ba959f0 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/placeholder-position-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/placeholder-position-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/layers/scroll-with-transform-layer-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/layers/scroll-with-transform-layer-expected.png index b94996b..066f8be 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/layers/scroll-with-transform-layer-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/layers/scroll-with-transform-layer-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/custom/foreign-object-skew-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/custom/foreign-object-skew-expected.png index c0aa7b730..35db139c 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/custom/foreign-object-skew-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/custom/foreign-object-skew-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-expected.png index 9877fa03..c0aea11f 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-shadow-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-shadow-expected.png index f6b9b659..6f89722 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-shadow-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-shadow-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/fast/forms/placeholder-position-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/fast/forms/placeholder-position-expected.png index 284ceea..68da93f71 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-retina/fast/forms/placeholder-position-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-retina/fast/forms/placeholder-position-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-transformed-expected.png index cd6d214..5050e02e 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-transformed-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-transformed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-transformed2-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-transformed2-expected.png index 9517ed2a..a344d8c 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-transformed2-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-transformed2-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/reflection-in-composited-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/reflection-in-composited-expected.png index 349bd305..09073d2 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/reflection-in-composited-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/reflection-in-composited-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/backgrounds/repeat/negative-offset-repeat-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/backgrounds/repeat/negative-offset-repeat-transformed-expected.png index fbc8982..8881d88 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/backgrounds/repeat/negative-offset-repeat-transformed-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/backgrounds/repeat/negative-offset-repeat-transformed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-image-rotate-transform-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-image-rotate-transform-expected.png index c79a602..baf5817 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-image-rotate-transform-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-image-rotate-transform-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-inner-bleed-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-inner-bleed-expected.png index 57c869b09..88f67dc 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-inner-bleed-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-inner-bleed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/canvas/canvas-composite-video-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/canvas/canvas-composite-video-expected.png index 89b633e1..4cbdf75 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/canvas/canvas-composite-video-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/canvas/canvas-composite-video-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/canvas/canvas-composite-video-shadow-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/canvas/canvas-composite-video-shadow-expected.png index bfd4965..90973311 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/canvas/canvas-composite-video-shadow-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/canvas/canvas-composite-video-shadow-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/canvas/image-object-in-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/canvas/image-object-in-canvas-expected.png index ebff45f8..6ef7d5c 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/canvas/image-object-in-canvas-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/canvas/image-object-in-canvas-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/css/transformed-mask-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/css/transformed-mask-expected.png index f4f175d..423ae30 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/css/transformed-mask-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/css/transformed-mask-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/layers/scroll-with-transform-layer-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/layers/scroll-with-transform-layer-expected.png index ddc33d6..e59d3a3 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/layers/scroll-with-transform-layer-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/layers/scroll-with-transform-layer-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/reflections/opacity-reflection-transform-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/reflections/opacity-reflection-transform-expected.png index 161c887..977b328 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/reflections/opacity-reflection-transform-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/reflections/opacity-reflection-transform-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/animated-path-inside-transformed-html-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/animated-path-inside-transformed-html-expected.png index c2ded6e8..759daf8 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/animated-path-inside-transformed-html-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/animated-path-inside-transformed-html-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/batik/filters/feTile-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/batik/filters/feTile-expected.png index 5364dc6..cb260e92 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/batik/filters/feTile-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/batik/filters/feTile-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/smallFonts-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/smallFonts-expected.png index 0f003bd..2e864da 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/smallFonts-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/smallFonts-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/textFeatures-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/textFeatures-expected.png index b4b029d..83765b08 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/textFeatures-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/textFeatures-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/focus-ring-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/focus-ring-expected.png index b90cbed..0301123 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/focus-ring-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/focus-ring-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/foreign-object-skew-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/foreign-object-skew-expected.png index a71aefe..c5a07ab 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/foreign-object-skew-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/foreign-object-skew-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/pattern-rotate-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/pattern-rotate-expected.png index 17ecef5..9be0afc 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/pattern-rotate-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/pattern-rotate-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/transformed-outlines-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/transformed-outlines-expected.png index c7379b7..ec336cb 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/transformed-outlines-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/transformed-outlines-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/hixie/perf/004-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/hixie/perf/004-expected.png index 46b1b9d2..f8392e94 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/hixie/perf/004-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/hixie/perf/004-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/transforms/text-with-pattern-inside-transformed-html-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/transforms/text-with-pattern-inside-transformed-html-expected.png index 731024c..7c7281fc 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/transforms/text-with-pattern-inside-transformed-html-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/transforms/text-with-pattern-inside-transformed-html-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/transforms/text-with-pattern-with-svg-transform-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/transforms/text-with-pattern-with-svg-transform-expected.png index 580ebf3..0fafdf7 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/transforms/text-with-pattern-with-svg-transform-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/transforms/text-with-pattern-with-svg-transform-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/transforms/transformed-document-element-expected.png b/third_party/WebKit/LayoutTests/platform/mac/transforms/transformed-document-element-expected.png index b3a8853..6ad401a 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/transforms/transformed-document-element-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/transforms/transformed-document-element-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-expected.png index 89b633e1..4cbdf75 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-shadow-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-shadow-expected.png index bfd4965..90973311 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-shadow-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-shadow-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/image-object-in-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/image-object-in-canvas-expected.png index ae68f84..5a04d50 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/image-object-in-canvas-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/image-object-in-canvas-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-transformed-expected.png index 326cf1e..3349df3 100644 --- a/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-transformed-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-transformed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-transformed2-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-transformed2-expected.png index d59dd8e..19c47c13 100644 --- a/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-transformed2-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-transformed2-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/reflection-in-composited-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/reflection-in-composited-expected.png index ec7415fb..6f6ae4c 100644 --- a/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/reflection-in-composited-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/reflection-in-composited-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/backgrounds/repeat/negative-offset-repeat-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/backgrounds/repeat/negative-offset-repeat-transformed-expected.png index e91a060..8ac880e 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/backgrounds/repeat/negative-offset-repeat-transformed-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/fast/backgrounds/repeat/negative-offset-repeat-transformed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-image-rotate-transform-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-image-rotate-transform-expected.png index 3efca06..1d8da6b 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-image-rotate-transform-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-image-rotate-transform-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-inner-bleed-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-inner-bleed-expected.png index b26d4fd..d5c1163 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-inner-bleed-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-inner-bleed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/canvas/canvas-composite-video-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/canvas/canvas-composite-video-expected.png index db2e272..5754aae 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/canvas/canvas-composite-video-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/fast/canvas/canvas-composite-video-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/canvas/canvas-composite-video-shadow-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/canvas/canvas-composite-video-shadow-expected.png index a578bd10..05a993d 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/canvas/canvas-composite-video-shadow-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/fast/canvas/canvas-composite-video-shadow-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/canvas/image-object-in-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/canvas/image-object-in-canvas-expected.png index e8f7162..bdbc6ab 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/canvas/image-object-in-canvas-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/fast/canvas/image-object-in-canvas-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/css/transformed-mask-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/css/transformed-mask-expected.png index 4d902fa..589c940 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/css/transformed-mask-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/fast/css/transformed-mask-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/reflections/opacity-reflection-transform-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/reflections/opacity-reflection-transform-expected.png index 9cec965..f76e53c 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/reflections/opacity-reflection-transform-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/fast/reflections/opacity-reflection-transform-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/animated-path-inside-transformed-html-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/animated-path-inside-transformed-html-expected.png index a281ad5..89f387f 100644 --- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/animated-path-inside-transformed-html-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/animated-path-inside-transformed-html-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/batik/filters/feTile-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/batik/filters/feTile-expected.png index bfc9e2c..630122b1 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/batik/filters/feTile-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/batik/filters/feTile-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/smallFonts-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/smallFonts-expected.png index b170da1a..c7b51fd 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/smallFonts-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/smallFonts-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textFeatures-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textFeatures-expected.png index a436184..a1a56c3 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textFeatures-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textFeatures-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/custom/focus-ring-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/custom/focus-ring-expected.png index f141ebb..45c44f9 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/custom/focus-ring-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/custom/focus-ring-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/custom/pattern-rotate-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/custom/pattern-rotate-expected.png index 740098a..8adf3b5 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/custom/pattern-rotate-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/custom/pattern-rotate-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/custom/transformed-outlines-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/custom/transformed-outlines-expected.png index 9fe658ad..de89ae7 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/custom/transformed-outlines-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/custom/transformed-outlines-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/hixie/perf/004-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/hixie/perf/004-expected.png index d57f21b2..aa0fd8c 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/hixie/perf/004-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/hixie/perf/004-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/transforms/text-with-pattern-inside-transformed-html-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/transforms/text-with-pattern-inside-transformed-html-expected.png index 48034234..3738002 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/transforms/text-with-pattern-inside-transformed-html-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/transforms/text-with-pattern-inside-transformed-html-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/transforms/text-with-pattern-with-svg-transform-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/transforms/text-with-pattern-with-svg-transform-expected.png index 8b2d555..a36dd18 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/transforms/text-with-pattern-with-svg-transform-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/transforms/text-with-pattern-with-svg-transform-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/transforms/transformed-document-element-expected.png b/third_party/WebKit/LayoutTests/platform/win/transforms/transformed-document-element-expected.png index 137dee85..c639d58 100644 --- a/third_party/WebKit/LayoutTests/platform/win/transforms/transformed-document-element-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/transforms/transformed-document-element-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-expected.png index db2e272..5754aae 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-shadow-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-shadow-expected.png index a578bd10..05a993d 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-shadow-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video-shadow-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/image-object-in-canvas-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/image-object-in-canvas-expected.png index e73fe3a..35673c7 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/image-object-in-canvas-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/image-object-in-canvas-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/display_list_2d_canvas/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png b/third_party/WebKit/LayoutTests/virtual/display_list_2d_canvas/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png index 1649230..bbfecdf 100644 --- a/third_party/WebKit/LayoutTests/virtual/display_list_2d_canvas/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png +++ b/third_party/WebKit/LayoutTests/virtual/display_list_2d_canvas/fast/canvas/canvas-pattern-no-repeat-with-transformations-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/exif-orientation-height-image-document-expected.png b/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/exif-orientation-height-image-document-expected.png index 679d3b5f..6366d72 100644 --- a/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/exif-orientation-height-image-document-expected.png +++ b/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/exif-orientation-height-image-document-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt index 553a40d..adcfe35b 100644 --- a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
@@ -4939,8 +4939,8 @@ interface PerformanceServerTiming attribute @@toStringTag getter description - getter metric - getter value + getter duration + getter name method constructor interface PerformanceTiming attribute @@toStringTag
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt index f1c0e7d..ff1ddb4 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -4946,8 +4946,8 @@ interface PerformanceServerTiming attribute @@toStringTag getter description - getter metric - getter value + getter duration + getter name method constructor interface PerformanceTiming attribute @@toStringTag
diff --git a/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl b/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl index 0e04b24..c4c6528 100644 --- a/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl +++ b/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl
@@ -911,7 +911,7 @@ } void {{v8_class_or_partial}}::install{{feature.name}}(ScriptState* scriptState, v8::Local<v8::Object> instance) { - V8PerContextData* perContextData = V8PerContextData::From(scriptState->GetContext()); + V8PerContextData* perContextData = scriptState->PerContextData(); v8::Local<v8::Object> prototype = perContextData->PrototypeForType(&{{v8_class}}::wrapperTypeInfo); v8::Local<v8::Function> interface = perContextData->ConstructorForType(&{{v8_class}}::wrapperTypeInfo); ALLOW_UNUSED_LOCAL(interface);
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestConstants.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestConstants.cpp index fd15644..d2afdd9 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestConstants.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestConstants.cpp
@@ -199,7 +199,7 @@ } void V8TestConstants::installFeatureName1(ScriptState* scriptState, v8::Local<v8::Object> instance) { - V8PerContextData* perContextData = V8PerContextData::From(scriptState->GetContext()); + V8PerContextData* perContextData = scriptState->PerContextData(); v8::Local<v8::Object> prototype = perContextData->PrototypeForType(&V8TestConstants::wrapperTypeInfo); v8::Local<v8::Function> interface = perContextData->ConstructorForType(&V8TestConstants::wrapperTypeInfo); ALLOW_UNUSED_LOCAL(interface); @@ -218,7 +218,7 @@ } void V8TestConstants::installFeatureName2(ScriptState* scriptState, v8::Local<v8::Object> instance) { - V8PerContextData* perContextData = V8PerContextData::From(scriptState->GetContext()); + V8PerContextData* perContextData = scriptState->PerContextData(); v8::Local<v8::Object> prototype = perContextData->PrototypeForType(&V8TestConstants::wrapperTypeInfo); v8::Local<v8::Function> interface = perContextData->ConstructorForType(&V8TestConstants::wrapperTypeInfo); ALLOW_UNUSED_LOCAL(interface);
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp index f88287b..4748e12 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
@@ -13060,7 +13060,7 @@ } void V8TestObject::installFeatureName(ScriptState* scriptState, v8::Local<v8::Object> instance) { - V8PerContextData* perContextData = V8PerContextData::From(scriptState->GetContext()); + V8PerContextData* perContextData = scriptState->PerContextData(); v8::Local<v8::Object> prototype = perContextData->PrototypeForType(&V8TestObject::wrapperTypeInfo); v8::Local<v8::Function> interface = perContextData->ConstructorForType(&V8TestObject::wrapperTypeInfo); ALLOW_UNUSED_LOCAL(interface);
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterfacePartial.cpp b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterfacePartial.cpp index 070f582..0d32c442 100644 --- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterfacePartial.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterfacePartial.cpp
@@ -507,7 +507,7 @@ } void V8TestInterfacePartial::installOriginTrialPartialFeature(ScriptState* scriptState, v8::Local<v8::Object> instance) { - V8PerContextData* perContextData = V8PerContextData::From(scriptState->GetContext()); + V8PerContextData* perContextData = scriptState->PerContextData(); v8::Local<v8::Object> prototype = perContextData->PrototypeForType(&V8TestInterface::wrapperTypeInfo); v8::Local<v8::Function> interface = perContextData->ConstructorForType(&V8TestInterface::wrapperTypeInfo); ALLOW_UNUSED_LOCAL(interface);
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn index f80c029..fb9988c5 100644 --- a/third_party/WebKit/Source/core/BUILD.gn +++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -1314,7 +1314,6 @@ "css/invalidation/StyleInvalidatorTest.cpp", "css/parser/CSSLazyParsingTest.cpp", "css/parser/CSSParserFastPathsTest.cpp", - "css/parser/CSSParserTokenStreamTest.cpp", "css/parser/CSSParserTokenTest.cpp", "css/parser/CSSPropertyParserTest.cpp", "css/parser/CSSSelectorParserTest.cpp",
diff --git a/third_party/WebKit/Source/core/css/BUILD.gn b/third_party/WebKit/Source/core/css/BUILD.gn index ee3fcd9..5d886d9 100644 --- a/third_party/WebKit/Source/core/css/BUILD.gn +++ b/third_party/WebKit/Source/core/css/BUILD.gn
@@ -351,7 +351,6 @@ "parser/CSSParserToken.h", "parser/CSSParserTokenRange.cpp", "parser/CSSParserTokenRange.h", - "parser/CSSParserTokenStream.cpp", "parser/CSSParserTokenStream.h", "parser/CSSPropertyParser.cpp", "parser/CSSPropertyParser.h",
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp index 5e68393..9d9803f 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp
@@ -169,7 +169,8 @@ CSSParserImpl parser(context, document.ElementSheet().Contents()); CSSTokenizer tokenizer(string); CSSParserTokenStream stream(tokenizer); - parser.ConsumeDeclarationList(stream, StyleRule::kStyle); + // TODO(shend): Use streams instead of ranges + parser.ConsumeDeclarationList(stream.MakeRangeToEOF(), StyleRule::kStyle); return CreateStylePropertySet(parser.parsed_properties_, mode); } @@ -182,7 +183,8 @@ rule_type = StyleRule::kViewport; CSSTokenizer tokenizer(string); CSSParserTokenStream stream(tokenizer); - parser.ConsumeDeclarationList(stream, rule_type); + // TODO(shend): Use streams instead of ranges + parser.ConsumeDeclarationList(stream.MakeRangeToEOF(), rule_type); if (parser.parsed_properties_.IsEmpty()) return false; @@ -846,57 +848,6 @@ CreateStylePropertySet(parsed_properties_, context_->Mode())); } -void CSSParserImpl::ConsumeDeclarationList(CSSParserTokenStream& stream, - StyleRule::RuleType rule_type) { - DCHECK(parsed_properties_.IsEmpty()); - - bool use_observer = observer_wrapper_ && (rule_type == StyleRule::kStyle || - rule_type == StyleRule::kKeyframe); - DCHECK(!use_observer); // TODO(shend): Implement streaming with observers. - - while (!stream.AtEnd()) { - switch (stream.UncheckedPeek().GetType()) { - case kWhitespaceToken: - case kSemicolonToken: - stream.UncheckedConsume(); - break; - case kIdentToken: { - // TODO(shend): Use streams instead of ranges - auto range = stream.MakeRangeToEOF(); - - const CSSParserToken* declaration_start = &range.Peek(); - while (!range.AtEnd() && range.Peek().GetType() != kSemicolonToken) - range.ConsumeComponentValue(); - - ConsumeDeclaration(range.MakeSubRange(declaration_start, &range.Peek()), - rule_type); - - stream.UpdatePositionFromRange(range); - break; - } - case kAtKeywordToken: { - AllowedRulesType allowed_rules = - rule_type == StyleRule::kStyle && - RuntimeEnabledFeatures::CSSApplyAtRulesEnabled() - ? kApplyRules - : kNoRules; - - // TODO(shend): Use streams instead of ranges - auto range = stream.MakeRangeToEOF(); - StyleRuleBase* rule = ConsumeAtRule(range, allowed_rules); - stream.UpdatePositionFromRange(range); - DCHECK(!rule); - break; - } - default: // Parse error, unexpected token in declaration list - while (!stream.AtEnd() && - stream.UncheckedPeek().GetType() != kSemicolonToken) - stream.UncheckedConsumeComponentValue(); - break; - } - } -} - void CSSParserImpl::ConsumeDeclarationList(CSSParserTokenRange range, StyleRule::RuleType rule_type) { DCHECK(parsed_properties_.IsEmpty());
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.h b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.h index a467eea3f..df169ad 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.h +++ b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.h
@@ -21,7 +21,6 @@ class CSSParserContext; class CSSParserObserver; class CSSParserObserverWrapper; -class CSSParserTokenStream; class StyleRule; class StyleRuleBase; class StyleRuleCharset; @@ -141,8 +140,6 @@ StyleRule* ConsumeStyleRule(CSSParserTokenRange prelude, CSSParserTokenRange block); - void ConsumeDeclarationList(CSSParserTokenStream&, StyleRule::RuleType); - // TODO(shend): Remove this overload once we switch over to streams. void ConsumeDeclarationList(CSSParserTokenRange, StyleRule::RuleType); void ConsumeDeclaration(CSSParserTokenRange, StyleRule::RuleType); void ConsumeDeclarationValue(CSSParserTokenRange,
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserTokenStream.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserTokenStream.cpp deleted file mode 100644 index 0a2eaf1..0000000 --- a/third_party/WebKit/Source/core/css/parser/CSSParserTokenStream.cpp +++ /dev/null
@@ -1,20 +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 "core/css/parser/CSSParserTokenStream.h" - -namespace blink { - -void CSSParserTokenStream::UncheckedConsumeComponentValue() { - unsigned nesting_level = 0; - do { - const CSSParserToken& token = UncheckedConsume(); - if (token.GetBlockType() == CSSParserToken::kBlockStart) - nesting_level++; - else if (token.GetBlockType() == CSSParserToken::kBlockEnd) - nesting_level--; - } while (nesting_level && !AtEnd()); -} - -} // namespace blink
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserTokenStream.h b/third_party/WebKit/Source/core/css/parser/CSSParserTokenStream.h index fbfb0ad..ba4c05b 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserTokenStream.h +++ b/third_party/WebKit/Source/core/css/parser/CSSParserTokenStream.h
@@ -6,75 +6,23 @@ #define CSSParserTokenStream_h #include "CSSTokenizer.h" -#include "core/css/parser/CSSParserTokenRange.h" namespace blink { // A streaming interface to CSSTokenizer that tokenizes on demand. -// Methods prefixed with "Unchecked" can only be called after Peek() -// returns a non-EOF token or after AtEnd() returns false, with no -// subsequent modifications to the stream such as a consume. -class CORE_EXPORT CSSParserTokenStream { +class CSSParserTokenStream { DISALLOW_NEW(); public: explicit CSSParserTokenStream(CSSTokenizer& tokenizer) - : tokenizer_(tokenizer), next_index_(0) { + : tokenizer_(tokenizer) { DCHECK_EQ(tokenizer.tokens_.size(), 0U); } - // TODO(shend): Remove this method. We should never convert from a range to a - // stream. We can remove this once all the functions in CSSParserImpl.h accept - // streams. - void UpdatePositionFromRange(const CSSParserTokenRange& range) { - next_index_ = range.begin() - tokenizer_.tokens_.begin(); - } - - const CSSParserToken& Peek() const { - if (next_index_ == tokenizer_.tokens_.size()) { - // Reached end of token buffer, but might not be end of input. - if (tokenizer_.TokenizeSingle().IsEOF()) - return g_static_eof_token; - } - DCHECK_LT(next_index_, tokenizer_.tokens_.size()); - return UncheckedPeek(); - } - - const CSSParserToken& UncheckedPeek() const { - DCHECK_LT(next_index_, tokenizer_.tokens_.size()); - return tokenizer_.tokens_[next_index_]; - } - - const CSSParserToken& Consume() { - const CSSParserToken& token = Peek(); - if (!token.IsEOF()) - next_index_++; - - DCHECK_LE(next_index_, tokenizer_.tokens_.size()); - return token; - } - - const CSSParserToken& UncheckedConsume() { - DCHECK_LE(next_index_, tokenizer_.tokens_.size()); - return tokenizer_.tokens_[next_index_++]; - } - - bool AtEnd() const { return Peek().IsEOF(); } - - // Range represents all tokens from current position to EOF. - // Eagerly consumes all the remaining input. - // TODO(shend): Remove this method once we switch over to using streams - // completely. - CSSParserTokenRange MakeRangeToEOF() { - return tokenizer_.TokenRange().MakeSubRange( - tokenizer_.tokens_.begin() + next_index_, tokenizer_.tokens_.end()); - } - - void UncheckedConsumeComponentValue(); + CSSParserTokenRange MakeRangeToEOF() { return tokenizer_.TokenRange(); } private: CSSTokenizer& tokenizer_; - size_t next_index_; // Index of next token to be consumed. }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserTokenStreamTest.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserTokenStreamTest.cpp deleted file mode 100644 index e675e4d..0000000 --- a/third_party/WebKit/Source/core/css/parser/CSSParserTokenStreamTest.cpp +++ /dev/null
@@ -1,93 +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 "core/css/parser/CSSParserTokenStream.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace blink { - -TEST(CSSParserTokenStreamTest, EmptyStream) { - CSSTokenizer tokenizer(""); - CSSParserTokenStream stream(tokenizer); - EXPECT_TRUE(stream.Consume().IsEOF()); - EXPECT_TRUE(stream.Peek().IsEOF()); - EXPECT_TRUE(stream.AtEnd()); - EXPECT_TRUE(stream.MakeRangeToEOF().AtEnd()); -} - -TEST(CSSParserTokenStreamTest, PeekThenConsume) { - CSSTokenizer tokenizer("A"); // kIdent - CSSParserTokenStream stream(tokenizer); - EXPECT_EQ(kIdentToken, stream.Peek().GetType()); - EXPECT_EQ(kIdentToken, stream.Consume().GetType()); - EXPECT_TRUE(stream.AtEnd()); -} - -TEST(CSSParserTokenStreamTest, ConsumeThenPeek) { - CSSTokenizer tokenizer("A"); // kIdent - CSSParserTokenStream stream(tokenizer); - EXPECT_EQ(kIdentToken, stream.Consume().GetType()); - EXPECT_TRUE(stream.AtEnd()); -} - -TEST(CSSParserTokenStreamTest, ConsumeMultipleTokens) { - CSSTokenizer tokenizer("A 1"); // kIdent kWhitespace kNumber - CSSParserTokenStream stream(tokenizer); - EXPECT_EQ(kIdentToken, stream.Consume().GetType()); - EXPECT_EQ(kWhitespaceToken, stream.Consume().GetType()); - EXPECT_EQ(kNumberToken, stream.Consume().GetType()); - EXPECT_TRUE(stream.AtEnd()); -} - -TEST(CSSParserTokenStreamTest, UncheckedPeekAndConsumeAfterPeek) { - CSSTokenizer tokenizer("A"); // kIdent - CSSParserTokenStream stream(tokenizer); - EXPECT_EQ(kIdentToken, stream.Peek().GetType()); - EXPECT_EQ(kIdentToken, stream.UncheckedPeek().GetType()); - EXPECT_EQ(kIdentToken, stream.UncheckedConsume().GetType()); - EXPECT_TRUE(stream.AtEnd()); -} - -TEST(CSSParserTokenStreamTest, UncheckedPeekAndConsumeAfterAtEnd) { - CSSTokenizer tokenizer("A"); // kIdent - CSSParserTokenStream stream(tokenizer); - EXPECT_FALSE(stream.AtEnd()); - EXPECT_EQ(kIdentToken, stream.UncheckedPeek().GetType()); - EXPECT_EQ(kIdentToken, stream.UncheckedConsume().GetType()); - EXPECT_TRUE(stream.AtEnd()); -} - -TEST(CSSParserTokenStreamTest, MakeRangeToEOF) { - CSSTokenizer tokenizer("A 1"); // kIdent kWhitespace kNumber - CSSParserTokenStream stream(tokenizer); - EXPECT_EQ(kIdentToken, stream.Consume().GetType()); - - auto range = stream.MakeRangeToEOF(); - EXPECT_FALSE(stream.AtEnd()); - EXPECT_EQ(kWhitespaceToken, range.Consume().GetType()); - EXPECT_FALSE(stream.AtEnd()); - EXPECT_EQ(kNumberToken, range.Consume().GetType()); - EXPECT_TRUE(range.AtEnd()); - - EXPECT_FALSE(stream.AtEnd()); -} - -TEST(CSSParserTokenStreamTest, UncheckedConsumeComponentValue) { - CSSTokenizer tokenizer("A{1}{2{3}}B"); - CSSParserTokenStream stream(tokenizer); - - EXPECT_EQ(kIdentToken, stream.Peek().GetType()); - stream.UncheckedConsumeComponentValue(); - EXPECT_EQ(kLeftBraceToken, stream.Peek().GetType()); - stream.UncheckedConsumeComponentValue(); - EXPECT_EQ(kLeftBraceToken, stream.Peek().GetType()); - stream.UncheckedConsumeComponentValue(); - EXPECT_EQ(kIdentToken, stream.Peek().GetType()); - stream.UncheckedConsumeComponentValue(); - - EXPECT_TRUE(stream.AtEnd()); -} - -} // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/Range.cpp b/third_party/WebKit/Source/core/dom/Range.cpp index 5cfc8ad9..981602e 100644 --- a/third_party/WebKit/Source/core/dom/Range.cpp +++ b/third_party/WebKit/Source/core/dom/Range.cpp
@@ -1610,27 +1610,32 @@ return DOMRect::FromFloatRect(BoundingRect()); } +// https://www.w3.org/TR/cssom-view-1/#dom-range-getclientrects void Range::GetBorderAndTextQuads(Vector<FloatQuad>& quads) const { Node* start_container = &start_.Container(); Node* end_container = &end_.Container(); Node* stop_node = PastLastNode(); - HeapHashSet<Member<Node>> node_set; + // Stores the elements selected by the range. + HeapHashSet<Member<Node>> selected_elements; for (Node* node = FirstNode(); node != stop_node; node = NodeTraversal::Next(*node)) { - if (node->IsElementNode()) - node_set.insert(node); + if (!node->IsElementNode()) + continue; + if (selected_elements.Contains(node->parentNode()) || + (!node->contains(start_container) && !node->contains(end_container))) { + DCHECK_LE(StartPosition(), Position::BeforeNode(*node)); + DCHECK_GE(EndPosition(), Position::AfterNode(*node)); + selected_elements.insert(node); + } } for (Node* node = FirstNode(); node != stop_node; node = NodeTraversal::Next(*node)) { if (node->IsElementNode()) { - // Exclude start & end container unless the entire corresponding - // node is included in the range. - if (!node_set.Contains(node->parentNode()) && - (start_container == end_container || - (!node->contains(start_container) && - !node->contains(end_container)))) { + // TODO(xiaochengh): Apply early continue style to reduce indentation. + if (selected_elements.Contains(node) && + !selected_elements.Contains(node->parentNode())) { if (LayoutObject* layout_object = ToElement(node)->GetLayoutObject()) { Vector<FloatQuad> element_quads; layout_object->AbsoluteQuads(element_quads);
diff --git a/third_party/WebKit/Source/core/dom/RangeTest.cpp b/third_party/WebKit/Source/core/dom/RangeTest.cpp index 64ca6ff..34d94d7 100644 --- a/third_party/WebKit/Source/core/dom/RangeTest.cpp +++ b/third_party/WebKit/Source/core/dom/RangeTest.cpp
@@ -296,4 +296,20 @@ EXPECT_EQ(rect_before, rect_after); } +// Regression test for crbug.com/681536 +TEST_F(RangeTest, BorderAndTextQuadsWithInputInBetween) { + GetDocument().body()->setInnerHTML("<div>foo <u><input> bar</u></div>"); + GetDocument().UpdateStyleAndLayout(); + + Node* foo = GetDocument().QuerySelector("div")->firstChild(); + Node* bar = GetDocument().QuerySelector("u")->lastChild(); + Range* range = Range::Create(GetDocument(), foo, 2, bar, 2); + + Vector<FloatQuad> quads; + range->GetBorderAndTextQuads(quads); + + // Should get one quad for "o ", <input> and " b", respectively. + ASSERT_EQ(3u, quads.size()); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/BUILD.gn b/third_party/WebKit/Source/core/editing/BUILD.gn index 5434e49d..bbdb5c2 100644 --- a/third_party/WebKit/Source/core/editing/BUILD.gn +++ b/third_party/WebKit/Source/core/editing/BUILD.gn
@@ -9,10 +9,6 @@ sources = [ "CaretDisplayItemClient.cpp", "CaretDisplayItemClient.h", - "CompositionUnderline.cpp", - "CompositionUnderline.h", - "CompositionUnderlineVectorBuilder.cpp", - "CompositionUnderlineVectorBuilder.h", "DOMSelection.cpp", "DOMSelection.h", "DragCaret.cpp", @@ -42,6 +38,10 @@ "FrameSelection.h", "GranularityStrategy.cpp", "GranularityStrategy.h", + "ImeTextSpan.cpp", + "ImeTextSpan.h", + "ImeTextSpanVectorBuilder.cpp", + "ImeTextSpanVectorBuilder.h", "InlineBoxTraversal.cpp", "InlineBoxTraversal.h", "InputMethodController.cpp", @@ -310,7 +310,6 @@ source_set("unit_tests") { testonly = true sources = [ - "CompositionUnderlineTest.cpp", "EditingCommandTest.cpp", "EditingStrategyTest.cpp", "EditingStyleTest.cpp", @@ -322,6 +321,7 @@ "FrameCaretTest.cpp", "FrameSelectionTest.cpp", "GranularityStrategyTest.cpp", + "ImeTextSpanTest.cpp", "InputMethodControllerTest.cpp", "LayoutSelectionTest.cpp", "PositionIteratorTest.cpp",
diff --git a/third_party/WebKit/Source/core/editing/CompositionUnderline.cpp b/third_party/WebKit/Source/core/editing/CompositionUnderline.cpp deleted file mode 100644 index 5bd9d7d..0000000 --- a/third_party/WebKit/Source/core/editing/CompositionUnderline.cpp +++ /dev/null
@@ -1,33 +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 "core/editing/CompositionUnderline.h" - -#include <algorithm> -#include "public/web/WebCompositionUnderline.h" - -namespace blink { - -CompositionUnderline::CompositionUnderline(unsigned start_offset, - unsigned end_offset, - const Color& color, - bool thick, - const Color& background_color) - : color_(color), thick_(thick), background_color_(background_color) { - // Sanitize offsets by ensuring a valid range corresponding to the last - // possible position. - // TODO(wkorman): Consider replacing with DCHECK_LT(startOffset, endOffset). - start_offset_ = - std::min(start_offset, std::numeric_limits<unsigned>::max() - 1u); - end_offset_ = std::max(start_offset_ + 1u, end_offset); -} - -CompositionUnderline::CompositionUnderline( - const WebCompositionUnderline& underline) - : CompositionUnderline(underline.start_offset, - underline.end_offset, - Color(underline.color), - underline.thick, - Color(underline.background_color)) {} -} // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/CompositionUnderlineTest.cpp b/third_party/WebKit/Source/core/editing/CompositionUnderlineTest.cpp deleted file mode 100644 index ef0a2fb..0000000 --- a/third_party/WebKit/Source/core/editing/CompositionUnderlineTest.cpp +++ /dev/null
@@ -1,72 +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 "core/editing/CompositionUnderline.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace blink { -namespace { - -CompositionUnderline CreateCompositionUnderline(unsigned start_offset, - unsigned end_offset) { - return CompositionUnderline(start_offset, end_offset, Color::kTransparent, - false, Color::kTransparent); -} - -TEST(CompositionUnderlineTest, OneChar) { - CompositionUnderline underline = CreateCompositionUnderline(0, 1); - EXPECT_EQ(0u, underline.StartOffset()); - EXPECT_EQ(1u, underline.EndOffset()); -} - -TEST(CompositionUnderlineTest, MultiChar) { - CompositionUnderline underline = CreateCompositionUnderline(0, 5); - EXPECT_EQ(0u, underline.StartOffset()); - EXPECT_EQ(5u, underline.EndOffset()); -} - -TEST(CompositionUnderlineTest, ZeroLength) { - CompositionUnderline underline = CreateCompositionUnderline(0, 0); - EXPECT_EQ(0u, underline.StartOffset()); - EXPECT_EQ(1u, underline.EndOffset()); -} - -TEST(CompositionUnderlineTest, ZeroLengthNonZeroStart) { - CompositionUnderline underline = CreateCompositionUnderline(3, 3); - EXPECT_EQ(3u, underline.StartOffset()); - EXPECT_EQ(4u, underline.EndOffset()); -} - -TEST(CompositionUnderlineTest, EndBeforeStart) { - CompositionUnderline underline = CreateCompositionUnderline(1, 0); - EXPECT_EQ(1u, underline.StartOffset()); - EXPECT_EQ(2u, underline.EndOffset()); -} - -TEST(CompositionUnderlineTest, LastChar) { - CompositionUnderline underline = - CreateCompositionUnderline(std::numeric_limits<unsigned>::max() - 1, - std::numeric_limits<unsigned>::max()); - EXPECT_EQ(std::numeric_limits<unsigned>::max() - 1, underline.StartOffset()); - EXPECT_EQ(std::numeric_limits<unsigned>::max(), underline.EndOffset()); -} - -TEST(CompositionUnderlineTest, LastCharEndBeforeStart) { - CompositionUnderline underline = - CreateCompositionUnderline(std::numeric_limits<unsigned>::max(), - std::numeric_limits<unsigned>::max() - 1); - EXPECT_EQ(std::numeric_limits<unsigned>::max() - 1, underline.StartOffset()); - EXPECT_EQ(std::numeric_limits<unsigned>::max(), underline.EndOffset()); -} - -TEST(CompositionUnderlineTest, LastCharEndBeforeStartZeroEnd) { - CompositionUnderline underline = - CreateCompositionUnderline(std::numeric_limits<unsigned>::max(), 0); - EXPECT_EQ(std::numeric_limits<unsigned>::max() - 1, underline.StartOffset()); - EXPECT_EQ(std::numeric_limits<unsigned>::max(), underline.EndOffset()); -} - -} // namespace -} // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/ImeTextSpan.cpp b/third_party/WebKit/Source/core/editing/ImeTextSpan.cpp new file mode 100644 index 0000000..e337a2e --- /dev/null +++ b/third_party/WebKit/Source/core/editing/ImeTextSpan.cpp
@@ -0,0 +1,33 @@ +// 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 "core/editing/ImeTextSpan.h" + +#include <algorithm> +#include "public/web/WebImeTextSpan.h" + +namespace blink { + +ImeTextSpan::ImeTextSpan(unsigned start_offset, + unsigned end_offset, + const Color& color, + bool thick, + const Color& background_color) + : color_(color), thick_(thick), background_color_(background_color) { + // Sanitize offsets by ensuring a valid range corresponding to the last + // possible position. + // TODO(wkorman): Consider replacing with DCHECK_LT(startOffset, endOffset). + start_offset_ = + std::min(start_offset, std::numeric_limits<unsigned>::max() - 1u); + end_offset_ = std::max(start_offset_ + 1u, end_offset); +} + +ImeTextSpan::ImeTextSpan(const WebImeTextSpan& ime_text_span) + : ImeTextSpan(ime_text_span.start_offset, + ime_text_span.end_offset, + Color(ime_text_span.color), + ime_text_span.thick, + Color(ime_text_span.background_color)) {} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/CompositionUnderline.h b/third_party/WebKit/Source/core/editing/ImeTextSpan.h similarity index 81% rename from third_party/WebKit/Source/core/editing/CompositionUnderline.h rename to third_party/WebKit/Source/core/editing/ImeTextSpan.h index cb7d7b4ec..8f50f3b 100644 --- a/third_party/WebKit/Source/core/editing/CompositionUnderline.h +++ b/third_party/WebKit/Source/core/editing/ImeTextSpan.h
@@ -23,8 +23,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CompositionUnderline_h -#define CompositionUnderline_h +#ifndef ImeTextSpan_h +#define ImeTextSpan_h #include "core/CoreExport.h" #include "platform/graphics/Color.h" @@ -32,19 +32,19 @@ namespace blink { -struct WebCompositionUnderline; +struct WebImeTextSpan; -class CORE_EXPORT CompositionUnderline { +class CORE_EXPORT ImeTextSpan { DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); public: - CompositionUnderline(unsigned start_offset, - unsigned end_offset, - const Color&, - bool thick, - const Color& background_color); + ImeTextSpan(unsigned start_offset, + unsigned end_offset, + const Color&, + bool thick, + const Color& background_color); - CompositionUnderline(const WebCompositionUnderline&); + ImeTextSpan(const WebImeTextSpan&); unsigned StartOffset() const { return start_offset_; } unsigned EndOffset() const { return end_offset_; } @@ -62,4 +62,4 @@ } // namespace blink -#endif // CompositionUnderline_h +#endif // ImeTextSpan_h
diff --git a/third_party/WebKit/Source/core/editing/ImeTextSpanTest.cpp b/third_party/WebKit/Source/core/editing/ImeTextSpanTest.cpp new file mode 100644 index 0000000..858b055 --- /dev/null +++ b/third_party/WebKit/Source/core/editing/ImeTextSpanTest.cpp
@@ -0,0 +1,74 @@ +// 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 "core/editing/ImeTextSpan.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace blink { +namespace { + +ImeTextSpan CreateImeTextSpan(unsigned start_offset, unsigned end_offset) { + return ImeTextSpan(start_offset, end_offset, Color::kTransparent, false, + Color::kTransparent); +} + +TEST(ImeTextSpanTest, OneChar) { + ImeTextSpan ime_text_span = CreateImeTextSpan(0, 1); + EXPECT_EQ(0u, ime_text_span.StartOffset()); + EXPECT_EQ(1u, ime_text_span.EndOffset()); +} + +TEST(ImeTextSpanTest, MultiChar) { + ImeTextSpan ime_text_span = CreateImeTextSpan(0, 5); + EXPECT_EQ(0u, ime_text_span.StartOffset()); + EXPECT_EQ(5u, ime_text_span.EndOffset()); +} + +TEST(ImeTextSpanTest, ZeroLength) { + ImeTextSpan ime_text_span = CreateImeTextSpan(0, 0); + EXPECT_EQ(0u, ime_text_span.StartOffset()); + EXPECT_EQ(1u, ime_text_span.EndOffset()); +} + +TEST(ImeTextSpanTest, ZeroLengthNonZeroStart) { + ImeTextSpan ime_text_span = CreateImeTextSpan(3, 3); + EXPECT_EQ(3u, ime_text_span.StartOffset()); + EXPECT_EQ(4u, ime_text_span.EndOffset()); +} + +TEST(ImeTextSpanTest, EndBeforeStart) { + ImeTextSpan ime_text_span = CreateImeTextSpan(1, 0); + EXPECT_EQ(1u, ime_text_span.StartOffset()); + EXPECT_EQ(2u, ime_text_span.EndOffset()); +} + +TEST(ImeTextSpanTest, LastChar) { + ImeTextSpan ime_text_span = + CreateImeTextSpan(std::numeric_limits<unsigned>::max() - 1, + std::numeric_limits<unsigned>::max()); + EXPECT_EQ(std::numeric_limits<unsigned>::max() - 1, + ime_text_span.StartOffset()); + EXPECT_EQ(std::numeric_limits<unsigned>::max(), ime_text_span.EndOffset()); +} + +TEST(ImeTextSpanTest, LastCharEndBeforeStart) { + ImeTextSpan ime_text_span = + CreateImeTextSpan(std::numeric_limits<unsigned>::max(), + std::numeric_limits<unsigned>::max() - 1); + EXPECT_EQ(std::numeric_limits<unsigned>::max() - 1, + ime_text_span.StartOffset()); + EXPECT_EQ(std::numeric_limits<unsigned>::max(), ime_text_span.EndOffset()); +} + +TEST(ImeTextSpanTest, LastCharEndBeforeStartZeroEnd) { + ImeTextSpan ime_text_span = + CreateImeTextSpan(std::numeric_limits<unsigned>::max(), 0); + EXPECT_EQ(std::numeric_limits<unsigned>::max() - 1, + ime_text_span.StartOffset()); + EXPECT_EQ(std::numeric_limits<unsigned>::max(), ime_text_span.EndOffset()); +} + +} // namespace +} // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/CompositionUnderlineVectorBuilder.cpp b/third_party/WebKit/Source/core/editing/ImeTextSpanVectorBuilder.cpp similarity index 84% rename from third_party/WebKit/Source/core/editing/CompositionUnderlineVectorBuilder.cpp rename to third_party/WebKit/Source/core/editing/ImeTextSpanVectorBuilder.cpp index cccfebbb..d312a263 100644 --- a/third_party/WebKit/Source/core/editing/CompositionUnderlineVectorBuilder.cpp +++ b/third_party/WebKit/Source/core/editing/ImeTextSpanVectorBuilder.cpp
@@ -28,17 +28,17 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "core/editing/CompositionUnderlineVectorBuilder.h" +#include "core/editing/ImeTextSpanVectorBuilder.h" namespace blink { -Vector<CompositionUnderline> CompositionUnderlineVectorBuilder::Build( - const WebVector<WebCompositionUnderline>& underlines) { - Vector<CompositionUnderline> result; - size_t size = underlines.size(); +Vector<ImeTextSpan> ImeTextSpanVectorBuilder::Build( + const WebVector<WebImeTextSpan>& ime_text_spans) { + Vector<ImeTextSpan> result; + size_t size = ime_text_spans.size(); result.ReserveCapacity(size); for (size_t i = 0; i < size; ++i) - result.push_back(underlines[i]); + result.push_back(ime_text_spans[i]); return result; }
diff --git a/third_party/WebKit/Source/core/editing/CompositionUnderlineVectorBuilder.h b/third_party/WebKit/Source/core/editing/ImeTextSpanVectorBuilder.h similarity index 77% rename from third_party/WebKit/Source/core/editing/CompositionUnderlineVectorBuilder.h rename to third_party/WebKit/Source/core/editing/ImeTextSpanVectorBuilder.h index 9b44790..fc658ec 100644 --- a/third_party/WebKit/Source/core/editing/CompositionUnderlineVectorBuilder.h +++ b/third_party/WebKit/Source/core/editing/ImeTextSpanVectorBuilder.h
@@ -28,26 +28,26 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CompositionUnderlineVectorBuilder_h -#define CompositionUnderlineVectorBuilder_h +#ifndef ImeTextSpanVectorBuilder_h +#define ImeTextSpanVectorBuilder_h #include "core/CoreExport.h" -#include "core/editing/CompositionUnderline.h" +#include "core/editing/ImeTextSpan.h" #include "platform/wtf/Vector.h" #include "public/platform/WebVector.h" -#include "public/web/WebCompositionUnderline.h" +#include "public/web/WebImeTextSpan.h" namespace blink { -// This class is used for converting from WebVector<WebCompositionUnderline> -// to Vector<CompositionUnderline>. +// This class is used for converting from WebVector<WebImeTextSpan> +// to Vector<ImeTextSpan>. -class CompositionUnderlineVectorBuilder { - STATIC_ONLY(CompositionUnderlineVectorBuilder); +class ImeTextSpanVectorBuilder { + STATIC_ONLY(ImeTextSpanVectorBuilder); public: - CORE_EXPORT static Vector<CompositionUnderline> Build( - const WebVector<WebCompositionUnderline>&); + CORE_EXPORT static Vector<ImeTextSpan> Build( + const WebVector<WebImeTextSpan>&); }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/InputMethodController.cpp b/third_party/WebKit/Source/core/editing/InputMethodController.cpp index 853f3d59..c78c81c 100644 --- a/third_party/WebKit/Source/core/editing/InputMethodController.cpp +++ b/third_party/WebKit/Source/core/editing/InputMethodController.cpp
@@ -432,14 +432,14 @@ bool InputMethodController::CommitText( const String& text, - const Vector<CompositionUnderline>& underlines, + const Vector<ImeTextSpan>& ime_text_spans, int relative_caret_position) { if (HasComposition()) { return ReplaceCompositionAndMoveCaret(text, relative_caret_position, - underlines); + ime_text_spans); } - return InsertTextAndMoveCaret(text, relative_caret_position, underlines); + return InsertTextAndMoveCaret(text, relative_caret_position, ime_text_spans); } bool InputMethodController::ReplaceComposition(const String& text) { @@ -480,32 +480,34 @@ return text_start + text_length + relative_caret_position; } -void InputMethodController::AddCompositionUnderlines( - const Vector<CompositionUnderline>& underlines, +void InputMethodController::AddImeTextSpans( + const Vector<ImeTextSpan>& ime_text_spans, ContainerNode* base_element, unsigned offset_in_plain_chars) { - for (const auto& underline : underlines) { - unsigned underline_start = offset_in_plain_chars + underline.StartOffset(); - unsigned underline_end = offset_in_plain_chars + underline.EndOffset(); + for (const auto& ime_text_span : ime_text_spans) { + unsigned ime_text_span_start = + offset_in_plain_chars + ime_text_span.StartOffset(); + unsigned ime_text_span_end = + offset_in_plain_chars + ime_text_span.EndOffset(); EphemeralRange ephemeral_line_range = - PlainTextRange(underline_start, underline_end) + PlainTextRange(ime_text_span_start, ime_text_span_end) .CreateRange(*base_element); if (ephemeral_line_range.IsNull()) continue; GetDocument().Markers().AddCompositionMarker( - ephemeral_line_range, underline.GetColor(), - underline.Thick() ? StyleableMarker::Thickness::kThick - : StyleableMarker::Thickness::kThin, - underline.BackgroundColor()); + ephemeral_line_range, ime_text_span.GetColor(), + ime_text_span.Thick() ? StyleableMarker::Thickness::kThick + : StyleableMarker::Thickness::kThin, + ime_text_span.BackgroundColor()); } } bool InputMethodController::ReplaceCompositionAndMoveCaret( const String& text, int relative_caret_position, - const Vector<CompositionUnderline>& underlines) { + const Vector<ImeTextSpan>& ime_text_spans) { Element* root_editable_element = GetFrame() .Selection() @@ -527,7 +529,7 @@ // needs to be audited. see http://crbug.com/590369 for more details. GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets(); - AddCompositionUnderlines(underlines, root_editable_element, text_start); + AddImeTextSpans(ime_text_spans, root_editable_element, text_start); int absolute_caret_position = ComputeAbsoluteCaretPosition( text_start, text.length(), relative_caret_position); @@ -545,7 +547,7 @@ bool InputMethodController::InsertTextAndMoveCaret( const String& text, int relative_caret_position, - const Vector<CompositionUnderline>& underlines) { + const Vector<ImeTextSpan>& ime_text_spans) { PlainTextRange selection_range = GetSelectionOffsets(); if (selection_range.IsNull()) return false; @@ -559,7 +561,7 @@ .ComputeVisibleSelectionInDOMTreeDeprecated() .RootEditableElement(); if (root_editable_element) { - AddCompositionUnderlines(underlines, root_editable_element, text_start); + AddImeTextSpans(ime_text_spans, root_editable_element, text_start); } int absolute_caret_position = ComputeAbsoluteCaretPosition( @@ -598,7 +600,7 @@ void InputMethodController::SetComposition( const String& text, - const Vector<CompositionUnderline>& underlines, + const Vector<ImeTextSpan>& ime_text_spans, int selection_start, int selection_end) { Editor::RevealSelectionScope reveal_selection_scope(&GetEditor()); @@ -719,7 +721,7 @@ // We shouldn't close typing in the middle of setComposition. SetEditableSelectionOffsets(selected_range, TypingContinuation::kContinue); - if (underlines.IsEmpty()) { + if (ime_text_spans.IsEmpty()) { GetDocument().Markers().AddCompositionMarker( EphemeralRange(composition_range_), Color::kBlack, StyleableMarker::Thickness::kThin, @@ -729,8 +731,8 @@ const PlainTextRange composition_plain_text_range = PlainTextRange::Create(*base_node->parentNode(), *composition_range_); - AddCompositionUnderlines(underlines, base_node->parentNode(), - composition_plain_text_range.Start()); + AddImeTextSpans(ime_text_spans, base_node->parentNode(), + composition_plain_text_range.Start()); } PlainTextRange InputMethodController::CreateSelectionRangeForSetComposition( @@ -745,7 +747,7 @@ } void InputMethodController::SetCompositionFromExistingText( - const Vector<CompositionUnderline>& underlines, + const Vector<ImeTextSpan>& ime_text_spans, unsigned composition_start, unsigned composition_end) { Element* editable = GetFrame() @@ -772,7 +774,7 @@ Clear(); - AddCompositionUnderlines(underlines, editable, composition_start); + AddImeTextSpans(ime_text_spans, editable, composition_start); has_composition_ = true; if (!composition_range_)
diff --git a/third_party/WebKit/Source/core/editing/InputMethodController.h b/third_party/WebKit/Source/core/editing/InputMethodController.h index 88f1f25..40e62b2c 100644 --- a/third_party/WebKit/Source/core/editing/InputMethodController.h +++ b/third_party/WebKit/Source/core/editing/InputMethodController.h
@@ -29,8 +29,8 @@ #include "base/gtest_prod_util.h" #include "core/CoreExport.h" #include "core/dom/SynchronousMutationObserver.h" -#include "core/editing/CompositionUnderline.h" #include "core/editing/EphemeralRange.h" +#include "core/editing/ImeTextSpan.h" #include "core/editing/PlainTextRange.h" #include "platform/heap/Handle.h" #include "platform/wtf/Vector.h" @@ -63,10 +63,10 @@ // international text input composition bool HasComposition() const; void SetComposition(const String& text, - const Vector<CompositionUnderline>& underlines, + const Vector<ImeTextSpan>& ime_text_spans, int selection_start, int selection_end); - void SetCompositionFromExistingText(const Vector<CompositionUnderline>& text, + void SetCompositionFromExistingText(const Vector<ImeTextSpan>& ime_text_spans, unsigned composition_start, unsigned composition_end); @@ -74,7 +74,7 @@ // changes the selection according to relativeCaretPosition, which is // relative to the end of the inserting text. bool CommitText(const String& text, - const Vector<CompositionUnderline>& underlines, + const Vector<ImeTextSpan>& ime_text_spans, int relative_caret_position); // Inserts ongoing composing text; changes the selection to the end of @@ -134,14 +134,14 @@ // Returns true if selection offsets were successfully set. bool SetSelectionOffsets(const PlainTextRange&); - void AddCompositionUnderlines(const Vector<CompositionUnderline>& underlines, - ContainerNode* base_element, - unsigned offset_in_plain_chars); + void AddImeTextSpans(const Vector<ImeTextSpan>& ime_text_spans, + ContainerNode* base_element, + unsigned offset_in_plain_chars); bool InsertText(const String&); bool InsertTextAndMoveCaret(const String&, int relative_caret_position, - const Vector<CompositionUnderline>& underlines); + const Vector<ImeTextSpan>& ime_text_spans); // Inserts the given text string in the place of the existing composition. // Returns true if did replace. @@ -151,7 +151,7 @@ bool ReplaceCompositionAndMoveCaret( const String&, int relative_caret_position, - const Vector<CompositionUnderline>& underlines); + const Vector<ImeTextSpan>& ime_text_spans); // Returns true if moved caret successfully. bool MoveCaret(int new_caret_position);
diff --git a/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp b/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp index c368cc3..f9b5775 100644 --- a/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp +++ b/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp
@@ -171,9 +171,9 @@ Element* div = InsertHTMLElement( "<div id='sample' contenteditable>hello world</div>", "sample"); - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); - Controller().SetCompositionFromExistingText(underlines, 0, 5); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(0, 5, Color(255, 0, 0), false, 0)); + Controller().SetCompositionFromExistingText(ime_text_spans, 0, 5); Range* range = Controller().CompositionRange(); EXPECT_EQ(0u, range->startOffset()); @@ -189,8 +189,8 @@ Element* div = InsertHTMLElement( "<div id='sample' contenteditable>🏆</div>", "sample"); - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(0, 2, Color(255, 0, 0), false, 0)); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(0, 2, Color(255, 0, 0), false, 0)); GetDocument().UpdateStyleAndLayout(); Controller().SetEditableSelectionOffsets(PlainTextRange(2, 2)); @@ -205,25 +205,25 @@ .Extent() .ComputeOffsetInContainerNode()); - Controller().SetComposition(String("a"), underlines, 1, 1); + Controller().SetComposition(String("a"), ime_text_spans, 1, 1); EXPECT_STREQ("\xF0\x9F\x8F\x86\x61", div->innerText().Utf8().data()); - Controller().SetComposition(String("ab"), underlines, 2, 2); + Controller().SetComposition(String("ab"), ime_text_spans, 2, 2); EXPECT_STREQ("\xF0\x9F\x8F\x86\x61\x62", div->innerText().Utf8().data()); } TEST_F(InputMethodControllerTest, SetCompositionWithGraphemeCluster) { InsertHTMLElement("<div id='sample' contenteditable></div>", "sample"); - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(6, 6, Color(255, 0, 0), false, 0)); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(6, 6, Color(255, 0, 0), false, 0)); GetDocument().UpdateStyleAndLayout(); // UTF16 = 0x0939 0x0947 0x0932 0x0932. Note that 0x0932 0x0932 is a grapheme // cluster. Controller().SetComposition( String::FromUTF8("\xE0\xA4\xB9\xE0\xA5\x87\xE0\xA4\xB2\xE0\xA4\xB2"), - underlines, 4, 4); + ime_text_spans, 4, 4); EXPECT_EQ(4u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(4u, Controller().GetSelectionOffsets().End()); @@ -231,7 +231,7 @@ Controller().SetComposition( String::FromUTF8("\xE0\xA4\xB9\xE0\xA5\x87\xE0\xA4\xB2\xE0\xA5\x8D\xE0" "\xA4\xB2\xE0\xA5\x8B"), - underlines, 6, 6); + ime_text_spans, 6, 6); EXPECT_EQ(6u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(6u, Controller().GetSelectionOffsets().End()); } @@ -241,9 +241,8 @@ Element* div = InsertHTMLElement("<div id='sample' contenteditable></div>", "sample"); - Vector<CompositionUnderline> underlines; - underlines.push_back( - CompositionUnderline(12, 12, Color(255, 0, 0), false, 0)); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(12, 12, Color(255, 0, 0), false, 0)); GetDocument().UpdateStyleAndLayout(); // UTF16 = 0x0939 0x0947 0x0932 0x094D 0x0932 0x094B. 0x0939 0x0947 0x0932 is @@ -251,9 +250,9 @@ Controller().CommitText( String::FromUTF8("\xE0\xA4\xB9\xE0\xA5\x87\xE0\xA4\xB2\xE0\xA5\x8D\xE0" "\xA4\xB2\xE0\xA5\x8B"), - underlines, 1); - Controller().CommitText("\nab ", underlines, 1); - Controller().SetComposition(String("c"), underlines, 1, 1); + ime_text_spans, 1); + Controller().CommitText("\nab ", ime_text_spans, 1); + Controller().SetComposition(String("c"), ime_text_spans, 1, 1); EXPECT_STREQ( "\xE0\xA4\xB9\xE0\xA5\x87\xE0\xA4\xB2\xE0\xA5\x8D\xE0\xA4\xB2\xE0\xA5" "\x8B\nab c", @@ -261,7 +260,7 @@ EXPECT_EQ(11u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(11u, Controller().GetSelectionOffsets().End()); - Controller().SetComposition(String("cd"), underlines, 2, 2); + Controller().SetComposition(String("cd"), ime_text_spans, 2, 2); EXPECT_STREQ( "\xE0\xA4\xB9\xE0\xA5\x87\xE0\xA4\xB2\xE0\xA5\x8D\xE0\xA4\xB2\xE0\xA5" "\x8B\nab cd", @@ -276,26 +275,26 @@ "contenteditable>abc1<b>2</b>34567<b>8</b>9d<b>e</b>f</div>", "sample"); - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(3, 12, Color(255, 0, 0), false, 0)); - Controller().SetCompositionFromExistingText(underlines, 3, 12); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(3, 12, Color(255, 0, 0), false, 0)); + Controller().SetCompositionFromExistingText(ime_text_spans, 3, 12); // Subtract a character. - Controller().SetComposition(String("12345789"), underlines, 8, 8); + Controller().SetComposition(String("12345789"), ime_text_spans, 8, 8); EXPECT_STREQ("abc1<b>2</b>3457<b>8</b>9d<b>e</b>f", div->innerHTML().Utf8().data()); EXPECT_EQ(11u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(11u, Controller().GetSelectionOffsets().End()); // Append a character. - Controller().SetComposition(String("123456789"), underlines, 9, 9); + Controller().SetComposition(String("123456789"), ime_text_spans, 9, 9); EXPECT_STREQ("abc1<b>2</b>34567<b>8</b>9d<b>e</b>f", div->innerHTML().Utf8().data()); EXPECT_EQ(12u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(12u, Controller().GetSelectionOffsets().End()); // Subtract and append characters. - Controller().SetComposition(String("123hello789"), underlines, 11, 11); + Controller().SetComposition(String("123hello789"), ime_text_spans, 11, 11); EXPECT_STREQ("abc1<b>2</b>3hello7<b>8</b>9d<b>e</b>f", div->innerHTML().Utf8().data()); } @@ -305,19 +304,19 @@ Element* div = InsertHTMLElement( "<div id='sample' contenteditable><b>🏠</b></div>", "sample"); - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(0, 2, Color(255, 0, 0), false, 0)); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(0, 2, Color(255, 0, 0), false, 0)); - Controller().SetCompositionFromExistingText(underlines, 0, 2); + Controller().SetCompositionFromExistingText(ime_text_spans, 0, 2); // 0xF0 0x9F 0x8F 0xAB is also an emoji character, with the same leading // surrogate pair to the previous one. - Controller().SetComposition(String::FromUTF8("\xF0\x9F\x8F\xAB"), underlines, - 2, 2); + Controller().SetComposition(String::FromUTF8("\xF0\x9F\x8F\xAB"), + ime_text_spans, 2, 2); EXPECT_STREQ("<b>\xF0\x9F\x8F\xAB</b>", div->innerHTML().Utf8().data()); - Controller().SetComposition(String::FromUTF8("\xF0\x9F\x8F\xA0"), underlines, - 2, 2); + Controller().SetComposition(String::FromUTF8("\xF0\x9F\x8F\xA0"), + ime_text_spans, 2, 2); EXPECT_STREQ("<b>\xF0\x9F\x8F\xA0</b>", div->innerHTML().Utf8().data()); } @@ -329,19 +328,19 @@ Element* div = InsertHTMLElement( "<div id='sample' contenteditable><b>ః</b></div>", "sample"); - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(0, 2, Color(255, 0, 0), false, 0)); - Controller().SetCompositionFromExistingText(underlines, 0, 1); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(0, 2, Color(255, 0, 0), false, 0)); + Controller().SetCompositionFromExistingText(ime_text_spans, 0, 1); // 0xE0 0xB0 0x83 0xE0 0xB0 0x83, a telugu character with 2 code points in // 1 grapheme cluster. Controller().SetComposition(String::FromUTF8("\xE0\xB0\x83\xE0\xB0\x83"), - underlines, 2, 2); + ime_text_spans, 2, 2); EXPECT_STREQ("<b>\xE0\xB0\x83\xE0\xB0\x83</b>", div->innerHTML().Utf8().data()); - Controller().SetComposition(String::FromUTF8("\xE0\xB0\x83"), underlines, 1, - 1); + Controller().SetComposition(String::FromUTF8("\xE0\xB0\x83"), ime_text_spans, + 1, 1); EXPECT_STREQ("<b>\xE0\xB0\x83</b>", div->innerHTML().Utf8().data()); } @@ -351,11 +350,11 @@ "contenteditable>abc1<b>2</b>34567<b>8</b>9</div>", "sample"); - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(3, 12, Color(255, 0, 0), false, 0)); - Controller().SetCompositionFromExistingText(underlines, 3, 12); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(3, 12, Color(255, 0, 0), false, 0)); + Controller().SetCompositionFromExistingText(ime_text_spans, 3, 12); - Controller().SetComposition(String("123hello789"), underlines, 11, 11); + Controller().SetComposition(String("123hello789"), ime_text_spans, 11, 11); EXPECT_STREQ("abc1<b>2</b>3hello7<b>8</b>9", div->innerHTML().Utf8().data()); Controller().FinishComposingText(InputMethodController::kKeepSelection); @@ -368,21 +367,21 @@ "contenteditable>abc1<b>2</b>34567<b>8</b>9</div>", "sample"); - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(3, 12, Color(255, 0, 0), false, 0)); - Controller().SetCompositionFromExistingText(underlines, 3, 12); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(3, 12, Color(255, 0, 0), false, 0)); + Controller().SetCompositionFromExistingText(ime_text_spans, 3, 12); - Controller().CommitText(String("123789"), underlines, 0); + Controller().CommitText(String("123789"), ime_text_spans, 0); EXPECT_STREQ("abc1<b>2</b>37<b>8</b>9", div->innerHTML().Utf8().data()); } TEST_F(InputMethodControllerTest, InsertTextWithNewLine) { Element* div = InsertHTMLElement("<div id='sample' contenteditable></div>", "sample"); - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(0, 11, Color(255, 0, 0), false, 0)); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(0, 11, Color(255, 0, 0), false, 0)); - Controller().CommitText(String("hello\nworld"), underlines, 0); + Controller().CommitText(String("hello\nworld"), ime_text_spans, 0); EXPECT_STREQ("hello<div>world</div>", div->innerHTML().Utf8().data()); } @@ -390,12 +389,12 @@ Element* div = InsertHTMLElement("<div id='sample' contenteditable></div>", "sample"); - Vector<CompositionUnderline> underlines; - Controller().CommitText("a", underlines, 0); - Controller().SetComposition("bcd", underlines, 0, 2); + Vector<ImeTextSpan> ime_text_spans; + Controller().CommitText("a", ime_text_spans, 0); + Controller().SetComposition("bcd", ime_text_spans, 0, 2); EXPECT_STREQ("abcd", div->innerHTML().Utf8().data()); - Controller().CommitText(String("bcd\nefgh\nijkl"), underlines, 0); + Controller().CommitText(String("bcd\nefgh\nijkl"), ime_text_spans, 0); EXPECT_STREQ("abcd<div>efgh</div><div>ijkl</div>", div->innerHTML().Utf8().data()); } @@ -404,9 +403,9 @@ InsertHTMLElement("<div id='sample' contenteditable>hello world</div>", "sample"); - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); - Controller().SetCompositionFromExistingText(underlines, 0, 5); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(0, 5, Color(255, 0, 0), false, 0)); + Controller().SetCompositionFromExistingText(ime_text_spans, 0, 5); Controller().FinishComposingText(InputMethodController::kKeepSelection); EXPECT_EQ(0, GetFrame() @@ -439,11 +438,11 @@ Controller().ExtendSelectionAndDelete(1, 0); EXPECT_STREQ("foo", input->value().Utf8().data()); - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(0, 3, Color(255, 0, 0), false, 0)); - Controller().SetCompositionFromExistingText(underlines, 0, 3); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(0, 3, Color(255, 0, 0), false, 0)); + Controller().SetCompositionFromExistingText(ime_text_spans, 0, 3); - Controller().SetComposition(String(""), underlines, 0, 3); + Controller().SetComposition(String(""), ime_text_spans, 0, 3); EXPECT_STREQ("", input->value().Utf8().data()); } @@ -455,9 +454,9 @@ Element* div = InsertHTMLElement( "<div id='sample' contenteditable>\nhello world</div>", "sample"); - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); - Controller().SetCompositionFromExistingText(underlines, 0, 5); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(0, 5, Color(255, 0, 0), false, 0)); + Controller().SetCompositionFromExistingText(ime_text_spans, 0, 5); Range* range = Controller().CompositionRange(); EXPECT_EQ(1u, range->startOffset()); @@ -472,9 +471,9 @@ SetCompositionFromExistingTextWithInvalidOffsets) { InsertHTMLElement("<div id='sample' contenteditable>test</div>", "sample"); - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(7, 8, Color(255, 0, 0), false, 0)); - Controller().SetCompositionFromExistingText(underlines, 7, 8); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(7, 8, Color(255, 0, 0), false, 0)); + Controller().SetCompositionFromExistingText(ime_text_spans, 7, 8); EXPECT_FALSE(Controller().CompositionRange()); } @@ -483,9 +482,9 @@ HTMLInputElement* input = toHTMLInputElement(InsertHTMLElement( "<input id='sample' type='password' size='24'>", "sample")); - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); - Controller().SetComposition("foo", underlines, 0, 3); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(0, 5, Color(255, 0, 0), false, 0)); + Controller().SetComposition("foo", ime_text_spans, 0, 3); Controller().FinishComposingText(InputMethodController::kKeepSelection); EXPECT_STREQ("foo", input->value().Utf8().data()); @@ -936,47 +935,47 @@ EXPECT_EQ(2u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(2u, Controller().GetSelectionOffsets().End()); - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(0, 2, Color(255, 0, 0), false, 0)); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(0, 2, Color(255, 0, 0), false, 0)); // The caret exceeds left boundary. // "*heABllo", where * stands for caret. - Controller().SetComposition("AB", underlines, -100, -100); + Controller().SetComposition("AB", ime_text_spans, -100, -100); EXPECT_STREQ("heABllo", input->value().Utf8().data()); EXPECT_EQ(0u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(0u, Controller().GetSelectionOffsets().End()); // The caret is on left boundary. // "*heABllo". - Controller().SetComposition("AB", underlines, -2, -2); + Controller().SetComposition("AB", ime_text_spans, -2, -2); EXPECT_STREQ("heABllo", input->value().Utf8().data()); EXPECT_EQ(0u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(0u, Controller().GetSelectionOffsets().End()); // The caret is before the composing text. // "he*ABllo". - Controller().SetComposition("AB", underlines, 0, 0); + Controller().SetComposition("AB", ime_text_spans, 0, 0); EXPECT_STREQ("heABllo", input->value().Utf8().data()); EXPECT_EQ(2u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(2u, Controller().GetSelectionOffsets().End()); // The caret is after the composing text. // "heAB*llo". - Controller().SetComposition("AB", underlines, 2, 2); + Controller().SetComposition("AB", ime_text_spans, 2, 2); EXPECT_STREQ("heABllo", input->value().Utf8().data()); EXPECT_EQ(4u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(4u, Controller().GetSelectionOffsets().End()); // The caret is on right boundary. // "heABllo*". - Controller().SetComposition("AB", underlines, 5, 5); + Controller().SetComposition("AB", ime_text_spans, 5, 5); EXPECT_STREQ("heABllo", input->value().Utf8().data()); EXPECT_EQ(7u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(7u, Controller().GetSelectionOffsets().End()); // The caret exceeds right boundary. // "heABllo*". - Controller().SetComposition("AB", underlines, 100, 100); + Controller().SetComposition("AB", ime_text_spans, 100, 100); EXPECT_STREQ("heABllo", input->value().Utf8().data()); EXPECT_EQ(7u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(7u, Controller().GetSelectionOffsets().End()); @@ -1000,82 +999,82 @@ EXPECT_EQ(17u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(17u, Controller().GetSelectionOffsets().End()); - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(0, 2, Color(255, 0, 0), false, 0)); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(0, 2, Color(255, 0, 0), false, 0)); // The caret exceeds left boundary. // "*hello\nworld\n01234AB56789", where * stands for caret. - Controller().SetComposition("AB", underlines, -100, -100); + Controller().SetComposition("AB", ime_text_spans, -100, -100); EXPECT_STREQ("hello\nworld\n01234AB56789", div->innerText().Utf8().data()); EXPECT_EQ(0u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(0u, Controller().GetSelectionOffsets().End()); // The caret is on left boundary. // "*hello\nworld\n01234AB56789". - Controller().SetComposition("AB", underlines, -17, -17); + Controller().SetComposition("AB", ime_text_spans, -17, -17); EXPECT_STREQ("hello\nworld\n01234AB56789", div->innerText().Utf8().data()); EXPECT_EQ(0u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(0u, Controller().GetSelectionOffsets().End()); // The caret is in the 1st node. // "he*llo\nworld\n01234AB56789". - Controller().SetComposition("AB", underlines, -15, -15); + Controller().SetComposition("AB", ime_text_spans, -15, -15); EXPECT_STREQ("hello\nworld\n01234AB56789", div->innerText().Utf8().data()); EXPECT_EQ(2u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(2u, Controller().GetSelectionOffsets().End()); // The caret is on right boundary of the 1st node. // "hello*\nworld\n01234AB56789". - Controller().SetComposition("AB", underlines, -12, -12); + Controller().SetComposition("AB", ime_text_spans, -12, -12); EXPECT_STREQ("hello\nworld\n01234AB56789", div->innerText().Utf8().data()); EXPECT_EQ(5u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(5u, Controller().GetSelectionOffsets().End()); // The caret is on right boundary of the 2nd node. // "hello\n*world\n01234AB56789". - Controller().SetComposition("AB", underlines, -11, -11); + Controller().SetComposition("AB", ime_text_spans, -11, -11); EXPECT_STREQ("hello\nworld\n01234AB56789", div->innerText().Utf8().data()); EXPECT_EQ(6u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(6u, Controller().GetSelectionOffsets().End()); // The caret is on right boundary of the 3rd node. // "hello\nworld*\n01234AB56789". - Controller().SetComposition("AB", underlines, -6, -6); + Controller().SetComposition("AB", ime_text_spans, -6, -6); EXPECT_STREQ("hello\nworld\n01234AB56789", div->innerText().Utf8().data()); EXPECT_EQ(11u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(11u, Controller().GetSelectionOffsets().End()); // The caret is on right boundary of the 4th node. // "hello\nworld\n*01234AB56789". - Controller().SetComposition("AB", underlines, -5, -5); + Controller().SetComposition("AB", ime_text_spans, -5, -5); EXPECT_STREQ("hello\nworld\n01234AB56789", div->innerText().Utf8().data()); EXPECT_EQ(12u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(12u, Controller().GetSelectionOffsets().End()); // The caret is before the composing text. // "hello\nworld\n01234*AB56789". - Controller().SetComposition("AB", underlines, 0, 0); + Controller().SetComposition("AB", ime_text_spans, 0, 0); EXPECT_STREQ("hello\nworld\n01234AB56789", div->innerText().Utf8().data()); EXPECT_EQ(17u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(17u, Controller().GetSelectionOffsets().End()); // The caret is after the composing text. // "hello\nworld\n01234AB*56789". - Controller().SetComposition("AB", underlines, 2, 2); + Controller().SetComposition("AB", ime_text_spans, 2, 2); EXPECT_STREQ("hello\nworld\n01234AB56789", div->innerText().Utf8().data()); EXPECT_EQ(19u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(19u, Controller().GetSelectionOffsets().End()); // The caret is on right boundary. // "hello\nworld\n01234AB56789*". - Controller().SetComposition("AB", underlines, 7, 7); + Controller().SetComposition("AB", ime_text_spans, 7, 7); EXPECT_STREQ("hello\nworld\n01234AB56789", div->innerText().Utf8().data()); EXPECT_EQ(24u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(24u, Controller().GetSelectionOffsets().End()); // The caret exceeds right boundary. // "hello\nworld\n01234AB56789*". - Controller().SetComposition("AB", underlines, 100, 100); + Controller().SetComposition("AB", ime_text_spans, 100, 100); EXPECT_STREQ("hello\nworld\n01234AB56789", div->innerText().Utf8().data()); EXPECT_EQ(24u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(24u, Controller().GetSelectionOffsets().End()); @@ -1090,20 +1089,20 @@ EXPECT_EQ(2u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(2u, Controller().GetSelectionOffsets().End()); - Vector<CompositionUnderline> underlines0; - underlines0.push_back(CompositionUnderline(0, 0, Color(255, 0, 0), false, 0)); - Vector<CompositionUnderline> underlines2; - underlines2.push_back(CompositionUnderline(0, 2, Color(255, 0, 0), false, 0)); + Vector<ImeTextSpan> ime_text_spans0; + ime_text_spans0.push_back(ImeTextSpan(0, 0, Color(255, 0, 0), false, 0)); + Vector<ImeTextSpan> ime_text_spans2; + ime_text_spans2.push_back(ImeTextSpan(0, 2, Color(255, 0, 0), false, 0)); - Controller().SetComposition("AB", underlines2, 2, 2); + Controller().SetComposition("AB", ime_text_spans2, 2, 2); // With previous composition. - Controller().SetComposition("", underlines0, 2, 2); + Controller().SetComposition("", ime_text_spans0, 2, 2); EXPECT_STREQ("hello", div->innerText().Utf8().data()); EXPECT_EQ(4u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(4u, Controller().GetSelectionOffsets().End()); // Without previous composition. - Controller().SetComposition("", underlines0, -1, -1); + Controller().SetComposition("", ime_text_spans0, -1, -1); EXPECT_STREQ("hello", div->innerText().Utf8().data()); EXPECT_EQ(3u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(3u, Controller().GetSelectionOffsets().End()); @@ -1113,9 +1112,9 @@ Element* div = InsertHTMLElement("<div id='sample' contenteditable></div>", "sample"); - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); - Controller().SetComposition("hello", underlines, 5, 5); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(0, 5, Color(255, 0, 0), false, 0)); + Controller().SetComposition("hello", ime_text_spans, 5, 5); EXPECT_STREQ("hello", div->innerText().Utf8().data()); EXPECT_EQ(5u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(5u, Controller().GetSelectionOffsets().End()); @@ -1130,9 +1129,9 @@ Element* div = InsertHTMLElement("<div id='sample' contenteditable></div>", "sample"); - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(0, 2, Color(255, 0, 0), false, 0)); - Controller().CommitText("hello", underlines, 0); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(0, 2, Color(255, 0, 0), false, 0)); + Controller().CommitText("hello", ime_text_spans, 0); EXPECT_STREQ("hello", div->innerText().Utf8().data()); Controller().SetEditableSelectionOffsets(PlainTextRange(2, 2)); @@ -1161,17 +1160,17 @@ GetDocument().View()->UpdateAllLifecyclePhases(); // Simulate composition in the |contentEditable|. - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(0, 5, Color(255, 0, 0), false, 0)); editable->focus(); GetDocument().setTitle(g_empty_string); - Controller().SetComposition("foo", underlines, 0, 3); + Controller().SetComposition("foo", ime_text_spans, 0, 3); EXPECT_STREQ("beforeinput.isComposing:true;input.isComposing:true;", GetDocument().title().Utf8().data()); GetDocument().setTitle(g_empty_string); - Controller().CommitText("bar", underlines, 0); + Controller().CommitText("bar", ime_text_spans, 0); // Last pair of InputEvent should also be inside composition scope. EXPECT_STREQ("beforeinput.isComposing:true;input.isComposing:true;", GetDocument().title().Utf8().data()); @@ -1181,17 +1180,17 @@ CreateHTMLWithCompositionInputEventListeners(); // Simulate composition in the |contentEditable|. - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(0, 5, Color(255, 0, 0), false, 0)); GetDocument().setTitle(g_empty_string); - Controller().SetComposition("hell", underlines, 4, 4); + Controller().SetComposition("hell", ime_text_spans, 4, 4); EXPECT_STREQ("beforeinput.data:hell;input.data:hell;", GetDocument().title().Utf8().data()); // Replace the existing composition. GetDocument().setTitle(g_empty_string); - Controller().SetComposition("hello", underlines, 0, 0); + Controller().SetComposition("hello", ime_text_spans, 0, 0); EXPECT_STREQ("beforeinput.data:hello;input.data:hello;", GetDocument().title().Utf8().data()); } @@ -1200,11 +1199,11 @@ CreateHTMLWithCompositionInputEventListeners(); // Simulate composition in the |contentEditable|. - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(0, 5, Color(255, 0, 0), false, 0)); GetDocument().setTitle(g_empty_string); - Controller().SetComposition("hello", underlines, 5, 5); + Controller().SetComposition("hello", ime_text_spans, 5, 5); EXPECT_STREQ("beforeinput.data:hello;input.data:hello;", GetDocument().title().Utf8().data()); @@ -1219,17 +1218,17 @@ CreateHTMLWithCompositionInputEventListeners(); // Simulate composition in the |contentEditable|. - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(0, 5, Color(255, 0, 0), false, 0)); GetDocument().setTitle(g_empty_string); - Controller().SetComposition("hello", underlines, 5, 5); + Controller().SetComposition("hello", ime_text_spans, 5, 5); EXPECT_STREQ("beforeinput.data:hello;input.data:hello;", GetDocument().title().Utf8().data()); // Delete the existing composition. GetDocument().setTitle(g_empty_string); - Controller().SetComposition("", underlines, 0, 0); + Controller().SetComposition("", ime_text_spans, 0, 0); EXPECT_STREQ("beforeinput.data:;input.data:null;compositionend.data:;", GetDocument().title().Utf8().data()); } @@ -1238,25 +1237,25 @@ CreateHTMLWithCompositionInputEventListeners(); // Simulate composition in the |contentEditable|. - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(0, 5, Color(255, 0, 0), false, 0)); // Insert new text without previous composition. GetDocument().setTitle(g_empty_string); GetDocument().UpdateStyleAndLayout(); - Controller().CommitText("hello", underlines, 0); + Controller().CommitText("hello", ime_text_spans, 0); EXPECT_STREQ("beforeinput.data:hello;input.data:hello;", GetDocument().title().Utf8().data()); GetDocument().setTitle(g_empty_string); - Controller().SetComposition("n", underlines, 1, 1); + Controller().SetComposition("n", ime_text_spans, 1, 1); EXPECT_STREQ("beforeinput.data:n;input.data:n;", GetDocument().title().Utf8().data()); // Insert new text with previous composition. GetDocument().setTitle(g_empty_string); GetDocument().UpdateStyleAndLayout(); - Controller().CommitText("hello", underlines, 1); + Controller().CommitText("hello", ime_text_spans, 1); EXPECT_STREQ( "beforeinput.data:hello;input.data:hello;compositionend.data:hello;", GetDocument().title().Utf8().data()); @@ -1266,24 +1265,24 @@ CreateHTMLWithCompositionInputEventListeners(); // Simulate composition in the |contentEditable|. - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(0, 5, Color(255, 0, 0), false, 0)); // Insert empty text without previous composition. GetDocument().setTitle(g_empty_string); GetDocument().UpdateStyleAndLayout(); - Controller().CommitText("", underlines, 0); + Controller().CommitText("", ime_text_spans, 0); EXPECT_STREQ("beforeinput.data:;", GetDocument().title().Utf8().data()); GetDocument().setTitle(g_empty_string); - Controller().SetComposition("n", underlines, 1, 1); + Controller().SetComposition("n", ime_text_spans, 1, 1); EXPECT_STREQ("beforeinput.data:n;input.data:n;", GetDocument().title().Utf8().data()); // Insert empty text with previous composition. GetDocument().setTitle(g_empty_string); GetDocument().UpdateStyleAndLayout(); - Controller().CommitText("", underlines, 1); + Controller().CommitText("", ime_text_spans, 1); EXPECT_STREQ("beforeinput.data:;input.data:null;compositionend.data:;", GetDocument().title().Utf8().data()); } @@ -1292,10 +1291,10 @@ CreateHTMLWithCompositionEndEventListener(kNoSelection); // Simulate composition in the |contentEditable|. - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(0, 5, Color(255, 0, 0), false, 0)); - Controller().SetComposition("hello", underlines, 1, 1); + Controller().SetComposition("hello", ime_text_spans, 1, 1); GetDocument().UpdateStyleAndLayout(); EXPECT_EQ(1u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(1u, Controller().GetSelectionOffsets().End()); @@ -1314,7 +1313,7 @@ EXPECT_EQ(kWebTextInputTypeText, Controller().TextInputType()); // The test requires non-empty composition. - Controller().SetComposition("hello", Vector<CompositionUnderline>(), 5, 5); + Controller().SetComposition("hello", Vector<ImeTextSpan>(), 5, 5); EXPECT_EQ(kWebTextInputTypeText, Controller().TextInputType()); // Remove element 'a'. @@ -1331,8 +1330,8 @@ TEST_F(InputMethodControllerTest, ReflectsSpaceWithoutNbspMangling) { InsertHTMLElement("<div id='sample' contenteditable></div>", "sample"); - Vector<CompositionUnderline> underlines; - Controller().CommitText(String(" "), underlines, 0); + Vector<ImeTextSpan> ime_text_spans; + Controller().CommitText(String(" "), ime_text_spans, 0); // In a contenteditable, multiple spaces or a space at the edge needs to be // nbsp to affect layout properly, but it confuses some IMEs (particularly @@ -1342,13 +1341,13 @@ EXPECT_EQ(' ', Controller().TextInputInfo().value.Ascii()[1]); } -TEST_F(InputMethodControllerTest, SetCompositionPlainTextWithUnderline) { +TEST_F(InputMethodControllerTest, SetCompositionPlainTextWithIme_Span) { InsertHTMLElement("<div id='sample' contenteditable></div>", "sample"); - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(0, 1, Color(255, 0, 0), false, 0)); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(0, 1, Color(255, 0, 0), false, 0)); - Controller().SetComposition(" ", underlines, 1, 1); + Controller().SetComposition(" ", ime_text_spans, 1, 1); ASSERT_EQ(1u, GetDocument().Markers().Markers().size()); @@ -1356,17 +1355,17 @@ EXPECT_EQ(1u, GetDocument().Markers().Markers()[0]->EndOffset()); } -TEST_F(InputMethodControllerTest, CommitPlainTextWithUnderlineInsert) { +TEST_F(InputMethodControllerTest, CommitPlainTextWithIme_SpanInsert) { InsertHTMLElement("<div id='sample' contenteditable>Initial text.</div>", "sample"); - Vector<CompositionUnderline> underlines; + Vector<ImeTextSpan> ime_text_spans; Controller().SetEditableSelectionOffsets(PlainTextRange(8, 8)); - underlines.push_back(CompositionUnderline(1, 11, Color(255, 0, 0), false, 0)); + ime_text_spans.push_back(ImeTextSpan(1, 11, Color(255, 0, 0), false, 0)); - Controller().CommitText(String("underlined"), underlines, 0); + Controller().CommitText(String("ime_text_spand"), ime_text_spans, 0); ASSERT_EQ(1u, GetDocument().Markers().Markers().size()); @@ -1374,17 +1373,17 @@ EXPECT_EQ(19u, GetDocument().Markers().Markers()[0]->EndOffset()); } -TEST_F(InputMethodControllerTest, CommitPlainTextWithUnderlineReplace) { +TEST_F(InputMethodControllerTest, CommitPlainTextWithIme_SpanReplace) { InsertHTMLElement("<div id='sample' contenteditable>Initial text.</div>", "sample"); - Vector<CompositionUnderline> underlines; + Vector<ImeTextSpan> ime_text_spans; - Controller().SetCompositionFromExistingText(underlines, 8, 12); + Controller().SetCompositionFromExistingText(ime_text_spans, 8, 12); - underlines.push_back(CompositionUnderline(1, 11, Color(255, 0, 0), false, 0)); + ime_text_spans.push_back(ImeTextSpan(1, 11, Color(255, 0, 0), false, 0)); - Controller().CommitText(String("string"), underlines, 0); + Controller().CommitText(String("string"), ime_text_spans, 0); ASSERT_EQ(1u, GetDocument().Markers().Markers().size()); @@ -1392,23 +1391,22 @@ EXPECT_EQ(15u, GetDocument().Markers().Markers()[0]->EndOffset()); } -TEST_F(InputMethodControllerTest, - CompositionUnderlineAppearsCorrectlyAfterNewline) { +TEST_F(InputMethodControllerTest, ImeTextSpanAppearsCorrectlyAfterNewline) { Element* div = InsertHTMLElement("<div id='sample' contenteditable></div>", "sample"); - Vector<CompositionUnderline> underlines; - Controller().SetComposition(String("hello"), underlines, 6, 6); + Vector<ImeTextSpan> ime_text_spans; + Controller().SetComposition(String("hello"), ime_text_spans, 6, 6); Controller().FinishComposingText(InputMethodController::kKeepSelection); GetFrame().GetEditor().InsertLineBreak(); - Controller().SetCompositionFromExistingText(underlines, 8, 8); + Controller().SetCompositionFromExistingText(ime_text_spans, 8, 8); - underlines.push_back(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); - Controller().SetComposition(String("world"), underlines, 0, 0); + ime_text_spans.push_back(ImeTextSpan(0, 5, Color(255, 0, 0), false, 0)); + Controller().SetComposition(String("world"), ime_text_spans, 0, 0); ASSERT_EQ(1u, GetDocument().Markers().Markers().size()); - // Verify composition underline shows up on the second line, not the first + // Verify composition marker shows up on the second line, not the first ASSERT_FALSE(GetDocument().Markers().MarkerAtPosition( PlainTextRange(2).CreateRange(*div).StartPosition(), DocumentMarker::AllMarkers())); @@ -1429,9 +1427,9 @@ editable->focus(); // Simulate composition in the |contentEditable|. - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); - Controller().SetComposition("foo", underlines, 3, 3); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(0, 5, Color(255, 0, 0), false, 0)); + Controller().SetComposition("foo", ime_text_spans, 3, 3); EXPECT_TRUE(Controller().HasComposition()); EXPECT_EQ(0u, Controller().CompositionRange()->startOffset()); @@ -1474,11 +1472,11 @@ GetDocument().UpdateStyleAndLayout(); Controller().SetEditableSelectionOffsets(PlainTextRange(4, 4)); - Vector<CompositionUnderline> underlines; - underlines.push_back(CompositionUnderline(0, 3, Color(255, 0, 0), false, 0)); - Controller().SetComposition(String("def"), underlines, 0, 3); - Controller().SetComposition(String(""), underlines, 0, 3); - Controller().CommitText(String("def"), underlines, 0); + Vector<ImeTextSpan> ime_text_spans; + ime_text_spans.push_back(ImeTextSpan(0, 3, Color(255, 0, 0), false, 0)); + Controller().SetComposition(String("def"), ime_text_spans, 0, 3); + Controller().SetComposition(String(""), ime_text_spans, 0, 3); + Controller().CommitText(String("def"), ime_text_spans, 0); EXPECT_STREQ("abc\ndef", textarea->value().Utf8().data()); } @@ -1488,17 +1486,17 @@ "<div id='sample' contenteditable>Initial text blah</div>", "sample"); // Delete "Initial" - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 0, 7); - Controller().CommitText(String(""), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 0, 7); + Controller().CommitText(String(""), empty_ime_text_spans, 0); // The space at the beginning of the string should have been converted to an // nbsp EXPECT_STREQ(" text blah", div->innerHTML().Utf8().data()); // Delete "blah" - Controller().SetCompositionFromExistingText(empty_underlines, 6, 10); - Controller().CommitText(String(""), empty_underlines, 0); + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 6, 10); + Controller().CommitText(String(""), empty_ime_text_spans, 0); // The space at the end of the string should have been converted to an nbsp EXPECT_STREQ(" text ", div->innerHTML().Utf8().data()); @@ -1510,13 +1508,13 @@ input->setValue("Abc Def Ghi"); GetDocument().UpdateStyleAndLayout(); - Vector<CompositionUnderline> empty_underlines; + Vector<ImeTextSpan> empty_ime_text_spans; Controller().SetEditableSelectionOffsets(PlainTextRange(4, 8)); - Controller().CommitText(String(""), empty_underlines, 0); + Controller().CommitText(String(""), empty_ime_text_spans, 0); EXPECT_STREQ("Abc Ghi", input->value().Utf8().data()); Controller().SetEditableSelectionOffsets(PlainTextRange(4, 7)); - Controller().CommitText(String("1"), empty_underlines, 0); + Controller().CommitText(String("1"), empty_ime_text_spans, 0); EXPECT_STREQ("Abc 1", input->value().Utf8().data()); } @@ -1541,13 +1539,13 @@ marker_range, Color::kBlack, StyleableMarker::Thickness::kThin, Color::kBlack); // Delete "Initial" - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 0, 7); - Controller().CommitText(String(""), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 0, 7); + Controller().CommitText(String(""), empty_ime_text_spans, 0); // Delete "blah" - Controller().SetCompositionFromExistingText(empty_underlines, 6, 10); - Controller().CommitText(String(""), empty_underlines, 0); + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 6, 10); + Controller().CommitText(String(""), empty_ime_text_spans, 0); // Check that the marker is still attached to "text" and doesn't include // either space around it @@ -1570,13 +1568,13 @@ marker_range, Color::kBlack, StyleableMarker::Thickness::kThin, Color::kBlack); // Delete "Initial" - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 0, 7); - Controller().CommitText(String(""), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 0, 7); + Controller().CommitText(String(""), empty_ime_text_spans, 0); // Delete "blah" - Controller().SetCompositionFromExistingText(empty_underlines, 6, 10); - Controller().CommitText(String(""), empty_underlines, 0); + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 6, 10); + Controller().CommitText(String(""), empty_ime_text_spans, 0); // Check that the marker is still attached to " text" and includes the space // before "text" but not the space after @@ -1599,13 +1597,13 @@ marker_range, Color::kBlack, StyleableMarker::Thickness::kThin, Color::kBlack); // Delete "Initial" - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 0, 7); - Controller().CommitText(String(""), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 0, 7); + Controller().CommitText(String(""), empty_ime_text_spans, 0); // Delete "blah" - Controller().SetCompositionFromExistingText(empty_underlines, 6, 10); - Controller().CommitText(String(""), empty_underlines, 0); + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 6, 10); + Controller().CommitText(String(""), empty_ime_text_spans, 0); // Check that the marker is still attached to "text " and includes the space // after "text" but not the space before @@ -1630,13 +1628,13 @@ Color::kBlack); // Delete "Initial" - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 0, 7); - Controller().CommitText(String(""), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 0, 7); + Controller().CommitText(String(""), empty_ime_text_spans, 0); // Delete "blah" - Controller().SetCompositionFromExistingText(empty_underlines, 6, 10); - Controller().CommitText(String(""), empty_underlines, 0); + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 6, 10); + Controller().CommitText(String(""), empty_ime_text_spans, 0); // Check that the marker is still attached to " text " and includes both the // space before "text" and the space after @@ -1657,9 +1655,9 @@ marker_range, TextMatchMarker::MatchStatus::kInactive); // Replace "Initial" with "Original" - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 0, 7); - Controller().CommitText(String("Original"), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 0, 7); + Controller().CommitText(String("Original"), empty_ime_text_spans, 0); // Verify marker was removed EXPECT_EQ(0u, GetDocument().Markers().Markers().size()); @@ -1677,9 +1675,9 @@ Color::kBlack); // Replace "Initial" with "Original" - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 0, 7); - Controller().CommitText(String("Original"), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 0, 7); + Controller().CommitText(String("Original"), empty_ime_text_spans, 0); // Verify marker is under "Original text" EXPECT_EQ(1u, GetDocument().Markers().Markers().size()); @@ -1701,9 +1699,9 @@ marker_range, TextMatchMarker::MatchStatus::kInactive); // Replace "some initial" with "boring" - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 8, 20); - Controller().CommitText(String("boring"), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 8, 20); + Controller().CommitText(String("boring"), empty_ime_text_spans, 0); // Verify marker was removed EXPECT_EQ(0u, GetDocument().Markers().Markers().size()); @@ -1722,9 +1720,9 @@ Color::kBlack); // Replace "some initial" with "boring" - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 8, 20); - Controller().CommitText(String("boring"), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 8, 20); + Controller().CommitText(String("boring"), empty_ime_text_spans, 0); // Verify marker is under " text" EXPECT_EQ(1u, GetDocument().Markers().Markers().size()); @@ -1744,9 +1742,9 @@ marker_range, TextMatchMarker::MatchStatus::kInactive); // Replace "text" with "string" - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 8, 12); - Controller().CommitText(String("string"), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 8, 12); + Controller().CommitText(String("string"), empty_ime_text_spans, 0); // Verify marker was removed EXPECT_EQ(0u, GetDocument().Markers().Markers().size()); @@ -1763,9 +1761,9 @@ Color::kBlack); // Replace "text" with "string" - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 8, 12); - Controller().CommitText(String("string"), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 8, 12); + Controller().CommitText(String("string"), empty_ime_text_spans, 0); // Verify marker is under "Initial string" EXPECT_EQ(1u, GetDocument().Markers().Markers().size()); @@ -1787,9 +1785,9 @@ marker_range, TextMatchMarker::MatchStatus::kInactive); // Replace "initial text" with "content" - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 13, 25); - Controller().CommitText(String("content"), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 13, 25); + Controller().CommitText(String("content"), empty_ime_text_spans, 0); EXPECT_STREQ("This is some content", div->innerHTML().Utf8().data()); @@ -1810,9 +1808,9 @@ Color::kBlack); // Replace "initial text" with "content" - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 13, 25); - Controller().CommitText(String("content"), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 13, 25); + Controller().CommitText(String("content"), empty_ime_text_spans, 0); EXPECT_STREQ("This is some content", div->innerHTML().Utf8().data()); @@ -1834,9 +1832,9 @@ marker_range, TextMatchMarker::MatchStatus::kInactive); // Replace "text" with "string" - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 8, 12); - Controller().CommitText(String("string"), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 8, 12); + Controller().CommitText(String("string"), empty_ime_text_spans, 0); // Verify marker was removed EXPECT_EQ(0u, GetDocument().Markers().Markers().size()); @@ -1854,9 +1852,9 @@ Color::kBlack); // Replace "text" with "string" - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 8, 12); - Controller().CommitText(String("string"), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 8, 12); + Controller().CommitText(String("string"), empty_ime_text_spans, 0); // Verify marker is under "string" EXPECT_EQ(1u, GetDocument().Markers().Markers().size()); @@ -1879,9 +1877,9 @@ EXPECT_EQ(1u, GetDocument().Markers().Markers().size()); // Replace "Initial text" with "New string" - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 0, 12); - Controller().CommitText(String("New string"), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 0, 12); + Controller().CommitText(String("New string"), empty_ime_text_spans, 0); // Verify marker was removed EXPECT_EQ(0u, GetDocument().Markers().Markers().size()); @@ -1901,9 +1899,9 @@ EXPECT_EQ(1u, GetDocument().Markers().Markers().size()); // Replace "Initial text" with "New string" - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 0, 12); - Controller().CommitText(String("New string"), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 0, 12); + Controller().CommitText(String("New string"), empty_ime_text_spans, 0); // Verify marker was removed EXPECT_EQ(0u, GetDocument().Markers().Markers().size()); @@ -1922,9 +1920,9 @@ EXPECT_EQ(1u, GetDocument().Markers().Markers().size()); // Replace "Initial text" with "New string" - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 0, 12); - Controller().CommitText(String("New string"), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 0, 12); + Controller().CommitText(String("New string"), empty_ime_text_spans, 0); // Verify marker was removed EXPECT_EQ(0u, GetDocument().Markers().Markers().size()); @@ -1944,9 +1942,9 @@ EXPECT_EQ(1u, GetDocument().Markers().Markers().size()); // Replace "Initial text" with "New string" - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 0, 12); - Controller().CommitText(String("New string"), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 0, 12); + Controller().CommitText(String("New string"), empty_ime_text_spans, 0); // Verify marker was removed EXPECT_EQ(0u, GetDocument().Markers().Markers().size()); @@ -1980,9 +1978,9 @@ EXPECT_EQ(5u, GetDocument().Markers().Markers().size()); // Delete third marker and portions of second and fourth - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 8, 17); - Controller().CommitText(String(""), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 8, 17); + Controller().CommitText(String(""), empty_ime_text_spans, 0); // Verify markers were updated correctly EXPECT_EQ(2u, GetDocument().Markers().Markers().size()); @@ -2027,9 +2025,9 @@ EXPECT_EQ(5u, GetDocument().Markers().Markers().size()); // Delete third marker and portions of second and fourth - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 8, 17); - Controller().CommitText(String(""), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 8, 17); + Controller().CommitText(String(""), empty_ime_text_spans, 0); // Verify markers were updated correctly EXPECT_EQ(4u, GetDocument().Markers().Markers().size()); @@ -2060,9 +2058,9 @@ EXPECT_EQ(1u, GetDocument().Markers().Markers().size()); // Delete exactly on the marker - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 5, 10); - Controller().CommitText(String(""), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 5, 10); + Controller().CommitText(String(""), empty_ime_text_spans, 0); EXPECT_EQ(0u, GetDocument().Markers().Markers().size()); } @@ -2080,9 +2078,9 @@ EXPECT_EQ(1u, GetDocument().Markers().Markers().size()); // Delete exactly on the marker - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 5, 10); - Controller().CommitText(String(""), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 5, 10); + Controller().CommitText(String(""), empty_ime_text_spans, 0); EXPECT_EQ(0u, GetDocument().Markers().Markers().size()); } @@ -2096,9 +2094,9 @@ marker_range, TextMatchMarker::MatchStatus::kInactive); // Delete middle of marker - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 6, 9); - Controller().CommitText(String(""), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 6, 9); + Controller().CommitText(String(""), empty_ime_text_spans, 0); // Verify marker was removed EXPECT_EQ(0u, GetDocument().Markers().Markers().size()); @@ -2116,9 +2114,9 @@ Color::kBlack); // Delete middle of marker - Vector<CompositionUnderline> empty_underlines; - Controller().SetCompositionFromExistingText(empty_underlines, 6, 9); - Controller().CommitText(String(""), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetCompositionFromExistingText(empty_ime_text_spans, 6, 9); + Controller().CommitText(String(""), empty_ime_text_spans, 0); EXPECT_EQ(1u, GetDocument().Markers().Markers().size()); @@ -2147,9 +2145,9 @@ EXPECT_EQ(3u, GetDocument().Markers().Markers().size()); // insert in middle of second marker - Vector<CompositionUnderline> empty_underlines; - Controller().SetComposition("", empty_underlines, 7, 7); - Controller().CommitText(String("66666"), empty_underlines, -7); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetComposition("", empty_ime_text_spans, 7, 7); + Controller().CommitText(String("66666"), empty_ime_text_spans, -7); EXPECT_EQ(2u, GetDocument().Markers().Markers().size()); @@ -2184,9 +2182,9 @@ EXPECT_EQ(3u, GetDocument().Markers().Markers().size()); // insert in middle of second marker - Vector<CompositionUnderline> empty_underlines; - Controller().SetComposition("", empty_underlines, 7, 7); - Controller().CommitText(String("66666"), empty_underlines, -7); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetComposition("", empty_ime_text_spans, 7, 7); + Controller().CommitText(String("66666"), empty_ime_text_spans, -7); EXPECT_EQ(3u, GetDocument().Markers().Markers().size()); @@ -2219,9 +2217,9 @@ EXPECT_EQ(3u, GetDocument().Markers().Markers().size()); - Vector<CompositionUnderline> empty_underlines; - Controller().SetComposition("", empty_underlines, 5, 5); - Controller().CommitText(String("77777"), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetComposition("", empty_ime_text_spans, 5, 5); + Controller().CommitText(String("77777"), empty_ime_text_spans, 0); EXPECT_EQ(3u, GetDocument().Markers().Markers().size()); @@ -2258,9 +2256,9 @@ EXPECT_EQ(3u, GetDocument().Markers().Markers().size()); - Vector<CompositionUnderline> empty_underlines; - Controller().SetComposition("", empty_underlines, 5, 5); - Controller().CommitText(String("77777"), empty_underlines, 0); + Vector<ImeTextSpan> empty_ime_text_spans; + Controller().SetComposition("", empty_ime_text_spans, 5, 5); + Controller().CommitText(String("77777"), empty_ime_text_spans, 0); EXPECT_EQ(3u, GetDocument().Markers().Markers().size()); @@ -2295,7 +2293,7 @@ EXPECT_EQ(kWebTextInputTypeText, Controller().TextInputType()); - Controller().SetComposition("abcde", Vector<CompositionUnderline>(), 4, 4); + Controller().SetComposition("abcde", Vector<ImeTextSpan>(), 4, 4); EXPECT_STREQ("abcde", input->value().Utf8().data()); Controller().FinishComposingText(InputMethodController::kKeepSelection);
diff --git a/third_party/WebKit/Source/core/exported/WebInputMethodControllerImpl.cpp b/third_party/WebKit/Source/core/exported/WebInputMethodControllerImpl.cpp index 0a7f545..ec3ab31ac 100644 --- a/third_party/WebKit/Source/core/exported/WebInputMethodControllerImpl.cpp +++ b/third_party/WebKit/Source/core/exported/WebInputMethodControllerImpl.cpp
@@ -7,11 +7,11 @@ #include "core/InputTypeNames.h" #include "core/dom/Document.h" #include "core/dom/UserGestureIndicator.h" -#include "core/editing/CompositionUnderlineVectorBuilder.h" #include "core/editing/EditingUtilities.h" #include "core/editing/Editor.h" #include "core/editing/EphemeralRange.h" #include "core/editing/FrameSelection.h" +#include "core/editing/ImeTextSpanVectorBuilder.h" #include "core/editing/InputMethodController.h" #include "core/editing/PlainTextRange.h" #include "core/exported/WebPluginContainerImpl.h" @@ -37,12 +37,12 @@ bool WebInputMethodControllerImpl::SetComposition( const WebString& text, - const WebVector<WebCompositionUnderline>& underlines, + const WebVector<WebImeTextSpan>& ime_text_spans, const WebRange& replacement_range, int selection_start, int selection_end) { if (WebPlugin* plugin = FocusedPluginIfInputMethodSupported()) { - return plugin->SetComposition(text, underlines, replacement_range, + return plugin->SetComposition(text, ime_text_spans, replacement_range, selection_start, selection_end); } @@ -72,12 +72,8 @@ UserGestureIndicator gesture_indicator(UserGestureToken::Create( GetFrame()->GetDocument(), UserGestureToken::kNewGesture)); - // When the range of composition underlines overlap with the range between - // selectionStart and selectionEnd, WebKit somehow won't paint the selection - // at all (see InlineTextBox::paint() function in InlineTextBox.cpp). - // But the selection range actually takes effect. GetInputMethodController().SetComposition( - String(text), CompositionUnderlineVectorBuilder::Build(underlines), + String(text), ImeTextSpanVectorBuilder::Build(ime_text_spans), selection_start, selection_end); return text.IsEmpty() || GetInputMethodController().HasComposition(); @@ -107,14 +103,14 @@ bool WebInputMethodControllerImpl::CommitText( const WebString& text, - const WebVector<WebCompositionUnderline>& underlines, + const WebVector<WebImeTextSpan>& ime_text_spans, const WebRange& replacement_range, int relative_caret_position) { UserGestureIndicator gesture_indicator(UserGestureToken::Create( GetFrame()->GetDocument(), UserGestureToken::kNewGesture)); if (WebPlugin* plugin = FocusedPluginIfInputMethodSupported()) { - return plugin->CommitText(text, underlines, replacement_range, + return plugin->CommitText(text, ime_text_spans, replacement_range, relative_caret_position); } @@ -127,7 +123,7 @@ GetFrame()->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets(); return GetInputMethodController().CommitText( - text, CompositionUnderlineVectorBuilder::Build(underlines), + text, ImeTextSpanVectorBuilder::Build(ime_text_spans), relative_caret_position); }
diff --git a/third_party/WebKit/Source/core/exported/WebInputMethodControllerImpl.h b/third_party/WebKit/Source/core/exported/WebInputMethodControllerImpl.h index a2e4219..001d1c6 100644 --- a/third_party/WebKit/Source/core/exported/WebInputMethodControllerImpl.h +++ b/third_party/WebKit/Source/core/exported/WebInputMethodControllerImpl.h
@@ -8,7 +8,7 @@ #include "core/CoreExport.h" #include "platform/heap/Handle.h" #include "platform/wtf/Allocator.h" -#include "public/web/WebCompositionUnderline.h" +#include "public/web/WebImeTextSpan.h" #include "public/web/WebInputMethodController.h" namespace blink { @@ -31,12 +31,12 @@ // WebInputMethodController overrides. bool SetComposition(const WebString& text, - const WebVector<WebCompositionUnderline>& underlines, + const WebVector<WebImeTextSpan>& ime_text_spans, const WebRange& replacement_range, int selection_start, int selection_end) override; bool CommitText(const WebString& text, - const WebVector<WebCompositionUnderline>& underlines, + const WebVector<WebImeTextSpan>& ime_text_spans, const WebRange& replacement_range, int relative_caret_position) override; bool FinishComposingText(
diff --git a/third_party/WebKit/Source/core/exported/WebViewImpl.cpp b/third_party/WebKit/Source/core/exported/WebViewImpl.cpp index 41353c58..bf69e60 100644 --- a/third_party/WebKit/Source/core/exported/WebViewImpl.cpp +++ b/third_party/WebKit/Source/core/exported/WebViewImpl.cpp
@@ -1853,11 +1853,8 @@ // apparent position unchanged. ResizeViewportAnchor::ResizeScope resize_scope(*resize_viewport_anchor_); - float browser_controls_viewport_adjustment = - GetBrowserControls().LayoutHeight() - - GetBrowserControls().ContentOffset(); visual_viewport.SetBrowserControlsAdjustment( - browser_controls_viewport_adjustment); + GetBrowserControls().UnreportedSizeAdjustment()); } }
diff --git a/third_party/WebKit/Source/core/exported/WebViewTest.cpp b/third_party/WebKit/Source/core/exported/WebViewTest.cpp index af31524..cb95a65b 100644 --- a/third_party/WebKit/Source/core/exported/WebViewTest.cpp +++ b/third_party/WebKit/Source/core/exported/WebViewTest.cpp
@@ -961,9 +961,9 @@ // The test requires non-empty composition. std::string composition_text("hello"); - WebVector<WebCompositionUnderline> empty_underlines; + WebVector<WebImeTextSpan> empty_ime_text_spans; active_input_method_controller->SetComposition( - WebString::FromUTF8(composition_text.c_str()), empty_underlines, + WebString::FromUTF8(composition_text.c_str()), empty_ime_text_spans, WebRange(), 5, 5); // Do arbitrary change to make layout dirty. @@ -991,9 +991,9 @@ web_view->MainFrameImpl() ->FrameWidget() ->GetActiveWebInputMethodController(); - WebVector<WebCompositionUnderline> empty_underlines; + WebVector<WebImeTextSpan> empty_ime_text_spans; active_input_method_controller->SetComposition( - WebString::FromUTF8(composition_text.c_str()), empty_underlines, + WebString::FromUTF8(composition_text.c_str()), empty_ime_text_spans, WebRange(), 3, 3); WebTextInputInfo info = active_input_method_controller->TextInputInfo(); @@ -1012,7 +1012,7 @@ EXPECT_EQ(-1, info.composition_end); active_input_method_controller->SetComposition( - WebString::FromUTF8(composition_text.c_str()), empty_underlines, + WebString::FromUTF8(composition_text.c_str()), empty_ime_text_spans, WebRange(), 3, 3); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("helhellolo", std::string(info.value.Utf8().data())); @@ -1040,11 +1040,11 @@ ->FrameWidget() ->GetActiveWebInputMethodController(); - WebVector<WebCompositionUnderline> empty_underlines; + WebVector<WebImeTextSpan> empty_ime_text_spans; - active_input_method_controller->CommitText("hello", empty_underlines, + active_input_method_controller->CommitText("hello", empty_ime_text_spans, WebRange(), 0); - active_input_method_controller->CommitText("world", empty_underlines, + active_input_method_controller->CommitText("world", empty_ime_text_spans, WebRange(), -5); WebTextInputInfo info = active_input_method_controller->TextInputInfo(); @@ -1059,7 +1059,7 @@ // Caret is on the left of composing text. active_input_method_controller->SetComposition( - WebString::FromUTF8(composition_text.c_str()), empty_underlines, + WebString::FromUTF8(composition_text.c_str()), empty_ime_text_spans, WebRange(), 0, 0); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("helloABCworld", std::string(info.value.Utf8().data())); @@ -1070,7 +1070,7 @@ // Caret is on the right of composing text. active_input_method_controller->SetComposition( - WebString::FromUTF8(composition_text.c_str()), empty_underlines, + WebString::FromUTF8(composition_text.c_str()), empty_ime_text_spans, WebRange(), 3, 3); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("helloABCworld", std::string(info.value.Utf8().data())); @@ -1081,7 +1081,7 @@ // Caret is between composing text and left boundary. active_input_method_controller->SetComposition( - WebString::FromUTF8(composition_text.c_str()), empty_underlines, + WebString::FromUTF8(composition_text.c_str()), empty_ime_text_spans, WebRange(), -2, -2); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("helloABCworld", std::string(info.value.Utf8().data())); @@ -1092,7 +1092,7 @@ // Caret is between composing text and right boundary. active_input_method_controller->SetComposition( - WebString::FromUTF8(composition_text.c_str()), empty_underlines, + WebString::FromUTF8(composition_text.c_str()), empty_ime_text_spans, WebRange(), 5, 5); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("helloABCworld", std::string(info.value.Utf8().data())); @@ -1103,7 +1103,7 @@ // Caret is on the left boundary. active_input_method_controller->SetComposition( - WebString::FromUTF8(composition_text.c_str()), empty_underlines, + WebString::FromUTF8(composition_text.c_str()), empty_ime_text_spans, WebRange(), -5, -5); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("helloABCworld", std::string(info.value.Utf8().data())); @@ -1114,7 +1114,7 @@ // Caret is on the right boundary. active_input_method_controller->SetComposition( - WebString::FromUTF8(composition_text.c_str()), empty_underlines, + WebString::FromUTF8(composition_text.c_str()), empty_ime_text_spans, WebRange(), 8, 8); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("helloABCworld", std::string(info.value.Utf8().data())); @@ -1125,7 +1125,7 @@ // Caret exceeds the left boundary. active_input_method_controller->SetComposition( - WebString::FromUTF8(composition_text.c_str()), empty_underlines, + WebString::FromUTF8(composition_text.c_str()), empty_ime_text_spans, WebRange(), -100, -100); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("helloABCworld", std::string(info.value.Utf8().data())); @@ -1136,7 +1136,7 @@ // Caret exceeds the right boundary. active_input_method_controller->SetComposition( - WebString::FromUTF8(composition_text.c_str()), empty_underlines, + WebString::FromUTF8(composition_text.c_str()), empty_ime_text_spans, WebRange(), 100, 100); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("helloABCworld", std::string(info.value.Utf8().data())); @@ -1156,9 +1156,9 @@ ->FrameWidget() ->GetActiveWebInputMethodController(); - WebVector<WebCompositionUnderline> empty_underlines; + WebVector<WebImeTextSpan> empty_ime_text_spans; - active_input_method_controller->CommitText("hello", empty_underlines, + active_input_method_controller->CommitText("hello", empty_ime_text_spans, WebRange(), 0); WebTextInputInfo info = active_input_method_controller->TextInputInfo(); @@ -1169,7 +1169,7 @@ EXPECT_EQ(-1, info.composition_end); active_input_method_controller->SetComposition( - WebString::FromUTF8(""), empty_underlines, WebRange(), 0, 0); + WebString::FromUTF8(""), empty_ime_text_spans, WebRange(), 0, 0); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("hello", std::string(info.value.Utf8().data())); EXPECT_EQ(5, info.selection_start); @@ -1178,7 +1178,7 @@ EXPECT_EQ(-1, info.composition_end); active_input_method_controller->SetComposition( - WebString::FromUTF8(""), empty_underlines, WebRange(), -2, -2); + WebString::FromUTF8(""), empty_ime_text_spans, WebRange(), -2, -2); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("hello", std::string(info.value.Utf8().data())); EXPECT_EQ(3, info.selection_start); @@ -1197,11 +1197,11 @@ ->FrameWidget() ->GetActiveWebInputMethodController(); - WebVector<WebCompositionUnderline> empty_underlines; + WebVector<WebImeTextSpan> empty_ime_text_spans; // Caret is on the left of composing text. - active_input_method_controller->CommitText("ab", empty_underlines, WebRange(), - -2); + active_input_method_controller->CommitText("ab", empty_ime_text_spans, + WebRange(), -2); WebTextInputInfo info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("ab", std::string(info.value.Utf8().data())); EXPECT_EQ(0, info.selection_start); @@ -1210,8 +1210,8 @@ EXPECT_EQ(-1, info.composition_end); // Caret is on the right of composing text. - active_input_method_controller->CommitText("c", empty_underlines, WebRange(), - 1); + active_input_method_controller->CommitText("c", empty_ime_text_spans, + WebRange(), 1); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("cab", std::string(info.value.Utf8().data())); EXPECT_EQ(2, info.selection_start); @@ -1220,7 +1220,7 @@ EXPECT_EQ(-1, info.composition_end); // Caret is on the left boundary. - active_input_method_controller->CommitText("def", empty_underlines, + active_input_method_controller->CommitText("def", empty_ime_text_spans, WebRange(), -5); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("cadefb", std::string(info.value.Utf8().data())); @@ -1230,8 +1230,8 @@ EXPECT_EQ(-1, info.composition_end); // Caret is on the right boundary. - active_input_method_controller->CommitText("g", empty_underlines, WebRange(), - 6); + active_input_method_controller->CommitText("g", empty_ime_text_spans, + WebRange(), 6); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("gcadefb", std::string(info.value.Utf8().data())); EXPECT_EQ(7, info.selection_start); @@ -1240,8 +1240,8 @@ EXPECT_EQ(-1, info.composition_end); // Caret exceeds the left boundary. - active_input_method_controller->CommitText("hi", empty_underlines, WebRange(), - -100); + active_input_method_controller->CommitText("hi", empty_ime_text_spans, + WebRange(), -100); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("gcadefbhi", std::string(info.value.Utf8().data())); EXPECT_EQ(0, info.selection_start); @@ -1250,8 +1250,8 @@ EXPECT_EQ(-1, info.composition_end); // Caret exceeds the right boundary. - active_input_method_controller->CommitText("jk", empty_underlines, WebRange(), - 100); + active_input_method_controller->CommitText("jk", empty_ime_text_spans, + WebRange(), 100); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("jkgcadefbhi", std::string(info.value.Utf8().data())); EXPECT_EQ(11, info.selection_start); @@ -1270,9 +1270,9 @@ ->FrameWidget() ->GetActiveWebInputMethodController(); - WebVector<WebCompositionUnderline> empty_underlines; + WebVector<WebImeTextSpan> empty_ime_text_spans; active_input_method_controller->SetComposition( - WebString::FromUTF8("abc"), empty_underlines, WebRange(), 0, 0); + WebString::FromUTF8("abc"), empty_ime_text_spans, WebRange(), 0, 0); WebTextInputInfo info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("abc", std::string(info.value.Utf8().data())); EXPECT_EQ(0, info.selection_start); @@ -1282,7 +1282,7 @@ // Deletes ongoing composition, inserts the specified text and moves the // caret. - active_input_method_controller->CommitText("hello", empty_underlines, + active_input_method_controller->CommitText("hello", empty_ime_text_spans, WebRange(), -2); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("hello", std::string(info.value.Utf8().data())); @@ -1292,7 +1292,7 @@ EXPECT_EQ(-1, info.composition_end); active_input_method_controller->SetComposition( - WebString::FromUTF8("abc"), empty_underlines, WebRange(), 0, 0); + WebString::FromUTF8("abc"), empty_ime_text_spans, WebRange(), 0, 0); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("helabclo", std::string(info.value.Utf8().data())); EXPECT_EQ(3, info.selection_start); @@ -1301,8 +1301,8 @@ EXPECT_EQ(6, info.composition_end); // Deletes ongoing composition and moves the caret. - active_input_method_controller->CommitText("", empty_underlines, WebRange(), - 2); + active_input_method_controller->CommitText("", empty_ime_text_spans, + WebRange(), 2); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("hello", std::string(info.value.Utf8().data())); EXPECT_EQ(5, info.selection_start); @@ -1311,7 +1311,7 @@ EXPECT_EQ(-1, info.composition_end); // Inserts the specified text and moves the caret. - active_input_method_controller->CommitText("world", empty_underlines, + active_input_method_controller->CommitText("world", empty_ime_text_spans, WebRange(), -5); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("helloworld", std::string(info.value.Utf8().data())); @@ -1321,8 +1321,8 @@ EXPECT_EQ(-1, info.composition_end); // Only moves the caret. - active_input_method_controller->CommitText("", empty_underlines, WebRange(), - 5); + active_input_method_controller->CommitText("", empty_ime_text_spans, + WebRange(), 5); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("helloworld", std::string(info.value.Utf8().data())); EXPECT_EQ(10, info.selection_start); @@ -1341,10 +1341,10 @@ EXPECT_EQ(0, web_view->MainFrameImpl()->GetScrollOffset().height); // Set up a composition from existing text that needs to be committed. - Vector<CompositionUnderline> empty_underlines; + Vector<ImeTextSpan> empty_ime_text_spans; WebLocalFrameImpl* frame = web_view->MainFrameImpl(); frame->GetFrame()->GetInputMethodController().SetCompositionFromExistingText( - empty_underlines, 0, 3); + empty_ime_text_spans, 0, 3); // Scroll the input field out of the viewport. Element* element = static_cast<Element*>( @@ -1371,13 +1371,13 @@ base_url_ + "text_area_populated.html"); web_view->SetInitialFocus(false); - WebVector<WebCompositionUnderline> empty_underlines; + WebVector<WebImeTextSpan> empty_ime_text_spans; WebLocalFrameImpl* frame = web_view->MainFrameImpl(); WebInputMethodController* active_input_method_controller = frame->GetInputMethodController(); frame->SetEditableSelectionOffsets(4, 4); - frame->SetCompositionFromExistingText(8, 12, empty_underlines); + frame->SetCompositionFromExistingText(8, 12, empty_ime_text_spans); WebTextInputInfo info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("0123456789abcdefghijklmnopqrstuvwxyz", @@ -1397,7 +1397,7 @@ std::string composition_text("\n"); active_input_method_controller->CommitText( - WebString::FromUTF8(composition_text.c_str()), empty_underlines, + WebString::FromUTF8(composition_text.c_str()), empty_ime_text_spans, WebRange(), 0); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ(5, info.selection_start); @@ -1475,20 +1475,20 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad( base_url_ + "input_field_populated.html"); web_view->SetInitialFocus(false); - WebVector<WebCompositionUnderline> underlines(static_cast<size_t>(1)); - underlines[0] = WebCompositionUnderline(0, 4, 0, false, 0); + WebVector<WebImeTextSpan> ime_text_spans(static_cast<size_t>(1)); + ime_text_spans[0] = WebImeTextSpan(0, 4, 0, false, 0); WebLocalFrameImpl* frame = web_view->MainFrameImpl(); WebInputMethodController* active_input_method_controller = frame->GetInputMethodController(); frame->SetEditableSelectionOffsets(4, 10); - frame->SetCompositionFromExistingText(8, 12, underlines); + frame->SetCompositionFromExistingText(8, 12, ime_text_spans); WebTextInputInfo info = active_input_method_controller->TextInputInfo(); EXPECT_EQ(4, info.selection_start); EXPECT_EQ(10, info.selection_end); EXPECT_EQ(8, info.composition_start); EXPECT_EQ(12, info.composition_end); - WebVector<WebCompositionUnderline> empty_underlines; - frame->SetCompositionFromExistingText(0, 0, empty_underlines); + WebVector<WebImeTextSpan> empty_ime_text_spans; + frame->SetCompositionFromExistingText(0, 0, empty_ime_text_spans); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ(4, info.selection_start); EXPECT_EQ(10, info.selection_end); @@ -1501,23 +1501,23 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad( base_url_ + "text_area_populated.html"); web_view->SetInitialFocus(false); - WebVector<WebCompositionUnderline> underlines(static_cast<size_t>(1)); - underlines[0] = WebCompositionUnderline(0, 4, 0, false, 0); + WebVector<WebImeTextSpan> ime_text_spans(static_cast<size_t>(1)); + ime_text_spans[0] = WebImeTextSpan(0, 4, 0, false, 0); WebLocalFrameImpl* frame = web_view->MainFrameImpl(); WebInputMethodController* active_input_method_controller = frame->FrameWidget()->GetActiveWebInputMethodController(); frame->SetEditableSelectionOffsets(27, 27); std::string new_line_text("\n"); - WebVector<WebCompositionUnderline> empty_underlines; + WebVector<WebImeTextSpan> empty_ime_text_spans; active_input_method_controller->CommitText( - WebString::FromUTF8(new_line_text.c_str()), empty_underlines, WebRange(), - 0); + WebString::FromUTF8(new_line_text.c_str()), empty_ime_text_spans, + WebRange(), 0); WebTextInputInfo info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("0123456789abcdefghijklmnopq\nrstuvwxyz", std::string(info.value.Utf8().data())); frame->SetEditableSelectionOffsets(31, 31); - frame->SetCompositionFromExistingText(30, 34, underlines); + frame->SetCompositionFromExistingText(30, 34, ime_text_spans); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("0123456789abcdefghijklmnopq\nrstuvwxyz", std::string(info.value.Utf8().data())); @@ -1528,7 +1528,7 @@ std::string composition_text("yolo"); active_input_method_controller->CommitText( - WebString::FromUTF8(composition_text.c_str()), empty_underlines, + WebString::FromUTF8(composition_text.c_str()), empty_ime_text_spans, WebRange(), 0); info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("0123456789abcdefghijklmnopq\nrsyoloxyz", @@ -1544,13 +1544,13 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad( base_url_ + "content_editable_rich_text.html"); web_view->SetInitialFocus(false); - WebVector<WebCompositionUnderline> underlines(static_cast<size_t>(1)); - underlines[0] = WebCompositionUnderline(0, 4, 0, false, 0); + WebVector<WebImeTextSpan> ime_text_spans(static_cast<size_t>(1)); + ime_text_spans[0] = WebImeTextSpan(0, 4, 0, false, 0); WebLocalFrameImpl* frame = web_view->MainFrameImpl(); frame->SetEditableSelectionOffsets(1, 1); WebDocument document = web_view->MainFrameImpl()->GetDocument(); EXPECT_FALSE(document.GetElementById("bold").IsNull()); - frame->SetCompositionFromExistingText(0, 4, underlines); + frame->SetCompositionFromExistingText(0, 4, ime_text_spans); EXPECT_FALSE(document.GetElementById("bold").IsNull()); } @@ -1562,17 +1562,17 @@ std::string composition_text_first("hello "); std::string composition_text_second("world"); - WebVector<WebCompositionUnderline> empty_underlines; + WebVector<WebImeTextSpan> empty_ime_text_spans; WebInputMethodController* active_input_method_controller = web_view->MainFrameImpl() ->FrameWidget() ->GetActiveWebInputMethodController(); active_input_method_controller->CommitText( - WebString::FromUTF8(composition_text_first.c_str()), empty_underlines, + WebString::FromUTF8(composition_text_first.c_str()), empty_ime_text_spans, WebRange(), 0); active_input_method_controller->SetComposition( - WebString::FromUTF8(composition_text_second.c_str()), empty_underlines, - WebRange(), 5, 5); + WebString::FromUTF8(composition_text_second.c_str()), + empty_ime_text_spans, WebRange(), 5, 5); WebTextInputInfo info = active_input_method_controller->TextInputInfo(); EXPECT_EQ("hello world", std::string(info.value.Utf8().data())); @@ -2825,10 +2825,10 @@ WebInputMethodController* active_input_method_controller = frame->FrameWidget()->GetActiveWebInputMethodController(); EXPECT_TRUE(TapElementById(WebInputEvent::kGestureTap, target)); - WebVector<WebCompositionUnderline> empty_underlines; + WebVector<WebImeTextSpan> empty_ime_text_spans; frame->SetEditableSelectionOffsets(8, 8); EXPECT_TRUE(active_input_method_controller->SetComposition( - "12345", empty_underlines, WebRange(), 8, 13)); + "12345", empty_ime_text_spans, WebRange(), 8, 13)); EXPECT_TRUE(frame->GetFrame()->GetInputMethodController().HasComposition()); EXPECT_EQ("", std::string(frame->SelectionAsText().Utf8().data())); EXPECT_FALSE(frame->GetFrame()->Selection().IsHandleVisible()); @@ -3209,9 +3209,9 @@ web_view->SetInitialFocus(false); // Set up a composition that needs to be committed. - WebVector<WebCompositionUnderline> empty_underlines; + WebVector<WebImeTextSpan> empty_ime_text_spans; frame->SetEditableSelectionOffsets(4, 10); - frame->SetCompositionFromExistingText(8, 12, empty_underlines); + frame->SetCompositionFromExistingText(8, 12, empty_ime_text_spans); WebTextInputInfo info = frame->GetInputMethodController()->TextInputInfo(); EXPECT_EQ(4, info.selection_start); EXPECT_EQ(10, info.selection_end); @@ -3253,12 +3253,12 @@ // Test both input elements. for (int i = 0; i < 2; ++i) { // Select composition and do sanity check. - WebVector<WebCompositionUnderline> empty_underlines; + WebVector<WebImeTextSpan> empty_ime_text_spans; frame->SetEditableSelectionOffsets(6, 6); WebInputMethodController* active_input_method_controller = frame->FrameWidget()->GetActiveWebInputMethodController(); EXPECT_TRUE(active_input_method_controller->SetComposition( - "fghij", empty_underlines, WebRange(), 0, 5)); + "fghij", empty_ime_text_spans, WebRange(), 0, 5)); frame->SetEditableSelectionOffsets(11, 11); VerifySelectionAndComposition(web_view, 11, 11, 6, 11, "initial case"); @@ -3273,7 +3273,7 @@ frame->SetEditableSelectionOffsets(6, 6); EXPECT_TRUE(active_input_method_controller->SetComposition( - "fghi", empty_underlines, WebRange(), 0, 4)); + "fghi", empty_ime_text_spans, WebRange(), 0, 4)); frame->SetEditableSelectionOffsets(10, 10); VerifySelectionAndComposition(web_view, 10, 10, 6, 10, "after pressing Backspace"); @@ -3305,9 +3305,9 @@ // Set up a composition that needs to be committed. std::string composition_text("testingtext"); - WebVector<WebCompositionUnderline> empty_underlines; + WebVector<WebImeTextSpan> empty_ime_text_spans; active_input_method_controller->SetComposition( - WebString::FromUTF8(composition_text.c_str()), empty_underlines, + WebString::FromUTF8(composition_text.c_str()), empty_ime_text_spans, WebRange(), 0, composition_text.length()); WebTextInputInfo info = active_input_method_controller->TextInputInfo(); @@ -3338,10 +3338,10 @@ frame->SetAutofillClient(&client); web_view->SetInitialFocus(false); - WebVector<WebCompositionUnderline> empty_underlines; + WebVector<WebImeTextSpan> empty_ime_text_spans; client.ClearChangeCounts(); - frame->SetCompositionFromExistingText(8, 12, empty_underlines); + frame->SetCompositionFromExistingText(8, 12, empty_ime_text_spans); WebTextInputInfo info = frame->GetInputMethodController()->TextInputInfo(); EXPECT_EQ("0123456789abcdefghijklmnopqrstuvwxyz", @@ -4079,7 +4079,7 @@ EXPECT_TRUE( frame->FrameWidget()->GetActiveWebInputMethodController()->SetComposition( WebString::FromUTF8(std::string("hello").c_str()), - WebVector<WebCompositionUnderline>(), WebRange(), 3, 3)); + WebVector<WebImeTextSpan>(), WebRange(), 3, 3)); EXPECT_EQ(1, client.TextChangesFromUserGesture()); EXPECT_FALSE(UserGestureIndicator::ProcessingUserGesture()); EXPECT_TRUE(frame->HasMarkedText()); @@ -4482,12 +4482,12 @@ frame->SetAutofillClient(&client); web_view->SetInitialFocus(false); - WebVector<WebCompositionUnderline> empty_underlines; + WebVector<WebImeTextSpan> empty_ime_text_spans; EXPECT_TRUE( frame->FrameWidget()->GetActiveWebInputMethodController()->CommitText( - WebString::FromUTF8(std::string("hello").c_str()), empty_underlines, - WebRange(), 0)); + WebString::FromUTF8(std::string("hello").c_str()), + empty_ime_text_spans, WebRange(), 0)); EXPECT_EQ(1, client.TextChangesFromUserGesture()); EXPECT_FALSE(UserGestureIndicator::ProcessingUserGesture()); frame->SetAutofillClient(0);
diff --git a/third_party/WebKit/Source/core/frame/BrowserControls.cpp b/third_party/WebKit/Source/core/frame/BrowserControls.cpp index 46a13e38..241b830c 100644 --- a/third_party/WebKit/Source/core/frame/BrowserControls.cpp +++ b/third_party/WebKit/Source/core/frame/BrowserControls.cpp
@@ -80,8 +80,8 @@ top_height_ ? ContentOffset() : BottomContentOffset(); } -float BrowserControls::LayoutHeight() { - return shrink_viewport_ ? top_height_ + bottom_height_ : 0; +float BrowserControls::UnreportedSizeAdjustment() { + return (shrink_viewport_ ? top_height_ : 0) - ContentOffset(); } float BrowserControls::ContentOffset() {
diff --git a/third_party/WebKit/Source/core/frame/BrowserControls.h b/third_party/WebKit/Source/core/frame/BrowserControls.h index 7c61fc2..6dd983c 100644 --- a/third_party/WebKit/Source/core/frame/BrowserControls.h +++ b/third_party/WebKit/Source/core/frame/BrowserControls.h
@@ -30,12 +30,11 @@ DECLARE_TRACE(); - // The amount that the viewport was shrunk by to accommodate the top - // controls. - float LayoutHeight(); + // The height the top controls are hidden; used for viewport adjustments + // while the controls are resizing. + float UnreportedSizeAdjustment(); // The amount that browser controls are currently shown. float ContentOffset(); - float BottomContentOffset(); float TopHeight() const { return top_height_; } float BottomHeight() const { return bottom_height_; } @@ -61,6 +60,7 @@ private: explicit BrowserControls(const Page&); void ResetBaseline(); + float BottomContentOffset(); Member<const Page> page_;
diff --git a/third_party/WebKit/Source/core/frame/BrowserControlsTest.cpp b/third_party/WebKit/Source/core/frame/BrowserControlsTest.cpp index 3596e526..04c0027 100644 --- a/third_party/WebKit/Source/core/frame/BrowserControlsTest.cpp +++ b/third_party/WebKit/Source/core/frame/BrowserControlsTest.cpp
@@ -1132,4 +1132,40 @@ } } +// Test the size adjustment sent to the viewport when top controls exist. +TEST_F(BrowserControlsTest, MAYBE(TopControlsSizeAdjustment)) { + WebViewImpl* web_view = Initialize(); + web_view->ResizeWithBrowserControls(web_view->Size(), 50.f, 0, false); + web_view->GetBrowserControls().SetShownRatio(1); + EXPECT_FLOAT_EQ(-50.f, + web_view->GetBrowserControls().UnreportedSizeAdjustment()); + + web_view->GetBrowserControls().SetShownRatio(0.5); + EXPECT_FLOAT_EQ(-25.f, + web_view->GetBrowserControls().UnreportedSizeAdjustment()); + + web_view->GetBrowserControls().SetShownRatio(0.0); + EXPECT_FLOAT_EQ(0.f, + web_view->GetBrowserControls().UnreportedSizeAdjustment()); +} + +// Test the size adjustment sent to the viewport when bottom controls exist. +// There should never be an adjustment since the bottom controls do not change +// the content offset. +TEST_F(BrowserControlsTest, MAYBE(BottomControlsSizeAdjustment)) { + WebViewImpl* web_view = Initialize(); + web_view->ResizeWithBrowserControls(web_view->Size(), 0, 50.f, false); + web_view->GetBrowserControls().SetShownRatio(1); + EXPECT_FLOAT_EQ(0.f, + web_view->GetBrowserControls().UnreportedSizeAdjustment()); + + web_view->GetBrowserControls().SetShownRatio(0.5); + EXPECT_FLOAT_EQ(0.f, + web_view->GetBrowserControls().UnreportedSizeAdjustment()); + + web_view->GetBrowserControls().SetShownRatio(0.0); + EXPECT_FLOAT_EQ(0.f, + web_view->GetBrowserControls().UnreportedSizeAdjustment()); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp index d4bff49..fce9db4 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp +++ b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
@@ -208,12 +208,14 @@ needs_paint_property_update_(true), current_update_lifecycle_phases_target_state_( DocumentLifecycle::kUninitialized), + past_layout_lifecycle_update_(false), scroll_anchor_(this), scrollbar_manager_(*this), needs_scrollbars_update_(false), suppress_adjust_view_size_(false), allows_layout_invalidation_after_layout_clean_(true), forcing_layout_parent_view_(false), + needs_intersection_observation_(false), main_thread_scrolling_reasons_(0), paint_frame_count_(0) { Init(); @@ -3143,6 +3145,9 @@ return; } + AutoReset<bool> past_layout_lifecycle_update(&past_layout_lifecycle_update_, + true); + ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) { frame_view.PerformScrollAnchoringAdjustments(); }); @@ -4977,6 +4982,7 @@ child = child->Tree().NextSibling()) { child->View()->UpdateViewportIntersectionsForSubtree(target_state); } + needs_intersection_observation_ = false; } void LocalFrameView::UpdateRenderThrottlingStatusForTesting() { @@ -5137,9 +5143,23 @@ total_screens_away)); } +void LocalFrameView::SetNeedsIntersectionObservation() { + needs_intersection_observation_ = true; + if (LocalFrameView* parent = ParentFrameView()) + parent->SetNeedsIntersectionObservation(); +} + bool LocalFrameView::ShouldThrottleRendering() const { - return CanThrottleRendering() && frame_->GetDocument() && - Lifecycle().ThrottlingAllowed(); + bool throttled_for_global_reasons = CanThrottleRendering() && + frame_->GetDocument() && + Lifecycle().ThrottlingAllowed(); + if (!throttled_for_global_reasons) + return false; + + // Only lifecycle phases up to layout are needed to generate an + // intersection observation. + return !needs_intersection_observation_ || + GetFrame().LocalFrameRoot().View()->past_layout_lifecycle_update_; } bool LocalFrameView::CanThrottleRendering() const {
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.h b/third_party/WebKit/Source/core/frame/LocalFrameView.h index 827c27a..75319ca 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrameView.h +++ b/third_party/WebKit/Source/core/frame/LocalFrameView.h
@@ -182,6 +182,10 @@ void SetNeedsUpdateGeometries() { needs_update_geometries_ = true; } void UpdateGeometry() override; + // Marks this frame, and ancestor frames, as needing one intersection + // observervation. This overrides throttling for one frame. + void SetNeedsIntersectionObservation(); + // Methods for getting/setting the size Blink should use to layout the // contents. // NOTE: Scrollbar exclusion is based on the LocalFrameView's scrollbars. To @@ -1181,6 +1185,7 @@ // This is set on the local root frame view only. DocumentLifecycle::LifecycleState current_update_lifecycle_phases_target_state_; + bool past_layout_lifecycle_update_; ScrollAnchor scroll_anchor_; using AnchoringAdjustmentQueue = @@ -1194,6 +1199,7 @@ bool suppress_adjust_view_size_; bool allows_layout_invalidation_after_layout_clean_; bool forcing_layout_parent_view_; + bool needs_intersection_observation_; Member<ElementVisibilityObserver> visibility_observer_;
diff --git a/third_party/WebKit/Source/core/frame/WebFrameWidgetImpl.cpp b/third_party/WebKit/Source/core/frame/WebFrameWidgetImpl.cpp index eab267d..d205f37 100644 --- a/third_party/WebKit/Source/core/frame/WebFrameWidgetImpl.cpp +++ b/third_party/WebKit/Source/core/frame/WebFrameWidgetImpl.cpp
@@ -35,7 +35,6 @@ #include "build/build_config.h" #include "core/animation/CompositorMutatorImpl.h" #include "core/dom/UserGestureIndicator.h" -#include "core/editing/CompositionUnderlineVectorBuilder.h" #include "core/editing/EditingUtilities.h" #include "core/editing/Editor.h" #include "core/editing/FrameSelection.h"
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp index e652c8c5..4aebd03 100644 --- a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp +++ b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
@@ -109,11 +109,11 @@ #include "core/dom/NodeTraversal.h" #include "core/dom/ShadowRoot.h" #include "core/dom/UserGestureIndicator.h" -#include "core/editing/CompositionUnderlineVectorBuilder.h" #include "core/editing/EditingUtilities.h" #include "core/editing/Editor.h" #include "core/editing/FindInPageCoordinates.h" #include "core/editing/FrameSelection.h" +#include "core/editing/ImeTextSpanVectorBuilder.h" #include "core/editing/InputMethodController.h" #include "core/editing/PlainTextRange.h" #include "core/editing/SetSelectionData.h" @@ -954,7 +954,7 @@ void WebLocalFrameImpl::SetMarkedText(const WebString& text, unsigned location, unsigned length) { - Vector<CompositionUnderline> decorations; + Vector<ImeTextSpan> decorations; GetFrame()->GetInputMethodController().SetComposition(text, decorations, location, length); } @@ -1289,7 +1289,7 @@ bool WebLocalFrameImpl::SetCompositionFromExistingText( int composition_start, int composition_end, - const WebVector<WebCompositionUnderline>& underlines) { + const WebVector<WebImeTextSpan>& ime_text_spans) { TRACE_EVENT0("blink", "WebLocalFrameImpl::setCompositionFromExistingText"); if (!GetFrame()->GetEditor().CanEdit()) return false; @@ -1302,7 +1302,7 @@ GetFrame()->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets(); input_method_controller.SetCompositionFromExistingText( - CompositionUnderlineVectorBuilder::Build(underlines), composition_start, + ImeTextSpanVectorBuilder::Build(ime_text_spans), composition_start, composition_end); return true;
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h index 9cc9467e..548d045 100644 --- a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h +++ b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h
@@ -203,7 +203,7 @@ bool SetCompositionFromExistingText( int composition_start, int composition_end, - const WebVector<WebCompositionUnderline>& underlines) override; + const WebVector<WebImeTextSpan>& ime_text_spans) override; void ExtendSelectionAndDelete(int before, int after) override; void DeleteSurroundingText(int before, int after) override; void DeleteSurroundingTextInCodePoints(int before, int after) override;
diff --git a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp index cc56c1e..bb40501a 100644 --- a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp +++ b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp
@@ -137,12 +137,8 @@ BackgroundHTMLParser::~BackgroundHTMLParser() {} void BackgroundHTMLParser::AppendRawBytesFromMainThread( - std::unique_ptr<Vector<char>> buffer, - double bytes_received_time) { + std::unique_ptr<Vector<char>> buffer) { DCHECK(decoder_); - DEFINE_STATIC_LOCAL(CustomCountHistogram, queue_delay, - ("Parser.AppendBytesDelay", 1, 5000, 50)); - queue_delay.Count(MonotonicallyIncreasingTimeMS() - bytes_received_time); UpdateDocument(decoder_->Decode(buffer->data(), buffer->size())); }
diff --git a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.h b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.h index bedb00d2..b67a00a 100644 --- a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.h +++ b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.h
@@ -89,8 +89,7 @@ String unparsed_input; }; - void AppendRawBytesFromMainThread(std::unique_ptr<Vector<char>>, - double bytes_received_time); + void AppendRawBytesFromMainThread(std::unique_ptr<Vector<char>>); void SetDecoder(std::unique_ptr<TextResourceDecoder>); void Flush(); void ResumeFrom(std::unique_ptr<Checkpoint>);
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp index 4a3dde3..f4243eb 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
@@ -181,18 +181,6 @@ } void HTMLDocumentParser::Detach() { - if (!IsParsingFragment() && tokenized_chunk_queue_.Get() && - tokenized_chunk_queue_->PeakPendingChunkCount()) { - DEFINE_STATIC_LOCAL(CustomCountHistogram, peak_pending_chunk_histogram, - ("Parser.PeakPendingChunkCount", 1, 1000, 50)); - peak_pending_chunk_histogram.Count( - tokenized_chunk_queue_->PeakPendingChunkCount()); - DEFINE_STATIC_LOCAL(CustomCountHistogram, peak_pending_token_histogram, - ("Parser.PeakPendingTokenCount", 1, 100000, 50)); - peak_pending_token_histogram.Count( - tokenized_chunk_queue_->PeakPendingTokenCount()); - } - if (have_background_parser_) StopBackgroundParser(); DocumentParser::Detach(); @@ -1186,7 +1174,6 @@ return; if (ShouldUseThreading()) { - double bytes_received_time = MonotonicallyIncreasingTimeMS(); if (!have_background_parser_) StartBackgroundParser(); @@ -1199,8 +1186,7 @@ loading_task_runner_->PostTask( BLINK_FROM_HERE, WTF::Bind(&BackgroundHTMLParser::AppendRawBytesFromMainThread, - background_parser_, WTF::Passed(std::move(buffer)), - bytes_received_time)); + background_parser_, WTF::Passed(std::move(buffer)))); return; }
diff --git a/third_party/WebKit/Source/core/html/parser/TokenizedChunkQueue.cpp b/third_party/WebKit/Source/core/html/parser/TokenizedChunkQueue.cpp index dac3543..528ecd3 100644 --- a/third_party/WebKit/Source/core/html/parser/TokenizedChunkQueue.cpp +++ b/third_party/WebKit/Source/core/html/parser/TokenizedChunkQueue.cpp
@@ -16,20 +16,12 @@ bool TokenizedChunkQueue::Enqueue( std::unique_ptr<HTMLDocumentParser::TokenizedChunk> chunk) { - pending_token_count_ += chunk->tokens->size(); - peak_pending_token_count_ = - std::max(peak_pending_token_count_, pending_token_count_); - bool was_empty = pending_chunks_.IsEmpty(); pending_chunks_.push_back(std::move(chunk)); - peak_pending_chunk_count_ = - std::max(peak_pending_chunk_count_, pending_chunks_.size()); - return was_empty; } void TokenizedChunkQueue::Clear() { - pending_token_count_ = 0; pending_chunks_.clear(); } @@ -39,12 +31,4 @@ pending_chunks_.swap(vector); } -size_t TokenizedChunkQueue::PeakPendingChunkCount() { - return peak_pending_chunk_count_; -} - -size_t TokenizedChunkQueue::PeakPendingTokenCount() { - return peak_pending_token_count_; -} - } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/parser/TokenizedChunkQueue.h b/third_party/WebKit/Source/core/html/parser/TokenizedChunkQueue.h index e84cd88..b7080a4 100644 --- a/third_party/WebKit/Source/core/html/parser/TokenizedChunkQueue.h +++ b/third_party/WebKit/Source/core/html/parser/TokenizedChunkQueue.h
@@ -35,16 +35,11 @@ void Clear(); void TakeAll(Vector<std::unique_ptr<HTMLDocumentParser::TokenizedChunk>>&); - size_t PeakPendingChunkCount(); - size_t PeakPendingTokenCount(); private: TokenizedChunkQueue(); Vector<std::unique_ptr<HTMLDocumentParser::TokenizedChunk>> pending_chunks_; - size_t peak_pending_chunk_count_ = 0; - size_t peak_pending_token_count_ = 0; - size_t pending_token_count_ = 0; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/input/ScrollManager.cpp b/third_party/WebKit/Source/core/input/ScrollManager.cpp index ec6c58a..218f6c69 100644 --- a/third_party/WebKit/Source/core/input/ScrollManager.cpp +++ b/third_party/WebKit/Source/core/input/ScrollManager.cpp
@@ -591,9 +591,6 @@ if (scrollbar) { bool should_update_capture = false; - // scrollbar->gestureEvent always returns true for touchpad based GSB - // events. Therefore, while mouse is over a fully scrolled scrollbar, GSB - // won't propagate to the next scrollable layer. if (scrollbar->GestureEvent(gesture_event, &should_update_capture)) { if (should_update_capture) scrollbar_handling_scroll_gesture_ = scrollbar;
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json index b6ed8c1..1a922071 100644 --- a/third_party/WebKit/Source/core/inspector/browser_protocol.json +++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -1096,8 +1096,8 @@ { "name": "securityState", "$ref": "SecurityState", "description": "Security state representing the severity of the factor being explained." }, { "name": "summary", "type": "string", "description": "Short phrase describing the type of factor." }, { "name": "description", "type": "string", "description": "Full text explanation of the factor." }, - { "name": "hasCertificate", "type": "boolean", "description": "True if the page has a certificate." }, - { "name": "mixedContentType", "$ref": "MixedContentType", "description": "The type of mixed content described by the explanation." } + { "name": "mixedContentType", "$ref": "MixedContentType", "description": "The type of mixed content described by the explanation." }, + { "name": "certificate", "type": "array", "items": { "type": "string" }, "description": "Page certificate." } ], "description": "An explanation of an factor contributing to the security state." }, @@ -1132,10 +1132,6 @@ "description": "Disables tracking security state changes." }, { - "name": "showCertificateViewer", - "description": "Displays native dialog with the certificate details." - }, - { "name": "handleCertificateError", "description": "Handles a certificate error that fired a certificateError event.", "parameters": [ @@ -4970,6 +4966,17 @@ ] }, { + "name": "getVersion", + "description": "Returns version information.", + "returns": [ + { "name": "protocolVersion", "type": "string", "description": "Protocol version." }, + { "name": "product", "type": "string", "description": "Product name." }, + { "name": "revision", "type": "string", "description": "Product revision." }, + { "name": "userAgent", "type": "string", "description": "User-Agent." }, + { "name": "jsVersion", "type": "string", "description": "V8 version." } + ] + }, + { "name": "setWindowBounds", "description": "Set position and/or size of the browser window.", "parameters": [
diff --git a/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.cpp b/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.cpp index e075155..69643fc 100644 --- a/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.cpp +++ b/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.cpp
@@ -257,8 +257,12 @@ new IntersectionObservation(*this, *target); target->EnsureIntersectionObserverData().AddObservation(*observation); observations_.insert(observation); - if (LocalFrameView* frame_view = target_frame->View()) + if (LocalFrameView* frame_view = target_frame->View()) { + // The IntersectionObsever spec requires that at least one observation + // be recorded afer observe() is called, even if the frame is throttled. + frame_view->SetNeedsIntersectionObservation(); frame_view->ScheduleAnimation(); + } } void IntersectionObserver::unobserve(Element* target,
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp index ca234d0d..68a3782 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -190,8 +190,7 @@ // to the canvas. Just dirty the entire canvas when our style changes // substantially. if ((diff.NeedsFullPaintInvalidation() || diff.NeedsLayout()) && - GetNode() && - (isHTMLHtmlElement(*GetNode()) || isHTMLBodyElement(*GetNode()))) { + GetNode() && (IsDocumentElement() || isHTMLBodyElement(*GetNode()))) { View()->SetShouldDoFullPaintInvalidation(); if (old_style->HasEntirelyFixedBackground() !=
diff --git a/third_party/WebKit/Source/core/layout/LayoutText.cpp b/third_party/WebKit/Source/core/layout/LayoutText.cpp index cf3b4cf..bb6974e 100644 --- a/third_party/WebKit/Source/core/layout/LayoutText.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutText.cpp
@@ -1634,12 +1634,7 @@ revealed_text = text_[last_typed_character_offset_to_reveal]; } - // Replace all grapheme clusters in the text with the mask character. - size_t length = NumGraphemeClusters(text_); - CHECK_LE(length, text_.length()); - text_.Truncate(length); text_.Fill(mask); - if (last_typed_character_offset_to_reveal >= 0) { text_.replace(last_typed_character_offset_to_reveal, 1, String(&revealed_text, 1));
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc index 276b2247..a7d0696 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
@@ -36,10 +36,10 @@ bool should_clear_left = (clear == EClear::kBoth || clear == EClear::kLeft); bool should_clear_right = (clear == EClear::kBoth || clear == EClear::kRight); - if (exclusions.last_left_float && should_clear_left) + if (exclusions.float_left_clear_offset && should_clear_left) return true; - if (exclusions.last_right_float && should_clear_right) + if (exclusions.float_right_clear_offset && should_clear_right) return true; auto should_clear_pred =
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_exclusion.cc b/third_party/WebKit/Source/core/layout/ng/ng_exclusion.cc index 444e00eb..dd32629 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_exclusion.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_exclusion.cc
@@ -49,37 +49,27 @@ return stream << value.ToString(); } -NGExclusions::NGExclusions() - : last_left_float(nullptr), last_right_float(nullptr) {} - -NGExclusions::NGExclusions(const NGExclusions& other) { - for (const auto& exclusion : other.storage) - Add(*exclusion); -} - void NGExclusions::Add(const NGExclusion& exclusion) { - storage.push_back(WTF::MakeUnique<NGExclusion>(exclusion)); - if (exclusion.type == NGExclusion::kFloatLeft) { - last_left_float = storage.rbegin()->get(); - } else if (exclusion.type == NGExclusion::kFloatRight) { - last_right_float = storage.rbegin()->get(); - } -} + storage.push_back(exclusion); + last_float_block_start = + std::max(last_float_block_start, exclusion.rect.BlockStartOffset()); -inline NGExclusions& NGExclusions::operator=(const NGExclusions& other) { - storage.clear(); - last_left_float = nullptr; - last_right_float = nullptr; - for (const auto& exclusion : other.storage) - Add(*exclusion); - return *this; + if (exclusion.type == NGExclusion::kFloatLeft) { + float_left_clear_offset = + std::max(float_left_clear_offset.value_or(LayoutUnit::Min()), + exclusion.rect.BlockEndOffset()); + } else if (exclusion.type == NGExclusion::kFloatRight) { + float_right_clear_offset = + std::max(float_right_clear_offset.value_or(LayoutUnit::Min()), + exclusion.rect.BlockEndOffset()); + } } bool NGExclusions::operator==(const NGExclusions& other) const { if (storage.size() != other.storage.size()) return false; for (size_t i = 0; i < storage.size(); ++i) { - if (*storage[i] != *other.storage[i]) + if (storage[i] != other.storage[i]) return false; } return true;
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_exclusion.h b/third_party/WebKit/Source/core/layout/ng/ng_exclusion.h index 9466dfb..465e1f87 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_exclusion.h +++ b/third_party/WebKit/Source/core/layout/ng/ng_exclusion.h
@@ -7,6 +7,7 @@ #include "core/CoreExport.h" #include "core/layout/ng/geometry/ng_logical_rect.h" +#include "platform/wtf/Optional.h" #include "platform/wtf/Vector.h" namespace blink { @@ -56,17 +57,18 @@ CORE_EXPORT std::ostream& operator<<(std::ostream&, const NGExclusion&); struct CORE_EXPORT NGExclusions { - NGExclusions(); - NGExclusions(const NGExclusions& other); + Vector<NGExclusion> storage; - Vector<std::unique_ptr<const NGExclusion>> storage; + // This member is used for implementing the "top edge alignment rule" for + // floats. Floats can be positioned at negative offsets, hence is initialized + // the minimum value. + LayoutUnit last_float_block_start = LayoutUnit::Min(); - // Last left/right float exclusions are used to enforce the top edge alignment - // rule for floats and for the support of CSS "clear" property. - const NGExclusion* last_left_float; // Owned by storage. - const NGExclusion* last_right_float; // Owned by storage. + // These members are used for keeping track of the "lowest" offset for each + // type of float. This is used for implementing float clearance. + Optional<LayoutUnit> float_left_clear_offset; + Optional<LayoutUnit> float_right_clear_offset; - NGExclusions& operator=(const NGExclusions& other); bool operator==(const NGExclusions& other) const; bool operator!=(const NGExclusions& other) const { return !(*this == other); }
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_floats_utils.cc b/third_party/WebKit/Source/core/layout/ng/ng_floats_utils.cc index b222f935..10fe94c8 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_floats_utils.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_floats_utils.cc
@@ -22,15 +22,9 @@ NGLogicalOffset AdjustToTopEdgeAlignmentRule(const NGConstraintSpace& space, const NGLogicalOffset& offset) { NGLogicalOffset adjusted_offset = offset; - LayoutUnit& adjusted_block_offset = adjusted_offset.block_offset; - if (space.Exclusions()->last_left_float) - adjusted_block_offset = - std::max(adjusted_block_offset, - space.Exclusions()->last_left_float->rect.BlockStartOffset()); - if (space.Exclusions()->last_right_float) - adjusted_block_offset = - std::max(adjusted_block_offset, - space.Exclusions()->last_right_float->rect.BlockStartOffset()); + adjusted_offset.block_offset = std::max( + adjusted_offset.block_offset, space.Exclusions()->last_float_block_start); + return adjusted_offset; }
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.cc b/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.cc index 3ae30d0..5f9ab6d 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.cc
@@ -228,10 +228,9 @@ } // Compares exclusions by their top position. -bool CompareNGExclusionsByTopAsc( - const std::unique_ptr<const NGExclusion>& lhs, - const std::unique_ptr<const NGExclusion>& rhs) { - return rhs->rect.offset.block_offset > lhs->rect.offset.block_offset; +bool CompareNGExclusionsByTopAsc(const NGExclusion& lhs, + const NGExclusion& rhs) { + return rhs.rect.offset.block_offset > lhs.rect.offset.block_offset; } // Compares Layout Opportunities by Start Point. @@ -294,14 +293,12 @@ NGLayoutOpportunity initial_opportunity = CreateInitialOpportunity(available_size, Offset()); - opportunity_tree_root_.reset( - new NGLayoutOpportunityTreeNode(initial_opportunity)); + NGLayoutOpportunityTreeNode tree(initial_opportunity); for (const auto& exclusion : exclusions->storage) { - InsertExclusion(MutableOpportunityTreeRoot(), exclusion.get(), - opportunities_); + InsertExclusion(&tree, &exclusion, opportunities_); } - CollectAllOpportunities(OpportunityTreeRoot(), opportunities_); + CollectAllOpportunities(&tree, opportunities_); std::sort(opportunities_.begin(), opportunities_.end(), &CompareNGLayoutOpportunitesByStartPoint); @@ -316,13 +313,4 @@ return NGLayoutOpportunity(*opportunity); } -#ifndef NDEBUG -void NGLayoutOpportunityIterator::ShowLayoutOpportunityTree() const { - StringBuilder string_builder; - string_builder.Append("\n.:: LayoutOpportunity Tree ::.\n\nRoot Node: "); - AppendNodeToString(opportunity_tree_root_.get(), &string_builder); - fprintf(stderr, "%s\n", string_builder.ToString().Utf8().data()); -} -#endif - } // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.h b/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.h index 6144fa7..41e19d9 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.h +++ b/third_party/WebKit/Source/core/layout/ng/ng_layout_opportunity_iterator.h
@@ -25,6 +25,8 @@ const NGLogicalSize& size); class CORE_EXPORT NGLayoutOpportunityIterator final { + STACK_ALLOCATED(); + public: // Default constructor. // @@ -59,19 +61,8 @@ #endif private: - // Mutable Getters. - NGLayoutOpportunityTreeNode* MutableOpportunityTreeRoot() { - return opportunity_tree_root_.get(); - } - - // Read-only Getters. - const NGLayoutOpportunityTreeNode* OpportunityTreeRoot() const { - return opportunity_tree_root_.get(); - } - NGLayoutOpportunities opportunities_; NGLayoutOpportunities::const_iterator opportunity_iter_; - std::unique_ptr<NGLayoutOpportunityTreeNode> opportunity_tree_root_; NGLogicalOffset offset_; };
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_space_utils.cc b/third_party/WebKit/Source/core/layout/ng/ng_space_utils.cc index f3cf053..382df0a 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_space_utils.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_space_utils.cc
@@ -12,50 +12,28 @@ #include "core/layout/ng/ng_writing_mode.h" namespace blink { -namespace { -// Returns max of 2 {@code WTF::Optional} values. -template <typename T> -WTF::Optional<T> OptionalMax(const WTF::Optional<T>& value1, - const WTF::Optional<T>& value2) { - if (value1 && value2) { - return std::max(value1.value(), value2.value()); - } else if (value1) { - return value1; - } - return value2; -} - -} // namespace - -WTF::Optional<LayoutUnit> GetClearanceOffset( - const std::shared_ptr<NGExclusions>& exclusions, - EClear clear_type) { - const NGExclusion* right_exclusion = exclusions->last_right_float; - const NGExclusion* left_exclusion = exclusions->last_left_float; - - WTF::Optional<LayoutUnit> left_offset; - if (left_exclusion) { - left_offset = left_exclusion->rect.BlockEndOffset(); - } - WTF::Optional<LayoutUnit> right_offset; - if (right_exclusion) { - right_offset = right_exclusion->rect.BlockEndOffset(); - } +LayoutUnit GetClearanceOffset(const std::shared_ptr<NGExclusions>& exclusions, + EClear clear_type) { + LayoutUnit float_left_clear_offset = + exclusions->float_left_clear_offset.value_or(LayoutUnit::Min()); + LayoutUnit float_right_clear_offset = + exclusions->float_right_clear_offset.value_or(LayoutUnit::Min()); switch (clear_type) { case EClear::kNone: - return WTF::nullopt; // nothing to do here. + return LayoutUnit::Min(); // nothing to do here. case EClear::kLeft: - return left_offset; + return float_left_clear_offset; case EClear::kRight: - return right_offset; + return float_right_clear_offset; case EClear::kBoth: - return OptionalMax<LayoutUnit>(left_offset, right_offset); + return std::max(float_left_clear_offset, float_right_clear_offset); default: NOTREACHED(); } - return WTF::nullopt; + + return LayoutUnit::Min(); } bool ShouldShrinkToFit(const ComputedStyle& parent_style,
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_space_utils.h b/third_party/WebKit/Source/core/layout/ng/ng_space_utils.h index c2c9737..1217b4f 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_space_utils.h +++ b/third_party/WebKit/Source/core/layout/ng/ng_space_utils.h
@@ -18,9 +18,9 @@ // Gets the clearance offset based on the provided {@code clear_type} and list // of exclusions that represent left/right float. -CORE_EXPORT WTF::Optional<LayoutUnit> GetClearanceOffset( - const std::shared_ptr<NGExclusions>& exclusions, - EClear clear_type); +CORE_EXPORT LayoutUnit +GetClearanceOffset(const std::shared_ptr<NGExclusions>& exclusions, + EClear clear_type); // Whether child's constraint space should shrink to its intrinsic width. // This is needed for buttons, select, input, floats and orthogonal children.
diff --git a/third_party/WebKit/Source/core/paint/EmbeddedContentPainter.cpp b/third_party/WebKit/Source/core/paint/EmbeddedContentPainter.cpp index 8ebba762..a260c8e 100644 --- a/third_party/WebKit/Source/core/paint/EmbeddedContentPainter.cpp +++ b/third_party/WebKit/Source/core/paint/EmbeddedContentPainter.cpp
@@ -62,10 +62,6 @@ return; if (layout_embedded_content_.GetEmbeddedContentView()) { - // TODO(schenney) crbug.com/93805 Speculative release assert to verify that - // the crashes we see in EmbeddedContentView painting are due to a destroyed - // LayoutEmbeddedContent object. - CHECK(layout_embedded_content_.GetNode()); Optional<RoundedInnerRectClipper> clipper; if (layout_embedded_content_.Style()->HasBorderRadius()) { if (border_rect.IsEmpty())
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp index abef542..48f1dd9 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
@@ -1973,10 +1973,6 @@ needs_composited_scrolling = false; } - // TODO(schenney) Tests fail if we do not also exclude - // layer->layoutObject().style()->hasBorderDecoration() (missing background - // behind dashed borders). Resolve this case, or not, and update this check - // with the results. if (layer->GetLayoutObject().Style()->HasBorderRadius()) { non_composited_main_thread_scrolling_reasons_ |= MainThreadScrollingReason::kHasBorderRadius;
diff --git a/third_party/WebKit/Source/core/paint/compositing/PaintLayerCompositor.h b/third_party/WebKit/Source/core/paint/compositing/PaintLayerCompositor.h index bc67cd7..f1cf7baa 100644 --- a/third_party/WebKit/Source/core/paint/compositing/PaintLayerCompositor.h +++ b/third_party/WebKit/Source/core/paint/compositing/PaintLayerCompositor.h
@@ -27,6 +27,7 @@ #define PaintLayerCompositor_h #include <memory> +#include "base/gtest_prod_util.h" #include "core/CoreExport.h" #include "core/dom/DocumentLifecycle.h" #include "core/paint/compositing/CompositingReasonFinder.h" @@ -298,6 +299,9 @@ std::unique_ptr<GraphicsLayer> layer_for_horizontal_scrollbar_; std::unique_ptr<GraphicsLayer> layer_for_vertical_scrollbar_; std::unique_ptr<GraphicsLayer> layer_for_scroll_corner_; + + FRIEND_TEST_ALL_PREFIXES(FrameThrottlingTest, + IntersectionObservationOverridesThrottling); }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/scheduler/FrameThrottlingTest.cpp b/third_party/WebKit/Source/core/scheduler/FrameThrottlingTest.cpp index 8db9bfb..49c5c1e 100644 --- a/third_party/WebKit/Source/core/scheduler/FrameThrottlingTest.cpp +++ b/third_party/WebKit/Source/core/scheduler/FrameThrottlingTest.cpp
@@ -189,6 +189,70 @@ EXPECT_TRUE(inner_frame_document->View()->CanThrottleRendering()); } +TEST_P(FrameThrottlingTest, IntersectionObservationOverridesThrottling) { + // Create a document with doubly nested iframes. + SimRequest main_resource("https://example.com/", "text/html"); + SimRequest frame_resource("https://example.com/iframe.html", "text/html"); + + LoadURL("https://example.com/"); + main_resource.Complete("<iframe id=frame src=iframe.html></iframe>"); + frame_resource.Complete("<iframe id=innerFrame sandbox></iframe>"); + + auto* frame_element = + toHTMLIFrameElement(GetDocument().getElementById("frame")); + auto* frame_document = frame_element->contentDocument(); + + auto* inner_frame_element = + toHTMLIFrameElement(frame_document->getElementById("innerFrame")); + auto* inner_frame_document = inner_frame_element->contentDocument(); + + DocumentLifecycle::AllowThrottlingScope throttling_scope( + GetDocument().Lifecycle()); + + // Hidden cross origin frames are throttled. + frame_element->setAttribute(styleAttr, "transform: translateY(480px)"); + CompositeFrame(); + EXPECT_FALSE(GetDocument().View()->CanThrottleRendering()); + EXPECT_FALSE(frame_document->View()->CanThrottleRendering()); + EXPECT_TRUE(inner_frame_document->View()->ShouldThrottleRendering()); + + // An intersection observation overrides... + inner_frame_document->View()->SetNeedsIntersectionObservation(); + EXPECT_FALSE(inner_frame_document->View()->ShouldThrottleRendering()); + inner_frame_document->View()->ScheduleAnimation(); + + LayoutView* inner_view = inner_frame_document->View()->GetLayoutView(); + + inner_view->SetNeedsLayout("test"); + inner_view->Compositor()->SetNeedsCompositingUpdate( + kCompositingUpdateRebuildTree); + inner_view->SetShouldDoFullPaintInvalidation( + PaintInvalidationReason::kForTesting); + inner_view->Layer()->SetNeedsRepaint(); + EXPECT_FALSE(inner_frame_document->View() + ->GetLayoutView() + ->FullPaintInvalidationReason() == + PaintInvalidationReason::kNone); + inner_view->Compositor()->SetNeedsCompositingUpdate( + kCompositingUpdateRebuildTree); + EXPECT_EQ(kCompositingUpdateRebuildTree, + inner_view->Compositor()->pending_update_type_); + EXPECT_TRUE(inner_view->Layer()->NeedsRepaint()); + + CompositeFrame(); + // ...but only for one frame. + EXPECT_TRUE(inner_frame_document->View()->ShouldThrottleRendering()); + + EXPECT_FALSE(inner_view->NeedsLayout()); + EXPECT_FALSE(inner_frame_document->View() + ->GetLayoutView() + ->FullPaintInvalidationReason() == + PaintInvalidationReason::kNone); + EXPECT_EQ(kCompositingUpdateRebuildTree, + inner_view->Compositor()->pending_update_type_); + EXPECT_TRUE(inner_view->Layer()->NeedsRepaint()); +} + TEST_P(FrameThrottlingTest, HiddenCrossOriginZeroByZeroFramesAreNotThrottled) { // Create a document with doubly nested iframes. SimRequest main_resource("https://example.com/", "text/html");
diff --git a/third_party/WebKit/Source/core/timing/PerformanceServerTiming.cpp b/third_party/WebKit/Source/core/timing/PerformanceServerTiming.cpp index 597b765..80eb269 100644 --- a/third_party/WebKit/Source/core/timing/PerformanceServerTiming.cpp +++ b/third_party/WebKit/Source/core/timing/PerformanceServerTiming.cpp
@@ -11,23 +11,23 @@ namespace blink { PerformanceServerTiming::PerformanceServerTiming( - const String& metric, - double value, + const String& name, + double duration, const String& description, ShouldAllowTimingDetails shouldAllowTimingDetails) - : metric_(metric), - value_(value), + : name_(name), + duration_(duration), description_(description), shouldAllowTimingDetails_(shouldAllowTimingDetails) {} PerformanceServerTiming::~PerformanceServerTiming() {} -String PerformanceServerTiming::metric() const { - return metric_; +String PerformanceServerTiming::name() const { + return name_; } -double PerformanceServerTiming::value() const { - return shouldAllowTimingDetails_ == ShouldAllowTimingDetails::Yes ? value_ +double PerformanceServerTiming::duration() const { + return shouldAllowTimingDetails_ == ShouldAllowTimingDetails::Yes ? duration_ : 0.0; } @@ -40,8 +40,8 @@ ScriptValue PerformanceServerTiming::toJSONForBinding( ScriptState* script_state) const { V8ObjectBuilder builder(script_state); - builder.AddString("metric", metric()); - builder.AddNumber("value", value()); + builder.AddString("name", name()); + builder.AddNumber("duration", duration()); builder.AddString("description", description()); return builder.GetScriptValue(); } @@ -56,7 +56,7 @@ response.HttpHeaderField(HTTPNames::Server_Timing)); for (const auto& header : *headers) { entries.push_back(new PerformanceServerTiming( - header->metric, header->value, header->description, + header->name, header->duration, header->description, shouldAllowTimingDetails)); } }
diff --git a/third_party/WebKit/Source/core/timing/PerformanceServerTiming.h b/third_party/WebKit/Source/core/timing/PerformanceServerTiming.h index 815bb363..9f0a2b49 100644 --- a/third_party/WebKit/Source/core/timing/PerformanceServerTiming.h +++ b/third_party/WebKit/Source/core/timing/PerformanceServerTiming.h
@@ -28,14 +28,14 @@ No, }; - PerformanceServerTiming(const String& metric, - double value, + PerformanceServerTiming(const String& name, + double duration, const String& description, ShouldAllowTimingDetails); ~PerformanceServerTiming(); - String metric() const; - double value() const; + String name() const; + double duration() const; String description() const; static PerformanceServerTimingVector ParseServerTiming( @@ -47,8 +47,8 @@ DEFINE_INLINE_VIRTUAL_TRACE() {} private: - const String metric_; - double value_; + const String name_; + double duration_; const String description_; ShouldAllowTimingDetails shouldAllowTimingDetails_; };
diff --git a/third_party/WebKit/Source/core/timing/PerformanceServerTiming.idl b/third_party/WebKit/Source/core/timing/PerformanceServerTiming.idl index fd4069e..5026f3a 100644 --- a/third_party/WebKit/Source/core/timing/PerformanceServerTiming.idl +++ b/third_party/WebKit/Source/core/timing/PerformanceServerTiming.idl
@@ -7,7 +7,7 @@ [ RuntimeEnabled=ServerTiming ] interface PerformanceServerTiming { - readonly attribute DOMString metric; - readonly attribute double value; + readonly attribute DOMString name; + readonly attribute DOMHighResTimeStamp duration; readonly attribute DOMString description; };
diff --git a/third_party/WebKit/Source/devtools/BUILD.gn b/third_party/WebKit/Source/devtools/BUILD.gn index 0ffc52c..34355b7 100644 --- a/third_party/WebKit/Source/devtools/BUILD.gn +++ b/third_party/WebKit/Source/devtools/BUILD.gn
@@ -19,6 +19,8 @@ "front_end/accessibility/axBreadcrumbs.css", "front_end/accessibility/AXBreadcrumbsPane.js", "front_end/accessibility/module.json", + "front_end/accessibility_test_runner/AccessibilityPaneTestRunner.js", + "front_end/accessibility_test_runner/module.json", "front_end/animation/AnimationGroupPreviewUI.js", "front_end/animation/AnimationModel.js", "front_end/animation/animationScreenshotPopover.css", @@ -27,6 +29,13 @@ "front_end/animation/AnimationTimeline.js", "front_end/animation/AnimationUI.js", "front_end/animation/module.json", + "front_end/application_test_runner/AppcacheTestRunner.js", + "front_end/application_test_runner/CacheStorageTestRunner.js", + "front_end/application_test_runner/IndexedDBTestRunner.js", + "front_end/application_test_runner/module.json", + "front_end/application_test_runner/ResourcesTestRunner.js", + "front_end/application_test_runner/ResourceTreeTestRunner.js", + "front_end/application_test_runner/ServiceWorkersTestRunner.js", "front_end/audits/AuditCategories.js", "front_end/audits/AuditCategory.js", "front_end/audits/AuditController.js", @@ -54,6 +63,8 @@ "front_end/audits2/lighthouse/renderer/report-renderer.js", "front_end/audits2/lighthouse/renderer/util.js", "front_end/audits2/module.json", + "front_end/audits_test_runner/AuditsTestRunner.js", + "front_end/audits_test_runner/module.json", "front_end/bindings/BlackboxManager.js", "front_end/bindings/BreakpointManager.js", "front_end/bindings/CompilerScriptMapping.js", @@ -72,6 +83,11 @@ "front_end/bindings/SASSSourceMapping.js", "front_end/bindings/StylesSourceMapping.js", "front_end/bindings/TempFile.js", + "front_end/bindings_test_runner/AutomappingTestRunner.js", + "front_end/bindings_test_runner/BindingsTestRunner.js", + "front_end/bindings_test_runner/IsolatedFilesystemTestRunner.js", + "front_end/bindings_test_runner/module.json", + "front_end/bindings_test_runner/PersistenceTestRunner.js", "front_end/changes/ChangesHighlighter.js", "front_end/changes/changesView.css", "front_end/changes/ChangesView.js", @@ -163,6 +179,8 @@ "front_end/coverage/coverageView.css", "front_end/coverage/CoverageView.js", "front_end/coverage/module.json", + "front_end/coverage_test_runner/CoverageTestRunner.js", + "front_end/coverage_test_runner/module.json", "front_end/data_grid/dataGrid.css", "front_end/data_grid/DataGrid.js", "front_end/data_grid/module.json", @@ -171,6 +189,8 @@ "front_end/data_grid/ViewportDataGrid.js", "front_end/data_grid_test_runner/DataGridTestRunner.js", "front_end/data_grid_test_runner/module.json", + "front_end/device_mode_test_runner/DeviceModeTestRunner.js", + "front_end/device_mode_test_runner/module.json", "front_end/devices/devicesView.css", "front_end/devices/DevicesView.js", "front_end/devices/module.json", @@ -209,6 +229,11 @@ "front_end/elements/stylesSectionTree.css", "front_end/elements/stylesSidebarPane.css", "front_end/elements/StylesSidebarPane.js", + "front_end/elements_test_runner/EditDOMTestRunner.js", + "front_end/elements_test_runner/ElementsPanelShadowSelectionOnRefreshTestRunner.js", + "front_end/elements_test_runner/ElementsTestRunner.js", + "front_end/elements_test_runner/SetOuterHTMLTestRunner.js", + "front_end/elements_test_runner/StylesUpdateLinksTestRunner.js", "front_end/emulated_devices/module.json", "front_end/emulation/AdvancedApp.js", "front_end/emulation/DeviceModeModel.js", @@ -238,6 +263,9 @@ "front_end/extensions/ExtensionServer.js", "front_end/extensions/ExtensionView.js", "front_end/extensions/module.json", + "front_end/extensions_test_runner/ExtensionsNetworkTestRunner.js", + "front_end/extensions_test_runner/ExtensionsTestRunner.js", + "front_end/extensions_test_runner/module.json", "front_end/formatter/FormatterWorkerPool.js", "front_end/formatter/module.json", "front_end/formatter/ScriptFormatter.js", @@ -303,6 +331,8 @@ "front_end/integration_test_runner.json", "front_end/integration_test_runner/IntegrationTestRunner.js", "front_end/integration_test_runner/module.json", + "front_end/integration_test_runner/PageMockTestRunner.js", + "front_end/integration_test_runner/SyntaxHighlightTestRunner.js", "front_end/layer_viewer/layerDetailsView.css", "front_end/layer_viewer/LayerDetailsView.js", "front_end/layer_viewer/layers3DView.css", @@ -317,6 +347,8 @@ "front_end/layers/LayersPanel.js", "front_end/layers/LayerTreeModel.js", "front_end/layers/module.json", + "front_end/layers_test_runner/LayersTestRunner.js", + "front_end/layers_test_runner/module.json", "front_end/main/ExecutionContextSelector.js", "front_end/main/GCActionDelegate.js", "front_end/main/Main.js", @@ -374,6 +406,9 @@ "front_end/network_log/NetworkLog.js", "front_end/network_priorities/module.json", "front_end/network_priorities/NetworkPriorities.js", + "front_end/network_test_runner/module.json", + "front_end/network_test_runner/NetworkTestRunner.js", + "front_end/network_test_runner/ProductRegistryTestRunner.js", "front_end/object_ui/customPreviewComponent.css", "front_end/object_ui/CustomPreviewComponent.js", "front_end/object_ui/JavaScriptAutocomplete.js", @@ -401,6 +436,9 @@ "front_end/perf_ui/TimelineGrid.js", "front_end/perf_ui/timelineOverviewInfo.css", "front_end/perf_ui/TimelineOverviewPane.js", + "front_end/performance_test_runner/module.json", + "front_end/performance_test_runner/TimelineDataTestRunner.js", + "front_end/performance_test_runner/TimelineTestRunner.js", "front_end/persistence/Automapping.js", "front_end/persistence/DefaultMapping.js", "front_end/persistence/editFileSystemView.css", @@ -444,6 +482,9 @@ "front_end/profiler/ProfileView.js", "front_end/profiler/TargetsComboBoxController.js", "front_end/profiler/TopDownProfileDataGrid.js", + "front_end/profiler_test_runner/HeapSnapshotTestRunner.js", + "front_end/profiler_test_runner/module.json", + "front_end/profiler_test_runner/ProfilerTestRunner.js", "front_end/protocol/InspectorBackend.js", "front_end/protocol/module.json", "front_end/quick_open/CommandMenu.js", @@ -485,6 +526,8 @@ "front_end/sass/SASSProcessor.js", "front_end/sass/SASSSourceMapFactory.js", "front_end/sass/SASSSupport.js", + "front_end/sass_test_runner/module.json", + "front_end/sass_test_runner/SASSTestRunner.js", "front_end/screencast/InputModel.js", "front_end/screencast/module.json", "front_end/screencast/ScreencastApp.js", @@ -540,6 +583,8 @@ "front_end/security/SecurityModel.js", "front_end/security/SecurityPanel.js", "front_end/security/sidebar.css", + "front_end/security_test_runner/module.json", + "front_end/security_test_runner/SecurityTestRunner.js", "front_end/services/ServiceManager.js", "front_end/settings/frameworkBlackboxSettingsTab.css", "front_end/settings/FrameworkBlackboxSettingsTab.js", @@ -618,6 +663,12 @@ "front_end/sources/WorkspaceMappingTip.js", "front_end/sources/xhrBreakpointsSidebarPane.css", "front_end/sources/XHRBreakpointsSidebarPane.js", + "front_end/sources_test_runner/AutocompleteTestRunner.js", + "front_end/sources_test_runner/BreakpointManagerTestRunner.js", + "front_end/sources_test_runner/DebuggerTestRunner.js", + "front_end/sources_test_runner/EditorTestRunner.js", + "front_end/sources_test_runner/LiveEditTestRunner.js", + "front_end/sources_test_runner/SearchTestRunner.js", "front_end/sources_test_runner/SourcesTestRunner.js", "front_end/sources_test_runner/module.json", "front_end/terminal/terminal.css",
diff --git a/third_party/WebKit/Source/devtools/front_end/Runtime.js b/third_party/WebKit/Source/devtools/front_end/Runtime.js index b3123ed..f8dd1ac 100644 --- a/third_party/WebKit/Source/devtools/front_end/Runtime.js +++ b/third_party/WebKit/Source/devtools/front_end/Runtime.js
@@ -738,6 +738,7 @@ 'object_ui': 'ObjectUI', 'perf_ui': 'PerfUI', 'har_importer': 'HARImporter', + 'sass_test_runner': 'SASSTestRunner', }; var namespace = specialCases[this._name] || this._name.split('_').map(a => a.substring(0, 1).toUpperCase() + a.substring(1)).join(''); self[namespace] = self[namespace] || {};
diff --git a/third_party/WebKit/Source/devtools/front_end/accessibility_test_runner/AccessibilityPaneTestRunner.js b/third_party/WebKit/Source/devtools/front_end/accessibility_test_runner/AccessibilityPaneTestRunner.js new file mode 100644 index 0000000..7d19972 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/accessibility_test_runner/AccessibilityPaneTestRunner.js
@@ -0,0 +1,74 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +AccessibilityTestRunner.accessibilitySidebarPane = function() { + return self.runtime.sharedInstance(Accessibility.AccessibilitySidebarView); +}; + +AccessibilityTestRunner.selectNodeAndWaitForAccessibility = function(idValue) { + return new Promise(resolve => { + ElementsTestRunner.selectNodeWithId(idValue, function() { + self.runtime.sharedInstance(Accessibility.AccessibilitySidebarView).doUpdate().then(resolve); + }); + }); +}; + +AccessibilityTestRunner.dumpSelectedElementAccessibilityNode = function() { + var sidebarPane = AccessibilityTestRunner.accessibilitySidebarPane(); + + if (!sidebarPane) { + TestRunner.addResult('No sidebarPane in dumpSelectedElementAccessibilityNode'); + TestRunner.completeTest(); + return; + } + + AccessibilityTestRunner.dumpAccessibilityNode(sidebarPane._axNodeSubPane._axNode); +}; + +AccessibilityTestRunner.dumpAccessibilityNode = function(accessibilityNode) { + if (!accessibilityNode) { + TestRunner.addResult('<null>'); + TestRunner.completeTest(); + return; + } + + var builder = []; + builder.push(accessibilityNode.role().value); + builder.push((accessibilityNode.name() ? '"' + accessibilityNode.name().value + '"' : '<undefined>')); + + if (accessibilityNode.properties()) { + for (var property of accessibilityNode.properties()) { + if ('value' in property) + builder.push(property.name + '="' + property.value.value + '"'); + } + } + + TestRunner.addResult(builder.join(' ')); +}; + +AccessibilityTestRunner.findARIAAttributeTreeElement = function(attribute) { + var sidebarPane = AccessibilityTestRunner.accessibilitySidebarPane(); + + if (!sidebarPane) { + TestRunner.addResult('Could not get Accessibility sidebar pane.'); + TestRunner.completeTest(); + return; + } + + var ariaSubPane = sidebarPane._ariaSubPane; + var treeOutline = ariaSubPane._treeOutline; + var childNodes = treeOutline._rootElement._children; + + for (var treeElement of childNodes) { + if (treeElement._attribute.name === attribute) + return treeElement; + } + + return null; +};
diff --git a/third_party/WebKit/Source/devtools/front_end/accessibility_test_runner/module.json b/third_party/WebKit/Source/devtools/front_end/accessibility_test_runner/module.json new file mode 100644 index 0000000..aac49bd --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/accessibility_test_runner/module.json
@@ -0,0 +1,14 @@ +{ + "dependencies": [ + "test_runner", + "integration_test_runner", + "accessibility", + "elements_test_runner" + ], + "scripts": [ + "AccessibilityPaneTestRunner.js" + ], + "skip_compilation": [ + "AccessibilityPaneTestRunner.js" + ] +}
diff --git a/third_party/WebKit/Source/devtools/front_end/application_test_runner/AppcacheTestRunner.js b/third_party/WebKit/Source/devtools/front_end/application_test_runner/AppcacheTestRunner.js new file mode 100644 index 0000000..17c8274 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/application_test_runner/AppcacheTestRunner.js
@@ -0,0 +1,215 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +ApplicationTestRunner.createAndNavigateIFrame = function(url, callback) { + TestRunner.addSniffer(SDK.ResourceTreeModel.prototype, '_frameNavigated', frameNavigated); + TestRunner.evaluateInPage('createAndNavigateIFrame(unescape(\'' + escape(url) + '\'))'); + + function frameNavigated(frame) { + callback(frame.id); + } +}; + +ApplicationTestRunner.navigateIFrame = function(frameId, url, callback) { + var frame = TestRunner.resourceTreeModel.frameForId(frameId); + TestRunner.evaluateInPage( + 'navigateIFrame(unescape(\'' + escape(frame.name) + '\'), unescape(\'' + escape(url) + '\'))'); + TestRunner.addSniffer(SDK.ResourceTreeModel.prototype, '_frameNavigated', frameNavigated); + + function frameNavigated(frame) { + callback(frame.id); + } +}; + +ApplicationTestRunner.removeIFrame = function(frameId, callback) { + var frame = TestRunner.resourceTreeModel.frameForId(frameId); + TestRunner.evaluateInPage('removeIFrame(unescape(\'' + escape(frame.name) + '\'))'); + TestRunner.addSniffer(SDK.ResourceTreeModel.prototype, '_frameDetached', frameDetached); + + function frameDetached(frame) { + callback(frame.id); + } +}; + +ApplicationTestRunner.swapFrameCache = function(frameId) { + var frame = TestRunner.resourceTreeModel.frameForId(frameId); + TestRunner.evaluateInPage('swapFrameCache(unescape(\'' + escape(frame.name) + '\'))'); +}; + +ApplicationTestRunner.dumpApplicationCache = function() { + ApplicationTestRunner.dumpApplicationCacheTree(); + ApplicationTestRunner.dumpApplicationCacheModel(); + TestRunner.addResult(''); +}; + +ApplicationTestRunner.dumpApplicationCacheTree = function() { + TestRunner.addResult('Dumping application cache tree:'); + var applicationCacheTreeElement = UI.panels.resources._sidebar.applicationCacheListTreeElement; + + if (!applicationCacheTreeElement.childCount()) { + TestRunner.addResult(' (empty)'); + return; + } + + for (var i = 0; i < applicationCacheTreeElement.childCount(); ++i) { + var manifestTreeElement = applicationCacheTreeElement.childAt(i); + TestRunner.addResult(' Manifest URL: ' + manifestTreeElement.manifestURL); + + if (!manifestTreeElement.childCount()) { + TestRunner.addResult(' (no frames)'); + continue; + } + + for (var j = 0; j < manifestTreeElement.childCount(); ++j) { + var frameTreeElement = manifestTreeElement.childAt(j); + TestRunner.addResult(' Frame: ' + frameTreeElement.title); + } + } +}; + +ApplicationTestRunner.frameIdToString = function(frameId) { + if (!ApplicationTestRunner.framesByFrameId) + ApplicationTestRunner.framesByFrameId = {}; + + var frame = TestRunner.resourceTreeModel.frameForId(frameId); + + if (!frame) + frame = ApplicationTestRunner.framesByFrameId[frameId]; + + ApplicationTestRunner.framesByFrameId[frameId] = frame; + return frame.name; +}; + +ApplicationTestRunner.applicationCacheStatusToString = function(status) { + var statusInformation = {}; + statusInformation[applicationCache.UNCACHED] = 'UNCACHED'; + statusInformation[applicationCache.IDLE] = 'IDLE'; + statusInformation[applicationCache.CHECKING] = 'CHECKING'; + statusInformation[applicationCache.DOWNLOADING] = 'DOWNLOADING'; + statusInformation[applicationCache.UPDATEREADY] = 'UPDATEREADY'; + statusInformation[applicationCache.OBSOLETE] = 'OBSOLETE'; + return statusInformation[status] || statusInformation[applicationCache.UNCACHED]; +}; + +ApplicationTestRunner.dumpApplicationCacheModel = function() { + TestRunner.addResult('Dumping application cache model:'); + var model = UI.panels.resources._sidebar._applicationCacheModel; + var frameIds = []; + + for (var frameId in model._manifestURLsByFrame) + frameIds.push(frameId); + + function compareFunc(a, b) { + return ApplicationTestRunner.frameIdToString(a).localeCompare(ApplicationTestRunner.frameIdToString(b)); + } + + frameIds.sort(compareFunc); + + if (!frameIds.length) { + TestRunner.addResult(' (empty)'); + return; + } + + for (var i = 0; i < frameIds.length; ++i) { + var frameId = frameIds[i]; + var manifestURL = model.frameManifestURL(frameId); + var status = model.frameManifestStatus(frameId); + TestRunner.addResult(' Frame: ' + ApplicationTestRunner.frameIdToString(frameId)); + TestRunner.addResult(' manifest url: ' + manifestURL); + TestRunner.addResult(' status: ' + ApplicationTestRunner.applicationCacheStatusToString(status)); + } +}; + +ApplicationTestRunner.waitForFrameManifestURLAndStatus = function(frameId, manifestURL, status, callback) { + var frameManifestStatus = UI.panels.resources._sidebar._applicationCacheModel.frameManifestStatus(frameId); + var frameManifestURL = UI.panels.resources._sidebar._applicationCacheModel.frameManifestURL(frameId); + + if (frameManifestStatus === status && frameManifestURL.indexOf(manifestURL) !== -1) { + callback(); + return; + } + + var handler = + ApplicationTestRunner.waitForFrameManifestURLAndStatus.bind(this, frameId, manifestURL, status, callback); + TestRunner.addSniffer(Resources.ApplicationCacheModel.prototype, '_frameManifestUpdated', handler); +}; + +ApplicationTestRunner.startApplicationCacheStatusesRecording = function() { + if (ApplicationTestRunner.applicationCacheStatusesRecords) { + ApplicationTestRunner.applicationCacheStatusesRecords = {}; + return; + } + + ApplicationTestRunner.applicationCacheStatusesRecords = {}; + + function addRecord(frameId, manifestURL, status) { + var record = {}; + record.manifestURL = manifestURL; + record.status = status; + + if (!ApplicationTestRunner.applicationCacheStatusesRecords[frameId]) + ApplicationTestRunner.applicationCacheStatusesRecords[frameId] = []; + + ApplicationTestRunner.applicationCacheStatusesRecords[frameId].push(record); + + if (ApplicationTestRunner.awaitedFrameStatusEventsCount && + ApplicationTestRunner.awaitedFrameStatusEventsCount[frameId]) { + ApplicationTestRunner.awaitedFrameStatusEventsCount[frameId].count--; + + if (!ApplicationTestRunner.awaitedFrameStatusEventsCount[frameId].count) + ApplicationTestRunner.awaitedFrameStatusEventsCount[frameId].callback(); + } + } + + TestRunner.addSniffer(Resources.ApplicationCacheModel.prototype, '_frameManifestUpdated', addRecord, true); +}; + +ApplicationTestRunner.ensureFrameStatusEventsReceived = function(frameId, count, callback) { + var records = ApplicationTestRunner.applicationCacheStatusesRecords[frameId] || []; + var eventsLeft = count - records.length; + + if (!eventsLeft) { + callback(); + return; + } + + if (!ApplicationTestRunner.awaitedFrameStatusEventsCount) + ApplicationTestRunner.awaitedFrameStatusEventsCount = {}; + + ApplicationTestRunner.awaitedFrameStatusEventsCount[frameId] = {count: eventsLeft, callback: callback}; +}; + +(async function() { + await TestRunner.evaluateInPagePromise(` + var framesCount = 0; + + function createAndNavigateIFrame(url) { + var iframe = document.createElement('iframe'); + iframe.src = url; + iframe.name = 'frame' + ++framesCount; + iframe.id = iframe.name; + document.body.appendChild(iframe); + } + + function removeIFrame(name) { + var iframe = document.querySelector('#' + name); + iframe.parentElement.removeChild(iframe); + } + + function navigateIFrame(name, url) { + var iframe = document.querySelector('#' + name); + iframe.src = url; + } + + function swapFrameCache(name) { + var iframe = document.querySelector('#' + name); + iframe.contentWindow.applicationCache.swapCache(); + } + `); +})();
diff --git a/third_party/WebKit/Source/devtools/front_end/application_test_runner/CacheStorageTestRunner.js b/third_party/WebKit/Source/devtools/front_end/application_test_runner/CacheStorageTestRunner.js new file mode 100644 index 0000000..2a290155 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/application_test_runner/CacheStorageTestRunner.js
@@ -0,0 +1,173 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +ApplicationTestRunner.dumpCacheTree = async function() { + UI.panels.resources._sidebar.cacheStorageListTreeElement.expand(); + TestRunner.addResult('Dumping CacheStorage tree:'); + var cachesTreeElement = UI.panels.resources._sidebar.cacheStorageListTreeElement; + var promise = TestRunner.addSnifferPromise(SDK.ServiceWorkerCacheModel.prototype, '_updateCacheNames'); + UI.panels.resources._sidebar.cacheStorageListTreeElement._refreshCaches(); + await promise; + + if (!cachesTreeElement.childCount()) { + TestRunner.addResult(' (empty)'); + return; + } + + for (var i = 0; i < cachesTreeElement.childCount(); ++i) { + var cacheTreeElement = cachesTreeElement.childAt(i); + TestRunner.addResult(' cache: ' + cacheTreeElement.title); + var view = cacheTreeElement._view; + promise = TestRunner.addSnifferPromise(Resources.ServiceWorkerCacheView.prototype, '_updateDataCallback'); + + if (!view) + cacheTreeElement.onselect(false); + else + view._updateData(true); + + view = cacheTreeElement._view; + await promise; + + if (view._entries.length === 0) { + TestRunner.addResult(' (cache empty)'); + continue; + } + + var dataGrid = view._dataGrid; + + for (var node of dataGrid.rootNode().children) { + var children = Array.from(node.element().children).filter(function(element) { + return !element.classList.contains('responseTime-column'); + }); + + var entries = Array.from(children, td => td.textContent).filter(text => text); + TestRunner.addResult(' ' + entries.join(', ')); + } + } +}; + +ApplicationTestRunner.deleteCacheFromInspector = async function(cacheName, optionalEntry) { + UI.panels.resources._sidebar.cacheStorageListTreeElement.expand(); + + if (optionalEntry) + TestRunner.addResult('Deleting CacheStorage entry ' + optionalEntry + ' in cache ' + cacheName); + else + TestRunner.addResult('Deleting CacheStorage cache ' + cacheName); + + var cachesTreeElement = UI.panels.resources._sidebar.cacheStorageListTreeElement; + var promise = TestRunner.addSnifferPromise(SDK.ServiceWorkerCacheModel.prototype, '_updateCacheNames'); + UI.panels.resources._sidebar.cacheStorageListTreeElement._refreshCaches(); + await promise; + + if (!cachesTreeElement.childCount()) + throw 'Error: Could not find CacheStorage cache ' + cacheName; + + + for (var i = 0; i < cachesTreeElement.childCount(); i++) { + var cacheTreeElement = cachesTreeElement.childAt(i); + var title = cacheTreeElement.title; + var elementCacheName = title.substring(0, title.lastIndexOf(' - ')); + + if (elementCacheName !== cacheName) + continue; + + if (!optionalEntry) { + promise = TestRunner.addSnifferPromise(SDK.ServiceWorkerCacheModel.prototype, '_cacheRemoved'); + cacheTreeElement._clearCache(); + await promise; + return; + } + + promise = TestRunner.addSnifferPromise(Resources.ServiceWorkerCacheView.prototype, '_updateDataCallback'); + var view = cacheTreeElement._view; + + if (!view) + cacheTreeElement.onselect(false); + else + view._updateData(true); + + view = cacheTreeElement._view; + await promise; + var entry = view._entries.find(entry => entry.request === optionalEntry); + + if (!entry) + throw 'Error: Could not find cache entry to delete: ' + optionalEntry; + + await view._model.deleteCacheEntry(view._cache, entry.request); + return; + } + + throw 'Error: Could not find CacheStorage cache ' + cacheName; +}; + +ApplicationTestRunner.waitForCacheRefresh = function(callback) { + TestRunner.addSniffer(SDK.ServiceWorkerCacheModel.prototype, '_updateCacheNames', callback, false); +}; + +ApplicationTestRunner.createCache = function(cacheName) { + return TestRunner.callFunctionInPageAsync('createCache', [cacheName]); +}; + +ApplicationTestRunner.addCacheEntry = function(cacheName, requestUrl, responseText) { + return TestRunner.callFunctionInPageAsync('addCacheEntry', [cacheName, requestUrl, responseText]); +}; + +ApplicationTestRunner.deleteCache = function(cacheName) { + return TestRunner.callFunctionInPageAsync('deleteCache', [cacheName]); +}; + +ApplicationTestRunner.deleteCacheEntry = function(cacheName, requestUrl) { + return TestRunner.callFunctionInPageAsync('deleteCacheEntry', [cacheName, requestUrl]); +}; + +ApplicationTestRunner.clearAllCaches = function() { + return TestRunner.callFunctionInPageAsync('clearAllCaches'); +}; + +(async function() { + await TestRunner.evaluateInPagePromise(` + function onCacheStorageError(e) { + console.error('CacheStorage error: ' + e); + } + + function createCache(cacheName) { + return caches.open(cacheName).catch(onCacheStorageError); + } + + function addCacheEntry(cacheName, requestUrl, responseText) { + return caches.open(cacheName).then(function(cache) { + var request = new Request(requestUrl); + var myBlob = new Blob(); + + var init = { + 'status': 200, + 'statusText': responseText + }; + + var response = new Response(myBlob, init); + return cache.put(request, response); + }).catch(onCacheStorageError); + } + + function deleteCache(cacheName) { + return caches.delete(cacheName).then(function(success) { + if (!success) + onCacheStorageError('Could not find cache ' + cacheName); + }).catch(onCacheStorageError); + } + + function deleteCacheEntry(cacheName, requestUrl) { + return caches.open(cacheName).then(cache => cache.delete(new Request(requestUrl))).catch(onCacheStorageError); + } + + function clearAllCaches() { + return caches.keys().then(keys => Promise.all(keys.map(key => caches.delete(key)))).catch(onCacheStorageError.bind(this, undefined)); + } + `); +})();
diff --git a/third_party/WebKit/Source/devtools/front_end/application_test_runner/IndexedDBTestRunner.js b/third_party/WebKit/Source/devtools/front_end/application_test_runner/IndexedDBTestRunner.js new file mode 100644 index 0000000..696bf91 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/application_test_runner/IndexedDBTestRunner.js
@@ -0,0 +1,356 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +ApplicationTestRunner.dumpIndexedDBTree = function() { + TestRunner.addResult('Dumping IndexedDB tree:'); + var indexedDBTreeElement = UI.panels.resources._sidebar.indexedDBListTreeElement; + + if (!indexedDBTreeElement.childCount()) { + TestRunner.addResult(' (empty)'); + return; + } + + for (var i = 0; i < indexedDBTreeElement.childCount(); ++i) { + var databaseTreeElement = indexedDBTreeElement.childAt(i); + TestRunner.addResult(' database: ' + databaseTreeElement.title); + + if (!databaseTreeElement.childCount()) { + TestRunner.addResult(' (no object stores)'); + continue; + } + + for (var j = 0; j < databaseTreeElement.childCount(); ++j) { + var objectStoreTreeElement = databaseTreeElement.childAt(j); + TestRunner.addResult(' Object store: ' + objectStoreTreeElement.title); + + if (!objectStoreTreeElement.childCount()) { + TestRunner.addResult(' (no indexes)'); + continue; + } + + for (var k = 0; k < objectStoreTreeElement.childCount(); ++k) { + var indexTreeElement = objectStoreTreeElement.childAt(k); + TestRunner.addResult(' Index: ' + indexTreeElement.title); + } + } + } +}; + +var lastCallbackId = 0; +var callbacks = {}; +var callbackIdPrefix = 'InspectorTest.IndexedDB_callback'; + +ApplicationTestRunner.evaluateWithCallback = function(frameId, methodName, parameters, callback) { + ApplicationTestRunner._installIndexedDBSniffer(); + var callbackId = ++lastCallbackId; + callbacks[callbackId] = callback; + var parametersString = 'dispatchCallback.bind(this, "' + callbackIdPrefix + callbackId + '")'; + + for (var i = 0; i < parameters.length; ++i) + parametersString += ', ' + JSON.stringify(parameters[i]); + + var requestString = methodName + '(' + parametersString + ')'; + TestRunner.evaluateInPage(requestString); +}; + +ApplicationTestRunner._installIndexedDBSniffer = function() { + ConsoleTestRunner.addConsoleSniffer(consoleMessageOverride, false); + + function consoleMessageOverride(msg) { + var text = msg.messageText; + + if (!text.startsWith(callbackIdPrefix)) { + ConsoleTestRunner.addConsoleSniffer(consoleMessageOverride, false); + return; + } + + var callbackId = text.substring(callbackIdPrefix.length); + callbacks[callbackId].call(); + delete callbacks[callbackId]; + } +}; + +ApplicationTestRunner.createDatabase = function(frameId, databaseName, callback) { + ApplicationTestRunner.evaluateWithCallback(frameId, 'createDatabase', [databaseName], callback); +}; + +ApplicationTestRunner.deleteDatabase = function(frameId, databaseName, callback) { + ApplicationTestRunner.evaluateWithCallback(frameId, 'deleteDatabase', [databaseName], callback); +}; + +ApplicationTestRunner.createObjectStore = function( + frameId, databaseName, objectStoreName, keyPath, autoIncrement, callback) { + ApplicationTestRunner.evaluateWithCallback( + frameId, 'createObjectStore', [databaseName, objectStoreName, keyPath, autoIncrement], callback); +}; + +ApplicationTestRunner.deleteObjectStore = function(frameId, databaseName, objectStoreName, callback) { + ApplicationTestRunner.evaluateWithCallback(frameId, 'deleteObjectStore', [databaseName, objectStoreName], callback); +}; + +ApplicationTestRunner.createObjectStoreIndex = function( + frameId, databaseName, objectStoreName, objectStoreIndexName, keyPath, unique, multiEntry, callback) { + ApplicationTestRunner.evaluateWithCallback( + frameId, 'createObjectStoreIndex', + [databaseName, objectStoreName, objectStoreIndexName, keyPath, unique, multiEntry], callback); +}; + +ApplicationTestRunner.deleteObjectStoreIndex = function( + frameId, databaseName, objectStoreName, objectStoreIndexName, callback) { + ApplicationTestRunner.evaluateWithCallback( + frameId, 'deleteObjectStoreIndex', [databaseName, objectStoreName, objectStoreIndexName], callback); +}; + +ApplicationTestRunner.addIDBValue = function(frameId, databaseName, objectStoreName, value, key, callback) { + ApplicationTestRunner.evaluateWithCallback( + frameId, 'addIDBValue', [databaseName, objectStoreName, value, key], callback); +}; + +ApplicationTestRunner.createIndexedDBModel = function() { + var indexedDBModel = new Resources.IndexedDBModel(SDK.targetManager.mainTarget(), TestRunner.securityOriginManager); + indexedDBModel.enable(); + return indexedDBModel; +}; + +ApplicationTestRunner.createDatabaseAsync = function(databaseName) { + return TestRunner.evaluateInPageAsync('createDatabaseAsync(\'' + databaseName + '\')'); +}; + +ApplicationTestRunner.createObjectStoreAsync = function(databaseName, objectStoreName, indexName, keyPath) { + return TestRunner.evaluateInPageAsync( + 'createObjectStoreAsync(\'' + databaseName + '\', \'' + objectStoreName + '\', \'' + indexName + '\', \'' + + keyPath + '\')'); +}; + +ApplicationTestRunner.addIDBValueAsync = function(databaseName, objectStoreName, key, value) { + return TestRunner.evaluateInPageAsync( + 'addIDBValueAsync(\'' + databaseName + '\', \'' + objectStoreName + '\', \'' + key + '\', \'' + value + '\')'); +}; + +(async function() { + await TestRunner.evaluateInPagePromise(` + function dispatchCallback(callbackId) { + console.log(callbackId); + } + + function onIndexedDBError(e) { + console.error('IndexedDB error: ' + e); + } + + function onIndexedDBBlocked(e) { + console.error('IndexedDB blocked: ' + e); + } + + function doWithDatabase(databaseName, callback) { + function innerCallback() { + var db = request.result; + callback(db); + } + + var request = indexedDB.open(databaseName); + request.onblocked = onIndexedDBBlocked; + request.onerror = onIndexedDBError; + request.onsuccess = innerCallback; + } + + function doWithVersionTransaction(databaseName, callback, commitCallback) { + doWithDatabase(databaseName, step2); + + function step2(db) { + var version = db.version; + db.close(); + request = indexedDB.open(databaseName, version + 1); + request.onerror = onIndexedDBError; + request.onupgradeneeded = onUpgradeNeeded; + request.onsuccess = onOpened; + + function onUpgradeNeeded(e) { + var db = e.target.result; + var trans = e.target.transaction; + callback(db, trans); + } + + function onOpened(e) { + var db = e.target.result; + db.close(); + commitCallback(); + } + } + } + + function doWithReadWriteTransaction(databaseName, objectStoreName, callback, commitCallback) { + doWithDatabase(databaseName, step2); + + function step2(db) { + var transaction = db.transaction([objectStoreName], 'readwrite'); + var objectStore = transaction.objectStore(objectStoreName); + callback(objectStore, innerCommitCallback); + + function innerCommitCallback() { + db.close(); + commitCallback(); + } + } + } + + function createDatabase(callback, databaseName) { + var request = indexedDB.open(databaseName); + request.onerror = onIndexedDBError; + request.onsuccess = closeDatabase; + + function closeDatabase() { + request.result.close(); + callback(); + } + } + + function deleteDatabase(callback, databaseName) { + var request = indexedDB.deleteDatabase(databaseName); + request.onerror = onIndexedDBError; + request.onsuccess = callback; + } + + function createObjectStore(callback, databaseName, objectStoreName, keyPath, autoIncrement) { + doWithVersionTransaction(databaseName, withTransactionCallback, callback); + + function withTransactionCallback(db, transaction) { + var store = db.createObjectStore(objectStoreName, { + keyPath: keyPath, + autoIncrement: autoIncrement + }); + } + } + + function deleteObjectStore(callback, databaseName, objectStoreName) { + doWithVersionTransaction(databaseName, withTransactionCallback, callback); + + function withTransactionCallback(db, transaction) { + var store = db.deleteObjectStore(objectStoreName); + } + } + + function createObjectStoreIndex(callback, databaseName, objectStoreName, objectStoreIndexName, keyPath, unique, multiEntry) { + doWithVersionTransaction(databaseName, withTransactionCallback, callback); + + function withTransactionCallback(db, transaction) { + var objectStore = transaction.objectStore(objectStoreName); + + objectStore.createIndex(objectStoreIndexName, keyPath, { + unique: unique, + multiEntry: multiEntry + }); + } + } + + function deleteObjectStoreIndex(callback, databaseName, objectStoreName, objectStoreIndexName) { + doWithVersionTransaction(databaseName, withTransactionCallback, callback); + + function withTransactionCallback(db, transaction) { + var objectStore = transaction.objectStore(objectStoreName); + objectStore.deleteIndex(objectStoreIndexName); + } + } + + function addIDBValue(callback, databaseName, objectStoreName, value, key) { + doWithReadWriteTransaction(databaseName, objectStoreName, withTransactionCallback, callback); + + function withTransactionCallback(objectStore, commitCallback) { + var request; + + if (key) + request = objectStore.add(value, key); + else + request = objectStore.add(value); + + request.onerror = onIndexedDBError; + request.onsuccess = commitCallback; + } + } + + function createDatabaseAsync(databaseName) { + var callback; + var promise = new Promise(fulfill => callback = fulfill); + var request = indexedDB.open(databaseName); + request.onerror = onIndexedDBError; + + request.onsuccess = function(event) { + request.result.close(); + callback(); + }; + + return promise; + } + + function createObjectStoreAsync(databaseName, objectStoreName, indexName, keyPath) { + var callback; + var promise = new Promise(fulfill => callback = fulfill); + var request = indexedDB.open(databaseName); + request.onerror = onIndexedDBError; + + request.onsuccess = function(event) { + var db = request.result; + var version = db.version; + db.close(); + var upgradeRequest = indexedDB.open(databaseName, version + 1); + upgradeRequest.onerror = onIndexedDBError; + + upgradeRequest.onupgradeneeded = function(e) { + var upgradeDb = e.target.result; + + var store = upgradeDb.createObjectStore(objectStoreName, { + keyPath: 'test', + autoIncrement: false + }); + + store.createIndex(indexName, 'test', { + unique: false, + multiEntry: false + }); + + callback(); + }; + + upgradeRequest.onsuccess = function(e) { + var upgradeDb = e.target.result; + upgradeDb.close(); + callback(); + }; + }; + + return promise; + } + + function addIDBValueAsync(databaseName, objectStoreName, key, value) { + var callback; + var promise = new Promise(fulfill => callback = fulfill); + var request = indexedDB.open(databaseName); + request.onerror = onIndexedDBError; + + request.onsuccess = function(event) { + var db = request.result; + var transaction = db.transaction(objectStoreName, 'readwrite'); + var store = transaction.objectStore(objectStoreName); + + store.put({ + test: key, + testValue: value + }); + + transaction.onerror = onIndexedDBError; + + transaction.oncomplete = function() { + db.close(); + callback(); + }; + }; + + return promise; + } + `); +})();
diff --git a/third_party/WebKit/Source/devtools/front_end/application_test_runner/ResourceTreeTestRunner.js b/third_party/WebKit/Source/devtools/front_end/application_test_runner/ResourceTreeTestRunner.js new file mode 100644 index 0000000..941d976 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/application_test_runner/ResourceTreeTestRunner.js
@@ -0,0 +1,92 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +ApplicationTestRunner.dumpResources = function(formatter) { + var results = []; + + function formatterWrapper(resource) { + if (formatter) + results.push({resource: resource, text: formatter(resource)}); + else + results.push({resource: resource, text: resource.url}); + } + + TestRunner.resourceTreeModel.forAllResources(formatterWrapper); + + function comparator(result1, result2) { + return result1.resource.url.localeCompare(result2.resource.url); + } + + results.sort(comparator); + + for (var i = 0; i < results.length; ++i) + TestRunner.addResult(results[i].text); +}; + +ApplicationTestRunner.dumpResourcesURLMap = function() { + var results = []; + TestRunner.resourceTreeModel.forAllResources(collect); + + function collect(resource) { + results.push({url: resource.url, resource: TestRunner.resourceTreeModel.resourceForURL(resource.url)}); + } + + function comparator(result1, result2) { + if (result1.url > result2.url) + return 1; + + if (result2.url > result1.url) + return -1; + + return 0; + } + + results.sort(comparator); + + for (var i = 0; i < results.length; ++i) + TestRunner.addResult(results[i].url + ' == ' + results[i].resource.url); +}; + +ApplicationTestRunner.dumpResourcesTree = function() { + function dump(treeItem, prefix) { + if (typeof treeItem._resetBubble === 'function') + treeItem._resetBubble(); + + TestRunner.addResult(prefix + treeItem.listItemElement.textContent); + treeItem.expand(); + var children = treeItem.children(); + + for (var i = 0; children && i < children.length; ++i) + dump(children[i], prefix + ' '); + } + + dump(UI.panels.resources._sidebar._resourcesSection._treeElement, ''); + + if (!ApplicationTestRunner._testSourceNavigator) { + ApplicationTestRunner._testSourceNavigator = new Sources.SourcesNavigatorView(); + ApplicationTestRunner._testSourceNavigator.show(UI.inspectorView.element); + } + + SourcesTestRunner.dumpNavigatorViewInAllModes(ApplicationTestRunner._testSourceNavigator); +}; + +ApplicationTestRunner.dumpResourceTreeEverything = function() { + function format(resource) { + return resource.resourceType().name() + ' ' + resource.url; + } + + TestRunner.addResult('Resources:'); + ApplicationTestRunner.dumpResources(format); + TestRunner.addResult(''); + TestRunner.addResult('Resources URL Map:'); + ApplicationTestRunner.dumpResourcesURLMap(); + TestRunner.addResult(''); + TestRunner.addResult('Resources Tree:'); + ApplicationTestRunner.dumpResourcesTree(); +};
diff --git a/third_party/WebKit/Source/devtools/front_end/application_test_runner/ResourcesTestRunner.js b/third_party/WebKit/Source/devtools/front_end/application_test_runner/ResourcesTestRunner.js new file mode 100644 index 0000000..7c620763 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/application_test_runner/ResourcesTestRunner.js
@@ -0,0 +1,109 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +ApplicationTestRunner.createWebSQLDatabase = function(name) { + return TestRunner.evaluateInPageAsync(`_openWebSQLDatabase("${name}")`); +}; + +ApplicationTestRunner.requestURLComparer = function(r1, r2) { + return r1.request.url.localeCompare(r2.request.url); +}; + +ApplicationTestRunner.runAfterCachedResourcesProcessed = function(callback) { + if (!TestRunner.resourceTreeModel._cachedResourcesProcessed) + TestRunner.resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.CachedResourcesLoaded, callback); + else + callback(); +}; + +ApplicationTestRunner.runAfterResourcesAreFinished = function(resourceURLs, callback) { + var resourceURLsMap = new Set(resourceURLs); + + function checkResources() { + for (var url of resourceURLsMap) { + var resource = ApplicationTestRunner.resourceMatchingURL(url); + + if (resource) + resourceURLsMap.delete(url); + } + + if (!resourceURLsMap.size) { + TestRunner.resourceTreeModel.removeEventListener(SDK.ResourceTreeModel.Events.ResourceAdded, checkResources); + callback(); + } + } + + checkResources(); + + if (resourceURLsMap.size) + TestRunner.resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.ResourceAdded, checkResources); +}; + +ApplicationTestRunner.showResource = function(resourceURL, callback) { + var reported = false; + + function callbackWrapper(sourceFrame) { + if (reported) + return; + + callback(sourceFrame); + reported = true; + } + + function showResourceCallback() { + var resource = ApplicationTestRunner.resourceMatchingURL(resourceURL); + + if (!resource) + return; + + UI.panels.resources.showResource(resource, 1); + var sourceFrame = UI.panels.resources._resourceViewForResource(resource); + + if (sourceFrame.loaded) + callbackWrapper(sourceFrame); + else + TestRunner.addSniffer(sourceFrame, 'onTextEditorContentSet', callbackWrapper.bind(null, sourceFrame)); + } + + ApplicationTestRunner.runAfterResourcesAreFinished([resourceURL], showResourceCallback); +}; + +ApplicationTestRunner.resourceMatchingURL = function(resourceURL) { + var result = null; + TestRunner.resourceTreeModel.forAllResources(visit); + + function visit(resource) { + if (resource.url.indexOf(resourceURL) !== -1) { + result = resource; + return true; + } + } + + return result; +}; + +ApplicationTestRunner.databaseModel = function() { + return TestRunner.mainTarget.model(Resources.DatabaseModel); +}; + +ApplicationTestRunner.domStorageModel = function() { + return TestRunner.mainTarget.model(Resources.DOMStorageModel); +}; + +ApplicationTestRunner.indexedDBModel = function() { + return TestRunner.mainTarget.model(Resources.IndexedDBModel); +}; + +(async function() { + await TestRunner.evaluateInPagePromise(` + function _openWebSQLDatabase(name) { + return new Promise(resolve => openDatabase(name, '1.0', '', 1024 * 1024, resolve)); + } + `); +})();
diff --git a/third_party/WebKit/Source/devtools/front_end/application_test_runner/ServiceWorkersTestRunner.js b/third_party/WebKit/Source/devtools/front_end/application_test_runner/ServiceWorkersTestRunner.js new file mode 100644 index 0000000..51158e46 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/application_test_runner/ServiceWorkersTestRunner.js
@@ -0,0 +1,104 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +ApplicationTestRunner.registerServiceWorker = function(script, scope) { + return TestRunner.callFunctionInPageAsync('registerServiceWorker', [script, scope]); +}; + +ApplicationTestRunner.unregisterServiceWorker = function(scope) { + return TestRunner.callFunctionInPageAsync('unregisterServiceWorker', [scope]); +}; + +ApplicationTestRunner.postToServiceWorker = function(scope, message) { + return TestRunner.evaluateInPagePromise('postToServiceWorker("' + scope + '","' + message + '")'); +}; + +ApplicationTestRunner.waitForServiceWorker = function(callback) { + function isRightTarget(target) { + return TestRunner.isDedicatedWorker(target) && TestRunner.isServiceWorker(target.parentTarget()); + } + + SDK.targetManager.observeTargets({ + targetAdded: function(target) { + if (isRightTarget(target) && callback) { + setTimeout(callback.bind(null, target), 0); + callback = null; + } + }, + + targetRemoved: function(target) {} + }); +}; + +ApplicationTestRunner.dumpServiceWorkersView = function() { + var swView = UI.panels.resources.visibleView; + + return swView._reportView._sectionList.childTextNodes() + .map(function(node) { + return node.textContent.replace(/Received.*/, 'Received').replace(/#\d+/, '#N'); + }) + .join('\n'); +}; + +ApplicationTestRunner.deleteServiceWorkerRegistration = function(scope) { + TestRunner.serviceWorkerManager.registrations().valuesArray().map(function(registration) { + if (registration.scopeURL === scope) + TestRunner.serviceWorkerManager.deleteRegistration(registration.id); + }); +}; + +ApplicationTestRunner.makeFetchInServiceWorker = function(scope, url, requestInitializer, callback) { + TestRunner.callFunctionInPageAsync('makeFetchInServiceWorker', [scope, url, requestInitializer]).then(callback); +}; + +(async function() { + await TestRunner.evaluateInPagePromise(` + var registrations = {}; + + function registerServiceWorker(script, scope) { + return navigator.serviceWorker.register(script, { + scope: scope + }).then(reg => registrations[scope] = reg); + } + + function postToServiceWorker(scope, message) { + registrations[scope].active.postMessage(message); + } + + function unregisterServiceWorker(scope) { + var registration = registrations[scope]; + + if (!registration) + return Promise.reject('ServiceWorker for ' + scope + ' is not registered'); + + return registration.unregister().then(() => delete registrations[scope]); + } + + function makeFetchInServiceWorker(scope, url, requestInitializer) { + let script = 'resources/network-fetch-worker.js'; + + return navigator.serviceWorker.register(script, { + scope: scope + }).then(registration => { + let worker = registration.installing; + + return new Promise(resolve => { + navigator.serviceWorker.onmessage = e => { + resolve(e.data); + }; + + worker.postMessage({ + url: url, + init: requestInitializer + }); + }); + }); + } + `); +})();
diff --git a/third_party/WebKit/Source/devtools/front_end/application_test_runner/module.json b/third_party/WebKit/Source/devtools/front_end/application_test_runner/module.json new file mode 100644 index 0000000..ccb40aca --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/application_test_runner/module.json
@@ -0,0 +1,26 @@ +{ + "dependencies": [ + "test_runner", + "integration_test_runner", + "resources", + "console_test_runner", + "sources", + "sources_test_runner" + ], + "scripts": [ + "AppcacheTestRunner.js", + "CacheStorageTestRunner.js", + "IndexedDBTestRunner.js", + "ResourceTreeTestRunner.js", + "ResourcesTestRunner.js", + "ServiceWorkersTestRunner.js" + ], + "skip_compilation": [ + "AppcacheTestRunner.js", + "CacheStorageTestRunner.js", + "IndexedDBTestRunner.js", + "ResourceTreeTestRunner.js", + "ResourcesTestRunner.js", + "ServiceWorkersTestRunner.js" + ] +}
diff --git a/third_party/WebKit/Source/devtools/front_end/audits_test_runner/AuditsTestRunner.js b/third_party/WebKit/Source/devtools/front_end/audits_test_runner/AuditsTestRunner.js new file mode 100644 index 0000000..649f1c40 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/audits_test_runner/AuditsTestRunner.js
@@ -0,0 +1,66 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +AuditsTestRunner.collectAuditResults = function(callback) { + UI.panels.audits.showResults(UI.panels.audits._auditResultsTreeElement.firstChild().results); + var trees = UI.panels.audits.visibleView.element.querySelectorAll('.audit-result-tree'); + + for (var i = 0; i < trees.length; ++i) { + var liElements = trees[i].shadowRoot.querySelectorAll('li'); + + for (var j = 0; j < liElements.length; ++j) { + if (liElements[j].treeElement) + liElements[j].treeElement.expand(); + } + } + + TestRunner.deprecatedRunAfterPendingDispatches(function() { + AuditsTestRunner.collectTextContent(UI.panels.audits.visibleView.element, ''); + callback(); + }); +}; + +AuditsTestRunner.launchAllAudits = function(shouldReload, callback) { + TestRunner.addSniffer(Audits.AuditController.prototype, '_auditFinishedCallback', callback); + var launcherView = UI.panels.audits._launcherView; + launcherView._selectAllClicked(true); + launcherView._auditPresentStateElement.checked = !shouldReload; + launcherView._launchButtonClicked(); +}; + +AuditsTestRunner.collectTextContent = function(element, indent) { + var nodeOutput = ''; + var child = element.shadowRoot || element.firstChild; + + var nonTextTags = {'STYLE': 1, 'SCRIPT': 1}; + + while (child) { + if (child.nodeName === 'CONTENT') { + AuditsTestRunner.collectTextContent(child.getDistributedNodes()[0], indent); + } else if (child.nodeType === Node.TEXT_NODE) { + if (!nonTextTags[child.parentElement.nodeName]) + nodeOutput += child.nodeValue.replace('​', ''); + } else if (child.nodeType === Node.ELEMENT_NODE || child.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { + if (nodeOutput !== '') { + TestRunner.addResult(indent + nodeOutput); + nodeOutput = ''; + } + + if (!child.firstChild && child.classList.contains('severity')) + nodeOutput = '[' + child.className + '] '; + else + AuditsTestRunner.collectTextContent(child, indent + ' '); + } + + child = child.nextSibling; + } + + if (nodeOutput !== '') + TestRunner.addResult(indent + nodeOutput); +};
diff --git a/third_party/WebKit/Source/devtools/front_end/audits_test_runner/module.json b/third_party/WebKit/Source/devtools/front_end/audits_test_runner/module.json new file mode 100644 index 0000000..be3a2642 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/audits_test_runner/module.json
@@ -0,0 +1,13 @@ +{ + "dependencies": [ + "test_runner", + "integration_test_runner", + "audits" + ], + "scripts": [ + "AuditsTestRunner.js" + ], + "skip_compilation": [ + "AuditsTestRunner.js" + ] +}
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings_test_runner/AutomappingTestRunner.js b/third_party/WebKit/Source/devtools/front_end/bindings_test_runner/AutomappingTestRunner.js new file mode 100644 index 0000000..56d89996 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/bindings_test_runner/AutomappingTestRunner.js
@@ -0,0 +1,121 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +BindingsTestRunner.addFiles = function(testFileSystem, files) { + for (var filePath in files) { + var file = files[filePath]; + testFileSystem.addFile(filePath, file.content, (file.time ? file.time.getTime() : 0)); + } +}; + +var timeOverrides; +var originalRequestMetadata; + +BindingsTestRunner.overrideNetworkModificationTime = function(urlToTime) { + if (!timeOverrides) { + timeOverrides = new Map(); + originalRequestMetadata = + TestRunner.override(Bindings.ContentProviderBasedProject.prototype, 'requestMetadata', overrideTime, true); + } + + for (var url in urlToTime) + timeOverrides.set(url, urlToTime[url]); + + function overrideTime(uiSourceCode) { + if (!timeOverrides.has(uiSourceCode.url())) + return originalRequestMetadata.call(this, uiSourceCode); + + var override = timeOverrides.get(uiSourceCode.url()); + return originalRequestMetadata.call(this, uiSourceCode).then(onOriginalMetadata.bind(null, override)); + } + + function onOriginalMetadata(timeOverride, metadata) { + if (!timeOverride && !metadata) + return null; + + return new Workspace.UISourceCodeMetadata(timeOverride, (metadata ? metadata.contentSize : null)); + } +}; + +BindingsTestRunner.AutomappingTest = function(workspace) { + this._workspace = workspace; + this._networkProject = new Bindings.ContentProviderBasedProject( + this._workspace, 'AUTOMAPPING', Workspace.projectTypes.Network, 'simple website'); + + if (workspace !== Workspace.workspace) + new Persistence.FileSystemWorkspaceBinding(Persistence.isolatedFileSystemManager, this._workspace); + + this._failedBindingsCount = 0; + this._automapping = + new Persistence.Automapping(this._workspace, this._onBindingAdded.bind(this), this._onBindingRemoved.bind(this)); + TestRunner.addSniffer(this._automapping, '_onBindingFailedForTest', this._onBindingFailed.bind(this), true); + TestRunner.addSniffer(this._automapping, '_onSweepHappenedForTest', this._onSweepHappened.bind(this), true); +}; + +BindingsTestRunner.AutomappingTest.prototype = { + removeResources: function(urls) { + for (var url of urls) + this._networkProject.removeFile(url); + }, + + addNetworkResources: function(assets) { + for (var url in assets) { + var asset = assets[url]; + var contentType = asset.contentType || Common.resourceTypes.Script; + var contentProvider = new Common.StaticContentProvider(url, contentType, Promise.resolve(asset.content)); + var metadata = + (typeof asset.content === 'string' || asset.time ? + new Workspace.UISourceCodeMetadata(asset.time, asset.content.length) : + null); + var uiSourceCode = this._networkProject.createUISourceCode(url, contentType); + this._networkProject.addUISourceCodeWithProvider(uiSourceCode, contentProvider, metadata); + } + }, + + waitUntilMappingIsStabilized: function() { + var promise = new Promise(x => this._stabilizedCallback = x); + this._checkStabilized(); + return promise; + }, + + _onSweepHappened: function() { + this._failedBindingsCount = 0; + this._checkStabilized(); + }, + + _onBindingAdded: function(binding) { + TestRunner.addResult('Binding created: ' + binding); + this._checkStabilized(); + }, + + _onBindingFailed: function() { + ++this._failedBindingsCount; + this._checkStabilized(); + }, + + _onBindingRemoved: function(binding) { + TestRunner.addResult('Binding removed: ' + binding); + this._checkStabilized(); + }, + + _checkStabilized: function() { + if (!this._stabilizedCallback || this._automapping._sweepThrottler._process) + return; + + var networkUISourceCodes = this._workspace.uiSourceCodesForProjectType(Workspace.projectTypes.Network); + var stabilized = this._failedBindingsCount + this._automapping._bindings.size === networkUISourceCodes.length; + + if (stabilized) { + TestRunner.addResult('Mapping has stabilized.'); + var callback = this._stabilizedCallback; + delete this._stabilizedCallback; + callback.call(null); + } + } +};
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings_test_runner/BindingsTestRunner.js b/third_party/WebKit/Source/devtools/front_end/bindings_test_runner/BindingsTestRunner.js new file mode 100644 index 0000000..ec92bcd --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/bindings_test_runner/BindingsTestRunner.js
@@ -0,0 +1,219 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +BindingsTestRunner.dumpWorkspace = function(previousSnapshot) { + var uiSourceCodes = Workspace.workspace.uiSourceCodes().slice(); + var urls = uiSourceCodes.map(code => code.url()); + + urls = urls.map(url => { + if (!url.startsWith('debugger://')) + return url; + + return url.replace(/VM\d+/g, 'VM[XXX]'); + }); + + urls.sort(String.caseInsensetiveComparator); + var isAdded = new Array(urls.length).fill(false); + var removedLines = []; + + if (previousSnapshot) { + var diff = Diff.Diff.lineDiff(previousSnapshot, urls); + var removedEntries = diff.filter(entry => entry[0] === Diff.Diff.Operation.Delete).map(entry => entry[1]); + removedLines = [].concat.apply([], removedEntries); + var index = 0; + + for (var entry of diff) { + if (entry[0] === Diff.Diff.Operation.Delete) + continue; + + if (entry[0] === Diff.Diff.Operation.Equal) { + index += entry[1].length; + continue; + } + + // eslint-disable-next-line no-unused-vars + for (var line of entry[1]) + isAdded[index++] = true; + } + + var addedEntries = diff.filter(entry => entry[0] === Diff.Diff.Operation.Insert).map(entry => entry[1]); + addedLines = [].concat.apply([], addedEntries); + } + + TestRunner.addResult(`Removed: ${removedLines.length} uiSourceCodes`); + + for (var url of removedLines) + TestRunner.addResult('[-] ' + url); + + TestRunner.addResult(`Workspace: ${urls.length} uiSourceCodes.`); + + for (var i = 0; i < urls.length; ++i) { + var url = urls[i]; + var prefix = (isAdded[i] ? '[+] ' : ' '); + TestRunner.addResult(prefix + url); + } + + return urls; +}; + +BindingsTestRunner.attachFrame = function(frameId, url, evalSourceURL) { + var evalSource = `(${attachFrame.toString()})('${frameId}', '${url}')`; + + if (evalSourceURL) + evalSource += '//# sourceURL=' + evalSourceURL; + + return TestRunner.evaluateInPageAsync(evalSource); + + function attachFrame(frameId, url) { + var frame = document.createElement('iframe'); + frame.src = url; + frame.id = frameId; + document.body.appendChild(frame); + return new Promise(x => frame.onload = x); + } +}; + +BindingsTestRunner.detachFrame = function(frameId, evalSourceURL) { + var evalSource = `(${detachFrame.toString()})('${frameId}')`; + + if (evalSourceURL) + evalSource += '//# sourceURL=' + evalSourceURL; + + return TestRunner.evaluateInPagePromise(evalSource); + + function detachFrame(frameId) { + var frame = document.getElementById(frameId); + frame.remove(); + } +}; + +BindingsTestRunner.navigateFrame = function(frameId, navigateURL, evalSourceURL) { + var evalSource = `(${navigateFrame.toString()})('${frameId}', '${navigateURL}')`; + + if (evalSourceURL) + evalSource += '//# sourceURL=' + evalSourceURL; + + return TestRunner.evaluateInPageAsync(evalSource); + + function navigateFrame(frameId, url) { + var frame = document.getElementById(frameId); + frame.src = url; + return new Promise(x => frame.onload = x); + } +}; + +BindingsTestRunner.attachShadowDOM = function(id, templateSelector, evalSourceURL) { + var evalSource = `(${createShadowDOM.toString()})('${id}', '${templateSelector}')`; + + if (evalSourceURL) + evalSource += '//# sourceURL=' + evalSourceURL; + + return TestRunner.evaluateInPagePromise(evalSource); + + function createShadowDOM(id, templateSelector) { + var shadowHost = document.createElement('div'); + shadowHost.setAttribute('id', id); + + let shadowRoot = shadowHost.attachShadow({mode: 'open'}); + + var t = document.querySelector(templateSelector); + var instance = t.content.cloneNode(true); + shadowRoot.appendChild(instance); + document.body.appendChild(shadowHost); + } +}; + +BindingsTestRunner.detachShadowDOM = function(id, evalSourceURL) { + var evalSource = `(${removeShadowDOM.toString()})('${id}')`; + + if (evalSourceURL) + evalSource += '//# sourceURL=' + evalSourceURL; + + return TestRunner.evaluateInPagePromise(evalSource); + + function removeShadowDOM(id) { + document.querySelector('#' + id).remove(); + } +}; + +BindingsTestRunner.waitForStyleSheetRemoved = function(urlSuffix) { + var fulfill; + var promise = new Promise(x => fulfill = x); + TestRunner.cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetRemoved, onStyleSheetRemoved); + return promise; + + function onStyleSheetRemoved(event) { + var styleSheetHeader = event.data; + + if (!styleSheetHeader.resourceURL().endsWith(urlSuffix)) + return; + + TestRunner.cssModel.removeEventListener(SDK.CSSModel.Events.StyleSheetRemoved, onStyleSheetRemoved); + fulfill(); + } +}; + +TestRunner.addSniffer(Bindings.CompilerScriptMapping.prototype, '_sourceMapAttachedForTest', onSourceMap, true); +TestRunner.addSniffer(Bindings.SASSSourceMapping.prototype, '_sourceMapAttachedForTest', onSourceMap, true); +var sourceMapCallbacks = new Map(); + +function onSourceMap(sourceMap) { + for (var urlSuffix of sourceMapCallbacks.keys()) { + if (sourceMap.url().endsWith(urlSuffix)) { + var callback = sourceMapCallbacks.get(urlSuffix); + callback.call(null); + sourceMapCallbacks.delete(urlSuffix); + } + } +} + +BindingsTestRunner.waitForSourceMap = function(sourceMapURLSuffix) { + var fulfill; + var promise = new Promise(x => fulfill = x); + sourceMapCallbacks.set(sourceMapURLSuffix, fulfill); + return promise; +}; + +var locationPool = new Bindings.LiveLocationPool(); +var nameSymbol = Symbol('LiveLocationNameForTest'); +var createdSymbol = Symbol('LiveLocationCreated'); + +BindingsTestRunner.createDebuggerLiveLocation = function(name, urlSuffix, lineNumber, columnNumber) { + var script = TestRunner.debuggerModel.scripts().find(script => script.sourceURL.endsWith(urlSuffix)); + var rawLocation = TestRunner.debuggerModel.createRawLocation(script, lineNumber || 0, columnNumber || 0); + return Bindings.debuggerWorkspaceBinding.createLiveLocation( + rawLocation, updateDelegate.bind(null, name), locationPool); +}; + +BindingsTestRunner.createCSSLiveLocation = function(name, urlSuffix, lineNumber, columnNumber) { + var header = TestRunner.cssModel.styleSheetHeaders().find(header => header.resourceURL().endsWith(urlSuffix)); + var rawLocation = new SDK.CSSLocation(header, lineNumber || 0, columnNumber || 0); + return Bindings.cssWorkspaceBinding.createLiveLocation(rawLocation, updateDelegate.bind(null, name), locationPool); +}; + +function updateDelegate(name, liveLocation) { + liveLocation[nameSymbol] = name; + var hint = (liveLocation[createdSymbol] ? '[ UPDATE ]' : '[ CREATE ]'); + liveLocation[createdSymbol] = true; + BindingsTestRunner.dumpLocation(liveLocation, hint); +} + +BindingsTestRunner.dumpLocation = function(liveLocation, hint) { + hint = hint || '[ GET ]'; + var prefix = `${hint} LiveLocation-${liveLocation[nameSymbol]}: `; + var uiLocation = liveLocation.uiLocation(); + + if (!uiLocation) { + TestRunner.addResult(prefix + 'null'); + return; + } + + TestRunner.addResult( + prefix + uiLocation.uiSourceCode.url() + ':' + uiLocation.lineNumber + ':' + uiLocation.columnNumber); +};
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings_test_runner/IsolatedFilesystemTestRunner.js b/third_party/WebKit/Source/devtools/front_end/bindings_test_runner/IsolatedFilesystemTestRunner.js new file mode 100644 index 0000000..6c77c419 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/bindings_test_runner/IsolatedFilesystemTestRunner.js
@@ -0,0 +1,292 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +InspectorFrontendHost.isolatedFileSystem = function(name) { + return BindingsTestRunner.TestFileSystem._instances[name]; +}; + +BindingsTestRunner.TestFileSystem = function(fileSystemPath) { + this.root = new BindingsTestRunner.TestFileSystem.Entry(this, '', true, null); + this.fileSystemPath = fileSystemPath; +}; + +BindingsTestRunner.TestFileSystem._instances = {}; + +BindingsTestRunner.TestFileSystem.prototype = { + dumpAsText: function() { + var result = []; + dfs(this.root, ''); + result[0] = this.fileSystemPath; + return result.join('\n'); + + function dfs(node, indent) { + result.push(indent + node.name); + var newIndent = indent + ' '; + + for (var child of node._children) + dfs(child, newIndent); + } + }, + + reportCreatedPromise: function() { + return new Promise(fulfill => this.reportCreated(fulfill)); + }, + + reportCreated: function(callback) { + var fileSystemPath = this.fileSystemPath; + BindingsTestRunner.TestFileSystem._instances[this.fileSystemPath] = this; + + InspectorFrontendHost.events.dispatchEventToListeners( + InspectorFrontendHostAPI.Events.FileSystemAdded, + {fileSystem: {fileSystemPath: this.fileSystemPath, fileSystemName: this.fileSystemPath}}); + + Persistence.isolatedFileSystemManager.addEventListener( + Persistence.IsolatedFileSystemManager.Events.FileSystemAdded, created); + + function created(event) { + var fileSystem = event.data; + + if (fileSystem.path() !== fileSystemPath) + return; + + Persistence.isolatedFileSystemManager.removeEventListener( + Persistence.IsolatedFileSystemManager.Events.FileSystemAdded, created); + callback(fileSystem); + } + }, + + reportRemoved: function() { + delete BindingsTestRunner.TestFileSystem._instances[this.fileSystemPath]; + InspectorFrontendHost.events.dispatchEventToListeners( + InspectorFrontendHostAPI.Events.FileSystemRemoved, this.fileSystemPath); + }, + + addFileMapping: function(urlPrefix, pathPrefix) { + var fileSystemMapping = new Persistence.FileSystemMapping(Persistence.isolatedFileSystemManager); + fileSystemMapping.addFileSystem(this.fileSystemPath); + fileSystemMapping.addFileMapping(this.fileSystemPath, urlPrefix, pathPrefix); + fileSystemMapping.dispose(); + Persistence.fileSystemMapping._loadFromSettings(); + }, + + addFile: function(path, content, lastModified) { + var pathTokens = path.split('/'); + var node = this.root; + var folders = pathTokens.slice(0, pathTokens.length - 1); + var fileName = pathTokens.peekLast(); + + for (var folder of folders) { + var dir = node._childrenMap[folder]; + + if (!dir) + dir = node.mkdir(folder); + + node = dir; + } + + var file = node.addFile(fileName, content); + + if (lastModified) + file._timestamp = lastModified; + + return file; + } +}; + +BindingsTestRunner.TestFileSystem.Entry = function(fileSystem, name, isDirectory, parent) { + this._fileSystem = fileSystem; + this.name = name; + this._children = []; + this._childrenMap = {}; + this.isDirectory = isDirectory; + this._timestamp = 1000000; + this._parent = parent; +}; + +BindingsTestRunner.TestFileSystem.Entry.prototype = { + get fullPath() { + return (this.parent ? this.parent.fullPath + '/' + this.name : ''); + }, + + remove: function(success, failure) { + this._parent._removeChild(this, success, failure); + }, + + _removeChild: function(child, success, failure) { + var index = this._children.indexOf(child); + + if (index === -1) { + failure('Failed to remove file: file not found.'); + return; + } + + var fullPath = this._fileSystem.fileSystemPath + child.fullPath; + this._children.splice(index, 1); + delete this._childrenMap[child.name]; + child.parent = null; + + InspectorFrontendHost.events.dispatchEventToListeners( + InspectorFrontendHostAPI.Events.FileSystemFilesChangedAddedRemoved, + {changed: [], added: [], removed: [fullPath]}); + + success(); + }, + + mkdir: function(name) { + var child = new BindingsTestRunner.TestFileSystem.Entry(this._fileSystem, name, true, this); + this._childrenMap[name] = child; + this._children.push(child); + child.parent = this; + return child; + }, + + addFile: function(name, content) { + var child = new BindingsTestRunner.TestFileSystem.Entry(this._fileSystem, name, false, this); + this._childrenMap[name] = child; + this._children.push(child); + child.parent = this; + + child.content = new Blob([content], {type: 'text/plain'}); + + var fullPath = this._fileSystem.fileSystemPath + child.fullPath; + + InspectorFrontendHost.events.dispatchEventToListeners( + InspectorFrontendHostAPI.Events.FileSystemFilesChangedAddedRemoved, + {changed: [], added: [fullPath], removed: []}); + + return child; + }, + + setContent: function(content) { + this.content = new Blob([content], {type: 'text/plain'}); + + this._timestamp += 1000; + var fullPath = this._fileSystem.fileSystemPath + this.fullPath; + + InspectorFrontendHost.events.dispatchEventToListeners( + InspectorFrontendHostAPI.Events.FileSystemFilesChangedAddedRemoved, + {changed: [fullPath], added: [], removed: []}); + }, + + createReader: function() { + return new BindingsTestRunner.TestFileSystem.Reader(this._children); + }, + + createWriter: function(success, failure) { + success(new BindingsTestRunner.TestFileSystem.Writer(this)); + }, + + file: function(callback) { + callback(this.content); + }, + + getDirectory: function(path, noop, callback, errorCallback) { + this.getEntry(path, noop, callback, errorCallback); + }, + + getFile: function(path, noop, callback, errorCallback) { + this.getEntry(path, noop, callback, errorCallback); + }, + + _createEntry: function(path, options, callback, errorCallback) { + var tokens = path.split('/'); + var name = tokens.pop(); + var parentEntry = this; + + for (var token of tokens) + parentEntry = parentEntry._childrenMap[token]; + + var entry = parentEntry._childrenMap[name]; + + if (entry && options.exclusive) { + errorCallback(new DOMException('File exists: ' + path, 'InvalidModificationError')); + return; + } + + if (!entry) + entry = parentEntry.addFile(name, ''); + + callback(entry); + }, + + getEntry: function(path, options, callback, errorCallback) { + if (path.startsWith('/')) + path = path.substring(1); + + if (options && options.create) { + this._createEntry(path, options, callback, errorCallback); + return; + } + + if (!path) { + callback(this); + return; + } + + var entry = this; + + for (var token of path.split('/')) + entry = entry._childrenMap[token]; + + (entry ? callback(entry) : errorCallback(new DOMException('Path not found: ' + path, 'NotFoundError'))); + }, + + getMetadata: function(success, failure) { + success({modificationTime: new Date(this._timestamp), size: (this.isDirectory ? 0 : this.content.size)}); + }, + + moveTo: function(parent, newName, callback, errorCallback) { + this._parent._children.remove(this); + delete this._parent._childrenMap[this.name]; + this._parent = parent; + this._parent._children.push(this); + this.name = newName; + this._parent._childrenMap[this.name] = this; + callback(this); + }, + + getParent: function(callback, errorCallback) { + callback(this._parent); + } +}; + +BindingsTestRunner.TestFileSystem.Reader = function(children) { + this._children = children; +}; + +BindingsTestRunner.TestFileSystem.Reader.prototype = { + readEntries: function(callback) { + var children = this._children; + this._children = []; + callback(children); + } +}; + +BindingsTestRunner.TestFileSystem.Writer = function(entry) { + this._entry = entry; + this._modificationTimesDelta = 500; +}; + +BindingsTestRunner.TestFileSystem.Writer.prototype = { + write: function(blob) { + this._entry._timestamp += this._modificationTimesDelta; + this._entry.content = blob; + + if (this.onwriteend) + this.onwriteend(); + }, + + truncate: function(num) { + this._entry._timestamp += this._modificationTimesDelta; + this._entry.content = this._entry.content.slice(0, num); + + if (this.onwriteend) + this.onwriteend(); + } +};
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings_test_runner/PersistenceTestRunner.js b/third_party/WebKit/Source/devtools/front_end/bindings_test_runner/PersistenceTestRunner.js new file mode 100644 index 0000000..6ec92a4 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/bindings_test_runner/PersistenceTestRunner.js
@@ -0,0 +1,113 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +Runtime.experiments.enableForTest('persistenceValidation'); + +Persistence.PersistenceBinding.prototype.toString = function() { + var lines = [ + '{', ' network: ' + this.network.url(), ' fileSystem: ' + this.fileSystem.url(), + ' exactMatch: ' + this.exactMatch, '}' + ]; + + return lines.join('\n'); +}; + +BindingsTestRunner.waitForBinding = function(fileName) { + var uiSourceCodes = Workspace.workspace.uiSourceCodes(); + + for (var uiSourceCode of uiSourceCodes) { + var binding = Persistence.persistence.binding(uiSourceCode); + + if (!binding) + continue; + + if (uiSourceCode.name() === fileName) + return Promise.resolve(binding); + } + + return TestRunner.waitForEvent( + Persistence.Persistence.Events.BindingCreated, Persistence.persistence, + binding => binding.network.name() === fileName || binding.fileSystem.name() === fileName); +}; + +BindingsTestRunner.addFooJSFile = function(fs) { + return fs.root.mkdir('inspector') + .mkdir('persistence') + .mkdir('resources') + .addFile('foo.js', '\n\nwindow.foo = ()=>\'foo\';'); +}; + +BindingsTestRunner.forceUseDefaultMapping = function() { + Persistence.persistence._setMappingForTest((bindingCreated, bindingRemoved) => { + return new Persistence.DefaultMapping( + Workspace.workspace, Persistence.fileSystemMapping, bindingCreated, bindingRemoved); + }); +}; + +BindingsTestRunner.initializeTestMapping = function() { + var testMapping; + + Persistence.persistence._setMappingForTest((bindingCreated, bindingRemoved) => { + testMapping = new TestMapping(bindingCreated, bindingRemoved); + return testMapping; + }); + + return testMapping; +}; + +class TestMapping { + constructor(onBindingAdded, onBindingRemoved) { + this._onBindingAdded = onBindingAdded; + this._onBindingRemoved = onBindingRemoved; + this._bindings = new Set(); + } + + async addBinding(urlSuffix) { + if (this._findBinding(urlSuffix)) { + TestRunner.addResult(`FAILED TO ADD BINDING: binding already exists for ${urlSuffix}`); + TestRunner.completeTest(); + return; + } + + var networkUISourceCode = await TestRunner.waitForUISourceCode(urlSuffix, Workspace.projectTypes.Network); + var fileSystemUISourceCode = await TestRunner.waitForUISourceCode(urlSuffix, Workspace.projectTypes.FileSystem); + var binding = new Persistence.PersistenceBinding(networkUISourceCode, fileSystemUISourceCode, false); + this._bindings.add(binding); + this._onBindingAdded.call(null, binding); + } + + _findBinding(urlSuffix) { + for (var binding of this._bindings) { + if (binding.network.url().endsWith(urlSuffix)) + return binding; + } + + return null; + } + + async removeBinding(urlSuffix) { + var binding = this._findBinding(urlSuffix); + + if (!binding) { + TestRunner.addResult(`FAILED TO REMOVE BINDING: binding does not exist for ${urlSuffix}`); + TestRunner.completeTest(); + return; + } + + this._bindings.delete(binding); + this._onBindingRemoved.call(null, binding); + } + + dispose() { + for (var binding of this._bindings) + this._onBindingRemoved.call(null, binding); + + this._bindings.clear(); + } +}
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings_test_runner/module.json b/third_party/WebKit/Source/devtools/front_end/bindings_test_runner/module.json new file mode 100644 index 0000000..82d789a --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/bindings_test_runner/module.json
@@ -0,0 +1,22 @@ +{ + "dependencies": [ + "test_runner", + "integration_test_runner", + "workspace", + "diff", + "bindings", + "persistence" + ], + "scripts": [ + "BindingsTestRunner.js", + "IsolatedFilesystemTestRunner.js", + "AutomappingTestRunner.js", + "PersistenceTestRunner.js" + ], + "skip_compilation": [ + "BindingsTestRunner.js", + "IsolatedFilesystemTestRunner.js", + "AutomappingTestRunner.js", + "PersistenceTestRunner.js" + ] +}
diff --git a/third_party/WebKit/Source/devtools/front_end/coverage_test_runner/CoverageTestRunner.js b/third_party/WebKit/Source/devtools/front_end/coverage_test_runner/CoverageTestRunner.js new file mode 100644 index 0000000..185834f8 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/coverage_test_runner/CoverageTestRunner.js
@@ -0,0 +1,84 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +CoverageTestRunner.startCoverage = function() { + UI.viewManager.showView('coverage'); + var coverageView = self.runtime.sharedInstance(Coverage.CoverageView); + coverageView._startRecording(); +}; + +CoverageTestRunner.stopCoverage = function() { + var coverageView = self.runtime.sharedInstance(Coverage.CoverageView); + return coverageView._stopRecording(); +}; + +CoverageTestRunner.sourceDecorated = async function(source) { + await UI.inspectorView.showPanel('sources'); + var decoratePromise = TestRunner.addSnifferPromise(Coverage.CoverageView.LineDecorator.prototype, '_innerDecorate'); + var sourceFrame = await new Promise(fulfill => SourcesTestRunner.showScriptSource(source, fulfill)); + await decoratePromise; + return sourceFrame; +}; + +CoverageTestRunner.dumpDecorations = async function(source) { + var sourceFrame = await CoverageTestRunner.sourceDecorated(source); + CoverageTestRunner.dumpDecorationsInSourceFrame(sourceFrame); +}; + +CoverageTestRunner.findCoverageNodeForURL = function(url) { + var coverageListView = self.runtime.sharedInstance(Coverage.CoverageView)._listView; + var rootNode = coverageListView._dataGrid.rootNode(); + + for (var child of rootNode.children) { + if (child._coverageInfo.url().endsWith(url)) + return child; + } + + return null; +}; + +CoverageTestRunner.dumpDecorationsInSourceFrame = function(sourceFrame) { + var markerMap = new Map([['used', '+'], ['unused', '-']]); + var codeMirror = sourceFrame.textEditor.codeMirror(); + + for (var line = 0; line < codeMirror.lineCount(); ++line) { + var text = codeMirror.getLine(line); + var markerType = ' '; + var lineInfo = codeMirror.lineInfo(line); + + if (!lineInfo) + continue; + + var gutterElement = lineInfo.gutterMarkers && lineInfo.gutterMarkers['CodeMirror-gutter-coverage']; + + if (gutterElement) { + var markerClass = /^text-editor-coverage-(\w*)-marker$/.exec(gutterElement.classList)[1]; + markerType = markerMap.get(markerClass) || gutterElement.classList; + } + + TestRunner.addResult(`${line}: ${markerType} ${text}`); + } +}; + +CoverageTestRunner.dumpCoverageListView = function() { + var coverageListView = self.runtime.sharedInstance(Coverage.CoverageView)._listView; + var dataGrid = coverageListView._dataGrid; + dataGrid.updateInstantly(); + + for (var child of dataGrid.rootNode().children) { + var data = child._coverageInfo; + var url = TestRunner.formatters.formatAsURL(data.url()); + + if (url.endsWith('-test.js') || url.endsWith('.html')) + continue; + + var type = Coverage.CoverageListView._typeToString(data.type()); + TestRunner.addResult(`${url} ${type} used: ${data.usedSize()} unused: ${data.unusedSize()} total: ${data.size()}`); + } +};
diff --git a/third_party/WebKit/Source/devtools/front_end/coverage_test_runner/module.json b/third_party/WebKit/Source/devtools/front_end/coverage_test_runner/module.json new file mode 100644 index 0000000..4f200a4 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/coverage_test_runner/module.json
@@ -0,0 +1,14 @@ +{ + "dependencies": [ + "test_runner", + "integration_test_runner", + "coverage", + "sources_test_runner" + ], + "scripts": [ + "CoverageTestRunner.js" + ], + "skip_compilation": [ + "CoverageTestRunner.js" + ] +}
diff --git a/third_party/WebKit/Source/devtools/front_end/data_grid/DataGrid.js b/third_party/WebKit/Source/devtools/front_end/data_grid/DataGrid.js index b891fc2..6500f66 100644 --- a/third_party/WebKit/Source/devtools/front_end/data_grid/DataGrid.js +++ b/third_party/WebKit/Source/devtools/front_end/data_grid/DataGrid.js
@@ -125,6 +125,23 @@ } /** + * @param {!Element} element + * @param {string} newText + * @param {boolean} longText + */ + static setElementText(element, newText, longText) { + if (longText && newText.length > 1000) { + element.textContent = newText.trimEnd(1000); + element.title = newText; + element[DataGrid.DataGrid._longTextSymbol] = newText; + } else { + element.textContent = newText; + element.title = ''; + element[DataGrid.DataGrid._longTextSymbol] = undefined; + } + } + + /** * @param {boolean} isStriped */ setStriped(isStriped) { @@ -351,6 +368,8 @@ } this._editing = true; + if (element[DataGrid.DataGrid._longTextSymbol]) + element.textContent = element[DataGrid.DataGrid._longTextSymbol]; UI.InplaceEditor.startEditing(element, this._startEditingConfig(element)); element.getComponentSelection().selectAllChildren(element); @@ -368,8 +387,7 @@ * @return {!UI.InplaceEditor.Config} */ _startEditingConfig(element) { - return new UI.InplaceEditor.Config( - this._editingCommitted.bind(this), this._editingCancelled.bind(this), element.textContent); + return new UI.InplaceEditor.Config(this._editingCommitted.bind(this), this._editingCancelled.bind(this)); } /** @@ -437,6 +455,9 @@ } } + // Show trimmed text after editing. + DataGrid.DataGrid.setElementText(element, newText, !!column.longText); + if (textBeforeEditing === newText) { this._editingCancelled(element); moveToNextIfNeeded.call(this, false); @@ -1216,6 +1237,7 @@ DataGrid.DataGrid._preferredWidthSymbol = Symbol('preferredWidth'); DataGrid.DataGrid._columnIdSymbol = Symbol('columnId'); DataGrid.DataGrid._sortIconSymbol = Symbol('sortIcon'); +DataGrid.DataGrid._longTextSymbol = Symbol('longText'); DataGrid.DataGrid.ColumnResizePadding = 24; DataGrid.DataGrid.CenterResizerOverBorderAdjustment = 3; @@ -1581,13 +1603,10 @@ var cell = this.createTD(columnId); var data = this.data[columnId]; - if (data instanceof Node) { + if (data instanceof Node) cell.appendChild(data); - } else if (data !== null) { - cell.textContent = data; - if (this.dataGrid._columns[columnId].longText) - cell.title = data; - } + else if (data !== null) + DataGrid.DataGrid.setElementText(cell, /** @type {string} */ (data), !!this.dataGrid._columns[columnId].longText); return cell; }
diff --git a/third_party/WebKit/Source/devtools/front_end/data_grid_test_runner/DataGridTestRunner.js b/third_party/WebKit/Source/devtools/front_end/data_grid_test_runner/DataGridTestRunner.js index bff22d7..ad3e492 100644 --- a/third_party/WebKit/Source/devtools/front_end/data_grid_test_runner/DataGridTestRunner.js +++ b/third_party/WebKit/Source/devtools/front_end/data_grid_test_runner/DataGridTestRunner.js
@@ -78,3 +78,43 @@ } return output.join('\n'); }; + +DataGridTestRunner.validateDataGrid = function(root) { + var children = root.children; + + for (var i = 0; i < children.length; ++i) { + var child = children[i]; + + if (child.parent !== root) + throw 'Wrong parent for child ' + child.data.id + ' of ' + root.data.id; + + if (child.nextSibling !== ((i + 1 === children.length ? null : children[i + 1]))) + throw 'Wrong child.nextSibling for ' + child.data.id + ' (' + i + ' of ' + children.length + ') '; + + if (child.previousSibling !== ((i ? children[i - 1] : null))) + throw 'Wrong child.previousSibling for ' + child.data.id + ' (' + i + ' of ' + children.length + ') '; + + if (child.parent && !child.parent._isRoot && child.depth !== root.depth + 1) + throw 'Wrong depth for ' + child.data.id + ' expected ' + (root.depth + 1) + ' but got ' + child.depth; + + DataGridTestRunner.validateDataGrid(child); + } + + var selectedNode = root.dataGrid.selectedNode; + + if (!root.parent && selectedNode) { + if (!selectedNode.selectable) + throw 'Selected node is not selectable'; + + for (var node = selectedNode; node && node !== root; node = node.parent) { + } + + if (!node) + throw 'Selected node (' + selectedNode.data.id + ') is not within the DataGrid'; + } +}; + +DataGridTestRunner.dumpAndValidateDataGrid = function(root) { + DataGridTestRunner.dumpDataGrid(root); + DataGridTestRunner.validateDataGrid(root); +};
diff --git a/third_party/WebKit/Source/devtools/front_end/data_grid_test_runner/module.json b/third_party/WebKit/Source/devtools/front_end/data_grid_test_runner/module.json index 89ab830..8a1da51 100644 --- a/third_party/WebKit/Source/devtools/front_end/data_grid_test_runner/module.json +++ b/third_party/WebKit/Source/devtools/front_end/data_grid_test_runner/module.json
@@ -5,5 +5,8 @@ ], "scripts": [ "DataGridTestRunner.js" + ], + "skip_compilation": [ + "DataGridTestRunner.js" ] }
diff --git a/third_party/WebKit/Source/devtools/front_end/device_mode_test_runner/DeviceModeTestRunner.js b/third_party/WebKit/Source/devtools/front_end/device_mode_test_runner/DeviceModeTestRunner.js new file mode 100644 index 0000000..017b5d59 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/device_mode_test_runner/DeviceModeTestRunner.js
@@ -0,0 +1,45 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +DeviceModeTestRunner.buildFakePhone = function(overrides) { + var StandardPhoneJSON = { + 'show-by-default': false, + 'title': 'Fake Phone 1', + + 'screen': { + 'horizontal': {'width': 480, 'height': 320}, + + 'device-pixel-ratio': 2, + + 'vertical': {'width': 320, 'height': 480} + }, + + 'capabilities': ['touch', 'mobile'], + 'user-agent': 'fakeUserAgent', + 'type': 'phone', + + 'modes': [ + { + 'title': 'default', + 'orientation': 'vertical', + + 'insets': {'left': 0, 'top': 0, 'right': 0, 'bottom': 0} + }, + { + 'title': 'default', + 'orientation': 'horizontal', + + 'insets': {'left': 0, 'top': 0, 'right': 0, 'bottom': 0} + } + ] + }; + + var json = Object.assign(StandardPhoneJSON, overrides || {}); + return Emulation.EmulatedDevice.fromJSONV1(json); +};
diff --git a/third_party/WebKit/Source/devtools/front_end/device_mode_test_runner/module.json b/third_party/WebKit/Source/devtools/front_end/device_mode_test_runner/module.json new file mode 100644 index 0000000..dde42c2a --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/device_mode_test_runner/module.json
@@ -0,0 +1,13 @@ +{ + "dependencies": [ + "test_runner", + "integration_test_runner", + "emulation" + ], + "scripts": [ + "DeviceModeTestRunner.js" + ], + "skip_compilation": [ + "DeviceModeTestRunner.js" + ] +}
diff --git a/third_party/WebKit/Source/devtools/front_end/elements_test_runner/EditDOMTestRunner.js b/third_party/WebKit/Source/devtools/front_end/elements_test_runner/EditDOMTestRunner.js new file mode 100644 index 0000000..e2bb707 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/elements_test_runner/EditDOMTestRunner.js
@@ -0,0 +1,76 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +ElementsTestRunner.doAddAttribute = function(testName, dataNodeId, attributeText, next) { + ElementsTestRunner.domActionTestForNodeId(testName, dataNodeId, testBody, next); + + function testBody(node, done) { + ElementsTestRunner.editNodePart(node, 'webkit-html-attribute'); + eventSender.keyDown('Tab'); + TestRunner.deprecatedRunAfterPendingDispatches(testContinuation); + + function testContinuation() { + var editorElement = UI.panels.elements._treeOutlines[0]._shadowRoot.getSelection().anchorNode.parentElement; + editorElement.textContent = attributeText; + editorElement.dispatchEvent(TestRunner.createKeyEvent('Enter')); + TestRunner.addSniffer(Elements.ElementsTreeOutline.prototype, '_updateModifiedNodes', done); + } + } +}; + +ElementsTestRunner.domActionTestForNodeId = function(testName, dataNodeId, testBody, next) { + function callback(testNode, continuation) { + ElementsTestRunner.selectNodeWithId(dataNodeId, continuation); + } + + ElementsTestRunner.domActionTest(testName, callback, testBody, next); +}; + +ElementsTestRunner.domActionTest = function(testName, dataNodeSelectionCallback, testBody, next) { + var testNode = ElementsTestRunner.expandedNodeWithId(testName); + TestRunner.addResult('==== before ===='); + ElementsTestRunner.dumpElementsTree(testNode); + dataNodeSelectionCallback(testNode, step0); + + function step0(node) { + TestRunner.deprecatedRunAfterPendingDispatches(step1.bind(null, node)); + } + + function step1(node) { + testBody(node, step2); + } + + function step2() { + TestRunner.addResult('==== after ===='); + ElementsTestRunner.dumpElementsTree(testNode); + next(); + } +}; + +ElementsTestRunner.editNodePart = function(node, className) { + var treeElement = ElementsTestRunner.firstElementsTreeOutline().findTreeElement(node); + var textElement = treeElement.listItemElement.getElementsByClassName(className)[0]; + + if (!textElement && treeElement.childrenListElement) + textElement = treeElement.childrenListElement.getElementsByClassName(className)[0]; + + treeElement._startEditingTarget(textElement); + return textElement; +}; + +ElementsTestRunner.editNodePartAndRun = function(node, className, newValue, step2, useSniffer) { + var editorElement = ElementsTestRunner.editNodePart(node, className); + editorElement.textContent = newValue; + editorElement.dispatchEvent(TestRunner.createKeyEvent('Enter')); + + if (useSniffer) + TestRunner.addSniffer(Elements.ElementsTreeOutline.prototype, '_updateModifiedNodes', step2); + else + TestRunner.deprecatedRunAfterPendingDispatches(step2); +};
diff --git a/third_party/WebKit/Source/devtools/front_end/elements_test_runner/ElementsPanelShadowSelectionOnRefreshTestRunner.js b/third_party/WebKit/Source/devtools/front_end/elements_test_runner/ElementsPanelShadowSelectionOnRefreshTestRunner.js new file mode 100644 index 0000000..ceea077 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/elements_test_runner/ElementsPanelShadowSelectionOnRefreshTestRunner.js
@@ -0,0 +1,39 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +ElementsTestRunner.selectReloadAndDump = function(next, node) { + ElementsTestRunner.selectNode(node).then(onSelected); + var reloaded = false; + var selected = false; + + function onSelected() { + TestRunner.reloadPage(onReloaded); + TestRunner.addSniffer(Elements.ElementsPanel.prototype, '_lastSelectedNodeSelectedForTest', onReSelected); + } + + function onReloaded() { + reloaded = true; + maybeDumpSelectedNode(); + } + + function onReSelected() { + selected = true; + maybeDumpSelectedNode(); + } + + function maybeDumpSelectedNode() { + if (!reloaded || !selected) + return; + + var selectedElement = ElementsTestRunner.firstElementsTreeOutline().selectedTreeElement; + var nodeName = (selectedElement ? selectedElement.node().nodeNameInCorrectCase() : 'null'); + TestRunner.addResult('Selected node: \'' + nodeName + '\''); + next(); + } +};
diff --git a/third_party/WebKit/Source/devtools/front_end/elements_test_runner/ElementsTestRunner.js b/third_party/WebKit/Source/devtools/front_end/elements_test_runner/ElementsTestRunner.js index 502cd8c..6f70ac2 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements_test_runner/ElementsTestRunner.js +++ b/third_party/WebKit/Source/devtools/front_end/elements_test_runner/ElementsTestRunner.js
@@ -121,3 +121,962 @@ EventListeners.EventListenersView.prototype, '_eventListenersArrivedForTest', listenersArrived); } }; + +ElementsTestRunner.inlineStyleSection = function() { + return UI.panels.elements._stylesWidget._sectionBlocks[0].sections[0]; +}; + +ElementsTestRunner.computedStyleWidget = function() { + return UI.panels.elements._computedStyleWidget; +}; + +ElementsTestRunner.dumpComputedStyle = function(doNotAutoExpand) { + var computed = ElementsTestRunner.computedStyleWidget(); + var treeOutline = computed._propertiesOutline; + var children = treeOutline.rootElement().children(); + + for (var treeElement of children) { + var property = treeElement[Elements.ComputedStyleWidget._propertySymbol]; + + if (property.name === 'width' || property.name === 'height') + continue; + + var dumpText = ''; + dumpText += treeElement.title.querySelector('.property-name').textContent; + dumpText += ' '; + dumpText += treeElement.title.querySelector('.property-value').textContent; + TestRunner.addResult(dumpText); + + if (doNotAutoExpand && !treeElement.expanded) + continue; + + for (var trace of treeElement.children()) { + var title = trace.title; + var dumpText = ''; + + if (trace.title.classList.contains('property-trace-inactive')) + dumpText += 'OVERLOADED '; + + dumpText += title.querySelector('.property-trace-value').textContent; + dumpText += ' - '; + dumpText += title.querySelector('.property-trace-selector').textContent; + var link = title.querySelector('.trace-link'); + + if (link) + dumpText += ' ' + extractLinkText(link); + + TestRunner.addResult(' ' + dumpText); + } + } +}; + +ElementsTestRunner.findComputedPropertyWithName = function(name) { + var computed = ElementsTestRunner.computedStyleWidget(); + var treeOutline = computed._propertiesOutline; + var children = treeOutline.rootElement().children(); + + for (var treeElement of children) { + var property = treeElement[Elements.ComputedStyleWidget._propertySymbol]; + + if (property.name === name) + return treeElement; + } + + return null; +}; + +ElementsTestRunner.firstMatchedStyleSection = function() { + return UI.panels.elements._stylesWidget._sectionBlocks[0].sections[1]; +}; + +ElementsTestRunner.firstMediaTextElementInSection = function(section) { + return section.element.querySelector('.media-text'); +}; + +ElementsTestRunner.querySelector = async function(selector, callback) { + var doc = await TestRunner.domModel.requestDocumentPromise(); + var nodeId = await TestRunner.domModel.querySelector(doc.id, selector); + callback(TestRunner.domModel.nodeForId(nodeId)); +}; + +ElementsTestRunner.shadowRootByHostId = function(idValue, callback) { + function shadowRootMatches(node) { + return node.isShadowRoot() && node.parentNode.getAttribute('id') === idValue; + } + + ElementsTestRunner.findNode(shadowRootMatches, callback); +}; + +ElementsTestRunner.nodeWithClass = function(classValue, callback) { + function nodeClassMatches(node) { + var classAttr = node.getAttribute('class'); + return classAttr && classAttr.indexOf(classValue) > -1; + } + + ElementsTestRunner.findNode(nodeClassMatches, callback); +}; + +ElementsTestRunner.expandedNodeWithId = function(idValue) { + var result; + ElementsTestRunner.nodeWithId(idValue, node => result = node); + return result; +}; + +function waitForStylesRebuild(matchFunction, callback, requireRebuild) { + (function sniff(node, rebuild) { + if ((rebuild || !requireRebuild) && node && matchFunction(node)) { + callback(); + return; + } + + TestRunner.addSniffer(Elements.StylesSidebarPane.prototype, '_nodeStylesUpdatedForTest', sniff); + })(null); +} + +ElementsTestRunner.waitForStyles = function(idValue, callback, requireRebuild) { + callback = TestRunner.safeWrap(callback); + + function nodeWithId(node) { + return node.getAttribute('id') === idValue; + } + + waitForStylesRebuild(nodeWithId, callback, requireRebuild); +}; + +ElementsTestRunner.waitForStylesForClass = function(classValue, callback, requireRebuild) { + callback = TestRunner.safeWrap(callback); + + function nodeWithClass(node) { + var classAttr = node.getAttribute('class'); + return classAttr && classAttr.indexOf(classValue) > -1; + } + + waitForStylesRebuild(nodeWithClass, callback, requireRebuild); +}; + +ElementsTestRunner.waitForSelectorCommitted = function(callback) { + TestRunner.addSniffer(Elements.StylePropertiesSection.prototype, '_editingSelectorCommittedForTest', callback); +}; + +ElementsTestRunner.waitForMediaTextCommitted = function(callback) { + TestRunner.addSniffer(Elements.StylePropertiesSection.prototype, '_editingMediaTextCommittedForTest', callback); +}; + +ElementsTestRunner.waitForStyleApplied = function(callback) { + TestRunner.addSniffer(Elements.StylePropertyTreeElement.prototype, 'styleTextAppliedForTest', callback); +}; + +ElementsTestRunner.selectNodeAndWaitForStyles = function(idValue, callback) { + callback = TestRunner.safeWrap(callback); + var targetNode; + ElementsTestRunner.waitForStyles(idValue, stylesUpdated, true); + ElementsTestRunner.selectNodeWithId(idValue, nodeSelected); + + function nodeSelected(node) { + targetNode = node; + } + + function stylesUpdated() { + callback(targetNode); + } +}; + +ElementsTestRunner.selectPseudoElementAndWaitForStyles = function(parentId, pseudoType, callback) { + callback = TestRunner.safeWrap(callback); + var targetNode; + waitForStylesRebuild(isPseudoElement, stylesUpdated, true); + ElementsTestRunner.findNode(isPseudoElement, nodeFound); + + function nodeFound(node) { + targetNode = node; + Common.Revealer.reveal(node); + } + + function stylesUpdated() { + callback(targetNode); + } + + function isPseudoElement(node) { + return node.parentNode && node.parentNode.getAttribute('id') === parentId && node.pseudoType() === pseudoType; + } +}; + +ElementsTestRunner.selectNodeAndWaitForStylesWithComputed = function(idValue, callback) { + callback = TestRunner.safeWrap(callback); + ElementsTestRunner.selectNodeAndWaitForStyles(idValue, onSidebarRendered); + + function onSidebarRendered(node) { + ElementsTestRunner.computedStyleWidget().doUpdate().then(callback.bind(null, node)); + } +}; + +ElementsTestRunner.firstElementsTreeOutline = function() { + return UI.panels.elements._treeOutlines[0]; +}; + +ElementsTestRunner.filterMatchedStyles = function(text) { + var regex = (text ? new RegExp(text, 'i') : null); + TestRunner.addResult('Filtering styles by: ' + text); + UI.panels.elements._stylesWidget._onFilterChanged(regex); +}; + +ElementsTestRunner.dumpRenderedMatchedStyles = function() { + var sectionBlocks = UI.panels.elements._stylesWidget._sectionBlocks; + + for (var block of sectionBlocks) { + for (var section of block.sections) { + if (section.element.classList.contains('hidden')) + continue; + + dumpRenderedSection(section); + } + } + + function dumpRenderedSection(section) { + TestRunner.addResult(section._selectorElement.textContent + ' {'); + var rootElement = section.propertiesTreeOutline.rootElement(); + + for (var i = 0; i < rootElement.childCount(); ++i) + dumpRenderedProperty(rootElement.childAt(i)); + + TestRunner.addResult('}'); + } + + function dumpRenderedProperty(property) { + var text = new Array(4).join(' '); + text += property.nameElement.textContent; + text += ':'; + + if (property.isExpandable()) + text += (property.expanded ? 'v' : '>'); + else + text += ' '; + + text += property.valueElement.textContent; + + if (property.listItemElement.classList.contains('filter-match')) + text = 'F' + text.substring(1); + + TestRunner.addResult(text); + + if (!property.expanded) + return; + + var indent = new Array(8).join(' '); + + for (var i = 0; i < property.childCount(); ++i) { + var childProperty = property.childAt(i); + var text = indent; + text += String.sprintf('%s: %s', childProperty.nameElement.textContent, childProperty.valueElement.textContent); + + if (childProperty.listItemElement.classList.contains('filter-match')) + text = 'F' + text.substring(1); + + TestRunner.addResult(text); + } + } +}; + +ElementsTestRunner.dumpSelectedElementStyles = function( + excludeComputed, excludeMatched, omitLonghands, includeSelectorGroupMarks) { + var sectionBlocks = UI.panels.elements._stylesWidget._sectionBlocks; + + if (!excludeComputed) + ElementsTestRunner.dumpComputedStyle(); + + for (var block of sectionBlocks) { + for (var section of block.sections) { + if (section.style().parentRule && excludeMatched) + continue; + + if (section.element.previousSibling && section.element.previousSibling.className === 'sidebar-separator') { + var nodeDescription = ''; + + if (section.element.previousSibling.firstElementChild) + nodeDescription = section.element.previousSibling.firstElementChild.shadowRoot.lastChild.textContent; + + TestRunner.addResult('======== ' + section.element.previousSibling.textContent + nodeDescription + ' ========'); + } + + printStyleSection(section, omitLonghands, includeSelectorGroupMarks); + } + } +}; + +function printStyleSection(section, omitLonghands, includeSelectorGroupMarks) { + if (!section) + return; + + TestRunner.addResult( + '[expanded] ' + ((section.propertiesTreeOutline.element.classList.contains('no-affect') ? '[no-affect] ' : ''))); + var medias = section._titleElement.querySelectorAll('.media-list .media'); + + for (var i = 0; i < medias.length; ++i) { + var media = medias[i]; + TestRunner.addResult(media.textContent); + } + + var selector = + section._titleElement.querySelector('.selector') || section._titleElement.querySelector('.keyframe-key'); + var selectorText = (includeSelectorGroupMarks ? buildMarkedSelectors(selector) : selector.textContent); + selectorText += selector.nextSibling.textContent; + var anchor = section._titleElement.querySelector('.styles-section-subtitle'); + + if (anchor) { + var anchorText = extractLinkText(anchor); + selectorText += String.sprintf(' (%s)', anchorText); + } + + TestRunner.addResult(selectorText); + ElementsTestRunner.dumpStyleTreeOutline(section.propertiesTreeOutline, (omitLonghands ? 1 : 2)); + TestRunner.addResult(''); +} + +function extractLinkText(element) { + var anchor = element.querySelector('.devtools-link'); + + if (!anchor) + return element.textContent; + + var anchorText = anchor.textContent; + var info = Components.Linkifier._linkInfo(anchor); + var uiLocation = info && info.uiLocation; + var anchorTarget = + (uiLocation ? + uiLocation.uiSourceCode.name() + ':' + (uiLocation.lineNumber + 1) + ':' + (uiLocation.columnNumber + 1) : + ''); + return anchorText + ' -> ' + anchorTarget; +} + +function buildMarkedSelectors(element) { + var result = ''; + + for (var node = element.firstChild; node; node = node.nextSibling) { + if (node.nodeType === Node.ELEMENT_NODE && node.classList.contains('selector-matches')) + result += '[$' + node.textContent + '$]'; + else + result += node.textContent; + } + + return result; +} + +ElementsTestRunner.toggleStyleProperty = function(propertyName, checked) { + var treeItem = ElementsTestRunner.getElementStylePropertyTreeItem(propertyName); + + treeItem._toggleEnabled({ + target: {checked: checked}, + + consume: function() {} + }); +}; + +ElementsTestRunner.toggleMatchedStyleProperty = function(propertyName, checked) { + var treeItem = ElementsTestRunner.getMatchedStylePropertyTreeItem(propertyName); + + treeItem._toggleEnabled({ + target: {checked: checked}, + + consume: function() {} + }); +}; + +ElementsTestRunner.eventListenersWidget = function() { + UI.viewManager.showView('elements.eventListeners'); + return self.runtime.sharedInstance(Elements.EventListenersWidget); +}; + +ElementsTestRunner.showEventListenersWidget = function() { + return UI.viewManager.showView('elements.eventListeners'); +}; + +ElementsTestRunner.expandAndDumpSelectedElementEventListeners = function(callback, force) { + ElementsTestRunner.expandAndDumpEventListeners( + ElementsTestRunner.eventListenersWidget()._eventListenersView, callback, force); +}; + +ElementsTestRunner.removeFirstEventListener = function() { + var treeOutline = ElementsTestRunner.eventListenersWidget()._eventListenersView._treeOutline; + var listenerTypes = treeOutline.rootElement().children(); + + for (var i = 0; i < listenerTypes.length; i++) { + var listeners = listenerTypes[i].children(); + + if (listeners.length && !listenerTypes[i].hidden) { + listeners[0].eventListener().remove(); + listeners[0]._removeListenerBar(); + break; + } + } +}; + +ElementsTestRunner.dumpObjectPropertySectionDeep = function(section) { + function domNodeToString(node) { + if (node) + return '\'' + node.textContent + '\''; + else + return 'null'; + } + + function dumpTreeElementRecursively(treeElement, prefix) { + if ('nameElement' in treeElement) { + TestRunner.addResult( + prefix + domNodeToString(treeElement.nameElement) + ' => ' + domNodeToString(treeElement.valueElement)); + } else { + TestRunner.addResult(prefix + treeElement.title); + } + + for (var i = 0; i < treeElement.childCount(); i++) + dumpTreeElementRecursively(treeElement.childAt(i), prefix + ' '); + } + + var childNodes = section.propertiesTreeOutline.rootElement().children(); + + for (var i = 0; i < childNodes.length; i++) + dumpTreeElementRecursively(childNodes[i], ''); + +}; + +ElementsTestRunner.getElementStylePropertyTreeItem = function(propertyName) { + return ElementsTestRunner.getFirstPropertyTreeItemForSection(ElementsTestRunner.inlineStyleSection(), propertyName); +}; + +ElementsTestRunner.getMatchedStylePropertyTreeItem = function(propertyName) { + var sectionBlocks = UI.panels.elements._stylesWidget._sectionBlocks; + + for (var block of sectionBlocks) { + for (var section of block.sections) { + var treeItem = ElementsTestRunner.getFirstPropertyTreeItemForSection(section, propertyName); + + if (treeItem) + return treeItem; + } + } + + return null; +}; + +ElementsTestRunner.getFirstPropertyTreeItemForSection = function(section, propertyName) { + var outline = section.propertiesTreeOutline.rootElement(); + + for (var i = 0; i < outline.childCount(); ++i) { + var treeItem = outline.childAt(i); + + if (treeItem.name === propertyName) + return treeItem; + } + + return null; +}; + +ElementsTestRunner.dumpStyleTreeOutline = function(treeItem, depth) { + var children = treeItem.rootElement().children(); + + for (var i = 0; i < children.length; ++i) + ElementsTestRunner.dumpStyleTreeItem(children[i], '', depth || 2); +}; + +ElementsTestRunner.dumpStyleTreeItem = function(treeItem, prefix, depth) { + if (treeItem.listItemElement.textContent.indexOf(' width:') !== -1 || + treeItem.listItemElement.textContent.indexOf(' height:') !== -1) + return; + + if (treeItem.listItemElement.classList.contains('inherited')) + return; + + var typePrefix = ''; + + if (treeItem.listItemElement.classList.contains('overloaded') || + treeItem.listItemElement.classList.contains('inactive') || + treeItem.listItemElement.classList.contains('not-parsed-ok')) + typePrefix += '/-- overloaded --/ '; + + if (treeItem.listItemElement.classList.contains('disabled')) + typePrefix += '/-- disabled --/ '; + + var textContent = treeItem.listItemElement.textContent; + TestRunner.addResult(prefix + typePrefix + textContent); + + if (--depth) { + treeItem.expand(); + var children = treeItem.children(); + + for (var i = 0; children && i < children.length; ++i) + ElementsTestRunner.dumpStyleTreeItem(children[i], prefix + ' ', depth); + } +}; + +ElementsTestRunner.dumpElementsTree = function(rootNode, depth, resultsArray) { + function beautify(element) { + return element.innerText.replace(/\u200b/g, '').replace(/\n/g, '\\n').trim(); + } + + function dumpMap(name, map) { + var result = []; + + for (var id of map.keys()) + result.push(id + '=' + map.get(id)); + + if (!result.length) + return ''; + + return name + ':[' + result.join(',') + ']'; + } + + function markersDataDump(treeItem) { + if (treeItem._elementCloseTag) + return ''; + + var markers = ''; + var node = treeItem._node; + + if (node) { + markers += dumpMap('markers', node._markers); + var dump = (node._subtreeMarkerCount ? 'subtreeMarkerCount:' + node._subtreeMarkerCount : ''); + + if (dump) { + if (markers) + markers += ', '; + + markers += dump; + } + + if (markers) + markers = ' [' + markers + ']'; + } + + return markers; + } + + function print(treeItem, prefix, depth) { + if (!treeItem.root) { + var expander; + + if (treeItem.isExpandable()) { + if (treeItem.expanded) + expander = '- '; + else + expander = '+ '; + } else { + expander = ' '; + } + + var markers = markersDataDump(treeItem); + var value = prefix + expander + beautify(treeItem.listItemElement) + markers; + + if (treeItem.shadowHostToolbar) { + value = prefix + expander + 'shadow-root '; + + for (var i = 0; i < treeItem.shadowHostToolbar.children.length; ++i) { + var button = treeItem.shadowHostToolbar.children[i]; + var toggled = button.disabled; + var name = ((toggled ? '<' : '')) + button.textContent + ((toggled ? '>' : '')); + value += name + ' '; + } + } + + if (resultsArray) + resultsArray.push(value); + else + TestRunner.addResult(value); + } + + if (!treeItem.expanded) + return; + + var children = treeItem.children(); + var newPrefix = (treeItem.root ? '' : prefix + ' '); + + for (var i = 0; depth && children && i < children.length; ++i) { + if (!children[i]._elementCloseTag) + print(children[i], newPrefix, depth - 1); + else + print(children[i], prefix, depth); + } + } + + var treeOutline = ElementsTestRunner.firstElementsTreeOutline(); + treeOutline.runPendingUpdates(); + print((rootNode ? treeOutline.findTreeElement(rootNode) : treeOutline.rootElement()), '', depth || 10000); +}; + +ElementsTestRunner.dumpDOMUpdateHighlights = function(rootNode, callback, depth) { + var hasHighlights = false; + TestRunner.addSniffer(Elements.ElementsTreeOutline.prototype, '_updateModifiedNodes', didUpdate); + + function didUpdate() { + var treeOutline = ElementsTestRunner.firstElementsTreeOutline(); + print((rootNode ? treeOutline.findTreeElement(rootNode) : treeOutline.rootElement()), '', depth || 10000); + + if (!hasHighlights) + TestRunner.addResult('<No highlights>'); + + if (callback) + callback(); + } + + function print(treeItem, prefix, depth) { + if (!treeItem.root) { + var elementXPath = Components.DOMPresentationUtils.xPath(treeItem.node(), true); + var highlightedElements = treeItem.listItemElement.querySelectorAll('.dom-update-highlight'); + + for (var i = 0; i < highlightedElements.length; ++i) { + var element = highlightedElements[i]; + var classList = element.classList; + var xpath = elementXPath; + + if (classList.contains('webkit-html-attribute-name')) { + xpath += '/@' + element.textContent + ' (empty)'; + } else if (classList.contains('webkit-html-attribute-value')) { + name = element.parentElement.querySelector('.webkit-html-attribute-name').textContent; + xpath += '/@' + name + ' ' + element.textContent; + } else if (classList.contains('webkit-html-text-node')) { + xpath += '/text() "' + element.textContent + '"'; + } + + TestRunner.addResult(prefix + xpath); + hasHighlights = true; + } + } + + if (!treeItem.expanded) + return; + + var children = treeItem.children(); + var newPrefix = (treeItem.root ? '' : prefix + ' '); + + for (var i = 0; depth && children && i < children.length; ++i) { + if (!children[i]._elementCloseTag) + print(children[i], newPrefix, depth - 1); + } + } +}; + +ElementsTestRunner.expandElementsTree = function(callback) { + var expandedSomething = false; + callback = TestRunner.safeWrap(callback); + + function expand(treeItem) { + var children = treeItem.children(); + + for (var i = 0; children && i < children.length; ++i) { + var child = children[i]; + + if (child.isExpandable() && !child.expanded) { + child.expand(); + expandedSomething = true; + } + + expand(child); + } + } + + function onAllNodesAvailable() { + ElementsTestRunner.firstElementsTreeOutline().runPendingUpdates(); + expand(ElementsTestRunner.firstElementsTreeOutline().rootElement()); + setTimeout(callback.bind(null, expandedSomething)); + } + + ElementsTestRunner.findNode(function() { + return false; + }, onAllNodesAvailable); +}; + +ElementsTestRunner.dumpDOMAgentTree = function(node) { + if (!TestRunner.domModel._document) + return; + + function dump(node, prefix) { + TestRunner.addResult(prefix + node.nodeName()); + prefix = prefix + ' '; + + if (node.templateContent()) + dump(node.templateContent(), prefix); + + if (node.importedDocument()) + dump(node.importedDocument(), prefix); + + var shadowRoots = node.shadowRoots(); + + for (var i = 0; i < shadowRoots.length; ++i) + dump(shadowRoots[i], prefix); + + var children = node.children(); + + for (var i = 0; children && i < children.length; ++i) + dump(children[i], prefix); + } + + dump(node, ''); +}; + +ElementsTestRunner.rangeText = function(range) { + if (!range) + return '[undefined-undefined]'; + + return '[' + range.startLine + ':' + range.startColumn + '-' + range.endLine + ':' + range.endColumn + ']'; +}; + +ElementsTestRunner.generateUndoTest = function(testBody) { + function result(next) { + var testNode = ElementsTestRunner.expandedNodeWithId(/function\s([^(]*)/.exec(testBody)[1]); + TestRunner.addResult('Initial:'); + ElementsTestRunner.dumpElementsTree(testNode); + testBody(undo); + + function undo() { + TestRunner.addResult('Post-action:'); + ElementsTestRunner.dumpElementsTree(testNode); + ElementsTestRunner.expandElementsTree(expandedCallback); + + function expandedCallback(expandedSomething) { + if (expandedSomething) { + TestRunner.addResult('== Expanded: =='); + ElementsTestRunner.dumpElementsTree(testNode); + } + + TestRunner.domModel.undo().then(redo); + } + } + + function redo() { + TestRunner.addResult('Post-undo (initial):'); + ElementsTestRunner.dumpElementsTree(testNode); + ElementsTestRunner.expandElementsTree(expandedCallback); + + function expandedCallback(expandedSomething) { + if (expandedSomething) { + TestRunner.addResult('== Expanded: =='); + ElementsTestRunner.dumpElementsTree(testNode); + } + + TestRunner.domModel.redo().then(done); + } + } + + function done() { + TestRunner.addResult('Post-redo (action):'); + ElementsTestRunner.dumpElementsTree(testNode); + ElementsTestRunner.expandElementsTree(expandedCallback); + + function expandedCallback(expandedSomething) { + if (expandedSomething) { + TestRunner.addResult('== Expanded: =='); + ElementsTestRunner.dumpElementsTree(testNode); + } + + next(); + } + } + } + + result.toString = function() { + return testBody.toString(); + }; + + return result; +}; + +const indent = ' '; + +ElementsTestRunner.dumpRulesArray = function(rules, currentIndent) { + if (!rules) + return; + + currentIndent = currentIndent || ''; + + for (var i = 0; i < rules.length; ++i) + ElementsTestRunner.dumpRule(rules[i], currentIndent); +}; + +ElementsTestRunner.dumpRuleMatchesArray = function(matches, currentIndent) { + if (!matches) + return; + + currentIndent = currentIndent || ''; + + for (var i = 0; i < matches.length; ++i) + ElementsTestRunner.dumpRule(matches[i].rule, currentIndent); +}; + +ElementsTestRunner.dumpRule = function(rule, currentIndent) { + function selectorRange() { + var selectors = rule.selectorList.selectors; + + if (!selectors || !selectors[0].range) + return ''; + + var ranges = []; + + for (var i = 0; i < selectors.length; ++i) { + var range = selectors[i].range; + ranges.push(range.startLine + ':' + range.startColumn + '-' + range.endLine + ':' + range.endColumn); + } + + return ', ' + ranges.join('; '); + } + + currentIndent = currentIndent || ''; + + if (!rule.type || rule.type === 'style') { + TestRunner.addResult(currentIndent + rule.selectorList.text + ': [' + rule.origin + selectorRange() + '] {'); + ElementsTestRunner.dumpStyle(rule.style, currentIndent + indent); + TestRunner.addResult(currentIndent + '}'); + return; + } + + if (rule.type === 'media') { + TestRunner.addResult(currentIndent + '@media ' + rule.mediaText + ' {'); + ElementsTestRunner.dumpRulesArray(rule.childRules, currentIndent + indent); + TestRunner.addResult(currentIndent + '}'); + return; + } + + if (rule.type === 'import') { + TestRunner.addResult( + currentIndent + '@import: header=' + ElementsTestRunner.rangeText(rule.headerRange) + + ', body=' + ElementsTestRunner.rangeText(rule.bodyRange)); + + return; + } + + if (rule.type === 'page' || rule.type === 'font-face') { + if (rule.type === 'page') { + TestRunner.addResult(currentIndent + rule.selectorList.text + ' {'); + } else { + TestRunner.addResult( + currentIndent + '@' + rule.type + ' ' + ((rule.selectorList.text ? rule.selectorList.text + ' ' : '')) + '{'); + } + + ElementsTestRunner.dumpStyle(rule.style, currentIndent + indent); + TestRunner.addResult(currentIndent + '}'); + return; + } + + if (rule.type === 'charset') { + TestRunner.addResult('@charset'); + return; + } + + TestRunner.addResult( + currentIndent + '[UNKNOWN RULE]: header=' + ElementsTestRunner.rangeText(rule.headerRange) + + ', body=' + ElementsTestRunner.rangeText(rule.bodyRange)); +}; + +ElementsTestRunner.dumpStyle = function(style, currentIndent) { + currentIndent = currentIndent || ''; + + if (!style) { + TestRunner.addResult(currentIndent + '[NO STYLE]'); + return; + } + + for (var i = 0; i < style.cssProperties.length; ++i) { + var property = style.cssProperties[i]; + + if (!property.disabled) { + TestRunner.addResult( + currentIndent + '[\'' + property.name + '\':\'' + property.value + '\'' + + ((property.important ? ' is-important' : '')) + (('parsedOk' in property ? ' non-parsed' : '')) + '] @' + + ElementsTestRunner.rangeText(property.range) + ' '); + } else { + TestRunner.addResult(currentIndent + '[text=\'' + property.text + '\'] disabled'); + } + } +}; + +ElementsTestRunner.dumpCSSStyleDeclaration = function(style, currentIndent) { + currentIndent = currentIndent || ''; + + if (!style) { + TestRunner.addResult(currentIndent + '[NO STYLE]'); + return; + } + + var properties = style.allProperties(); + + for (var i = 0; i < properties.length; ++i) { + var property = properties[i]; + + if (!property.disabled) { + TestRunner.addResult( + currentIndent + '[\'' + property.name + '\':\'' + property.value + '\'' + + ((property.important ? ' is-important' : '')) + ((!property['parsedOk'] ? ' non-parsed' : '')) + '] @' + + ElementsTestRunner.rangeText(property.range) + ' '); + } else { + TestRunner.addResult(currentIndent + '[text=\'' + property.text + '\'] disabled'); + } + } +}; + +ElementsTestRunner.dumpBreadcrumb = function(message) { + if (message) + TestRunner.addResult(message + ':'); + + var result = []; + var crumbs = UI.panels.elements._breadcrumbs.crumbsElement; + var crumb = crumbs.lastChild; + + while (crumb) { + result.unshift(crumb.textContent); + crumb = crumb.previousSibling; + } + + TestRunner.addResult(result.join(' > ')); +}; + +ElementsTestRunner.matchingSelectors = function(matchedStyles, rule) { + var selectors = []; + var matchingSelectors = matchedStyles.matchingSelectors(rule); + + for (var i = 0; i < matchingSelectors.length; ++i) + selectors.push(rule.selectors[matchingSelectors[i]].text); + + return '[' + selectors.join(', ') + ']'; +}; + +ElementsTestRunner.addNewRuleInStyleSheet = function(styleSheetHeader, selector, callback) { + TestRunner.addSniffer( + Elements.StylesSidebarPane.prototype, '_addBlankSection', onBlankSection.bind(null, selector, callback)); + UI.panels.elements._stylesWidget._createNewRuleInStyleSheet(styleSheetHeader); +}; + +ElementsTestRunner.addNewRule = function(selector, callback) { + UI.panels.elements._stylesWidget.contentElement.querySelector('.styles-pane-toolbar') + .shadowRoot.querySelector('.largeicon-add') + .click(); + TestRunner.addSniffer( + Elements.StylesSidebarPane.prototype, '_addBlankSection', onBlankSection.bind(null, selector, callback)); +}; + +function onBlankSection(selector, callback) { + var section = ElementsTestRunner.firstMatchedStyleSection(); + + if (typeof selector === 'string') + section._selectorElement.textContent = selector; + + section._selectorElement.dispatchEvent(TestRunner.createKeyEvent('Enter')); + ElementsTestRunner.waitForSelectorCommitted(callback.bind(null, section)); +} + +ElementsTestRunner.dumpInspectorHighlightJSON = function(idValue, callback) { + ElementsTestRunner.nodeWithId(idValue, nodeResolved); + + async function nodeResolved(node) { + var result = await TestRunner.OverlayAgent.getHighlightObjectForTest(node.id); + TestRunner.addResult(idValue + JSON.stringify(result, null, 2)); + callback(); + } +}; + +ElementsTestRunner.waitForAnimationAdded = function(callback) { + TestRunner.addSniffer(Animation.AnimationTimeline.prototype, '_addAnimationGroup', callback); +}; + +ElementsTestRunner.dumpAnimationTimeline = function(timeline) { + for (var ui of timeline._uiAnimations) { + TestRunner.addResult(ui.animation().type()); + TestRunner.addResult(ui._nameElement.innerHTML); + TestRunner.addResult(ui._svg.innerHTML); + } +};
diff --git a/third_party/WebKit/Source/devtools/front_end/elements_test_runner/SetOuterHTMLTestRunner.js b/third_party/WebKit/Source/devtools/front_end/elements_test_runner/SetOuterHTMLTestRunner.js new file mode 100644 index 0000000..abdc7e7 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/elements_test_runner/SetOuterHTMLTestRunner.js
@@ -0,0 +1,109 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +ElementsTestRunner.events = []; +ElementsTestRunner.containerId; + +ElementsTestRunner.setUpTestSuite = function(next) { + ElementsTestRunner.expandElementsTree(step1); + + function step1() { + ElementsTestRunner.selectNodeWithId('container', step2); + } + + function step2(node) { + ElementsTestRunner.containerId = node.id; + TestRunner.DOMAgent.getOuterHTML(ElementsTestRunner.containerId).then(step3); + } + + function step3(text) { + ElementsTestRunner.containerText = text; + + for (var key in SDK.DOMModel.Events) { + var eventName = SDK.DOMModel.Events[key]; + + if (eventName === SDK.DOMModel.Events.MarkersChanged || eventName === SDK.DOMModel.Events.DOMMutated) + continue; + + TestRunner.domModel.addEventListener( + eventName, ElementsTestRunner.recordEvent.bind(ElementsTestRunner, eventName)); + } + + next(); + } +}; + +ElementsTestRunner.recordEvent = function(eventName, event) { + if (!event.data) + return; + + var node = event.data.node || event.data; + var parent = event.data.parent; + + for (var currentNode = parent || node; currentNode; currentNode = currentNode.parentNode) { + if (currentNode.getAttribute('id') === 'output') + return; + } + + ElementsTestRunner.events.push('Event ' + eventName.toString() + ': ' + node.nodeName()); +}; + +ElementsTestRunner.patchOuterHTML = function(pattern, replacement, next) { + TestRunner.addResult('Replacing \'' + pattern + '\' with \'' + replacement + '\'\n'); + ElementsTestRunner.setOuterHTML(ElementsTestRunner.containerText.replace(pattern, replacement), next); +}; + +ElementsTestRunner.patchOuterHTMLUseUndo = function(pattern, replacement, next) { + TestRunner.addResult('Replacing \'' + pattern + '\' with \'' + replacement + '\'\n'); + ElementsTestRunner.setOuterHTMLUseUndo(ElementsTestRunner.containerText.replace(pattern, replacement), next); +}; + +ElementsTestRunner.setOuterHTML = function(newText, next) { + ElementsTestRunner.innerSetOuterHTML(newText, false, bringBack); + + function bringBack() { + TestRunner.addResult('\nBringing things back\n'); + ElementsTestRunner.innerSetOuterHTML(ElementsTestRunner.containerText, true, next); + } +}; + +ElementsTestRunner.setOuterHTMLUseUndo = function(newText, next) { + ElementsTestRunner.innerSetOuterHTML(newText, false, bringBack); + + async function bringBack() { + TestRunner.addResult('\nBringing things back\n'); + await TestRunner.domModel.undo(); + ElementsTestRunner._dumpOuterHTML(true, next); + } +}; + +ElementsTestRunner.innerSetOuterHTML = async function(newText, last, next) { + await TestRunner.DOMAgent.setOuterHTML(ElementsTestRunner.containerId, newText); + ElementsTestRunner._dumpOuterHTML(last, next); +}; + +ElementsTestRunner._dumpOuterHTML = async function(last, next) { + var result = await TestRunner.RuntimeAgent.evaluate('document.getElementById("identity").wrapperIdentity'); + TestRunner.addResult('Wrapper identity: ' + result.value); + ElementsTestRunner.events.sort(); + + for (var i = 0; i < ElementsTestRunner.events.length; ++i) + TestRunner.addResult(ElementsTestRunner.events[i]); + + ElementsTestRunner.events = []; + var text = await TestRunner.DOMAgent.getOuterHTML(ElementsTestRunner.containerId); + TestRunner.addResult('==========8<=========='); + TestRunner.addResult(text); + TestRunner.addResult('==========>8=========='); + + if (last) + TestRunner.addResult('\n\n\n'); + + next(); +};
diff --git a/third_party/WebKit/Source/devtools/front_end/elements_test_runner/StylesUpdateLinksTestRunner.js b/third_party/WebKit/Source/devtools/front_end/elements_test_runner/StylesUpdateLinksTestRunner.js new file mode 100644 index 0000000..a48b193 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/elements_test_runner/StylesUpdateLinksTestRunner.js
@@ -0,0 +1,129 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +function flattenRuleRanges(rule) { + var ranges = []; + var medias = rule.media || []; + + for (var i = 0; i < medias.length; ++i) { + var media = medias[i]; + + if (!media.range) + continue; + + ranges.push({range: media.range, name: 'media #' + i}); + } + + for (var i = 0; i < rule.selectors.length; ++i) { + var selector = rule.selectors[i]; + + if (!selector.range) + continue; + + ranges.push({range: selector.range, name: 'selector #' + i}); + } + + if (rule.style.range) + ranges.push({range: rule.style.range, name: 'style range'}); + + + var properties = rule.style.allProperties(); + + for (var i = 0; i < properties.length; ++i) { + var property = properties[i]; + + if (!property.range) + continue; + + ranges.push({range: property.range, name: 'property >>' + property.text + '<<'}); + } + + return ranges; +} + +function compareRuleRanges(lazyRule, originalRule) { + if (lazyRule.selectorText !== originalRule.selectorText) { + TestRunner.addResult( + 'Error: rule selectors are not equal: ' + lazyRule.selectorText + ' != ' + originalRule.selectorText); + return false; + } + + var flattenLazy = flattenRuleRanges(lazyRule); + var flattenOriginal = flattenRuleRanges(originalRule); + + if (flattenLazy.length !== flattenOriginal.length) { + TestRunner.addResult( + 'Error: rule range amount is not equal: ' + flattenLazy.length + ' != ' + flattenOriginal.length); + return false; + } + + for (var i = 0; i < flattenLazy.length; ++i) { + var lazyRange = flattenLazy[i]; + var originalRange = flattenOriginal[i]; + + if (lazyRange.name !== originalRange.name) { + TestRunner.addResult('Error: rule names are not equal: ' + lazyRange.name + ' != ' + originalRange.name); + return false; + } + + if (!lazyRange.range.equal(originalRange.range)) { + TestRunner.addResult( + 'Error: ranges \'' + lazyRange.name + '\' are not equal: ' + lazyRange.range.toString() + + ' != ' + originalRange.range.toString()); + + return false; + } + } + + TestRunner.addResult(flattenLazy.length + ' rule ranges are equal.'); + return true; +} + +ElementsTestRunner.validateRuleRanges = function(selector, rules, callback) { + ElementsTestRunner.selectNodeAndWaitForStyles('other', onOtherSelected); + + function onOtherSelected() { + ElementsTestRunner.selectNodeAndWaitForStyles(selector, onContainerSelected); + } + + function onContainerSelected() { + var fetchedRules = ElementsTestRunner.getMatchedRules(); + + if (fetchedRules.length !== rules.length) { + TestRunner.addResult(String.sprintf( + 'Error: rules sizes are not equal! Expected: %d, actual: %d', fetchedRules.length, rules.length)); + TestRunner.completeTest(); + return; + } + + for (var i = 0; i < fetchedRules.length; ++i) { + if (!compareRuleRanges(rules[i], fetchedRules[i])) { + TestRunner.completeTest(); + return; + } + } + + callback(); + } +}; + +ElementsTestRunner.getMatchedRules = function() { + var rules = []; + + for (var block of UI.panels.elements._stylesWidget._sectionBlocks) { + for (var section of block.sections) { + var rule = section.style().parentRule; + + if (rule) + rules.push(rule); + } + } + + return rules; +};
diff --git a/third_party/WebKit/Source/devtools/front_end/elements_test_runner/module.json b/third_party/WebKit/Source/devtools/front_end/elements_test_runner/module.json index f39e9e9b..6111fce0 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements_test_runner/module.json +++ b/third_party/WebKit/Source/devtools/front_end/elements_test_runner/module.json
@@ -3,9 +3,21 @@ "test_runner", "integration_test_runner", "elements", - "event_listeners" + "event_listeners", + "animation" ], "scripts": [ - "ElementsTestRunner.js" + "ElementsTestRunner.js", + "EditDOMTestRunner.js", + "SetOuterHTMLTestRunner.js", + "ElementsPanelShadowSelectionOnRefreshTestRunner.js", + "StylesUpdateLinksTestRunner.js" + ], + "skip_compilation": [ + "ElementsTestRunner.js", + "EditDOMTestRunner.js", + "SetOuterHTMLTestRunner.js", + "ElementsPanelShadowSelectionOnRefreshTestRunner.js", + "StylesUpdateLinksTestRunner.js" ] }
diff --git a/third_party/WebKit/Source/devtools/front_end/extensions_test_runner/ExtensionsNetworkTestRunner.js b/third_party/WebKit/Source/devtools/front_end/extensions_test_runner/ExtensionsNetworkTestRunner.js new file mode 100644 index 0000000..497078f --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/extensions_test_runner/ExtensionsNetworkTestRunner.js
@@ -0,0 +1,28 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +function extension_getRequestByUrl(urls, callback) { + function onHAR(response) { + var entries = response.entries; + + for (var i = 0; i < entries.length; ++i) { + for (var url = 0; url < urls.length; ++url) { + if (urls[url].test(entries[i].request.url)) { + callback(entries[i]); + return; + } + } + } + + output('no item found'); + callback(null); + } + + webInspector.network.getHAR(onHAR); +}
diff --git a/third_party/WebKit/Source/devtools/front_end/extensions_test_runner/ExtensionsTestRunner.js b/third_party/WebKit/Source/devtools/front_end/extensions_test_runner/ExtensionsTestRunner.js new file mode 100644 index 0000000..21cb4d88 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/extensions_test_runner/ExtensionsTestRunner.js
@@ -0,0 +1,75 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +var extensionsHost = 'devtools-extensions.oopif.test'; +var extensionsOrigin = `http://${extensionsHost}:8000`; +Extensions.extensionServer._registerHandler('evaluateForTestInFrontEnd', onEvaluate); + +Extensions.extensionServer._extensionAPITestHook = function(extensionServerClient, coreAPI) { + window.webInspector = coreAPI; + window._extensionServerForTests = extensionServerClient; + coreAPI.panels.themeName = 'themeNameForTest'; +}; + +ExtensionsTestRunner._replyToExtension = function(requestId, port) { + Extensions.extensionServer._dispatchCallback(requestId, port); +}; + +function onEvaluate(message, port) { + try { + eval(message.expression); + } catch (e) { + TestRunner.addResult('Exception while running: ' + message.expression + '\n' + (e.stack || e)); + TestRunner.completeTest(); + } +} + +ExtensionsTestRunner.runExtensionTests = async function() { + var result = await TestRunner.RuntimeAgent.evaluate('location.href', 'console', false); + + if (!result) + return; + + var pageURL = result.value; + var extensionURL = ((/^https?:/.test(pageURL) ? pageURL.replace(/^(https?:\/\/[^\/]*\/).*$/, '$1') : + pageURL.replace(/\/inspector\/extensions\/[^\/]*$/, '/http/tests'))) + + 'inspector/resources/extension-main.html'; + extensionURL = extensionURL.replace('127.0.0.1', extensionsHost); + + InspectorFrontendAPI.addExtensions( + [{startPage: extensionURL, name: 'test extension', exposeWebInspectorNamespace: true}]); + + Extensions.extensionServer.initializeExtensions(); +}; + +(async function() { + await TestRunner.evaluateInPagePromise(` + function extensionFunctions() { + var functions = ''; + + for (symbol in window) { + if (/^extension_/.exec(symbol) && typeof window[symbol] === 'function') + functions += window[symbol].toString(); + } + + return functions; + } + + var extensionsOrigin = 'http://devtools-extensions.oopif.test:8000'; + + function extension_showPanel(panelId, callback) { + evaluateOnFrontend('InspectorTest.showPanel(unescape(\'' + escape(panelId) + '\')).then(function() { reply(); });', callback); + } + + var test = function() { + Common.moduleSetting('shortcutPanelSwitch').set(true); + InspectorTest.runExtensionTests(); + }; + `); +})();
diff --git a/third_party/WebKit/Source/devtools/front_end/extensions_test_runner/module.json b/third_party/WebKit/Source/devtools/front_end/extensions_test_runner/module.json new file mode 100644 index 0000000..82e956c --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/extensions_test_runner/module.json
@@ -0,0 +1,15 @@ +{ + "dependencies": [ + "test_runner", + "integration_test_runner", + "extensions" + ], + "scripts": [ + "ExtensionsNetworkTestRunner.js", + "ExtensionsTestRunner.js" + ], + "skip_compilation": [ + "ExtensionsNetworkTestRunner.js", + "ExtensionsTestRunner.js" + ] +}
diff --git a/third_party/WebKit/Source/devtools/front_end/integration_test_runner.json b/third_party/WebKit/Source/devtools/front_end/integration_test_runner.json index c327aab4..0242b890 100644 --- a/third_party/WebKit/Source/devtools/front_end/integration_test_runner.json +++ b/third_party/WebKit/Source/devtools/front_end/integration_test_runner.json
@@ -1,5 +1,18 @@ { "modules" : [ + { "name": "application_test_runner" }, + { "name": "audits_test_runner" }, + { "name": "bindings_test_runner" }, + { "name": "extensions_test_runner" }, + { "name": "layers_test_runner" }, + { "name": "network_test_runner" }, + { "name": "security_test_runner" }, + { "name": "performance_test_runner" }, + { "name": "coverage_test_runner" }, + { "name": "device_mode_test_runner" }, + { "name": "accessibility_test_runner" }, + { "name": "profiler_test_runner" }, + { "name": "sass_test_runner" }, { "name": "test_runner", "type": "autostart" }, { "name": "integration_test_runner", "type": "autostart" }, { "name": "console_test_runner" }, @@ -8,6 +21,11 @@ { "name": "data_grid_test_runner" }, + + { "name": "heap_snapshot_worker" }, + + + { "name": "platform", "type": "autostart" }, { "name": "dom_extension", "type": "autostart" }, { "name": "main", "type": "autostart" },
diff --git a/third_party/WebKit/Source/devtools/front_end/integration_test_runner/IntegrationTestRunner.js b/third_party/WebKit/Source/devtools/front_end/integration_test_runner/IntegrationTestRunner.js index 8c7901b..5da2f43 100644 --- a/third_party/WebKit/Source/devtools/front_end/integration_test_runner/IntegrationTestRunner.js +++ b/third_party/WebKit/Source/devtools/front_end/integration_test_runner/IntegrationTestRunner.js
@@ -21,6 +21,7 @@ TestRunner.HeapProfilerAgent = target.heapProfilerAgent(); TestRunner.InspectorAgent = target.inspectorAgent(); TestRunner.NetworkAgent = target.networkAgent(); + TestRunner.OverlayAgent = target.overlayAgent(); TestRunner.PageAgent = target.pageAgent(); TestRunner.ProfilerAgent = target.profilerAgent(); TestRunner.RuntimeAgent = target.runtimeAgent(); @@ -35,6 +36,7 @@ TestRunner.domDebuggerModel = target.model(SDK.DOMDebuggerModel); TestRunner.cssModel = target.model(SDK.CSSModel); TestRunner.cpuProfilerModel = target.model(SDK.CPUProfilerModel); + TestRunner.overlayModel = target.model(SDK.OverlayModel); TestRunner.serviceWorkerManager = target.model(SDK.ServiceWorkerManager); TestRunner.tracingManager = target.model(SDK.TracingManager); TestRunner.mainTarget = target; @@ -732,6 +734,41 @@ return 'frame'; }; +/** + * @param {string} urlSuffix + * @param {!Workspace.projectTypes=} projectType + * @return {!Promise} + */ +TestRunner.waitForUISourceCode = function(urlSuffix, projectType) { + /** + * @param {!Workspace.UISourceCode} uiSourceCode + * @return {boolean} + */ + function matches(uiSourceCode) { + if (projectType && uiSourceCode.project().type() !== projectType) + return false; + if (!projectType && uiSourceCode.project().type() === Workspace.projectTypes.Service) + return false; + if (urlSuffix && !uiSourceCode.url().endsWith(urlSuffix)) + return false; + return true; + } + + for (var uiSourceCode of Workspace.workspace.uiSourceCodes()) { + if (urlSuffix && matches(uiSourceCode)) + return Promise.resolve(uiSourceCode); + } + + return TestRunner.waitForEvent(Workspace.Workspace.Events.UISourceCodeAdded, Workspace.workspace, matches); +}; + +/** + * @param {!Function} callback + */ +TestRunner.waitForUISourceCodeRemoved = function(callback) { + Workspace.workspace.once(Workspace.Workspace.Events.UISourceCodeRemoved).then(callback); +}; + /** @type {boolean} */ IntegrationTestRunner._startedTest = false;
diff --git a/third_party/WebKit/Source/devtools/front_end/integration_test_runner/PageMockTestRunner.js b/third_party/WebKit/Source/devtools/front_end/integration_test_runner/PageMockTestRunner.js new file mode 100644 index 0000000..fe125dfb --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/integration_test_runner/PageMockTestRunner.js
@@ -0,0 +1,244 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +var id = 0; + +function nextId(prefix) { + return (prefix || '') + ++id; +} + +TestRunner.connectToPage = function(targetName, pageMock, makeMainTarget) { + var mockTarget = SDK.targetManager.createTarget( + nextId('mock-target-'), targetName, pageMock.capabilities(), params => pageMock.createConnection(params)); + + if (makeMainTarget) { + SDK.targetManager._targets = SDK.targetManager._targets.filter(target => target !== mockTarget); + SDK.targetManager._targets.unshift(mockTarget); + } + + return mockTarget; +}; + +TestRunner.PageMock = class { + constructor(url) { + this._url = url; + this._capabilities = SDK.Target.Capability.DOM | SDK.Target.Capability.JS | SDK.Target.Capability.Browser; + this._enabledDomains = new Set(); + + this._mainFrame = + {id: nextId(), loaderId: nextId(), mimeType: 'text/html', securityOrigin: this._url, url: this._url}; + + this._executionContexts = []; + this._executionContexts.push(this._createExecutionContext(this._mainFrame, false)); + this._scripts = []; + this._scriptContents = new Map(); + + this._dispatchMap = { + 'Debugger.enable': this._debuggerEnable, + 'Debugger.getScriptSource': this._debuggerGetScriptSource, + 'Debugger.setBlackboxPatterns': (id, params) => this._sendResponse(id, {}), + 'Runtime.enable': this._runtimeEnable, + 'Page.enable': this._pageEnable, + 'Page.getResourceTree': this._pageGetResourceTree + }; + } + + capabilities() { + return this._capabilities; + } + + disableDOMCapability() { + this._capabilities = this._capabilities & ~SDK.Target.Capability.DOM; + } + + createConnection(params) { + this._enabledDomains.clear(); + this._connection = new MockPageConnection(this, params); + return this._connection; + } + + evalScript(url, content, isContentScript) { + var id = nextId(); + content += '\n//# sourceURL=' + url; + this._scriptContents.set(id, content); + var context = this._executionContexts.find(context => context.auxData.isDefault !== isContentScript); + + if (!context) { + context = this._createExecutionContext(this._mainFrame, isContentScript); + + this._fireEvent('Runtime.executionContextCreated', {context: context}); + } + + var text = new TextUtils.Text(content); + + var script = { + scriptId: id, + url: url, + startLine: 0, + startColumn: 0, + endLine: text.lineCount(), + endColumn: text.lineAt(text.lineCount()).length - 1, + executionContextId: context.id, + hash: String.hashCode(content), + executionContextAuxData: context.auxData, + sourceMapURL: '', + hasSourceURL: true, + isLiveEdit: false, + isModule: false, + length: content.length + }; + + this._scripts.push(script); + this._fireEvent('Debugger.scriptParsed', script); + } + + reload() { + this._fireEvent('Page.frameStartedLoading', {frameId: this._mainFrame.id}); + + for (var context of this._executionContexts) + this._fireEvent('Runtime.executionContextDestroyed', {executionContextId: context.id}); + + + this._scripts = []; + this._scriptContents.clear(); + this._executionContexts = []; + this._fireEvent('Runtime.executionContextsCleared', {}); + this._executionContexts.push(this._createExecutionContext(this._mainFrame, false)); + + for (var context of this._executionContexts) + this._fireEvent('Runtime.executionContextCreated', {context: context}); + + + this._fireEvent('Page.frameNavigated', {frame: this._mainFrame}); + + this._fireEvent('Page.loadEventFired', {timestamp: Date.now() / 1000}); + + this._fireEvent('Page.frameStoppedLoading', {frameId: this._mainFrame.id}); + + this._fireEvent('Page.domContentEventFired', {timestamp: Date.now() / 1000}); + } + + close() { + if (this._connection) { + this._connection.disconnect(); + this._connection = null; + } + } + + _createExecutionContext(frame, isContentScript) { + return { + id: nextId(), + + auxData: {isDefault: !isContentScript, frameId: frame.id}, + + origin: frame.securityOrigin, + name: '' + }; + } + + _debuggerEnable(id, params) { + this._enabledDomains.add('Debugger'); + this._sendResponse(id, {}); + + for (var script of this._scripts) + this._fireEvent('Debugger.scriptParsed', script); + } + + _debuggerGetScriptSource(id, params) { + if (!this._scriptContents.has(params.scriptId)) { + this._sendResponse(id, undefined, {message: 'Can\'t get script content for id ' + params.scriptId, code: 1}); + + return; + } + + var result = {scriptSource: this._scriptContents.get(params.scriptId)}; + + this._sendResponse(id, result); + } + + _runtimeEnable(id, params) { + this._enabledDomains.add('Runtime'); + this._sendResponse(id, {}); + + for (var context of this._executionContexts) + this._fireEvent('Runtime.executionContextCreated', {context: context}); + } + + _pageEnable(id, params) { + this._enabledDomains.add('Page'); + this._sendResponse(id, {}); + } + + _pageGetResourceTree(id, params) { + var result = {frameTree: {frame: this._mainFrame, resources: []}}; + + this._sendResponse(id, result); + } + + _isSupportedDomain(methodName) { + var domain = methodName.split('.')[0]; + + if (domain === 'Page') + return !!(this._capabilities & SDK.Target.Capability.DOM); + + return true; + } + + _dispatch(id, methodName, params, message) { + var handler = (this._isSupportedDomain(methodName) ? this._dispatchMap[methodName] : null); + + if (handler) + return handler.call(this, id, params); + + this._sendResponse( + id, undefined, + {message: 'Can\'t handle command ' + methodName, code: Protocol.InspectorBackend.DevToolsStubErrorCode}); + } + + _sendResponse(id, result, error) { + var message = {id: id, result: result, error: error}; + + this._connection.sendMessageToDevTools(message); + } + + _fireEvent(methodName, params) { + var domain = methodName.split('.')[0]; + + if (!this._enabledDomains.has(domain)) + return; + + var message = {method: methodName, params: params}; + + this._connection.sendMessageToDevTools(message); + } +}; + +var MockPageConnection = class { + constructor(page, params) { + this._page = page; + this._onMessage = params.onMessage; + this._onDisconnect = params.onDisconnect; + } + + sendMessageToDevTools(message) { + setTimeout(() => this._onMessage.call(null, JSON.stringify(message)), 0); + } + + sendMessage(message) { + var json = JSON.parse(message); + this._page._dispatch(json.id, json.method, json.params, message); + } + + disconnect() { + this._onDisconnect.call(null, 'force disconnect'); + this._onDisconnect = null; + this._onMessage = null; + return Promise.resolve(); + } +};
diff --git a/third_party/WebKit/Source/devtools/front_end/integration_test_runner/SyntaxHighlightTestRunner.js b/third_party/WebKit/Source/devtools/front_end/integration_test_runner/SyntaxHighlightTestRunner.js new file mode 100644 index 0000000..4f44a11 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/integration_test_runner/SyntaxHighlightTestRunner.js
@@ -0,0 +1,28 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +TestRunner.dumpSyntaxHighlight = function(str, mimeType) { + var node = document.createElement('span'); + node.textContent = str; + var javascriptSyntaxHighlighter = new UI.SyntaxHighlighter(mimeType); + return javascriptSyntaxHighlighter.syntaxHighlightNode(node).then(dumpSyntax); + + function dumpSyntax() { + var node_parts = []; + + for (var i = 0; i < node.childNodes.length; i++) { + if (node.childNodes[i].getAttribute) + node_parts.push(node.childNodes[i].getAttribute('class')); + else + node_parts.push('*'); + } + + TestRunner.addResult(str + ': ' + node_parts.join(', ')); + } +};
diff --git a/third_party/WebKit/Source/devtools/front_end/integration_test_runner/module.json b/third_party/WebKit/Source/devtools/front_end/integration_test_runner/module.json index 511866b..6d8d374 100644 --- a/third_party/WebKit/Source/devtools/front_end/integration_test_runner/module.json +++ b/third_party/WebKit/Source/devtools/front_end/integration_test_runner/module.json
@@ -2,9 +2,16 @@ "dependencies": [ "test_runner", "sdk", - "network_log" + "network_log", + "workspace" ], "scripts": [ - "IntegrationTestRunner.js" + "IntegrationTestRunner.js", + "PageMockTestRunner.js", + "SyntaxHighlightTestRunner.js" + ], + "skip_compilation": [ + "PageMockTestRunner.js", + "SyntaxHighlightTestRunner.js" ] }
diff --git a/third_party/WebKit/Source/devtools/front_end/layers_test_runner/LayersTestRunner.js b/third_party/WebKit/Source/devtools/front_end/layers_test_runner/LayersTestRunner.js new file mode 100644 index 0000000..64dda2c6 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/layers_test_runner/LayersTestRunner.js
@@ -0,0 +1,157 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +LayersTestRunner.layerTreeModel = function() { + if (!LayersTestRunner._layerTreeModel) + LayersTestRunner._layerTreeModel = TestRunner.mainTarget.model(Layers.LayerTreeModel); + + return LayersTestRunner._layerTreeModel; +}; + +LayersTestRunner.labelForLayer = function(layer) { + var node = layer.nodeForSelfOrAncestor(); + var label = (node ? Components.DOMPresentationUtils.fullQualifiedSelector(node, false) : '<invalid node id>'); + var height = layer.height(); + var width = layer.width(); + + if (height <= 200 && width <= 200) + label += ' ' + height + 'x' + width; + + if (typeof layer.__extraData !== 'undefined') + label += ' (' + layer.__extraData + ')'; + + return label; +}; + +LayersTestRunner.dumpLayerTree = function(prefix, root) { + if (!prefix) + prefix = ''; + + if (!root) { + root = LayersTestRunner.layerTreeModel().layerTree().contentRoot(); + + if (!root) { + TestRunner.addResult('No layer root, perhaps not in the composited mode! '); + TestRunner.completeTest(); + return; + } + } + + TestRunner.addResult(prefix + LayersTestRunner.labelForLayer(root)); + root.children().forEach(LayersTestRunner.dumpLayerTree.bind(LayersTestRunner, prefix + ' ')); +}; + +LayersTestRunner.dumpLayers3DView = function(prefix, root) { + if (!prefix) + prefix = ''; + + if (!root) + root = UI.panels.layers._layers3DView._rotatingContainerElement; + + if (root.__layer) + TestRunner.addResult(prefix + LayersTestRunner.labelForLayer(root.__layer)); + + for (var element = root.firstElementChild; element; element = element.nextSibling) + LayersTestRunner.dumpLayers3DView(prefix + ' ', element); +}; + +LayersTestRunner.evaluateAndRunWhenTreeChanges = function(expression, callback) { + function eventHandler() { + LayersTestRunner.layerTreeModel().removeEventListener(Layers.LayerTreeModel.Events.LayerTreeChanged, eventHandler); + callback(); + } + + TestRunner.evaluateInPage(expression, function() { + LayersTestRunner.layerTreeModel().addEventListener(Layers.LayerTreeModel.Events.LayerTreeChanged, eventHandler); + }); +}; + +LayersTestRunner.findLayerByNodeIdAttribute = function(nodeIdAttribute) { + var result; + + function testLayer(layer) { + var node = layer.node(); + + if (!node) + return false; + + if (!node || node.getAttribute('id') !== nodeIdAttribute) + return false; + + result = layer; + return true; + } + + LayersTestRunner.layerTreeModel().layerTree().forEachLayer(testLayer); + + if (!result) + TestRunner.addResult('ERROR: No layer for ' + nodeIdAttribute); + + return result; +}; + +LayersTestRunner.requestLayers = function(callback) { + LayersTestRunner.layerTreeModel().addEventListener(Layers.LayerTreeModel.Events.LayerTreeChanged, onLayerTreeChanged); + LayersTestRunner.layerTreeModel().enable(); + + function onLayerTreeChanged() { + LayersTestRunner.layerTreeModel().removeEventListener( + Layers.LayerTreeModel.Events.LayerTreeChanged, onLayerTreeChanged); + callback(); + } +}; + +LayersTestRunner.dumpModelScrollRects = function() { + function dumpScrollRectsForLayer(layer) { + if (layer._scrollRects.length > 0) + TestRunner.addObject(layer._scrollRects); + } + + TestRunner.addResult('Model elements dump'); + LayersTestRunner.layerTreeModel().layerTree().forEachLayer(dumpScrollRectsForLayer.bind(this)); +}; + +LayersTestRunner.dumpModelStickyPositionConstraint = function() { + function dumpModelStickyPositionConstraintForLayer(layer) { + var stickyFormatters = { + '_nearestLayerShiftingContainingBlock': 'formatAsTypeNameOrNull', + '_nearestLayerShiftingStickyBox': 'formatAsTypeNameOrNull' + }; + + if (layer._stickyPositionConstraint) + TestRunner.addObject(layer._stickyPositionConstraint, stickyFormatters); + } + + TestRunner.addResult('Model elements dump'); + LayersTestRunner.layerTreeModel().layerTree().forEachLayer(dumpModelStickyPositionConstraintForLayer.bind(this)); +}; + +LayersTestRunner.dispatchMouseEvent = function(eventType, button, element, offsetX, offsetY) { + var totalOffset = element.totalOffset(); + + var eventArguments = { + bubbles: true, + cancelable: true, + view: window, + screenX: totalOffset.left - element.scrollLeft + offsetX, + screenY: totalOffset.top - element.scrollTop + offsetY, + clientX: totalOffset.left + offsetX, + clientY: totalOffset.top + offsetY, + button: button + }; + + if (eventType === 'mouseout') { + eventArguments.screenX = 0; + eventArguments.screenY = 0; + eventArguments.clientX = 0; + eventArguments.clientY = 0; + } + + element.dispatchEvent(new MouseEvent(eventType, eventArguments)); +};
diff --git a/third_party/WebKit/Source/devtools/front_end/layers_test_runner/module.json b/third_party/WebKit/Source/devtools/front_end/layers_test_runner/module.json new file mode 100644 index 0000000..a76d127 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/layers_test_runner/module.json
@@ -0,0 +1,14 @@ +{ + "dependencies": [ + "test_runner", + "integration_test_runner", + "layers", + "components" + ], + "scripts": [ + "LayersTestRunner.js" + ], + "skip_compilation": [ + "LayersTestRunner.js" + ] +}
diff --git a/third_party/WebKit/Source/devtools/front_end/network_test_runner/NetworkTestRunner.js b/third_party/WebKit/Source/devtools/front_end/network_test_runner/NetworkTestRunner.js new file mode 100644 index 0000000..eaf0454 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/network_test_runner/NetworkTestRunner.js
@@ -0,0 +1,225 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +NetworkTestRunner.waitForRequestResponse = function(request) { + if (request.responseReceivedTime !== -1) + return Promise.resolve(request); + + return TestRunner.waitForEvent( + SDK.NetworkManager.Events.RequestUpdated, TestRunner.networkManager, + updateRequest => updateRequest === request && request.responseReceivedTime !== -1); +}; + +NetworkTestRunner.waitForNetworkLogViewNodeForRequest = function(request) { + var networkLogView = UI.panels.network._networkLogView; + var node = networkLogView.nodeForRequest(request); + + if (node) + return Promise.resolve(node); + + console.assert(networkLogView._staleRequests.has(request)); + + return TestRunner.addSnifferPromise(networkLogView, '_didRefreshForTest').then(() => { + var node = networkLogView.nodeForRequest(request); + console.assert(node); + return node; + }); +}; + +NetworkTestRunner.waitForWebsocketFrameReceived = function(wsRequest, message) { + for (var frame of wsRequest.frames()) { + if (checkFrame(frame)) + return Promise.resolve(frame); + } + + return TestRunner.waitForEvent(SDK.NetworkRequest.Events.WebsocketFrameAdded, wsRequest, checkFrame); + + function checkFrame(frame) { + return frame.type === SDK.NetworkRequest.WebSocketFrameType.Receive && frame.text === message; + } +}; + +NetworkTestRunner.recordNetwork = function() { + UI.panels.network._networkLogView.setRecording(true); +}; + +NetworkTestRunner.networkRequests = function() { + return Array.from(NetworkLog.networkLog.requests()); +}; + +NetworkTestRunner.dumpNetworkRequests = function() { + var requests = NetworkTestRunner.networkRequests(); + + requests.sort(function(a, b) { + return a.url().localeCompare(b.url()); + }); + + TestRunner.addResult('resources count = ' + requests.length); + + for (i = 0; i < requests.length; i++) + TestRunner.addResult(requests[i].url()); +}; + +NetworkTestRunner.findRequestsByURLPattern = function(urlPattern) { + return NetworkTestRunner.networkRequests().filter(function(value) { + return urlPattern.test(value.url()); + }); +}; + +NetworkTestRunner.makeSimpleXHR = function(method, url, async, callback) { + NetworkTestRunner.makeXHR(method, url, async, undefined, undefined, [], false, undefined, undefined, callback); +}; + +NetworkTestRunner.makeSimpleXHRWithPayload = function(method, url, async, payload, callback) { + NetworkTestRunner.makeXHR(method, url, async, undefined, undefined, [], false, payload, undefined, callback); +}; + +NetworkTestRunner.makeXHR = function( + method, url, async, user, password, headers, withCredentials, payload, type, callback) { + var args = {}; + args.method = method; + args.url = url; + args.async = async; + args.user = user; + args.password = password; + args.headers = headers; + args.withCredentials = withCredentials; + args.payload = payload; + args.type = type; + var jsonArgs = JSON.stringify(args).replace(/\"/g, '\\"'); + + function innerCallback(msg) { + if (msg.messageText.indexOf('XHR loaded') !== -1) { + if (callback) + callback(); + } else { + ConsoleTestRunner.addConsoleSniffer(innerCallback); + } + } + + ConsoleTestRunner.addConsoleSniffer(innerCallback); + TestRunner.evaluateInPage('makeXHRForJSONArguments("' + jsonArgs + '")'); +}; + +NetworkTestRunner.makeFetch = function(url, requestInitializer, callback) { + TestRunner.callFunctionInPageAsync('makeFetch', [url, requestInitializer]).then(callback); +}; + +NetworkTestRunner.makeFetchInWorker = function(url, requestInitializer, callback) { + TestRunner.callFunctionInPageAsync('makeFetchInWorker', [url, requestInitializer]).then(callback); +}; + +NetworkTestRunner.clearNetworkCache = function() { + var networkAgent = TestRunner.NetworkAgent; + var promise = networkAgent.setCacheDisabled(true); + return promise.then(() => networkAgent.setCacheDisabled(false)); +}; + +NetworkTestRunner.HARPropertyFormatters = { + bodySize: 'formatAsTypeName', + compression: 'formatAsTypeName', + connection: 'formatAsTypeName', + headers: 'formatAsTypeName', + headersSize: 'formatAsTypeName', + id: 'formatAsTypeName', + onContentLoad: 'formatAsTypeName', + onLoad: 'formatAsTypeName', + receive: 'formatAsTypeName', + startedDateTime: 'formatAsRecentTime', + time: 'formatAsTypeName', + timings: 'formatAsTypeName', + version: 'formatAsTypeName', + wait: 'formatAsTypeName', + _transferSize: 'formatAsTypeName', + _error: 'skip' +}; + +NetworkTestRunner.HARPropertyFormattersWithSize = JSON.parse(JSON.stringify(NetworkTestRunner.HARPropertyFormatters)); +NetworkTestRunner.HARPropertyFormattersWithSize.size = 'formatAsTypeName'; + +(async function() { + await TestRunner.evaluateInPagePromise(` + var lastXHRIndex = 0; + + function xhrLoadedCallback() { + console.log('XHR loaded: ' + ++lastXHRIndex); + } + + function makeSimpleXHR(method, url, async, callback) { + makeSimpleXHRWithPayload(method, url, async, null, callback); + } + + function makeSimpleXHRWithPayload(method, url, async, payload, callback) { + makeXHR(method, url, async, undefined, undefined, [], false, payload, callback); + } + + function makeXHR(method, url, async, user, password, headers, withCredentials, payload, type, callback) { + var xhr = new XMLHttpRequest(); + + if (type == undefined) + xhr.responseType = ''; + else + xhr.responseType = type; + + xhr.onreadystatechange = function() { + if (xhr.readyState === XMLHttpRequest.DONE) { + if (typeof callback === 'function') + callback(); + } + }; + + xhr.open(method, url, async, user, password); + xhr.withCredentials = withCredentials; + + for (var i = 0; i < headers.length; ++i) + xhr.setRequestHeader(headers[i][0], headers[i][1]); + + xhr.send(payload); + } + + function makeXHRForJSONArguments(jsonArgs) { + var args = JSON.parse(jsonArgs); + + makeXHR( + args.method, + args.url, + args.async, + args.user, + args.password, + args.headers || [], + args.withCredentials, + args.payload, + args.type, + xhrLoadedCallback + ); + } + + function makeFetch(url, requestInitializer) { + return fetch(url, requestInitializer).then(res => { + res.text(); + return res; + }).catch(e => e); + } + + function makeFetchInWorker(url, requestInitializer) { + return new Promise(resolve => { + var worker = new Worker('/inspector/network/resources/fetch-worker.js'); + + worker.onmessage = event => { + resolve(event.data); + }; + + worker.postMessage({ + url: url, + init: requestInitializer + }); + }); + } + `); +})();
diff --git a/third_party/WebKit/Source/devtools/front_end/network_test_runner/ProductRegistryTestRunner.js b/third_party/WebKit/Source/devtools/front_end/network_test_runner/ProductRegistryTestRunner.js new file mode 100644 index 0000000..9f6fb50 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/network_test_runner/ProductRegistryTestRunner.js
@@ -0,0 +1,39 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +NetworkTestRunner.resetProductRegistry = function() { + TestRunner.addResult('Cleared ProductRegistryImpl'); + ProductRegistryImpl._productsByDomainHash.clear(); +}; + +NetworkTestRunner.addProductRegistryEntry = function(domainPattern, productName, type) { + TestRunner.addResult('Adding entry: ' + domainPattern); + var wildCardPosition = domainPattern.indexOf('*'); + var prefix = ''; + + if (wildCardPosition === -1) { + } else if (wildCardPosition === 0) { + prefix = '*'; + console.assert(domainPattern.substr(1, 1) === '.', 'Domain pattern wildcard must be followed by \'.\''); + domainPattern = domainPattern.substr(2); + } else { + prefix = domainPattern.substr(0, wildCardPosition); + console.assert( + domainPattern.substr(wildCardPosition + 1, 1) === '.', 'Domain pattern wildcard must be followed by \'.\''); + domainPattern = domainPattern.substr(wildCardPosition + 2); + } + + console.assert(domainPattern.indexOf('*') === -1, 'Domain pattern may only have 1 wildcard.'); + var prefixes = {}; + + prefixes[prefix] = {product: 0, type: type}; + + ProductRegistryImpl.register( + [productName], [{hash: ProductRegistryImpl._hashForDomain(domainPattern), prefixes: prefixes}]); +};
diff --git a/third_party/WebKit/Source/devtools/front_end/network_test_runner/module.json b/third_party/WebKit/Source/devtools/front_end/network_test_runner/module.json new file mode 100644 index 0000000..82029ea --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/network_test_runner/module.json
@@ -0,0 +1,16 @@ +{ + "dependencies": [ + "test_runner", + "integration_test_runner", + "product_registry_impl", + "console_test_runner" + ], + "scripts": [ + "NetworkTestRunner.js", + "ProductRegistryTestRunner.js" + ], + "skip_compilation": [ + "NetworkTestRunner.js", + "ProductRegistryTestRunner.js" + ] +}
diff --git a/third_party/WebKit/Source/devtools/front_end/performance_test_runner/TimelineDataTestRunner.js b/third_party/WebKit/Source/devtools/front_end/performance_test_runner/TimelineDataTestRunner.js new file mode 100644 index 0000000..6f53685 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/performance_test_runner/TimelineDataTestRunner.js
@@ -0,0 +1,5363 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +PerformanceTestRunner.timelineData = function() { + return JSON.stringify([ + { + 'args': {'number': 32}, + + 'cat': '__metadata', + 'name': 'num_cpus', + 'ph': 'M', + 'pid': 3840, + 'tid': 0, + 'ts': 0 + }, + { + 'args': {'sort_index': -5}, + + 'cat': '__metadata', + 'name': 'process_sort_index', + 'ph': 'M', + 'pid': 3840, + 'tid': 12, + 'ts': 0 + }, + { + 'args': {'name': 'Renderer'}, + + 'cat': '__metadata', + 'name': 'process_name', + 'ph': 'M', + 'pid': 3840, + 'tid': 12, + 'ts': 0 + }, + { + 'args': {'sort_index': -1}, + + 'cat': '__metadata', + 'name': 'thread_sort_index', + 'ph': 'M', + 'pid': 3840, + 'tid': 11, + 'ts': 0 + }, + { + 'args': {'sessionId': '9.4'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'TracingStartedInPage', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673092068, + 'tts': 170409 + }, + { + 'args': {'layerTreeId': 1, 'sessionId': '9.4'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'SetLayerTreeId', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673092082, + 'tts': 170421 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673092095, + 'tts': 170434 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673107791, + 'tts': 170482 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673107799, + 'tts': 170490 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 438}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 65, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 64, + 'tid': 9, + 'ts': 1122673107821, + 'tts': 170511 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 27, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 26, + 'tid': 9, + 'ts': 1122673107849, + 'tts': 170539 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 439}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673107869, + 'tts': 170559 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2688936, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673107883, + 'tts': 170573 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673107891, + 'tts': 170581 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673107921, + 'tts': 170612 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673107934, + 'tts': 170624 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673107941, + 'tts': 170631 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673126470, + 'tts': 170708 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673126480, + 'tts': 170717 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 439}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 108, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 107, + 'tid': 9, + 'ts': 1122673126522, + 'tts': 170759 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 47, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 46, + 'tid': 9, + 'ts': 1122673126569, + 'tts': 170806 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 440}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673126606, + 'tts': 170843 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2688952, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673126627, + 'tts': 170864 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673126637, + 'tts': 170874 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673126683, + 'tts': 170920 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673126699, + 'tts': 170936 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673126708, + 'tts': 170944 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673141177, + 'tts': 171002 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673141186, + 'tts': 171010 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 440}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 110, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 109, + 'tid': 9, + 'ts': 1122673141212, + 'tts': 171036 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 46, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 43, + 'tid': 9, + 'ts': 1122673141259, + 'tts': 171084 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 441}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673141293, + 'tts': 171117 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2688968, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673141318, + 'tts': 171142 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673141329, + 'tts': 171154 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673141379, + 'tts': 171204 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673141406, + 'tts': 171231 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673141421, + 'tts': 171246 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673162929, + 'tts': 171304 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673162938, + 'tts': 171313 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 441}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 98, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 97, + 'tid': 9, + 'ts': 1122673162975, + 'tts': 171350 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 41, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 39, + 'tid': 9, + 'ts': 1122673163020, + 'tts': 171395 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 442}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673163051, + 'tts': 171426 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2688984, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673163070, + 'tts': 171445 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673163081, + 'tts': 171455 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673163119, + 'tts': 171493 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673163133, + 'tts': 171508 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673163141, + 'tts': 171516 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673179592, + 'tts': 171569 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673179600, + 'tts': 171576 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 442}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 77, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 76, + 'tid': 9, + 'ts': 1122673179625, + 'tts': 171601 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 31, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 31, + 'tid': 9, + 'ts': 1122673179660, + 'tts': 171635 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 443}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673179683, + 'tts': 171659 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689000, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673179699, + 'tts': 171675 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673179707, + 'tts': 171682 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673179736, + 'tts': 171711 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673179751, + 'tts': 171727 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673179759, + 'tts': 171735 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673196258, + 'tts': 171788 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673196265, + 'tts': 171794 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 443}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 73, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 72, + 'tid': 9, + 'ts': 1122673196291, + 'tts': 171820 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 30, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 29, + 'tid': 9, + 'ts': 1122673196323, + 'tts': 171852 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 444}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673196346, + 'tts': 171875 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689016, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673196361, + 'tts': 171890 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673196370, + 'tts': 171899 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673196402, + 'tts': 171931 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673196417, + 'tts': 171946 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673196425, + 'tts': 171954 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673213043, + 'tts': 172016 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122673107747, + 'tts': 77989 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122673107777, + 'tts': 78018 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122673126358, + 'tts': 78708 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122673126413, + 'tts': 78760 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122673141111, + 'tts': 78880 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122673141133, + 'tts': 78902 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122673162867, + 'tts': 79126 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122673162886, + 'tts': 79145 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122673179534, + 'tts': 79253 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122673179551, + 'tts': 79269 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673313423, + 'tts': 174171 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673313452, + 'tts': 174200 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673313467, + 'tts': 174215 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673329958, + 'tts': 174302 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673329971, + 'tts': 174314 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 451}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 98, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 96, + 'tid': 9, + 'ts': 1122673330000, + 'tts': 174343 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 44, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 41, + 'tid': 9, + 'ts': 1122673330035, + 'tts': 174379 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 452}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673330066, + 'tts': 174409 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689144, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673330092, + 'tts': 174435 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673330106, + 'tts': 174450 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673330151, + 'tts': 174495 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673330180, + 'tts': 174523 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673330194, + 'tts': 174538 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673346680, + 'tts': 174624 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673346692, + 'tts': 174635 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 452}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 98, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 96, + 'tid': 9, + 'ts': 1122673346721, + 'tts': 174664 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 45, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 43, + 'tid': 9, + 'ts': 1122673346756, + 'tts': 174699 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 453}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673346787, + 'tts': 174730 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689160, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673346813, + 'tts': 174756 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673346827, + 'tts': 174770 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673346871, + 'tts': 174814 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673346900, + 'tts': 174843 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673346914, + 'tts': 174857 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673363348, + 'tts': 174943 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673363361, + 'tts': 174954 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 453}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 98, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 95, + 'tid': 9, + 'ts': 1122673363390, + 'tts': 174984 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 45, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 42, + 'tid': 9, + 'ts': 1122673363425, + 'tts': 175019 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 454}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673363456, + 'tts': 175050 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689176, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673363482, + 'tts': 175075 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673363496, + 'tts': 175090 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673363540, + 'tts': 175134 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673363569, + 'tts': 175163 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673363584, + 'tts': 175177 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673380043, + 'tts': 175286 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673380057, + 'tts': 175299 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 454}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 99, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 97, + 'tid': 9, + 'ts': 1122673380086, + 'tts': 175328 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 45, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 42, + 'tid': 9, + 'ts': 1122673380122, + 'tts': 175364 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 455}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673380153, + 'tts': 175396 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689192, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673380179, + 'tts': 175421 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673380194, + 'tts': 175436 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673380238, + 'tts': 175480 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673380266, + 'tts': 175508 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673380281, + 'tts': 175523 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673396686, + 'tts': 175611 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673396699, + 'tts': 175622 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 455}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 99, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 96, + 'tid': 9, + 'ts': 1122673396735, + 'tts': 175659 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 44, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 42, + 'tid': 9, + 'ts': 1122673396771, + 'tts': 175694 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 456}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673396802, + 'tts': 175725 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689208, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673396828, + 'tts': 175751 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673396842, + 'tts': 175765 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673396886, + 'tts': 175810 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673396915, + 'tts': 175838 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673396930, + 'tts': 175853 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673413345, + 'tts': 175940 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673413358, + 'tts': 175952 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674113927, + 'tts': 89784 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674113950, + 'tts': 89806 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674130606, + 'tts': 89979 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674130629, + 'tts': 90001 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674147273, + 'tts': 90157 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674147296, + 'tts': 90179 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674163929, + 'tts': 90337 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674163951, + 'tts': 90358 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673747387, + 'tts': 182445 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 476}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 100, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 97, + 'tid': 9, + 'ts': 1122673747439, + 'tts': 182498 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 45, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 42, + 'tid': 9, + 'ts': 1122673747475, + 'tts': 182534 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 477}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673747507, + 'tts': 182565 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689544, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673747532, + 'tts': 182591 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673747547, + 'tts': 182605 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673747592, + 'tts': 182650 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673747621, + 'tts': 182680 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673747636, + 'tts': 182694 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673764047, + 'tts': 182781 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673764060, + 'tts': 182792 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 477}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 99, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 97, + 'tid': 9, + 'ts': 1122673764089, + 'tts': 182821 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 45, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 42, + 'tid': 9, + 'ts': 1122673764125, + 'tts': 182858 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 478}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673764156, + 'tts': 182889 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689560, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673764182, + 'tts': 182914 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673764196, + 'tts': 182929 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673764241, + 'tts': 182973 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673764268, + 'tts': 183001 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673764283, + 'tts': 183015 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673780702, + 'tts': 183103 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673780715, + 'tts': 183114 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 478}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 106, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 104, + 'tid': 9, + 'ts': 1122673780744, + 'tts': 183143 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 44, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 42, + 'tid': 9, + 'ts': 1122673780787, + 'tts': 183186 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 479}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673780818, + 'tts': 183217 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689576, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673780844, + 'tts': 183243 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673780858, + 'tts': 183257 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673780902, + 'tts': 183302 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673780932, + 'tts': 183331 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673780946, + 'tts': 183346 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673797374, + 'tts': 183434 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673797387, + 'tts': 183445 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 479}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 106, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 104, + 'tid': 9, + 'ts': 1122673797416, + 'tts': 183475 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 45, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 42, + 'tid': 9, + 'ts': 1122673797458, + 'tts': 183517 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 480}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673797489, + 'tts': 183548 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689592, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673797516, + 'tts': 183575 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673797530, + 'tts': 183589 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673797575, + 'tts': 183633 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673797604, + 'tts': 183662 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673797618, + 'tts': 183677 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673814044, + 'tts': 183764 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673814056, + 'tts': 183776 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 480}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 98, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 96, + 'tid': 9, + 'ts': 1122673814086, + 'tts': 183805 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 45, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 43, + 'tid': 9, + 'ts': 1122673814121, + 'tts': 183840 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 481}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673814153, + 'tts': 183872 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689608, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673814178, + 'tts': 183897 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673814193, + 'tts': 183912 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673814237, + 'tts': 183956 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673814265, + 'tts': 183985 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673814280, + 'tts': 183999 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673830696, + 'tts': 184086 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673830709, + 'tts': 184097 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 481}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 99, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 97, + 'tid': 9, + 'ts': 1122673830738, + 'tts': 184126 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 45, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 42, + 'tid': 9, + 'ts': 1122673830774, + 'tts': 184163 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 482}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673830806, + 'tts': 184194 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689624, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673830831, + 'tts': 184219 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673830846, + 'tts': 184234 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673830890, + 'tts': 184278 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673830917, + 'tts': 184305 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673830932, + 'tts': 184320 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122673847325, + 'tts': 184405 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122673847337, + 'tts': 184417 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674030729, + 'tts': 188070 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 493}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 98, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 96, + 'tid': 9, + 'ts': 1122674030758, + 'tts': 188099 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 44, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 42, + 'tid': 9, + 'ts': 1122674030794, + 'tts': 188135 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 494}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674030825, + 'tts': 188166 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689816, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674030850, + 'tts': 188191 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674030864, + 'tts': 188205 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674030908, + 'tts': 188249 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674030937, + 'tts': 188278 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674030951, + 'tts': 188292 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674047345, + 'tts': 188381 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674047358, + 'tts': 188393 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 494}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 98, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 96, + 'tid': 9, + 'ts': 1122674047387, + 'tts': 188422 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 45, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 43, + 'tid': 9, + 'ts': 1122674047422, + 'tts': 188457 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 495}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674047453, + 'tts': 188489 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689832, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674047479, + 'tts': 188514 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674047493, + 'tts': 188528 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674047538, + 'tts': 188573 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674047566, + 'tts': 188601 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674047580, + 'tts': 188615 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674064041, + 'tts': 188723 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674064054, + 'tts': 188735 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 495}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 114, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 112, + 'tid': 9, + 'ts': 1122674064084, + 'tts': 188765 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 60, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 57, + 'tid': 9, + 'ts': 1122674064120, + 'tts': 188801 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 496}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674064166, + 'tts': 188847 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689848, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674064192, + 'tts': 188873 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674064207, + 'tts': 188888 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674064252, + 'tts': 188933 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674064279, + 'tts': 188960 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674064293, + 'tts': 188974 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674080701, + 'tts': 189063 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674080714, + 'tts': 189075 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 496}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 112, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 110, + 'tid': 9, + 'ts': 1122674080743, + 'tts': 189104 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 46, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 44, + 'tid': 9, + 'ts': 1122674080791, + 'tts': 189152 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 497}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674080823, + 'tts': 189185 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689864, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674080849, + 'tts': 189210 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674080864, + 'tts': 189225 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674080908, + 'tts': 189269 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674080936, + 'tts': 189297 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674080950, + 'tts': 189312 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674097365, + 'tts': 189401 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674097378, + 'tts': 189412 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 497}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 97, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 95, + 'tid': 9, + 'ts': 1122674097407, + 'tts': 189441 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 43, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 42, + 'tid': 9, + 'ts': 1122674097443, + 'tts': 189477 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 498}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674097473, + 'tts': 189507 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689880, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674097498, + 'tts': 189532 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674097513, + 'tts': 189547 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674097556, + 'tts': 189591 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674097585, + 'tts': 189619 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674097599, + 'tts': 189634 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674114019, + 'tts': 189724 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674114032, + 'tts': 189735 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 498}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 97, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 95, + 'tid': 9, + 'ts': 1122674114061, + 'tts': 189765 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 45, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 42, + 'tid': 9, + 'ts': 1122674114096, + 'tts': 189800 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 499}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674114127, + 'tts': 189830 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689896, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674114153, + 'tts': 189856 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674114167, + 'tts': 189870 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674114211, + 'tts': 189914 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674114239, + 'tts': 189942 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674114253, + 'tts': 189957 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674130694, + 'tts': 190042 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674130707, + 'tts': 190054 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 499}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 98, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 95, + 'tid': 9, + 'ts': 1122674130736, + 'tts': 190084 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 44, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 42, + 'tid': 9, + 'ts': 1122674130772, + 'tts': 190119 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 500}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674130802, + 'tts': 190150 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689912, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674130828, + 'tts': 190175 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674130842, + 'tts': 190189 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674130887, + 'tts': 190234 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674130914, + 'tts': 190262 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674130929, + 'tts': 190276 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674147364, + 'tts': 190365 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674147377, + 'tts': 190376 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 500}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 111, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 109, + 'tid': 9, + 'ts': 1122674147406, + 'tts': 190406 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 47, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 44, + 'tid': 9, + 'ts': 1122674147452, + 'tts': 190453 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 501}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674147486, + 'tts': 190486 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689928, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674147511, + 'tts': 190511 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674147526, + 'tts': 190526 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674147570, + 'tts': 190570 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674147598, + 'tts': 190598 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674147613, + 'tts': 190613 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674164055, + 'tts': 190720 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674164068, + 'tts': 190732 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 501}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 113, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 111, + 'tid': 9, + 'ts': 1122674164097, + 'tts': 190761 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 46, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 44, + 'tid': 9, + 'ts': 1122674164146, + 'tts': 190810 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 502}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674164178, + 'tts': 190842 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689944, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674164204, + 'tts': 190868 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674164219, + 'tts': 190883 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674164263, + 'tts': 190927 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674164312, + 'tts': 190976 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674164327, + 'tts': 190991 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674180694, + 'tts': 191071 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674180707, + 'tts': 191083 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 502}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 111, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 109, + 'tid': 9, + 'ts': 1122674180736, + 'tts': 191112 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 46, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 43, + 'tid': 9, + 'ts': 1122674180783, + 'tts': 191160 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 503}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674180816, + 'tts': 191192 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689960, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674180841, + 'tts': 191217 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674180855, + 'tts': 191232 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674180899, + 'tts': 191276 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674180928, + 'tts': 191305 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674180943, + 'tts': 191319 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674197354, + 'tts': 191407 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674197367, + 'tts': 191418 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 503}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 98, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 96, + 'tid': 9, + 'ts': 1122674197396, + 'tts': 191447 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 45, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 42, + 'tid': 9, + 'ts': 1122674197431, + 'tts': 191483 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 504}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674197462, + 'tts': 191514 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689976, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674197487, + 'tts': 191539 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674197502, + 'tts': 191553 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674197546, + 'tts': 191598 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674197590, + 'tts': 191642 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674197606, + 'tts': 191657 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674214025, + 'tts': 191747 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674214038, + 'tts': 191759 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 504}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 111, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 110, + 'tid': 9, + 'ts': 1122674214067, + 'tts': 191788 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 45, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 43, + 'tid': 9, + 'ts': 1122674214115, + 'tts': 191836 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 505}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674214147, + 'tts': 191868 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2689992, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674214173, + 'tts': 191894 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674214187, + 'tts': 191908 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674214232, + 'tts': 191953 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674214259, + 'tts': 191981 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674214274, + 'tts': 191995 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674230673, + 'tts': 192083 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674230686, + 'tts': 192095 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 505}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 125, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 123, + 'tid': 9, + 'ts': 1122674230716, + 'tts': 192124 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 48, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 46, + 'tid': 9, + 'ts': 1122674230775, + 'tts': 192183 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 506}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674230809, + 'tts': 192217 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2690008, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674230835, + 'tts': 192243 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674230849, + 'tts': 192258 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674230894, + 'tts': 192303 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674230924, + 'tts': 192332 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674230938, + 'tts': 192347 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674247362, + 'tts': 192436 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674247374, + 'tts': 192447 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 506}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 97, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 95, + 'tid': 9, + 'ts': 1122674247403, + 'tts': 192476 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 43, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 41, + 'tid': 9, + 'ts': 1122674247439, + 'tts': 192512 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 507}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674247469, + 'tts': 192543 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2690024, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674247494, + 'tts': 192567 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674247509, + 'tts': 192582 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674247553, + 'tts': 192626 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674247581, + 'tts': 192655 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674247596, + 'tts': 192669 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674264048, + 'tts': 192774 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674264062, + 'tts': 192786 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 507}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 99, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 97, + 'tid': 9, + 'ts': 1122674264091, + 'tts': 192815 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 45, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 42, + 'tid': 9, + 'ts': 1122674264127, + 'tts': 192851 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 508}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674264158, + 'tts': 192883 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2690040, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674264184, + 'tts': 192908 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674264199, + 'tts': 192923 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674264243, + 'tts': 192967 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674264272, + 'tts': 192996 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674264286, + 'tts': 193010 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674280687, + 'tts': 193099 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674180599, + 'tts': 90536 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674180634, + 'tts': 90570 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674197265, + 'tts': 90728 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674197288, + 'tts': 90750 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674213934, + 'tts': 90908 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674213956, + 'tts': 90929 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674230583, + 'tts': 91100 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674230606, + 'tts': 91122 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674247271, + 'tts': 91300 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674247293, + 'tts': 91321 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674263915, + 'tts': 91477 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674263938, + 'tts': 91499 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674280596, + 'tts': 91655 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674280619, + 'tts': 91677 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674297261, + 'tts': 91831 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674297287, + 'tts': 91856 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674313908, + 'tts': 92015 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674313930, + 'tts': 92036 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674330601, + 'tts': 92208 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674330623, + 'tts': 92230 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674347259, + 'tts': 92385 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674347281, + 'tts': 92407 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674363933, + 'tts': 92564 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674363956, + 'tts': 92586 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674380587, + 'tts': 92742 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674380610, + 'tts': 92764 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674397245, + 'tts': 92919 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674397268, + 'tts': 92940 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674413915, + 'tts': 93111 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674413938, + 'tts': 93133 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674430594, + 'tts': 93290 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674430617, + 'tts': 93312 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674447250, + 'tts': 93468 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674447273, + 'tts': 93490 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674463925, + 'tts': 93617 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674463948, + 'tts': 93639 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674480599, + 'tts': 93799 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674480621, + 'tts': 93820 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674497252, + 'tts': 93974 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674497275, + 'tts': 93996 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674513924, + 'tts': 94167 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674513946, + 'tts': 94189 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674530585, + 'tts': 94357 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674530607, + 'tts': 94379 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674547254, + 'tts': 94537 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674547276, + 'tts': 94558 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'BeginFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674563916, + 'tts': 94716 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline.frame', + 'name': 'RequestMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 't', + 'tid': 17, + 'ts': 1122674563954, + 'tts': 94753 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674514204, + 'tts': 198558 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674514232, + 'tts': 198586 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674514246, + 'tts': 198600 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674530672, + 'tts': 198686 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674530685, + 'tts': 198697 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 523}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 97, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 95, + 'tid': 9, + 'ts': 1122674530714, + 'tts': 198727 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 44, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 41, + 'tid': 9, + 'ts': 1122674530749, + 'tts': 198762 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 524}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674530780, + 'tts': 198792 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2693784, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674530805, + 'tts': 198817 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674530820, + 'tts': 198832 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674530864, + 'tts': 198876 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674530892, + 'tts': 198905 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674530907, + 'tts': 198919 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674547345, + 'tts': 199009 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674547358, + 'tts': 199020 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 524}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 98, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 95, + 'tid': 9, + 'ts': 1122674547387, + 'tts': 199050 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 44, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 41, + 'tid': 9, + 'ts': 1122674547423, + 'tts': 199086 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 525}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674547454, + 'tts': 199116 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2693800, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674547479, + 'tts': 199141 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674547493, + 'tts': 199156 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674547538, + 'tts': 199200 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674547566, + 'tts': 199229 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674547581, + 'tts': 199243 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674564053, + 'tts': 199343 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'BeginMainThreadFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674564066, + 'tts': 199355 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 525}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 99, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3834, + 'tdur': 97, + 'tid': 9, + 'ts': 1122674564096, + 'tts': 199384 + }, + { + 'args': { + 'data': + {'frame': '0x1100e70a8000', 'scriptId': '29', 'scriptLine': 2, 'scriptName': 'http://localhost/raf.html'} + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 44, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3834, + 'tdur': 42, + 'tid': 9, + 'ts': 1122674564132, + 'tts': 199420 + }, + { + 'args': {'data': {'frame': '0x1100e70a8000', 'id': 526}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674564162, + 'tts': 199451 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 0, 'jsHeapSizeUsed': 2693816, 'nodes': 7}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674564188, + 'tts': 199477 + }, + { + 'args': {'frame': '0x1100e70a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3834, + 's': 'g', + 'tid': 9, + 'ts': 1122674564203, + 'tts': 199492 + }, + { + 'args': {'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'B', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674564248, + 'tts': 199536 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'CompositeLayers', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674564276, + 'tts': 199565 + }, + { + 'args': {}, + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Program', + 'ph': 'E', + 'pid': 3834, + 'tid': 9, + 'ts': 1122674564291, + 'tts': 199579 + }, + { + 'args': {'number': 32}, + + 'cat': '__metadata', + 'name': 'num_cpus', + 'ph': 'M', + 'pid': 3834, + 'tid': 0, + 'ts': 0 + }, + { + 'args': {'sort_index': -5}, + + 'cat': '__metadata', + 'name': 'process_sort_index', + 'ph': 'M', + 'pid': 3834, + 'tid': 10, + 'ts': 0 + }, + { + 'args': {'name': 'Renderer'}, + + 'cat': '__metadata', + 'name': 'process_name', + 'ph': 'M', + 'pid': 3834, + 'tid': 10, + 'ts': 0 + }, + { + 'args': {'sort_index': -1}, + + 'cat': '__metadata', + 'name': 'thread_sort_index', + 'ph': 'M', + 'pid': 3834, + 'tid': 9, + 'ts': 0 + }, + { + 'args': {'name': 'CrRendererMain'}, + + 'cat': '__metadata', + 'name': 'thread_name', + 'ph': 'M', + 'pid': 3834, + 'tid': 9, + 'ts': 0 + }, + { + 'args': {'name': 'Compositor'}, + + 'cat': '__metadata', + 'name': 'thread_name', + 'ph': 'M', + 'pid': 3834, + 'tid': 17, + 'ts': 0 + }, + { + 'args': {'elementCount': 47}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RecalculateStyles', + 'ph': 'E', + 'pid': 3872, + 'tid': 26, + 'ts': 1122673092850, + 'tts': 827512 + }, + { + 'args': + {'beginData': {'dirtyObjects': 44, 'frame': '0x176b9c2a8000', 'partialLayout': false, 'totalObjects': 261}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Layout', + 'ph': 'B', + 'pid': 3872, + 'tid': 26, + 'ts': 1122673092873, + 'tts': 827535 + }, + { + 'args': {'endData': {'root': [0, 0, 1570, 0, 1570, 1472, 0, 1472], 'rootNode': 2}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'Layout', + 'ph': 'E', + 'pid': 3872, + 'tid': 26, + 'ts': 1122673093523, + 'tts': 828186 + }, + { + 'args': {'data': {'frame': '0x176b9c2a8000', 'id': 12}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 1828, + 'name': 'FireAnimationFrame', + 'ph': 'X', + 'pid': 3872, + 'tdur': 1827, + 'tid': 26, + 'ts': 1122673093558, + 'tts': 828220 + }, + { + 'args': { + 'data': { + 'frame': '0x176b9c2a8000', + 'scriptId': '65', + 'scriptLine': 939, + 'scriptName': 'chrome-devtools://devtools/bundled/ui/UIUtils.js' + } + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 1770, + 'name': 'FunctionCall', + 'ph': 'X', + 'pid': 3872, + 'tdur': 1770, + 'tid': 26, + 'ts': 1122673093604, + 'tts': 828265 + }, + { + 'args': {'frame': '0x176b9c2a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'ScheduleStyleRecalculation', + 'ph': 'I', + 'pid': 3872, + 's': 'g', + 'tid': 26, + 'ts': 1122673094798, + 'tts': 829461 + }, + { + 'args': {'frame': '0x176b9c2a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RecalculateStyles', + 'ph': 'B', + 'pid': 3872, + 'tid': 26, + 'ts': 1122673094958, + 'tts': 829620 + }, + { + 'args': {'elementCount': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RecalculateStyles', + 'ph': 'E', + 'pid': 3872, + 'tid': 26, + 'ts': 1122673094989, + 'tts': 829651 + }, + { + 'args': {'data': {'frame': '0x176b9c2a8000', 'id': 13}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'RequestAnimationFrame', + 'ph': 'I', + 'pid': 3872, + 's': 'g', + 'tid': 26, + 'ts': 1122673095367, + 'tts': 830030 + }, + { + 'args': {'data': {'documents': 1, 'jsEventListeners': 141, 'jsHeapSizeUsed': 15850696, 'nodes': 1705}}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateCounters', + 'ph': 'I', + 'pid': 3872, + 's': 'g', + 'tid': 26, + 'ts': 1122673095384, + 'tts': 830046 + }, + { + 'args': {'frame': '0x176b9c2a8000'}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayerTree', + 'ph': 'I', + 'pid': 3872, + 's': 'g', + 'tid': 26, + 'ts': 1122673095390, + 'tts': 830052 + }, + { + 'args': {'layerId': 11, 'layerTreeId': 1}, + + 'cat': 'disabled-by-default-devtools.timeline', + 'name': 'UpdateLayer', + 'ph': 'B', + 'pid': 3872, + 'tid': 26, + 'ts': 1122673095845, + 'tts': 830507 + }, + { + 'args': { + 'data': { + 'clip': [-15, -15, 1585, -15, 1585, 1487, -15, 1487], + 'frame': '0x176b9c2a8000', + 'layerId': 11, + 'nodeId': 2 + } + }, + + 'cat': 'disabled-by-default-devtools.timeline', + 'dur': 4637, + 'name': 'Paint', + 'ph': 'X', + 'pid': 3872, + 'tdur': 4630, + 'tid': 26, + 'ts': 1122673095897, + 'tts': 830559 + }, + { + 'args': {'name': 'Browser'}, + + 'cat': '__metadata', + 'name': 'process_name', + 'ph': 'M', + 'pid': 3778, + 'tid': 3801, + 'ts': 0 + }, + { + 'args': {'name': 'CrBrowserMain'}, + + 'cat': '__metadata', + 'name': 'thread_name', + 'ph': 'M', + 'pid': 3778, + 'tid': 3778, + 'ts': 0 + } + ]); +};
diff --git a/third_party/WebKit/Source/devtools/front_end/performance_test_runner/TimelineTestRunner.js b/third_party/WebKit/Source/devtools/front_end/performance_test_runner/TimelineTestRunner.js new file mode 100644 index 0000000..2f8442b --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/performance_test_runner/TimelineTestRunner.js
@@ -0,0 +1,408 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +PerformanceTestRunner.timelinePropertyFormatters = { + children: 'formatAsTypeName', + endTime: 'formatAsTypeName', + requestId: 'formatAsTypeName', + startTime: 'formatAsTypeName', + stackTrace: 'formatAsTypeName', + url: 'formatAsURL', + scriptName: 'formatAsTypeName', + scriptId: 'formatAsTypeName', + usedHeapSizeDelta: 'skip', + mimeType: 'formatAsTypeName', + id: 'formatAsTypeName', + timerId: 'formatAsTypeName', + scriptLine: 'formatAsTypeName', + layerId: 'formatAsTypeName', + lineNumber: 'formatAsTypeName', + columnNumber: 'formatAsTypeName', + frameId: 'formatAsTypeName', + frame: 'formatAsTypeName', + page: 'formatAsTypeName', + encodedDataLength: 'formatAsTypeName', + identifier: 'formatAsTypeName', + clip: 'formatAsTypeName', + root: 'formatAsTypeName', + backendNodeId: 'formatAsTypeName', + nodeId: 'formatAsTypeName', + rootNode: 'formatAsTypeName', + finishTime: 'formatAsTypeName', + thread: 'formatAsTypeName', + allottedMilliseconds: 'formatAsTypeName', + timedOut: 'formatAsTypeName', + networkTime: 'formatAsTypeName' +}; + +PerformanceTestRunner.InvalidationFormatters = { + _tracingEvent: 'skip', + cause: 'formatAsInvalidationCause', + frame: 'skip', + invalidatedSelectorId: 'skip', + invalidationList: 'skip', + invalidationSet: 'skip', + linkedRecalcStyleEvent: 'skip', + linkedLayoutEvent: 'skip', + nodeId: 'skip', + paintId: 'skip', + startTime: 'skip' +}; + +TestRunner.formatters.formatAsInvalidationCause = function(cause) { + if (!cause) + return '<undefined>'; + + var stackTrace; + + if (cause.stackTrace && cause.stackTrace.length) { + stackTrace = + TestRunner.formatters.formatAsURL(cause.stackTrace[0].url) + ':' + (cause.stackTrace[0].lineNumber + 1); + } + + return '{reason: ' + cause.reason + ', stackTrace: ' + stackTrace + '}'; +}; + +PerformanceTestRunner.createTracingModel = function(events) { + var model = new SDK.TracingModel(new Bindings.TempFileBackingStorage('tracing')); + model.addEvents(events); + model.tracingComplete(); + return model; +}; + +PerformanceTestRunner.tracingModel = function() { + return UI.panels.timeline._performanceModel.tracingModel(); +}; + +PerformanceTestRunner.invokeWithTracing = function(functionName, callback, additionalCategories, enableJSSampling) { + var categories = + '-*,disabled-by-default-devtools.timeline*,devtools.timeline,' + SDK.TracingModel.TopLevelEventCategory; + + if (additionalCategories) + categories += ',' + additionalCategories; + + var timelinePanel = UI.panels.timeline; + var timelineController = PerformanceTestRunner.timelineController(); + timelinePanel._timelineController = timelineController; + timelineController._startRecordingWithCategories(categories, enableJSSampling).then(tracingStarted); + + function tracingStarted() { + timelinePanel._recordingStarted(); + TestRunner.callFunctionInPageAsync(functionName).then(onPageActionsDone); + } + + function onPageActionsDone() { + PerformanceTestRunner.runWhenTimelineIsReady(callback); + timelineController.stopRecording(); + } +}; + +PerformanceTestRunner.performanceModel = function() { + return UI.panels.timeline._performanceModel; +}; + +PerformanceTestRunner.timelineModel = function() { + return PerformanceTestRunner.performanceModel().timelineModel(); +}; + +PerformanceTestRunner.timelineFrameModel = function() { + return PerformanceTestRunner.performanceModel().frameModel(); +}; + +PerformanceTestRunner.createPerformanceModelWithEvents = function(events) { + var tracingModel = new SDK.TracingModel(new Bindings.TempFileBackingStorage('tracing')); + tracingModel.addEvents(events); + tracingModel.tracingComplete(); + var performanceModel = new Timeline.PerformanceModel(); + performanceModel.setTracingModel(tracingModel); + return performanceModel; +}; + +PerformanceTestRunner.timelineController = function() { + var performanceModel = new Timeline.PerformanceModel(); + UI.panels.timeline._pendingPerformanceModel = performanceModel; + return new Timeline.TimelineController(TestRunner.tracingManager, performanceModel, UI.panels.timeline); +}; + +PerformanceTestRunner.runWhenTimelineIsReady = function(callback) { + TestRunner.addSniffer(UI.panels.timeline, 'loadingComplete', () => callback()); +}; + +PerformanceTestRunner.startTimeline = function(callback) { + var panel = UI.panels.timeline; + TestRunner.addSniffer(panel, '_recordingStarted', callback); + panel._toggleRecording(); +}; + +PerformanceTestRunner.stopTimeline = function(callback) { + PerformanceTestRunner.runWhenTimelineIsReady(callback); + UI.panels.timeline._toggleRecording(); +}; + +PerformanceTestRunner.evaluateWithTimeline = function(actions, doneCallback) { + PerformanceTestRunner.startTimeline(step1); + + function step1() { + TestRunner.evaluateInPage(actions, step2); + } + + function step2() { + PerformanceTestRunner.stopTimeline(doneCallback); + } +}; + +PerformanceTestRunner.invokeAsyncWithTimeline = function(functionName, doneCallback) { + PerformanceTestRunner.startTimeline(step1); + + function step1() { + TestRunner.callFunctionInPageAsync(functionName).then(step2); + } + + function step2() { + PerformanceTestRunner.stopTimeline(TestRunner.safeWrap(doneCallback)); + } +}; + +PerformanceTestRunner.performActionsAndPrint = function(actions, typeName, includeTimeStamps) { + function callback() { + PerformanceTestRunner.printTimelineRecordsWithDetails(typeName); + + if (includeTimeStamps) { + TestRunner.addResult('Timestamp records: '); + PerformanceTestRunner.printTimestampRecords(typeName); + } + + TestRunner.completeTest(); + } + + PerformanceTestRunner.evaluateWithTimeline(actions, callback); +}; + +PerformanceTestRunner.printTimelineRecords = function(name) { + for (let event of PerformanceTestRunner.timelineModel().mainThreadEvents()) { + if (event.name === name) + PerformanceTestRunner.printTraceEventProperties(event); + } +}; + +PerformanceTestRunner.printTimelineRecordsWithDetails = function(name) { + for (let event of PerformanceTestRunner.timelineModel().mainThreadEvents()) { + if (name === event.name) + PerformanceTestRunner.printTraceEventPropertiesWithDetails(event); + } +}; + +PerformanceTestRunner.walkTimelineEventTree = function(callback) { + var performanceModel = PerformanceTestRunner.performanceModel(); + var view = new Timeline.EventsTimelineTreeView(UI.panels.timeline._filters, null); + view.setModel(performanceModel); + var selection = Timeline.TimelineSelection.fromRange( + performanceModel.timelineModel().minimumRecordTime(), performanceModel.timelineModel().maximumRecordTime()); + view.updateContents(selection); + PerformanceTestRunner.walkTimelineEventTreeUnderNode(callback, view._currentTree, 0); +}; + +PerformanceTestRunner.walkTimelineEventTreeUnderNode = function(callback, root, level) { + var event = root.event; + + if (event) + callback(event, level); + + for (var child of root.children().values()) + PerformanceTestRunner.walkTimelineEventTreeUnderNode(callback, child, (level || 0) + 1); +}; + +PerformanceTestRunner.printTimestampRecords = function(typeName) { + var dividers = PerformanceTestRunner.timelineModel().eventDividers(); + + for (var event of dividers) { + if (event.name === typeName) + PerformanceTestRunner.printTraceEventProperties(event); + } +}; + +PerformanceTestRunner.forAllEvents = function(events, callback) { + let eventStack = []; + + for (let event of events) { + while (eventStack.length && eventStack.peekLast().endTime <= event.startTime) + eventStack.pop(); + + callback(event, eventStack); + + if (event.endTime) + eventStack.push(event); + } +}; + +PerformanceTestRunner.printTraceEventProperties = function(traceEvent) { + TestRunner.addResult(traceEvent.name + ' Properties:'); + var data = traceEvent.args['beginData'] || traceEvent.args['data']; + var frameId = data && data['frame']; + + var object = { + data: traceEvent.args['data'] || traceEvent.args, + endTime: traceEvent.endTime || traceEvent.startTime, + frameId: frameId, + stackTrace: TimelineModel.TimelineData.forEvent(traceEvent).stackTrace, + startTime: traceEvent.startTime, + type: traceEvent.name + }; + + for (var field in object) { + if (object[field] === null || object[field] === undefined) + delete object[field]; + } + + TestRunner.addObject(object, PerformanceTestRunner.timelinePropertyFormatters); +}; + +PerformanceTestRunner.printTraceEventPropertiesWithDetails = function(event) { + PerformanceTestRunner.printTraceEventProperties(event); + const details = Timeline.TimelineUIUtils.buildDetailsTextForTraceEvent( + event, SDK.targetManager.mainTarget(), new Components.Linkifier()); + TestRunner.addResult(`Text details for ${event.name}: ${details}`); + + if (TimelineModel.TimelineData.forEvent(event).warning) + TestRunner.addResult(`${event.name} has a warning`); +}; + +PerformanceTestRunner.findTimelineEvent = function(name, index) { + return PerformanceTestRunner.timelineModel().mainThreadEvents().filter(e => e.name === name)[index || 0]; +}; + +PerformanceTestRunner.findChildEvent = function(events, parentIndex, name) { + var endTime = events[parentIndex].endTime; + + for (var i = parentIndex + 1; i < events.length && (!events[i].endTime || events[i].endTime <= endTime); ++i) { + if (events[i].name === name) + return events[i]; + } + + return null; +}; + +PerformanceTestRunner.dumpFrame = function(frame) { + var fieldsToDump = [ + 'cpuTime', 'duration', 'startTime', 'endTime', 'id', 'mainThreadFrameId', 'timeByCategory', 'other', 'scripting', + 'painting', 'rendering', 'committedFrom', 'idle' + ]; + + function formatFields(object) { + var result = {}; + + for (var key in object) { + if (fieldsToDump.indexOf(key) < 0) + continue; + + var value = object[key]; + + if (typeof value === 'number') + value = Number(value.toFixed(7)); + else if (typeof value === 'object' && value) + value = formatFields(value); + + result[key] = value; + } + + return result; + } + + TestRunner.addObject(formatFields(frame)); +}; + +PerformanceTestRunner.dumpInvalidations = function(recordType, index, comment) { + var event = PerformanceTestRunner.findTimelineEvent(recordType, index || 0); + + TestRunner.addArray( + TimelineModel.InvalidationTracker.invalidationEventsFor(event), PerformanceTestRunner.InvalidationFormatters, '', + comment); +}; + +PerformanceTestRunner.dumpFlameChartProvider = function(provider, includeGroups) { + var includeGroupsSet = includeGroups && new Set(includeGroups); + var timelineData = provider.timelineData(); + var stackDepth = provider.maxStackDepth(); + var entriesByLevel = new Multimap(); + + for (let i = 0; i < timelineData.entryLevels.length; ++i) + entriesByLevel.set(timelineData.entryLevels[i], i); + + for (let groupIndex = 0; groupIndex < timelineData.groups.length; ++groupIndex) { + const group = timelineData.groups[groupIndex]; + + if (includeGroupsSet && !includeGroupsSet.has(group.name)) + continue; + + var maxLevel = + (groupIndex + 1 < timelineData.groups.length ? timelineData.groups[groupIndex + 1].firstLevel : stackDepth); + TestRunner.addResult(`Group: ${group.name}`); + + for (let level = group.startLevel; level < maxLevel; ++level) { + TestRunner.addResult(`Level ${level - group.startLevel}`); + var entries = entriesByLevel.get(level); + + for (const index of entries) { + const title = provider.entryTitle(index); + const color = provider.entryColor(index); + TestRunner.addResult(`${title} (${color})`); + } + } + } +}; + +PerformanceTestRunner.dumpTimelineFlameChart = function(includeGroups) { + const provider = UI.panels.timeline._flameChart._mainDataProvider; + TestRunner.addResult('Timeline Flame Chart'); + PerformanceTestRunner.dumpFlameChartProvider(provider, includeGroups); +}; + +PerformanceTestRunner.loadTimeline = function(timelineData) { + var promise = new Promise(fulfill => PerformanceTestRunner.runWhenTimelineIsReady(fulfill)); + + UI.panels.timeline._loadFromFile(new Blob([timelineData], {type: 'text/plain'})); + + return promise; +}; + +(async function() { + await TestRunner.evaluateInPagePromise(` + function wrapCallFunctionForTimeline(f) { + var script = document.createElement('script'); + script.textContent = '(' + f.toString() + ')()\n//# sourceURL=wrapCallFunctionForTimeline.js'; + document.body.appendChild(script); + } + + function generateFrames(count) { + var promise = Promise.resolve(); + + for (let i = count; i > 0; --i) + promise = promise.then(changeBackgroundAndWaitForFrame.bind(null, i)); + + return promise; + + function changeBackgroundAndWaitForFrame(i) { + document.body.style.backgroundColor = (i & 1 ? 'rgb(200, 200, 200)' : 'rgb(240, 240, 240)'); + return waitForFrame(); + } + } + + function waitForFrame() { + var callback; + var promise = new Promise(fulfill => callback = fulfill); + + if (window.testRunner) + testRunner.capturePixelsAsyncThen(() => window.requestAnimationFrame(callback)); + else + window.requestAnimationFrame(callback); + + return promise; + } + `); +})();
diff --git a/third_party/WebKit/Source/devtools/front_end/performance_test_runner/module.json b/third_party/WebKit/Source/devtools/front_end/performance_test_runner/module.json new file mode 100644 index 0000000..c3e98e8 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/performance_test_runner/module.json
@@ -0,0 +1,16 @@ +{ + "dependencies": [ + "test_runner", + "integration_test_runner", + "timeline_model", + "timeline" + ], + "scripts": [ + "TimelineTestRunner.js", + "TimelineDataTestRunner.js" + ], + "skip_compilation": [ + "TimelineTestRunner.js", + "TimelineDataTestRunner.js" + ] +}
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler_test_runner/HeapSnapshotTestRunner.js b/third_party/WebKit/Source/devtools/front_end/profiler_test_runner/HeapSnapshotTestRunner.js new file mode 100644 index 0000000..c6a2e2d --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/profiler_test_runner/HeapSnapshotTestRunner.js
@@ -0,0 +1,641 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +ProfilerTestRunner.createHeapSnapshotMockFactories = function() { + ProfilerTestRunner.createJSHeapSnapshotMockObject = function() { + return { + _rootNodeIndex: 0, + _nodeTypeOffset: 0, + _nodeNameOffset: 1, + _nodeEdgeCountOffset: 2, + _nodeFieldCount: 3, + _edgeFieldsCount: 3, + _edgeTypeOffset: 0, + _edgeNameOffset: 1, + _edgeToNodeOffset: 2, + _nodeTypes: ['hidden', 'object'], + _edgeTypes: ['element', 'property', 'shortcut'], + _edgeShortcutType: -1, + _edgeHiddenType: -1, + _edgeElementType: 0, + _realNodesLength: 18, + nodes: new Uint32Array([0, 0, 2, 1, 1, 2, 1, 2, 2, 1, 3, 1, 1, 4, 0, 1, 5, 0]), + containmentEdges: new Uint32Array([2, 6, 3, 1, 7, 6, 0, 1, 6, 1, 8, 9, 1, 9, 9, 1, 10, 12, 1, 11, 15]), + strings: ['', 'A', 'B', 'C', 'D', 'E', 'a', 'b', 'ac', 'bc', 'bd', 'ce'], + _firstEdgeIndexes: new Uint32Array([0, 6, 12, 18, 21, 21, 21]), + createNode: HeapSnapshotWorker.JSHeapSnapshot.prototype.createNode, + createEdge: HeapSnapshotWorker.JSHeapSnapshot.prototype.createEdge, + createRetainingEdge: HeapSnapshotWorker.JSHeapSnapshot.prototype.createRetainingEdge + }; + }; + + ProfilerTestRunner.createHeapSnapshotMockRaw = function() { + return { + snapshot: { + meta: { + node_fields: ['type', 'name', 'id', 'self_size', 'retained_size', 'dominator', 'edge_count'], + node_types: [['hidden', 'object'], '', '', '', '', '', ''], + edge_fields: ['type', 'name_or_index', 'to_node'], + edge_types: [['element', 'property', 'shortcut'], '', ''] + }, + + node_count: 6, + edge_count: 7 + }, + + nodes: [ + 0, 0, 1, 0, 20, 0, 2, 1, 1, 2, 2, 2, 0, 2, 1, 2, 3, 3, 8, 0, 2, + 1, 3, 4, 4, 10, 0, 1, 1, 4, 5, 5, 5, 14, 0, 1, 5, 6, 6, 6, 21, 0 + ], + + edges: [1, 6, 7, 1, 7, 14, 0, 1, 14, 1, 8, 21, 1, 9, 21, 1, 10, 28, 1, 11, 35], + strings: ['', 'A', 'B', 'C', 'D', 'E', 'a', 'b', 'ac', 'bc', 'bd', 'ce'] + }; + }; + + ProfilerTestRunner._postprocessHeapSnapshotMock = function(mock) { + mock.nodes = new Uint32Array(mock.nodes); + mock.edges = new Uint32Array(mock.edges); + return mock; + }; + + ProfilerTestRunner.createHeapSnapshotMock = function() { + return ProfilerTestRunner._postprocessHeapSnapshotMock(ProfilerTestRunner.createHeapSnapshotMockRaw()); + }; + + ProfilerTestRunner.createHeapSnapshotMockWithDOM = function() { + return ProfilerTestRunner._postprocessHeapSnapshotMock({ + snapshot: { + meta: { + node_fields: ['type', 'name', 'id', 'edge_count'], + node_types: [['hidden', 'object', 'synthetic'], '', '', ''], + edge_fields: ['type', 'name_or_index', 'to_node'], + edge_types: [['element', 'hidden', 'internal'], '', ''] + }, + + node_count: 13, + edge_count: 13 + }, + + nodes: [ + 2, 0, 1, 4, 1, 11, 2, 2, 1, 11, 3, 3, 2, 5, 4, 0, 2, 6, 5, 1, 1, 1, 6, 0, 1, 2, + 7, 1, 1, 4, 8, 2, 1, 8, 9, 0, 1, 7, 10, 0, 1, 3, 11, 0, 1, 10, 12, 0, 1, 9, 13, 0 + ], + + edges: [ + 0, 1, 4, 0, 2, 8, 0, 3, 12, 0, 4, 16, 0, 1, 20, 0, 2, 24, 0, 1, + 24, 0, 2, 28, 1, 3, 32, 0, 1, 36, 0, 1, 40, 2, 12, 44, 2, 1, 48 + ], + + strings: ['', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'M', 'N', 'Window', 'native'] + }); + }; + + ProfilerTestRunner.HeapNode = function(name, selfSize, type, id) { + this._type = type || ProfilerTestRunner.HeapNode.Type.object; + this._name = name; + this._selfSize = selfSize || 0; + this._builder = null; + this._edges = {}; + this._edgesCount = 0; + this._id = id; + }; + + ProfilerTestRunner.HeapNode.Type = { + 'hidden': 'hidden', + 'array': 'array', + 'string': 'string', + 'object': 'object', + 'code': 'code', + 'closure': 'closure', + 'regexp': 'regexp', + 'number': 'number', + 'native': 'native', + 'synthetic': 'synthetic' + }; + + ProfilerTestRunner.HeapNode.prototype = { + linkNode: function(node, type, nameOrIndex) { + if (!this._builder) + throw new Error('parent node is not connected to a snapshot'); + + if (!node._builder) + node._setBuilder(this._builder); + + if (nameOrIndex === undefined) + nameOrIndex = this._edgesCount; + + ++this._edgesCount; + + if (nameOrIndex in this._edges) { + throw new Error( + 'Can\'t add edge with the same nameOrIndex. nameOrIndex: ' + nameOrIndex + + ' oldNodeName: ' + this._edges[nameOrIndex]._name + ' newNodeName: ' + node._name); + } + + this._edges[nameOrIndex] = new ProfilerTestRunner.HeapEdge(node, type, nameOrIndex); + }, + + _setBuilder: function(builder) { + if (this._builder) + throw new Error('node reusing is prohibited'); + + this._builder = builder; + this._ordinal = this._builder._registerNode(this); + }, + + _serialize: function(rawSnapshot) { + rawSnapshot.nodes.push(this._builder.lookupNodeType(this._type)); + rawSnapshot.nodes.push(this._builder.lookupOrAddString(this._name)); + rawSnapshot.nodes.push(this._id || this._ordinal * 2 + 1); + rawSnapshot.nodes.push(this._selfSize); + rawSnapshot.nodes.push(0); + rawSnapshot.nodes.push(0); + rawSnapshot.nodes.push(Object.keys(this._edges).length); + + for (var i in this._edges) + this._edges[i]._serialize(rawSnapshot); + } + }; + + ProfilerTestRunner.HeapEdge = function(targetNode, type, nameOrIndex) { + this._targetNode = targetNode; + this._type = type; + this._nameOrIndex = nameOrIndex; + }; + + ProfilerTestRunner.HeapEdge.prototype = { + _serialize: function(rawSnapshot) { + if (!this._targetNode._builder) + throw new Error('Inconsistent state of node: ' + this._name + ' no builder assigned'); + + var builder = this._targetNode._builder; + rawSnapshot.edges.push(builder.lookupEdgeType(this._type)); + rawSnapshot.edges.push( + (typeof this._nameOrIndex === 'string' ? builder.lookupOrAddString(this._nameOrIndex) : this._nameOrIndex)); + rawSnapshot.edges.push(this._targetNode._ordinal * builder.nodeFieldsCount); + } + }; + + ProfilerTestRunner.HeapEdge.Type = { + 'context': 'context', + 'element': 'element', + 'property': 'property', + 'internal': 'internal', + 'hidden': 'hidden', + 'shortcut': 'shortcut', + 'weak': 'weak' + }; + + ProfilerTestRunner.HeapSnapshotBuilder = function() { + this._nodes = []; + this._string2id = {}; + this._strings = []; + this.nodeFieldsCount = 7; + this._nodeTypesMap = {}; + this._nodeTypesArray = []; + + for (var nodeType in ProfilerTestRunner.HeapNode.Type) { + this._nodeTypesMap[nodeType] = this._nodeTypesArray.length; + this._nodeTypesArray.push(nodeType); + } + + this._edgeTypesMap = {}; + this._edgeTypesArray = []; + + for (var edgeType in ProfilerTestRunner.HeapEdge.Type) { + this._edgeTypesMap[edgeType] = this._edgeTypesArray.length; + this._edgeTypesArray.push(edgeType); + } + + this.rootNode = new ProfilerTestRunner.HeapNode('root', 0, 'object'); + this.rootNode._setBuilder(this); + }; + + ProfilerTestRunner.HeapSnapshotBuilder.prototype = { + generateSnapshot: function() { + var rawSnapshot = { + 'snapshot': { + 'meta': { + 'node_fields': ['type', 'name', 'id', 'self_size', 'retained_size', 'dominator', 'edge_count'], + 'node_types': [this._nodeTypesArray, 'string', 'number', 'number', 'number', 'number', 'number'], + 'edge_fields': ['type', 'name_or_index', 'to_node'], + 'edge_types': [this._edgeTypesArray, 'string_or_number', 'node'] + } + }, + + 'nodes': [], + 'edges': [], + 'strings': [] + }; + + for (var i = 0; i < this._nodes.length; ++i) + this._nodes[i]._serialize(rawSnapshot); + + rawSnapshot.strings = this._strings.slice(); + var meta = rawSnapshot.snapshot.meta; + rawSnapshot.snapshot.edge_count = rawSnapshot.edges.length / meta.edge_fields.length; + rawSnapshot.snapshot.node_count = rawSnapshot.nodes.length / meta.node_fields.length; + return rawSnapshot; + }, + + createJSHeapSnapshot: function() { + var parsedSnapshot = ProfilerTestRunner._postprocessHeapSnapshotMock(this.generateSnapshot()); + return new HeapSnapshotWorker.JSHeapSnapshot(parsedSnapshot, new HeapSnapshotWorker.HeapSnapshotProgress()); + }, + + _registerNode: function(node) { + this._nodes.push(node); + return this._nodes.length - 1; + }, + + lookupNodeType: function(typeName) { + if (typeName === undefined) + throw new Error('wrong node type: ' + typeName); + + if (!(typeName in this._nodeTypesMap)) + throw new Error('wrong node type name: ' + typeName); + + return this._nodeTypesMap[typeName]; + }, + + lookupEdgeType: function(typeName) { + if (!(typeName in this._edgeTypesMap)) + throw new Error('wrong edge type name: ' + typeName); + + return this._edgeTypesMap[typeName]; + }, + + lookupOrAddString: function(string) { + if (string in this._string2id) + return this._string2id[string]; + + this._string2id[string] = this._strings.length; + this._strings.push(string); + return this._strings.length - 1; + } + }; + + ProfilerTestRunner.createHeapSnapshot = function(instanceCount, firstId) { + var seed = 881669; + + function pseudoRandom(limit) { + seed = seed * 355109 + 153763 >> 2 & 65535; + return seed % limit; + } + + var builder = new ProfilerTestRunner.HeapSnapshotBuilder(); + var rootNode = builder.rootNode; + var gcRootsNode = new ProfilerTestRunner.HeapNode('(GC roots)', 0, ProfilerTestRunner.HeapNode.Type.synthetic); + rootNode.linkNode(gcRootsNode, ProfilerTestRunner.HeapEdge.Type.element); + var windowNode = new ProfilerTestRunner.HeapNode('Window', 20); + rootNode.linkNode(windowNode, ProfilerTestRunner.HeapEdge.Type.shortcut); + gcRootsNode.linkNode(windowNode, ProfilerTestRunner.HeapEdge.Type.element); + + for (var i = 0; i < instanceCount; ++i) { + var sizeOfB = pseudoRandom(20) + 1; + var nodeB = new ProfilerTestRunner.HeapNode('B', sizeOfB, undefined, firstId++); + windowNode.linkNode(nodeB, ProfilerTestRunner.HeapEdge.Type.element); + var sizeOfA = pseudoRandom(50) + 1; + var nodeA = new ProfilerTestRunner.HeapNode('A', sizeOfA, undefined, firstId++); + nodeB.linkNode(nodeA, ProfilerTestRunner.HeapEdge.Type.property, 'a'); + nodeA.linkNode(nodeA, ProfilerTestRunner.HeapEdge.Type.property, 'a'); + } + + return builder.generateSnapshot(); + }; +}; + +ProfilerTestRunner.createHeapSnapshotMockFactories(); + +ProfilerTestRunner.startProfilerTest = function(callback) { + TestRunner.addResult('Profiler was enabled.'); + ProfilerTestRunner._panelReset = TestRunner.override(UI.panels.heap_profiler, '_reset', function() {}, true); + TestRunner.addSniffer(Profiler.HeapSnapshotView.prototype, 'show', ProfilerTestRunner._snapshotViewShown, true); + + Profiler.HeapSnapshotContainmentDataGrid.prototype.defaultPopulateCount = function() { + return 10; + }; + + Profiler.HeapSnapshotConstructorsDataGrid.prototype.defaultPopulateCount = function() { + return 10; + }; + + Profiler.HeapSnapshotDiffDataGrid.prototype.defaultPopulateCount = function() { + return 5; + }; + + TestRunner.addResult('Detailed heap profiles were enabled.'); + TestRunner.safeWrap(callback)(); +}; + +ProfilerTestRunner.completeProfilerTest = function() { + TestRunner.addResult(''); + TestRunner.addResult('Profiler was disabled.'); + TestRunner.completeTest(); +}; + +ProfilerTestRunner.runHeapSnapshotTestSuite = function(testSuite) { + var testSuiteTests = testSuite.slice(); + var completeTestStack; + + function runner() { + if (!testSuiteTests.length) { + if (completeTestStack) + TestRunner.addResult('FAIL: test already completed at ' + completeTestStack); + + ProfilerTestRunner.completeProfilerTest(); + completeTestStack = new Error().stack; + return; + } + + var nextTest = testSuiteTests.shift(); + TestRunner.addResult(''); + TestRunner.addResult( + 'Running: ' + + /function\s([^(]*)/.exec(nextTest)[1]); + ProfilerTestRunner._panelReset.call(UI.panels.heap_profiler); + TestRunner.safeWrap(nextTest)(runner, runner); + } + + ProfilerTestRunner.startProfilerTest(runner); +}; + +ProfilerTestRunner.assertColumnContentsEqual = function(reference, actual) { + var length = Math.min(reference.length, actual.length); + + for (var i = 0; i < length; ++i) + TestRunner.assertEquals(reference[i], actual[i], 'row ' + i); + + if (reference.length > length) + TestRunner.addResult('extra rows in reference array:\n' + reference.slice(length).join('\n')); + else if (actual.length > length) + TestRunner.addResult('extra rows in actual array:\n' + actual.slice(length).join('\n')); +}; + +ProfilerTestRunner.checkArrayIsSorted = function(contents, sortType, sortOrder) { + function simpleComparator(a, b) { + return (a < b ? -1 : (a > b ? 1 : 0)); + } + + function parseSize(size) { + return parseInt(size.replace(/[\xa0,]/g, ''), 10); + } + + var extractor = { + text: function(data) { + data; + }, + + number: function(data) { + return parseInt(data, 10); + }, + + size: parseSize, + + name: function(data) { + return data; + }, + + id: function(data) { + return parseInt(data, 10); + } + }[sortType]; + + if (!extractor) { + TestRunner.addResult('Invalid sort type: ' + sortType); + return; + } + + var acceptableComparisonResult; + + if (sortOrder === DataGrid.DataGrid.Order.Ascending) { + acceptableComparisonResult = -1; + } else if (sortOrder === DataGrid.DataGrid.Order.Descending) { + acceptableComparisonResult = 1; + } else { + TestRunner.addResult('Invalid sort order: ' + sortOrder); + return; + } + + for (var i = 0; i < contents.length - 1; ++i) { + var a = extractor(contents[i]); + var b = extractor(contents[i + 1]); + var result = simpleComparator(a, b); + + if (result !== 0 && result !== acceptableComparisonResult) { + TestRunner.addResult( + 'Elements ' + i + ' and ' + (i + 1) + ' are out of order: ' + a + ' ' + b + ' (' + sortOrder + ')'); + } + } +}; + +ProfilerTestRunner.clickColumn = function(column, callback) { + callback = TestRunner.safeWrap(callback); + var cell = this._currentGrid()._headerTableHeaders[column.id]; + + var event = { + target: { + enclosingNodeOrSelfWithNodeName: function() { + return cell; + } + } + }; + + function sortingComplete() { + ProfilerTestRunner._currentGrid().removeEventListener( + Profiler.HeapSnapshotSortableDataGrid.Events.SortingComplete, sortingComplete, this); + TestRunner.assertEquals(column.id, this._currentGrid().sortColumnId(), 'unexpected sorting'); + column.sort = this._currentGrid().sortOrder(); + + function callCallback() { + callback(column); + } + + setTimeout(callCallback, 0); + } + + ProfilerTestRunner._currentGrid().addEventListener( + Profiler.HeapSnapshotSortableDataGrid.Events.SortingComplete, sortingComplete, this); + this._currentGrid()._clickInHeaderCell(event); +}; + +ProfilerTestRunner.clickRowAndGetRetainers = function(row, callback) { + callback = TestRunner.safeWrap(callback); + + var event = { + target: { + enclosingNodeOrSelfWithNodeName: function() { + return row._element; + }, + + selectedNode: row + } + }; + + this._currentGrid()._mouseDownInDataTable(event); + var rootNode = ProfilerTestRunner.currentProfileView()._retainmentDataGrid.rootNode(); + rootNode.once(Profiler.HeapSnapshotGridNode.Events.PopulateComplete).then(() => callback(rootNode)); +}; + +ProfilerTestRunner.clickShowMoreButton = function(buttonName, row, callback) { + callback = TestRunner.safeWrap(callback); + var parent = row.parent; + parent.once(Profiler.HeapSnapshotGridNode.Events.PopulateComplete).then(() => setTimeout(() => callback(parent), 0)); + row[buttonName].click(); +}; + +ProfilerTestRunner.columnContents = function(column, row) { + this._currentGrid().updateVisibleNodes(); + var columnOrdinal = ProfilerTestRunner.viewColumns().indexOf(column); + var result = []; + var parent = row || this._currentGrid().rootNode(); + + for (var node = parent.children[0]; node; node = node.traverseNextNode(true, parent, true)) { + if (!node.selectable) + continue; + + var content = node.element().children[columnOrdinal]; + + if (content.firstElementChild) + content = content.firstElementChild; + + result.push(content.textContent); + } + + return result; +}; + +ProfilerTestRunner.countDataRows = function(row, filter) { + var result = 0; + + filter = filter || function(node) { + return node.selectable; + }; + + for (var node = row.children[0]; node; node = node.traverseNextNode(true, row, true)) { + if (filter(node)) + ++result; + } + + return result; +}; + +ProfilerTestRunner.expandRow = function(row, callback) { + callback = TestRunner.safeWrap(callback); + row.once(Profiler.HeapSnapshotGridNode.Events.PopulateComplete).then(() => setTimeout(() => callback(row), 0)); + + (function expand() { + if (row.hasChildren()) + row.expand(); + else + setTimeout(expand, 0); + })(); +}; + +ProfilerTestRunner.findAndExpandGCRoots = function(callback) { + ProfilerTestRunner.findAndExpandRow('(GC roots)', callback); +}; + +ProfilerTestRunner.findAndExpandWindow = function(callback) { + ProfilerTestRunner.findAndExpandRow('Window', callback); +}; + +ProfilerTestRunner.findAndExpandRow = function(name, callback) { + callback = TestRunner.safeWrap(callback); + var row = ProfilerTestRunner.findRow(name); + TestRunner.assertEquals(true, !!row, '"' + name + '" row'); + ProfilerTestRunner.expandRow(row, callback); +}; + +ProfilerTestRunner.findButtonsNode = function(row, startNode) { + for (var node = startNode || row.children[0]; node; node = node.traverseNextNode(true, row, true)) { + if (!node.selectable && node.showNext) + return node; + } + + return null; +}; + +ProfilerTestRunner.findRow = function(name, parent) { + function matcher(x) { + return x._name === name; + } + + return ProfilerTestRunner.findMatchingRow(matcher, parent); +}; + +ProfilerTestRunner.findMatchingRow = function(matcher, parent) { + parent = parent || this._currentGrid().rootNode(); + + for (var node = parent.children[0]; node; node = node.traverseNextNode(true, parent, true)) { + if (matcher(node)) + return node; + } + + return null; +}; + +ProfilerTestRunner.switchToView = function(title, callback) { + callback = TestRunner.safeWrap(callback); + var view = UI.panels.heap_profiler.visibleView; + view._changePerspectiveAndWait(title).then(callback); + ProfilerTestRunner._currentGrid().scrollContainer.style.height = '10000px'; +}; + +ProfilerTestRunner.takeAndOpenSnapshot = function(generator, callback) { + callback = TestRunner.safeWrap(callback); + var snapshot = generator(); + var profileType = Profiler.ProfileTypeRegistry.instance.heapSnapshotProfileType; + + function pushGeneratedSnapshot(reportProgress) { + if (reportProgress) { + profileType._reportHeapSnapshotProgress({data: {done: 50, total: 100, finished: false}}); + + profileType._reportHeapSnapshotProgress({data: {done: 100, total: 100, finished: true}}); + } + + snapshot.snapshot.typeId = 'HEAP'; + + profileType._addHeapSnapshotChunk({data: JSON.stringify(snapshot)}); + + return Promise.resolve(); + } + + TestRunner.override(TestRunner.HeapProfilerAgent, 'takeHeapSnapshot', pushGeneratedSnapshot); + ProfilerTestRunner._takeAndOpenSnapshotCallback = callback; + profileType._takeHeapSnapshot(); +}; + +ProfilerTestRunner.viewColumns = function() { + return ProfilerTestRunner._currentGrid()._columnsArray; +}; + +ProfilerTestRunner.currentProfileView = function() { + return UI.panels.heap_profiler.visibleView; +}; + +ProfilerTestRunner._currentGrid = function() { + return this.currentProfileView()._dataGrid; +}; + +ProfilerTestRunner._snapshotViewShown = function() { + if (ProfilerTestRunner._takeAndOpenSnapshotCallback) { + var callback = ProfilerTestRunner._takeAndOpenSnapshotCallback; + ProfilerTestRunner._takeAndOpenSnapshotCallback = null; + var dataGrid = this._dataGrid; + + function sortingComplete() { + dataGrid.removeEventListener(Profiler.HeapSnapshotSortableDataGrid.Events.SortingComplete, sortingComplete, null); + callback(); + } + + dataGrid.addEventListener(Profiler.HeapSnapshotSortableDataGrid.Events.SortingComplete, sortingComplete, null); + } +};
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler_test_runner/ProfilerTestRunner.js b/third_party/WebKit/Source/devtools/front_end/profiler_test_runner/ProfilerTestRunner.js new file mode 100644 index 0000000..2200015 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/profiler_test_runner/ProfilerTestRunner.js
@@ -0,0 +1,79 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +ProfilerTestRunner.startProfilerTest = function(callback) { + TestRunner.addResult('Profiler was enabled.'); + TestRunner.addSniffer(UI.panels.js_profiler, '_addProfileHeader', ProfilerTestRunner._profileHeaderAdded, true); + TestRunner.addSniffer(Profiler.ProfileView.prototype, 'refresh', ProfilerTestRunner._profileViewRefresh, true); + TestRunner.safeWrap(callback)(); +}; + +ProfilerTestRunner.completeProfilerTest = function() { + TestRunner.addResult(''); + TestRunner.addResult('Profiler was disabled.'); + TestRunner.completeTest(); +}; + +ProfilerTestRunner.runProfilerTestSuite = function(testSuite) { + var testSuiteTests = testSuite.slice(); + + function runner() { + if (!testSuiteTests.length) { + ProfilerTestRunner.completeProfilerTest(); + return; + } + + var nextTest = testSuiteTests.shift(); + TestRunner.addResult(''); + TestRunner.addResult( + 'Running: ' + + /function\s([^(]*)/.exec(nextTest)[1]); + TestRunner.safeWrap(nextTest)(runner, runner); + } + + ProfilerTestRunner.startProfilerTest(runner); +}; + +ProfilerTestRunner.showProfileWhenAdded = function(title) { + ProfilerTestRunner._showProfileWhenAdded = title; +}; + +ProfilerTestRunner._profileHeaderAdded = function(profile) { + if (ProfilerTestRunner._showProfileWhenAdded === profile.title) + UI.panels.js_profiler.showProfile(profile); +}; + +ProfilerTestRunner.waitUntilProfileViewIsShown = function(title, callback) { + callback = TestRunner.safeWrap(callback); + var profilesPanel = UI.panels.js_profiler; + + if (profilesPanel.visibleView && profilesPanel.visibleView.profile && + profilesPanel.visibleView._profileHeader.title === title) + callback(profilesPanel.visibleView); + else + ProfilerTestRunner._waitUntilProfileViewIsShownCallback = {title: title, callback: callback}; + +}; + +ProfilerTestRunner._profileViewRefresh = function() { + if (ProfilerTestRunner._waitUntilProfileViewIsShownCallback && + ProfilerTestRunner._waitUntilProfileViewIsShownCallback.title === this._profileHeader.title) { + var callback = ProfilerTestRunner._waitUntilProfileViewIsShownCallback; + delete ProfilerTestRunner._waitUntilProfileViewIsShownCallback; + callback.callback(this); + } +}; + +ProfilerTestRunner.startSamplingHeapProfiler = function() { + Profiler.SamplingHeapProfileType.instance.startRecordingProfile(); +}; + +ProfilerTestRunner.stopSamplingHeapProfiler = function() { + Profiler.SamplingHeapProfileType.instance.stopRecordingProfile(); +};
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler_test_runner/module.json b/third_party/WebKit/Source/devtools/front_end/profiler_test_runner/module.json new file mode 100644 index 0000000..1ea4ac0 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/profiler_test_runner/module.json
@@ -0,0 +1,17 @@ +{ + "dependencies": [ + "test_runner", + "integration_test_runner", + "profiler", + "data_grid", + "heap_snapshot_worker" + ], + "scripts": [ + "HeapSnapshotTestRunner.js", + "ProfilerTestRunner.js" + ], + "skip_compilation": [ + "HeapSnapshotTestRunner.js", + "ProfilerTestRunner.js" + ] +}
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/DOMStorageItemsView.js b/third_party/WebKit/Source/devtools/front_end/resources/DOMStorageItemsView.js index 0a3fae67..2bf85cc8 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/DOMStorageItemsView.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/DOMStorageItemsView.js
@@ -36,8 +36,8 @@ this.element.classList.add('storage-view', 'table'); var columns = /** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([ - {id: 'key', title: Common.UIString('Key'), sortable: false, editable: true, weight: 50}, - {id: 'value', title: Common.UIString('Value'), sortable: false, editable: true, weight: 50} + {id: 'key', title: Common.UIString('Key'), sortable: false, editable: true, longText: true, weight: 50}, + {id: 'value', title: Common.UIString('Value'), sortable: false, editable: true, longText: true, weight: 50} ]); this._dataGrid = new DataGrid.DataGrid(columns, this._editingCallback.bind(this), this._deleteCallback.bind(this)); this._dataGrid.setStriped(true);
diff --git a/third_party/WebKit/Source/devtools/front_end/sass_test_runner/SASSTestRunner.js b/third_party/WebKit/Source/devtools/front_end/sass_test_runner/SASSTestRunner.js new file mode 100644 index 0000000..9e8d661 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/sass_test_runner/SASSTestRunner.js
@@ -0,0 +1,331 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +var sassSourceMapFactory = null; + +SASSTestRunner.sassSourceMapFactory = function() { + if (!sassSourceMapFactory) + sassSourceMapFactory = new Sass.SASSSourceMapFactory(); + + return sassSourceMapFactory; +}; + +SASSTestRunner.parseSCSS = function(url, text) { + return Sass.SASSSupport.parseSCSS(url, text); +}; + +SASSTestRunner.parseCSS = SASSTestRunner.parseSCSS; + +SASSTestRunner.loadASTMapping = function(header, callback) { + var sourceMapManager = header.cssModel().sourceMapManager(); + var sourceMap = sourceMapManager.sourceMapForClient(header); + + if (sourceMap) { + callback((sourceMap.editable() ? sourceMap : null)); + return; + } + + sourceMapManager.addEventListener(SDK.SourceMapManager.Events.SourceMapAttached, onAttached); + + function onAttached(event) { + if (event.data.client !== header) + return; + + sourceMapManager.removeEventListener(SDK.SourceMapManager.Events.SourceMapAttached, onAttached); + var sourceMap = event.data.sourceMap; + callback((sourceMap.editable() ? sourceMap : null)); + } +}; + +SASSTestRunner.dumpAST = function(ast) { + var lines = [String.sprintf('=== AST === %s', ast.document.url)]; + + for (var i = 0; i < ast.rules.length; ++i) { + var rule = ast.rules[i]; + lines.push(String.sprintf('rule %d', i)); + var ruleLines = dumpRule(rule); + lines = lines.concat(indent(ruleLines)); + } + + lines.push('======'); + TestRunner.addResult(lines.join('\n')); + return ast; + + function dumpRule(rule) { + var lines = []; + + for (var i = 0; i < rule.selectors.length; ++i) { + var selector = rule.selectors[i]; + lines.push(`selector ${i}: "${selector.text}"`); + var selectorLines = dumpTextNode(selector); + lines = lines.concat(indent(selectorLines)); + } + + for (var i = 0; i < rule.properties.length; ++i) { + var property = rule.properties[i]; + lines.push('property ' + i); + var propertyLines = dumpProperty(property); + lines = lines.concat(indent(propertyLines)); + } + + return lines; + } + + function dumpProperty(property) { + var lines = []; + lines.push(String.sprintf('name: "%s"', property.name.text)); + lines = lines.concat(indent(dumpTextNode(property.name))); + lines.push(String.sprintf('value: "%s"', property.value.text)); + lines = lines.concat(indent(dumpTextNode(property.value))); + lines.push(String.sprintf('range: %s', property.range.toString())); + lines.push(String.sprintf('disabled: %s', property.disabled)); + return lines; + } + + function dumpTextNode(textNode) { + return [String.sprintf('range: %s', textNode.range.toString())]; + } +}; + +function indent(lines) { + return lines.map(line => ' ' + line); +} + +SASSTestRunner.dumpASTDiff = function(diff) { + TestRunner.addResult('=== Diff ==='); + var changesPerRule = new Map(); + + for (var change of diff.changes) { + var oldRule = change.oldRule; + var ruleChanges = changesPerRule.get(oldRule); + + if (!ruleChanges) { + ruleChanges = []; + changesPerRule.set(oldRule, ruleChanges); + } + + ruleChanges.push(change); + } + + var T = Sass.SASSSupport.PropertyChangeType; + + for (var rule of changesPerRule.keys()) { + var changes = changesPerRule.get(rule); + var names = []; + var values = []; + + for (var property of rule.properties) { + names.push(str(property.name, ' ')); + values.push(str(property.value)); + } + + for (var i = changes.length - 1; i >= 0; --i) { + var change = changes[i]; + var newProperty = change.newRule.properties[change.newPropertyIndex]; + var oldProperty = change.oldRule.properties[change.oldPropertyIndex]; + + switch (change.type) { + case T.PropertyAdded: + names.splice(change.oldPropertyIndex, 0, str(newProperty.name, '[+] ')); + values.splice(change.oldPropertyIndex, 0, str(newProperty.value)); + break; + case T.PropertyRemoved: + names[change.oldPropertyIndex] = str(oldProperty.name, '[-] '); + break; + case T.PropertyToggled: + names[change.oldPropertyIndex] = str(oldProperty.name, '[T] '); + break; + case T.NameChanged: + names[change.oldPropertyIndex] = str(oldProperty.name, '[M] '); + break; + case T.ValueChanged: + values[change.oldPropertyIndex] = str(oldProperty.value, '[M] '); + break; + } + } + + var selectorText = rule.selectors.map(selector => selector.text).join(','); + TestRunner.addResult('Changes for rule: ' + selectorText); + names = indent(names); + + for (var i = 0; i < names.length; ++i) + TestRunner.addResult(names[i] + ': ' + values[i]); + } + + function str(node, prefix) { + prefix = prefix || ''; + return prefix + node.text.trim(); + } +}; + +SASSTestRunner.validateASTRanges = function(ast) { + var invalidNodes = []; + + for (var rule of ast.rules) { + for (var property of rule.properties) { + validate(property.name); + validate(property.value); + } + } + + if (invalidNodes.length) { + TestRunner.addResult('Bad ranges: ' + invalidNodes.length); + + for (var node of invalidNodes) + TestRunner.addResult(String.sprintf(' - range: %s text: %s', node.range.toString(), node.text)); + } else { + TestRunner.addResult('Ranges OK.'); + } + + return ast; + + function validate(textNode) { + if (textNode.document.text.extract(textNode.range) !== textNode.text) + invalidNodes.push(textNode); + } +}; + +SASSTestRunner.validateMapping = function(mapping) { + TestRunner.addResult('Mapped CSS: ' + mapping._compiledToSource.size); + TestRunner.addResult('Mapped SCSS: ' + mapping._sourceToCompiled.size); + var cssNodes = mapping._compiledToSource.keysArray(); + var staleCSS = 0; + var staleSASS = 0; + + for (var i = 0; i < cssNodes.length; ++i) { + var cssNode = cssNodes[i]; + staleCSS += (cssNode.document !== mapping.compiledModel().document ? 1 : 0); + var sassNode = mapping.toSourceNode(cssNode); + var sassAST = mapping.sourceModels().get(sassNode.document.url); + staleSASS += (sassNode.document !== sassAST.document ? 1 : 0); + } + + if (staleCSS || staleSASS) { + TestRunner.addResult('ERROR: found stale entries'); + TestRunner.addResult(' -stale CSS: ' + staleCSS); + TestRunner.addResult(' -stale SASS: ' + staleSASS); + } else { + TestRunner.addResult('No stale entries found.'); + } +}; + +SASSTestRunner.updateCSSText = function(url, newText) { + var styleSheetIds = TestRunner.cssModel.styleSheetIdsForURL(url); + var promises = styleSheetIds.map(id => TestRunner.cssModel.setStyleSheetText(id, newText, true)); + return Promise.all(promises); +}; + +SASSTestRunner.updateSASSText = function(url, newText) { + var uiSourceCode = Workspace.workspace.uiSourceCodeForURL(url); + uiSourceCode.addRevision(newText); +}; + +SASSTestRunner.runCSSEditTests = function(header, tests) { + var astSourceMap; + SASSTestRunner.loadASTMapping(header, onMapping); + + function onMapping(map) { + astSourceMap = map; + TestRunner.addResult('INITIAL MODELS'); + logASTText(map.compiledModel(), true); + + for (var ast of map.sourceModels().values()) + logASTText(ast, true); + + runTests(); + } + + function runTests() { + if (!tests.length) { + TestRunner.completeTest(); + return; + } + + var test = tests.shift(); + logTestName(test.name); + var text = astSourceMap.compiledModel().document.text.value(); + var edits = test(text); + logSourceEdits(text, edits); + var ranges = edits.map(edit => edit.oldRange); + var texts = edits.map(edit => edit.newText); + astSourceMap.editCompiled(ranges, texts).then(onEditsDone); + } + + function onEditsDone(result) { + if (!result.map) { + TestRunner.addResult('SASSProcessor failed to process edits.'); + runTests(); + return; + } + + logASTText(result.map.compiledModel()); + + for (var sassURL of result.newSources.keys()) { + var ast = result.map.sourceModels().get(sassURL); + logASTText(ast); + } + + runTests(); + } + + function logASTText(ast, avoidIndent, customTitle) { + customTitle = customTitle || ast.document.url.split('/').pop(); + TestRunner.addResult('===== ' + customTitle + ' ====='); + var text = ast.document.text.value().replace(/ /g, '.'); + var lines = text.split('\n'); + + if (!avoidIndent) + lines = indent(lines); + + TestRunner.addResult(lines.join('\n')); + } + + function logTestName(testName) { + var titleText = ' TEST: ' + testName + ' '; + var totalLength = 80; + var prefixLength = (totalLength - titleText.length) / 2 | 0; + var suffixLength = totalLength - titleText.length - prefixLength; + var prefix = new Array(prefixLength).join('-'); + var suffix = new Array(suffixLength).join('-'); + TestRunner.addResult('\n' + prefix + titleText + suffix + '\n'); + } + + function logSourceEdits(text, edits) { + var lines = []; + + for (var i = 0; i < edits.length; ++i) { + var edit = edits[i]; + var range = edit.oldRange; + var line = String.sprintf('{%d, %d, %d, %d}', range.startLine, range.startColumn, range.endLine, range.endColumn); + line += String.sprintf(' \'%s\' => \'%s\'', new TextUtils.Text(text).extract(range), edit.newText); + lines.push(line); + } + + lines = indent(lines); + lines.unshift('Edits:'); + TestRunner.addResult(lines.join('\n')); + } +}; + +SASSTestRunner.createEdit = function(source, pattern, newText, matchNumber) { + matchNumber = matchNumber || 0; + var re = new RegExp(pattern.escapeForRegExp(), 'g'); + var match; + + while ((match = re.exec(source)) !== null && matchNumber) + --matchNumber; + + + if (!match) + return null; + + var sourceRange = new TextUtils.SourceRange(match.index, match[0].length); + var textRange = new TextUtils.Text(source).toTextRange(sourceRange); + return new TextUtils.SourceEdit('', textRange, newText); +};
diff --git a/third_party/WebKit/Source/devtools/front_end/sass_test_runner/module.json b/third_party/WebKit/Source/devtools/front_end/sass_test_runner/module.json new file mode 100644 index 0000000..3aace150 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/sass_test_runner/module.json
@@ -0,0 +1,13 @@ +{ + "dependencies": [ + "test_runner", + "integration_test_runner", + "sass" + ], + "scripts": [ + "SASSTestRunner.js" + ], + "skip_compilation": [ + "SASSTestRunner.js" + ] +}
diff --git a/third_party/WebKit/Source/devtools/front_end/security/SecurityModel.js b/third_party/WebKit/Source/devtools/front_end/security/SecurityModel.js index 411c70d..a90a173 100644 --- a/third_party/WebKit/Source/devtools/front_end/security/SecurityModel.js +++ b/third_party/WebKit/Source/devtools/front_end/security/SecurityModel.js
@@ -58,10 +58,6 @@ return aScore - bScore; } - - showCertificateViewer() { - this._securityAgent.showCertificateViewer(); - } }; SDK.SDKModel.register(Security.SecurityModel, SDK.Target.Capability.Security, false);
diff --git a/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js b/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js index 3407caa..1cb04de 100644 --- a/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js +++ b/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js
@@ -38,37 +38,27 @@ /** * @param {string} text - * @param {!Security.SecurityPanel} panel + * @param {string} origin * @return {!Element} */ - static createCertificateViewerButton(text, panel) { - /** - * @param {!Event} e - */ - function showCertificateViewer(e) { + static createCertificateViewerButtonForOrigin(text, origin) { + return UI.createTextButton(text, async e => { e.consume(); - panel.showCertificateViewer(); - } - - return UI.createTextButton(text, showCertificateViewer, 'security-certificate-button'); + var names = await SDK.multitargetNetworkManager.getCertificate(origin); + InspectorFrontendHost.showCertificateViewer(names); + }, 'security-certificate-button'); } /** * @param {string} text - * @param {string} origin + * @param {!Array<string>} names * @return {!Element} */ - static createCertificateViewerButton2(text, origin) { - /** - * @param {!Event} e - */ - function showCertificateViewer(e) { + static createCertificateViewerButtonForCert(text, names) { + return UI.createTextButton(text, e => { e.consume(); - SDK.multitargetNetworkManager.getCertificate(origin).then( - names => InspectorFrontendHost.showCertificateViewer(names)); - } - - return UI.createTextButton(text, showCertificateViewer, 'security-certificate-button'); + InspectorFrontendHost.showCertificateViewer(names); + }, 'security-certificate-button'); } /** @@ -258,10 +248,6 @@ return this._filterRequestCounts.get(filterKey) || 0; } - showCertificateViewer() { - this._securityModel.showCertificateViewer(); - } - /** * @param {!Protocol.Security.SecurityState} stateA * @param {!Protocol.Security.SecurityState} stateB @@ -614,11 +600,10 @@ text.createChild('div', 'security-explanation-title').textContent = explanation.summary; text.createChild('div').textContent = explanation.description; - if (explanation.hasCertificate) { - text.appendChild( - Security.SecurityPanel.createCertificateViewerButton(Common.UIString('View certificate'), this._panel)); + if (explanation.certificate.length) { + text.appendChild(Security.SecurityPanel.createCertificateViewerButtonForCert( + Common.UIString('View certificate'), explanation.certificate)); } - return text; } @@ -682,10 +667,11 @@ if (this._panel.filterRequestCount(Network.NetworkLogView.MixedContentFilterValues.Blocked) > 0) { var explanation = /** @type {!Protocol.Security.SecurityStateExplanation} */ ({ - 'securityState': Protocol.Security.SecurityState.Info, - 'summary': Common.UIString('Blocked mixed content'), - 'description': Common.UIString('Your page requested non-secure resources that were blocked.'), - 'mixedContentType': Protocol.Security.MixedContentType.Blockable + securityState: Protocol.Security.SecurityState.Info, + summary: Common.UIString('Blocked mixed content'), + description: Common.UIString('Your page requested non-secure resources that were blocked.'), + mixedContentType: Protocol.Security.MixedContentType.Blockable, + certificate: [] }); this._addMixedContentExplanation( this._securityExplanationsMain, explanation, Network.NetworkLogView.MixedContentFilterValues.Blocked); @@ -805,9 +791,11 @@ table.addRow(Common.UIString('Valid from'), validFromString); table.addRow(Common.UIString('Valid until'), validUntilString); table.addRow(Common.UIString('Issuer'), originState.securityDetails.issuer); + table.addRow( - '', Security.SecurityPanel.createCertificateViewerButton2( - Common.UIString('Open full certificate details'), origin)); + '', + Security.SecurityPanel.createCertificateViewerButtonForOrigin( + Common.UIString('Open full certificate details'), origin)); if (!originState.securityDetails.signedCertificateTimestampList.length) return;
diff --git a/third_party/WebKit/Source/devtools/front_end/security_test_runner/SecurityTestRunner.js b/third_party/WebKit/Source/devtools/front_end/security_test_runner/SecurityTestRunner.js new file mode 100644 index 0000000..b50fa77 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/security_test_runner/SecurityTestRunner.js
@@ -0,0 +1,28 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +SecurityTestRunner.dumpSecurityPanelSidebarOrigins = function() { + for (var key in Security.SecurityPanelSidebarTree.OriginGroupName) { + var originGroupName = Security.SecurityPanelSidebarTree.OriginGroupName[key]; + var originGroup = Security.SecurityPanel._instance()._sidebarTree._originGroups.get(originGroupName); + + if (originGroup.hidden) + continue; + + TestRunner.addResult('Group: ' + originGroupName); + var originTitles = originGroup.childrenListElement.getElementsByClassName('title'); + + for (var originTitle of originTitles) + TestRunner.dumpDeepInnerHTML(originTitle); + } +}; + +SecurityTestRunner.dispatchRequestFinished = function(request) { + TestRunner.networkManager.dispatchEventToListeners(SDK.NetworkManager.Events.RequestFinished, request); +};
diff --git a/third_party/WebKit/Source/devtools/front_end/security_test_runner/module.json b/third_party/WebKit/Source/devtools/front_end/security_test_runner/module.json new file mode 100644 index 0000000..20d36679 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/security_test_runner/module.json
@@ -0,0 +1,13 @@ +{ + "dependencies": [ + "test_runner", + "integration_test_runner", + "security" + ], + "scripts": [ + "SecurityTestRunner.js" + ], + "skip_compilation": [ + "SecurityTestRunner.js" + ] +}
diff --git a/third_party/WebKit/Source/devtools/front_end/sources_test_runner/AutocompleteTestRunner.js b/third_party/WebKit/Source/devtools/front_end/sources_test_runner/AutocompleteTestRunner.js new file mode 100644 index 0000000..8a71653 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/sources_test_runner/AutocompleteTestRunner.js
@@ -0,0 +1,42 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +SourcesTestRunner.dumpSuggestions = function(textEditor, lines) { + var resolve; + var promise = new Promise(fulfill => resolve = fulfill); + var lineNumber = -1, columnNumber; + + for (var i = 0; i < lines.length; ++i) { + var columnNumber = lines[i].indexOf('|'); + + if (columnNumber !== -1) { + lineNumber = i; + break; + } + } + + if (lineNumber === -1) + throw new Error('Test case is invalid: cursor position is not marked with \'|\' symbol.'); + + textEditor.setText(lines.join('\n').replace('|', '')); + textEditor.setSelection(TextUtils.TextRange.createFromLocation(lineNumber, columnNumber)); + TestRunner.addSniffer( + TextEditor.TextEditorAutocompleteController.prototype, '_onSuggestionsShownForTest', suggestionsShown); + textEditor._autocompleteController.autocomplete(); + + function suggestionsShown(words) { + TestRunner.addResult('========= Selection In Editor ========='); + SourcesTestRunner.dumpTextWithSelection(textEditor); + TestRunner.addResult('======= Autocomplete Suggestions ======='); + TestRunner.addResult('[' + words.map(item => item.text).join(', ') + ']'); + resolve(); + } + + return promise; +};
diff --git a/third_party/WebKit/Source/devtools/front_end/sources_test_runner/BreakpointManagerTestRunner.js b/third_party/WebKit/Source/devtools/front_end/sources_test_runner/BreakpointManagerTestRunner.js new file mode 100644 index 0000000..88aec2c --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/sources_test_runner/BreakpointManagerTestRunner.js
@@ -0,0 +1,430 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +SourcesTestRunner.createWorkspace = function() { + SourcesTestRunner.testTargetManager = new SDK.TargetManager(); + SourcesTestRunner.testWorkspace = new Workspace.Workspace(); + SourcesTestRunner.testNetworkProjectManager = + new Bindings.NetworkProjectManager(SourcesTestRunner.testTargetManager, SourcesTestRunner.testWorkspace); + SourcesTestRunner.testResourceMapping = + new Bindings.ResourceMapping(SourcesTestRunner.testTargetManager, SourcesTestRunner.testWorkspace); + SourcesTestRunner.testDebuggerWorkspaceBinding = + new Bindings.DebuggerWorkspaceBinding(SourcesTestRunner.testTargetManager, SourcesTestRunner.testWorkspace); + Bindings.resourceMapping = SourcesTestRunner.testResourceMapping; +}; + +function resourceMappingModelInfoForTarget(target) { + var resourceTreeModel = target.model(SDK.ResourceTreeModel); + var binding = (resourceTreeModel ? SourcesTestRunner.testResourceMapping._modelToInfo.get(resourceTreeModel) : null); + return binding; +} + +SourcesTestRunner.createMockTarget = function(id) { + var capabilities = SDK.Target.Capability.AllForTests; + + var target = SourcesTestRunner.testTargetManager.createTarget( + 'mock-target-id-' + id, 'mock-target-' + id, capabilities & ~SDK.Target.Capability.JS, + params => new SDK.StubConnection(params), null); + + SourcesTestRunner.testNetworkProject = Bindings.NetworkProject.forTarget(target); + SourcesTestRunner.testResourceMappingModelInfo = resourceMappingModelInfoForTarget(target); + target._capabilitiesMask = capabilities; + target._inspectedURL = TestRunner.mainTarget.inspectedURL(); + target.resourceTreeModel = target.model(SDK.ResourceTreeModel); + target.resourceTreeModel._cachedResourcesProcessed = true; + target.resourceTreeModel._frameAttached('42', 0); + target.runtimeModel = target.model(SDK.RuntimeModel); + target.debuggerModel = new SourcesTestRunner.DebuggerModelMock(target); + target._modelByConstructor.set(SDK.DebuggerModel, target.debuggerModel); + SourcesTestRunner.testTargetManager.modelAdded(target, SDK.DebuggerModel, target.debuggerModel); + return target; +}; + +SourcesTestRunner.uiSourceCodes = {}; + +SourcesTestRunner.initializeDefaultMappingOnTarget = function(target) { + var defaultMapping = { + rawLocationToUILocation: function(rawLocation) { + return null; + }, + + uiLocationToRawLocation: function(uiSourceCode, lineNumber) { + if (!SourcesTestRunner.uiSourceCodes[uiSourceCode.url()]) + return null; + + return new SDK.DebuggerModel.Location(target.debuggerModel, uiSourceCode.url(), lineNumber, 0); + }, + + isIdentity: function() { + return true; + } + }; + + target.defaultMapping = defaultMapping; +}; + +SourcesTestRunner.DebuggerModelMock = class extends SDK.SDKModel { + sourceMapManager() { + return this._sourceMapManager; + } + + constructor(target) { + super(target); + this._sourceMapManager = new SDK.SourceMapManager(); + this._target = target; + this._breakpointResolvedEventTarget = new Common.Object(); + this._scripts = {}; + this._breakpoints = {}; + this._debuggerWorkspaceBinding = SourcesTestRunner.testDebuggerWorkspaceBinding; + } + + target() { + return this._target; + } + + runtimeModel() { + return this._target.runtimeModel; + } + + setBeforePausedCallback(callback) { + } + + debuggerEnabled() { + return true; + } + + scriptsForSourceURL(url) { + var script = this._scriptForURL(url); + return (script ? [script] : []); + } + + _addScript(scriptId, url) { + var script = new SDK.Script(this, scriptId, url); + this._scripts[scriptId] = script; + var modelData = this._debuggerWorkspaceBinding._debuggerModelToData.get(this); + + modelData._defaultMapping._parsedScriptSource({data: script}); + + modelData._resourceMapping._parsedScriptSource({data: script}); + } + + _scriptForURL(url) { + for (var scriptId in this._scripts) { + var script = this._scripts[scriptId]; + + if (script.sourceURL === url) + return script; + } + } + + _scheduleSetBeakpointCallback(callback, breakpointId, locations) { + setTimeout(innerCallback.bind(this), 0); + + function innerCallback() { + if (callback) + callback(breakpointId, locations); + + if (window.setBreakpointCallback) { + var savedCallback = window.setBreakpointCallback; + delete window.setBreakpointCallback; + savedCallback(); + } + } + } + + createRawLocation(script, line, column) { + return new SDK.DebuggerModel.Location(this, script.scriptId, line, column); + } + + createRawLocationByURL(url, line, column) { + var script = this._scriptForURL(url); + + if (!script) + return null; + + return new SDK.DebuggerModel.Location(this, script.scriptId, line, column); + } + + setBreakpointByURL(url, lineNumber, columnNumber, condition, callback) { + TestRunner.addResult(' debuggerModel.setBreakpoint(' + [url, lineNumber, condition].join(':') + ')'); + var breakpointId = url + ':' + lineNumber; + + if (this._breakpoints[breakpointId]) { + this._scheduleSetBeakpointCallback(callback, null); + return; + } + + this._breakpoints[breakpointId] = true; + + if (lineNumber >= 2000) { + this._scheduleSetBeakpointCallback(callback, breakpointId, []); + return; + } + + if (lineNumber >= 1000) { + var shiftedLocation = new SDK.DebuggerModel.Location(this, url, lineNumber + 10, columnNumber); + this._scheduleSetBeakpointCallback(callback, breakpointId, [shiftedLocation]); + return; + } + + var locations = []; + var script = this._scriptForURL(url); + + if (script) { + var location = new SDK.DebuggerModel.Location(this, script.scriptId, lineNumber, 0); + locations.push(location); + } + + this._scheduleSetBeakpointCallback(callback, breakpointId, locations); + } + + async removeBreakpoint(breakpointId) { + TestRunner.addResult(' debuggerModel.removeBreakpoint(' + breakpointId + ')'); + delete this._breakpoints[breakpointId]; + } + + setBreakpointsActive() { + } + + scriptForId(scriptId) { + return this._scripts[scriptId]; + } + + reset() { + TestRunner.addResult(' Resetting debugger.'); + this._scripts = {}; + this._debuggerWorkspaceBinding._reset(this); + } + + addBreakpointListener(breakpointId, listener, thisObject) { + this._breakpointResolvedEventTarget.addEventListener(breakpointId, listener, thisObject); + } + + removeBreakpointListener(breakpointId, listener, thisObject) { + this._breakpointResolvedEventTarget.removeEventListener(breakpointId, listener, thisObject); + } + + _breakpointResolved(breakpointId, location) { + this._breakpointResolvedEventTarget.dispatchEventToListeners(breakpointId, location); + } +}; + +SourcesTestRunner.setupLiveLocationSniffers = function() { + TestRunner.addSniffer(Bindings.DebuggerWorkspaceBinding.prototype, 'createLiveLocation', function(rawLocation) { + TestRunner.addResult(' Location created: ' + rawLocation.scriptId + ':' + rawLocation.lineNumber); + }, true); + + TestRunner.addSniffer(Bindings.DebuggerWorkspaceBinding.Location.prototype, 'dispose', function() { + TestRunner.addResult(' Location disposed: ' + this._rawLocation.scriptId + ':' + this._rawLocation.lineNumber); + }, true); +}; + +SourcesTestRunner.addScript = function(target, breakpointManager, url) { + target.debuggerModel._addScript(url, url); + TestRunner.addResult(' Adding script: ' + url); +}; + +SourcesTestRunner.addUISourceCode = function(target, breakpointManager, url, doNotSetSourceMapping, doNotAddScript) { + if (!doNotAddScript) + SourcesTestRunner.addScript(target, breakpointManager, url); + + TestRunner.addResult(' Adding UISourceCode: ' + url); + var resourceMappingModelInfo = resourceMappingModelInfoForTarget(target); + + if (resourceMappingModelInfo._bindings.has(url)) { + resourceMappingModelInfo._bindings.get(url).dispose(); + resourceMappingModelInfo._bindings.delete(url); + } + + var resource = + new SDK.Resource(target, null, url, url, '', '', Common.resourceTypes.Document, 'text/html', null, null); + + resourceMappingModelInfo._resourceAdded({data: resource}); + + uiSourceCode = SourcesTestRunner.testWorkspace.uiSourceCodeForURL(url); + SourcesTestRunner.uiSourceCodes[url] = uiSourceCode; + + if (!doNotSetSourceMapping) + breakpointManager._debuggerWorkspaceBinding.updateLocations(target.debuggerModel.scriptForId(url)); + + + return uiSourceCode; +}; + +SourcesTestRunner.createBreakpointManager = function(targetManager, debuggerWorkspaceBinding, persistentBreakpoints) { + SourcesTestRunner._pendingBreakpointUpdates = 0; + TestRunner.addSniffer( + Bindings.BreakpointManager.ModelBreakpoint.prototype, '_updateInDebugger', updateInDebugger, true); + TestRunner.addSniffer( + Bindings.BreakpointManager.ModelBreakpoint.prototype, '_didUpdateInDebugger', didUpdateInDebugger, true); + + function updateInDebugger() { + SourcesTestRunner._pendingBreakpointUpdates++; + } + + function didUpdateInDebugger() { + SourcesTestRunner._pendingBreakpointUpdates--; + SourcesTestRunner._notifyAfterBreakpointUpdate(); + } + + persistentBreakpoints = persistentBreakpoints || []; + + var setting = { + get: function() { + return persistentBreakpoints; + }, + + set: function(breakpoints) { + persistentBreakpoints = breakpoints; + } + }; + + function breakpointAdded(event) { + var breakpoint = event.data.breakpoint; + var uiLocation = event.data.uiLocation; + + TestRunner.addResult(' breakpointAdded(' + [ + uiLocation.uiSourceCode.url(), uiLocation.lineNumber, uiLocation.columnNumber, breakpoint.condition(), + breakpoint.enabled() + ].join(', ') + ')'); + } + + function breakpointRemoved(event) { + var uiLocation = event.data.uiLocation; + + TestRunner.addResult(' breakpointRemoved(' + [ + uiLocation.uiSourceCode.url(), uiLocation.lineNumber, uiLocation.columnNumber + ].join(', ') + ')'); + } + + var targets = targetManager.targets(); + var mappingForManager; + + for (var i = 0; i < targets.length; ++i) { + SourcesTestRunner.initializeDefaultMappingOnTarget(targets[i]); + + if (!mappingForManager) + mappingForManager = targets[i].defaultMapping; + } + + var breakpointManager = new Bindings.BreakpointManager( + setting, debuggerWorkspaceBinding._workspace, targetManager, debuggerWorkspaceBinding); + breakpointManager.defaultMapping = mappingForManager; + breakpointManager.addEventListener(Bindings.BreakpointManager.Events.BreakpointAdded, breakpointAdded); + breakpointManager.addEventListener(Bindings.BreakpointManager.Events.BreakpointRemoved, breakpointRemoved); + TestRunner.addResult(' Created breakpoints manager'); + SourcesTestRunner.dumpBreakpointStorage(breakpointManager); + return breakpointManager; +}; + +SourcesTestRunner.setBreakpoint = function( + breakpointManager, uiSourceCode, lineNumber, columnNumber, condition, enabled, setBreakpointCallback) { + TestRunner.addResult( + ' Setting breakpoint at ' + uiSourceCode.url() + ':' + lineNumber + ':' + columnNumber + ' enabled:' + enabled + + ' condition:' + condition); + + if (setBreakpointCallback) + window.setBreakpointCallback = setBreakpointCallback; + + return breakpointManager.setBreakpoint(uiSourceCode, lineNumber, columnNumber, condition, enabled); +}; + +SourcesTestRunner.removeBreakpoint = function(breakpointManager, uiSourceCode, lineNumber, columnNumber) { + TestRunner.addResult(' Removing breakpoint at ' + uiSourceCode.url() + ':' + lineNumber + ':' + columnNumber); + breakpointManager.findBreakpoint(uiSourceCode, lineNumber, columnNumber).remove(); +}; + +SourcesTestRunner.dumpBreakpointStorage = function(breakpointManager) { + var breakpoints = breakpointManager._storage._setting.get(); + TestRunner.addResult(' Dumping Storage'); + + for (var i = 0; i < breakpoints.length; ++i) { + TestRunner.addResult( + ' ' + breakpoints[i].url + ':' + breakpoints[i].lineNumber + ' enabled:' + breakpoints[i].enabled + + ' condition:' + breakpoints[i].condition); + } +}; + +SourcesTestRunner.dumpBreakpointLocations = function(breakpointManager) { + var allBreakpointLocations = breakpointManager.allBreakpointLocations(); + TestRunner.addResult(' Dumping Breakpoint Locations'); + var lastUISourceCode = null; + var locations = []; + + function dumpLocations(uiSourceCode, locations) { + locations.sort(function(a, b) { + return a.lineNumber - b.lineNumber; + }); + + TestRunner.addResult(' UISourceCode (url=\'' + uiSourceCode.url() + '\', uri=\'' + uiSourceCode.url() + '\')'); + + for (var i = 0; i < locations.length; ++i) + TestRunner.addResult(' Location: (' + locations[i].lineNumber + ', ' + locations[i].columnNumber + ')'); + } + + for (var i = 0; i < allBreakpointLocations.length; ++i) { + var uiLocation = allBreakpointLocations[i].uiLocation; + var uiSourceCode = uiLocation.uiSourceCode; + + if (lastUISourceCode && lastUISourceCode !== uiSourceCode) { + dumpLocations(uiSourceCode, locations); + locations = []; + } + + lastUISourceCode = uiSourceCode; + locations.push(uiLocation); + } + + if (lastUISourceCode) + dumpLocations(lastUISourceCode, locations); +}; + +SourcesTestRunner.resetBreakpointManager = function(breakpointManager, next) { + TestRunner.addResult(' Resetting breakpoint manager'); + breakpointManager.removeAllBreakpoints(); + breakpointManager.removeProvisionalBreakpointsForTest(); + SourcesTestRunner.uiSourceCodes = {}; + next(); +}; + +SourcesTestRunner.runAfterPendingBreakpointUpdates = function(breakpointManager, callback) { + SourcesTestRunner._pendingBreakpointUpdatesCallback = callback; + SourcesTestRunner._notifyAfterBreakpointUpdate(); +}; + +SourcesTestRunner._notifyAfterBreakpointUpdate = function() { + if (!SourcesTestRunner._pendingBreakpointUpdates && SourcesTestRunner._pendingBreakpointUpdatesCallback) { + var callback = SourcesTestRunner._pendingBreakpointUpdatesCallback; + delete SourcesTestRunner._pendingBreakpointUpdatesCallback; + callback(); + } +}; + +SourcesTestRunner.finishBreakpointTest = function(breakpointManager, next) { + SourcesTestRunner.runAfterPendingBreakpointUpdates(breakpointManager, dump); + + function dump() { + SourcesTestRunner.dumpBreakpointLocations(breakpointManager); + SourcesTestRunner.dumpBreakpointStorage(breakpointManager); + SourcesTestRunner.runAfterPendingBreakpointUpdates(breakpointManager, reset); + } + + function reset() { + SourcesTestRunner.resetBreakpointManager(breakpointManager, didReset); + } + + function didReset() { + SourcesTestRunner.runAfterPendingBreakpointUpdates(breakpointManager, finish); + } + + function finish() { + SourcesTestRunner.dumpBreakpointLocations(breakpointManager); + next(); + } +};
diff --git a/third_party/WebKit/Source/devtools/front_end/sources_test_runner/DebuggerTestRunner.js b/third_party/WebKit/Source/devtools/front_end/sources_test_runner/DebuggerTestRunner.js new file mode 100644 index 0000000..3f52c02 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/sources_test_runner/DebuggerTestRunner.js
@@ -0,0 +1,757 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +SourcesTestRunner.startDebuggerTest = function(callback, quiet) { + console.assert(TestRunner.debuggerModel.debuggerEnabled(), 'Debugger has to be enabled'); + + if (quiet !== undefined) + SourcesTestRunner._quiet = quiet; + + UI.viewManager.showView('sources'); + TestRunner.addSniffer(SDK.DebuggerModel.prototype, '_pausedScript', SourcesTestRunner._pausedScript, true); + TestRunner.addSniffer(SDK.DebuggerModel.prototype, '_resumedScript', SourcesTestRunner._resumedScript, true); + TestRunner.safeWrap(callback)(); +}; + +SourcesTestRunner.startDebuggerTestPromise = function(quiet) { + var cb; + var p = new Promise(fullfill => cb = fullfill); + SourcesTestRunner.startDebuggerTest(cb, quiet); + return p; +}; + +SourcesTestRunner.completeDebuggerTest = function() { + Bindings.breakpointManager.setBreakpointsActive(true); + SourcesTestRunner.resumeExecution(TestRunner.completeTest.bind(TestRunner)); +}; + +(function() { +var origThen = Promise.prototype.then; +var origCatch = Promise.prototype.catch; + +Promise.prototype.then = function() { + var result = origThen.apply(this, arguments); + origThen.call(result, undefined, onUncaughtPromiseReject.bind(null, new Error().stack)); + return result; +}; + +Promise.prototype.catch = function() { + var result = origCatch.apply(this, arguments); + origThen.call(result, undefined, onUncaughtPromiseReject.bind(null, new Error().stack)); + return result; +}; + +function onUncaughtPromiseReject(stack, e) { + var message = typeof e === 'object' && e.stack || e; + TestRunner.addResult('FAIL: Uncaught exception in promise: ' + message + ' ' + stack); + SourcesTestRunner.completeDebuggerTest(); +} +})(); + +SourcesTestRunner.runDebuggerTestSuite = function(testSuite) { + var testSuiteTests = testSuite.slice(); + + function runner() { + if (!testSuiteTests.length) { + SourcesTestRunner.completeDebuggerTest(); + return; + } + + var nextTest = testSuiteTests.shift(); + TestRunner.addResult(''); + TestRunner.addResult( + 'Running: ' + + /function\s([^(]*)/.exec(nextTest)[1]); + TestRunner.safeWrap(nextTest)(runner, runner); + } + + SourcesTestRunner.startDebuggerTest(runner); +}; + +SourcesTestRunner.runTestFunction = function() { + TestRunner.evaluateInPage('scheduleTestFunction()'); + TestRunner.addResult('Set timer for test function.'); +}; + +SourcesTestRunner.runTestFunctionAndWaitUntilPaused = function(callback) { + SourcesTestRunner.runTestFunction(); + SourcesTestRunner.waitUntilPaused(callback); +}; + +SourcesTestRunner.runTestFunctionAndWaitUntilPausedPromise = function() { + return new Promise(SourcesTestRunner.runTestFunctionAndWaitUntilPaused); +}; + +SourcesTestRunner.runAsyncCallStacksTest = function(totalDebuggerStatements, maxAsyncCallStackDepth) { + var defaultMaxAsyncCallStackDepth = 32; + SourcesTestRunner.setQuiet(true); + SourcesTestRunner.startDebuggerTest(step1); + + async function step1() { + await TestRunner.DebuggerAgent.setAsyncCallStackDepth(maxAsyncCallStackDepth || defaultMaxAsyncCallStackDepth); + SourcesTestRunner.runTestFunctionAndWaitUntilPaused(didPause); + } + + var step = 0; + var callStacksOutput = []; + + function didPause(callFrames, reason, breakpointIds, asyncStackTrace) { + ++step; + callStacksOutput.push(SourcesTestRunner.captureStackTraceIntoString(callFrames, asyncStackTrace) + '\n'); + + if (step < totalDebuggerStatements) { + SourcesTestRunner.resumeExecution(SourcesTestRunner.waitUntilPaused.bind(SourcesTestRunner, didPause)); + } else { + TestRunner.addResult('Captured call stacks in no particular order:'); + callStacksOutput.sort(); + TestRunner.addResults(callStacksOutput); + SourcesTestRunner.completeDebuggerTest(); + } + } +}; + +SourcesTestRunner.dumpSourceFrameMessages = function(sourceFrame, dumpFullURL) { + var messages = []; + + for (var bucket of sourceFrame._rowMessageBuckets.values()) { + for (var rowMessage of bucket._messages) { + var message = rowMessage.message(); + messages.push(String.sprintf( + ' %d:%d [%s] %s', message.lineNumber(), message.columnNumber(), message.level(), message.text())); + } + } + + var name = (dumpFullURL ? sourceFrame.uiSourceCode().url() : sourceFrame.uiSourceCode().displayName()); + TestRunner.addResult('SourceFrame ' + name + ': ' + messages.length + ' message(s)'); + TestRunner.addResult(messages.join('\n')); +}; + +SourcesTestRunner.waitUntilPausedNextTime = function(callback) { + SourcesTestRunner._waitUntilPausedCallback = TestRunner.safeWrap(callback); +}; + +SourcesTestRunner.waitUntilPaused = function(callback) { + callback = TestRunner.safeWrap(callback); + + if (SourcesTestRunner._pausedScriptArguments) + callback.apply(callback, SourcesTestRunner._pausedScriptArguments); + else + SourcesTestRunner._waitUntilPausedCallback = callback; +}; + +SourcesTestRunner.waitUntilPausedPromise = function() { + return new Promise(resolve => SourcesTestRunner.waitUntilPaused(resolve)); +}; + +SourcesTestRunner.waitUntilResumedNextTime = function(callback) { + SourcesTestRunner._waitUntilResumedCallback = TestRunner.safeWrap(callback); +}; + +SourcesTestRunner.waitUntilResumed = function(callback) { + callback = TestRunner.safeWrap(callback); + + if (!SourcesTestRunner._pausedScriptArguments) + callback(); + else + SourcesTestRunner._waitUntilResumedCallback = callback; +}; + +SourcesTestRunner.resumeExecution = function(callback) { + if (UI.panels.sources.paused()) + UI.panels.sources._togglePause(); + + SourcesTestRunner.waitUntilResumed(callback); +}; + +SourcesTestRunner.waitUntilPausedAndDumpStackAndResume = function(callback, options) { + SourcesTestRunner.waitUntilPaused(paused); + TestRunner.addSniffer(Sources.SourcesPanel.prototype, '_updateDebuggerButtonsAndStatus', setStatus); + var caption; + var callFrames; + var asyncStackTrace; + + function setStatus() { + var statusElement = this.element.querySelector('.paused-message'); + caption = statusElement.deepTextContent(); + + if (callFrames) + step1(); + } + + function paused(frames, reason, breakpointIds, async) { + callFrames = frames; + asyncStackTrace = async; + + if (typeof caption === 'string') + step1(); + } + + function step1() { + SourcesTestRunner.captureStackTrace(callFrames, asyncStackTrace, options); + TestRunner.addResult(TestRunner.clearSpecificInfoFromStackFrames(caption)); + TestRunner.deprecatedRunAfterPendingDispatches(step2); + } + + function step2() { + SourcesTestRunner.resumeExecution(TestRunner.safeWrap(callback)); + } +}; + +SourcesTestRunner.stepOver = function() { + Promise.resolve().then(function() { + UI.panels.sources._stepOver(); + }); +}; + +SourcesTestRunner.stepInto = function() { + Promise.resolve().then(function() { + UI.panels.sources._stepInto(); + }); +}; + +SourcesTestRunner.stepOut = function() { + Promise.resolve().then(function() { + UI.panels.sources._stepOut(); + }); +}; + +SourcesTestRunner.togglePause = function() { + Promise.resolve().then(function() { + UI.panels.sources._togglePause(); + }); +}; + +SourcesTestRunner.waitUntilPausedAndPerformSteppingActions = function(actions, callback) { + callback = TestRunner.safeWrap(callback); + SourcesTestRunner.waitUntilPaused(didPause); + + function didPause(callFrames, reason, breakpointIds, asyncStackTrace) { + var action = actions.shift(); + + if (action === 'Print') { + SourcesTestRunner.captureStackTrace(callFrames, asyncStackTrace); + TestRunner.addResult(''); + + while (action === 'Print') + action = actions.shift(); + } + + if (!action) { + callback(); + return; + } + + TestRunner.addResult('Executing ' + action + '...'); + + switch (action) { + case 'StepInto': + SourcesTestRunner.stepInto(); + break; + case 'StepOver': + SourcesTestRunner.stepOver(); + break; + case 'StepOut': + SourcesTestRunner.stepOut(); + break; + case 'Resume': + SourcesTestRunner.togglePause(); + break; + default: + TestRunner.addResult('FAIL: Unknown action: ' + action); + callback(); + return; + } + + SourcesTestRunner.waitUntilResumed( + (actions.length ? SourcesTestRunner.waitUntilPaused.bind(SourcesTestRunner, didPause) : callback)); + } +}; + +SourcesTestRunner.captureStackTrace = function(callFrames, asyncStackTrace, options) { + TestRunner.addResult(SourcesTestRunner.captureStackTraceIntoString(callFrames, asyncStackTrace, options)); +}; + +SourcesTestRunner.captureStackTraceIntoString = function(callFrames, asyncStackTrace, options) { + var results = []; + options = options || {}; + + function printCallFrames(callFrames, locationFunction, returnValueFunction) { + var printed = 0; + + for (var i = 0; i < callFrames.length; i++) { + var frame = callFrames[i]; + var location = locationFunction.call(frame); + var script = location.script(); + var uiLocation = Bindings.debuggerWorkspaceBinding.rawLocationToUILocation(location); + var isFramework = Bindings.blackboxManager.isBlackboxedRawLocation(location); + + if (options.dropFrameworkCallFrames && isFramework) + continue; + + var url; + var lineNumber; + + if (uiLocation && uiLocation.uiSourceCode.project().type() !== Workspace.projectTypes.Debugger) { + url = uiLocation.uiSourceCode.name(); + lineNumber = uiLocation.lineNumber + 1; + } else { + url = Bindings.displayNameForURL(script.sourceURL); + lineNumber = location.lineNumber + 1; + } + + var s = ((isFramework ? ' * ' : ' ')) + printed++ + ') ' + frame.functionName + ' (' + url + + ((options.dropLineNumbers ? '' : ':' + lineNumber)) + ')'; + results.push(s); + + if (options.printReturnValue && returnValueFunction && returnValueFunction.call(frame)) + results.push(' <return>: ' + returnValueFunction.call(frame).description); + + if (frame.functionName === 'scheduleTestFunction') { + var remainingFrames = callFrames.length - 1 - i; + + if (remainingFrames) + results.push(' <... skipped remaining frames ...>'); + + break; + } + } + + return printed; + } + + function runtimeCallFramePosition() { + return new SDK.DebuggerModel.Location(debuggerModel, this.scriptId, this.lineNumber, this.columnNumber); + } + + results.push('Call stack:'); + printCallFrames( + callFrames, SDK.DebuggerModel.CallFrame.prototype.location, SDK.DebuggerModel.CallFrame.prototype.returnValue); + + while (asyncStackTrace) { + results.push(' [' + (asyncStackTrace.description || 'Async Call') + ']'); + var debuggerModel = TestRunner.debuggerModel; + var printed = printCallFrames(asyncStackTrace.callFrames, runtimeCallFramePosition); + + if (!printed) + results.pop(); + + asyncStackTrace = asyncStackTrace.parent; + } + + return results.join('\n'); +}; + +SourcesTestRunner.dumpSourceFrameContents = function(sourceFrame) { + TestRunner.addResult('==Source frame contents start=='); + var textEditor = sourceFrame._textEditor; + + for (var i = 0; i < textEditor.linesCount; ++i) + TestRunner.addResult(textEditor.line(i)); + + TestRunner.addResult('==Source frame contents end=='); +}; + +SourcesTestRunner._pausedScript = function(callFrames, reason, auxData, breakpointIds, asyncStackTrace) { + if (!SourcesTestRunner._quiet) + TestRunner.addResult('Script execution paused.'); + + var debuggerModel = this.target().model(SDK.DebuggerModel); + SourcesTestRunner._pausedScriptArguments = [ + SDK.DebuggerModel.CallFrame.fromPayloadArray(debuggerModel, callFrames), reason, breakpointIds, asyncStackTrace, + auxData + ]; + + if (SourcesTestRunner._waitUntilPausedCallback) { + var callback = SourcesTestRunner._waitUntilPausedCallback; + delete SourcesTestRunner._waitUntilPausedCallback; + setTimeout(() => callback.apply(callback, SourcesTestRunner._pausedScriptArguments)); + } +}; + +SourcesTestRunner._resumedScript = function() { + if (!SourcesTestRunner._quiet) + TestRunner.addResult('Script execution resumed.'); + + delete SourcesTestRunner._pausedScriptArguments; + + if (SourcesTestRunner._waitUntilResumedCallback) { + var callback = SourcesTestRunner._waitUntilResumedCallback; + delete SourcesTestRunner._waitUntilResumedCallback; + callback(); + } +}; + +SourcesTestRunner.showUISourceCode = function(uiSourceCode, callback) { + var panel = UI.panels.sources; + panel.showUISourceCode(uiSourceCode); + var sourceFrame = panel.visibleView; + + if (sourceFrame.loaded) + callback(sourceFrame); + else + TestRunner.addSniffer(sourceFrame, 'onTextEditorContentSet', callback && callback.bind(null, sourceFrame)); +}; + +SourcesTestRunner.showUISourceCodePromise = function(uiSourceCode) { + var fulfill; + var promise = new Promise(x => fulfill = x); + SourcesTestRunner.showUISourceCode(uiSourceCode, fulfill); + return promise; +}; + +SourcesTestRunner.showScriptSource = function(scriptName, callback) { + SourcesTestRunner.waitForScriptSource(scriptName, onScriptSource); + + function onScriptSource(uiSourceCode) { + SourcesTestRunner.showUISourceCode(uiSourceCode, callback); + } +}; + +SourcesTestRunner.waitForScriptSource = function(scriptName, callback) { + var panel = UI.panels.sources; + var uiSourceCodes = panel._workspace.uiSourceCodes(); + + for (var i = 0; i < uiSourceCodes.length; ++i) { + if (uiSourceCodes[i].project().type() === Workspace.projectTypes.Service) + continue; + + if (uiSourceCodes[i].name() === scriptName) { + callback(uiSourceCodes[i]); + return; + } + } + + TestRunner.addSniffer( + Sources.SourcesView.prototype, '_addUISourceCode', + SourcesTestRunner.waitForScriptSource.bind(SourcesTestRunner, scriptName, callback)); +}; + +SourcesTestRunner.setBreakpoint = function(sourceFrame, lineNumber, condition, enabled) { + if (!sourceFrame._muted) + sourceFrame._setBreakpoint(lineNumber, 0, condition, enabled); +}; + +SourcesTestRunner.removeBreakpoint = function(sourceFrame, lineNumber) { + sourceFrame._breakpointManager.findBreakpoints(sourceFrame._uiSourceCode, lineNumber)[0].remove(); +}; + +SourcesTestRunner.createNewBreakpoint = function(sourceFrame, lineNumber, condition, enabled) { + var promise = + new Promise(resolve => TestRunner.addSniffer(sourceFrame.__proto__, '_breakpointWasSetForTest', resolve)); + sourceFrame._createNewBreakpoint(lineNumber, condition, enabled); + return promise; +}; + +SourcesTestRunner.toggleBreakpoint = function(sourceFrame, lineNumber, disableOnly) { + if (!sourceFrame._muted) + sourceFrame._toggleBreakpoint(lineNumber, disableOnly); +}; + +SourcesTestRunner.waitBreakpointSidebarPane = function(waitUntilResolved) { + return new Promise( + resolve => TestRunner.addSniffer( + Sources.JavaScriptBreakpointsSidebarPane.prototype, '_didUpdateForTest', resolve)) + .then(checkIfReady); + + function checkIfReady() { + if (!waitUntilResolved) + return; + + for (var breakpoint of Bindings.breakpointManager._allBreakpoints()) { + if (breakpoint._fakePrimaryLocation && breakpoint.enabled()) + return SourcesTestRunner.waitBreakpointSidebarPane(); + } + } +}; + +SourcesTestRunner.breakpointsSidebarPaneContent = function() { + var paneElement = self.runtime.sharedInstance(Sources.JavaScriptBreakpointsSidebarPane).contentElement; + var empty = paneElement.querySelector('.gray-info-message'); + + if (empty) + return TestRunner.textContentWithLineBreaks(empty); + + var entries = Array.from(paneElement.querySelectorAll('.breakpoint-entry')); + return entries.map(TestRunner.textContentWithLineBreaks).join('\n'); +}; + +SourcesTestRunner.dumpBreakpointSidebarPane = function(title) { + TestRunner.addResult('Breakpoint sidebar pane ' + (title || '')); + TestRunner.addResult(SourcesTestRunner.breakpointsSidebarPaneContent()); +}; + +SourcesTestRunner.dumpScopeVariablesSidebarPane = function() { + TestRunner.addResult('Scope variables sidebar pane:'); + var sections = SourcesTestRunner.scopeChainSections(); + + for (var i = 0; i < sections.length; ++i) { + var textContent = TestRunner.textContentWithLineBreaks(sections[i].element); + var text = TestRunner.clearSpecificInfoFromStackFrames(textContent); + + if (text.length > 0) + TestRunner.addResult(text); + + if (!sections[i].objectTreeElement().expanded) + TestRunner.addResult(' <section collapsed>'); + } +}; + +SourcesTestRunner.scopeChainSections = function() { + var children = self.runtime.sharedInstance(Sources.ScopeChainSidebarPane).contentElement.children; + var sections = []; + + for (var i = 0; i < children.length; ++i) + sections.push(children[i]._section); + + return sections; +}; + +SourcesTestRunner.expandScopeVariablesSidebarPane = function(callback) { + var sections = SourcesTestRunner.scopeChainSections(); + + for (var i = 0; i < sections.length - 1; ++i) + sections[i].expand(); + + TestRunner.deprecatedRunAfterPendingDispatches(callback); +}; + +SourcesTestRunner.expandProperties = function(properties, callback) { + var index = 0; + + function expandNextPath() { + if (index === properties.length) { + TestRunner.safeWrap(callback)(); + return; + } + + var parentTreeElement = properties[index++]; + var path = properties[index++]; + SourcesTestRunner._expandProperty(parentTreeElement, path, 0, expandNextPath); + } + + TestRunner.deprecatedRunAfterPendingDispatches(expandNextPath); +}; + +SourcesTestRunner._expandProperty = function(parentTreeElement, path, pathIndex, callback) { + if (pathIndex === path.length) { + TestRunner.addResult('Expanded property: ' + path.join('.')); + callback(); + return; + } + + var name = path[pathIndex++]; + var propertyTreeElement = SourcesTestRunner._findChildPropertyTreeElement(parentTreeElement, name); + + if (!propertyTreeElement) { + TestRunner.addResult('Failed to expand property: ' + path.slice(0, pathIndex).join('.')); + SourcesTestRunner.completeDebuggerTest(); + return; + } + + propertyTreeElement.expand(); + TestRunner.deprecatedRunAfterPendingDispatches( + SourcesTestRunner._expandProperty.bind(SourcesTestRunner, propertyTreeElement, path, pathIndex, callback)); +}; + +SourcesTestRunner._findChildPropertyTreeElement = function(parent, childName) { + var children = parent.children(); + + for (var i = 0; i < children.length; i++) { + var treeElement = children[i]; + var property = treeElement.property; + + if (property.name === childName) + return treeElement; + } +}; + +SourcesTestRunner.setQuiet = function(quiet) { + SourcesTestRunner._quiet = quiet; +}; + +SourcesTestRunner.queryScripts = function(filter) { + var scripts = TestRunner.debuggerModel.scripts(); + return (filter ? scripts.filter(filter) : scripts); +}; + +SourcesTestRunner.createScriptMock = function( + url, startLine, startColumn, isContentScript, source, target, preRegisterCallback) { + target = target || SDK.targetManager.mainTarget(); + var debuggerModel = target.model(SDK.DebuggerModel); + var scriptId = ++SourcesTestRunner._lastScriptId + ''; + var lineCount = source.computeLineEndings().length; + var endLine = startLine + lineCount - 1; + var endColumn = + (lineCount === 1 ? startColumn + source.length : source.length - source.computeLineEndings()[lineCount - 2]); + var hasSourceURL = + !!source.match(/\/\/#\ssourceURL=\s*(\S*?)\s*$/m) || !!source.match(/\/\/@\ssourceURL=\s*(\S*?)\s*$/m); + + var script = new SDK.Script( + debuggerModel, scriptId, url, startLine, startColumn, endLine, endColumn, 0, '', isContentScript, false, + undefined, hasSourceURL, source.length); + + script.requestContent = function() { + var trimmedSource = SDK.Script._trimSourceURLComment(source); + return Promise.resolve(trimmedSource); + }; + + if (preRegisterCallback) + preRegisterCallback(script); + + debuggerModel._registerScript(script); + return script; +}; + +SourcesTestRunner._lastScriptId = 0; + +SourcesTestRunner.checkRawLocation = function(script, lineNumber, columnNumber, location) { + TestRunner.assertEquals(script.scriptId, location.scriptId, 'Incorrect scriptId'); + TestRunner.assertEquals(lineNumber, location.lineNumber, 'Incorrect lineNumber'); + TestRunner.assertEquals(columnNumber, location.columnNumber, 'Incorrect columnNumber'); +}; + +SourcesTestRunner.checkUILocation = function(uiSourceCode, lineNumber, columnNumber, location) { + TestRunner.assertEquals( + uiSourceCode, location.uiSourceCode, + 'Incorrect uiSourceCode, expected \'' + ((uiSourceCode ? uiSourceCode.url() : null)) + '\',' + + ' but got \'' + ((location.uiSourceCode ? location.uiSourceCode.url() : null)) + '\''); + + TestRunner.assertEquals( + lineNumber, location.lineNumber, + 'Incorrect lineNumber, expected \'' + lineNumber + '\', but got \'' + location.lineNumber + '\''); + + TestRunner.assertEquals( + columnNumber, location.columnNumber, + 'Incorrect columnNumber, expected \'' + columnNumber + '\', but got \'' + location.columnNumber + '\''); +}; + +SourcesTestRunner.scriptFormatter = function() { + return self.runtime.allInstances(Sources.SourcesView.EditorAction).then(function(editorActions) { + for (var i = 0; i < editorActions.length; ++i) { + if (editorActions[i] instanceof Sources.ScriptFormatterEditorAction) + return editorActions[i]; + } + + return null; + }); +}; + +SourcesTestRunner.waitForExecutionContextInTarget = function(target, callback) { + var runtimeModel = target.model(SDK.RuntimeModel); + + if (runtimeModel.executionContexts().length) { + callback(runtimeModel.executionContexts()[0]); + return; + } + + runtimeModel.addEventListener(SDK.RuntimeModel.Events.ExecutionContextCreated, contextCreated); + + function contextCreated() { + runtimeModel.removeEventListener(SDK.RuntimeModel.Events.ExecutionContextCreated, contextCreated); + callback(runtimeModel.executionContexts()[0]); + } +}; + +SourcesTestRunner.selectThread = function(target) { + var threadsPane = self.runtime.sharedInstance(Sources.ThreadsSidebarPane); + threadsPane._list.selectItem(target.model(SDK.DebuggerModel)); +}; + +SourcesTestRunner.evaluateOnCurrentCallFrame = function(code) { + return new Promise( + succ => TestRunner.debuggerModel.evaluateOnSelectedCallFrame( + code, 'console', false, true, false, false, TestRunner.safeWrap(succ))); +}; + +SourcesTestRunner.waitJavaScriptSourceFrameBreakpoints = function(sourceFrame, inline) { + return waitUpdate().then(checkIfReady); + + function waitUpdate() { + return new Promise( + resolve => TestRunner.addSniffer(sourceFrame.__proto__, '_breakpointDecorationsUpdatedForTest', resolve)); + } + + function checkIfReady() { + for (var breakpoint of Bindings.breakpointManager._allBreakpoints()) { + if (breakpoint._fakePrimaryLocation && breakpoint.enabled()) + return waitUpdate().then(checkIfReady); + } + + return Promise.resolve(); + } +}; + +SourcesTestRunner.dumpJavaScriptSourceFrameBreakpoints = function(sourceFrame) { + var textEditor = sourceFrame._textEditor; + + for (var lineNumber = 0; lineNumber < textEditor.linesCount; ++lineNumber) { + if (!textEditor.hasLineClass(lineNumber, 'cm-breakpoint')) + continue; + + var disabled = textEditor.hasLineClass(lineNumber, 'cm-breakpoint-disabled'); + var conditional = textEditor.hasLineClass(lineNumber, 'cm-breakpoint-conditional'); + TestRunner.addResult( + 'breakpoint at ' + lineNumber + ((disabled ? ' disabled' : '')) + ((conditional ? ' conditional' : ''))); + var range = new TextUtils.TextRange(lineNumber, 0, lineNumber, textEditor.line(lineNumber).length); + var bookmarks = textEditor.bookmarks(range, Sources.JavaScriptSourceFrame.BreakpointDecoration._bookmarkSymbol); + bookmarks = bookmarks.filter(bookmark => !!bookmark.position()); + bookmarks.sort((bookmark1, bookmark2) => bookmark1.position().startColumn - bookmark2.position().startColumn); + + for (var bookmark of bookmarks) { + var position = bookmark.position(); + var element = bookmark[Sources.JavaScriptSourceFrame.BreakpointDecoration._elementSymbolForTest]; + var disabled = element.classList.contains('cm-inline-disabled'); + var conditional = element.classList.contains('cm-inline-conditional'); + + TestRunner.addResult( + ' inline breakpoint at (' + position.startLine + ', ' + position.startColumn + ')' + + ((disabled ? ' disabled' : '')) + ((conditional ? ' conditional' : ''))); + } + } +}; + +SourcesTestRunner.clickJavaScriptSourceFrameBreakpoint = function(sourceFrame, lineNumber, index, next) { + var textEditor = sourceFrame._textEditor; + var lineLength = textEditor.line(lineNumber).length; + var lineRange = new TextUtils.TextRange(lineNumber, 0, lineNumber, lineLength); + var bookmarks = textEditor.bookmarks(lineRange, Sources.JavaScriptSourceFrame.BreakpointDecoration._bookmarkSymbol); + bookmarks.sort((bookmark1, bookmark2) => bookmark1.position().startColumn - bookmark2.position().startColumn); + var bookmark = bookmarks[index]; + + if (bookmark) { + bookmark[Sources.JavaScriptSourceFrame.BreakpointDecoration._elementSymbolForTest].click(); + } else { + TestRunner.addResult(`Could not click on Javascript breakpoint - lineNumber: ${lineNumber}, index: ${index}`); + next(); + } +}; + +SourcesTestRunner.setEventListenerBreakpoint = function(id, enabled, targetName) { + var pane = self.runtime.sharedInstance(Sources.EventListenerBreakpointsSidebarPane); + + var auxData = {'eventName': id}; + + if (targetName) + auxData.targetName = targetName; + + var breakpoint = SDK.domDebuggerManager.resolveEventListenerBreakpoint(auxData); + + if (breakpoint.enabled() !== enabled) { + pane._breakpoints.get(breakpoint).checkbox.checked = enabled; + pane._breakpointCheckboxClicked(breakpoint); + } +}; + +(async function() { + await TestRunner.evaluateInPagePromise(` + function scheduleTestFunction() { + setTimeout(testFunction, 0); + } + `); +})();
diff --git a/third_party/WebKit/Source/devtools/front_end/sources_test_runner/EditorTestRunner.js b/third_party/WebKit/Source/devtools/front_end/sources_test_runner/EditorTestRunner.js new file mode 100644 index 0000000..59983cc --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/sources_test_runner/EditorTestRunner.js
@@ -0,0 +1,219 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +SourcesTestRunner.createTestEditor = function(clientHeight, textEditorDelegate) { + var textEditor = new SourceFrame.SourcesTextEditor(textEditorDelegate || new SourceFrame.SourcesTextEditorDelegate()); + clientHeight = clientHeight || 100; + textEditor.element.style.height = clientHeight + 'px'; + textEditor.element.style.flex = 'none'; + textEditor.show(UI.inspectorView.element); + return textEditor; +}; + +function textWithSelection(text, selections) { + if (!selections.length) + return text; + + function lineWithCursor(line, column, cursorChar) { + return line.substring(0, column) + cursorChar + line.substring(column); + } + + var lines = text.split('\n'); + selections.sort(TextUtils.TextRange.comparator); + + for (var i = selections.length - 1; i >= 0; --i) { + var selection = selections[i]; + selection = selection.normalize(); + var endCursorChar = (selection.isEmpty() ? '|' : '<'); + lines[selection.endLine] = lineWithCursor(lines[selection.endLine], selection.endColumn, endCursorChar); + + if (!selection.isEmpty()) + lines[selection.startLine] = lineWithCursor(lines[selection.startLine], selection.startColumn, '>'); + } + + return lines.join('\n'); +} + +SourcesTestRunner.dumpTextWithSelection = function(textEditor, dumpWhiteSpaces) { + var text = textWithSelection(textEditor.text(), textEditor.selections()); + + if (dumpWhiteSpaces) + text = text.replace(/ /g, '.'); + + TestRunner.addResult(text); +}; + +SourcesTestRunner.setLineSelections = function(editor, selections) { + var coords = []; + + for (var i = 0; i < selections.length; ++i) { + var selection = selections[i]; + + if (typeof selection.column === 'number') { + selection.from = selection.column; + selection.to = selection.column; + } + + coords.push(new TextUtils.TextRange(selection.line, selection.from, selection.line, selection.to)); + } + + editor.setSelections(coords); +}; + +SourcesTestRunner.typeIn = function(editor, typeText, callback) { + callback = callback || new Function(); + var noop = new Function(); + + for (var charIndex = 0; charIndex < typeText.length; ++charIndex) { + var iterationCallback = (charIndex + 1 === typeText.length ? callback : noop); + + switch (typeText[charIndex]) { + case '\n': + SourcesTestRunner.fakeKeyEvent(editor, 'Enter', null, iterationCallback); + break; + case 'L': + SourcesTestRunner.fakeKeyEvent(editor, 'ArrowLeft', null, iterationCallback); + break; + case 'R': + SourcesTestRunner.fakeKeyEvent(editor, 'ArrowRight', null, iterationCallback); + break; + case 'U': + SourcesTestRunner.fakeKeyEvent(editor, 'ArrowUp', null, iterationCallback); + break; + case 'D': + SourcesTestRunner.fakeKeyEvent(editor, 'ArrowDown', null, iterationCallback); + break; + default: + SourcesTestRunner.fakeKeyEvent(editor, typeText[charIndex], null, iterationCallback); + } + } +}; + +var eventCodes = {Enter: 13, Home: 36, ArrowLeft: 37, ArrowUp: 38, ArrowRight: 39, ArrowDown: 40}; + +function createCodeMirrorFakeEvent(editor, eventType, code, charCode, modifiers) { + function eventPreventDefault() { + this._handled = true; + } + + var event = { + _handled: false, + type: eventType, + keyCode: code, + charCode: charCode, + preventDefault: eventPreventDefault, + stopPropagation: function() {}, + target: editor._codeMirror.display.input.textarea + }; + + if (modifiers) { + for (var i = 0; i < modifiers.length; ++i) + event[modifiers[i]] = true; + } + + return event; +} + +function fakeCodeMirrorKeyEvent(editor, eventType, code, charCode, modifiers) { + var event = createCodeMirrorFakeEvent(editor, eventType, code, charCode, modifiers); + + switch (eventType) { + case 'keydown': + editor._codeMirror.triggerOnKeyDown(event); + break; + case 'keypress': + editor._codeMirror.triggerOnKeyPress(event); + break; + case 'keyup': + editor._codeMirror.triggerOnKeyUp(event); + break; + default: + throw new Error('Unknown KeyEvent type'); + } + + return event._handled; +} + +function fakeCodeMirrorInputEvent(editor, character) { + if (typeof character === 'string') + editor._codeMirror.display.input.textarea.value += character; +} + +SourcesTestRunner.fakeKeyEvent = function(editor, originalCode, modifiers, callback) { + modifiers = modifiers || []; + var code; + var charCode; + + if (originalCode === '\'') { + code = 222; + charCode = 0; + } else if (originalCode === '"') { + code = 222; + modifiers.push('shiftKey'); + charCode = 34; + } else if (originalCode === '(') { + code = '9'.charCodeAt(0); + modifiers.push('shiftKey'); + charCode = originalCode.charCodeAt(0); + } + + var code = code || eventCodes[originalCode] || originalCode; + + if (typeof code === 'string') + code = code.charCodeAt(0); + + if (fakeCodeMirrorKeyEvent(editor, 'keydown', code, charCode, modifiers)) { + callback(); + return; + } + + if (fakeCodeMirrorKeyEvent(editor, 'keypress', code, charCode, modifiers)) { + callback(); + return; + } + + fakeCodeMirrorInputEvent(editor, originalCode); + fakeCodeMirrorKeyEvent(editor, 'keyup', code, charCode, modifiers); + + function callbackWrapper() { + editor._codeMirror.off('inputRead', callbackWrapper); + callback(); + } + + editor._codeMirror.on('inputRead', callbackWrapper); +}; + +SourcesTestRunner.dumpSelectionStats = function(textEditor) { + var listHashMap = {}; + var sortedKeys = []; + var selections = textEditor.selections(); + + for (var i = 0; i < selections.length; ++i) { + var selection = selections[i]; + var text = textEditor.text(selection); + + if (!listHashMap[text]) { + listHashMap[text] = 1; + sortedKeys.push(text); + } else { + ++listHashMap[text]; + } + } + + for (var i = 0; i < sortedKeys.length; ++i) { + var keyName = sortedKeys[i]; + + if (!keyName.length) + keyName = '<Empty string>'; + else + keyName = '\'' + keyName + '\''; + + TestRunner.addResult(keyName + ': ' + listHashMap[sortedKeys[i]]); + } +};
diff --git a/third_party/WebKit/Source/devtools/front_end/sources_test_runner/LiveEditTestRunner.js b/third_party/WebKit/Source/devtools/front_end/sources_test_runner/LiveEditTestRunner.js new file mode 100644 index 0000000..80afde0 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/sources_test_runner/LiveEditTestRunner.js
@@ -0,0 +1,31 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +SourcesTestRunner.replaceInSource = function(sourceFrame, string, replacement) { + sourceFrame._textEditor.setReadOnly(false); + + for (var i = 0; i < sourceFrame._textEditor.linesCount; ++i) { + var line = sourceFrame._textEditor.line(i); + var column = line.indexOf(string); + + if (column === -1) + continue; + + range = new TextUtils.TextRange(i, column, i, column + string.length); + break; + } +}; + +SourcesTestRunner.commitSource = function(sourceFrame) { + sourceFrame.commitEditing(); +}; + +SourcesTestRunner.undoSourceEditing = function(sourceFrame) { + sourceFrame._textEditor.undo(); +};
diff --git a/third_party/WebKit/Source/devtools/front_end/sources_test_runner/SearchTestRunner.js b/third_party/WebKit/Source/devtools/front_end/sources_test_runner/SearchTestRunner.js new file mode 100644 index 0000000..588523a --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/sources_test_runner/SearchTestRunner.js
@@ -0,0 +1,148 @@ +// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +SourcesTestRunner.dumpSearchResults = function(searchResults) { + function comparator(a, b) { + a.url.localeCompare(b.url); + } + + searchResults.sort(comparator); + TestRunner.addResult('Search results: '); + + for (var i = 0; i < searchResults.length; i++) { + TestRunner.addResult( + 'url: ' + searchResults[i].url.replace(/VM\d+/, 'VMXX') + ', matchesCount: ' + searchResults[i].matchesCount); + } + + TestRunner.addResult(''); +}; + +SourcesTestRunner.dumpSearchMatches = function(searchMatches) { + TestRunner.addResult('Search matches: '); + + for (var i = 0; i < searchMatches.length; i++) { + TestRunner.addResult( + 'lineNumber: ' + searchMatches[i].lineNumber + ', line: \'' + searchMatches[i].lineContent + '\''); + } + + TestRunner.addResult(''); +}; + +SourcesTestRunner.runSearchAndDumpResults = function(scope, searchConfig, callback) { + var searchResults = []; + var progress = new Common.Progress(); + scope.performSearch(searchConfig, progress, searchResultCallback, searchFinishedCallback); + + function searchResultCallback(searchResult) { + searchResults.push(searchResult); + } + + function searchFinishedCallback() { + function comparator(searchResultA, searchResultB) { + return searchResultA.uiSourceCode.url().compareTo(searchResultB.uiSourceCode.url()); + } + + searchResults.sort(comparator); + + for (var i = 0; i < searchResults.length; ++i) { + var searchResult = searchResults[i]; + var uiSourceCode = searchResult.uiSourceCode; + var searchMatches = searchResult.searchMatches; + + if (!searchMatches.length) + continue; + + TestRunner.addResult( + 'Search result #' + (i + 1) + ': uiSourceCode.url = ' + uiSourceCode.url().replace(/VM\d+/, 'VMXX')); + + for (var j = 0; j < searchMatches.length; ++j) { + var lineNumber = searchMatches[j].lineNumber; + var lineContent = searchMatches[j].lineContent; + TestRunner.addResult( + ' search match #' + (j + 1) + ': lineNumber = ' + lineNumber + ', lineContent = \'' + lineContent + '\''); + } + } + + callback(); + } +}; + +SourcesTestRunner.replaceAndDumpChange = function(sourceFrame, searchConfig, replacement, replaceAll) { + var modifiers = []; + + if (searchConfig.isRegex) + modifiers.push('regex'); + + if (searchConfig.caseSensitive) + modifiers.push('caseSensitive'); + + if (replaceAll) + modifiers.push('replaceAll'); + + var modifiersString = (modifiers.length ? ' (' + modifiers.join(', ') + ')' : ''); + TestRunner.addResult( + 'Running replace test for /' + searchConfig.query + '/' + replacement + '/ ' + modifiersString + ':'); + editor = sourceFrame._textEditor; + var oldLines = []; + + for (var i = 0; i < editor.linesCount; ++i) + oldLines.push(editor.line(i)); + + var searchableView = UI.panels.sources.sourcesView().searchableView(); + searchableView.showSearchField(); + searchableView._caseSensitiveButton.setToggled(searchConfig.caseSensitive); + searchableView._regexButton.setToggled(searchConfig.isRegex); + searchableView._searchInputElement.value = searchConfig.query; + searchableView._replaceCheckboxElement.checked = true; + searchableView._updateSecondRowVisibility(); + searchableView._replaceInputElement.value = replacement; + searchableView._performSearch(true, true); + + if (replaceAll) + searchableView._replaceAll(); + else + searchableView._replace(); + + var newLines = []; + + for (var i = 0; i < editor.linesCount; ++i) + newLines.push(editor.line(i)); + + for (var i = 0; i < newLines.length; ++i) { + if (oldLines[i] === newLines[i]) + continue; + + var oldLine = oldLines[i]; + var newLine = newLines[i]; + var prefixLength = 0; + + for (var j = 0; j < oldLine.length && j < newLine.length && newLine[j] === oldLine[j]; ++j) + ++prefixLength; + + var postfixLength = 0; + + for (var j = 0; j < oldLine.length && j < newLine.length && + newLine[newLine.length - j - 1] === oldLine[oldLine.length - j - 1]; + ++j) + ++postfixLength; + + var prefix = oldLine.substring(0, prefixLength); + var removed = oldLine.substring(prefixLength, oldLine.length - postfixLength); + var added = newLine.substring(prefixLength, newLine.length - postfixLength); + var postfix = oldLine.substring(oldLine.length - postfixLength); + TestRunner.addResult(' - ' + prefix + '#' + removed + '#' + added + '#' + postfix); + } +}; + +(async function() { + await TestRunner.evaluateInPagePromise(` + if (window.GCController) + GCController.collect(); + `); +})();
diff --git a/third_party/WebKit/Source/devtools/front_end/sources_test_runner/SourcesTestRunner.js b/third_party/WebKit/Source/devtools/front_end/sources_test_runner/SourcesTestRunner.js index ed36909..4b28e95 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources_test_runner/SourcesTestRunner.js +++ b/third_party/WebKit/Source/devtools/front_end/sources_test_runner/SourcesTestRunner.js
@@ -74,41 +74,6 @@ }; /** - * @param {string} urlSuffix - * @param {!Workspace.projectTypes=} projectType - * @return {!Promise} - */ -SourcesTestRunner.waitForUISourceCode = function(urlSuffix, projectType) { - /** - * @param {!Workspace.UISourceCode} uiSourceCode - * @return {boolean} - */ - function matches(uiSourceCode) { - if (projectType && uiSourceCode.project().type() !== projectType) - return false; - if (!projectType && uiSourceCode.project().type() === Workspace.projectTypes.Service) - return false; - if (urlSuffix && !uiSourceCode.url().endsWith(urlSuffix)) - return false; - return true; - } - - for (var uiSourceCode of Workspace.workspace.uiSourceCodes()) { - if (urlSuffix && matches(uiSourceCode)) - return Promise.resolve(uiSourceCode); - } - - return TestRunner.waitForEvent(Workspace.Workspace.Events.UISourceCodeAdded, Workspace.workspace, matches); -}; - -/** - * @param {!Function} callback - */ -SourcesTestRunner.waitForUISourceCodeRemoved = function(callback) { - Workspace.workspace.once(Workspace.Workspace.Events.UISourceCodeRemoved).then(callback); -}; - -/** * @param {string} url * @param {string} content * @param {boolean=} isContentScript @@ -120,5 +85,70 @@ if (isContentScript) content = `testRunner.evaluateScriptInIsolatedWorld(${worldId}, \`${content}\`)`; TestRunner.evaluateInPagePromise(content); - return SourcesTestRunner.waitForUISourceCode(url); + return TestRunner.waitForUISourceCode(url); +}; + +function testSourceMapping(text1, text2, mapping, testToken) { + var originalPosition = text1.indexOf(testToken); + TestRunner.assertTrue(originalPosition !== -1); + var originalLocation = Formatter.Formatter.positionToLocation(text1.computeLineEndings(), originalPosition); + var formattedLocation = mapping.originalToFormatted(originalLocation[0], originalLocation[1]); + var formattedPosition = + Formatter.Formatter.locationToPosition(text2.computeLineEndings(), formattedLocation[0], formattedLocation[1]); + var expectedFormattedPosition = text2.indexOf(testToken); + + if (expectedFormattedPosition === formattedPosition) + TestRunner.addResult(String.sprintf('Correct mapping for <%s>', testToken)); + else + TestRunner.addResult(String.sprintf('ERROR: Wrong mapping for <%s>', testToken)); +} + +SourcesTestRunner.testPrettyPrint = function(mimeType, text, mappingQueries, next) { + new Formatter.ScriptFormatter(mimeType, text, didFormatContent); + + function didFormatContent(formattedSource, mapping) { + TestRunner.addResult('====== 8< ------'); + TestRunner.addResult(formattedSource); + TestRunner.addResult('------ >8 ======'); + + while (mappingQueries && mappingQueries.length) + testSourceMapping(text, formattedSource, mapping, mappingQueries.shift()); + + next(); + } +}; + +SourcesTestRunner.testJavascriptOutline = function(text) { + var fulfill; + var promise = new Promise(x => fulfill = x); + Formatter.formatterWorkerPool().javaScriptOutline(text, onChunk); + var items = []; + return promise; + + function onChunk(isLastChunk, outlineItems) { + items.pushAll(outlineItems); + + if (!isLastChunk) + return; + + TestRunner.addResult('Text:'); + TestRunner.addResult(text.split('\n').map(line => ' ' + line).join('\n')); + TestRunner.addResult('Outline:'); + + for (var item of items) + TestRunner.addResult(' ' + item.name + (item.arguments || '') + ':' + item.line + ':' + item.column); + + fulfill(); + } +}; + +SourcesTestRunner.dumpSwatchPositions = function(sourceFrame, bookmarkType) { + var textEditor = sourceFrame.textEditor; + var markers = textEditor.bookmarks(textEditor.fullRange(), bookmarkType); + + for (var i = 0; i < markers.length; i++) { + var position = markers[i].position(); + var text = markers[i]._marker.widgetNode.firstChild.textContent; + TestRunner.addResult('Line ' + position.startLine + ', Column ' + position.startColumn + ': ' + text); + } };
diff --git a/third_party/WebKit/Source/devtools/front_end/sources_test_runner/module.json b/third_party/WebKit/Source/devtools/front_end/sources_test_runner/module.json index 147271d..b9ceb99 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources_test_runner/module.json +++ b/third_party/WebKit/Source/devtools/front_end/sources_test_runner/module.json
@@ -3,9 +3,26 @@ "test_runner", "integration_test_runner", "sources", - "workspace" + "workspace", + "source_frame", + "text_utils" ], "scripts": [ - "SourcesTestRunner.js" + "SourcesTestRunner.js", + "DebuggerTestRunner.js", + "LiveEditTestRunner.js", + "SearchTestRunner.js", + "EditorTestRunner.js", + "AutocompleteTestRunner.js", + "BreakpointManagerTestRunner.js" + ], + "skip_compilation": [ + "DebuggerTestRunner.js", + "LiveEditTestRunner.js", + "SearchTestRunner.js", + "SourcesTestRunner.js", + "EditorTestRunner.js", + "AutocompleteTestRunner.js", + "BreakpointManagerTestRunner.js" ] -} \ No newline at end of file +}
diff --git a/third_party/WebKit/Source/devtools/front_end/test_runner/TestRunner.js b/third_party/WebKit/Source/devtools/front_end/test_runner/TestRunner.js index b03973c..d394f2d 100644 --- a/third_party/WebKit/Source/devtools/front_end/test_runner/TestRunner.js +++ b/third_party/WebKit/Source/devtools/front_end/test_runner/TestRunner.js
@@ -11,7 +11,15 @@ const testScriptURL = /** @type {string} */ (Runtime.queryParam('test')); fetch(testScriptURL) .then(data => data.text()) - .then(testScript => eval(`(function test(){${testScript}})()\n//# sourceURL=${testScriptURL}`)) + .then(testScript => { + if (!self.testRunner || Runtime.queryParam('debugFrontend')) { + self.eval(`function test(){${testScript}}\n//# sourceURL=${testScriptURL}`); + TestRunner.addResult = console.log; + TestRunner.completeTest = () => console.log('Test completed'); + return; + } + eval(`(function test(){${testScript}})()\n//# sourceURL=${testScriptURL}`); + }) .catch(error => { TestRunner.addResult(`Unable to execute test script because of error: ${error}`); TestRunner.completeTest(); @@ -22,10 +30,6 @@ TestRunner._results = []; TestRunner.completeTest = function() { - if (!self.testRunner) { - console.log('Test Done'); - return; - } TestRunner.flushResults(); self.testRunner.notifyDone(); }; @@ -54,10 +58,7 @@ * @param {*} text */ TestRunner.addResult = function(text) { - if (self.testRunner) - TestRunner._results.push(String(text)); - else - console.log(text); + TestRunner._results.push(String(text)); }; /** @@ -270,17 +271,6 @@ return buffer; }; -/** - * @param {!Function} testFunction - * @return {!Function} - */ -function debugTest(testFunction) { - self.test = testFunction; - TestRunner.addResult = console.log; - TestRunner.completeTest = () => console.log('Test completed'); - return () => {}; -} - (function() { /** * @param {string|!Event} message
diff --git a/third_party/WebKit/Source/devtools/scripts/compile_frontend.py b/third_party/WebKit/Source/devtools/scripts/compile_frontend.py index 5a783d4..e1d82786 100755 --- a/third_party/WebKit/Source/devtools/scripts/compile_frontend.py +++ b/third_party/WebKit/Source/devtools/scripts/compile_frontend.py
@@ -258,6 +258,8 @@ def check_conditional_dependencies(modules_by_name): errors_found = False for name in modules_by_name: + if 'test_runner' in name: + continue for dep_name in modules_by_name[name].get('dependencies', []): dependency = modules_by_name[dep_name] if dependency.get('experiment') or dependency.get('condition'):
diff --git a/third_party/WebKit/Source/devtools/scripts/migrate_test/glob.js b/third_party/WebKit/Source/devtools/scripts/migrate_test/glob.js new file mode 100644 index 0000000..c5ea1b9 --- /dev/null +++ b/third_party/WebKit/Source/devtools/scripts/migrate_test/glob.js
@@ -0,0 +1,45 @@ +// 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. + +'use strict'; + +const fs = require('fs'); +const path = require('path'); + +const utils = require('../utils'); + +const TESTS_PATH = path.resolve(__dirname, 'tests.txt'); + +function main() { + const files = process.argv.slice(2); + const inputPaths = files.map(p => path.isAbsolute(p) ? p : path.resolve(process.cwd(), p)); + let globbedPaths = []; + for (const p of inputPaths) { + glob(p); + } + let contents = fs.readFileSync(TESTS_PATH, 'utf-8'); + const tests = new Set(contents.split('\n').map(l => l.split(' ')[0])); + for (const p of globbedPaths) { + const relativePath = p.slice(p.indexOf('LayoutTests') + 'LayoutTests'.length + 1); + if (!tests.has(relativePath)) + contents += relativePath + '\n' + } + console.log('contents', contents); + fs.writeFileSync(TESTS_PATH, contents, 'utf-8'); + + + function glob(globPath) { + for (const filename of fs.readdirSync(globPath)) { + const p = path.resolve(globPath, filename); + if (utils.isDir(p) && filename !== 'resources') { + glob(p); + } + if (utils.isFile(p) && p.endsWith('.html')) { + globbedPaths.push(p); + } + } + } +} + +main();
diff --git a/third_party/WebKit/Source/devtools/scripts/migrate_test/migrate_helpers.js b/third_party/WebKit/Source/devtools/scripts/migrate_test/migrate_helpers.js new file mode 100644 index 0000000..4fe0ca9 --- /dev/null +++ b/third_party/WebKit/Source/devtools/scripts/migrate_test/migrate_helpers.js
@@ -0,0 +1,519 @@ +// 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. + +'use strict'; + +const fs = require('fs'); +const path = require('path'); + +const recast = require('recast'); +const types = recast.types; +const b = recast.types.builders; + +const utils = require('../utils'); +const migrateUtils = require('./migrate_utils'); +/** + * propertyToNamespace {[testProperty:string]: {namespace: string, done: boolean}} + * Moved file + * {ETR.something: ETR} + * Existing helper module + * {ConsoleTestRunner.something: CTR} + */ +const BUILD_GN_PATH = path.resolve(__dirname, '..', '..', 'BUILD.gn'); +const DRY_RUN = process.env.DRY_RUN || false; +const FRONT_END_PATH = path.resolve(__dirname, '..', '..', 'front_end'); + +function main() { + const helperPaths = scanHelpers(); + const helpers = mapTestFilesToHelperModules(helperPaths); + transformHelperCode(helpers); + if (DRY_RUN) { + return; + } + updateModuleDescriptors(helpers); + const newModules = new Set(); + const helperFiles = []; + for (const h of helpers) { + newModules.add(h.helperModule); + helperFiles.push(h.newPath); + } + const existingModulesJson = require(path.resolve(FRONT_END_PATH, 'integration_test_runner.json')); + for (const module of existingModulesJson.modules) { + newModules.delete(module.name) + } + updateApplicationDescriptor('integration_test_runner.json', newModules); + updateBuildGN(newModules, helperFiles); + writeNewHelpers(helpers); +} + +function updateBuildGN(newModuleSet, helperFiles) { + let content = fs.readFileSync(BUILD_GN_PATH).toString(); + helperFiles = + helperFiles.map(p => p.split('/').slice(-3).join('/')).filter(p => content.indexOf(p) === -1).map(p => `"${p}",`); + + let newContent = addContentToLinesInSortedOrder({ + content, + startLine: 'all_devtools_files = [', + endLine: ']', + linesToInsert: + [...newModuleSet].map(module => `"front_end/${module}/module.json",`).filter(p => content.indexOf(p) === -1), + }); + + newContent = addContentToLinesInSortedOrder({ + content: newContent, + startLine: 'all_devtools_files = [', + endLine: ']', + linesToInsert: helperFiles, + }); + + fs.writeFileSync(BUILD_GN_PATH, newContent); + + function top(array) { + return array[array.length - 1]; + } + + function addContentToLinesInSortedOrder({content, startLine, endLine, linesToInsert}) { + if (linesToInsert.length === 0) + return content; + let lines = content.split('\n'); + let seenStartLine = false; + let contentStack = linesToInsert.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())).reverse(); + for (var i = 0; i < lines.length; i++) { + let line = lines[i].trim(); + let nextLine = lines[i + 1].trim(); + if (line === startLine) + seenStartLine = true; + + if (line === endLine && seenStartLine) + break; + + if (!seenStartLine) + continue; + + const nextContent = top(contentStack) ? top(contentStack).toLowerCase() : ''; + if ((line === startLine || nextContent >= line.toLowerCase()) && + (nextLine === endLine || nextContent <= nextLine.toLowerCase())) + lines.splice(i + 1, 0, contentStack.pop()); + } + if (contentStack.length) + lines.splice(i, 0, ...contentStack); + return lines.join('\n'); + } +} + +function updateApplicationDescriptor(descriptorFileName, newModuleSet) { + let descriptorPath = path.join(FRONT_END_PATH, descriptorFileName); + let newModules = [...newModuleSet]; + if (newModules.length === 0) + return; + let includeNewModules = (acc, line) => { + if (line === ' "modules" : [') { + acc.push(line); + return acc.concat(newModules.map((m, i) => { + // Need spacing to preserve indentation + let string; + string = ` { "name": "${m}" },`; + return string; + })); + } + return acc.concat([line]); + }; + let lines = fs.readFileSync(descriptorPath).toString().split('\n').reduce(includeNewModules, []); + fs.writeFileSync(descriptorPath, lines.join('\n')); +} + +function updateModuleDescriptors(helpers) { + const dependenciesByModule = { + application_test_runner: ['resources', 'console_test_runner', 'sources', 'sources_test_runner'], + audits_test_runner: ['audits'], + bindings_test_runner: ['workspace', 'diff', 'bindings', 'persistence'], + coverage_test_runner: ['coverage', 'sources_test_runner'], + device_mode_test_runner: ['emulation'], + elements_test_runner: ['animation'], + accessibility_test_runner: ['accessibility', 'elements_test_runner'], + extensions_test_runner: ['extensions'], + layers_test_runner: ['layers', 'components'], + network_test_runner: ['product_registry_impl', 'console_test_runner'], + performance_test_runner: ['timeline_model', 'timeline'], + profiler_test_runner: ['profiler', 'data_grid', 'heap_snapshot_worker'], + security_test_runner: ['security'], + sources_test_runner: ['source_frame', 'text_utils'], + sass_test_runner: ['sass'], + }; + + for (const helper of helpers) { + const parentPath = path.dirname(helper.newPath); + if (!utils.isDir(parentPath)) + fs.mkdirSync(parentPath); + const modulePath = path.resolve(parentPath, 'module.json'); + const additionalDependencies = dependenciesByModule[helper.helperModule] || []; + let contents = { + dependencies: ['test_runner', 'integration_test_runner'], + scripts: [], + }; + if (utils.isFile(modulePath)) { + contents = JSON.parse(fs.readFileSync(modulePath, 'utf-8')); + } + contents.dependencies = unique(contents.dependencies.concat(additionalDependencies)); + const filename = path.basename(helper.newPath); + if (contents.scripts.indexOf(filename) === -1) + contents.scripts.push(filename); + contents.skip_compilation = contents.skip_compilation || []; + contents.skip_compilation.push(filename); + fs.writeFileSync(modulePath, stringifyJSON(contents)); + } + + function unique(array) { + const set = new Set(); + for (const el of array) + set.add(el); + return Array.from(set); + } + + function stringifyJSON(obj) { + return unicodeEscape(JSON.stringify(obj, null, 2) + '\n'); + } + + // http://stackoverflow.com/questions/7499473/need-to-escape-non-ascii-characters-in-javascript + function unicodeEscape(string) { + function padWithLeadingZeros(string) { + return new Array(5 - string.length).join('0') + string; + } + + function unicodeCharEscape(charCode) { + return '\\u' + padWithLeadingZeros(charCode.toString(16)); + } + + return string.split('') + .map(function(char) { + var charCode = char.charCodeAt(0); + return charCode > 127 ? unicodeCharEscape(charCode) : char; + }) + .join(''); + } +} + +function transformHelperCode(helpers) { + const boilerplate = `// Copyright 2017 The Chromium Authors. All +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview using private properties isn't a Closure violation in tests. + * @suppress {accessControls} + */ + +`; + + const propertyToNamespace = scrapeTestProperties(helpers); + + for (const helper of helpers) { + const ast = recast.parse(helper.originalContents); + unwrapInitializeFunction(ast); + + recast.visit(ast, { + /** + * Remove all deprecated API calls + */ + visitIdentifier: function(path) { + if (path.parentPath && path.parentPath.value && path.parentPath.value.object && + path.parentPath.value.object.name === 'InspectorTest' && path.value.name !== 'InspectorTest') { + const identifier = path.value.name; + if (identifier === 'preloadPanel' || identifier === 'preloadModule') { + console.log('helper: ', helper.originalPath, recast.print(path.parentPath.parentPath.value).code) + // Removes these types of calls: InspectorTest.preloadPanel("elements"); + path.parentPath.parentPath.prune(); + } + } + return false; + }, + /** + * Skip already ported API calls + */ + visitAssignmentExpression: function(path) { + if (!path.value.left.object) { + return false; + } + const namespace = path.value.left.object.name; + const propertyName = path.value.left.property.name; + if (namespace === 'InspectorTest' && propertyToNamespace.get(propertyName).done) { + // console.log('pruning', propertyName); + path.prune(); + } + this.traverse(path); + }, + }); + + /** + * Migrate all the call sites from InspectorTest to .*TestRunner + */ + recast.visit(ast, { + visitIdentifier: function(path) { + if (path.parentPath && path.parentPath.value && path.parentPath.value.object && + path.parentPath.value.object.name === 'InspectorTest' && path.value.name !== 'InspectorTest') { + if (!propertyToNamespace.get(path.value.name)) { + throw new Error('Could not find identifier for: ' + path.value.name); + } + const newParentIdentifier = propertyToNamespace.get(path.value.name).namespace; + path.parentPath.value.object.name = newParentIdentifier; + } + return false; + } + }); + + /** + * Migrate all the .bind call sites + * Example: SourcesTestRunner.waitUntilPaused.bind(InspectorTest, didPause) + */ + recast.visit(ast, { + visitCallExpression: function(path) { + const node = path.value; + if (node.callee.property && node.callee.property.name === 'bind') { + const code = recast.prettyPrint(node); + if (node.arguments[0].name === 'InspectorTest') { + node.arguments[0].name = node.callee.object.object.name; + } + } + this.traverse(path); + } + }); + + + const existingContents = utils.isFile(helper.newPath) ? fs.readFileSync(helper.newPath) : ''; + if (existingContents) + helper.contents = existingContents + '\n' + print(ast); + else + helper.contents = boilerplate + print(ast); + } + + function unwrapInitializeFunction(ast) { + // Handle function expression + let index = ast.program.body.findIndex( + n => n.type === 'VariableDeclaration' && n.declarations[0].id.name.indexOf('initialize_') !== -1); + if (index > -1) { + const otherNodes = ast.program.body.filter((_, i) => i !== index); + const testFunctionNode = ast.program.body[index]; + ast.program.body = testFunctionNode.declarations[0].init.body.body; + inspectedPageNodes(otherNodes); + return; + } + + // Handle function declaration + index = + ast.program.body.findIndex(n => n.type === 'FunctionDeclaration' && n.id.name.indexOf('initialize_') !== -1); + if (index > -1) { + const otherNodes = ast.program.body.filter((_, i) => i !== index); + const testFunctionNode = ast.program.body[index]; + ast.program.body.splice(index, 1); + ast.program.body = testFunctionNode.body.body; + inspectedPageNodes(otherNodes); + } + + function inspectedPageNodes(otherNodes) { + if (!otherNodes.length) + return; + const code = otherNodes.map(node => print(node)).join('\n').slice(0, -1); + ast.program.body.push(createAwaitExpressionNode(`await TestRunner.evaluateInPagePromise(\` +${code.split('\n').map(x => x.length ? ' ' + x : x).join('\n')} + \`)`)); + } + } +} + +function print(ast) { + /** + * Not using clang-format because certain tests look bad when formatted by it. + * Recast pretty print is smarter about preserving existing spacing. + */ + let code = recast.prettyPrint(ast, {tabWidth: 2, wrapColumn: 120, quote: 'single'}).code; + code = code.replace(/(\/\/\#\s*sourceURL=[\w-]+)\.html/, '$1.js'); + code = code.replace(/\s*\$\$SECRET_IDENTIFIER_FOR_LINE_BREAK\$\$\(\);/g, '\n'); + return code + '\n'; +} + +function scrapeTestProperties(helpers) { + const propertyToNamespace = new Map(); + scrapeOriginalHelpers(propertyToNamespace, helpers); + scrapeMovedHelpers(propertyToNamespace); + + // Manual overrides + propertyToNamespace.set('consoleModel', { + namespace: 'ConsoleModel', + done: true, + }); + propertyToNamespace.set('networkLog', { + namespace: 'NetworkLog', + done: true, + }); + return propertyToNamespace; +} + +function scrapeMovedHelpers(propertyToNamespace) { + const testRunnerPaths = fs.readdirSync(FRONT_END_PATH) + .filter(folder => folder.indexOf('test_runner') !== -1) + .map(folder => path.resolve(FRONT_END_PATH, folder)) + .filter(file => utils.isDir(file)); + + testRunnerPaths.forEach((helperPath) => { + const files = fs.readdirSync(helperPath) + .filter(file => file.indexOf('TestRunner') !== -1) + .map(file => path.resolve(helperPath, file)); + files.forEach(file => scrapeTestHelperIdentifiers(file)); + }); + + function scrapeTestHelperIdentifiers(filePath) { + var content = fs.readFileSync(filePath).toString(); + var lines = content.split('\n'); + for (var line of lines) { + var line = line.trim(); + if (line.indexOf('TestRunner.') === -1) + continue; + var match = line.match(/^\s*(\b\w*TestRunner.[a-z_A-Z0-9]+)\s*(\=[^,}]|[;])/) || + line.match(/^(TestRunner.[a-z_A-Z0-9]+)\s*\=$/); + if (!match) + continue; + var name = match[1]; + var components = name.split('.'); + if (components.length !== 2) + continue; + propertyToNamespace.set(components[1], { + namespace: components[0], + done: true, + }); + } + } +} + +function scrapeOriginalHelpers(propertyToNamespace, helpers) { + const testRunnerPaths = fs.readdirSync(FRONT_END_PATH) + .filter(folder => folder.indexOf('test_runner') !== -1) + .map(folder => path.resolve(FRONT_END_PATH, folder)); + + for (const helper of helpers) { + scrapeTestHelperIdentifiers(helper.originalContents, helper.namespace); + } + + function scrapeTestHelperIdentifiers(content, namespace) { + var lines = content.split('\n'); + for (var line of lines) { + var line = line.trim(); + if (line.indexOf('InspectorTest.') === -1) + continue; + var match = line.match(/^\s*(\b\w*InspectorTest.[a-z_A-Z0-9]+)\s*(\=[^,}]|[;])/) || + line.match(/^(InspectorTest.[a-z_A-Z0-9]+)\s*\=$/); + if (!match) + continue; + var name = match[1]; + var components = name.split('.'); + if (components.length !== 2) + continue; + propertyToNamespace.set(components[1], { + namespace: namespace, + done: false, + }); + } + } +} + +// Causes too much diff in test expectations +// function appendComment(helpers) { +// for (const {originalPath, originalContents, helperModule, filename} of helpers) { +// const comment = `// This file is being deprecated and is moving to front_end/${helperModule}/${filename} +// // Please see crbug.com/667560 for more details\n\n`; +// fs.writeFileSync(originalPath, comment + originalContents); +// } +// } + +function writeNewHelpers(helpers) { + for (const {contents, helperModule, filename} of helpers) { + const modulePath = path.resolve(FRONT_END_PATH, helperModule); + if (!utils.isDir(modulePath)) + fs.mkdirSync(modulePath); + const destPath = path.resolve(modulePath, filename); + fs.writeFileSync(destPath, contents); + } +} + +function mapTestFilesToHelperModules(helperPaths) { + const helpers = new Set(); + for (const p of helperPaths) { + const inputFilename = path.basename(p); + let namespacePrefix = path.basename(p) + .split('-test')[0] + .split('-') + .map(a => a.substring(0, 1).toUpperCase() + a.substring(1)) + .join(''); + let filenamePrefix = namespacePrefix; + + // Already migrated or n/a + if (namespacePrefix === 'Inspector' || namespacePrefix === 'Console' || namespacePrefix === 'Protocol' || + namespacePrefix === 'ExampleFilesetFor') { + continue; + } + + // Needs to be manually migrated + if (namespacePrefix === 'CspInline' || namespacePrefix === 'Stacktrace') + continue; + + const res = migrateUtils.mapTestFilename(inputFilename); + namespacePrefix = res.namespacePrefix; + filenamePrefix = res.filenamePrefix; + + const contents = fs.readFileSync(p, 'utf-8'); + const namespace = namespacePrefix + 'TestRunner'; + const helperModule = namespacePrefix === 'SASS' ? + 'sass_test_runner' : + namespacePrefix === '' ? 'integration_test_runner' : + namespace.replace(/([A-Z])/g, '_$1').replace(/^_/, '').toLowerCase(); + const filename = filenamePrefix + 'TestRunner.js'; + helpers.add({ + originalPath: p, + newPath: path.resolve(FRONT_END_PATH, helperModule, filename), + namespace, + helperModule, + filename, + originalContents: contents, + contents, + }); + } + return helpers; +} + +main(); + +function scanHelpers() { + const paths = []; + + const http_root = path.resolve(__dirname, '..', '..', '..', '..', 'LayoutTests', 'http', 'tests', 'inspector'); + const non_http_root = path.resolve(__dirname, '..', '..', '..', '..', 'LayoutTests', 'inspector'); + scan(http_root); + scan(non_http_root); + + function scan(p) { + const files = fs.readdirSync(p).map(file => path.resolve(p, file)); + for (const file of files) { + if (utils.isDir(file)) + scan(file); + else if ( + file.indexOf('-test.js') !== -1 || file.indexOf('syntax-highlight.js') !== -1 || + file.indexOf('timeline-data.js') !== -1 || file.indexOf('styles-update-links.js') !== -1 || + file.indexOf('breakpoint-manager.js') !== -1 || + file.indexOf('elements-panel-shadow-selection-on-refresh.js') !== -1 || file.indexOf('page-mock.js') !== -1) + paths.push(file); + } + } + + return paths; +} + +/** + * Hack to quickly create an AST node + */ +function createAwaitExpressionNode(code) { + return recast + .parse(`(async function(){ + ${code} + })()`) + .program.body[0]; +} \ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/scripts/migrate_test/migrate_test.js b/third_party/WebKit/Source/devtools/scripts/migrate_test/migrate_test.js index f9face9..99774b7 100644 --- a/third_party/WebKit/Source/devtools/scripts/migrate_test/migrate_test.js +++ b/third_party/WebKit/Source/devtools/scripts/migrate_test/migrate_test.js
@@ -9,6 +9,7 @@ const cheerio = require('cheerio'); const mkdirp = require('mkdirp'); +const prettier = require('prettier'); const recast = require('recast'); const types = recast.types; const b = recast.types.builders; @@ -24,6 +25,7 @@ const files = process.argv.slice(2); const inputPaths = files.map(p => path.isAbsolute(p) ? p : path.resolve(process.cwd(), p)); const identifierMap = generateTestHelperMap(); + for (const inputPath of inputPaths) { migrateTest(inputPath, identifierMap); } @@ -36,11 +38,12 @@ console.log('Starting to migrate: ', inputPath); const htmlTestFile = fs.readFileSync(inputPath, 'utf-8'); const $ = cheerio.load(htmlTestFile); + const onloadFunctionName = $('body')[0].attribs.onload ? $('body')[0].attribs.onload.slice(0, -2) : ''; const javascriptFixtures = []; const inputCode = $('script:not([src])') .toArray() .map(n => n.children[0].data) - .map(code => processScriptCode(code, javascriptFixtures)) + .map(code => processScriptCode(code, javascriptFixtures, onloadFunctionName)) .filter(x => !!x) .join('\n'); const bodyText = $('body').text().trim(); @@ -56,12 +59,6 @@ helperScripts.push(filename); }); - const testsPath = path.resolve(__dirname, 'tests.txt'); - const newToOldTests = new Map(fs.readFileSync(testsPath, 'utf-8').split('\n').map(line => line.split(' ').reverse())); - const originalTestPath = path.resolve( - __dirname, '..', '..', '..', '..', 'LayoutTests', newToOldTests.get(inputPath.slice(inputPath.indexOf('http/')))); - - const srcResourcePaths = resourceScripts.map(s => path.resolve(path.dirname(originalTestPath), s)); const destResourcePaths = resourceScripts.map(s => path.resolve(path.dirname(inputPath), s)); const relativeResourcePaths = destResourcePaths.map(p => p.slice(p.indexOf('/http/tests') + '/http/tests'.length)); @@ -74,14 +71,17 @@ // Tries to remove it if it has it's own line .replace(bodyText + '\n', '') // Tries to remove it if it's inline - .replace(bodyText, ''); - if (/<p>\s*<\/p>/.test(domFixture)) { - domFixture = undefined; - } - const onloadFunctionName = $('body')[0].attribs.onload.slice(0, -2); + .replace(bodyText, '') + .replace(/<p>\s*<\/p>/, '') + .replace(/<div>\s*<\/div>/, '') + .trim(); + const docType = htmlTestFile.match(/<!DOCTYPE.*>/) ? htmlTestFile.match(/<!DOCTYPE.*>/)[0] : ''; + if (docType) + domFixture = docType + (domFixture.length ? '\n' : '') + domFixture; outputCode = transformTestScript( inputCode, bodyText, identifierMap, testHelpers, javascriptFixtures, getPanel(inputPath), domFixture, onloadFunctionName, relativeResourcePaths); + outputCode = prettier.format(outputCode, {tabWidth: 2, printWidth: 120, singleQuote: true}); } catch (err) { console.log('Unable to migrate: ', inputPath); console.log('ERROR: ', err); @@ -90,13 +90,22 @@ console.log(outputCode); if (!DRY_RUN) { + const testsPath = path.resolve(__dirname, 'tests.txt'); + const newToOldTests = + new Map(fs.readFileSync(testsPath, 'utf-8').split('\n').map(line => line.split(' ').reverse())); + const originalTestPath = path.resolve( + __dirname, '..', '..', '..', '..', 'LayoutTests', + newToOldTests.get(inputPath.slice(inputPath.indexOf('http/')))); + + const srcResourcePaths = resourceScripts.map(s => path.resolve(path.dirname(originalTestPath), s)); + fs.writeFileSync(inputPath, outputCode); - copyResourceScripts(srcResourcePaths, destResourcePaths); + copyResourceScripts(srcResourcePaths, destResourcePaths, inputPath); console.log('Migrated: ', inputPath); } } -function copyResourceScripts(srcResourcePaths, destResourcePaths) { +function copyResourceScripts(srcResourcePaths, destResourcePaths, inputPath) { destResourcePaths.forEach((p, i) => { mkdirp.sync(path.dirname(p)); if (!utils.isFile(p)) { @@ -131,8 +140,8 @@ nonTestNodes.push(node); } - unwrapTestFunctionExpressionIfNecessary(ast); - unwrapTestFunctionDeclarationIfNecessary(ast); + unwrapFunctionExpression(ast, 'test'); + unwrapFunctionDeclaration(ast, 'test'); /** @@ -159,6 +168,24 @@ } }); + /** + * Migrate all the .bind call sites + * Example: SourcesTestRunner.waitUntilPaused.bind(InspectorTest, didPause) + */ + recast.visit(ast, { + visitCallExpression: function(path) { + const node = path.value; + if (node.callee.property && node.callee.property.name === 'bind') { + const code = recast.prettyPrint(node); + if (node.arguments[0].name === 'InspectorTest') { + node.arguments[0].name = node.callee.object.object.name; + } + } + this.traverse(path); + } + }); + + const allTestHelpers = new Set(); for (const helper of explicitTestHelpers) { @@ -181,7 +208,8 @@ for (const helper of allTestHelpers) { headerLines.push(createAwaitExpressionNode(`await TestRunner.loadModule('${helper}');`)); } - headerLines.push(createAwaitExpressionNode(`await TestRunner.showPanel('${panel}');`)); + if (panel) + headerLines.push(createAwaitExpressionNode(`await TestRunner.showPanel('${panel}');`)); if (domFixture) { headerLines.push(createAwaitExpressionNode(`await TestRunner.loadHTML(\` @@ -200,15 +228,15 @@ } let nonTestCode = nonTestNodes.reduce((acc, node) => { - let code = recast.print(node).code.split('\n').map(line => ' ' + line).join('\n'); - if (node.id && node.id.name === onloadFunctionName) { - code = code.replace(' runTest();\n', ''); - code = ` (${code.trimLeft()})();`; - }; + const ast = recast.parse(recast.print(node).code); + unwrapFunctionExpression(ast, onloadFunctionName); + unwrapFunctionDeclaration(ast, onloadFunctionName); + let code = recast.print(ast).code.split('\n').map(line => ' ' + line).join('\n'); + code = code.replace(/\s*runTest\(\);?\s*/, ''); + code = ` ${code.trim()};`; return acc + '\n' + code; }, ''); - - nonTestCode = nonTestCode.startsWith('\n') && nonTestCode.slice(2); + nonTestCode = ' ' + nonTestCode.trimLeft(); if (nonTestCode) { headerLines.push((createAwaitExpressionNode(`await TestRunner.evaluateInPagePromise(\` ${nonTestCode} @@ -238,7 +266,7 @@ * If the <script></script> block doesn't contain a test function * assume that it needs to be serialized */ -function processScriptCode(code, additionalHelperBlocks) { +function processScriptCode(code, javascriptFixtures, onloadFunctionName) { const ast = recast.parse(code); const testFunctionExpression = ast.program.body.find(n => n.type === 'VariableDeclaration' && n.declarations[0].id.name === 'test'); @@ -246,8 +274,16 @@ if (testFunctionExpression || testFunctionDeclaration) { return code; } - const formattedCode = code.trimRight().split('\n').map(line => ' ' + line).join('\n'); - additionalHelperBlocks.push(createAwaitExpressionNode(`await TestRunner.evaluateInPagePromise(\`${formattedCode} + unwrapFunctionExpression(ast, onloadFunctionName); + unwrapFunctionDeclaration(ast, onloadFunctionName); + const formattedCode = recast.print(ast) + .code.trimRight() + .split('\n') + .map(line => ' ' + line) + .join('\n') + .replace(/\s*runTest\(\);?\s*/, ''); + + javascriptFixtures.push(createAwaitExpressionNode(`await TestRunner.evaluateInPagePromise(\`${formattedCode} \`)`)); return; } @@ -256,9 +292,9 @@ * Unwrap test if it's a function expression * var test = function () {...} */ -function unwrapTestFunctionExpressionIfNecessary(ast) { +function unwrapFunctionExpression(ast, functionName) { const index = - ast.program.body.findIndex(n => n.type === 'VariableDeclaration' && n.declarations[0].id.name === 'test'); + ast.program.body.findIndex(n => n.type === 'VariableDeclaration' && n.declarations[0].id.name === functionName); if (index > -1) { const testFunctionNode = ast.program.body[index]; ast.program.body = testFunctionNode.declarations[0].init.body.body; @@ -270,8 +306,8 @@ * Unwrap test if it's a function declaration * function test () {...} */ -function unwrapTestFunctionDeclarationIfNecessary(ast) { - const index = ast.program.body.findIndex(n => n.type === 'FunctionDeclaration' && n.id.name === 'test'); +function unwrapFunctionDeclaration(ast, functionName) { + const index = ast.program.body.findIndex(n => n.type === 'FunctionDeclaration' && n.id.name === functionName); if (index > -1) { const testFunctionNode = ast.program.body[index]; ast.program.body.splice(index, 1); @@ -318,6 +354,8 @@ const components = inputPath.slice(inputPath.indexOf('LayoutTests/')).split('/'); const folder = inputPath.indexOf('LayoutTests/inspector') === -1 ? components[4] : components[2]; + if (folder.endsWith('.html')) + return; const panel = panelByFolder[folder]; if (!panel) { throw new Error('Could not figure out which panel to map folder: ' + folder); @@ -326,24 +364,18 @@ } function mapTestHelpers(testHelpers) { - const SKIP = 'SKIP'; - const testHelperMap = { - 'inspector-test': SKIP, - 'console-test': 'console_test_runner', - 'elements-test': 'elements_test_runner', - 'sources-test': 'sources_test_runner', - }; - const mappedHelpers = []; + const mappedHelpers = new Set(); for (const helper of testHelpers) { - const mappedHelper = testHelperMap[helper]; + const namespace = migrateUtils.mapTestFilename(helper).namespacePrefix + 'TestRunner'; + const mappedHelper = namespace.replace(/([A-Z])/g, '_$1').replace(/^_/, '').toLowerCase(); if (!mappedHelper) { throw Error('Could not map helper ' + helper); } - if (mappedHelper !== SKIP) { - mappedHelpers.push(mappedHelper); + if (mappedHelper !== 'inspector_test_runner') { + mappedHelpers.add(mappedHelper); } } - return mappedHelpers; + return Array.from(mappedHelpers); } function generateTestHelperMap() {
diff --git a/third_party/WebKit/Source/devtools/scripts/migrate_test/migrate_utils.js b/third_party/WebKit/Source/devtools/scripts/migrate_test/migrate_utils.js index be774e4..97d8124 100644 --- a/third_party/WebKit/Source/devtools/scripts/migrate_test/migrate_utils.js +++ b/third_party/WebKit/Source/devtools/scripts/migrate_test/migrate_utils.js
@@ -18,6 +18,92 @@ return out; } + +function mapTestFilename(filename) { + let namespacePrefix = path.basename(filename, '.js') + .split('-test')[0] + .split('-') + .map(a => a.substring(0, 1).toUpperCase() + a.substring(1)) + .join(''); + let filenamePrefix = namespacePrefix; + if (namespacePrefix === 'PageMock') + namespacePrefix = ''; + if (namespacePrefix === 'SyntaxHighlight') + namespacePrefix = ''; + if (namespacePrefix === 'Datagrid') { + namespacePrefix = 'DataGrid'; + filenamePrefix = 'DataGrid'; + } + if (namespacePrefix === 'TimelineData') + namespacePrefix = 'Performance'; + if (namespacePrefix === 'StylesUpdateLinks') + namespacePrefix = 'Elements'; + if (namespacePrefix === 'BreakpointManager') + namespacePrefix = 'Sources'; + if (namespacePrefix === 'ElementsPanelShadowSelectionOnRefresh') + namespacePrefix = 'Elements'; + + if (namespacePrefix === 'ExtensionsNetwork') + namespacePrefix = 'Extensions'; + if (namespacePrefix === 'CspInline') + namespacePrefix = 'CSPInline'; + if (namespacePrefix === 'Debugger') + namespacePrefix = 'Sources'; + if (namespacePrefix === 'Resources') { + namespacePrefix = 'Application'; + } + if (namespacePrefix === 'Appcache') + namespacePrefix = 'Application'; + if (namespacePrefix === 'ResourceTree') + namespacePrefix = 'Application'; + if (namespacePrefix === 'ServiceWorkers') + namespacePrefix = 'Application'; + if (namespacePrefix === 'CacheStorage') + namespacePrefix = 'Application'; + if (namespacePrefix === 'Indexeddb') { + namespacePrefix = 'Application'; + filenamePrefix = 'IndexedDB'; + } + if (namespacePrefix === 'Timeline') + namespacePrefix = 'Performance'; + if (namespacePrefix === 'ProductRegistry') + namespacePrefix = 'Network'; + if (namespacePrefix === 'Editor') + namespacePrefix = 'Sources'; + if (namespacePrefix === 'Search') + namespacePrefix = 'Sources'; + if (namespacePrefix === 'LiveEdit') + namespacePrefix = 'Sources'; + if (namespacePrefix === 'Autocomplete') + namespacePrefix = 'Sources'; + if (namespacePrefix === 'Changes') + namespacePrefix = 'Sources'; + if (namespacePrefix === 'Persistence') + namespacePrefix = 'Bindings'; + if (namespacePrefix === 'IsolatedFilesystem') + namespacePrefix = 'Bindings'; + if (namespacePrefix === 'Automapping') + namespacePrefix = 'Bindings'; + if (namespacePrefix === 'AccessibilityPane') + namespacePrefix = 'Accessibility'; + if (namespacePrefix === 'EditDom') { + namespacePrefix = 'Elements'; + filenamePrefix = 'EditDOM'; + } + if (namespacePrefix === 'SetOuterHtml') { + namespacePrefix = 'Elements'; + filenamePrefix = 'SetOuterHTML'; + } + if (namespacePrefix === 'HeapSnapshot') + namespacePrefix = 'Profiler'; + if (namespacePrefix === 'Sass') { + namespacePrefix = 'SASS' + filenamePrefix = 'SASS' + } + return {namespacePrefix, filenamePrefix}; +} + module.exports = { getOutPath, + mapTestFilename, };
diff --git a/third_party/WebKit/Source/devtools/scripts/migrate_test/move.js b/third_party/WebKit/Source/devtools/scripts/migrate_test/move.js index 21b6270..5bfecfa 100644 --- a/third_party/WebKit/Source/devtools/scripts/migrate_test/move.js +++ b/third_party/WebKit/Source/devtools/scripts/migrate_test/move.js
@@ -15,8 +15,9 @@ const MIGRATE_TEST_PATH = path.resolve(__dirname, 'migrate_test.js'); const TESTS_PATH = path.resolve(__dirname, 'tests.txt'); -const TEST_EXPECTATIONS_PATH = path.resolve(__dirname, '..', '..', '..', '..', 'LayoutTests', 'TestExpectations'); -const FLAG_EXPECTATIONS_PATH = path.resolve(__dirname, '..', '..', '..', '..', 'LayoutTests', 'FlagExpectations'); +const LAYOUT_TESTS_PATH = path.resolve(__dirname, '..', '..', '..', '..', 'LayoutTests'); +const TEST_EXPECTATIONS_PATH = path.resolve(LAYOUT_TESTS_PATH, 'TestExpectations'); +const FLAG_EXPECTATIONS_PATH = path.resolve(LAYOUT_TESTS_PATH, 'FlagExpectations'); function main() { const originalTests = fs.readFileSync(TESTS_PATH, 'utf-8').split('\n').map(line => line.split(' ')[0]); @@ -62,30 +63,78 @@ const newTestPaths = Array.from(oldToNewTestPath.values()).filter(x => x); + const TestExpectationFailureTypes = + ['Crash', 'Failure', 'Rebaseline', 'Skip', 'Timeout', 'WontFix', 'Missing', 'NeedsManualRebaseline']; + + const testsAlreadyExempted = new Set(); + // Update TestExpectations const testExpectations = fs.readFileSync(TEST_EXPECTATIONS_PATH, 'utf-8'); - const updatedTestExpecations = testExpectations.split('\n').map(line => { + let updatedTestExpecations = testExpectations.split('\n').map(line => { for (const [oldTestPath, newTestPath] of oldToNewTestPath) { if (!newTestPath) continue; - if (line.indexOf(oldTestPath) !== -1) + if (line.indexOf(oldTestPath) !== -1) { + if (TestExpectationFailureTypes.some(x => line.indexOf(x) !== -1)) { + testsAlreadyExempted.add(newTestPath); + } return line.replace(oldTestPath, newTestPath); + } + } + return line; + }); + + updatedTestExpecations = updatedTestExpecations.map(line => { + for (const [oldTestPath, newTestPath] of oldToNewTestPath) { + if (!newTestPath) + continue; if (line === '# See crbug.com/667560 for details') { - return line + '\n' + Array.from(newTestPaths).map(x => `crbug.com/667560 ${x} [ Skip ]`).join('\n'); + return line + '\n' + + Array.from(newTestPaths) + .filter(t => !testsAlreadyExempted.has(t)) + .map(x => `crbug.com/667560 ${x} [ Skip ]`) + .join('\n'); } if (line === '### virtual/mojo-loading/http/tests/devtools') { return line + '\n' + - Array.from(newTestPaths).map(x => `crbug.com/667560 virtual/mojo-loading/${x} [ Skip ]`).join('\n'); + Array.from(newTestPaths) + .filter(t => !testsAlreadyExempted.has(t)) + .map(x => `crbug.com/667560 virtual/mojo-loading/${x} [ Skip ]`) + .join('\n'); + } + + // Put mojo tests here so we don't re-enable the test after migrating + if (line === '### Manually fix after migration') { + return line + '\n' + + Array.from(newTestPaths) + .filter(t => testsAlreadyExempted.has(t)) + .map(x => `crbug.com/667560 virtual/mojo-loading/${x} [ Skip ]`) + .join('\n'); } } return line; }); fs.writeFileSync(TEST_EXPECTATIONS_PATH, updatedTestExpecations.join('\n')); + // Update additional test expectations + for (const filename + of ['ASANExpectations', 'LeakExpectations', 'MSANExpectations', 'NeverFixTests', 'SlowTests', 'SmokeTests', + 'StaleTestExpectations']) { + const filePath = path.resolve(LAYOUT_TESTS_PATH, filename); + updateExpectationsFile(filePath); + } + // Update FlagExpectations - for (const folder of fs.readdirSync(FLAG_EXPECTATIONS_PATH)) { - const flagFilePath = path.resolve(FLAG_EXPECTATIONS_PATH, folder); - const expectations = fs.readFileSync(flagFilePath, 'utf-8'); + for (const filename of fs.readdirSync(FLAG_EXPECTATIONS_PATH)) { + const filePath = path.resolve(FLAG_EXPECTATIONS_PATH, filename); + updateExpectationsFile(filePath); + } + + for (const [oldResourcesPath, newResourcesPath] of oldToNewResourcesPath) + utils.copyRecursive(oldResourcesPath, path.dirname(newResourcesPath)); + + function updateExpectationsFile(filePath) { + const expectations = fs.readFileSync(filePath, 'utf-8'); const updatedExpectations = expectations.split('\n').map(line => { for (const [oldTestPath, newTestPath] of oldToNewTestPath) { if (!newTestPath) @@ -96,11 +145,8 @@ } return line; }); - fs.writeFileSync(flagFilePath, updatedExpectations.join('\n')); + fs.writeFileSync(filePath, updatedExpectations.join('\n')); } - - for (const [oldResourcesPath, newResourcesPath] of oldToNewResourcesPath) - utils.copyRecursive(oldResourcesPath, path.dirname(newResourcesPath)); } main();
diff --git a/third_party/WebKit/Source/devtools/scripts/migrate_test/package.json b/third_party/WebKit/Source/devtools/scripts/migrate_test/package.json index a5279af..8eb135ec 100644 --- a/third_party/WebKit/Source/devtools/scripts/migrate_test/package.json +++ b/third_party/WebKit/Source/devtools/scripts/migrate_test/package.json
@@ -6,6 +6,7 @@ "dependencies": { "cheerio": "^1.0.0-rc.2", "mkdirp": "^0.5.1", + "prettier": "^1.5.3", "recast": "^0.12.6" } }
diff --git a/third_party/WebKit/Source/devtools/scripts/migrate_test/transform.js b/third_party/WebKit/Source/devtools/scripts/migrate_test/transform.js index 2cf305b..a27cb643 100644 --- a/third_party/WebKit/Source/devtools/scripts/migrate_test/transform.js +++ b/third_party/WebKit/Source/devtools/scripts/migrate_test/transform.js
@@ -27,7 +27,7 @@ continue; const fullTestPath = path.resolve(__dirname, '..', '..', '..', '..', 'LayoutTests', testPath); try { - childProcess.execSync(`node ${MIGRATE_SCRIPT_PATH} ${fullTestPath}`) + childProcess.execSync(`node ${MIGRATE_SCRIPT_PATH} ${fullTestPath}`); } catch (err) { console.log(err.stdout.toString()); continue; @@ -56,7 +56,7 @@ updatedTestExpecationLines.push(line); continue; } - if (line === '# ====== DevTools test migration failures until here ======') { + if (line === '### Manually fix after migration') { seenEndSentinel = true; updatedTestExpecationLines.push(line); continue;
diff --git a/third_party/WebKit/Source/devtools/scripts/special_case_namespaces.json b/third_party/WebKit/Source/devtools/scripts/special_case_namespaces.json index a973224..ff555c9 100644 --- a/third_party/WebKit/Source/devtools/scripts/special_case_namespaces.json +++ b/third_party/WebKit/Source/devtools/scripts/special_case_namespaces.json
@@ -4,5 +4,6 @@ "object_ui": "ObjectUI", "perf_ui": "PerfUI", "css_tracker": "CSSTracker", - "har_importer": "HARImporter" + "har_importer": "HARImporter", + "sass_test_runner": "SASSTestRunner" } \ No newline at end of file
diff --git a/third_party/WebKit/Source/modules/mediasource/TrackDefault.cpp b/third_party/WebKit/Source/modules/mediasource/TrackDefault.cpp index 19326c2..9c0453f 100644 --- a/third_party/WebKit/Source/modules/mediasource/TrackDefault.cpp +++ b/third_party/WebKit/Source/modules/mediasource/TrackDefault.cpp
@@ -5,9 +5,11 @@ #include "modules/mediasource/TrackDefault.h" #include "bindings/core/v8/ExceptionState.h" +#include "bindings/core/v8/ToV8ForCore.h" #include "core/html/track/AudioTrack.h" #include "core/html/track/TextTrack.h" #include "core/html/track/VideoTrack.h" +#include "platform/bindings/ScriptState.h" namespace blink { @@ -26,6 +28,10 @@ return text; } +ScriptValue TrackDefault::kinds(ScriptState* script_state) const { + return ScriptValue(script_state, ToV8(kinds_, script_state)); +} + TrackDefault* TrackDefault::Create(const AtomicString& type, const String& language, const String& label,
diff --git a/third_party/WebKit/Source/modules/mediasource/TrackDefault.h b/third_party/WebKit/Source/modules/mediasource/TrackDefault.h index c25e151f..6fb1926 100644 --- a/third_party/WebKit/Source/modules/mediasource/TrackDefault.h +++ b/third_party/WebKit/Source/modules/mediasource/TrackDefault.h
@@ -5,12 +5,14 @@ #ifndef TrackDefault_h #define TrackDefault_h +#include "bindings/core/v8/ScriptValue.h" #include "platform/bindings/ScriptWrappable.h" #include "platform/wtf/text/WTFString.h" namespace blink { class ExceptionState; +class ScriptState; class TrackDefault final : public GarbageCollectedFinalized<TrackDefault>, public ScriptWrappable { @@ -35,7 +37,7 @@ String byteStreamTrackID() const { return byte_stream_track_id_; } String language() const { return language_; } String label() const { return label_; } - const Vector<String>& kinds() const { return kinds_; } + ScriptValue kinds(ScriptState*) const; DEFINE_INLINE_TRACE() {}
diff --git a/third_party/WebKit/Source/modules/mediasource/TrackDefault.idl b/third_party/WebKit/Source/modules/mediasource/TrackDefault.idl index 89ae52a..8a8e11a9 100644 --- a/third_party/WebKit/Source/modules/mediasource/TrackDefault.idl +++ b/third_party/WebKit/Source/modules/mediasource/TrackDefault.idl
@@ -16,9 +16,10 @@ readonly attribute DOMString byteStreamTrackID; readonly attribute DOMString language; readonly attribute DOMString label; - // TODO(wolenetz): |kinds| should be [SameObject] FrozenArray<DOMString> or - // a getKinds() method returning sequence<DOMString>. - // https://github.com/w3c/media-source/issues/91 - // https://crbug.com/619665 - readonly attribute DOMString[] kinds; + // TrackDefault was removed from the spec in + // https://github.com/w3c/media-source/pull/138, and the last version to + // have it had getKinds() instead of |kinds|. Use an object here to avoid + // WebIDL arrays (which no longer exist) while not breaking compatibility + // See also: https://crbug.com/619665. + [CallWith=ScriptState] readonly attribute object kinds; };
diff --git a/third_party/WebKit/Source/platform/bindings/ScopedPersistent.h b/third_party/WebKit/Source/platform/bindings/ScopedPersistent.h index 11e12a0..559b82f 100644 --- a/third_party/WebKit/Source/platform/bindings/ScopedPersistent.h +++ b/third_party/WebKit/Source/platform/bindings/ScopedPersistent.h
@@ -61,7 +61,7 @@ handle_.Reset(isolate, local); } - virtual ~ScopedPersistent() { Clear(); } + ~ScopedPersistent() { Clear(); } ALWAYS_INLINE v8::Local<T> NewLocal(v8::Isolate* isolate) const { return v8::Local<T>::New(isolate, handle_); @@ -85,7 +85,7 @@ bool IsEmpty() const { return handle_.IsEmpty(); } bool IsWeak() const { return handle_.IsWeak(); } - virtual void Set(v8::Isolate* isolate, v8::Local<T> handle) { + void Set(v8::Isolate* isolate, v8::Local<T> handle) { handle_.Reset(isolate, handle); }
diff --git a/third_party/WebKit/Source/platform/bindings/ScriptState.h b/third_party/WebKit/Source/platform/bindings/ScriptState.h index e2e75ee..c6c9e71 100644 --- a/third_party/WebKit/Source/platform/bindings/ScriptState.h +++ b/third_party/WebKit/Source/platform/bindings/ScriptState.h
@@ -125,7 +125,7 @@ // ScriptState::from() must not be called for a context that does not have // valid embedder data in the embedder field. SECURITY_CHECK(script_state); - SECURITY_CHECK(script_state->GetContext() == context); + SECURITY_CHECK(script_state->context_ == context); return script_state; }
diff --git a/third_party/WebKit/Source/platform/blob/BlobDataTest.cpp b/third_party/WebKit/Source/platform/blob/BlobDataTest.cpp index b0bdd75..315de8d 100644 --- a/third_party/WebKit/Source/platform/blob/BlobDataTest.cpp +++ b/third_party/WebKit/Source/platform/blob/BlobDataTest.cpp
@@ -68,6 +68,18 @@ std::move(request)); } + void ReadRange(uint64_t offset, + uint64_t length, + mojo::ScopedDataPipeProducerHandle, + storage::mojom::blink::BlobReaderClientPtr) override { + NOTREACHED(); + } + + void ReadAll(mojo::ScopedDataPipeProducerHandle, + storage::mojom::blink::BlobReaderClientPtr) override { + NOTREACHED(); + } + void GetInternalUUID(GetInternalUUIDCallback callback) override { std::move(callback).Run(uuid_); }
diff --git a/third_party/WebKit/Source/platform/graphics/StrokeData.cpp b/third_party/WebKit/Source/platform/graphics/StrokeData.cpp index 2c909df..f8f4d81 100644 --- a/third_party/WebKit/Source/platform/graphics/StrokeData.cpp +++ b/third_party/WebKit/Source/platform/graphics/StrokeData.cpp
@@ -117,7 +117,6 @@ SkScalar intervals[2] = {0, gap + dash_width - kEpsilon}; flags->setPathEffect(SkDashPathEffect::Make(intervals, 2, 0)); } else { - // TODO(schenney): WavyStroke https://crbug.com/229574 flags->setPathEffect(0); } }
diff --git a/third_party/WebKit/Source/platform/heap/HeapAllocator.h b/third_party/WebKit/Source/platform/heap/HeapAllocator.h index 42dd648..117d9ba1 100644 --- a/third_party/WebKit/Source/platform/heap/HeapAllocator.h +++ b/third_party/WebKit/Source/platform/heap/HeapAllocator.h
@@ -329,23 +329,22 @@ // Use the payload size as recorded by the heap to determine how many // elements to finalize. size_t length = header->PayloadSize() / sizeof(T); - T* buffer = reinterpret_cast<T*>(pointer); + char* payload = static_cast<char*>(pointer); #ifdef ANNOTATE_CONTIGUOUS_CONTAINER + ANNOTATE_CHANGE_SIZE(payload, length * sizeof(T), 0, length * sizeof(T)); +#endif // As commented above, HeapVectorBacking calls finalizers for unused slots // (which are already zeroed out). - ANNOTATE_CHANGE_SIZE(buffer, length, 0, length); -#endif if (std::is_polymorphic<T>::value) { - char* pointer = reinterpret_cast<char*>(buffer); for (unsigned i = 0; i < length; ++i) { - char* element = pointer + i * sizeof(T); + char* element = payload + i * sizeof(T); if (blink::VTableInitialized(element)) reinterpret_cast<T*>(element)->~T(); } } else { - for (unsigned i = 0; i < length; ++i) { + T* buffer = reinterpret_cast<T*>(payload); + for (unsigned i = 0; i < length; ++i) buffer[i].~T(); - } } }
diff --git a/third_party/WebKit/Source/platform/network/HTTPParsers.cpp b/third_party/WebKit/Source/platform/network/HTTPParsers.cpp index 39c96cd..3d0015b 100644 --- a/third_party/WebKit/Source/platform/network/HTTPParsers.cpp +++ b/third_party/WebKit/Source/platform/network/HTTPParsers.cpp
@@ -835,8 +835,8 @@ HeaderFieldTokenizer tokenizer(headerValue); while (!tokenizer.IsConsumed()) { - StringView metric; - if (!tokenizer.ConsumeToken(Mode::kNormal, metric)) { + StringView name; + if (!tokenizer.ConsumeToken(Mode::kNormal, name)) { break; } @@ -853,7 +853,7 @@ } headers->push_back(WTF::MakeUnique<ServerTimingHeader>( - metric.ToString(), value, description)); + name.ToString(), value, description)); if (!tokenizer.Consume(',')) { break;
diff --git a/third_party/WebKit/Source/platform/network/HTTPParsers.h b/third_party/WebKit/Source/platform/network/HTTPParsers.h index b52261c..cd6fff7b 100644 --- a/third_party/WebKit/Source/platform/network/HTTPParsers.h +++ b/third_party/WebKit/Source/platform/network/HTTPParsers.h
@@ -84,12 +84,12 @@ }; struct ServerTimingHeader { - String metric; - double value; + String name; + double duration; String description; - ServerTimingHeader(String metric, double value, String description) - : metric(metric), value(value), description(description) {} + ServerTimingHeader(String name, double duration, String description) + : name(name), duration(duration), description(description) {} }; using ServerTimingHeaderVector = Vector<std::unique_ptr<ServerTimingHeader>>; @@ -158,11 +158,11 @@ ResourceResponse*, size_t* end); -// Parses a header value containing JSON data, according to +// Parses a header duration containing JSON data, according to // https://tools.ietf.org/html/draft-ietf-httpbis-jfv-01 // Returns an empty unique_ptr if the header cannot be parsed as JSON. JSON // strings which represent object nested deeper than |maxParseDepth| will also -// cause an empty return value. +// cause an empty return duration. PLATFORM_EXPORT std::unique_ptr<JSONArray> ParseJSONHeader(const String& header, int max_parse_depth);
diff --git a/third_party/WebKit/Source/platform/network/HTTPParsersTest.cpp b/third_party/WebKit/Source/platform/network/HTTPParsersTest.cpp index 436ffa4..ffd03ea 100644 --- a/third_party/WebKit/Source/platform/network/HTTPParsersTest.cpp +++ b/third_party/WebKit/Source/platform/network/HTTPParsersTest.cpp
@@ -501,8 +501,8 @@ unsigned i = 0; for (const auto& header : *results) { Vector<String> expectedResult = expectedResults[i++]; - EXPECT_EQ(header->metric, expectedResult[0]); - EXPECT_EQ(header->value, expectedResult[1].ToDouble()); + EXPECT_EQ(header->name, expectedResult[0]); + EXPECT_EQ(header->duration, expectedResult[1].ToDouble()); EXPECT_EQ(header->description, expectedResult[2]); } }
diff --git a/third_party/WebKit/Source/platform/scheduler/BUILD.gn b/third_party/WebKit/Source/platform/scheduler/BUILD.gn index 7a26319..2ac5798 100644 --- a/third_party/WebKit/Source/platform/scheduler/BUILD.gn +++ b/third_party/WebKit/Source/platform/scheduler/BUILD.gn
@@ -88,6 +88,8 @@ "renderer/render_widget_scheduling_state.cc", "renderer/render_widget_signals.cc", "renderer/render_widget_signals.h", + "renderer/renderer_metrics_helper.cc", + "renderer/renderer_metrics_helper.h", "renderer/renderer_scheduler.cc", "renderer/renderer_scheduler_impl.cc", "renderer/renderer_scheduler_impl.h", @@ -187,6 +189,7 @@ "renderer/deadline_task_runner_unittest.cc", "renderer/idle_time_estimator_unittest.cc", "renderer/render_widget_signals_unittest.cc", + "renderer/renderer_metrics_helper_unittest.cc", "renderer/renderer_scheduler_impl_unittest.cc", "renderer/task_cost_estimator_unittest.cc", "renderer/task_duration_metric_reporter_unittest.cc",
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper.cc new file mode 100644 index 0000000..0680913 --- /dev/null +++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper.cc
@@ -0,0 +1,359 @@ +// 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 "platform/scheduler/renderer/renderer_metrics_helper.h" + +#include "base/bind.h" +#include "base/metrics/histogram_macros.h" +#include "platform/scheduler/renderer/renderer_scheduler_impl.h" +#include "public/platform/scheduler/renderer_process_type.h" + +namespace blink { +namespace scheduler { + +#define TASK_DURATION_METRIC_NAME "RendererScheduler.TaskDurationPerQueueType2" +#define TASK_COUNT_METRIC_NAME "RendererScheduler.TaskCountPerQueueType" +#define MAIN_THREAD_LOAD_METRIC_NAME "RendererScheduler.RendererMainThreadLoad5" +#define EXTENSIONS_MAIN_THREAD_LOAD_METRIC_NAME \ + MAIN_THREAD_LOAD_METRIC_NAME ".Extension" + +namespace { + +constexpr base::TimeDelta kThreadLoadTrackerReportingInterval = + base::TimeDelta::FromSeconds(1); +// Threshold for discarding ultra-long tasks. Is it assumed that ultra-long +// tasks are reporting glitches (e.g. system falling asleep in the middle +// of the task). +constexpr base::TimeDelta kLongTaskDiscardingThreshold = + base::TimeDelta::FromSeconds(30); +constexpr base::TimeDelta kLongIdlePeriodDiscardingThreshold = + base::TimeDelta::FromMinutes(3); + +} // namespace + +RendererMetricsHelper::RendererMetricsHelper( + RendererSchedulerImpl* renderer_scheduler, + base::TimeTicks now, + bool renderer_backgrounded) + : renderer_scheduler_(renderer_scheduler), + main_thread_load_tracker( + now, + base::Bind(&RendererMetricsHelper::RecordMainThreadTaskLoad, + base::Unretained(this)), + kThreadLoadTrackerReportingInterval), + background_main_thread_load_tracker( + now, + base::Bind(&RendererMetricsHelper::RecordBackgroundMainThreadTaskLoad, + base::Unretained(this)), + kThreadLoadTrackerReportingInterval), + foreground_main_thread_load_tracker( + now, + base::Bind(&RendererMetricsHelper::RecordForegroundMainThreadTaskLoad, + base::Unretained(this)), + kThreadLoadTrackerReportingInterval), + task_duration_reporter(TASK_DURATION_METRIC_NAME), + foreground_task_duration_reporter(TASK_DURATION_METRIC_NAME + ".Foreground"), + foreground_first_minute_task_duration_reporter(TASK_DURATION_METRIC_NAME + ".Foreground.FirstMinute"), + foreground_second_minute_task_duration_reporter( + TASK_DURATION_METRIC_NAME ".Foreground.SecondMinute"), + foreground_third_minute_task_duration_reporter(TASK_DURATION_METRIC_NAME + ".Foreground.ThirdMinute"), + foreground_after_third_minute_task_duration_reporter( + TASK_DURATION_METRIC_NAME ".Foreground.AfterThirdMinute"), + background_task_duration_reporter(TASK_DURATION_METRIC_NAME + ".Background"), + background_first_minute_task_duration_reporter(TASK_DURATION_METRIC_NAME + ".Background.FirstMinute"), + background_second_minute_task_duration_reporter( + TASK_DURATION_METRIC_NAME ".Background.SecondMinute"), + background_third_minute_task_duration_reporter(TASK_DURATION_METRIC_NAME + ".Background.ThirdMinute"), + background_fourth_minute_task_duration_reporter( + TASK_DURATION_METRIC_NAME ".Background.FourthMinute"), + background_fifth_minute_task_duration_reporter(TASK_DURATION_METRIC_NAME + ".Background.FifthMinute"), + background_after_fifth_minute_task_duration_reporter( + TASK_DURATION_METRIC_NAME ".Background.AfterFifthMinute"), + hidden_task_duration_reporter(TASK_DURATION_METRIC_NAME ".Hidden"), + visible_task_duration_reporter(TASK_DURATION_METRIC_NAME ".Visible"), + hidden_music_task_duration_reporter(TASK_DURATION_METRIC_NAME + ".HiddenMusic") { + main_thread_load_tracker.Resume(now); + if (renderer_backgrounded) { + background_main_thread_load_tracker.Resume(now); + } else { + foreground_main_thread_load_tracker.Resume(now); + } +} + +RendererMetricsHelper::~RendererMetricsHelper() {} + +void RendererMetricsHelper::OnRendererForegrounded(base::TimeTicks now) { + foreground_main_thread_load_tracker.Resume(now); + background_main_thread_load_tracker.Pause(now); +} + +void RendererMetricsHelper::OnRendererBackgrounded(base::TimeTicks now) { + foreground_main_thread_load_tracker.Pause(now); + background_main_thread_load_tracker.Resume(now); +} + +void RendererMetricsHelper::OnRendererShutdown(base::TimeTicks now) { + foreground_main_thread_load_tracker.RecordIdle(now); + background_main_thread_load_tracker.RecordIdle(now); + main_thread_load_tracker.RecordIdle(now); +} + +namespace { + +// Calculates the length of the intersection of two given time intervals. +base::TimeDelta DurationOfIntervalOverlap(base::TimeTicks start1, + base::TimeTicks end1, + base::TimeTicks start2, + base::TimeTicks end2) { + DCHECK_LE(start1, end1); + DCHECK_LE(start2, end2); + return std::max(std::min(end1, end2) - std::max(start1, start2), + base::TimeDelta()); +} + +} // namespace + +void RendererMetricsHelper::RecordTaskMetrics( + MainThreadTaskQueue::QueueType queue_type, + base::TimeTicks start_time, + base::TimeTicks end_time) { + base::TimeDelta duration = end_time - start_time; + if (duration > kLongTaskDiscardingThreshold) + return; + + // Discard anomalously long idle periods. + if (last_reported_task_ && start_time - last_reported_task_.value() > + kLongIdlePeriodDiscardingThreshold) { + main_thread_load_tracker.Reset(end_time); + foreground_main_thread_load_tracker.Reset(end_time); + background_main_thread_load_tracker.Reset(end_time); + return; + } + + last_reported_task_ = end_time; + + UMA_HISTOGRAM_CUSTOM_COUNTS("RendererScheduler.TaskTime2", + duration.InMicroseconds(), 1, 1000 * 1000, 50); + + // We want to measure thread time here, but for efficiency reasons + // we stick with wall time. + main_thread_load_tracker.RecordTaskTime(start_time, end_time); + foreground_main_thread_load_tracker.RecordTaskTime(start_time, end_time); + background_main_thread_load_tracker.RecordTaskTime(start_time, end_time); + + UMA_HISTOGRAM_ENUMERATION( + TASK_COUNT_METRIC_NAME, static_cast<int>(queue_type), + static_cast<int>(MainThreadTaskQueue::QueueType::COUNT)); + + if (duration >= base::TimeDelta::FromMilliseconds(16)) { + UMA_HISTOGRAM_ENUMERATION( + TASK_COUNT_METRIC_NAME ".LongerThan16ms", static_cast<int>(queue_type), + static_cast<int>(MainThreadTaskQueue::QueueType::COUNT)); + } + + if (duration >= base::TimeDelta::FromMilliseconds(50)) { + UMA_HISTOGRAM_ENUMERATION( + TASK_COUNT_METRIC_NAME ".LongerThan50ms", static_cast<int>(queue_type), + static_cast<int>(MainThreadTaskQueue::QueueType::COUNT)); + } + + if (duration >= base::TimeDelta::FromMilliseconds(100)) { + UMA_HISTOGRAM_ENUMERATION( + TASK_COUNT_METRIC_NAME ".LongerThan100ms", static_cast<int>(queue_type), + static_cast<int>(MainThreadTaskQueue::QueueType::COUNT)); + } + + if (duration >= base::TimeDelta::FromMilliseconds(150)) { + UMA_HISTOGRAM_ENUMERATION( + TASK_COUNT_METRIC_NAME ".LongerThan150ms", static_cast<int>(queue_type), + static_cast<int>(MainThreadTaskQueue::QueueType::COUNT)); + } + + if (duration >= base::TimeDelta::FromSeconds(1)) { + UMA_HISTOGRAM_ENUMERATION( + TASK_COUNT_METRIC_NAME ".LongerThan1s", static_cast<int>(queue_type), + static_cast<int>(MainThreadTaskQueue::QueueType::COUNT)); + } + + task_duration_reporter.RecordTask(queue_type, duration); + + if (renderer_scheduler_->main_thread_only().renderer_backgrounded) { + background_task_duration_reporter.RecordTask(queue_type, duration); + + // Collect detailed breakdown for first five minutes given that we stop + // timers on mobile after five minutes. + base::TimeTicks backgrounded_at = + renderer_scheduler_->main_thread_only().background_status_changed_at; + + background_first_minute_task_duration_reporter.RecordTask( + queue_type, DurationOfIntervalOverlap( + start_time, end_time, backgrounded_at, + backgrounded_at + base::TimeDelta::FromMinutes(1))); + + background_second_minute_task_duration_reporter.RecordTask( + queue_type, DurationOfIntervalOverlap( + start_time, end_time, + backgrounded_at + base::TimeDelta::FromMinutes(1), + backgrounded_at + base::TimeDelta::FromMinutes(2))); + + background_third_minute_task_duration_reporter.RecordTask( + queue_type, DurationOfIntervalOverlap( + start_time, end_time, + backgrounded_at + base::TimeDelta::FromMinutes(2), + backgrounded_at + base::TimeDelta::FromMinutes(3))); + + background_fourth_minute_task_duration_reporter.RecordTask( + queue_type, DurationOfIntervalOverlap( + start_time, end_time, + backgrounded_at + base::TimeDelta::FromMinutes(3), + backgrounded_at + base::TimeDelta::FromMinutes(4))); + + background_fifth_minute_task_duration_reporter.RecordTask( + queue_type, DurationOfIntervalOverlap( + start_time, end_time, + backgrounded_at + base::TimeDelta::FromMinutes(4), + backgrounded_at + base::TimeDelta::FromMinutes(5))); + + background_after_fifth_minute_task_duration_reporter.RecordTask( + queue_type, + DurationOfIntervalOverlap( + start_time, end_time, + backgrounded_at + base::TimeDelta::FromMinutes(5), + std::max(backgrounded_at + base::TimeDelta::FromMinutes(5), + end_time))); + } else { + foreground_task_duration_reporter.RecordTask(queue_type, duration); + + // For foreground tabs we do not expect such a notable difference as it is + // the case with background tabs, so we limit breakdown to three minutes. + base::TimeTicks foregrounded_at = + renderer_scheduler_->main_thread_only().background_status_changed_at; + + foreground_first_minute_task_duration_reporter.RecordTask( + queue_type, DurationOfIntervalOverlap( + start_time, end_time, foregrounded_at, + foregrounded_at + base::TimeDelta::FromMinutes(1))); + + foreground_second_minute_task_duration_reporter.RecordTask( + queue_type, DurationOfIntervalOverlap( + start_time, end_time, + foregrounded_at + base::TimeDelta::FromMinutes(1), + foregrounded_at + base::TimeDelta::FromMinutes(2))); + + foreground_third_minute_task_duration_reporter.RecordTask( + queue_type, DurationOfIntervalOverlap( + start_time, end_time, + foregrounded_at + base::TimeDelta::FromMinutes(2), + foregrounded_at + base::TimeDelta::FromMinutes(3))); + + foreground_after_third_minute_task_duration_reporter.RecordTask( + queue_type, + DurationOfIntervalOverlap( + start_time, end_time, + foregrounded_at + base::TimeDelta::FromMinutes(3), + std::max(foregrounded_at + base::TimeDelta::FromMinutes(3), + end_time))); + } + + if (renderer_scheduler_->main_thread_only().renderer_hidden) { + hidden_task_duration_reporter.RecordTask(queue_type, duration); + + if (renderer_scheduler_->ShouldDisableThrottlingBecauseOfAudio( + start_time)) { + hidden_music_task_duration_reporter.RecordTask(queue_type, duration); + } + } else { + visible_task_duration_reporter.RecordTask(queue_type, duration); + } +} + +void RendererMetricsHelper::RecordMainThreadTaskLoad(base::TimeTicks time, + double load) { + int load_percentage = static_cast<int>(load * 100); + DCHECK_LE(load_percentage, 100); + + UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME, load_percentage); + + if (renderer_scheduler_->main_thread_only().process_type == + RendererProcessType::kExtensionRenderer) { + UMA_HISTOGRAM_PERCENTAGE(EXTENSIONS_MAIN_THREAD_LOAD_METRIC_NAME, + load_percentage); + } + + TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), + "RendererScheduler.RendererMainThreadLoad", load_percentage); +} + +void RendererMetricsHelper::RecordForegroundMainThreadTaskLoad( + base::TimeTicks time, + double load) { + int load_percentage = static_cast<int>(load * 100); + DCHECK_LE(load_percentage, 100); + + switch (renderer_scheduler_->main_thread_only().process_type) { + case RendererProcessType::kExtensionRenderer: + UMA_HISTOGRAM_PERCENTAGE(EXTENSIONS_MAIN_THREAD_LOAD_METRIC_NAME + ".Foreground", + load_percentage); + break; + case RendererProcessType::kRenderer: + UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME ".Foreground", + load_percentage); + + if (time - renderer_scheduler_->main_thread_only() + .background_status_changed_at > + base::TimeDelta::FromMinutes(1)) { + UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME + ".Foreground.AfterFirstMinute", + load_percentage); + } + break; + } + + TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), + "RendererScheduler.RendererMainThreadLoad.Foreground", + load_percentage); +} + +void RendererMetricsHelper::RecordBackgroundMainThreadTaskLoad( + base::TimeTicks time, + double load) { + int load_percentage = static_cast<int>(load * 100); + DCHECK_LE(load_percentage, 100); + + switch (renderer_scheduler_->main_thread_only().process_type) { + case RendererProcessType::kExtensionRenderer: + UMA_HISTOGRAM_PERCENTAGE(EXTENSIONS_MAIN_THREAD_LOAD_METRIC_NAME + ".Background", + load_percentage); + break; + case RendererProcessType::kRenderer: + UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME ".Background", + load_percentage); + + if (time - renderer_scheduler_->main_thread_only() + .background_status_changed_at > + base::TimeDelta::FromMinutes(1)) { + UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME + ".Background.AfterFirstMinute", + load_percentage); + } + break; + } + + TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), + "RendererScheduler.RendererMainThreadLoad.Background", + load_percentage); +} + +} // namespace scheduler +} // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper.h b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper.h new file mode 100644 index 0000000..6ad79c03 --- /dev/null +++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper.h
@@ -0,0 +1,75 @@ +// 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 THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_RENDERER_METRICS_HELPER_H_ +#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_RENDERER_METRICS_HELPER_H_ + +#include "base/macros.h" +#include "base/time/time.h" +#include "platform/PlatformExport.h" +#include "platform/scheduler/base/thread_load_tracker.h" +#include "platform/scheduler/renderer/main_thread_task_queue.h" +#include "platform/scheduler/renderer/task_duration_metric_reporter.h" + +namespace blink { +namespace scheduler { + +class RendererSchedulerImpl; + +// Helper class to take care of metrics on behalf of RendererScheduler. +// This class should be used only on the main thread. +class PLATFORM_EXPORT RendererMetricsHelper { + public: + RendererMetricsHelper(RendererSchedulerImpl* renderer_scheduler, + base::TimeTicks now, + bool renderer_backgrounded); + ~RendererMetricsHelper(); + + void RecordTaskMetrics(MainThreadTaskQueue::QueueType queue_type, + base::TimeTicks start_time, + base::TimeTicks end_time); + + void OnRendererForegrounded(base::TimeTicks now); + void OnRendererBackgrounded(base::TimeTicks now); + void OnRendererShutdown(base::TimeTicks now); + + void RecordMainThreadTaskLoad(base::TimeTicks time, double load); + void RecordForegroundMainThreadTaskLoad(base::TimeTicks time, double load); + void RecordBackgroundMainThreadTaskLoad(base::TimeTicks time, double load); + + private: + RendererSchedulerImpl* renderer_scheduler_; // NOT OWNED + + base::Optional<base::TimeTicks> last_reported_task_; + + ThreadLoadTracker main_thread_load_tracker; + ThreadLoadTracker background_main_thread_load_tracker; + ThreadLoadTracker foreground_main_thread_load_tracker; + + TaskDurationMetricReporter task_duration_reporter; + TaskDurationMetricReporter foreground_task_duration_reporter; + TaskDurationMetricReporter foreground_first_minute_task_duration_reporter; + TaskDurationMetricReporter foreground_second_minute_task_duration_reporter; + TaskDurationMetricReporter foreground_third_minute_task_duration_reporter; + TaskDurationMetricReporter + foreground_after_third_minute_task_duration_reporter; + TaskDurationMetricReporter background_task_duration_reporter; + TaskDurationMetricReporter background_first_minute_task_duration_reporter; + TaskDurationMetricReporter background_second_minute_task_duration_reporter; + TaskDurationMetricReporter background_third_minute_task_duration_reporter; + TaskDurationMetricReporter background_fourth_minute_task_duration_reporter; + TaskDurationMetricReporter background_fifth_minute_task_duration_reporter; + TaskDurationMetricReporter + background_after_fifth_minute_task_duration_reporter; + TaskDurationMetricReporter hidden_task_duration_reporter; + TaskDurationMetricReporter visible_task_duration_reporter; + TaskDurationMetricReporter hidden_music_task_duration_reporter; + + DISALLOW_COPY_AND_ASSIGN(RendererMetricsHelper); +}; + +} // namespace scheduler +} // namespace blink + +#endif // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_RENDERER_METRICS_HELPER_H_
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper_unittest.cc new file mode 100644 index 0000000..18e7557 --- /dev/null +++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper_unittest.cc
@@ -0,0 +1,176 @@ +// 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 "platform/scheduler/renderer/renderer_metrics_helper.h" + +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "base/test/histogram_tester.h" +#include "base/test/simple_test_tick_clock.h" +#include "components/viz/test/ordered_simple_task_runner.h" +#include "platform/scheduler/base/test_time_source.h" +#include "platform/scheduler/child/scheduler_tqm_delegate_for_test.h" +#include "platform/scheduler/renderer/renderer_scheduler_impl.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace blink { +namespace scheduler { + +using QueueType = MainThreadTaskQueue::QueueType; +using testing::ElementsAre; +using base::Bucket; + +class RendererMetricsHelperTest : public ::testing::Test { + public: + RendererMetricsHelperTest() {} + ~RendererMetricsHelperTest() {} + + void SetUp() { + histogram_tester_.reset(new base::HistogramTester()); + clock_ = base::MakeUnique<base::SimpleTestTickClock>(); + mock_task_runner_ = + make_scoped_refptr(new cc::OrderedSimpleTaskRunner(clock_.get(), true)); + delegate_ = SchedulerTqmDelegateForTest::Create( + mock_task_runner_, base::MakeUnique<TestTimeSource>(clock_.get())); + scheduler_ = base::MakeUnique<RendererSchedulerImpl>(delegate_); + metrics_helper_ = &scheduler_->main_thread_only().metrics_helper; + } + + void TearDown() { + scheduler_->Shutdown(); + scheduler_.reset(); + } + + void RunTask(MainThreadTaskQueue::QueueType queue_type, + base::TimeTicks start, + base::TimeDelta duration) { + DCHECK_LE(clock_->NowTicks(), start); + clock_->SetNowTicks(start + duration); + metrics_helper_->RecordTaskMetrics(queue_type, start, start + duration); + } + + base::TimeTicks Microseconds(int microseconds) { + return base::TimeTicks() + base::TimeDelta::FromMicroseconds(microseconds); + } + + base::TimeTicks Milliseconds(int milliseconds) { + return base::TimeTicks() + base::TimeDelta::FromMilliseconds(milliseconds); + } + + std::unique_ptr<base::SimpleTestTickClock> clock_; + scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_; + scoped_refptr<SchedulerTqmDelegate> delegate_; + std::unique_ptr<RendererSchedulerImpl> scheduler_; + RendererMetricsHelper* metrics_helper_; // NOT OWNED + std::unique_ptr<base::HistogramTester> histogram_tester_; + + DISALLOW_COPY_AND_ASSIGN(RendererMetricsHelperTest); +}; + +TEST_F(RendererMetricsHelperTest, Metrics) { + // QueueType::DEFAULT is checking sub-millisecond task aggregation, + // FRAME_* tasks are checking normal task aggregation and other + // queue types have a single task. + RunTask(QueueType::DEFAULT, Milliseconds(1), + base::TimeDelta::FromMicroseconds(700)); + RunTask(QueueType::DEFAULT, Milliseconds(2), + base::TimeDelta::FromMicroseconds(700)); + RunTask(QueueType::DEFAULT, Milliseconds(3), + base::TimeDelta::FromMicroseconds(700)); + + RunTask(QueueType::DEFAULT_LOADING, Milliseconds(200), + base::TimeDelta::FromMilliseconds(20)); + RunTask(QueueType::CONTROL, Milliseconds(400), + base::TimeDelta::FromMilliseconds(30)); + RunTask(QueueType::DEFAULT_TIMER, Milliseconds(600), + base::TimeDelta::FromMilliseconds(5)); + RunTask(QueueType::FRAME_LOADING, Milliseconds(800), + base::TimeDelta::FromMilliseconds(70)); + RunTask(QueueType::FRAME_UNTHROTTLED, Milliseconds(1000), + base::TimeDelta::FromMilliseconds(20)); + RunTask(QueueType::COMPOSITOR, Milliseconds(1200), + base::TimeDelta::FromMilliseconds(25)); + RunTask(QueueType::TEST, Milliseconds(1600), + base::TimeDelta::FromMilliseconds(85)); + + scheduler_->SetRendererBackgrounded(true); + + RunTask(QueueType::CONTROL, Milliseconds(2000), + base::TimeDelta::FromMilliseconds(25)); + RunTask(QueueType::FRAME_TIMER, Milliseconds(2600), + base::TimeDelta::FromMilliseconds(175)); + RunTask(QueueType::UNTHROTTLED, Milliseconds(2800), + base::TimeDelta::FromMilliseconds(25)); + RunTask(QueueType::FRAME_LOADING, Milliseconds(3000), + base::TimeDelta::FromMilliseconds(35)); + RunTask(QueueType::FRAME_TIMER, Milliseconds(3200), + base::TimeDelta::FromMilliseconds(5)); + RunTask(QueueType::COMPOSITOR, Milliseconds(3400), + base::TimeDelta::FromMilliseconds(20)); + RunTask(QueueType::IDLE, Milliseconds(3600), + base::TimeDelta::FromMilliseconds(50)); + RunTask(QueueType::FRAME_LOADING_CONTROL, Milliseconds(4000), + base::TimeDelta::FromMilliseconds(5)); + RunTask(QueueType::CONTROL, Milliseconds(4200), + base::TimeDelta::FromMilliseconds(20)); + RunTask(QueueType::FRAME_TIMER, Milliseconds(4400), + base::TimeDelta::FromMilliseconds(115)); + RunTask(QueueType::FRAME_UNTHROTTLED, Milliseconds(4600), + base::TimeDelta::FromMilliseconds(175)); + RunTask(QueueType::IDLE, Milliseconds(5000), + base::TimeDelta::FromMilliseconds(1600)); + + std::vector<base::Bucket> expected_samples = { + {static_cast<int>(QueueType::CONTROL), 75}, + {static_cast<int>(QueueType::DEFAULT), 2}, + {static_cast<int>(QueueType::DEFAULT_LOADING), 20}, + {static_cast<int>(QueueType::DEFAULT_TIMER), 5}, + {static_cast<int>(QueueType::UNTHROTTLED), 25}, + {static_cast<int>(QueueType::FRAME_LOADING), 105}, + {static_cast<int>(QueueType::FRAME_TIMER), 295}, + {static_cast<int>(QueueType::FRAME_UNTHROTTLED), 195}, + {static_cast<int>(QueueType::COMPOSITOR), 45}, + {static_cast<int>(QueueType::IDLE), 1650}, + {static_cast<int>(QueueType::TEST), 85}, + {static_cast<int>(QueueType::FRAME_LOADING_CONTROL), 5}}; + EXPECT_THAT(histogram_tester_->GetAllSamples( + "RendererScheduler.TaskDurationPerQueueType2"), + testing::ContainerEq(expected_samples)); + + EXPECT_THAT( + histogram_tester_->GetAllSamples( + "RendererScheduler.TaskDurationPerQueueType2.Foreground"), + ElementsAre(Bucket(static_cast<int>(QueueType::CONTROL), 30), + Bucket(static_cast<int>(QueueType::DEFAULT), 2), + Bucket(static_cast<int>(QueueType::DEFAULT_LOADING), 20), + Bucket(static_cast<int>(QueueType::DEFAULT_TIMER), 5), + Bucket(static_cast<int>(QueueType::FRAME_LOADING), 70), + Bucket(static_cast<int>(QueueType::FRAME_UNTHROTTLED), 20), + Bucket(static_cast<int>(QueueType::COMPOSITOR), 25), + Bucket(static_cast<int>(QueueType::TEST), 85))); + + EXPECT_THAT( + histogram_tester_->GetAllSamples( + "RendererScheduler.TaskDurationPerQueueType2.Background"), + ElementsAre( + Bucket(static_cast<int>(QueueType::CONTROL), 45), + Bucket(static_cast<int>(QueueType::UNTHROTTLED), 25), + Bucket(static_cast<int>(QueueType::FRAME_LOADING), 35), + Bucket(static_cast<int>(QueueType::FRAME_TIMER), 295), + Bucket(static_cast<int>(QueueType::FRAME_UNTHROTTLED), 175), + Bucket(static_cast<int>(QueueType::COMPOSITOR), 20), + Bucket(static_cast<int>(QueueType::IDLE), 1650), + Bucket(static_cast<int>(QueueType::FRAME_LOADING_CONTROL), 5))); +} + +// TODO(crbug.com/754656): Add tests for NthMinute and AfterNthMinute +// histograms. + +// TODO(crbug.com/754656): Add tests for TaskDuration.Hidden/Visible histograms. + +// TODO(crbug.com/754656): Add tests for non-TaskDuration histograms. + +} // namespace scheduler +} // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc index a5ddef2..9769f9f 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc +++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc
@@ -45,20 +45,11 @@ // Amount of idle time left in a frame (as a ratio of the vsync interval) above // which main thread compositing can be considered fast. const double kFastCompositingIdleTimeThreshold = .2; -constexpr base::TimeDelta kThreadLoadTrackerReportingInterval = - base::TimeDelta::FromSeconds(1); // We do not throttle anything while audio is played and shortly after that. constexpr base::TimeDelta kThrottlingDelayAfterAudioIsPlayed = base::TimeDelta::FromSeconds(5); constexpr base::TimeDelta kQueueingTimeWindowDuration = base::TimeDelta::FromSeconds(1); -// Threshold for discarding ultra-long tasks. It is assumed that ultra-long -// tasks are reporting glitches (e.g. system falling asleep in the middle -// of the task). -constexpr base::TimeDelta kLongTaskDiscardingThreshold = - base::TimeDelta::FromSeconds(30); -constexpr base::TimeDelta kLongIdlePeriodDiscardingThreshold = - base::TimeDelta::FromMinutes(3); } // namespace @@ -164,12 +155,6 @@ DCHECK(main_thread_only().was_shutdown); } -#define TASK_DURATION_METRIC_NAME "RendererScheduler.TaskDurationPerQueueType2" -#define TASK_COUNT_METRIC_NAME "RendererScheduler.TaskCountPerQueueType" -#define MAIN_THREAD_LOAD_METRIC_NAME "RendererScheduler.RendererMainThreadLoad5" -#define EXTENSIONS_MAIN_THREAD_LOAD_METRIC_NAME \ - MAIN_THREAD_LOAD_METRIC_NAME ".Extension" - RendererSchedulerImpl::MainThreadOnly::MainThreadOnly( RendererSchedulerImpl* renderer_scheduler_impl, const scoped_refptr<MainThreadTaskQueue>& compositor_task_runner, @@ -185,21 +170,6 @@ time_source, kShortIdlePeriodDurationSampleCount, kShortIdlePeriodDurationPercentile), - main_thread_load_tracker( - now, - base::Bind(&RendererSchedulerImpl::RecordMainThreadTaskLoad, - base::Unretained(renderer_scheduler_impl)), - kThreadLoadTrackerReportingInterval), - background_main_thread_load_tracker( - now, - base::Bind(&RendererSchedulerImpl::RecordBackgroundMainThreadTaskLoad, - base::Unretained(renderer_scheduler_impl)), - kThreadLoadTrackerReportingInterval), - foreground_main_thread_load_tracker( - now, - base::Bind(&RendererSchedulerImpl::RecordForegroundMainThreadTaskLoad, - base::Unretained(renderer_scheduler_impl)), - kThreadLoadTrackerReportingInterval), current_use_case(UseCase::NONE), timer_queue_pause_count(0), navigation_task_expected_count(0), @@ -227,39 +197,8 @@ background_status_changed_at(now), rail_mode_observer(nullptr), wake_up_budget_pool(nullptr), - task_duration_reporter(TASK_DURATION_METRIC_NAME), - foreground_task_duration_reporter(TASK_DURATION_METRIC_NAME - ".Foreground"), - foreground_first_minute_task_duration_reporter(TASK_DURATION_METRIC_NAME - ".Foreground.FirstMinute"), - foreground_second_minute_task_duration_reporter( - TASK_DURATION_METRIC_NAME ".Foreground.SecondMinute"), - foreground_third_minute_task_duration_reporter(TASK_DURATION_METRIC_NAME - ".Foreground.ThirdMinute"), - foreground_after_third_minute_task_duration_reporter( - TASK_DURATION_METRIC_NAME ".Foreground.AfterThirdMinute"), - background_task_duration_reporter(TASK_DURATION_METRIC_NAME - ".Background"), - background_first_minute_task_duration_reporter(TASK_DURATION_METRIC_NAME - ".Background.FirstMinute"), - background_second_minute_task_duration_reporter( - TASK_DURATION_METRIC_NAME ".Background.SecondMinute"), - background_third_minute_task_duration_reporter(TASK_DURATION_METRIC_NAME - ".Background.ThirdMinute"), - background_fourth_minute_task_duration_reporter( - TASK_DURATION_METRIC_NAME ".Background.FourthMinute"), - background_fifth_minute_task_duration_reporter(TASK_DURATION_METRIC_NAME - ".Background.FifthMinute"), - background_after_fifth_minute_task_duration_reporter( - TASK_DURATION_METRIC_NAME ".Background.AfterFifthMinute"), - hidden_task_duration_reporter(TASK_DURATION_METRIC_NAME ".Hidden"), - visible_task_duration_reporter(TASK_DURATION_METRIC_NAME ".Visible"), - hidden_music_task_duration_reporter(TASK_DURATION_METRIC_NAME - ".HiddenMusic"), - process_type(RendererProcessType::kRenderer) { - main_thread_load_tracker.Resume(now); - foreground_main_thread_load_tracker.Resume(now); -} + metrics_helper(renderer_scheduler_impl, now, renderer_backgrounded), + process_type(RendererProcessType::kRenderer) {} RendererSchedulerImpl::MainThreadOnly::~MainThreadOnly() {} @@ -283,8 +222,7 @@ void RendererSchedulerImpl::Shutdown() { base::TimeTicks now = tick_clock()->NowTicks(); - main_thread_only().background_main_thread_load_tracker.RecordIdle(now); - main_thread_only().foreground_main_thread_load_tracker.RecordIdle(now); + main_thread_only().metrics_helper.OnRendererShutdown(now); task_queue_throttler_.reset(); helper_.Shutdown(); @@ -612,11 +550,9 @@ base::TimeTicks now = tick_clock()->NowTicks(); if (backgrounded) { - main_thread_only().foreground_main_thread_load_tracker.Pause(now); - main_thread_only().background_main_thread_load_tracker.Resume(now); + main_thread_only().metrics_helper.OnRendererBackgrounded(now); } else { - main_thread_only().foreground_main_thread_load_tracker.Resume(now); - main_thread_only().background_main_thread_load_tracker.Pause(now); + main_thread_only().metrics_helper.OnRendererForegrounded(now); } } @@ -1969,271 +1905,8 @@ task_queue_throttler()->OnTaskRunTimeReported(queue, start, end); // TODO(altimin): Per-page metrics should also be considered. - RecordTaskMetrics(queue->queue_type(), start, end); -} - -namespace { - -// Calculates the length of the intersection of two given time intervals. -base::TimeDelta DurationOfIntervalOverlap(base::TimeTicks start1, - base::TimeTicks end1, - base::TimeTicks start2, - base::TimeTicks end2) { - DCHECK_LE(start1, end1); - DCHECK_LE(start2, end2); - return std::max(std::min(end1, end2) - std::max(start1, start2), - base::TimeDelta()); -} - -} // namespace - -void RendererSchedulerImpl::RecordTaskMetrics( - MainThreadTaskQueue::QueueType queue_type, - base::TimeTicks start_time, - base::TimeTicks end_time) { - base::TimeDelta duration = end_time - start_time; - if (duration > kLongTaskDiscardingThreshold) - return; - - // Discard anomalously long idle periods. - if (main_thread_only().last_reported_task && - start_time - main_thread_only().last_reported_task.value() > - kLongIdlePeriodDiscardingThreshold) { - main_thread_only().main_thread_load_tracker.Reset(end_time); - main_thread_only().foreground_main_thread_load_tracker.Reset(end_time); - main_thread_only().background_main_thread_load_tracker.Reset(end_time); - return; - } - - main_thread_only().last_reported_task = end_time; - - UMA_HISTOGRAM_CUSTOM_COUNTS("RendererScheduler.TaskTime2", - duration.InMicroseconds(), 1, 1000 * 1000, 50); - - // We want to measure thread time here, but for efficiency reasons - // we stick with wall time. - main_thread_only().main_thread_load_tracker.RecordTaskTime(start_time, - end_time); - main_thread_only().foreground_main_thread_load_tracker.RecordTaskTime( - start_time, end_time); - main_thread_only().background_main_thread_load_tracker.RecordTaskTime( - start_time, end_time); - - UMA_HISTOGRAM_ENUMERATION( - TASK_COUNT_METRIC_NAME, static_cast<int>(queue_type), - static_cast<int>(MainThreadTaskQueue::QueueType::COUNT)); - - if (duration >= base::TimeDelta::FromMilliseconds(16)) { - UMA_HISTOGRAM_ENUMERATION( - TASK_COUNT_METRIC_NAME ".LongerThan16ms", static_cast<int>(queue_type), - static_cast<int>(MainThreadTaskQueue::QueueType::COUNT)); - } - - if (duration >= base::TimeDelta::FromMilliseconds(50)) { - UMA_HISTOGRAM_ENUMERATION( - TASK_COUNT_METRIC_NAME ".LongerThan50ms", static_cast<int>(queue_type), - static_cast<int>(MainThreadTaskQueue::QueueType::COUNT)); - } - - if (duration >= base::TimeDelta::FromMilliseconds(100)) { - UMA_HISTOGRAM_ENUMERATION( - TASK_COUNT_METRIC_NAME ".LongerThan100ms", static_cast<int>(queue_type), - static_cast<int>(MainThreadTaskQueue::QueueType::COUNT)); - } - - if (duration >= base::TimeDelta::FromMilliseconds(150)) { - UMA_HISTOGRAM_ENUMERATION( - TASK_COUNT_METRIC_NAME ".LongerThan150ms", static_cast<int>(queue_type), - static_cast<int>(MainThreadTaskQueue::QueueType::COUNT)); - } - - if (duration >= base::TimeDelta::FromSeconds(1)) { - UMA_HISTOGRAM_ENUMERATION( - TASK_COUNT_METRIC_NAME ".LongerThan1s", static_cast<int>(queue_type), - static_cast<int>(MainThreadTaskQueue::QueueType::COUNT)); - } - - main_thread_only().task_duration_reporter.RecordTask(queue_type, duration); - - if (main_thread_only().renderer_backgrounded) { - main_thread_only().background_task_duration_reporter.RecordTask(queue_type, - duration); - - // Collect detailed breakdown for first five minutes given that we stop - // timers on mobile after five minutes. - base::TimeTicks backgrounded_at = - main_thread_only().background_status_changed_at; - - main_thread_only() - .background_first_minute_task_duration_reporter.RecordTask( - queue_type, DurationOfIntervalOverlap( - start_time, end_time, backgrounded_at, - backgrounded_at + base::TimeDelta::FromMinutes(1))); - - main_thread_only() - .background_second_minute_task_duration_reporter.RecordTask( - queue_type, DurationOfIntervalOverlap( - start_time, end_time, - backgrounded_at + base::TimeDelta::FromMinutes(1), - backgrounded_at + base::TimeDelta::FromMinutes(2))); - - main_thread_only() - .background_third_minute_task_duration_reporter.RecordTask( - queue_type, DurationOfIntervalOverlap( - start_time, end_time, - backgrounded_at + base::TimeDelta::FromMinutes(2), - backgrounded_at + base::TimeDelta::FromMinutes(3))); - - main_thread_only() - .background_fourth_minute_task_duration_reporter.RecordTask( - queue_type, DurationOfIntervalOverlap( - start_time, end_time, - backgrounded_at + base::TimeDelta::FromMinutes(3), - backgrounded_at + base::TimeDelta::FromMinutes(4))); - - main_thread_only() - .background_fifth_minute_task_duration_reporter.RecordTask( - queue_type, DurationOfIntervalOverlap( - start_time, end_time, - backgrounded_at + base::TimeDelta::FromMinutes(4), - backgrounded_at + base::TimeDelta::FromMinutes(5))); - - main_thread_only() - .background_after_fifth_minute_task_duration_reporter.RecordTask( - queue_type, - DurationOfIntervalOverlap( - start_time, end_time, - backgrounded_at + base::TimeDelta::FromMinutes(5), - std::max(backgrounded_at + base::TimeDelta::FromMinutes(5), - end_time))); - } else { - main_thread_only().foreground_task_duration_reporter.RecordTask(queue_type, - duration); - - // For foreground tabs we do not expect such a notable difference as it is - // the case with background tabs, so we limit breakdown to three minutes. - base::TimeTicks foregrounded_at = - main_thread_only().background_status_changed_at; - - main_thread_only() - .foreground_first_minute_task_duration_reporter.RecordTask( - queue_type, DurationOfIntervalOverlap( - start_time, end_time, foregrounded_at, - foregrounded_at + base::TimeDelta::FromMinutes(1))); - - main_thread_only() - .foreground_second_minute_task_duration_reporter.RecordTask( - queue_type, DurationOfIntervalOverlap( - start_time, end_time, - foregrounded_at + base::TimeDelta::FromMinutes(1), - foregrounded_at + base::TimeDelta::FromMinutes(2))); - - main_thread_only() - .foreground_third_minute_task_duration_reporter.RecordTask( - queue_type, DurationOfIntervalOverlap( - start_time, end_time, - foregrounded_at + base::TimeDelta::FromMinutes(2), - foregrounded_at + base::TimeDelta::FromMinutes(3))); - - main_thread_only() - .foreground_after_third_minute_task_duration_reporter.RecordTask( - queue_type, - DurationOfIntervalOverlap( - start_time, end_time, - foregrounded_at + base::TimeDelta::FromMinutes(3), - std::max(foregrounded_at + base::TimeDelta::FromMinutes(3), - end_time))); - } - - if (main_thread_only().renderer_hidden) { - main_thread_only().hidden_task_duration_reporter.RecordTask(queue_type, - duration); - - if (ShouldDisableThrottlingBecauseOfAudio(start_time)) { - main_thread_only().hidden_music_task_duration_reporter.RecordTask( - queue_type, duration); - } - } else { - main_thread_only().visible_task_duration_reporter.RecordTask(queue_type, - duration); - } -} - -void RendererSchedulerImpl::RecordMainThreadTaskLoad(base::TimeTicks time, - double load) { - int load_percentage = static_cast<int>(load * 100); - DCHECK_LE(load_percentage, 100); - - UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME, load_percentage); - - if (main_thread_only().process_type == - RendererProcessType::kExtensionRenderer) { - UMA_HISTOGRAM_PERCENTAGE(EXTENSIONS_MAIN_THREAD_LOAD_METRIC_NAME, - load_percentage); - } - - TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), - "RendererScheduler.RendererMainThreadLoad", load_percentage); -} - -void RendererSchedulerImpl::RecordForegroundMainThreadTaskLoad( - base::TimeTicks time, - double load) { - int load_percentage = static_cast<int>(load * 100); - DCHECK_LE(load_percentage, 100); - - switch (main_thread_only().process_type) { - case RendererProcessType::kExtensionRenderer: - UMA_HISTOGRAM_PERCENTAGE(EXTENSIONS_MAIN_THREAD_LOAD_METRIC_NAME - ".Foreground", - load_percentage); - break; - case RendererProcessType::kRenderer: - UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME ".Foreground", - load_percentage); - - if (time - main_thread_only().background_status_changed_at > - base::TimeDelta::FromMinutes(1)) { - UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME - ".Foreground.AfterFirstMinute", - load_percentage); - } - break; - } - - TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), - "RendererScheduler.RendererMainThreadLoad.Foreground", - load_percentage); -} - -void RendererSchedulerImpl::RecordBackgroundMainThreadTaskLoad( - base::TimeTicks time, - double load) { - int load_percentage = static_cast<int>(load * 100); - DCHECK_LE(load_percentage, 100); - - switch (main_thread_only().process_type) { - case RendererProcessType::kExtensionRenderer: - UMA_HISTOGRAM_PERCENTAGE(EXTENSIONS_MAIN_THREAD_LOAD_METRIC_NAME - ".Background", - load_percentage); - break; - case RendererProcessType::kRenderer: - UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME ".Background", - load_percentage); - - if (time - main_thread_only().background_status_changed_at > - base::TimeDelta::FromMinutes(1)) { - UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME - ".Background.AfterFirstMinute", - load_percentage); - } - break; - } - - TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), - "RendererScheduler.RendererMainThreadLoad.Background", - load_percentage); + main_thread_only().metrics_helper.RecordTaskMetrics(queue->queue_type(), + start, end); } void RendererSchedulerImpl::OnBeginNestedRunLoop() {
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h index d314ef9..eb11315 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h +++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h
@@ -14,10 +14,10 @@ #include "base/synchronization/lock.h" #include "base/trace_event/trace_log.h" #include "device/base/synchronization/shared_memory_seqlock_buffer.h" +#include "platform/PlatformExport.h" #include "platform/scheduler/base/pollable_thread_safe_flag.h" #include "platform/scheduler/base/queueing_time_estimator.h" #include "platform/scheduler/base/task_time_observer.h" -#include "platform/scheduler/base/thread_load_tracker.h" #include "platform/scheduler/child/idle_canceled_delayed_task_sweeper.h" #include "platform/scheduler/child/idle_helper.h" #include "platform/scheduler/renderer/deadline_task_runner.h" @@ -25,8 +25,8 @@ #include "platform/scheduler/renderer/main_thread_scheduler_helper.h" #include "platform/scheduler/renderer/main_thread_task_queue.h" #include "platform/scheduler/renderer/render_widget_signals.h" +#include "platform/scheduler/renderer/renderer_metrics_helper.h" #include "platform/scheduler/renderer/task_cost_estimator.h" -#include "platform/scheduler/renderer/task_duration_metric_reporter.h" #include "platform/scheduler/renderer/user_model.h" #include "platform/scheduler/renderer/web_view_scheduler_impl.h" #include "public/platform/scheduler/renderer/renderer_scheduler.h" @@ -253,9 +253,12 @@ scoped_refptr<base::SingleThreadTaskRunner> TimerTaskRunner() override; private: - friend class RendererSchedulerImplTest; - friend class RendererSchedulerImplForTest; friend class RenderWidgetSchedulingState; + friend class RendererMetricsHelper; + + friend class RendererMetricsHelperTest; + friend class RendererSchedulerImplForTest; + friend class RendererSchedulerImplTest; FRIEND_TEST_ALL_PREFIXES(RendererSchedulerImplTest, Tracing); enum class ExpensiveTaskPolicy { RUN, BLOCK, THROTTLE }; @@ -505,14 +508,6 @@ void AddQueueToWakeUpBudgetPool(MainThreadTaskQueue* queue); - void RecordTaskMetrics(MainThreadTaskQueue::QueueType queue_type, - base::TimeTicks start_time, - base::TimeTicks end_time); - - void RecordMainThreadTaskLoad(base::TimeTicks time, double load); - void RecordForegroundMainThreadTaskLoad(base::TimeTicks time, double load); - void RecordBackgroundMainThreadTaskLoad(base::TimeTicks time, double load); - MainThreadSchedulerHelper helper_; IdleHelper idle_helper_; IdleCanceledDelayedTaskSweeper idle_canceled_delayed_task_sweeper_; @@ -560,9 +555,6 @@ TaskCostEstimator loading_task_cost_estimator; TaskCostEstimator timer_task_cost_estimator; IdleTimeEstimator idle_time_estimator; - ThreadLoadTracker main_thread_load_tracker; - ThreadLoadTracker background_main_thread_load_tracker; - ThreadLoadTracker foreground_main_thread_load_tracker; UseCase current_use_case; Policy current_policy; base::TimeTicks current_policy_expiration_time; @@ -601,25 +593,7 @@ std::set<WebViewSchedulerImpl*> web_view_schedulers; // Not owned. RAILModeObserver* rail_mode_observer; // Not owned. WakeUpBudgetPool* wake_up_budget_pool; // Not owned. - base::Optional<base::TimeTicks> last_reported_task; - TaskDurationMetricReporter task_duration_reporter; - TaskDurationMetricReporter foreground_task_duration_reporter; - TaskDurationMetricReporter foreground_first_minute_task_duration_reporter; - TaskDurationMetricReporter foreground_second_minute_task_duration_reporter; - TaskDurationMetricReporter foreground_third_minute_task_duration_reporter; - TaskDurationMetricReporter - foreground_after_third_minute_task_duration_reporter; - TaskDurationMetricReporter background_task_duration_reporter; - TaskDurationMetricReporter background_first_minute_task_duration_reporter; - TaskDurationMetricReporter background_second_minute_task_duration_reporter; - TaskDurationMetricReporter background_third_minute_task_duration_reporter; - TaskDurationMetricReporter background_fourth_minute_task_duration_reporter; - TaskDurationMetricReporter background_fifth_minute_task_duration_reporter; - TaskDurationMetricReporter - background_after_fifth_minute_task_duration_reporter; - TaskDurationMetricReporter hidden_task_duration_reporter; - TaskDurationMetricReporter visible_task_duration_reporter; - TaskDurationMetricReporter hidden_music_task_duration_reporter; + RendererMetricsHelper metrics_helper; RendererProcessType process_type; };
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn index 7799699..fb46e7d1 100644 --- a/third_party/WebKit/public/BUILD.gn +++ b/third_party/WebKit/public/BUILD.gn
@@ -474,7 +474,6 @@ "web/WebColorChooser.h", "web/WebColorChooserClient.h", "web/WebColorSuggestion.h", - "web/WebCompositionUnderline.h", "web/WebConsoleMessage.h", "web/WebContextFeatures.h", "web/WebContextMenuData.h", @@ -528,6 +527,7 @@ "web/WebIconURL.h", "web/WebImageCache.h", "web/WebImageDecoder.h", + "web/WebImeTextSpan.h", "web/WebInputElement.h", "web/WebInputMethodController.h", "web/WebKit.h",
diff --git a/third_party/WebKit/public/web/WebCompositionUnderline.h b/third_party/WebKit/public/web/WebImeTextSpan.h similarity index 80% rename from third_party/WebKit/public/web/WebCompositionUnderline.h rename to third_party/WebKit/public/web/WebImeTextSpan.h index 0b7f83e..53b1314 100644 --- a/third_party/WebKit/public/web/WebCompositionUnderline.h +++ b/third_party/WebKit/public/web/WebImeTextSpan.h
@@ -28,41 +28,37 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebCompositionUnderline_h -#define WebCompositionUnderline_h +#ifndef WebImeTextSpan_h +#define WebImeTextSpan_h #include "public/platform/WebColor.h" namespace blink { -// Class WebCompositionUnderline is intended to be used with WebWidget's +// Class WebImeTextSpan is intended to be used with WebWidget's // setComposition() method. -struct WebCompositionUnderline { - WebCompositionUnderline() +struct WebImeTextSpan { + WebImeTextSpan() : start_offset(0), end_offset(0), color(0), thick(false), background_color(0) {} - WebCompositionUnderline(unsigned s, - unsigned e, - WebColor c, - bool t, - WebColor bc) + WebImeTextSpan(unsigned s, unsigned e, WebColor c, bool t, WebColor bc) : start_offset(s), end_offset(e), color(c), thick(t), background_color(bc) {} - bool operator<(const WebCompositionUnderline& other) const { + bool operator<(const WebImeTextSpan& other) const { return start_offset != other.start_offset ? start_offset < other.start_offset : end_offset < other.end_offset; } - // Need to update IPC_STRUCT_TRAITS_BEGIN(blink::WebCompositionUnderline) + // Need to update IPC_STRUCT_TRAITS_BEGIN(blink::WebImeTextSpan) // if members change. unsigned start_offset; unsigned end_offset;
diff --git a/third_party/WebKit/public/web/WebInputMethodController.h b/third_party/WebKit/public/web/WebInputMethodController.h index d95ee7e..161d47f 100644 --- a/third_party/WebKit/public/web/WebInputMethodController.h +++ b/third_party/WebKit/public/web/WebInputMethodController.h
@@ -5,9 +5,9 @@ #ifndef WebInputMethodController_h #define WebInputMethodController_h -#include "public/platform/WebTextInputInfo.h" -#include "WebCompositionUnderline.h" +#include "WebImeTextSpan.h" #include "WebWidget.h" +#include "public/platform/WebTextInputInfo.h" namespace blink { @@ -31,19 +31,18 @@ // text will be canceled. |replacementRange| (when not null) is the range in // current text which should be replaced by |text|. Returns true if the // composition text was set successfully. - virtual bool SetComposition( - const WebString& text, - const WebVector<WebCompositionUnderline>& underlines, - const WebRange& replacement_range, - int selection_start, - int selection_end) = 0; + virtual bool SetComposition(const WebString& text, + const WebVector<WebImeTextSpan>& ime_text_spans, + const WebRange& replacement_range, + int selection_start, + int selection_end) = 0; // Called to inform the controller to delete the ongoing composition if any, // insert |text|, and move the caret according to |relativeCaretPosition|. // |replacementRange| (when not null) is the range in current text which // should be replaced by |text|. virtual bool CommitText(const WebString& text, - const WebVector<WebCompositionUnderline>& underlines, + const WebVector<WebImeTextSpan>& ime_text_spans, const WebRange& replacement_range, int relative_caret_position) = 0;
diff --git a/third_party/WebKit/public/web/WebLocalFrame.h b/third_party/WebKit/public/web/WebLocalFrame.h index b9ef892..d14a18de 100644 --- a/third_party/WebKit/public/web/WebLocalFrame.h +++ b/third_party/WebKit/public/web/WebLocalFrame.h
@@ -8,10 +8,10 @@ #include <memory> #include <set> -#include "WebCompositionUnderline.h" #include "WebFrame.h" #include "WebFrameLoadType.h" #include "WebHistoryItem.h" +#include "WebImeTextSpan.h" #include "public/platform/WebCachePolicy.h" #include "public/platform/WebFocusType.h" #include "public/platform/WebSize.h" @@ -503,7 +503,7 @@ virtual bool SetCompositionFromExistingText( int composition_start, int composition_end, - const WebVector<WebCompositionUnderline>& underlines) = 0; + const WebVector<WebImeTextSpan>& ime_text_spans) = 0; virtual void ExtendSelectionAndDelete(int before, int after) = 0; virtual void SetCaretVisible(bool) = 0;
diff --git a/third_party/WebKit/public/web/WebPlugin.h b/third_party/WebKit/public/web/WebPlugin.h index ff9fe31..1db7778 100644 --- a/third_party/WebKit/public/web/WebPlugin.h +++ b/third_party/WebKit/public/web/WebPlugin.h
@@ -47,7 +47,7 @@ class WebDragData; class WebPluginContainer; class WebURLResponse; -struct WebCompositionUnderline; +struct WebImeTextSpan; struct WebCursorInfo; struct WebPrintParams; struct WebPrintPresetOptions; @@ -170,12 +170,11 @@ // Sets composition text from input method, and returns true if the // composition is set successfully. If |replacementRange| is not null, the // text inside |replacementRange| will be replaced by |text| - virtual bool SetComposition( - const WebString& text, - const WebVector<WebCompositionUnderline>& underlines, - const WebRange& replacement_range, - int selection_start, - int selection_end) { + virtual bool SetComposition(const WebString& text, + const WebVector<WebImeTextSpan>& ime_text_spans, + const WebRange& replacement_range, + int selection_start, + int selection_end) { return false; } @@ -183,7 +182,7 @@ // moves the caret according to relativeCaretPosition. If |replacementRange| // is not null, the text inside |replacementRange| will be replaced by |text|. virtual bool CommitText(const WebString& text, - const WebVector<WebCompositionUnderline>& underlines, + const WebVector<WebImeTextSpan>& ime_text_spans, const WebRange& replacement_range, int relative_caret_position) { return false;
diff --git a/third_party/WebKit/public/web/WebWidget.h b/third_party/WebKit/public/web/WebWidget.h index 2a34655..bf139ef3 100644 --- a/third_party/WebKit/public/web/WebWidget.h +++ b/third_party/WebKit/public/web/WebWidget.h
@@ -41,7 +41,7 @@ #include "public/platform/WebRect.h" #include "public/platform/WebSize.h" #include "public/platform/WebTextInputInfo.h" -#include "public/web/WebCompositionUnderline.h" +#include "public/web/WebImeTextSpan.h" #include "public/web/WebRange.h" #include "public/web/WebTextDirection.h"
diff --git a/third_party/bazel/desugar/BUILD.gn b/third_party/bazel/desugar/BUILD.gn new file mode 100644 index 0000000..bff746ab --- /dev/null +++ b/third_party/bazel/desugar/BUILD.gn
@@ -0,0 +1,11 @@ +# 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. + +import("//build/config/android/rules.gni") + +# Provides runtime support for desugar transformations. +java_prebuilt("desugar_runtime_java") { + supports_android = true + jar_path = "Desugar-runtime.jar" +}
diff --git a/third_party/bazel/desugar/Desugar-runtime.jar b/third_party/bazel/desugar/Desugar-runtime.jar new file mode 100644 index 0000000..b04c6b83 --- /dev/null +++ b/third_party/bazel/desugar/Desugar-runtime.jar Binary files differ
diff --git a/third_party/bazel/desugar/README.chromium b/third_party/bazel/desugar/README.chromium index 8243288..368566f 100644 --- a/third_party/bazel/desugar/README.chromium +++ b/third_party/bazel/desugar/README.chromium
@@ -14,8 +14,10 @@ such as lambda experssions for Chrome on Android. Local Modifications: -Desugar.jar is the "Desugar_deploy.jar" target defined in -[bazel]src/tools/android/java/com/google/devtools/build/android/desugar/BUILD +* Desugar.jar is the "Desugar_deploy.jar" target defined in + [bazel]src/tools/android/java/com/google/devtools/build/android/desugar/BUILD +* Desugar-runtime.jar is derived from Desugar.jar (refer to update + instructions). Update instructions (requires @google.com account for uploading): - Check out Bazel from https://github.com/bazelbuild/bazel @@ -30,4 +32,7 @@ $ download_from_google_storage --config - Upload new jar to gcloud. In third_party/bazel/desugar, run $ upload_to_google_storage.py -b chromium-android-tools/bazel/desugar Desugar.jar - +- Update Desugar-runtime.jar: +$ unzip Desugar.jar "com/google/devtools/build/android/desugar/runtime*" +$ zip -rD0 Desugar-runtime.jar com +$ rm -r com
diff --git a/third_party/gvr-android-sdk/BUILD.gn b/third_party/gvr-android-sdk/BUILD.gn index 223ba74..b00908d 100644 --- a/third_party/gvr-android-sdk/BUILD.gn +++ b/third_party/gvr-android-sdk/BUILD.gn
@@ -7,6 +7,9 @@ android_aar_prebuilt("controller_test_api_java") { aar_path = "test-libraries/controller_test_api.aar" proguard_configs = [ "test-libraries/proguard.txt" ] + + # Jar includes conflicting copies of Desugar-runtime.jar classes. + jar_excluded_patterns = [ "*ThrowableExtension*.class" ] } android_aar_prebuilt("gvr_common_java") {
diff --git a/third_party/gvr-android-sdk/test-apks/daydream_home/apk_version_history.txt b/third_party/gvr-android-sdk/test-apks/daydream_home/apk_version_history.txt index 9200f48..f70d4aa 100644 --- a/third_party/gvr-android-sdk/test-apks/daydream_home/apk_version_history.txt +++ b/third_party/gvr-android-sdk/test-apks/daydream_home/apk_version_history.txt
@@ -7,3 +7,4 @@ v1.5 a02e2f95aa6f741f2be0ae03a4829e21fd749cf3 v1.6 43b876df3398687dfa1ae059ef2f64009c76254e v1.7 d5c72438acffe723e7717c45deedd8431bc613e7 +v1.8 cbc81aa4db5986f25d2c967f9b1e247cf07cd75e
diff --git a/third_party/gvr-android-sdk/test-apks/daydream_home/daydream_home_current.apk.sha1 b/third_party/gvr-android-sdk/test-apks/daydream_home/daydream_home_current.apk.sha1 index 31836cd7..11fa641 100644 --- a/third_party/gvr-android-sdk/test-apks/daydream_home/daydream_home_current.apk.sha1 +++ b/third_party/gvr-android-sdk/test-apks/daydream_home/daydream_home_current.apk.sha1
@@ -1 +1 @@ -d5c72438acffe723e7717c45deedd8431bc613e7 \ No newline at end of file +cbc81aa4db5986f25d2c967f9b1e247cf07cd75e \ No newline at end of file
diff --git a/third_party/gvr-android-sdk/test-apks/vr_services/apk_version_history.txt b/third_party/gvr-android-sdk/test-apks/vr_services/apk_version_history.txt index 4831ae6..2b7c0f5c 100644 --- a/third_party/gvr-android-sdk/test-apks/vr_services/apk_version_history.txt +++ b/third_party/gvr-android-sdk/test-apks/vr_services/apk_version_history.txt
@@ -10,3 +10,4 @@ v1.5 5d6d55728c7c728cef5416f37b0b71615719474e v1.6 abcdae2281956a76aa3b98d2e8f05a1975170dd0 v1.7 fcfa178173a2c0cab9c7d51829c2ee76ab66e1d9 +v1.8 f8f45ebf1963c5f9862218baca120ea974b87a08
diff --git a/third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk.sha1 b/third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk.sha1 index fb68207..c4102cf 100644 --- a/third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk.sha1 +++ b/third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk.sha1
@@ -1 +1 @@ -fcfa178173a2c0cab9c7d51829c2ee76ab66e1d9 \ No newline at end of file +f8f45ebf1963c5f9862218baca120ea974b87a08 \ No newline at end of file
diff --git a/tools/json_schema_compiler/test/features_generation_unittest.cc b/tools/json_schema_compiler/test/features_generation_unittest.cc index 28a90ed..81ab003 100644 --- a/tools/json_schema_compiler/test/features_generation_unittest.cc +++ b/tools/json_schema_compiler/test/features_generation_unittest.cc
@@ -35,7 +35,7 @@ explicit FeatureComparator(const std::string& name); ~FeatureComparator(); - void CompareFeature(SimpleFeature* feature); + void CompareFeature(const SimpleFeature* feature); std::string name; std::vector<std::string> blacklist; @@ -66,7 +66,7 @@ FeatureComparator::~FeatureComparator() {} -void FeatureComparator::CompareFeature(SimpleFeature* feature) { +void FeatureComparator::CompareFeature(const SimpleFeature* feature) { ASSERT_TRUE(feature); EXPECT_EQ(name, feature->name()); ExpectVectorsEqual(blacklist, feature->blacklist(), name); @@ -95,22 +95,22 @@ CompilerTestFeatureProvider provider; auto GetAsSimpleFeature = [&provider](const std::string& name) { - Feature* feature = provider.GetFeature(name); + const Feature* feature = provider.GetFeature(name); // Shame we can't test this more safely, but if our feature is declared as // the wrong class, things should blow up in a spectacular fashion. - return static_cast<SimpleFeature*>(feature); + return static_cast<const SimpleFeature*>(feature); }; auto GetAsComplexFeature = [&provider](const std::string& name) { - Feature* feature = provider.GetFeature(name); + const Feature* feature = provider.GetFeature(name); // Shame we can't test this more safely, but if our feature is declared as // the wrong class, things should blow up in a spectacular fashion. - return static_cast<ComplexFeature*>(feature); + return static_cast<const ComplexFeature*>(feature); }; // Check some simple features for accuracy. { - SimpleFeature* feature = GetAsSimpleFeature("alpha"); + const SimpleFeature* feature = GetAsSimpleFeature("alpha"); FeatureComparator comparator("alpha"); comparator.dependencies = {"permission:alpha"}; comparator.contexts = {Feature::BLESSED_EXTENSION_CONTEXT}; @@ -120,7 +120,7 @@ comparator.CompareFeature(feature); } { - SimpleFeature* feature = GetAsSimpleFeature("beta"); + const SimpleFeature* feature = GetAsSimpleFeature("beta"); FeatureComparator comparator("beta"); comparator.contexts = {Feature::BLESSED_EXTENSION_CONTEXT}; comparator.channel.reset( @@ -134,7 +134,7 @@ comparator.CompareFeature(feature); } { - SimpleFeature* feature = GetAsSimpleFeature("gamma"); + const SimpleFeature* feature = GetAsSimpleFeature("gamma"); FeatureComparator comparator("gamma"); comparator.channel.reset( new version_info::Channel(version_info::Channel::BETA)); @@ -157,7 +157,7 @@ { // Features that specify 'noparent' should not inherit features from any // other feature. - SimpleFeature* feature = GetAsSimpleFeature("gamma.unparented"); + const SimpleFeature* feature = GetAsSimpleFeature("gamma.unparented"); FeatureComparator comparator("gamma.unparented"); comparator.blacklist = {"ddd"}; comparator.contexts = {Feature::UNBLESSED_EXTENSION_CONTEXT}; @@ -166,7 +166,7 @@ comparator.CompareFeature(feature); } { - ComplexFeature* complex_feature = + const ComplexFeature* complex_feature = GetAsComplexFeature("gamma.complex_unparented"); FeatureComparator comparator("gamma.complex_unparented"); comparator.contexts = {Feature::UNBLESSED_EXTENSION_CONTEXT}; @@ -178,7 +178,7 @@ comparator.CompareFeature(static_cast<SimpleFeature*>(feature.get())); } { - SimpleFeature* feature = GetAsSimpleFeature("delta"); + const SimpleFeature* feature = GetAsSimpleFeature("delta"); FeatureComparator comparator("delta"); comparator.contexts = {Feature::BLESSED_EXTENSION_CONTEXT, Feature::WEBUI_CONTEXT}; @@ -190,7 +190,7 @@ comparator.CompareFeature(feature); } { - SimpleFeature* feature = GetAsSimpleFeature("allEnum"); + const SimpleFeature* feature = GetAsSimpleFeature("allEnum"); FeatureComparator comparator("allEnum"); comparator.contexts = {Feature::BLESSED_EXTENSION_CONTEXT, Feature::BLESSED_WEB_PAGE_CONTEXT, @@ -210,7 +210,7 @@ } { // Omega is imported from a second .json file. - SimpleFeature* feature = GetAsSimpleFeature("omega"); + const SimpleFeature* feature = GetAsSimpleFeature("omega"); FeatureComparator comparator("omega"); comparator.contexts = {Feature::WEB_PAGE_CONTEXT}; comparator.channel.reset( @@ -220,24 +220,24 @@ } { // Features specifying 'nocompile' should not be generated at all. - SimpleFeature* feature = GetAsSimpleFeature("uncompiled"); + const SimpleFeature* feature = GetAsSimpleFeature("uncompiled"); EXPECT_FALSE(feature); } // Test complex features. { - ComplexFeature* feature = GetAsComplexFeature("complex"); + const ComplexFeature* feature = GetAsComplexFeature("complex"); ASSERT_TRUE(feature); EXPECT_EQ(2u, feature->features_.size()); // Find the default parent. This is a little tedious because it might not // be guaranteed that the default_parent is in a specific index, but it // specifies channel as 'stable'. - SimpleFeature* default_parent = nullptr; - SimpleFeature* other_parent = nullptr; + const SimpleFeature* default_parent = nullptr; + const SimpleFeature* other_parent = nullptr; { - SimpleFeature* parent1 = + const SimpleFeature* parent1 = static_cast<SimpleFeature*>(feature->features_[0].get()); - SimpleFeature* parent2 = + const SimpleFeature* parent2 = static_cast<SimpleFeature*>(feature->features_[1].get()); if (parent1->channel() == version_info::Channel::STABLE) { default_parent = parent1; @@ -257,7 +257,7 @@ comparator.CompareFeature(default_parent); // Check the child of the complex feature. It should inherit its // properties from the default parent. - SimpleFeature* child_feature = GetAsSimpleFeature("complex.child"); + const SimpleFeature* child_feature = GetAsSimpleFeature("complex.child"); comparator.name = "complex.child"; comparator.platforms = {Feature::WIN_PLATFORM}; comparator.dependencies = {"permission:complex.child"}; @@ -277,7 +277,7 @@ // Test API aliases. { - SimpleFeature* feature = GetAsSimpleFeature("alias"); + const SimpleFeature* feature = GetAsSimpleFeature("alias"); FeatureComparator comparator("alias"); comparator.contexts = {Feature::BLESSED_EXTENSION_CONTEXT}; comparator.channel.reset( @@ -286,7 +286,7 @@ comparator.CompareFeature(feature); } { - SimpleFeature* feature = GetAsSimpleFeature("alias_source"); + const SimpleFeature* feature = GetAsSimpleFeature("alias_source"); FeatureComparator comparator("alias_source"); comparator.contexts = {Feature::BLESSED_EXTENSION_CONTEXT}; comparator.channel.reset( @@ -295,37 +295,37 @@ comparator.CompareFeature(feature); } { - Feature* feature = provider.GetFeature("complex_alias"); + const Feature* feature = provider.GetFeature("complex_alias"); ASSERT_EQ("", feature->alias()); ASSERT_EQ("complex_alias_source", feature->source()); } { - Feature* feature = provider.GetFeature("complex_alias_source"); + const Feature* feature = provider.GetFeature("complex_alias_source"); ASSERT_EQ("complex_alias", feature->alias()); ASSERT_EQ("", feature->source()); } { - Feature* feature = provider.GetFeature("parent_source"); + const Feature* feature = provider.GetFeature("parent_source"); ASSERT_EQ("parent_source_alias", feature->alias()); ASSERT_EQ("", feature->source()); } { - Feature* feature = provider.GetFeature("parent_source.child"); + const Feature* feature = provider.GetFeature("parent_source.child"); ASSERT_EQ("parent_source_alias", feature->alias()); ASSERT_EQ("", feature->source()); } { - Feature* feature = provider.GetFeature("parent_source.child_source"); + const Feature* feature = provider.GetFeature("parent_source.child_source"); ASSERT_EQ("parent_source_child_alias", feature->alias()); ASSERT_EQ("", feature->source()); } { - Feature* feature = provider.GetFeature("alias_parent"); + const Feature* feature = provider.GetFeature("alias_parent"); ASSERT_EQ("", feature->alias()); ASSERT_EQ("", feature->source()); } { - Feature* feature = provider.GetFeature("alias_parent.child"); + const Feature* feature = provider.GetFeature("alias_parent.child"); ASSERT_EQ("", feature->alias()); ASSERT_EQ("child_source", feature->source()); }
diff --git a/tools/luci-go/linux64/isolate.sha1 b/tools/luci-go/linux64/isolate.sha1 index acecc79..f923147 100644 --- a/tools/luci-go/linux64/isolate.sha1 +++ b/tools/luci-go/linux64/isolate.sha1
@@ -1 +1 @@ -21410c557b49620e8a44ec0f861f94605bdc6d5c +48ffe036be8eff7d39ebbdbb705bd26f0ec6f404
diff --git a/tools/luci-go/mac64/isolate.sha1 b/tools/luci-go/mac64/isolate.sha1 index 16a7dd6a..328cc06 100644 --- a/tools/luci-go/mac64/isolate.sha1 +++ b/tools/luci-go/mac64/isolate.sha1
@@ -1 +1 @@ -1966687828a068eee4c5da45bbb8afd91cddda6f +f0d9ea71e7059a164962658b588286ebf262c5dd
diff --git a/tools/luci-go/win64/isolate.exe.sha1 b/tools/luci-go/win64/isolate.exe.sha1 index 6f5491d..8038c79 100644 --- a/tools/luci-go/win64/isolate.exe.sha1 +++ b/tools/luci-go/win64/isolate.exe.sha1
@@ -1 +1 @@ -35482264cea0f9b9dd2efe0a01620557fc15b7c1 +40790017e9b7856009c36768bf9244a4182ad5d1
diff --git a/tools/mb/docs/user_guide.md b/tools/mb/docs/user_guide.md index d31ea67..0abb235 100644 --- a/tools/mb/docs/user_guide.md +++ b/tools/mb/docs/user_guide.md
@@ -167,6 +167,18 @@ This is mostly useful as a presubmit check and for verifying changes to the config file. +### `mb gerrit-buildbucket-config` + +Generates a gerrit buildbucket configuration file and prints it to +stdout. This file contains the list of trybots shown in gerrit's UI. + +The master copy of the buildbucket.config file lives +in a separate branch of the chromium repository. Run `mb +gerrit-buildbucket-config > buildbucket.config.new && git fetch origin +refs/meta/config:refs/remotes/origin/meta/config && git checkout +-t -b meta_config origin/meta/config && mv buildbucket.config.new +buildbucket.config` to update the file. + ## Isolates and Swarming `mb gen` is also responsible for generating the `.isolate` and
diff --git a/tools/mb/mb.py b/tools/mb/mb.py index 6905bcc..90c42bf 100755 --- a/tools/mb/mb.py +++ b/tools/mb/mb.py
@@ -56,6 +56,7 @@ self.sep = os.sep self.args = argparse.Namespace() self.configs = {} + self.luci_tryservers = {} self.masters = {} self.mixins = {} @@ -235,6 +236,14 @@ ' do compiles') subp.set_defaults(func=self.CmdAudit) + subp = subps.add_parser('gerrit-buildbucket-config', + help='Print buildbucket.config for gerrit ' + '(see MB user guide)') + subp.add_argument('-f', '--config-file', metavar='PATH', + default=self.default_config, + help='path to config file (default is %(default)s)') + subp.set_defaults(func=self.CmdBuildbucket) + subp = subps.add_parser('help', help='Get help on a subcommand.') subp.add_argument(nargs='?', action='store', dest='subcommand', @@ -368,6 +377,25 @@ return ret + def CmdBuildbucket(self): + self.ReadConfigFile() + + self.Print('# This file was generated using ' + '"tools/mb/mb.py gerrit-buildbucket-config".') + + for luci_tryserver in sorted(self.luci_tryservers): + self.Print('[bucket "luci.%s"]' % luci_tryserver) + for bot in sorted(self.luci_tryservers[luci_tryserver]): + self.Print('\tbuilder = %s' % bot) + + for master in sorted(self.masters): + if master.startswith('tryserver.'): + self.Print('[bucket "master.%s"]' % master) + for bot in sorted(self.masters[master]): + self.Print('\tbuilder = %s' % bot) + + return 0 + def CmdValidate(self, print_ok=True): errs = [] @@ -674,6 +702,7 @@ (self.args.config_file, e)) self.configs = contents['configs'] + self.luci_tryservers = contents.get('luci_tryservers', {}) self.masters = contents['masters'] self.mixins = contents['mixins']
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 063438b..32c68f6 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -525,6 +525,7 @@ 'cast_shell_audio_linux': 'cast_audio_release_trybot', 'chromeos_amd64-generic_chromium_compile_only_ng': 'cros_chrome_sdk', 'chromeos_daisy_chromium_compile_only_ng': 'cros_chrome_sdk', + 'chromium_presubmit': 'presubmit', 'closure_compilation': 'closure_compilation', 'fuchsia': 'release_trybot_fuchsia', 'fuchsia_compile': 'release_trybot_fuchsia', @@ -1415,6 +1416,11 @@ 'ozone_linux', 'release_trybot', ], + 'presubmit': [ + # The chromium_presubmit bot does not use mb. + 'error', + ], + 'release_afl_asan': [ 'release', 'afl', 'asan', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', ], @@ -1995,4 +2001,8 @@ 'gn_args': 'target_cpu="x86"', }, }, + + 'luci_tryservers': { + 'chromium.try': [ 'LUCI linux_chromium_rel_ng' ], + }, }
diff --git a/tools/mb/mb_unittest.py b/tools/mb/mb_unittest.py index 29b75cf..73c3e9c 100755 --- a/tools/mb/mb_unittest.py +++ b/tools/mb/mb_unittest.py
@@ -220,6 +220,28 @@ } """ +TRYSERVER_CONFIG = """\ +{ + 'masters': { + 'not_a_tryserver': { + 'fake_builder': 'fake_config', + }, + 'tryserver.chromium.linux': { + 'try_builder': 'fake_config', + }, + 'tryserver.chromium.mac': { + 'try_builder2': 'fake_config', + }, + }, + 'luci_tryservers': { + 'luci_tryserver1': ['luci_builder1'], + 'luci_tryserver2': ['luci_builder2'], + }, + 'configs': {}, + 'mixins': {}, +} +""" + class UnitTest(unittest.TestCase): def fake_mbw(self, files=None, win32=False): @@ -555,6 +577,22 @@ "LLVM_FORCE_HEAD_REVISION=1\n" "python build/gyp_chromium -G output_dir=_path_\n")) + def test_buildbucket(self): + mbw = self.fake_mbw() + mbw.files[mbw.default_config] = TRYSERVER_CONFIG + self.check(['gerrit-buildbucket-config'], mbw=mbw, + ret=0, + out=('# This file was generated using ' + '"tools/mb/mb.py gerrit-buildbucket-config".\n' + '[bucket "luci.luci_tryserver1"]\n' + '\tbuilder = luci_builder1\n' + '[bucket "luci.luci_tryserver2"]\n' + '\tbuilder = luci_builder2\n' + '[bucket "master.tryserver.chromium.linux"]\n' + '\tbuilder = try_builder\n' + '[bucket "master.tryserver.chromium.mac"]\n' + '\tbuilder = try_builder2\n')) + if __name__ == '__main__': unittest.main()
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 3b98f244..03704cd 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -22641,6 +22641,23 @@ <int value="4" label="Success"/> </enum> +<enum name="LockScreenActionAvailability"> + <int value="0" label="Available"/> + <int value="1" label="Not available - no action handler app"/> + <int value="2" label="Not available - app with no lock screen support"/> + <int value="3" label="Not available - action not enabled on lock screen"/> + <int value="4" label="Not available - disallowed by policy"/> +</enum> + +<enum name="LockScreenAppSessionState"> + <int value="0" label="Not launched"/> + <int value="1" label="Launching"/> + <int value="2" label="App window created"/> + <int value="3" label="App window shown"/> + <int value="4" label="App window in foreground"/> + <int value="5" label="App window in background"/> +</enum> + <enum name="LockScreenDataItemOperationResult"> <int value="0" label="Success"/> <int value="1" label="Operation failed"/> @@ -22651,6 +22668,22 @@ <int value="6" label="Wrong encryption key"/> </enum> +<enum name="LockScreenNoteTakingExitReason"> + <int value="0" label="Session was unlocked"/> + <int value="1" label="Session shutdown"/> + <int value="2" label="Screen turned off"/> + <int value="3" label="Device suspended"/> + <int value="4" label="App window closed"/> + <int value="5" label="Lock screen note taking disabled"/> +</enum> + +<enum name="LockScreenNoteTakingUnlockUIAction"> + <int value="0" label="User unlocked the session"/> + <int value="1" label="Session unlock was cancelled"/> + <int value="2" label="Device shut down"/> + <int value="3" label="User signed out"/> +</enum> + <enum name="LockScreenProgress"> <int value="0" label="Start screen lock"/> <int value="1" label="Enter password correctly"/> @@ -22670,6 +22703,7 @@ <int value="-2143328006" label="enable-fill-on-account-select-no-highlighting"/> <int value="-2143113994" label="enable-ephemeral-apps-in-webstore"/> + <int value="-2141661938" label="AnimatedAppMenuIcon:enabled"/> <int value="-2134717874" label="Multidevice:disabled"/> <int value="-2134333982" label="ShowArcFilesApp:enabled"/> <int value="-2134244069" label="HttpFormWarning:enabled"/> @@ -23505,6 +23539,7 @@ <int value="506680761" label="WebNFC:disabled"/> <int value="510814146" label="OfflineBookmarks:enabled"/> <int value="513356954" label="InstantTethering:disabled"/> + <int value="517568645" label="AnimatedAppMenuIcon:disabled"/> <int value="535131384" label="OmniboxTailSuggestions:enabled"/> <int value="535976218" label="enable-plugin-power-saver"/> <int value="538468149" label="OfflinePagesCT:enabled"/> @@ -27021,6 +27056,14 @@ <int value="6" label="Unknown"/> </enum> +<enum name="NewLockScreenNoteRequestType"> + <int value="0" label="System tray action"/> + <int value="1" label="Lock screen - button tap"/> + <int value="2" label="Lock screen - swipe gesture"/> + <int value="3" label="Lock screen - button activated by keyboard"/> + <int value="4" label="Stylus ejected"/> +</enum> + <enum name="NewTabPageActionAndroid"> <obsolete> Deprecated as of 01/2017. Replaced by NewTabPageActionAndroid2.
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 375f689..56edb6b 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -1803,6 +1803,120 @@ </summary> </histogram> +<histogram base="true" name="Apps.LockScreen.NoteTakingApp.AppWindowLifeTime" + units="ms"> + <owner>tbarzic@chromium.org</owner> + <owner>tbuckley@chromium.org</owner> + <summary> + The amount of time a lock screen enabled app window spent in a certain state + during the app window activity. The state to which the histogram refers to + is defined by the suffix. The metric is logged upon leaving the associated + state. + </summary> +</histogram> + +<histogram name="Apps.LockScreen.NoteTakingApp.AvailabilityOnScreenLock" + enum="LockScreenActionAvailability"> + <owner>tbarzic@chromium.org</owner> + <owner>tbuckley@chromium.org</owner> + <summary> + The note taking action availability state on the lock screen, recorded when + the user session is locked. + </summary> +</histogram> + +<histogram name="Apps.LockScreen.NoteTakingApp.FinalAppSessionState" + enum="LockScreenAppSessionState"> + <owner>tbarzic@chromium.org</owner> + <owner>tbuckley@chromium.org</owner> + <summary> + The state in which lock screen enabled note taking app was when the note + taking session ended. + </summary> +</histogram> + +<histogram name="Apps.LockScreen.NoteTakingApp.LaunchDurationAtLaunchCancel" + units="ms"> + <owner>tbarzic@chromium.org</owner> + <owner>tbuckley@chromium.org</owner> + <summary> + The amount time a lock screen app had been launching when the app launch was + canceled. Logged if the lock screen app session ends before the lock screen + app window is shown. + </summary> +</histogram> + +<histogram name="Apps.LockScreen.NoteTakingApp.LaunchRequestOrdinalNumber"> + <owner>tbarzic@chromium.org</owner> + <owner>tbuckley@chromium.org</owner> + <summary> + Ordinal number of a note taking app launch request from a lock screen within + a lock screen session. If a note taking app is launched n times during a + single lock screen session, this histogram will be reported with values 1 + through n. The launch counter is reset on screen unlock. + </summary> +</histogram> + +<histogram name="Apps.LockScreen.NoteTakingApp.LaunchRequestReason" + enum="NewLockScreenNoteRequestType"> + <owner>tbarzic@chromium.org</owner> + <owner>tbuckley@chromium.org</owner> + <summary> + The user action that launched note taking from the lock screen. + </summary> +</histogram> + +<histogram name="Apps.LockScreen.NoteTakingApp.LockScreenInstallationDuration" + units="ms"> + <owner>tbarzic@chromium.org</owner> + <owner>tbuckley@chromium.org</owner> + <summary> + Amount of time needed to install a copy of a lock screen note taking app + into lock screen apps profile. + </summary> +</histogram> + +<histogram name="Apps.LockScreen.NoteTakingApp.NoteTakingExitReason" + enum="LockScreenNoteTakingExitReason"> + <owner>tbarzic@chromium.org</owner> + <owner>tbuckley@chromium.org</owner> + <summary> + The reason the note taking on lock screen was ended (and lock screen app + window was closed). + </summary> +</histogram> + +<histogram name="Apps.LockScreen.NoteTakingApp.TimeToLoadAppWindowContents" + units="ms"> + <owner>tbarzic@chromium.org</owner> + <owner>tbuckley@chromium.org</owner> + <summary> + The amount of time needed to load a note taking app window contents on the + lock screen - i.e. the time passed from the user requesting an app launch to + the app window contents being loaded. + </summary> +</histogram> + +<histogram name="Apps.LockScreen.NoteTakingApp.TimeToShowWindow" units="ms"> + <owner>tbarzic@chromium.org</owner> + <owner>tbuckley@chromium.org</owner> + <summary> + The amount of time needed to launch a note taking app window from the lock + screen - i.e. the time passed from the user requesting an app launch to the + app window appearing on the screen. + </summary> +</histogram> + +<histogram name="Apps.LockScreen.NoteTakingApp.UnlockUIAction" + enum="LockScreenNoteTakingUnlockUIAction"> + <owner>tbarzic@chromium.org</owner> + <owner>tbuckley@chromium.org</owner> + <summary> + The action the user took on the lock screen UI shown when lock screen app + window is in background, shown under the lock screen. + </summary> +</histogram> + <histogram name="Apps.NoteTakingApp.DefaultLaunchResult" enum="NoteTakingAppLaunchResult"> <owner>derat@chromium.org</owner> @@ -53133,6 +53247,9 @@ </histogram> <histogram name="Parser.AppendBytesDelay" units="ms"> + <obsolete> + Deprecated Aug 2017 + </obsolete> <owner>csharrison@chromium.org</owner> <summary> The delay from when bytes are received on the main thread to when the @@ -53160,6 +53277,9 @@ </histogram> <histogram name="Parser.PeakPendingChunkCount" units="chunks"> + <obsolete> + Deprecated Aug 2017 + </obsolete> <owner>csharrison@chromium.org</owner> <summary> The maximum number of pending Chunks in the ParsedChunkQueue after the @@ -53168,6 +53288,9 @@ </histogram> <histogram name="Parser.PeakPendingTokenCount" units="tokens"> + <obsolete> + Deprecated Aug 2017 + </obsolete> <owner>csharrison@chromium.org</owner> <summary> The maximum number of pending tokens in the ParsedChunkQueue after the @@ -94223,6 +94346,16 @@ <affected-histogram name="Apps.LockScreen.DataItemStorage.OperationResult"/> </histogram_suffixes> +<histogram_suffixes name="LockScreenNoteTakingAppWindowState" separator="."> + <suffix name="Foreground" + label="The app window is in foreground (on top of the lock screen)"/> + <suffix name="Background" + label="The app window is in background (behind the lock screen)"/> + <suffix name="TotalActive" + label="The total amount of time an app window was active on lock screen"/> + <affected-histogram name="Apps.LockScreen.NoteTakingApp.AppWindowLifeTime"/> +</histogram_suffixes> + <histogram_suffixes name="LowMemoryMargin" separator="_"> <suffix name="default" label="Low memory margin set to the system default"/> <suffix name="off" label="Low memory notification disabled"/>
diff --git a/tools/perf/benchmark.csv b/tools/perf/benchmark.csv index db4f23a..91defb5 100644 --- a/tools/perf/benchmark.csv +++ b/tools/perf/benchmark.csv
@@ -10,6 +10,7 @@ blink_perf.dom,"jbroman@chromium.org, yukishiino@chromium.org, haraken@chromium.org", blink_perf.events,hayato@chromium.org, blink_perf.layout,eae@chromium.org, +blink_perf.owp_storage,dmurph@chromium.org, blink_perf.paint,wangxianzhu@chromium.org, blink_perf.parser,"jbroman@chromium.org, yukishiino@chromium.org, haraken@chromium.org", blink_perf.shadow_dom,hayato@chromium.org, @@ -51,8 +52,8 @@ power.steady_state,, power.trivial_pages,erikchen@chromium.org, power.typical_10_mobile,perezju@chromium.org, -rasterize_and_record_micro.partial_invalidation,, -rasterize_and_record_micro.top_25,, +rasterize_and_record_micro.partial_invalidation,"vmpstr@chromium.org, wkorman@chromium.org",Internals>Compositing>Rasterization +rasterize_and_record_micro.top_25,"vmpstr@chromium.org, wkorman@chromium.org",Internals>Compositing>Rasterization resource_sizes,"agrieve@chromium.org, rnephew@chromium.org, perezju@chromium.org", scheduler.tough_scheduling_cases,"skyostil@chromium.org, brianderson@chromium.org", service_worker.service_worker,horo@chromium.org,
diff --git a/tools/perf/benchmarks/blink_perf.py b/tools/perf/benchmarks/blink_perf.py index 2016be9e6..122785e 100644 --- a/tools/perf/benchmarks/blink_perf.py +++ b/tools/perf/benchmarks/blink_perf.py
@@ -358,7 +358,10 @@ def GetExpectations(self): class StoryExpectations(story.expectations.StoryExpectations): def SetExpectations(self): - pass # Nothing disabled. + self.DisableStory('structured-clone-long-string-deserialize.html', + [story.expectations.ALL_ANDROID], 'crbug.com/733655') + self.DisableStory('structured-clone-long-string-serialize.html', + [story.expectations.ALL_ANDROID], 'crbug.com/733655') return StoryExpectations() @@ -444,6 +447,19 @@ return Expectations() +@benchmark.Owner(emails=['dmurph@chromium.org']) +@benchmark.Disabled('all') +class BlinkPerfOWPStorage(_BlinkPerfBenchmark): + tag = 'owp_storage' + subdir = 'OWPStorage' + + def GetExpectations(self): + class StoryExpectations(story.expectations.StoryExpectations): + def SetExpectations(self): + pass # Nothing disabled. + return StoryExpectations() + + @benchmark.Owner(emails=['wangxianzhu@chromium.org']) class BlinkPerfPaint(_BlinkPerfBenchmark): tag = 'paint'
diff --git a/tools/perf/benchmarks/memory.py b/tools/perf/benchmarks/memory.py index 5722153..472b0b2 100644 --- a/tools/perf/benchmarks/memory.py +++ b/tools/perf/benchmarks/memory.py
@@ -132,6 +132,11 @@ return False @classmethod + def ShouldTearDownStateAfterEachStorySetRun(cls): + # Browser will now be closed as instructed by the shared state. + return False + + @classmethod def ValueCanBeAddedPredicate(cls, value, is_first_result): return DefaultValueCanBeAddedPredicateForMemoryMeasurement(value)
diff --git a/tools/perf/benchmarks/rasterize_and_record_micro.py b/tools/perf/benchmarks/rasterize_and_record_micro.py index 1a8ece57..c950055 100644 --- a/tools/perf/benchmarks/rasterize_and_record_micro.py +++ b/tools/perf/benchmarks/rasterize_and_record_micro.py
@@ -6,6 +6,7 @@ from measurements import rasterize_and_record_micro import page_sets +from telemetry import benchmark from telemetry import story @@ -43,6 +44,9 @@ options.record_repeat, options.timeout, options.report_detailed_results) +@benchmark.Owner( + emails=['vmpstr@chromium.org', 'wkorman@chromium.org'], + component='Internals>Compositing>Rasterization') class RasterizeAndRecordMicroTop25(_RasterizeAndRecordMicro): """Measures rasterize and record performance on the top 25 web pages. @@ -59,11 +63,14 @@ self.DisableStory('http://www.cnn.com', [story.expectations.ALL], 'crbug.com/528472') self.DisableStory('https://mail.google.com/mail/', - [story.expectations.ALL_LINUX], + [story.expectations.ALL], 'crbug.com/747021') return StoryExpectations() +@benchmark.Owner( + emails=['vmpstr@chromium.org', 'wkorman@chromium.org'], + component='Internals>Compositing>Rasterization') class RasterizeAndRecordMicroPartialInvalidation(_RasterizeAndRecordMicro): """Measures rasterize and record performance for partial inval. on big pages.
diff --git a/tools/perf/benchmarks/smoothness.py b/tools/perf/benchmarks/smoothness.py index 2cbc6f5..a790149 100644 --- a/tools/perf/benchmarks/smoothness.py +++ b/tools/perf/benchmarks/smoothness.py
@@ -439,7 +439,82 @@ def GetExpectations(self): class StoryExpectations(story_module.expectations.StoryExpectations): def SetExpectations(self): - pass # Nothing. + self.DisableStory('https://www.google.com/#hl=en&q=barack+obama', + [story_module.expectations.ALL_ANDROID, + story_module.expectations.ALL_WIN], + 'crbug.com/631015') + self.DisableStory('https://mail.google.com/mail/', + [story_module.expectations.ALL_ANDROID, + story_module.expectations.ALL_WIN], + 'crbug.com/631015') + self.DisableStory('https://www.google.com/calendar/', + [story_module.expectations.ALL_ANDROID, + story_module.expectations.ALL_WIN], + 'crbug.com/631015') + self.DisableStory('https://www.google.com/search?q=cats&tbm=isch', + [story_module.expectations.ALL_ANDROID, + story_module.expectations.ALL_WIN], + 'crbug.com/631015') + self.DisableStory('http://www.youtube.com', + [story_module.expectations.ALL_ANDROID, + story_module.expectations.ALL_WIN], + 'crbug.com/631015') + self.DisableStory('Blogger', + [story_module.expectations.ALL_ANDROID, + story_module.expectations.ALL_WIN], + 'crbug.com/631015') + self.DisableStory('Facebook', + [story_module.expectations.ALL_ANDROID, + story_module.expectations.ALL_WIN], + 'crbug.com/631015') + self.DisableStory('LinkedIn', + [story_module.expectations.ALL_ANDROID, + story_module.expectations.ALL_WIN], + 'crbug.com/631015') + self.DisableStory('Wikipedia (1 tab)', + [story_module.expectations.ALL_ANDROID, + story_module.expectations.ALL_WIN], + 'crbug.com/631015') + self.DisableStory('Twitter', + [story_module.expectations.ALL_ANDROID, + story_module.expectations.ALL_WIN], + 'crbug.com/631015') + self.DisableStory('ESPN', + [story_module.expectations.ALL_ANDROID, + story_module.expectations.ALL_WIN], + 'crbug.com/631015') + self.DisableStory('http://news.yahoo.com', + [story_module.expectations.ALL_ANDROID, + story_module.expectations.ALL_WIN], + 'crbug.com/631015') + self.DisableStory('http://www.cnn.com', + [story_module.expectations.ALL_ANDROID, + story_module.expectations.ALL_WIN], + 'crbug.com/631015') + self.DisableStory('Weather.com', + [story_module.expectations.ALL_ANDROID, + story_module.expectations.ALL_WIN], + 'crbug.com/631015') + self.DisableStory('http://www.amazon.com', + [story_module.expectations.ALL_ANDROID, + story_module.expectations.ALL_WIN], + 'crbug.com/631015') + self.DisableStory('http://www.ebay.com', + [story_module.expectations.ALL_ANDROID, + story_module.expectations.ALL_WIN], + 'crbug.com/631015') + self.DisableStory('http://games.yahoo.com', + [story_module.expectations.ALL_ANDROID, + story_module.expectations.ALL_WIN], + 'crbug.com/631015') + self.DisableStory('http://booking.com', + [story_module.expectations.ALL_ANDROID, + story_module.expectations.ALL_WIN], + 'crbug.com/631015') + self.DisableStory('http://sports.yahoo.com/', + [story_module.expectations.ALL_ANDROID, + story_module.expectations.ALL_WIN], + 'crbug.com/631015') return StoryExpectations() @@ -480,9 +555,63 @@ return 'smoothness.gpu_rasterization.tough_pinch_zoom_cases' def GetExpectations(self): + class StoryExpectations(story_module.expectations.StoryExpectations): + def SetExpectations(self): - pass # Nothing. + self.DisableStory('https://www.google.com/#hl=en&q=barack+obama', + [story_module.expectations.ALL_ANDROID], + 'crbug.com/610021') + self.DisableStory('https://mail.google.com/mail/', + [story_module.expectations.ALL_ANDROID], + 'crbug.com/610021') + self.DisableStory('https://www.google.com/calendar/', + [story_module.expectations.ALL_ANDROID], + 'crbug.com/610021') + self.DisableStory('https://www.google.com/search?q=cats&tbm=isch', + [story_module.expectations.ALL_ANDROID], + 'crbug.com/610021') + self.DisableStory('http://www.youtube.com', + [story_module.expectations.ALL_ANDROID], + 'crbug.com/610021') + self.DisableStory('Blogger', [story_module.expectations.ALL_ANDROID], + 'crbug.com/610021') + self.DisableStory('Facebook', [story_module.expectations.ALL_ANDROID], + 'crbug.com/610021') + self.DisableStory('LinkedIn', [story_module.expectations.ALL_ANDROID], + 'crbug.com/610021') + self.DisableStory('Wikipedia (1 tab)', + [story_module.expectations.ALL_ANDROID], + 'crbug.com/610021') + self.DisableStory('Twitter', [story_module.expectations.ALL_ANDROID], + 'crbug.com/610021') + self.DisableStory('ESPN', [story_module.expectations.ALL_ANDROID], + 'crbug.com/610021') + self.DisableStory('http://news.yahoo.com', + [story_module.expectations.ALL_ANDROID], + 'crbug.com/610021') + self.DisableStory('http://www.cnn.com', + [story_module.expectations.ALL_ANDROID], + 'crbug.com/610021') + self.DisableStory('Weather.com', + [story_module.expectations.ALL_ANDROID], + 'crbug.com/610021') + self.DisableStory('http://www.amazon.com', + [story_module.expectations.ALL_ANDROID], + 'crbug.com/610021') + self.DisableStory('http://www.ebay.com', + [story_module.expectations.ALL_ANDROID], + 'crbug.com/610021') + self.DisableStory('http://games.yahoo.com', + [story_module.expectations.ALL_ANDROID], + 'crbug.com/610021') + self.DisableStory('http://booking.com', + [story_module.expectations.ALL_ANDROID], + 'crbug.com/610021') + self.DisableStory('http://sports.yahoo.com/', + [story_module.expectations.ALL_ANDROID], + 'crbug.com/610021') + return StoryExpectations()
diff --git a/tools/perf/contrib/memory_extras/memory_extras.py b/tools/perf/contrib/memory_extras/memory_extras.py index abf810c0..33751abd 100644 --- a/tools/perf/contrib/memory_extras/memory_extras.py +++ b/tools/perf/contrib/memory_extras/memory_extras.py
@@ -18,18 +18,26 @@ on a webview-based browser (a stand in for the Search app), and loading pages on a select browser. """ - page_set = page_sets.DualBrowserStorySet options = {'pageset_repeat': 5} @classmethod def Name(cls): return 'memory.dual_browser_test' + def CreateStorySet(self, options): + del options + return page_sets.DualBrowserStorySet() + @classmethod def ShouldTearDownStateAfterEachStoryRun(cls): return False @classmethod + def ShouldTearDownStateAfterEachStorySetRun(cls): + # Browser will now be closed as instructed by the shared state. + return False + + @classmethod def ValueCanBeAddedPredicate(cls, value, is_first_result): # TODO(crbug.com/610962): Remove this stopgap when the perf dashboard # is able to cope with the data load generated by TBMv2 metrics. @@ -49,13 +57,16 @@ Same as memory.dual_browser_test, but the test is run for 60 iterations and the browser is *not* restarted between page set repeats. """ - page_set = page_sets.DualBrowserStorySet options = {'pageset_repeat': 60} @classmethod def Name(cls): return 'memory.long_running_dual_browser_test' + def CreateStorySet(self, options): + del options + return page_sets.DualBrowserStorySet(long_running=True) + @classmethod def ShouldTearDownStateAfterEachStoryRun(cls): return False
diff --git a/tools/perf/page_sets/data/kraken.json b/tools/perf/page_sets/data/kraken.json index a9b1d44..550d051e 100644 --- a/tools/perf/page_sets/data/kraken.json +++ b/tools/perf/page_sets/data/kraken.json
@@ -1,7 +1,7 @@ { "archives": { "http://krakenbenchmark.mozilla.org/kraken-1.1/driver.html": { - "DEFAULT": "kraken_000.wpr" + "DEFAULT": "kraken_000.wprgo" } }, "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating.",
diff --git a/tools/perf/page_sets/data/kraken_000.wpr.sha1 b/tools/perf/page_sets/data/kraken_000.wpr.sha1 deleted file mode 100644 index 5b47e88..0000000 --- a/tools/perf/page_sets/data/kraken_000.wpr.sha1 +++ /dev/null
@@ -1 +0,0 @@ -c096ee93213072a013e1799e07e1337cc2a2e806 \ No newline at end of file
diff --git a/tools/perf/page_sets/data/kraken_000.wprgo.sha1 b/tools/perf/page_sets/data/kraken_000.wprgo.sha1 new file mode 100644 index 0000000..dc6a6463f --- /dev/null +++ b/tools/perf/page_sets/data/kraken_000.wprgo.sha1
@@ -0,0 +1 @@ +cdf2ba76caaf50bddf279601dbc268c3aee99a3f \ No newline at end of file
diff --git a/tools/perf/page_sets/desktop_memory.py b/tools/perf/page_sets/desktop_memory.py index 59f9005..aef9de34d 100644 --- a/tools/perf/page_sets/desktop_memory.py +++ b/tools/perf/page_sets/desktop_memory.py
@@ -6,17 +6,24 @@ from telemetry.page import page as page_module from telemetry.page import shared_page_state -from telemetry import story +from telemetry import story as story_module _DUMP_WAIT_TIME = 3 _ITERATIONS = 10 + +class DesktopMemorySharedState(shared_page_state.SharedDesktopPageState): + def ShouldStopBrowserAfterStoryRun(self, story): + del story + return False # Keep the same browser instance open across stories. + + class DesktopMemoryPage(page_module.Page): def __init__(self, url, page_set): super(DesktopMemoryPage, self).__init__( url=url, page_set=page_set, - shared_page_state_class=shared_page_state.SharedDesktopPageState, + shared_page_state_class=DesktopMemorySharedState, name=url) def _DumpMemory(self, action_runner, phase): @@ -45,7 +52,7 @@ self._DumpMemory(action_runner, 'post') -class DesktopMemoryPageSet(story.StorySet): +class DesktopMemoryPageSet(story_module.StorySet): """ Desktop sites with interesting memory characteristics """
diff --git a/tools/perf/page_sets/dual_browser_story.py b/tools/perf/page_sets/dual_browser_story.py index e50fbe7..6ba5f2f 100644 --- a/tools/perf/page_sets/dual_browser_story.py +++ b/tools/perf/page_sets/dual_browser_story.py
@@ -179,6 +179,11 @@ self._current_story.Run(self) def DidRunStory(self, _): + if (not self._story_set.long_running and + self._story_set[-1] == self._current_story): + # In long_running mode we never close the browsers; otherwise we close + # them only after the last story in the set runs. + self._CloseAllBrowsers() self._current_story = None def TakeMemoryMeasurement(self): @@ -238,10 +243,11 @@ class DualBrowserStorySet(story_module.StorySet): """A story set that switches back and forth between two browsers.""" - def __init__(self): + def __init__(self, long_running=False): super(DualBrowserStorySet, self).__init__( archive_data_file='data/dual_browser_story.json', cloud_storage_bucket=story_module.PARTNER_BUCKET) + self.long_running = long_running for query, url in zip(SEARCH_QUERIES, URL_LIST): # Stories that run on the android-webview browser.
diff --git a/tools/perf/page_sets/memory_top_10_mobile.py b/tools/perf/page_sets/memory_top_10_mobile.py index 260af35..0a7239d 100644 --- a/tools/perf/page_sets/memory_top_10_mobile.py +++ b/tools/perf/page_sets/memory_top_10_mobile.py
@@ -6,13 +6,25 @@ from telemetry.page import page as page_module from telemetry.page import shared_page_state -from telemetry import story +from telemetry import story as story_module from devil.android.sdk import keyevent # pylint: disable=import-error from page_sets import top_10_mobile +class Top10MobileSharedState(shared_page_state.SharedMobilePageState): + def __init__(self, test, finder_options, story_set): + super(Top10MobileSharedState, self).__init__( + test, finder_options, story_set) + self._story_set = story_set + + def ShouldStopBrowserAfterStoryRun(self, story): + # Close the browser after the last story in the set. + # TODO(crbug.com/750055): Switch to close after each background page. + return self._story_set[-1] == story + + class MemoryMeasurementPage(page_module.Page): """Abstract class for measuring memory on a story unit.""" @@ -21,7 +33,7 @@ def __init__(self, story_set, name, url): super(MemoryMeasurementPage, self).__init__( page_set=story_set, name=name, url=url, - shared_page_state_class=shared_page_state.SharedMobilePageState, + shared_page_state_class=Top10MobileSharedState, grouping_keys={'phase': self._PHASE}) @@ -61,14 +73,14 @@ keyevent.KEYCODE_BACK) -class MemoryTop10Mobile(story.StorySet): +class MemoryTop10Mobile(story_module.StorySet): """User story to measure foreground/background memory in top 10 mobile.""" DETERMINISTIC_MODE = True def __init__(self): super(MemoryTop10Mobile, self).__init__( archive_data_file='data/memory_top_10_mobile.json', - cloud_storage_bucket=story.PARTNER_BUCKET) + cloud_storage_bucket=story_module.PARTNER_BUCKET) for url in top_10_mobile.URL_LIST: # We name pages so their foreground/background counterparts are easy
diff --git a/tools/perf/scripts_smoke_unittest.py b/tools/perf/scripts_smoke_unittest.py index c6d0fa6..da2e82a 100644 --- a/tools/perf/scripts_smoke_unittest.py +++ b/tools/perf/scripts_smoke_unittest.py
@@ -6,9 +6,11 @@ import os import subprocess import sys -from telemetry.testing import options_for_unittests import unittest +from telemetry import decorators +from telemetry.testing import options_for_unittests + class ScriptsSmokeTest(unittest.TestCase): @@ -58,6 +60,7 @@ self.assertEquals(return_code, 0, stdout) self.assertIn('kraken', stdout) + @decorators.Disabled('chromeos') # crbug.com/754913 def testRunTelemetryBenchmarkAsGoogletest(self): options = options_for_unittests.GetCopy() browser_type = options.browser_type
diff --git a/tools/perf/unowned_benchmarks.txt b/tools/perf/unowned_benchmarks.txt index b3d2d7f..2a892f4 100644 --- a/tools/perf/unowned_benchmarks.txt +++ b/tools/perf/unowned_benchmarks.txt
@@ -2,8 +2,6 @@ load_library_perf_tests power.idle_platform power.steady_state -rasterize_and_record_micro.partial_invalidation -rasterize_and_record_micro.top_25 smoothness.tough_image_decode_cases start_with_ext.cold.blank_page start_with_ext.warm.blank_page
diff --git a/ui/accessibility/platform/ax_platform_node_mac.mm b/ui/accessibility/platform/ax_platform_node_mac.mm index 2c2bd33..56dab4a 100644 --- a/ui/accessibility/platform/ax_platform_node_mac.mm +++ b/ui/accessibility/platform/ax_platform_node_mac.mm
@@ -69,7 +69,9 @@ {ui::AX_ROLE_FOOTER, NSAccessibilityGroupRole}, {ui::AX_ROLE_FORM, NSAccessibilityGroupRole}, {ui::AX_ROLE_GENERIC_CONTAINER, NSAccessibilityGroupRole}, - {ui::AX_ROLE_GRID, NSAccessibilityGridRole}, + // Should be NSAccessibilityGridRole but VoiceOver treating it like + // a list as of 10.12.6, so following WebKit and using table role: + {ui::AX_ROLE_GRID, NSAccessibilityTableRole}, // crbug.com/753925 {ui::AX_ROLE_GROUP, NSAccessibilityGroupRole}, {ui::AX_ROLE_HEADING, @"AXHeading"}, {ui::AX_ROLE_IFRAME, NSAccessibilityGroupRole},
diff --git a/ui/app_list/app_list_constants.cc b/ui/app_list/app_list_constants.cc index 1b503f8..2117297 100644 --- a/ui/app_list/app_list_constants.cc +++ b/ui/app_list/app_list_constants.cc
@@ -134,9 +134,24 @@ const int kSearchBoxPadding = 16; const int kSearchBoxTopPadding = 24; +// Bottom padding of search box in peeking state. +const int kSearchBoxPeekingBottomPadding = 12; + +// Bottom padding of search box in fullscreen state. +const int kSearchBoxFullscreenBottomPadding = 24; + // The background border corner radius of the search box in fullscreen mode. const int kSearchBoxBorderCornerRadiusFullscreen = 24; +// Preferred height of search box. +const int kSearchBoxPreferredHeight = 48; + +// The height of the peeking app list from the bottom of the screen. +const int kPeekingAppListHeight = 320; + +// The height/width of the shelf from the bottom/side of the screen. +const int kShelfSize = 48; + // Max items allowed in a folder. size_t kMaxFolderItems = 16;
diff --git a/ui/app_list/app_list_constants.h b/ui/app_list/app_list_constants.h index 01ab81d..8b96d84 100644 --- a/ui/app_list/app_list_constants.h +++ b/ui/app_list/app_list_constants.h
@@ -99,7 +99,13 @@ APP_LIST_EXPORT extern const int kAppsGridLeftRightPaddingFullscreen; APP_LIST_EXPORT extern const int kSearchBoxPadding; APP_LIST_EXPORT extern const int kSearchBoxTopPadding; +APP_LIST_EXPORT extern const int kSearchBoxPeekingBottomPadding; +APP_LIST_EXPORT extern const int kSearchBoxFullscreenBottomPadding; APP_LIST_EXPORT extern const int kSearchBoxBorderCornerRadiusFullscreen; +APP_LIST_EXPORT extern const int kSearchBoxPreferredHeight; + +APP_LIST_EXPORT extern const int kPeekingAppListHeight; +APP_LIST_EXPORT extern const int kShelfSize; APP_LIST_EXPORT extern size_t kMaxFolderItems; APP_LIST_EXPORT extern const size_t kNumFolderTopItems;
diff --git a/ui/app_list/presenter/app_list_presenter_impl.cc b/ui/app_list/presenter/app_list_presenter_impl.cc index 7872f99..c3d1ebb 100644 --- a/ui/app_list/presenter/app_list_presenter_impl.cc +++ b/ui/app_list/presenter/app_list_presenter_impl.cc
@@ -177,7 +177,9 @@ views::Widget* widget = view_->GetWidget(); ui::Layer* layer = GetLayer(widget); layer->GetAnimator()->StopAnimating(); - gfx::Rect target_bounds = widget->GetWindowBoundsInScreen(); + gfx::Rect target_bounds = is_fullscreen_app_list_enabled_ + ? widget->GetNativeView()->bounds() + : widget->GetWindowBoundsInScreen(); ui::ScopedLayerAnimationSettings animation(layer->GetAnimator()); aura::Window* root_window = widget->GetNativeView()->GetRootWindow(); const gfx::Vector2d offset = @@ -200,6 +202,10 @@ animation.AddObserver(this); layer->SetOpacity(is_visible_ ? 1.0 : 0.0); + if (is_fullscreen_app_list_enabled_) { + widget->GetNativeView()->SetBounds(target_bounds); + return; + } widget->SetBounds(target_bounds); }
diff --git a/ui/app_list/search/mixer.cc b/ui/app_list/search/mixer.cc index c7328e60..0e49894 100644 --- a/ui/app_list/search/mixer.cc +++ b/ui/app_list/search/mixer.cc
@@ -12,6 +12,7 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" +#include "ui/app_list/app_list_features.h" #include "ui/app_list/search_provider.h" #include "ui/app_list/search_result.h" @@ -47,8 +48,12 @@ // Used to group relevant providers together for mixing their results. class Mixer::Group { public: - Group(size_t max_results, double multiplier) - : max_results_(max_results), multiplier_(multiplier) {} + Group(size_t max_results, double multiplier, double boost) + : max_results_(max_results), + multiplier_(multiplier), + boost_(boost), + is_fullscreen_app_list_enabled_( + features::IsFullscreenAppListEnabled()) {} ~Group() {} void AddProvider(SearchProvider* provider) { @@ -63,43 +68,44 @@ DCHECK(!result->id().empty()); // We cannot rely on providers to give relevance scores in the range - // [0.0, 1.0] (e.g., PeopleProvider directly gives values from the - // Google+ API). Clamp to that range. + // [0.0, 1.0]. Clamp to that range. const double relevance = std::min(std::max(result->relevance(), 0.0), 1.0); - double boost = 0.0; + double boost = boost_; - // Recommendations should not be affected by query-to-launch correlation - // from KnownResults as it causes recommendations to become dominated by - // previously clicked results. This happens because the recommendation - // query is the empty string and the clicked results get forever - // boosted. - if (result->display_type() != SearchResult::DISPLAY_RECOMMENDATION) { - KnownResults::const_iterator known_it = - known_results.find(result->id()); - if (known_it != known_results.end()) { - switch (known_it->second) { - case PERFECT_PRIMARY: - boost = 4.0; - break; - case PREFIX_PRIMARY: - boost = 3.75; - break; - case PERFECT_SECONDARY: - boost = 3.25; - break; - case PREFIX_SECONDARY: - boost = 3.0; - break; - case UNKNOWN_RESULT: - NOTREACHED() << "Unknown result in KnownResults?"; - break; + if (!is_fullscreen_app_list_enabled_) { + // Recommendations should not be affected by query-to-launch + // correlation from KnownResults as it causes recommendations to + // become dominated by previously clicked results. This happens + // because the recommendation query is the empty string and the + // clicked results get forever boosted. + if (result->display_type() != SearchResult::DISPLAY_RECOMMENDATION) { + KnownResults::const_iterator known_it = + known_results.find(result->id()); + if (known_it != known_results.end()) { + switch (known_it->second) { + case PERFECT_PRIMARY: + boost = 4.0; + break; + case PREFIX_PRIMARY: + boost = 3.75; + break; + case PERFECT_SECONDARY: + boost = 3.25; + break; + case PREFIX_SECONDARY: + boost = 3.0; + break; + case UNKNOWN_RESULT: + NOTREACHED() << "Unknown result in KnownResults?"; + break; + } } - } - // If this is a voice query, voice results receive a massive boost. - if (is_voice_query && result->voice_result()) - boost += 4.0; + // If this is a voice query, voice results receive a massive boost. + if (is_voice_query && result->voice_result()) + boost += 4.0; + } } results_.emplace_back(result.get(), relevance * multiplier_ + boost); @@ -117,6 +123,9 @@ typedef std::vector<SearchProvider*> Providers; const size_t max_results_; const double multiplier_; + const double boost_; + + const bool is_fullscreen_app_list_enabled_; Providers providers_; // Not owned. SortedResults results_; @@ -130,8 +139,8 @@ Mixer::~Mixer() { } -size_t Mixer::AddGroup(size_t max_results, double multiplier) { - groups_.push_back(base::MakeUnique<Group>(max_results, multiplier)); +size_t Mixer::AddGroup(size_t max_results, double multiplier, double boost) { + groups_.push_back(base::MakeUnique<Group>(max_results, multiplier, boost)); return groups_.size() - 1; }
diff --git a/ui/app_list/search/mixer.h b/ui/app_list/search/mixer.h index 253de6fd3..41818396 100644 --- a/ui/app_list/search/mixer.h +++ b/ui/app_list/search/mixer.h
@@ -38,8 +38,9 @@ // chosen from this group (if 0, will allow unlimited results from this // group). If there aren't enough results from all groups, more than // |max_results| may be chosen from this group. Each result in the group will - // have its score multiplied by |multiplier|. Returns the group's group_id. - size_t AddGroup(size_t max_results, double multiplier); + // have its score multiplied by |multiplier| and added by |boost|. Returns the + // group's group_id. + size_t AddGroup(size_t max_results, double multiplier, double boost); // Associates a provider with a mixer group. void AddProviderToGroup(size_t group_id, SearchProvider* provider);
diff --git a/ui/app_list/search/mixer_unittest.cc b/ui/app_list/search/mixer_unittest.cc index fb4f91d..66546b3 100644 --- a/ui/app_list/search/mixer_unittest.cc +++ b/ui/app_list/search/mixer_unittest.cc
@@ -131,9 +131,12 @@ mixer_.reset(new Mixer(results_.get())); - size_t apps_group_id = mixer_->AddGroup(kMaxAppsGroupResults, 1.0); - size_t omnibox_group_id = mixer_->AddGroup(kMaxOmniboxResults, 1.0); - size_t webstore_group_id = mixer_->AddGroup(kMaxWebstoreResults, 0.5); + // TODO(warx): when fullscreen app list is default enabled, modify this test + // to (1) test answer card/apps group having relevance boost, (2) remove + // known results boost tests. + size_t apps_group_id = mixer_->AddGroup(kMaxAppsGroupResults, 1.0, 0.0); + size_t omnibox_group_id = mixer_->AddGroup(kMaxOmniboxResults, 1.0, 0.0); + size_t webstore_group_id = mixer_->AddGroup(kMaxWebstoreResults, 0.5, 0.0); mixer_->AddProviderToGroup(apps_group_id, providers_[0].get()); mixer_->AddProviderToGroup(omnibox_group_id, providers_[1].get());
diff --git a/ui/app_list/search_controller.cc b/ui/app_list/search_controller.cc index cae0583..b2628f2 100644 --- a/ui/app_list/search_controller.cc +++ b/ui/app_list/search_controller.cc
@@ -103,8 +103,10 @@ result->InvokeAction(action_index, event_flags); } -size_t SearchController::AddGroup(size_t max_results, double multiplier) { - return mixer_->AddGroup(max_results, multiplier); +size_t SearchController::AddGroup(size_t max_results, + double multiplier, + double boost) { + return mixer_->AddGroup(max_results, multiplier, boost); } void SearchController::AddProvider(size_t group_id,
diff --git a/ui/app_list/search_controller.h b/ui/app_list/search_controller.h index ea57747a..4c6c939 100644 --- a/ui/app_list/search_controller.h +++ b/ui/app_list/search_controller.h
@@ -42,7 +42,7 @@ int event_flags); // Adds a new mixer group. See Mixer::AddGroup. - size_t AddGroup(size_t max_results, double multiplier); + size_t AddGroup(size_t max_results, double multiplier, double boost); // Takes ownership of |provider| and associates it with given mixer group. void AddProvider(size_t group_id, std::unique_ptr<SearchProvider> provider);
diff --git a/ui/app_list/views/app_list_page.cc b/ui/app_list/views/app_list_page.cc index 9799f94..0953b75 100644 --- a/ui/app_list/views/app_list_page.cc +++ b/ui/app_list/views/app_list_page.cc
@@ -30,6 +30,11 @@ AppListModel::State from_state, AppListModel::State to_state) {} +gfx::Rect AppListPage::GetPageBoundsDuringDragging( + AppListModel::State state) const { + return GetPageBoundsForState(state); +} + gfx::Rect AppListPage::GetSearchBoxBounds() const { DCHECK(contents_view_); return contents_view_->GetDefaultSearchBoxBounds();
diff --git a/ui/app_list/views/app_list_page.h b/ui/app_list/views/app_list_page.h index f3c452b..0b07e42 100644 --- a/ui/app_list/views/app_list_page.h +++ b/ui/app_list/views/app_list_page.h
@@ -36,6 +36,10 @@ // Returns where this page should move to when the given state is active. virtual gfx::Rect GetPageBoundsForState(AppListModel::State state) const = 0; + // Returns the bounds of the page during dragging. + virtual gfx::Rect GetPageBoundsDuringDragging( + AppListModel::State state) const; + // Returns where the search box should be when this page is shown. Is at the // top of the app list by default, in the contents view's coordinate space. virtual gfx::Rect GetSearchBoxBounds() const;
diff --git a/ui/app_list/views/app_list_view.cc b/ui/app_list/views/app_list_view.cc index 7dd66588..6efa0e8 100644 --- a/ui/app_list/views/app_list_view.cc +++ b/ui/app_list/views/app_list_view.cc
@@ -58,9 +58,6 @@ // The margin from the edge to the speech UI. constexpr int kSpeechUIMargin = 12; -// The height of the peeking app list from the bottom of the screen. -constexpr int kPeekingAppListHeight = 320; - // The height of the half app list from the bottom of the screen. constexpr int kHalfAppListHeight = 561; @@ -178,16 +175,8 @@ AppListView::AppListView(AppListViewDelegate* delegate) : delegate_(delegate), - app_list_main_view_(nullptr), - speech_view_(nullptr), - search_box_focus_host_(nullptr), - search_box_widget_(nullptr), - search_box_view_(nullptr), is_fullscreen_app_list_enabled_(features::IsFullscreenAppListEnabled()), - processing_scroll_event_series_(false), - app_list_state_(PEEKING), display_observer_(this), - overlay_view_(nullptr), animation_observer_(new HideViewAnimationObserver()) { CHECK(delegate); delegate_->GetSpeechUI()->AddObserver(this); @@ -432,22 +421,17 @@ int initial_apps_page) { const display::Display display_nearest_view = GetDisplayNearestView(); const gfx::Rect display_work_area_bounds = display_nearest_view.work_area(); - const int bottom_of_screen = display_nearest_view.size().height(); // Set the widget height to the shelf height to replace the shelf background // on show animation with no flicker. In shelf mode we set the bounds to the // top of the screen because the widget does not animate. - const int overlay_view_bounds_y = - is_side_shelf_ ? 0 : (bottom_of_screen - kShelfSize); - const int overlay_view_bounds_x = - is_side_shelf_ ? 0 : display_work_area_bounds.x(); - const int overlay_view_bounds_width = - display_work_area_bounds.width() + (is_side_shelf_ ? kShelfSize : 0); - const int overlay_view_bounds_height = - display_work_area_bounds.height() + (is_side_shelf_ ? 0 : kShelfSize); + const int overlay_view_bounds_y = is_side_shelf_ + ? display_work_area_bounds.y() + : display_work_area_bounds.bottom(); gfx::Rect app_list_overlay_view_bounds( - overlay_view_bounds_x, overlay_view_bounds_y, overlay_view_bounds_width, - overlay_view_bounds_height); + display_nearest_view.bounds().x(), overlay_view_bounds_y, + display_nearest_view.bounds().width(), + display_nearest_view.bounds().height()); fullscreen_widget_ = new views::Widget; views::Widget::InitParams app_list_overlay_view_params( @@ -458,11 +442,18 @@ app_list_overlay_view_params.delegate = this; app_list_overlay_view_params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; - app_list_overlay_view_params.bounds = app_list_overlay_view_bounds; app_list_overlay_view_params.layer_type = ui::LAYER_SOLID_COLOR; fullscreen_widget_->Init(app_list_overlay_view_params); + // Set bounds directly in screen coordinates to avoid screen position + // controller setting bounds in the display where the widget has the largest + // intersection. + fullscreen_widget_->GetNativeView()->SetBoundsInScreen( + app_list_overlay_view_bounds, GetDisplayNearestView()); + overlay_view_ = new AppListOverlayView(0 /* no corners */); + + work_area_bottom_ = fullscreen_widget_->GetWorkAreaBoundsInScreen().bottom(); } void AppListView::InitializeBubble(gfx::NativeView parent, @@ -484,10 +475,17 @@ overlay_view_->SetBoundsRect(GetContentsBounds()); } -void AppListView::HandleClickOrTap() { +void AppListView::HandleClickOrTap(ui::LocatedEvent* event) { if (!is_fullscreen_app_list_enabled_) return; + // No-op if app list is on fullscreen all apps state and the event location is + // within apps grid view's bounds. + if (app_list_state_ == FULLSCREEN_ALL_APPS && + GetAppsGridView()->GetBoundsInScreen().Contains(event->location())) { + return; + } + if (!search_box_view_->is_search_box_active()) { SetState(CLOSED); return; @@ -498,17 +496,19 @@ } void AppListView::StartDrag(const gfx::Point& location) { + // Convert drag point from widget coordinates to screen coordinates because + // the widget bounds changes during the dragging. initial_drag_point_ = location; + ConvertPointToScreen(this, &initial_drag_point_); + initial_window_bounds_ = fullscreen_widget_->GetWindowBoundsInScreen(); } void AppListView::UpdateDrag(const gfx::Point& location) { - // Update the bounds of the widget while maintaining the - // relative position of the top of the widget and the mouse/gesture. - // Block drags north of 0 and recalculate the initial_drag_point_. - int new_y_position = location.y() - initial_drag_point_.y() + - fullscreen_widget_->GetWindowBoundsInScreen().y(); - if (new_y_position < 0) - initial_drag_point_ = location; + // Update the widget bounds based on the initial widget bounds and drag delta. + gfx::Point location_in_screen_coordinates = location; + ConvertPointToScreen(this, &location_in_screen_coordinates); + int new_y_position = location_in_screen_coordinates.y() - + initial_drag_point_.y() + initial_window_bounds_.y(); UpdateYPositionAndOpacity(new_y_position, GetAppListBackgroundOpacityDuringDragging(), @@ -520,8 +520,7 @@ if (app_list_state_ == CLOSED) return; - // Restores opacity of all the items in app list if dragging ends. - UpdateOpacity(kAppListOpacity, true /* is_end_gesture */); + DraggingLayout(); // Change the app list state based on where the drag ended. If fling velocity // was over the threshold, snap to the next state in the direction of the // fling. @@ -585,13 +584,15 @@ break; } - gfx::Point location_in_screen_coordinates = location; - ConvertPointToScreen(this, &location_in_screen_coordinates); - const int new_y_position = - location_in_screen_coordinates.y() - initial_drag_point_.y(); const int app_list_threshold = app_list_height / kAppListThresholdDenominator; - const int drag_delta = app_list_y_for_state - new_y_position; + gfx::Point location_in_screen_coordinates = location; + ConvertPointToScreen(this, &location_in_screen_coordinates); + const int drag_delta = + initial_drag_point_.y() - location_in_screen_coordinates.y(); + const int location_y_in_current_display = + location_in_screen_coordinates.y() - + GetDisplayNearestView().bounds().y(); switch (app_list_state_) { case FULLSCREEN_ALL_APPS: if (std::abs(drag_delta) > app_list_threshold) @@ -608,7 +609,7 @@ case HALF: if (std::abs(drag_delta) > app_list_threshold) { SetState(drag_delta > 0 ? FULLSCREEN_SEARCH : CLOSED); - } else if (location_in_screen_coordinates.y() >= + } else if (location_y_in_current_display >= display_height - kAppListBezelMargin) { // If the user drags to the bezel, close the app list. SetState(CLOSED); @@ -619,7 +620,7 @@ case PEEKING: if (std::abs(drag_delta) > app_list_threshold) { SetState(drag_delta > 0 ? FULLSCREEN_ALL_APPS : CLOSED); - } else if (location_in_screen_coordinates.y() >= + } else if (location_y_in_current_display >= display_height - kAppListBezelMargin) { // If the user drags to the bezel, close the app list. SetState(CLOSED); @@ -638,6 +639,12 @@ return display::Screen::GetScreen()->GetDisplayNearestView(parent_window()); } +AppsGridView* AppListView::GetAppsGridView() const { + return app_list_main_view_->contents_view() + ->apps_container_view() + ->apps_grid_view(); +} + void AppListView::OnBeforeBubbleWidgetInit(views::Widget::InitParams* params, views::Widget* widget) const { if (!params->native_widget) { @@ -692,7 +699,7 @@ switch (event->type()) { case ui::ET_MOUSE_PRESSED: event->SetHandled(); - HandleClickOrTap(); + HandleClickOrTap(event); break; case ui::ET_MOUSEWHEEL: if (HandleScroll(event)) @@ -709,32 +716,37 @@ switch (event->type()) { case ui::ET_GESTURE_TAP: - processing_scroll_event_series_ = false; + is_in_drag_ = false; event->SetHandled(); - HandleClickOrTap(); + HandleClickOrTap(event); break; case ui::ET_SCROLL_FLING_START: case ui::ET_GESTURE_SCROLL_BEGIN: if (is_side_shelf_) return; - processing_scroll_event_series_ = true; - StartDrag(event->location()); + // There may be multiple scroll begin events in one drag because the + // relative location of the finger and widget is almost unchanged and + // scroll begin event occurs when the relative location changes beyond a + // threshold. So avoid resetting the initial drag point in drag. + if (!is_in_drag_) + StartDrag(event->location()); + is_in_drag_ = true; event->SetHandled(); break; case ui::ET_GESTURE_SCROLL_UPDATE: if (is_side_shelf_) return; - processing_scroll_event_series_ = true; + is_in_drag_ = true; last_fling_velocity_ = event->details().scroll_y(); UpdateDrag(event->location()); event->SetHandled(); break; case ui::ET_GESTURE_END: - if (!processing_scroll_event_series_) + if (!is_in_drag_) break; if (is_side_shelf_) return; - processing_scroll_event_series_ = false; + is_in_drag_ = false; EndDrag(event->location()); event->SetHandled(); break; @@ -944,7 +956,7 @@ break; } - gfx::Rect target_bounds = fullscreen_widget_->GetWindowBoundsInScreen(); + gfx::Rect target_bounds = fullscreen_widget_->GetNativeView()->bounds(); target_bounds.set_y(target_state_y); std::unique_ptr<ui::LayerAnimationElement> bounds_animation_element = @@ -992,22 +1004,24 @@ void AppListView::UpdateYPositionAndOpacity(int y_position_in_screen, float background_opacity, bool is_end_gesture) { + is_in_drag_ = !is_end_gesture; + background_opacity_ = background_opacity; if (is_end_gesture) { SetState(FULLSCREEN_ALL_APPS); } else { gfx::Rect new_widget_bounds = fullscreen_widget_->GetWindowBoundsInScreen(); - new_widget_bounds.set_y(std::max(y_position_in_screen, 0)); - fullscreen_widget_->SetBounds(new_widget_bounds); + app_list_y_position_in_screen_ = + std::max(y_position_in_screen, GetDisplayNearestView().bounds().y()); + new_widget_bounds.set_y(app_list_y_position_in_screen_); + fullscreen_widget_->GetNativeView()->SetBoundsInScreen( + new_widget_bounds, GetDisplayNearestView()); } - UpdateOpacity(background_opacity, is_end_gesture); + DraggingLayout(); } -PaginationModel* AppListView::GetAppsPaginationModel() { - return app_list_main_view_->contents_view() - ->apps_container_view() - ->apps_grid_view() - ->pagination_model(); +PaginationModel* AppListView::GetAppsPaginationModel() const { + return GetAppsGridView()->pagination_model(); } void AppListView::OnSpeechRecognitionStateChanged( @@ -1085,8 +1099,7 @@ return; // Set the |fullscreen_widget_| size to fit the new display metrics. - gfx::Size size = GetDisplayNearestView().work_area().size(); - size.Enlarge(0, kShelfSize); + gfx::Size size = GetDisplayNearestView().size(); fullscreen_widget_->SetSize(size); // Update the |fullscreen_widget_| bounds to accomodate the new work @@ -1094,28 +1107,25 @@ SetState(app_list_state_); } -void AppListView::UpdateOpacity(float background_opacity, bool is_end_gesture) { +void AppListView::DraggingLayout() { app_list_background_shield_->layer()->SetOpacity( - is_end_gesture ? kAppListOpacity : background_opacity); - gfx::Rect work_area_bounds = fullscreen_widget_->GetWorkAreaBoundsInScreen(); - search_box_view_->UpdateOpacity(work_area_bounds.bottom(), is_end_gesture); - app_list_main_view_->contents_view() - ->apps_container_view() - ->apps_grid_view() - ->UpdateOpacity(work_area_bounds.bottom(), is_end_gesture); + is_in_drag_ ? background_opacity_ : kAppListOpacity); + + // Updates the opacity of the items in the app list. + search_box_view_->UpdateOpacity(app_list_y_position_in_screen_); + GetAppsGridView()->UpdateOpacity(app_list_y_position_in_screen_); + + app_list_main_view_->contents_view()->Layout(); if (app_list_state_ == PEEKING) { app_list_main_view_->contents_view()->start_page_view()->UpdateOpacity( - work_area_bounds.bottom(), is_end_gesture); + work_area_bottom_, !is_in_drag_); } } float AppListView::GetAppListBackgroundOpacityDuringDragging() { float top_of_applist = fullscreen_widget_->GetWindowBoundsInScreen().y(); - float work_area_bottom = - fullscreen_widget_->GetWorkAreaBoundsInScreen().bottom(); - - float dragging_height = std::max((work_area_bottom - top_of_applist), 0.f); + float dragging_height = std::max((work_area_bottom_ - top_of_applist), 0.f); float coefficient = std::min(dragging_height / (kNumOfShelfSize * kShelfSize), 1.0f); return coefficient * kAppListOpacity;
diff --git a/ui/app_list/views/app_list_view.h b/ui/app_list/views/app_list_view.h index b052b49..4119f77 100644 --- a/ui/app_list/views/app_list_view.h +++ b/ui/app_list/views/app_list_view.h
@@ -27,6 +27,7 @@ class AppListMainView; class AppListModel; class AppListViewDelegate; +class AppsGridView; class HideViewAnimationObserver; class PaginationModel; class SearchBoxView; @@ -43,9 +44,6 @@ public display::DisplayObserver, public AppListViewDelegateObserver { public: - // The height/width of the shelf from the bottom/side of the screen. - static constexpr int kShelfSize = 48; - // Number of the size of shelf. Used to determine the opacity of items in the // app list during dragging. static constexpr float kNumOfShelfSize = 2.0; @@ -128,6 +126,11 @@ void Layout() override; void SchedulePaintInRect(const gfx::Rect& rect) override; + // Overridden from ui::EventHandler: + void OnScrollEvent(ui::ScrollEvent* event) override; + void OnMouseEvent(ui::MouseEvent* event) override; + void OnGestureEvent(ui::GestureEvent* event) override; + // Called when tablet mode starts and ends. void OnTabletModeChanged(bool started); @@ -153,7 +156,7 @@ bool is_end_gesture); // Gets the PaginationModel owned by this view's apps grid. - PaginationModel* GetAppsPaginationModel(); + PaginationModel* GetAppsPaginationModel() const; views::Widget* get_fullscreen_widget_for_test() const { return fullscreen_widget_; @@ -163,9 +166,9 @@ views::Widget* search_box_widget() const { return search_box_widget_; } - SearchBoxView* search_box_view() { return search_box_view_; } + SearchBoxView* search_box_view() const { return search_box_view_; } - AppListMainView* app_list_main_view() { return app_list_main_view_; } + AppListMainView* app_list_main_view() const { return app_list_main_view_; } bool is_fullscreen() const { return app_list_state_ == FULLSCREEN_ALL_APPS || @@ -174,6 +177,14 @@ bool is_tablet_mode() const { return is_tablet_mode_; } + bool is_in_drag() const { return is_in_drag_; } + + int app_list_y_position_in_screen() const { + return app_list_y_position_in_screen_; + } + + int work_area_bottom() const { return work_area_bottom_; } + private: friend class test::AppListViewTestApi; @@ -189,7 +200,7 @@ // Closes the AppListView when a click or tap event propogates to the // AppListView. - void HandleClickOrTap(); + void HandleClickOrTap(ui::LocatedEvent* event); // Initializes |initial_drag_point_|. void StartDrag(const gfx::Point& location); @@ -205,6 +216,9 @@ // Gets the display nearest to the parent window. display::Display GetDisplayNearestView() const; + // Gets the apps grid view owned by this view. + AppsGridView* GetAppsGridView() const; + // Overridden from views::BubbleDialogDelegateView: void OnBeforeBubbleWidgetInit(views::Widget::InitParams* params, views::Widget* widget) const override; @@ -215,11 +229,6 @@ bool WidgetHasHitTestMask() const override; void GetWidgetHitTestMask(gfx::Path* mask) const override; - // Overridden from ui::EventHandler: - void OnScrollEvent(ui::ScrollEvent* event) override; - void OnMouseEvent(ui::MouseEvent* event) override; - void OnGestureEvent(ui::GestureEvent* event) override; - // Overridden from views::WidgetObserver: void OnWidgetDestroying(views::Widget* widget) override; void OnWidgetVisibilityChanged(views::Widget* widget, bool visible) override; @@ -232,8 +241,8 @@ void OnDisplayMetricsChanged(const display::Display& display, uint32_t changed_metrics) override; - // Updates opacity of both background and items in the app list. - void UpdateOpacity(float background_opacity, bool is_end_gesture); + // Layouts the app list during dragging. + void DraggingLayout(); // Gets app list background opacity during dragging. float GetAppListBackgroundOpacityDuringDragging(); @@ -246,13 +255,15 @@ AppListViewDelegate* delegate_; // Weak. Owned by AppListService. - AppListMainView* app_list_main_view_; - SpeechView* speech_view_; + AppListMainView* app_list_main_view_ = nullptr; + SpeechView* speech_view_ = nullptr; views::Widget* fullscreen_widget_ = nullptr; // Owned by AppListView. - views::View* search_box_focus_host_; // Owned by the views hierarchy. - views::Widget* search_box_widget_; // Owned by the app list's widget. - SearchBoxView* search_box_view_; // Owned by |search_box_widget_|. + views::View* search_box_focus_host_ = + nullptr; // Owned by the views hierarchy. + views::Widget* search_box_widget_ = + nullptr; // Owned by the app list's widget. + SearchBoxView* search_box_view_ = nullptr; // Owned by |search_box_widget_|. // Owned by the app list's widget. Null if the fullscreen app list is not // enabled. views::View* app_list_background_shield_ = nullptr; @@ -261,22 +272,37 @@ // Whether the shelf is oriented on the side. bool is_side_shelf_ = false; - // The gap between the initial gesture event and the top of the window. + // True if the user is in the process of gesture-dragging on opened app list, + // or dragging the app list from shelf. + bool is_in_drag_ = false; + + // Y position of the app list in screen space coordinate during dragging. + int app_list_y_position_in_screen_ = 0; + + // Bottom of work area. + int work_area_bottom_ = 0; + + // The opacity of app list background during dragging. + float background_opacity_ = 0.f; + + // The location of initial gesture event in screen coordinates. gfx::Point initial_drag_point_; + + // The rectangle of initial widget's window in screen coordinates. + gfx::Rect initial_window_bounds_; + // The velocity of the gesture event. float last_fling_velocity_ = 0; // Whether the fullscreen app list feature is enabled. const bool is_fullscreen_app_list_enabled_; - // Whether a series of scroll events are being processed. - bool processing_scroll_event_series_; // The state of the app list, controlled via SetState(). - AppListState app_list_state_; + AppListState app_list_state_ = PEEKING; // An observer that notifies AppListView when the display has changed. ScopedObserver<display::Screen, display::DisplayObserver> display_observer_; // A semi-transparent white overlay that covers the app list while dialogs // are open. - views::View* overlay_view_; + views::View* overlay_view_ = nullptr; std::unique_ptr<HideViewAnimationObserver> animation_observer_;
diff --git a/ui/app_list/views/app_list_view_unittest.cc b/ui/app_list/views/app_list_view_unittest.cc index e4e02a4..fb42ae7 100644 --- a/ui/app_list/views/app_list_view_unittest.cc +++ b/ui/app_list/views/app_list_view_unittest.cc
@@ -584,6 +584,36 @@ start_page_view()->GetSelectedIndexForTest()); } +// Tests that when a click or tap event propagates to the AppListView, if the +// event location is within the bounds of AppsGridView, do not close the +// AppListView. +TEST_F(AppListViewFullscreenTest, TapAndClickWithinAppsGridView) { + Initialize(0, false, false); + delegate_->GetTestModel()->PopulateApps(kInitialItems); + Show(); + view_->SetState(AppListView::FULLSCREEN_ALL_APPS); + EXPECT_EQ(AppListView::FULLSCREEN_ALL_APPS, view_->app_list_state()); + ContentsView* contents_view = view_->app_list_main_view()->contents_view(); + AppsContainerView* container_view = contents_view->apps_container_view(); + const gfx::Rect grid_view_bounds = + container_view->apps_grid_view()->GetBoundsInScreen(); + gfx::Point target_point = grid_view_bounds.origin(); + target_point.Offset(100, 100); + ASSERT_TRUE(grid_view_bounds.Contains(target_point)); + + // Tests gesture tap within apps grid view doesn't close app list view. + ui::GestureEvent tap(target_point.x(), target_point.y(), 0, base::TimeTicks(), + ui::GestureEventDetails(ui::ET_GESTURE_TAP)); + view_->OnGestureEvent(&tap); + EXPECT_EQ(AppListView::FULLSCREEN_ALL_APPS, view_->app_list_state()); + + // Tests mouse click within apps grid view doesn't close app list view. + ui::MouseEvent mouse_click(ui::ET_MOUSE_PRESSED, target_point, target_point, + base::TimeTicks(), 0, 0); + view_->OnMouseEvent(&mouse_click); + EXPECT_EQ(AppListView::FULLSCREEN_ALL_APPS, view_->app_list_state()); +} + // Tests displaying the app list and performs a standard set of checks on its // top level views. Then closes the window. TEST_F(AppListViewTest, DisplayTest) {
diff --git a/ui/app_list/views/apps_container_view.cc b/ui/app_list/views/apps_container_view.cc index ab652ab5..10ce60e 100644 --- a/ui/app_list/views/apps_container_view.cc +++ b/ui/app_list/views/apps_container_view.cc
@@ -15,9 +15,11 @@ #include "ui/app_list/views/app_list_folder_view.h" #include "ui/app_list/views/app_list_item_view.h" #include "ui/app_list/views/app_list_main_view.h" +#include "ui/app_list/views/app_list_view.h" #include "ui/app_list/views/apps_grid_view.h" #include "ui/app_list/views/contents_view.h" #include "ui/app_list/views/folder_background_view.h" +#include "ui/app_list/views/search_box_view.h" #include "ui/app_list/views/suggestions_container_view.h" #include "ui/base/l10n/l10n_util.h" #include "ui/events/event.h" @@ -25,6 +27,15 @@ namespace app_list { +// Initial search box top padding in shelf mode. +constexpr int kSearchBoxInitalTopPadding = 12; + +// Top padding of search box in peeking state. +constexpr int kSearchBoxPeekingTopPadding = 24; + +// Minimum top padding of search box in fullscreen state. +constexpr int kSearchBoxMinimumTopPadding = 24; + AppsContainerView::AppsContainerView(AppListMainView* app_list_main_view, AppListModel* model) : is_fullscreen_app_list_enabled_(features::IsFullscreenAppListEnabled()) { @@ -163,16 +174,58 @@ if (!is_fullscreen_app_list_enabled_) return AppListPage::GetSearchBoxBounds(); - // Makes search box and content vertically centered in screen. gfx::Rect search_box_bounds(contents_view()->GetDefaultSearchBoxBounds()); - const int total_height = - GetDefaultContentsBounds().bottom() - search_box_bounds.y(); - search_box_bounds.set_y( - std::max(search_box_bounds.y(), - (contents_view()->GetDisplayHeight() - total_height) / 2)); + if (contents_view()->app_list_view()->is_in_drag()) + search_box_bounds.set_y(GetSearchBoxTopPaddingDuringDragging()); + else + search_box_bounds.set_y(GetSearchBoxFinalTopPadding()); + return search_box_bounds; } +gfx::Rect AppsContainerView::GetPageBoundsDuringDragging( + AppListModel::State state) const { + float app_list_y_position_in_screen = + contents_view()->app_list_view()->app_list_y_position_in_screen(); + float work_area_bottom = contents_view()->app_list_view()->work_area_bottom(); + float drag_amount = + std::max(0.f, work_area_bottom - app_list_y_position_in_screen); + + float y = 0; + float peeking_final_y = + kSearchBoxPeekingTopPadding + kSearchBoxPreferredHeight + + kSearchBoxPeekingBottomPadding - kSearchBoxFullscreenBottomPadding; + if (drag_amount <= (kPeekingAppListHeight - kShelfSize)) { + // App list is dragged from collapsed to peeking, which moved up at most + // |kPeekingAppListHeight - kShelfSize| (272px). The top padding of apps + // container view changes from |-kSearchBoxFullscreenBottomPadding| to + // |kSearchBoxPeekingTopPadding + kSearchBoxPreferredHeight + + // kSearchBoxPeekingBottomPadding - kSearchBoxFullscreenBottomPadding|. + y = std::ceil( + ((peeking_final_y + kSearchBoxFullscreenBottomPadding) * drag_amount) / + (kPeekingAppListHeight - kShelfSize) - + kSearchBoxFullscreenBottomPadding); + } else { + // App list is dragged from peeking to fullscreen, which moved up at most + // |peeking_to_fullscreen_height|. The top padding of apps container view + // changes from |peeking_final_y| to |final_y|. + float final_y = GetSearchBoxFinalTopPadding() + kSearchBoxPreferredHeight; + float peeking_to_fullscreen_height = + contents_view()->GetDisplayHeight() - kPeekingAppListHeight; + y = std::ceil((final_y - peeking_final_y) * + (drag_amount - (kPeekingAppListHeight - kShelfSize)) / + peeking_to_fullscreen_height + + peeking_final_y); + y = std::max(std::min(final_y, y), peeking_final_y); + } + + gfx::Rect onscreen_bounds = GetPageBoundsForState(state); + if (state == AppListModel::STATE_APPS) + onscreen_bounds.set_y(y); + + return onscreen_bounds; +} + void AppsContainerView::OnTopIconAnimationsComplete() { --top_icon_animation_pending_count_; @@ -273,4 +326,49 @@ apps_grid_view_->activated_folder_item_view()->SetVisible(false); } +int AppsContainerView::GetSearchBoxFinalTopPadding() const { + gfx::Rect search_box_bounds(contents_view()->GetDefaultSearchBoxBounds()); + const int total_height = + GetDefaultContentsBounds().bottom() - search_box_bounds.y(); + + // Makes search box and content vertically centered in contents_view. + int y = std::max(search_box_bounds.y(), + (contents_view()->GetDisplayHeight() - total_height) / 2); + + // Top padding of the searchbox should not be smaller than + // |kSearchBoxMinimumTopPadding| + return std::max(y, kSearchBoxMinimumTopPadding); +} + +int AppsContainerView::GetSearchBoxTopPaddingDuringDragging() const { + float searchbox_final_y = GetSearchBoxFinalTopPadding(); + float peeking_to_fullscreen_height = + contents_view()->GetDisplayHeight() - kPeekingAppListHeight; + float drag_amount = std::max( + 0, contents_view()->app_list_view()->work_area_bottom() - + contents_view()->app_list_view()->app_list_y_position_in_screen()); + + if (drag_amount <= (kPeekingAppListHeight - kShelfSize)) { + // App list is dragged from collapsed to peeking, which moved up at most + // |kPeekingAppListHeight - kShelfSize| (272px). The top padding of search + // box changes from |kSearchBoxInitalTopPadding| to + // |kSearchBoxPeekingTopPadding|, + return std::ceil( + (kSearchBoxPeekingTopPadding - kSearchBoxInitalTopPadding) + + ((kSearchBoxPeekingTopPadding - kSearchBoxInitalTopPadding) * + drag_amount) / + (kPeekingAppListHeight - kShelfSize)); + } else { + // App list is dragged from peeking to fullscreen, which moved up at most + // |peeking_to_fullscreen_height|. The top padding of search box changes + // from |kSearchBoxPeekingTopPadding| to |searchbox_final_y|. + int y = (kSearchBoxPeekingTopPadding + + std::ceil((searchbox_final_y - kSearchBoxPeekingTopPadding) * + (drag_amount - (kPeekingAppListHeight - kShelfSize)) / + peeking_to_fullscreen_height)); + y = std::max(kSearchBoxPeekingTopPadding, y); + return y; + } +} + } // namespace app_list
diff --git a/ui/app_list/views/apps_container_view.h b/ui/app_list/views/apps_container_view.h index c55654d..934c9529 100644 --- a/ui/app_list/views/apps_container_view.h +++ b/ui/app_list/views/apps_container_view.h
@@ -73,6 +73,8 @@ void OnWillBeShown() override; gfx::Rect GetPageBoundsForState(AppListModel::State state) const override; gfx::Rect GetSearchBoxBounds() const override; + gfx::Rect GetPageBoundsDuringDragging( + AppListModel::State state) const override; // TopIconAnimationObserver overrides: void OnTopIconAnimationsComplete() override; @@ -106,6 +108,12 @@ void PrepareToShowApps(AppListFolderItem* folder_item); + // Gets the final top padding of search box. + int GetSearchBoxFinalTopPadding() const; + + // Gets the top padding of search box during dragging. + int GetSearchBoxTopPaddingDuringDragging() const; + // The views below are owned by views hierarchy. AppsGridView* apps_grid_view_ = nullptr; AppListFolderView* app_list_folder_view_ = nullptr;
diff --git a/ui/app_list/views/apps_grid_view.cc b/ui/app_list/views/apps_grid_view.cc index 20811b3..facb7c3 100644 --- a/ui/app_list/views/apps_grid_view.cc +++ b/ui/app_list/views/apps_grid_view.cc
@@ -97,9 +97,6 @@ // UI. constexpr int kFolderDroppingCircleRadius = 39; -// Bottom padding for search box. -constexpr int kSearchBoxBottomPadding = 24; - // Padding between suggested apps tiles and all apps indicator. constexpr int kSuggestionsAllAppsIndicatorPadding = 16; @@ -109,6 +106,21 @@ // The height of gradient fade-out zones. constexpr int kFadeoutZoneHeight = 24; +// Range of the fraction of app list from collapsed to peeking that suggested +// apps should change opacity. +constexpr float kSuggestedAppsOpacityStartFraction = 0.3f; +constexpr float kSuggestedAppsOpacityEndFraction = 0.7f; + +// Range of the fraction of app list from peeking to fullscreen that all apps +// indictor should change opacity. +constexpr float kAllAppsIndicatorOpacityStartFraction = 0.7f; +constexpr float kAllAppsIndicatorOpacityEndFraction = 1.0f; + +// Range of the height of centerline above screen bottom that all apps should +// change opacity. +constexpr float kAllAppsOpacityStartPx = 8.0f; +constexpr float kAllAppsOpacityEndPx = 144.0f; + // Returns the size of a tile view excluding its padding. gfx::Size GetTileViewSize() { if (features::IsFullscreenAppListEnabled()) @@ -774,7 +786,7 @@ if (is_fullscreen_app_list_enabled_) { fadeout_layer_delegate_->layer()->SetBounds(layer()->bounds()); - rect.Inset(0, kSearchBoxBottomPadding, 0, 0); + rect.Inset(0, kSearchBoxFullscreenBottomPadding, 0, 0); } if (!folder_delegate_) { @@ -1618,14 +1630,6 @@ return folder_delegate_->IsOEMFolder(); } -void AppsGridView::UpdateOpacityOfItem(views::View* view_item, - float centroid_y) { - float delta_y = std::max(work_area_bottom_ - centroid_y, 0.0f); - float opacity = std::min( - delta_y / (AppListView::kNumOfShelfSize * AppListView::kShelfSize), 1.0f); - view_item->layer()->SetOpacity(is_end_gesture_ ? 1.0f : opacity); -} - void AppsGridView::DispatchDragEventForReparent(Pointer pointer, const gfx::Point& drag_point) { folder_delegate_->DispatchDragEventForReparent(pointer, drag_point); @@ -1689,36 +1693,75 @@ item_list_ = nullptr; } -void AppsGridView::UpdateOpacity(float work_area_bottom, bool is_end_gesture) { - work_area_bottom_ = work_area_bottom; - is_end_gesture_ = is_end_gesture; +void AppsGridView::UpdateOpacity(int app_list_y_position_in_screen) { + int work_area_bottom = contents_view_->app_list_view()->work_area_bottom(); + bool is_in_drag = contents_view_->app_list_view()->is_in_drag(); + // The opacity of suggested apps is a function of the fractional displacement + // of the app list from collapsed(0) to peeking(1) state. When the fraction + // changes from |kSuggestedAppsOpacityStartFraction| to + // |kSuggestedAppsOpacityEndFraction|, the opacity of suggested apps changes + // from 0.f to 1.0f. + float fraction = + std::max<float>(work_area_bottom - app_list_y_position_in_screen, 0) / + (kPeekingAppListHeight - kShelfSize); + float opacity = + std::min(std::max((fraction - kSuggestedAppsOpacityStartFraction) / + (kSuggestedAppsOpacityEndFraction - + kSuggestedAppsOpacityStartFraction), + 0.f), + 1.0f); + suggestions_container_->layer()->SetOpacity(is_in_drag ? opacity : 1.0f); - // Updates the opacity of suggestions container. - gfx::Rect suggestions_container_bounds = - suggestions_container_->GetBoundsInScreen(); - UpdateOpacityOfItem(suggestions_container_, - suggestions_container_bounds.CenterPoint().y()); + // The opacity of all apps indicator is a function of the fractional + // displacement of the app list from peeking(0) to fullscreen(1) state. When + // the fraction changes from |kAllAppsIndicatorOpacityStartFraction| to + // |kAllAppsIndicatorOpacityEndFraction|, the opacity of all apps indicator + // changes from 0.f to 1.0f. + float peeking_to_fullscreen_height = + contents_view_->GetDisplayHeight() - kPeekingAppListHeight; + float drag_amount = (work_area_bottom + kShelfSize) - + app_list_y_position_in_screen - kPeekingAppListHeight; + fraction = std::max(drag_amount / peeking_to_fullscreen_height, 0.f); + opacity = std::min(std::max((fraction + kAllAppsIndicatorOpacityEndFraction - + kAllAppsIndicatorOpacityStartFraction - 1.0f) / + (kAllAppsIndicatorOpacityEndFraction - + kAllAppsIndicatorOpacityStartFraction), + 0.f), + 1.0f); + all_apps_indicator_->layer()->SetOpacity(is_in_drag ? opacity : 1.0f); - // Updates the opacity of all apps indicator. - gfx::Rect all_apps_indicator_bounds = - all_apps_indicator_->GetLabelBoundsInScreen(); - UpdateOpacityOfItem(all_apps_indicator_, - all_apps_indicator_bounds.CenterPoint().y()); - - // Updates the opacity of all apps. + // Updates the opacity of all apps. The opacity of the app starting at 0.f + // when the ceterline of the app is |kAllAppsOpacityStartPx| above the bottom + // of work area and transitioning to 1.0f by the time the centerline reaches + // |kAllAppsOpacityEndPx| above the work area bottom. + float centerline_above_work_area = 0.f; for (int i = 0; i < view_model_.view_size(); ++i) { AppListItemView* item_view = GetItemViewAt(i); if (item_view != drag_view_) { gfx::Rect view_bounds = view_model_.ideal_bounds(i); views::View::ConvertRectToScreen(this, &view_bounds); - UpdateOpacityOfItem(item_view, view_bounds.CenterPoint().y()); + centerline_above_work_area = std::max<float>( + work_area_bottom + kShelfSize - view_bounds.CenterPoint().y(), 0.f); + opacity = std::min( + std::max((centerline_above_work_area - kAllAppsOpacityStartPx) / + (kAllAppsOpacityEndPx - kAllAppsOpacityStartPx), + 0.f), + 1.0f); + item_view->layer()->SetOpacity(is_in_drag ? opacity : 1.0f); } } - // Updates the opacity of page switcher buttons. + // Updates the opacity of page switcher buttons. The same rule as all apps. if (page_switcher_view_) { gfx::Rect switcher_bounds = page_switcher_view_->GetBoundsInScreen(); - UpdateOpacityOfItem(page_switcher_view_, switcher_bounds.CenterPoint().y()); + centerline_above_work_area = std::max<float>( + work_area_bottom + kShelfSize - switcher_bounds.CenterPoint().y(), 0.f); + opacity = std::min( + std::max((centerline_above_work_area - kAllAppsOpacityStartPx) / + (kAllAppsOpacityEndPx - kAllAppsOpacityStartPx), + 0.f), + 1.0f); + page_switcher_view_->layer()->SetOpacity(is_in_drag ? opacity : 1.0f); } } @@ -2249,13 +2292,13 @@ return 0; if (page == 0) { - return kSearchBoxBottomPadding + + return kSearchBoxFullscreenBottomPadding + suggestions_container_->GetPreferredSize().height() + kSuggestionsAllAppsIndicatorPadding + all_apps_indicator_->GetPreferredSize().height() + kAllAppsIndicatorExtraPadding; } - return kSearchBoxBottomPadding - kTileVerticalPadding; + return kSearchBoxFullscreenBottomPadding - kTileVerticalPadding; } gfx::Rect AppsGridView::GetExpectedTileBounds(int slot) const {
diff --git a/ui/app_list/views/apps_grid_view.h b/ui/app_list/views/apps_grid_view.h index 37cb41f4..68c04ca 100644 --- a/ui/app_list/views/apps_grid_view.h +++ b/ui/app_list/views/apps_grid_view.h
@@ -193,11 +193,8 @@ // The grid view must be inside a folder view. void OnFolderItemRemoved(); - // Updates the opacity of all the items in the grid during dragging. The - // opacity of each item is based on how much the item's |centroid_y| is above - // |work_area_bottom|. If |is_end_gesture| is true, set all the items opacity - // to 1.0f. - void UpdateOpacity(float work_area_bottom, bool is_end_gesture); + // Updates the opacity of all the items in the grid during dragging. + void UpdateOpacity(int app_list_y_position_in_screen); // Return the view model for test purposes. const views::ViewModelT<AppListItemView>* view_model_for_test() const { @@ -488,9 +485,6 @@ // Returns true if the grid view is under an OEM folder. bool IsUnderOEMFolder(); - // Updates opacity of |view_item| in the app list based on |centroid_y|. - void UpdateOpacityOfItem(views::View* view_item, float centroid_y); - AppListModel* model_ = nullptr; // Owned by AppListView. AppListItemList* item_list_ = nullptr; // Not owned. @@ -599,9 +593,6 @@ // True if the fullscreen app list feature is enabled. const bool is_fullscreen_app_list_enabled_; - // The bottom of work area. - float work_area_bottom_ = 0.f; - // True if it is the end gesture from shelf dragging. bool is_end_gesture_ = false;
diff --git a/ui/app_list/views/contents_view.cc b/ui/app_list/views/contents_view.cc index c6c9f75..99b4ce6 100644 --- a/ui/app_list/views/contents_view.cc +++ b/ui/app_list/views/contents_view.cc
@@ -487,7 +487,10 @@ return; for (AppListPage* page : app_list_pages_) { - page->SetBoundsRect(page->GetPageBoundsForState(GetActiveState())); + if (app_list_view_ && app_list_view_->is_in_drag()) + page->SetBoundsRect(page->GetPageBoundsDuringDragging(GetActiveState())); + else + page->SetBoundsRect(page->GetPageBoundsForState(GetActiveState())); } // The search box is contained in a widget so set the bounds of the widget
diff --git a/ui/app_list/views/contents_view.h b/ui/app_list/views/contents_view.h index f8ff40d..56a55c04 100644 --- a/ui/app_list/views/contents_view.h +++ b/ui/app_list/views/contents_view.h
@@ -105,6 +105,8 @@ AppListMainView* app_list_main_view() const { return app_list_main_view_; } + AppListView* app_list_view() const { return app_list_view_; } + // Returns the pagination model for the ContentsView. const PaginationModel& pagination_model() { return pagination_model_; }
diff --git a/ui/app_list/views/search_box_view.cc b/ui/app_list/views/search_box_view.cc index c8a5c68..2b62cfc 100644 --- a/ui/app_list/views/search_box_view.cc +++ b/ui/app_list/views/search_box_view.cc
@@ -22,6 +22,7 @@ #include "ui/app_list/views/app_list_view.h" #include "ui/app_list/views/contents_view.h" #include "ui/app_list/views/search_box_view_delegate.h" +#include "ui/app_list/views/search_result_page_view.h" #include "ui/base/ime/text_input_flags.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" @@ -54,7 +55,6 @@ constexpr int kInnerPadding = 24; constexpr int kPreferredWidth = 360; constexpr int kPreferredWidthFullscreen = 544; -constexpr int kSearchBoxPreferredHeight = 48; constexpr int kSearchBoxBorderWidth = 4; constexpr SkColor kHintTextColor = SkColorSetARGBMacro(0xFF, 0xA0, 0xA0, 0xA0); @@ -69,6 +69,11 @@ constexpr int kLightVibrantBlendAlpha = 0xE6; +// Range of the fraction of app list from collapsed to peeking that search box +// should change opacity. +constexpr float kOpacityStartFraction = 0.1f; +constexpr float kOpacityEndFraction = 0.6f; + // Color of placeholder text in zero query state. constexpr SkColor kZeroQuerySearchboxColor = SkColorSetARGBMacro(0x8A, 0x00, 0x00, 0x00); @@ -644,21 +649,28 @@ return background_color_; } -void SearchBoxView::UpdateOpacity(float work_area_bottom, bool is_end_gesture) { - float opacity = 1.0f; - if (!is_end_gesture) { - gfx::Rect search_box_bounds = this->GetBoundsInScreen(); - float delta_y = std::max( - (work_area_bottom - search_box_bounds.CenterPoint().y()), 0.0f); - opacity = std::min( - delta_y / (AppListView::kNumOfShelfSize * AppListView::kShelfSize), - 1.0f); - } +void SearchBoxView::UpdateOpacity(int app_list_y_position_in_screen) { + // The opacity of searchbox is a function of the fractional displacement of + // the app list from collapsed(0) to peeking(1) state. When the fraction + // changes from |kOpacityStartFraction| to |kOpaticyEndFraction|, the opacity + // of searchbox changes from 0.f to 1.0f. + ContentsView* contents_view = static_cast<ContentsView*>(contents_view_); + float fraction = + std::max<float>(0, contents_view->app_list_view()->work_area_bottom() - + app_list_y_position_in_screen) / + (kPeekingAppListHeight - kShelfSize); - // Restores the opacity of searchbox to 1.0f if it is the end of the gesture - // dragging. + float opacity = 1.0f; + if (contents_view->app_list_view()->is_in_drag()) + opacity = + std::min(std::max((fraction - kOpacityStartFraction) / + (kOpacityEndFraction - kOpacityStartFraction), + 0.f), + 1.0f); + + // Restores the opacity of searchbox if the gesture dragging ends. this->layer()->SetOpacity(opacity); - contents_view_->layer()->SetOpacity(opacity); + contents_view->search_results_page_view()->layer()->SetOpacity(opacity); } bool SearchBoxView::IsArrowKey(const ui::KeyEvent& event) {
diff --git a/ui/app_list/views/search_box_view.h b/ui/app_list/views/search_box_view.h index 25af2b31..d0de203 100644 --- a/ui/app_list/views/search_box_view.h +++ b/ui/app_list/views/search_box_view.h
@@ -135,7 +135,7 @@ SkColor GetBackgroundColorForState(AppListModel::State state) const; // Updates the opacity of the searchbox. - void UpdateOpacity(float work_area_bottom, bool is_end_gesture); + void UpdateOpacity(int app_list_y_position_in_screen); // Used only in the tests to get the current search icon. views::ImageView* get_search_icon_for_test() { return search_icon_; }
diff --git a/ui/app_list/views/search_result_page_view.cc b/ui/app_list/views/search_result_page_view.cc index 0f4d9ad..4e4146b 100644 --- a/ui/app_list/views/search_result_page_view.cc +++ b/ui/app_list/views/search_result_page_view.cc
@@ -144,6 +144,9 @@ : selected_index_(0), is_fullscreen_app_list_enabled_(features::IsFullscreenAppListEnabled()), contents_view_(new views::View) { + SetPaintToLayer(); + layer()->SetFillsBoundsOpaquely(false); + if (is_fullscreen_app_list_enabled_) { contents_view_->SetLayoutManager( new views::BoxLayout(views::BoxLayout::kVertical, gfx::Insets(), 0));
diff --git a/ui/app_list/views/start_page_view.cc b/ui/app_list/views/start_page_view.cc index f982bb6..bd95de0 100644 --- a/ui/app_list/views/start_page_view.cc +++ b/ui/app_list/views/start_page_view.cc
@@ -47,7 +47,6 @@ // Layout constants. constexpr int kInstantContainerSpacing = 24; -constexpr int kSearchBoxBottomPadding = 12; constexpr int kSearchBoxAndTilesSpacing = 35; constexpr int kStartPageSearchBoxWidth = 480; constexpr int kStartPageSearchBoxWidthFullscreen = 544; @@ -147,8 +146,8 @@ views::BoxLayout* instant_layout_manager = new views::BoxLayout( views::BoxLayout::kVertical, gfx::Insets(), kInstantContainerSpacing); if (is_fullscreen_app_list_enabled_) { - instant_layout_manager->set_inside_border_insets( - gfx::Insets(kSearchBoxTopPadding, 0, kSearchBoxBottomPadding, 0)); + instant_layout_manager->set_inside_border_insets(gfx::Insets( + kSearchBoxTopPadding, 0, kSearchBoxPeekingBottomPadding, 0)); } else { instant_layout_manager->set_inside_border_insets( gfx::Insets(0, 0, kSearchBoxAndTilesSpacing, 0)); @@ -446,8 +445,8 @@ void StartPageView::UpdateOpacityOfItem(views::View* view_item, float centroid_y) { float delta_y = std::max(work_area_bottom_ - centroid_y, 0.f); - float opacity = std::min( - delta_y / (AppListView::kNumOfShelfSize * AppListView::kShelfSize), 1.0f); + float opacity = + std::min(delta_y / (AppListView::kNumOfShelfSize * kShelfSize), 1.0f); view_item->layer()->SetOpacity(is_end_gesture_ ? 1.0f : opacity); }
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn index f1e6c73b..002a68d0 100644 --- a/ui/base/BUILD.gn +++ b/ui/base/BUILD.gn
@@ -377,8 +377,6 @@ if (is_fuchsia) { sources += [ - "clipboard/clipboard_fuchsia.cc", - "clipboard/clipboard_fuchsia.h", "idle/idle_fuchsia.cc", "resource/resource_bundle_fuchsia.cc", ] @@ -649,10 +647,6 @@ if (is_android || is_ios) { sources -= [ "device_form_factor_desktop.cc" ] } - - if (is_fuchsia) { - sources += [ "cursor/cursor_loader_fuchsia.cc" ] - } } static_library("test_support") {
diff --git a/ui/base/clipboard/clipboard_fuchsia.cc b/ui/base/clipboard/clipboard_fuchsia.cc deleted file mode 100644 index 72de3f4..0000000 --- a/ui/base/clipboard/clipboard_fuchsia.cc +++ /dev/null
@@ -1,281 +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 "ui/base/clipboard/clipboard_fuchsia.h" - -#include <algorithm> -#include <utility> - -#include "base/callback.h" -#include "base/lazy_instance.h" -#include "base/stl_util.h" -#include "base/strings/utf_string_conversions.h" -#include "base/synchronization/lock.h" -#include "base/time/time.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "ui/gfx/geometry/size.h" - -namespace ui { - -const char kMimeTypeBitmap[] = "image/bmp"; - -// Clipboard::FormatType implementation. -Clipboard::FormatType::FormatType() {} - -Clipboard::FormatType::FormatType(const std::string& native_format) - : data_(native_format) {} - -Clipboard::FormatType::~FormatType() {} - -std::string Clipboard::FormatType::Serialize() const { - return data_; -} - -// static -Clipboard::FormatType Clipboard::FormatType::Deserialize( - const std::string& serialization) { - return FormatType(serialization); -} - -bool Clipboard::FormatType::operator<(const FormatType& other) const { - return data_ < other.data_; -} - -bool Clipboard::FormatType::Equals(const FormatType& other) const { - return data_ == other.data_; -} - -// Various predefined FormatTypes. -// static -Clipboard::FormatType Clipboard::GetFormatType( - const std::string& format_string) { - return FormatType::Deserialize(format_string); -} - -// static -const Clipboard::FormatType& Clipboard::GetUrlFormatType() { - CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeURIList)); - return type; -} - -// static -const Clipboard::FormatType& Clipboard::GetUrlWFormatType() { - return GetUrlFormatType(); -} - -// static -const Clipboard::FormatType& Clipboard::GetPlainTextFormatType() { - CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeText)); - return type; -} - -// static -const Clipboard::FormatType& Clipboard::GetPlainTextWFormatType() { - return GetPlainTextFormatType(); -} - -// static -const Clipboard::FormatType& Clipboard::GetWebKitSmartPasteFormatType() { - CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebkitSmartPaste)); - return type; -} - -// static -const Clipboard::FormatType& Clipboard::GetHtmlFormatType() { - CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeHTML)); - return type; -} - -// static -const Clipboard::FormatType& Clipboard::GetRtfFormatType() { - CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeRTF)); - return type; -} - -// static -const Clipboard::FormatType& Clipboard::GetBitmapFormatType() { - CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeBitmap)); - return type; -} - -// static -const Clipboard::FormatType& Clipboard::GetWebCustomDataFormatType() { - CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebCustomData)); - return type; -} - -// static -const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() { - CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypePepperCustomData)); - return type; -} - -// Clipboard factory method. -// static -Clipboard* Clipboard::Create() { - return new ClipboardFuchsia; -} - -// ClipboardFuchsia implementation. - -ClipboardFuchsia::ClipboardFuchsia() { - DCHECK(CalledOnValidThread()); -} - -ClipboardFuchsia::~ClipboardFuchsia() { - DCHECK(CalledOnValidThread()); -} - -void ClipboardFuchsia::OnPreShutdown() {} - -uint64_t ClipboardFuchsia::GetSequenceNumber(ClipboardType type) const { - DCHECK(CalledOnValidThread()); - NOTIMPLEMENTED(); - return 0; -} - -bool ClipboardFuchsia::IsFormatAvailable(const Clipboard::FormatType& format, - ClipboardType type) const { - DCHECK(CalledOnValidThread()); - DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); - NOTIMPLEMENTED(); - return false; -} - -void ClipboardFuchsia::Clear(ClipboardType type) { - DCHECK(CalledOnValidThread()); - DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); - NOTIMPLEMENTED(); -} - -void ClipboardFuchsia::ReadAvailableTypes(ClipboardType type, - std::vector<base::string16>* types, - bool* contains_filenames) const { - DCHECK(CalledOnValidThread()); - DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); - NOTIMPLEMENTED(); - types->clear(); - *contains_filenames = false; -} - -void ClipboardFuchsia::ReadText(ClipboardType type, - base::string16* result) const { - DCHECK(CalledOnValidThread()); - DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); - NOTREACHED(); -} - -void ClipboardFuchsia::ReadAsciiText(ClipboardType type, - std::string* result) const { - DCHECK(CalledOnValidThread()); - DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); - NOTREACHED(); -} - -// Note: |src_url| isn't really used. It is only implemented in Windows -void ClipboardFuchsia::ReadHTML(ClipboardType type, - base::string16* markup, - std::string* src_url, - uint32_t* fragment_start, - uint32_t* fragment_end) const { - DCHECK(CalledOnValidThread()); - DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); - NOTREACHED(); -} - -void ClipboardFuchsia::ReadRTF(ClipboardType type, std::string* result) const { - DCHECK(CalledOnValidThread()); - NOTREACHED(); -} - -SkBitmap ClipboardFuchsia::ReadImage(ClipboardType type) const { - DCHECK(CalledOnValidThread()); - DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); - NOTREACHED(); - return SkBitmap(); -} - -void ClipboardFuchsia::ReadCustomData(ClipboardType clipboard_type, - const base::string16& type, - base::string16* result) const { - DCHECK(CalledOnValidThread()); - NOTREACHED(); -} - -void ClipboardFuchsia::ReadBookmark(base::string16* title, - std::string* url) const { - DCHECK(CalledOnValidThread()); - NOTREACHED(); -} - -void ClipboardFuchsia::ReadData(const Clipboard::FormatType& format, - std::string* result) const { - DCHECK(CalledOnValidThread()); - NOTIMPLEMENTED(); - result->clear(); -} - -base::Time ClipboardFuchsia::GetLastModifiedTime() const { - DCHECK(CalledOnValidThread()); - NOTIMPLEMENTED(); - return base::Time(); -} - -void ClipboardFuchsia::ClearLastModifiedTime() { - DCHECK(CalledOnValidThread()); - NOTIMPLEMENTED(); -} - -// Main entry point used to write several values in the clipboard. -void ClipboardFuchsia::WriteObjects(ClipboardType type, - const ObjectMap& objects) { - DCHECK(CalledOnValidThread()); - DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE); - NOTIMPLEMENTED(); -} - -void ClipboardFuchsia::WriteText(const char* text_data, size_t text_len) { - DCHECK(CalledOnValidThread()); - NOTIMPLEMENTED(); -} - -void ClipboardFuchsia::WriteHTML(const char* markup_data, - size_t markup_len, - const char* url_data, - size_t url_len) { - DCHECK(CalledOnValidThread()); - NOTIMPLEMENTED(); -} - -void ClipboardFuchsia::WriteRTF(const char* rtf_data, size_t data_len) { - DCHECK(CalledOnValidThread()); - NOTIMPLEMENTED(); -} - -void ClipboardFuchsia::WriteBookmark(const char* title_data, - size_t title_len, - const char* url_data, - size_t url_len) { - DCHECK(CalledOnValidThread()); - NOTIMPLEMENTED(); -} - -void ClipboardFuchsia::WriteWebSmartPaste() { - DCHECK(CalledOnValidThread()); - NOTIMPLEMENTED(); -} - -void ClipboardFuchsia::WriteBitmap(const SkBitmap& bitmap) { - DCHECK(CalledOnValidThread()); - NOTIMPLEMENTED(); -} - -void ClipboardFuchsia::WriteData(const Clipboard::FormatType& format, - const char* data_data, - size_t data_len) { - DCHECK(CalledOnValidThread()); - NOTIMPLEMENTED(); -} - -} // namespace ui
diff --git a/ui/base/clipboard/clipboard_fuchsia.h b/ui/base/clipboard/clipboard_fuchsia.h deleted file mode 100644 index ca68893a..0000000 --- a/ui/base/clipboard/clipboard_fuchsia.h +++ /dev/null
@@ -1,71 +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 UI_BASE_CLIPBOARD_CLIPBOARD_FUCHSIA_H_ -#define UI_BASE_CLIPBOARD_CLIPBOARD_FUCHSIA_H_ - -#include "ui/base/clipboard/clipboard.h" - -#include "base/macros.h" -#include "base/time/time.h" - -namespace ui { - -// This is a stub implementation of Clipboard for Fuchsia. -// TODO(fuchsia): Implement this class. -class ClipboardFuchsia : public Clipboard { - private: - friend class Clipboard; - - ClipboardFuchsia(); - ~ClipboardFuchsia() override; - - // Clipboard overrides: - void OnPreShutdown() override; - uint64_t GetSequenceNumber(ClipboardType type) const override; - bool IsFormatAvailable(const FormatType& format, - ClipboardType type) const override; - void Clear(ClipboardType type) override; - void ReadAvailableTypes(ClipboardType type, - std::vector<base::string16>* types, - bool* contains_filenames) const override; - void ReadText(ClipboardType type, base::string16* result) const override; - void ReadAsciiText(ClipboardType type, std::string* result) const override; - void ReadHTML(ClipboardType type, - base::string16* markup, - std::string* src_url, - uint32_t* fragment_start, - uint32_t* fragment_end) const override; - void ReadRTF(ClipboardType type, std::string* result) const override; - SkBitmap ReadImage(ClipboardType type) const override; - void ReadCustomData(ClipboardType clipboard_type, - const base::string16& type, - base::string16* result) const override; - void ReadBookmark(base::string16* title, std::string* url) const override; - void ReadData(const FormatType& format, std::string* result) const override; - base::Time GetLastModifiedTime() const override; - void ClearLastModifiedTime() override; - void WriteObjects(ClipboardType type, const ObjectMap& objects) override; - void WriteText(const char* text_data, size_t text_len) override; - void WriteHTML(const char* markup_data, - size_t markup_len, - const char* url_data, - size_t url_len) override; - void WriteRTF(const char* rtf_data, size_t data_len) override; - void WriteBookmark(const char* title_data, - size_t title_len, - const char* url_data, - size_t url_len) override; - void WriteWebSmartPaste() override; - void WriteBitmap(const SkBitmap& bitmap) override; - void WriteData(const FormatType& format, - const char* data_data, - size_t data_len) override; - - DISALLOW_COPY_AND_ASSIGN(ClipboardFuchsia); -}; - -} // namespace ui - -#endif // UI_BASE_CLIPBOARD_CLIPBOARD_FUCHSIA_H_
diff --git a/ui/base/cursor/cursor_loader_fuchsia.cc b/ui/base/cursor/cursor_loader_fuchsia.cc deleted file mode 100644 index a7e4280..0000000 --- a/ui/base/cursor/cursor_loader_fuchsia.cc +++ /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. - -#include "ui/base/cursor/cursor_loader.h" - -#include "base/logging.h" - -namespace ui { - -CursorLoader* CursorLoader::Create() { - NOTIMPLEMENTED(); - return nullptr; -} - -} // namespace ui
diff --git a/ui/base/ime/BUILD.gn b/ui/base/ime/BUILD.gn index cc69675..6d44738 100644 --- a/ui/base/ime/BUILD.gn +++ b/ui/base/ime/BUILD.gn
@@ -52,11 +52,11 @@ "composition_text.h", "composition_text_util_pango.cc", "composition_text_util_pango.h", - "composition_underline.h", "ime_bridge.cc", "ime_bridge.h", "ime_engine_handler_interface.h", "ime_input_context_handler_interface.h", + "ime_text_span.h", "infolist_entry.cc", "infolist_entry.h", "input_method.h", @@ -199,4 +199,11 @@ "//ui/ozone", ] } + + if (is_fuchsia) { + sources -= [ + "input_method_auralinux.cc", + "input_method_auralinux.h", + ] + } }
diff --git a/ui/base/ime/composition_text.cc b/ui/base/ime/composition_text.cc index a2e583f6..3ee2ae3 100644 --- a/ui/base/ime/composition_text.cc +++ b/ui/base/ime/composition_text.cc
@@ -16,15 +16,15 @@ void CompositionText::Clear() { text.clear(); - underlines.clear(); + ime_text_spans.clear(); selection = gfx::Range(); } void CompositionText::CopyFrom(const CompositionText& obj) { Clear(); text = obj.text; - for (size_t i = 0; i < obj.underlines.size(); i++) { - underlines.push_back(obj.underlines[i]); + for (size_t i = 0; i < obj.ime_text_spans.size(); i++) { + ime_text_spans.push_back(obj.ime_text_spans[i]); } selection = obj.selection; }
diff --git a/ui/base/ime/composition_text.h b/ui/base/ime/composition_text.h index ba56c62..f46dc3c 100644 --- a/ui/base/ime/composition_text.h +++ b/ui/base/ime/composition_text.h
@@ -8,7 +8,7 @@ #include <stddef.h> #include "base/strings/string16.h" -#include "ui/base/ime/composition_underline.h" +#include "ui/base/ime/ime_text_span.h" #include "ui/base/ime/ui_base_ime_export.h" #include "ui/gfx/range/range.h" @@ -21,12 +21,11 @@ ~CompositionText(); bool operator==(const CompositionText& rhs) const { - if ((this->text != rhs.text) || - (this->selection != rhs.selection) || - (this->underlines.size() != rhs.underlines.size())) + if ((this->text != rhs.text) || (this->selection != rhs.selection) || + (this->ime_text_spans.size() != rhs.ime_text_spans.size())) return false; - for (size_t i = 0; i < this->underlines.size(); ++i) { - if (this->underlines[i] != rhs.underlines[i]) + for (size_t i = 0; i < this->ime_text_spans.size(); ++i) { + if (this->ime_text_spans[i] != rhs.ime_text_spans[i]) return false; } return true; @@ -43,10 +42,8 @@ // Content of the composition text. base::string16 text; - // Underline information of the composition text. - // They must be sorted in ascending order by their start_offset and cannot be - // overlapped with each other. - CompositionUnderlines underlines; + // ImeTextSpan information for the composition text. + ImeTextSpans ime_text_spans; // Selection range in the composition text. It represents the caret position // if the range length is zero. Usually it's used for representing the target
diff --git a/ui/base/ime/composition_text_unittest.cc b/ui/base/ime/composition_text_unittest.cc index c03090a5..c1623af6 100644 --- a/ui/base/ime/composition_text_unittest.cc +++ b/ui/base/ime/composition_text_unittest.cc
@@ -13,21 +13,21 @@ TEST(CompositionTextTest, CopyTest) { const base::string16 kSampleText = base::UTF8ToUTF16("Sample Text"); - const CompositionUnderline kSampleUnderline1(10, 20, SK_ColorBLACK, false, - SK_ColorTRANSPARENT); + const ImeTextSpan kSampleUnderline1(10, 20, SK_ColorBLACK, false, + SK_ColorTRANSPARENT); - const CompositionUnderline kSampleUnderline2(11, 21, SK_ColorBLACK, true, - SK_ColorTRANSPARENT); + const ImeTextSpan kSampleUnderline2(11, 21, SK_ColorBLACK, true, + SK_ColorTRANSPARENT); - const CompositionUnderline kSampleUnderline3(12, 22, SK_ColorRED, false, - SK_ColorTRANSPARENT); + const ImeTextSpan kSampleUnderline3(12, 22, SK_ColorRED, false, + SK_ColorTRANSPARENT); // Make CompositionText CompositionText text; text.text = kSampleText; - text.underlines.push_back(kSampleUnderline1); - text.underlines.push_back(kSampleUnderline2); - text.underlines.push_back(kSampleUnderline3); + text.ime_text_spans.push_back(kSampleUnderline1); + text.ime_text_spans.push_back(kSampleUnderline2); + text.ime_text_spans.push_back(kSampleUnderline3); text.selection.set_start(30); text.selection.set_end(40); @@ -35,15 +35,16 @@ text2.CopyFrom(text); EXPECT_EQ(text.text, text2.text); - EXPECT_EQ(text.underlines.size(), text2.underlines.size()); - for (size_t i = 0; i < text.underlines.size(); ++i) { - EXPECT_EQ(text.underlines[i].start_offset, - text2.underlines[i].start_offset); - EXPECT_EQ(text.underlines[i].end_offset, text2.underlines[i].end_offset); - EXPECT_EQ(text.underlines[i].color, text2.underlines[i].color); - EXPECT_EQ(text.underlines[i].thick, text2.underlines[i].thick); - EXPECT_EQ(text.underlines[i].background_color, - text2.underlines[i].background_color); + EXPECT_EQ(text.ime_text_spans.size(), text2.ime_text_spans.size()); + for (size_t i = 0; i < text.ime_text_spans.size(); ++i) { + EXPECT_EQ(text.ime_text_spans[i].start_offset, + text2.ime_text_spans[i].start_offset); + EXPECT_EQ(text.ime_text_spans[i].end_offset, + text2.ime_text_spans[i].end_offset); + EXPECT_EQ(text.ime_text_spans[i].color, text2.ime_text_spans[i].color); + EXPECT_EQ(text.ime_text_spans[i].thick, text2.ime_text_spans[i].thick); + EXPECT_EQ(text.ime_text_spans[i].background_color, + text2.ime_text_spans[i].background_color); } EXPECT_EQ(text.selection.start(), text2.selection.start());
diff --git a/ui/base/ime/composition_text_util_pango.cc b/ui/base/ime/composition_text_util_pango.cc index b8a9297..8b30ff6 100644 --- a/ui/base/ime/composition_text_util_pango.cc +++ b/ui/base/ime/composition_text_util_pango.cc
@@ -75,44 +75,41 @@ if (background_attr || underline_attr) { // Use a black thin underline by default. - CompositionUnderline underline(char16_offsets[start], - char16_offsets[end], - SK_ColorBLACK, - false, - SK_ColorTRANSPARENT); + ImeTextSpan ime_text_span(char16_offsets[start], char16_offsets[end], + SK_ColorBLACK, false, SK_ColorTRANSPARENT); // Always use thick underline for a range with background color, which // is usually the selection range. if (background_attr) { - underline.thick = true; + ime_text_span.thick = true; // If the cursor is at start or end of this underline, then we treat // it as the selection range as well, but make sure to set the cursor // position to the selection end. - if (underline.start_offset == cursor_offset) { - composition->selection.set_start(underline.end_offset); + if (ime_text_span.start_offset == cursor_offset) { + composition->selection.set_start(ime_text_span.end_offset); composition->selection.set_end(cursor_offset); - } else if (underline.end_offset == cursor_offset) { - composition->selection.set_start(underline.start_offset); + } else if (ime_text_span.end_offset == cursor_offset) { + composition->selection.set_start(ime_text_span.start_offset); composition->selection.set_end(cursor_offset); } } if (underline_attr) { int type = reinterpret_cast<PangoAttrInt*>(underline_attr)->value; if (type == PANGO_UNDERLINE_DOUBLE) - underline.thick = true; + ime_text_span.thick = true; else if (type == PANGO_UNDERLINE_ERROR) - underline.color = SK_ColorRED; + ime_text_span.color = SK_ColorRED; } - composition->underlines.push_back(underline); + composition->ime_text_spans.push_back(ime_text_span); } } while (pango_attr_iterator_next(iter)); pango_attr_iterator_destroy(iter); } // Use a black thin underline by default. - if (composition->underlines.empty()) { - composition->underlines.push_back(CompositionUnderline( - 0, length, SK_ColorBLACK, false, SK_ColorTRANSPARENT)); + if (composition->ime_text_spans.empty()) { + composition->ime_text_spans.push_back( + ImeTextSpan(0, length, SK_ColorBLACK, false, SK_ColorTRANSPARENT)); } }
diff --git a/ui/base/ime/composition_text_util_pango_unittest.cc b/ui/base/ime/composition_text_util_pango_unittest.cc index c645e30..eb2f340 100644 --- a/ui/base/ime/composition_text_util_pango_unittest.cc +++ b/ui/base/ime/composition_text_util_pango_unittest.cc
@@ -25,7 +25,7 @@ int end_offset; }; -struct Underline { +struct ImeTextSpan { unsigned start_offset; unsigned end_offset; uint32_t color; @@ -36,7 +36,7 @@ struct TestData { const char* text; const AttributeInfo attrs[10]; - const Underline underlines[10]; + const ImeTextSpan ime_text_spans[10]; }; const TestData kTestData[] = { @@ -95,8 +95,7 @@ {0, 0, 0, false, SK_ColorTRANSPARENT}}}, }; -void CompareUnderline(const Underline& a, - const ui::CompositionUnderline& b) { +void CompareImeTextSpan(const ImeTextSpan& a, const ui::ImeTextSpan& b) { EXPECT_EQ(a.start_offset, b.start_offset); EXPECT_EQ(a.end_offset, b.end_offset); EXPECT_EQ(a.color, b.color); @@ -135,11 +134,11 @@ ui::CompositionText result; ui::ExtractCompositionTextFromGtkPreedit(text, pango_attrs, 0, &result); - const Underline* underlines = kTestData[i].underlines; - for (size_t u = 0; underlines[u].color && - u < result.underlines.size(); ++u) { - SCOPED_TRACE(testing::Message() << "Underline:" << u); - CompareUnderline(underlines[u], result.underlines[u]); + const ImeTextSpan* ime_text_spans = kTestData[i].ime_text_spans; + for (size_t u = 0; + ime_text_spans[u].color && u < result.ime_text_spans.size(); ++u) { + SCOPED_TRACE(testing::Message() << "ImeTextSpan:" << u); + CompareImeTextSpan(ime_text_spans[u], result.ime_text_spans[u]); } pango_attr_list_unref(pango_attrs);
diff --git a/ui/base/ime/composition_underline.h b/ui/base/ime/ime_text_span.h similarity index 61% rename from ui/base/ime/composition_underline.h rename to ui/base/ime/ime_text_span.h index 9eb7763..ddfbd43 100644 --- a/ui/base/ime/composition_underline.h +++ b/ui/base/ime/ime_text_span.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 UI_BASE_IME_COMPOSITION_UNDERLINE_H_ -#define UI_BASE_IME_COMPOSITION_UNDERLINE_H_ +#ifndef UI_BASE_IME_IME_TEXT_SPAN_H_ +#define UI_BASE_IME_IME_TEXT_SPAN_H_ #include <stdint.h> @@ -13,10 +13,10 @@ namespace ui { -// Intentionally keep sync with blink::WebCompositionUnderline defined in: -// third_party/WebKit/public/web/WebCompositionUnderline.h -struct CompositionUnderline { - CompositionUnderline() +// Intentionally keep sync with blink::WebImeTextSpan defined in: +// third_party/WebKit/public/web/WebImeTextSpan.h +struct ImeTextSpan { + ImeTextSpan() : start_offset(0), end_offset(0), color(SK_ColorTRANSPARENT), @@ -24,35 +24,33 @@ background_color(SK_ColorTRANSPARENT) {} // TODO(huangs): remove this constructor. - CompositionUnderline(uint32_t s, uint32_t e, SkColor c, bool t) + ImeTextSpan(uint32_t s, uint32_t e, SkColor c, bool t) : start_offset(s), end_offset(e), color(c), thick(t), background_color(SK_ColorTRANSPARENT) {} - CompositionUnderline(uint32_t s, uint32_t e, SkColor c, bool t, SkColor bc) + ImeTextSpan(uint32_t s, uint32_t e, SkColor c, bool t, SkColor bc) : start_offset(s), end_offset(e), color(c), thick(t), background_color(bc) {} - bool operator<(const CompositionUnderline& rhs) const { + bool operator<(const ImeTextSpan& rhs) const { return std::tie(start_offset, end_offset) < std::tie(rhs.start_offset, rhs.end_offset); } - bool operator==(const CompositionUnderline& rhs) const { + bool operator==(const ImeTextSpan& rhs) const { return (this->start_offset == rhs.start_offset) && (this->end_offset == rhs.end_offset) && (this->color == rhs.color) && (this->thick == rhs.thick) && (this->background_color == rhs.background_color); } - bool operator!=(const CompositionUnderline& rhs) const { - return !(*this == rhs); - } + bool operator!=(const ImeTextSpan& rhs) const { return !(*this == rhs); } uint32_t start_offset; uint32_t end_offset; @@ -61,8 +59,8 @@ SkColor background_color; }; -typedef std::vector<CompositionUnderline> CompositionUnderlines; +typedef std::vector<ImeTextSpan> ImeTextSpans; } // namespace ui -#endif // UI_BASE_IME_COMPOSITION_UNDERLINE_H_ +#endif // UI_BASE_IME_IME_TEXT_SPAN_H_
diff --git a/ui/base/ime/input_method_chromeos.cc b/ui/base/ime/input_method_chromeos.cc index 1312ba4..a5dd1d6a 100644 --- a/ui/base/ime/input_method_chromeos.cc +++ b/ui/base/ime/input_method_chromeos.cc
@@ -613,17 +613,18 @@ out_composition->selection = gfx::Range(cursor_offset); - const CompositionUnderlines text_underlines = text.underlines; - if (!text_underlines.empty()) { - for (size_t i = 0; i < text_underlines.size(); ++i) { - const uint32_t start = text_underlines[i].start_offset; - const uint32_t end = text_underlines[i].end_offset; + const ImeTextSpans text_ime_text_spans = text.ime_text_spans; + if (!text_ime_text_spans.empty()) { + for (size_t i = 0; i < text_ime_text_spans.size(); ++i) { + const uint32_t start = text_ime_text_spans[i].start_offset; + const uint32_t end = text_ime_text_spans[i].end_offset; if (start >= end) continue; - CompositionUnderline underline( - char16_offsets[start], char16_offsets[end], text_underlines[i].color, - text_underlines[i].thick, text_underlines[i].background_color); - out_composition->underlines.push_back(underline); + ImeTextSpan ime_text_span(char16_offsets[start], char16_offsets[end], + text_ime_text_spans[i].color, + text_ime_text_spans[i].thick, + text_ime_text_spans[i].background_color); + out_composition->ime_text_spans.push_back(ime_text_span); } } @@ -631,28 +632,26 @@ if (text.selection.start() < text.selection.end()) { const uint32_t start = text.selection.start(); const uint32_t end = text.selection.end(); - CompositionUnderline underline(char16_offsets[start], - char16_offsets[end], - SK_ColorBLACK, - true /* thick */, - SK_ColorTRANSPARENT); - out_composition->underlines.push_back(underline); + ImeTextSpan ime_text_span(char16_offsets[start], char16_offsets[end], + SK_ColorBLACK, true /* thick */, + SK_ColorTRANSPARENT); + out_composition->ime_text_spans.push_back(ime_text_span); - // If the cursor is at start or end of this underline, then we treat + // If the cursor is at start or end of this ime_text_span, then we treat // it as the selection range as well, but make sure to set the cursor // position to the selection end. - if (underline.start_offset == cursor_offset) { - out_composition->selection.set_start(underline.end_offset); + if (ime_text_span.start_offset == cursor_offset) { + out_composition->selection.set_start(ime_text_span.end_offset); out_composition->selection.set_end(cursor_offset); - } else if (underline.end_offset == cursor_offset) { - out_composition->selection.set_start(underline.start_offset); + } else if (ime_text_span.end_offset == cursor_offset) { + out_composition->selection.set_start(ime_text_span.start_offset); out_composition->selection.set_end(cursor_offset); } } // Use a black thin underline by default. - if (out_composition->underlines.empty()) { - out_composition->underlines.push_back(CompositionUnderline( + if (out_composition->ime_text_spans.empty()) { + out_composition->ime_text_spans.push_back(ImeTextSpan( 0, length, SK_ColorBLACK, false /* thick */, SK_ColorTRANSPARENT)); } }
diff --git a/ui/base/ime/win/imm32_manager.cc b/ui/base/ime/win/imm32_manager.cc index 8b868ce5..bc444b7 100644 --- a/ui/base/ime/win/imm32_manager.cc +++ b/ui/base/ime/win/imm32_manager.cc
@@ -62,10 +62,10 @@ // Helper function for IMM32Manager::GetCompositionInfo() method, to get // underlines information of the current composition string. -void GetCompositionUnderlines(HIMC imm_context, - int target_start, - int target_end, - ui::CompositionUnderlines* underlines) { +void GetImeTextSpans(HIMC imm_context, + int target_start, + int target_end, + ui::ImeTextSpans* ime_text_spans) { int clause_size = ::ImmGetCompositionString(imm_context, GCS_COMPCLAUSE, NULL, 0); int clause_length = clause_size / sizeof(uint32_t); @@ -75,19 +75,19 @@ ::ImmGetCompositionString(imm_context, GCS_COMPCLAUSE, clause_data.get(), clause_size); for (int i = 0; i < clause_length - 1; ++i) { - ui::CompositionUnderline underline; - underline.start_offset = clause_data[i]; - underline.end_offset = clause_data[i+1]; - underline.color = SK_ColorBLACK; - underline.thick = false; - underline.background_color = SK_ColorTRANSPARENT; + ui::ImeTextSpan ime_text_span; + ime_text_span.start_offset = clause_data[i]; + ime_text_span.end_offset = clause_data[i + 1]; + ime_text_span.color = SK_ColorBLACK; + ime_text_span.thick = false; + ime_text_span.background_color = SK_ColorTRANSPARENT; // Use thick underline for the target clause. - if (underline.start_offset >= static_cast<uint32_t>(target_start) && - underline.end_offset <= static_cast<uint32_t>(target_end)) { - underline.thick = true; + if (ime_text_span.start_offset >= static_cast<uint32_t>(target_start) && + ime_text_span.end_offset <= static_cast<uint32_t>(target_end)) { + ime_text_span.thick = true; } - underlines->push_back(underline); + ime_text_spans->push_back(ime_text_span); } } } @@ -294,8 +294,8 @@ LPARAM lparam, CompositionText* composition) { // We only care about GCS_COMPATTR, GCS_COMPCLAUSE and GCS_CURSORPOS, and - // convert them into underlines and selection range respectively. - composition->underlines.clear(); + // convert them into composition underlines and selection range respectively. + composition->ime_text_spans.clear(); int length = static_cast<int>(composition->text.length()); @@ -320,36 +320,36 @@ composition->selection = gfx::Range(0); } - // Retrieve the clause segmentations and convert them to underlines. + // Retrieve the clause segmentations and convert them to ime_text_spans. if (lparam & GCS_COMPCLAUSE) { - GetCompositionUnderlines(imm_context, target_start, target_end, - &composition->underlines); + GetImeTextSpans(imm_context, target_start, target_end, + &composition->ime_text_spans); } - // Set default underlines in case there is no clause information. - if (!composition->underlines.empty()) + // Set default composition underlines in case there is no clause information. + if (!composition->ime_text_spans.empty()) return; - CompositionUnderline underline; - underline.color = SK_ColorBLACK; - underline.background_color = SK_ColorTRANSPARENT; + ImeTextSpan ime_text_span; + ime_text_span.color = SK_ColorBLACK; + ime_text_span.background_color = SK_ColorTRANSPARENT; if (target_start > 0) { - underline.start_offset = 0U; - underline.end_offset = static_cast<uint32_t>(target_start); - underline.thick = false; - composition->underlines.push_back(underline); + ime_text_span.start_offset = 0U; + ime_text_span.end_offset = static_cast<uint32_t>(target_start); + ime_text_span.thick = false; + composition->ime_text_spans.push_back(ime_text_span); } if (target_end > target_start) { - underline.start_offset = static_cast<uint32_t>(target_start); - underline.end_offset = static_cast<uint32_t>(target_end); - underline.thick = true; - composition->underlines.push_back(underline); + ime_text_span.start_offset = static_cast<uint32_t>(target_start); + ime_text_span.end_offset = static_cast<uint32_t>(target_end); + ime_text_span.thick = true; + composition->ime_text_spans.push_back(ime_text_span); } if (target_end < length) { - underline.start_offset = static_cast<uint32_t>(target_end); - underline.end_offset = static_cast<uint32_t>(length); - underline.thick = false; - composition->underlines.push_back(underline); + ime_text_span.start_offset = static_cast<uint32_t>(target_end); + ime_text_span.end_offset = static_cast<uint32_t>(length); + ime_text_span.thick = false; + composition->ime_text_spans.push_back(ime_text_span); } } @@ -403,7 +403,7 @@ composition->text[0] = 0xFF3F; } - // Retrieve the composition underlines and selection range information. + // Retrieve the IME text spans and selection range information. GetCompositionInfo(imm_context, lparam, composition); // Mark that there is an ongoing composition.
diff --git a/ui/chromeos/resources/default_100_percent/default_user_images/abstract/avatar_avocado.png b/ui/chromeos/resources/default_100_percent/default_user_images/abstract/avatar_avocado.png new file mode 100644 index 0000000..d36e36b --- /dev/null +++ b/ui/chromeos/resources/default_100_percent/default_user_images/abstract/avatar_avocado.png Binary files differ
diff --git a/ui/chromeos/resources/default_100_percent/default_user_images/abstract/avatar_cappucino.png b/ui/chromeos/resources/default_100_percent/default_user_images/abstract/avatar_cappucino.png new file mode 100644 index 0000000..b2aef62 --- /dev/null +++ b/ui/chromeos/resources/default_100_percent/default_user_images/abstract/avatar_cappucino.png Binary files differ
diff --git a/ui/chromeos/resources/default_100_percent/default_user_images/abstract/avatar_icecream.png b/ui/chromeos/resources/default_100_percent/default_user_images/abstract/avatar_icecream.png new file mode 100644 index 0000000..247f4bd98 --- /dev/null +++ b/ui/chromeos/resources/default_100_percent/default_user_images/abstract/avatar_icecream.png Binary files differ
diff --git a/ui/chromeos/resources/default_100_percent/default_user_images/abstract/avatar_icewater.png b/ui/chromeos/resources/default_100_percent/default_user_images/abstract/avatar_icewater.png new file mode 100644 index 0000000..b5427c3 --- /dev/null +++ b/ui/chromeos/resources/default_100_percent/default_user_images/abstract/avatar_icewater.png Binary files differ
diff --git a/ui/chromeos/resources/default_100_percent/default_user_images/abstract/avatar_melon.png b/ui/chromeos/resources/default_100_percent/default_user_images/abstract/avatar_melon.png new file mode 100644 index 0000000..d3a8248 --- /dev/null +++ b/ui/chromeos/resources/default_100_percent/default_user_images/abstract/avatar_melon.png Binary files differ
diff --git a/ui/chromeos/resources/default_100_percent/default_user_images/abstract/avatar_onigiri.png b/ui/chromeos/resources/default_100_percent/default_user_images/abstract/avatar_onigiri.png new file mode 100644 index 0000000..f2881146 --- /dev/null +++ b/ui/chromeos/resources/default_100_percent/default_user_images/abstract/avatar_onigiri.png Binary files differ
diff --git a/ui/chromeos/resources/default_100_percent/default_user_images/abstract/avatar_pizza.png b/ui/chromeos/resources/default_100_percent/default_user_images/abstract/avatar_pizza.png new file mode 100644 index 0000000..d533653 --- /dev/null +++ b/ui/chromeos/resources/default_100_percent/default_user_images/abstract/avatar_pizza.png Binary files differ
diff --git a/ui/chromeos/resources/default_100_percent/default_user_images/abstract/avatar_sandwich.png b/ui/chromeos/resources/default_100_percent/default_user_images/abstract/avatar_sandwich.png new file mode 100644 index 0000000..bbce58db --- /dev/null +++ b/ui/chromeos/resources/default_100_percent/default_user_images/abstract/avatar_sandwich.png Binary files differ
diff --git a/ui/chromeos/resources/default_200_percent/default_user_images/abstract/avatar_avocado.png b/ui/chromeos/resources/default_200_percent/default_user_images/abstract/avatar_avocado.png new file mode 100644 index 0000000..036fc9b0 --- /dev/null +++ b/ui/chromeos/resources/default_200_percent/default_user_images/abstract/avatar_avocado.png Binary files differ
diff --git a/ui/chromeos/resources/default_200_percent/default_user_images/abstract/avatar_cappucino.png b/ui/chromeos/resources/default_200_percent/default_user_images/abstract/avatar_cappucino.png new file mode 100644 index 0000000..8027ad4 --- /dev/null +++ b/ui/chromeos/resources/default_200_percent/default_user_images/abstract/avatar_cappucino.png Binary files differ
diff --git a/ui/chromeos/resources/default_200_percent/default_user_images/abstract/avatar_icecream.png b/ui/chromeos/resources/default_200_percent/default_user_images/abstract/avatar_icecream.png new file mode 100644 index 0000000..2aef7b30 --- /dev/null +++ b/ui/chromeos/resources/default_200_percent/default_user_images/abstract/avatar_icecream.png Binary files differ
diff --git a/ui/chromeos/resources/default_200_percent/default_user_images/abstract/avatar_icewater.png b/ui/chromeos/resources/default_200_percent/default_user_images/abstract/avatar_icewater.png new file mode 100644 index 0000000..9a38a16 --- /dev/null +++ b/ui/chromeos/resources/default_200_percent/default_user_images/abstract/avatar_icewater.png Binary files differ
diff --git a/ui/chromeos/resources/default_200_percent/default_user_images/abstract/avatar_melon.png b/ui/chromeos/resources/default_200_percent/default_user_images/abstract/avatar_melon.png new file mode 100644 index 0000000..180155f --- /dev/null +++ b/ui/chromeos/resources/default_200_percent/default_user_images/abstract/avatar_melon.png Binary files differ
diff --git a/ui/chromeos/resources/default_200_percent/default_user_images/abstract/avatar_onigiri.png b/ui/chromeos/resources/default_200_percent/default_user_images/abstract/avatar_onigiri.png new file mode 100644 index 0000000..51b3b75 --- /dev/null +++ b/ui/chromeos/resources/default_200_percent/default_user_images/abstract/avatar_onigiri.png Binary files differ
diff --git a/ui/chromeos/resources/default_200_percent/default_user_images/abstract/avatar_pizza.png b/ui/chromeos/resources/default_200_percent/default_user_images/abstract/avatar_pizza.png new file mode 100644 index 0000000..c5c8dd07 --- /dev/null +++ b/ui/chromeos/resources/default_200_percent/default_user_images/abstract/avatar_pizza.png Binary files differ
diff --git a/ui/chromeos/resources/default_200_percent/default_user_images/abstract/avatar_sandwich.png b/ui/chromeos/resources/default_200_percent/default_user_images/abstract/avatar_sandwich.png new file mode 100644 index 0000000..dfbfd17 --- /dev/null +++ b/ui/chromeos/resources/default_200_percent/default_user_images/abstract/avatar_sandwich.png Binary files differ
diff --git a/ui/chromeos/resources/ui_chromeos_resources.grd b/ui/chromeos/resources/ui_chromeos_resources.grd index d458dea..569f59d1 100644 --- a/ui/chromeos/resources/ui_chromeos_resources.grd +++ b/ui/chromeos/resources/ui_chromeos_resources.grd
@@ -78,6 +78,14 @@ <structure type="chrome_scaled_image" name="IDR_LOGIN_DEFAULT_USER_55" file="default_user_images/illustration/avatar_sushi.png" /> <structure type="chrome_scaled_image" name="IDR_LOGIN_DEFAULT_USER_56" file="default_user_images/illustration/avatar_bike.png" /> <structure type="chrome_scaled_image" name="IDR_LOGIN_DEFAULT_USER_57" file="default_user_images/illustration/avatar_sunglasses.png" /> + <structure type="chrome_scaled_image" name="IDR_LOGIN_DEFAULT_USER_58" file="default_user_images/abstract/avatar_pizza.png" /> + <structure type="chrome_scaled_image" name="IDR_LOGIN_DEFAULT_USER_59" file="default_user_images/abstract/avatar_sandwich.png" /> + <structure type="chrome_scaled_image" name="IDR_LOGIN_DEFAULT_USER_60" file="default_user_images/abstract/avatar_cappucino.png" /> + <structure type="chrome_scaled_image" name="IDR_LOGIN_DEFAULT_USER_61" file="default_user_images/abstract/avatar_icewater.png" /> + <structure type="chrome_scaled_image" name="IDR_LOGIN_DEFAULT_USER_62" file="default_user_images/abstract/avatar_icecream.png" /> + <structure type="chrome_scaled_image" name="IDR_LOGIN_DEFAULT_USER_63" file="default_user_images/abstract/avatar_onigiri.png" /> + <structure type="chrome_scaled_image" name="IDR_LOGIN_DEFAULT_USER_64" file="default_user_images/abstract/avatar_melon.png" /> + <structure type="chrome_scaled_image" name="IDR_LOGIN_DEFAULT_USER_65" file="default_user_images/abstract/avatar_avocado.png" /> <!-- Print Job Notification images. --> <structure type="chrome_scaled_image" name="IDR_PRINT_NOTIFICATION_CANCEL" file="print_notification/cancel.png" />
diff --git a/ui/chromeos/ui_chromeos_strings.grd b/ui/chromeos/ui_chromeos_strings.grd index 1ff7211..b1a2072 100644 --- a/ui/chromeos/ui_chromeos_strings.grd +++ b/ui/chromeos/ui_chromeos_strings.grd
@@ -239,6 +239,30 @@ <message name="IDS_LOGIN_DEFAULT_USER_DESC_57" desc="Description of the default user icon with a picture of a pair of sunglasses"> Sunglasses </message> + <message name="IDS_LOGIN_DEFAULT_USER_DESC_58" desc="Description of the default user icon with a picture of a pizza"> + Pizza + </message> + <message name="IDS_LOGIN_DEFAULT_USER_DESC_59" desc="Description of the default user icon with a picture of a sandwich"> + Sandwich + </message> + <message name="IDS_LOGIN_DEFAULT_USER_DESC_60" desc="Description of the default user icon with a picture of a cappocino"> + Cappocino + </message> + <message name="IDS_LOGIN_DEFAULT_USER_DESC_61" desc="Description of the default user icon with a picture of an ice water"> + Ice water + </message> + <message name="IDS_LOGIN_DEFAULT_USER_DESC_62" desc="Description of the default user icon with a picture of an ice cream"> + Ice cream + </message> + <message name="IDS_LOGIN_DEFAULT_USER_DESC_63" desc="Description of the default user icon with a picture of onigiri"> + Onigiri + </message> + <message name="IDS_LOGIN_DEFAULT_USER_DESC_64" desc="Description of the default user icon with a picture of a melon"> + Melon + </message> + <message name="IDS_LOGIN_DEFAULT_USER_DESC_65" desc="Description of the default user icon with a picture of an avocado"> + Avocado + </message> <!-- Attribution strings for stock user images, not translateable. --> <message translateable="false" name="IDS_LOGIN_DEFAULT_USER_AUTHOR">
diff --git a/ui/display/BUILD.gn b/ui/display/BUILD.gn index 8ec761f..dcede94 100644 --- a/ui/display/BUILD.gn +++ b/ui/display/BUILD.gn
@@ -76,10 +76,6 @@ "CoreGraphics.framework", ] } - - if (is_fuchsia) { - sources += [ "screen_fuchsia.cc" ] - } } component("display_manager_test_api") {
diff --git a/ui/display/screen_fuchsia.cc b/ui/display/screen_fuchsia.cc deleted file mode 100644 index e8f2cb8..0000000 --- a/ui/display/screen_fuchsia.cc +++ /dev/null
@@ -1,18 +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 "ui/display/screen.h" - -#include "base/logging.h" - -namespace display { - -// static -gfx::NativeWindow Screen::GetWindowForView(gfx::NativeView view) { - // TODO(fuchsia): Stubbed during headless bringup https://crbug.com/743296. - NOTREACHED(); - return nullptr; -} - -} // namespace display
diff --git a/ui/login/account_picker/md_user_pod_row.js b/ui/login/account_picker/md_user_pod_row.js index dae3ddd1c..b2606f7f 100644 --- a/ui/login/account_picker/md_user_pod_row.js +++ b/ui/login/account_picker/md_user_pod_row.js
@@ -2915,6 +2915,8 @@ // If testing mode is enabled. testingModeEnabled_: false, + // The color used by the scroll list when the user count exceeds + // LANDSCAPE_MODE_LIMIT or PORTRAIT_MODE_LIMIT. overlayColors_: {maskColor: undefined, scrollColor: undefined}, /** @override */ @@ -3577,7 +3579,15 @@ * screen orientation and showing the virtual keyboard. */ onWindowResize: function() { - this.placePods_(); + var isAccountPicker = + $('login-header-bar').signinUIState == SIGNIN_UI_STATE.ACCOUNT_PICKER; + if (isAccountPicker) { + // Redo pod placement if account picker is the current screen. + this.placePods_(); + } else { + // Postpone pod placement. |handleBeforeShow| will check this flag. + this.podPlacementPostponed_ = true; + } }, /**
diff --git a/ui/login/display_manager.js b/ui/login/display_manager.js index 1dcda53..87e40cc 100644 --- a/ui/login/display_manager.js +++ b/ui/login/display_manager.js
@@ -105,10 +105,6 @@ // A lock screen enabled app is running in foreground - an app window is // shown over the lock screen user pods (header bar should still be visible). FOREGROUND: 'LOCK_SCREEN_APPS_STATE.FOREGROUND', - // State used to request launch of a lock screen note-taking app - this state - // is not expected to be received from platform as a current state (instead, - // on successful launch, state will be changed to FOREGROUND). - LAUNCH_REQUESTED: 'LOCK_SCREEN_APPS_STATE.LAUNCH_REQUESTED' }; /** @const */ var USER_ACTION_ROLLBACK_TOGGLED = 'rollback-toggled'; @@ -809,6 +805,9 @@ var currentScreen = $(currentScreenId); if (currentScreen) currentScreen.onWindowResize(); + // The account picker always needs to be notified of window size changes. + if (currentScreenId != SCREEN_ACCOUNT_PICKER && $(SCREEN_ACCOUNT_PICKER)) + $(SCREEN_ACCOUNT_PICKER).onWindowResize(); }, /*
diff --git a/ui/views/animation/OWNERS b/ui/views/animation/OWNERS index 9710b4e0..be29560 100644 --- a/ui/views/animation/OWNERS +++ b/ui/views/animation/OWNERS
@@ -1 +1 @@ -per-file *ink*=bruthig@chromium.org +per-file *ink*=mohsen@chromium.org
diff --git a/ui/views/animation/test/OWNERS b/ui/views/animation/test/OWNERS index 9710b4e0..be29560 100644 --- a/ui/views/animation/test/OWNERS +++ b/ui/views/animation/test/OWNERS
@@ -1 +1 @@ -per-file *ink*=bruthig@chromium.org +per-file *ink*=mohsen@chromium.org
diff --git a/ui/views/bubble/bubble_dialog_delegate_unittest.cc b/ui/views/bubble/bubble_dialog_delegate_unittest.cc index 0887c89..a6c2b175 100644 --- a/ui/views/bubble/bubble_dialog_delegate_unittest.cc +++ b/ui/views/bubble/bubble_dialog_delegate_unittest.cc
@@ -13,6 +13,7 @@ #include "ui/events/event_utils.h" #include "ui/views/bubble/bubble_frame_view.h" #include "ui/views/controls/button/label_button.h" +#include "ui/views/controls/styled_label.h" #include "ui/views/test/test_views.h" #include "ui/views/test/test_widget_observer.h" #include "ui/views/test/views_test_base.h" @@ -58,6 +59,7 @@ using BubbleDialogDelegateView::SetAnchorRect; using BubbleDialogDelegateView::GetBubbleFrameView; + using BubbleDialogDelegateView::SizeToContents; private: View* view_; @@ -384,4 +386,37 @@ title_view->bounds().right()); } +// Ensure the BubbleFrameView correctly resizes when the title is provided by a +// StyledLabel. +TEST_F(BubbleDialogDelegateTest, StyledLabelTitle) { + std::unique_ptr<Widget> anchor_widget(CreateTestWidget()); + TestBubbleDialogDelegateView* bubble_delegate = + new TestBubbleDialogDelegateView(anchor_widget->GetContentsView()); + StyledLabel* title_view = new StyledLabel(base::ASCIIToUTF16("123"), nullptr); + bubble_delegate->set_title_view(title_view); + + Widget* bubble_widget = + BubbleDialogDelegateView::CreateBubble(bubble_delegate); + bubble_widget->Show(); + + const gfx::Size size_before_new_title = + bubble_widget->GetWindowBoundsInScreen().size(); + title_view->SetText(base::ASCIIToUTF16("12")); + bubble_delegate->SizeToContents(); + + // A shorter title should change nothing, since both will be within the + // minimum dialog width. + EXPECT_EQ(size_before_new_title, + bubble_widget->GetWindowBoundsInScreen().size()); + + title_view->SetText(base::UTF8ToUTF16(std::string(200, '0'))); + bubble_delegate->SizeToContents(); + + // A (much) longer title should increase the height, but not the width. + EXPECT_EQ(size_before_new_title.width(), + bubble_widget->GetWindowBoundsInScreen().width()); + EXPECT_LT(size_before_new_title.height(), + bubble_widget->GetWindowBoundsInScreen().height()); +} + } // namespace views
diff --git a/ui/views/bubble/bubble_frame_view.cc b/ui/views/bubble/bubble_frame_view.cc index 33849cd..a7b5468 100644 --- a/ui/views/bubble/bubble_frame_view.cc +++ b/ui/views/bubble/bubble_frame_view.cc
@@ -159,8 +159,10 @@ } gfx::Rect BubbleFrameView::GetBoundsForClientView() const { + // When NonClientView asks for this, the size of the frame view has been set + // (i.e. |this|), but not the client view bounds. gfx::Rect client_bounds = GetContentsBounds(); - client_bounds.Inset(GetInsets()); + client_bounds.Inset(GetClientInsetsForFrameWidth(client_bounds.width())); // Only account for footnote_container_'s height if it's visible, because // content_margins_ adds extra padding even if all child views are invisible. if (footnote_container_ && footnote_container_->visible()) { @@ -172,12 +174,17 @@ gfx::Rect BubbleFrameView::GetWindowBoundsForClientBounds( const gfx::Rect& client_bounds) const { - gfx::Size size(GetSizeForClientSize(client_bounds.size())); + gfx::Size size(GetFrameSizeForClientSize(client_bounds.size())); return bubble_border_->GetBounds(gfx::Rect(), size); } bool BubbleFrameView::GetClientMask(const gfx::Size& size, gfx::Path* path) const { + // NonClientView calls this after setting the client view size from the return + // of GetBoundsForClientView(); feeding it back in |size|. + DCHECK(GetBoundsForClientView().size() == size); + DCHECK(GetWidget()->client_view()->size() == size); + const int radius = bubble_border_->GetBorderCornerRadius(); gfx::Insets content_insets = GetInsets(); // If the client bounds don't touch the edges, no need to mask. @@ -288,20 +295,7 @@ } gfx::Insets BubbleFrameView::GetInsets() const { - gfx::Insets insets = content_margins_; - - const int icon_height = title_icon_->GetPreferredSize().height(); - const int label_height = title()->GetPreferredSize().height(); - const bool has_title = icon_height > 0 || label_height > 0; - const int title_padding = has_title ? title_margins_.height() : 0; - const int title_height = std::max(icon_height, label_height) + title_padding; - const int close_height = - GetWidget()->widget_delegate()->ShouldShowCloseButton() - ? close_->height() + LayoutProvider::Get()->GetDistanceMetric( - DISTANCE_CLOSE_BUTTON_MARGIN) - : 0; - insets += gfx::Insets(std::max(title_height, close_height), 0, 0, 0); - return insets; + return GetClientInsetsForFrameWidth(GetContentsBounds().width()); } gfx::Size BubbleFrameView::CalculatePreferredSize() const { @@ -369,6 +363,17 @@ title_icon_pref_size.width() > 0 ? title_margins_.left() : 0; const int title_label_x = bounds.x() + title_icon_pref_size.width() + title_icon_padding; + + // TODO(tapted): Layout() should skip more surrounding code when !HasTitle(). + // Currently DCHECKs fail since title_insets is 0 when there is no title. + if (DCHECK_IS_ON() && HasTitle()) { + gfx::Insets title_insets = GetTitleLabelInsetsFromFrame(); + if (border()) + title_insets += border()->GetInsets(); + DCHECK_EQ(title_insets.left(), title_label_x); + DCHECK_EQ(title_insets.right(), width() - title_label_right); + } + const int title_available_width = std::max(1, title_label_right - title_label_x); const int title_preferred_height = @@ -470,7 +475,7 @@ gfx::Rect BubbleFrameView::GetUpdatedWindowBounds(const gfx::Rect& anchor_rect, const gfx::Size& client_size, bool adjust_if_offscreen) { - gfx::Size size(GetSizeForClientSize(client_size)); + gfx::Size size(GetFrameSizeForClientSize(client_size)); const BubbleBorder::Arrow arrow = bubble_border_->arrow(); if (adjust_if_offscreen && BubbleBorder::has_arrow(arrow)) { @@ -572,34 +577,79 @@ SchedulePaint(); } -gfx::Size BubbleFrameView::GetSizeForClientSize( - const gfx::Size& client_size) const { - // Accommodate the width of the title bar elements. - int title_bar_width = title_margins_.width() + border()->GetInsets().width(); - gfx::Size title_icon_size = title_icon_->GetPreferredSize(); - gfx::Size title_label_size = title()->GetPreferredSize(); - if (title_icon_size.width() > 0 && title_label_size.width() > 0) - title_bar_width += title_margins_.left(); - title_bar_width += title_icon_size.width(); - if (close_->visible()) - title_bar_width += close_->width() + 1; +int BubbleFrameView::GetFrameWidthForClientWidth(int client_width) const { + // Note that GetMinimumSize() for multiline Labels is typically 0. + const int title_bar_width = title()->GetMinimumSize().width() + + GetTitleLabelInsetsFromFrame().width(); + const int client_area_width = client_width + content_margins_.width(); + const int frame_width = std::max(title_bar_width, client_area_width); + DialogDelegate* dialog_delegate = + GetWidget()->widget_delegate()->AsDialogDelegate(); + return dialog_delegate && dialog_delegate->ShouldSnapFrameWidth() + ? LayoutProvider::Get()->GetSnappedDialogWidth(frame_width) + : frame_width; +} - gfx::Size size(client_size); - gfx::Insets client_insets = GetInsets(); - size.Enlarge(client_insets.width(), client_insets.height()); - size.SetToMax(gfx::Size(title_bar_width, 0)); +gfx::Size BubbleFrameView::GetFrameSizeForClientSize( + const gfx::Size& client_size) const { + const int frame_width = GetFrameWidthForClientWidth(client_size.width()); + const gfx::Insets client_insets = GetClientInsetsForFrameWidth(frame_width); + DCHECK_GE(frame_width, client_size.width()); + gfx::Size size(frame_width, client_size.height() + client_insets.height()); // Only account for footnote_container_'s height if it's visible, because // content_margins_ adds extra padding even if all child views are invisible. if (footnote_container_ && footnote_container_->visible()) size.Enlarge(0, footnote_container_->GetHeightForWidth(size.width())); - DialogDelegate* dialog_delegate = - GetWidget()->widget_delegate()->AsDialogDelegate(); - if (dialog_delegate && dialog_delegate->ShouldSnapFrameWidth()) - size.set_width(LayoutProvider::Get()->GetSnappedDialogWidth(size.width())); - return size; } +bool BubbleFrameView::HasTitle() const { + return custom_title_ != nullptr || + default_title_->GetPreferredSize().height() > 0 || + title_icon_->GetPreferredSize().height() > 0; +} + +gfx::Insets BubbleFrameView::GetTitleLabelInsetsFromFrame() const { + int insets_right = 0; + if (GetWidget()->widget_delegate()->ShouldShowCloseButton()) { + const int close_margin = + LayoutProvider::Get()->GetDistanceMetric(DISTANCE_CLOSE_BUTTON_MARGIN); + insets_right = 2 * close_margin + close_->width(); + } + if (!HasTitle()) + return gfx::Insets(0, 0, 0, insets_right); + + insets_right = std::max(insets_right, title_margins_.right()); + const gfx::Size title_icon_pref_size = title_icon_->GetPreferredSize(); + const int title_icon_padding = + title_icon_pref_size.width() > 0 ? title_margins_.left() : 0; + const int insets_left = + title_margins_.left() + title_icon_pref_size.width() + title_icon_padding; + return gfx::Insets(title_margins_.top(), insets_left, title_margins_.bottom(), + insets_right); +} + +gfx::Insets BubbleFrameView::GetClientInsetsForFrameWidth( + int frame_width) const { + int close_height = 0; + if (GetWidget()->widget_delegate()->ShouldShowCloseButton()) { + const int close_margin = + LayoutProvider::Get()->GetDistanceMetric(DISTANCE_CLOSE_BUTTON_MARGIN); + // Note: |close_margin| is not applied on the bottom of the icon. + close_height = close_margin + close_->height(); + } + if (!HasTitle()) + return content_margins_ + gfx::Insets(close_height, 0, 0, 0); + + const int icon_height = title_icon_->GetPreferredSize().height(); + const int label_height = title()->GetHeightForWidth( + frame_width - GetTitleLabelInsetsFromFrame().width()); + const int title_height = + std::max(icon_height, label_height) + title_margins_.height(); + return content_margins_ + + gfx::Insets(std::max(title_height, close_height), 0, 0, 0); +} + } // namespace views
diff --git a/ui/views/bubble/bubble_frame_view.h b/ui/views/bubble/bubble_frame_view.h index 37d2fddf..b456f3c 100644 --- a/ui/views/bubble/bubble_frame_view.h +++ b/ui/views/bubble/bubble_frame_view.h
@@ -123,8 +123,26 @@ void OffsetArrowIfOffScreen(const gfx::Rect& anchor_rect, const gfx::Size& client_size); + // The width of the frame for the given |client_width|. The result accounts + // for the minimum title bar width and includes all insets and possible + // snapping. It does not include the border. + int GetFrameWidthForClientWidth(int client_width) const; + // Calculates the size needed to accommodate the given client area. - gfx::Size GetSizeForClientSize(const gfx::Size& client_size) const; + gfx::Size GetFrameSizeForClientSize(const gfx::Size& client_size) const; + + // True if the frame has a title area. This is the area affected by + // |title_margins_|, including the icon and title text, but not the close + // button. + bool HasTitle() const; + + // The insets of the text portion of the title, based on |title_margins_| and + // whether there is an icon and/or close button. Note there may be no title, + // in which case only insets required for the close button are returned. + gfx::Insets GetTitleLabelInsetsFromFrame() const; + + // The client_view insets (from the frame view) for the given |frame_width|. + gfx::Insets GetClientInsetsForFrameWidth(int frame_width) const; // The bubble border. BubbleBorder* bubble_border_;
diff --git a/ui/views/bubble/bubble_frame_view_unittest.cc b/ui/views/bubble/bubble_frame_view_unittest.cc index 61066f0..92072dfe 100644 --- a/ui/views/bubble/bubble_frame_view_unittest.cc +++ b/ui/views/bubble/bubble_frame_view_unittest.cc
@@ -552,11 +552,23 @@ } ~TestBubbleDialogDelegateView() override {} - using BubbleDialogDelegateView::SetAnchorView; + void ChangeTitle(const base::string16& title) { + title_ = title; + // Note UpdateWindowTitle() always does a layout, which will be invalid if + // the Widget needs to change size. But also SizeToContents() _only_ does a + // layout if the size is actually changing. + GetWidget()->UpdateWindowTitle(); + SizeToContents(); + } void set_override_snap(bool value) { override_snap_ = value; } // BubbleDialogDelegateView: + using BubbleDialogDelegateView::SetAnchorView; + using BubbleDialogDelegateView::SizeToContents; + base::string16 GetWindowTitle() const override { return title_; } + bool ShouldShowWindowTitle() const override { return !title_.empty(); } + void DeleteDelegate() override { // This delegate is owned by the test case itself, so it should not delete // itself here. @@ -566,16 +578,34 @@ return override_snap_.value_or( BubbleDialogDelegateView::ShouldSnapFrameWidth()); } + gfx::Size GetMinimumSize() const override { return gfx::Size(); } gfx::Size CalculatePreferredSize() const override { return gfx::Size(200, 200); } private: + base::string16 title_; base::Optional<bool> override_snap_; DISALLOW_COPY_AND_ASSIGN(TestBubbleDialogDelegateView); }; +class TestAnchor { + public: + explicit TestAnchor(Widget::InitParams params) { + params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + widget_.Init(params); + widget_.Show(); + } + + Widget& widget() { return widget_; } + + private: + Widget widget_; + + DISALLOW_COPY_AND_ASSIGN(TestAnchor); +}; + } // namespace // This test ensures that if the installed LayoutProvider snaps dialog widths, @@ -583,14 +613,9 @@ TEST_F(BubbleFrameViewTest, WidthSnaps) { test::TestLayoutProvider provider; TestBubbleDialogDelegateView delegate; + TestAnchor anchor(CreateParams(Widget::InitParams::TYPE_WINDOW)); - Widget anchor; - Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - anchor.Init(params); - anchor.Show(); - - delegate.SetAnchorView(anchor.GetContentsView()); + delegate.SetAnchorView(anchor.widget().GetContentsView()); delegate.set_margins(gfx::Insets()); Widget* w0 = BubbleDialogDelegateView::CreateBubble(&delegate); @@ -618,4 +643,83 @@ w2->CloseNow(); } +// Tests edge cases when the frame's title view starts to wrap text. This is to +// ensure that the calculations BubbleFrameView does to determine the Widget +// size for a given client view are consistent with the eventual size that the +// client view takes after Layout(). +TEST_F(BubbleFrameViewTest, LayoutEdgeCases) { + test::TestLayoutProvider provider; + TestBubbleDialogDelegateView delegate; + TestAnchor anchor(CreateParams(Widget::InitParams::TYPE_WINDOW)); + delegate.SetAnchorView(anchor.widget().GetContentsView()); + + Widget* bubble = BubbleDialogDelegateView::CreateBubble(&delegate); + bubble->Show(); + + // Even though the bubble has default margins, the dialog view should have + // been given its preferred size. + EXPECT_FALSE(delegate.margins().IsEmpty()); + EXPECT_EQ(delegate.size(), delegate.GetPreferredSize()); + + // Starting with a short title. + base::string16 title(1, 'i'); + delegate.ChangeTitle(title); + const int min_bubble_height = bubble->GetWindowBoundsInScreen().height(); + EXPECT_LT(delegate.GetPreferredSize().height(), min_bubble_height); + + // Grow the title incrementally until word wrap is required. There should + // never be a point where the BubbleFrameView over- or under-estimates the + // size required for the title. If it did, it would cause SizeToContents() to + // Widget size requiring the subsequent Layout() to fill the remaining client + // area with something other than |delegate|'s preferred size. + while (bubble->GetWindowBoundsInScreen().height() == min_bubble_height) { + title += ' '; + title += 'i'; + delegate.ChangeTitle(title); + EXPECT_EQ(delegate.GetPreferredSize(), delegate.size()) << title; + } + + // Sanity check that something interesting happened. The bubble should have + // grown by "a line" for the wrapped title, and the title should have reached + // a length that would have likely caused word wrap. A typical result would be + // a +17-20 change in height and title length of 53 characters. + const int two_line_height = bubble->GetWindowBoundsInScreen().height(); + EXPECT_LT(12, two_line_height - min_bubble_height); + EXPECT_GT(25, two_line_height - min_bubble_height); + EXPECT_LT(30u, title.size()); + EXPECT_GT(80u, title.size()); + + // Now add dialog snapping. + provider.SetSnappedDialogWidth(300); + delegate.SizeToContents(); + + // Height should go back to |min_bubble_height| since the window is wider: + // word wrapping should no longer happen. + EXPECT_EQ(min_bubble_height, bubble->GetWindowBoundsInScreen().height()); + EXPECT_EQ(300, bubble->GetWindowBoundsInScreen().width()); + + // Now we are allowed to diverge from the client view width, but not height. + EXPECT_EQ(delegate.GetPreferredSize().height(), delegate.height()); + EXPECT_LT(delegate.GetPreferredSize().width(), delegate.width()); + EXPECT_GT(300, delegate.width()); // Greater, since there are margins. + + const gfx::Size snapped_size = delegate.size(); + const size_t old_title_size = title.size(); + + // Grow the title again with width snapping until word wrapping occurs. + while (bubble->GetWindowBoundsInScreen().height() == min_bubble_height) { + title += ' '; + title += 'i'; + delegate.ChangeTitle(title); + EXPECT_EQ(snapped_size, delegate.size()) << title; + } + // Change to the height should have been the same as before. Title should + // have grown about 50%. + EXPECT_EQ(two_line_height, bubble->GetWindowBoundsInScreen().height()); + EXPECT_LT(15u, title.size() - old_title_size); + EXPECT_GT(40u, title.size() - old_title_size); + + // When |anchor| goes out of scope it should take |bubble| with it. +} + } // namespace views
diff --git a/ui/views/cocoa/bridged_content_view.mm b/ui/views/cocoa/bridged_content_view.mm index e300b7e..6d05846 100644 --- a/ui/views/cocoa/bridged_content_view.mm +++ b/ui/views/cocoa/bridged_content_view.mm
@@ -1449,7 +1449,7 @@ // the Chrome renderer. Add code to extract underlines from |text| once our // render text implementation supports thick underlines and discontinous // underlines for consecutive characters. See http://crbug.com/612675. - composition.underlines.push_back(ui::CompositionUnderline( + composition.ime_text_spans.push_back(ui::ImeTextSpan( 0, [text length], SK_ColorBLACK, false, SK_ColorTRANSPARENT)); textInputClient_->SetCompositionText(composition); hasUnhandledKeyDownEvent_ = NO;
diff --git a/ui/views/controls/textfield/textfield_model.cc b/ui/views/controls/textfield/textfield_model.cc index f4d2282..58d466b 100644 --- a/ui/views/controls/textfield/textfield_model.cc +++ b/ui/views/controls/textfield/textfield_model.cc
@@ -256,8 +256,8 @@ // representing the target clause (on Windows). Returns an invalid range if // there is no such a range. gfx::Range GetFirstEmphasizedRange(const ui::CompositionText& composition) { - for (size_t i = 0; i < composition.underlines.size(); ++i) { - const ui::CompositionUnderline& underline = composition.underlines[i]; + for (size_t i = 0; i < composition.ime_text_spans.size(); ++i) { + const ui::ImeTextSpan& underline = composition.ime_text_spans[i]; if (underline.thick) return gfx::Range(underline.start_offset, underline.end_offset); } @@ -659,8 +659,9 @@ base::string16 new_text = text(); render_text_->SetText(new_text.insert(cursor, composition.text)); composition_range_ = gfx::Range(cursor, cursor + composition.text.length()); - // Don't render transparent composition underlines. - if (composition.underlines.size() > 0 && composition.underlines[0].color != 0) + // Don't render transparent IME spans. + if (composition.ime_text_spans.size() > 0 && + composition.ime_text_spans[0].color != 0) render_text_->SetCompositionRange(composition_range_); else render_text_->SetCompositionRange(gfx::Range::InvalidRange());
diff --git a/ui/views/controls/textfield/textfield_model_unittest.cc b/ui/views/controls/textfield/textfield_model_unittest.cc index d3722bb..a28fb1e 100644 --- a/ui/views/controls/textfield/textfield_model_unittest.cc +++ b/ui/views/controls/textfield/textfield_model_unittest.cc
@@ -867,7 +867,7 @@ ui::CompositionText composition; composition.text = base::ASCIIToUTF16("678"); - composition.underlines.push_back(ui::CompositionUnderline(0, 3, 0, false)); + composition.ime_text_spans.push_back(ui::ImeTextSpan(0, 3, 0, false)); // Cursor should be at the end of composition when characters are just typed. composition.selection = gfx::Range(3, 3); @@ -881,15 +881,15 @@ // Restart composition with targeting "67" in "678". composition.selection = gfx::Range(1, 3); - composition.underlines.clear(); - composition.underlines.push_back(ui::CompositionUnderline(0, 2, 0, true)); - composition.underlines.push_back(ui::CompositionUnderline(2, 3, 0, false)); + composition.ime_text_spans.clear(); + composition.ime_text_spans.push_back(ui::ImeTextSpan(0, 2, 0, true)); + composition.ime_text_spans.push_back(ui::ImeTextSpan(2, 3, 0, false)); model.SetCompositionText(composition); EXPECT_TRUE(model.HasCompositionText()); EXPECT_TRUE(model.HasSelection()); #if !defined(OS_CHROMEOS) // |composition.selection| is ignored because SetCompositionText checks - // if a bold underline exists first. + // if a thick underline exists first. EXPECT_EQ(gfx::Range(5, 7), model.render_text()->selection()); EXPECT_EQ(7U, model.render_text()->cursor_position()); #else @@ -922,9 +922,9 @@ composition_text_confirmed_or_cleared_ = false; model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_NONE); - // Also test the case where a selection exists but a bold underline doesn't. + // Also test the case where a selection exists but a thick underline doesn't. composition.selection = gfx::Range(0, 1); - composition.underlines.clear(); + composition.ime_text_spans.clear(); model.SetCompositionText(composition); EXPECT_STR_EQ("1234567890678", model.text()); EXPECT_TRUE(model.HasSelection()); @@ -1475,7 +1475,7 @@ ui::CompositionText composition; composition.text = base::ASCIIToUTF16("abc"); - composition.underlines.push_back(ui::CompositionUnderline(0, 3, 0, false)); + composition.ime_text_spans.push_back(ui::ImeTextSpan(0, 3, 0, false)); composition.selection = gfx::Range(2, 3); model.SetText(base::ASCIIToUTF16("ABCDE"));
diff --git a/ui/views/view.cc b/ui/views/view.cc index 72cdf76..44d60e4 100644 --- a/ui/views/view.cc +++ b/ui/views/view.cc
@@ -908,10 +908,10 @@ // Transform |clip_path_| from local space to parent recording space. gfx::Transform to_parent_recording_space; + to_parent_recording_space.Translate(paint_info.offset_from_parent()); to_parent_recording_space.Scale( SkFloatToScalar(paint_info.paint_recording_scale_x()), SkFloatToScalar(paint_info.paint_recording_scale_y())); - to_parent_recording_space.Translate(paint_info.offset_from_parent()); clip_path_in_parent.transform(to_parent_recording_space.matrix()); clip_recorder.ClipPathWithAntiAliasing(clip_path_in_parent);
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.js b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.js index 0d06a9e..40fe593 100644 --- a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.js +++ b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.js
@@ -13,7 +13,7 @@ * Dimensions for camera capture. * @const */ -var CAPTURE_SIZE = {height: 480, width: 480}; +var CAPTURE_SIZE = {height: 384, width: 384}; Polymer({ is: 'cr-camera',
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.html b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.html index 131d207..6765125 100644 --- a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.html +++ b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.html
@@ -13,7 +13,17 @@ } cr-camera { - --cr-camera-image-size: var(--cr-picture-image-size, 228px); + --cr-camera-image-size: 288px; + } + + #preview { + bottom: 0; + height: var(--cr-picture-image-size, 228px); + left: 0; + margin: auto; + position: absolute; + right: 0; + top: 0; } img { @@ -43,18 +53,21 @@ #discard button { --iron-icon-fill-color: white; + -webkit-margin-start: 0; border-radius: 50%; } </style> <template is="dom-if" if="[[showImagePreview_(cameraActive_, imageSrc)]]"> - <img alt="[[previewAltText]]" src="[[getImgSrc_(imageSrc)]]" - data-show-discard$="[[showDiscard_(imageType)]]"> - <div id="discard" hidden="[[!showDiscard_(imageType)]]"> - <button is="paper-icon-button-light" id="discardImage" - class="icon-delete-white" title="[[discardImageLabel]]" - on-tap="onTapDiscardImage_"> - </button> + <div id="preview"> + <img alt="[[previewAltText]]" src="[[getImgSrc_(imageSrc)]]" + data-show-discard$="[[showDiscard_(imageType)]]"> + <div id="discard" hidden="[[!showDiscard_(imageType)]]"> + <button is="paper-icon-button-light" id="discardImage" + class="icon-delete-white" title="[[discardImageLabel]]" + on-tap="onTapDiscardImage_"> + </button> + </div> </div> </template> <template is="dom-if" if="[[cameraActive_]]">